github.com/metacubex/mihomo@v1.18.5/transport/tuic/v4/server.go (about) 1 package v4 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "net" 8 "sync" 9 10 "github.com/metacubex/mihomo/adapter/inbound" 11 "github.com/metacubex/mihomo/common/atomic" 12 N "github.com/metacubex/mihomo/common/net" 13 "github.com/metacubex/mihomo/common/pool" 14 C "github.com/metacubex/mihomo/constant" 15 "github.com/metacubex/mihomo/transport/socks5" 16 "github.com/metacubex/mihomo/transport/tuic/common" 17 18 "github.com/gofrs/uuid/v5" 19 "github.com/metacubex/quic-go" 20 "github.com/puzpuzpuz/xsync/v3" 21 ) 22 23 type ServerOption struct { 24 HandleTcpFn func(conn net.Conn, addr socks5.Addr, additions ...inbound.Addition) error 25 HandleUdpFn func(addr socks5.Addr, packet C.UDPPacket, additions ...inbound.Addition) error 26 27 Tokens [][32]byte 28 MaxUdpRelayPacketSize int 29 } 30 31 func NewServerHandler(option *ServerOption, quicConn quic.EarlyConnection, uuid uuid.UUID) common.ServerHandler { 32 return &serverHandler{ 33 ServerOption: option, 34 quicConn: quicConn, 35 uuid: uuid, 36 authCh: make(chan struct{}), 37 udpInputMap: xsync.NewMapOf[uint32, *atomic.Bool](), 38 } 39 } 40 41 type serverHandler struct { 42 *ServerOption 43 quicConn quic.EarlyConnection 44 uuid uuid.UUID 45 46 authCh chan struct{} 47 authOk atomic.Bool 48 authOnce sync.Once 49 50 udpInputMap *xsync.MapOf[uint32, *atomic.Bool] 51 } 52 53 func (s *serverHandler) AuthOk() bool { 54 return s.authOk.Load() 55 } 56 57 func (s *serverHandler) HandleTimeout() { 58 s.authOnce.Do(func() { 59 _ = s.quicConn.CloseWithError(AuthenticationTimeout, "AuthenticationTimeout") 60 s.authOk.Store(false) 61 close(s.authCh) 62 }) 63 } 64 65 func (s *serverHandler) HandleMessage(message []byte) (err error) { 66 buffer := bytes.NewBuffer(message) 67 packet, err := ReadPacket(buffer) 68 if err != nil { 69 return 70 } 71 return s.parsePacket(&packet, common.NATIVE) 72 } 73 74 func (s *serverHandler) parsePacket(packet *Packet, udpRelayMode common.UdpRelayMode) (err error) { 75 <-s.authCh 76 if !s.authOk.Load() { 77 return 78 } 79 var assocId uint32 80 81 assocId = packet.ASSOC_ID 82 83 writeClosed, _ := s.udpInputMap.LoadOrCompute(assocId, func() *atomic.Bool { return &atomic.Bool{} }) 84 if writeClosed.Load() { 85 return nil 86 } 87 88 pc := &quicStreamPacketConn{ 89 connId: assocId, 90 quicConn: s.quicConn, 91 inputConn: nil, 92 udpRelayMode: udpRelayMode, 93 maxUdpRelayPacketSize: s.MaxUdpRelayPacketSize, 94 deferQuicConnFn: nil, 95 closeDeferFn: nil, 96 writeClosed: writeClosed, 97 } 98 99 return s.HandleUdpFn(packet.ADDR.SocksAddr(), &serverUDPPacket{ 100 pc: pc, 101 packet: packet, 102 rAddr: N.NewCustomAddr("tuic", fmt.Sprintf("tuic-%s-%d", s.uuid, assocId), s.quicConn.RemoteAddr()), // for tunnel's handleUDPConn 103 }) 104 } 105 106 func (s *serverHandler) HandleStream(conn *N.BufferedConn) (err error) { 107 connect, err := ReadConnect(conn) 108 if err != nil { 109 return err 110 } 111 <-s.authCh 112 if !s.authOk.Load() { 113 return conn.Close() 114 } 115 116 buf := pool.GetBuffer() 117 defer pool.PutBuffer(buf) 118 err = s.HandleTcpFn(conn, connect.ADDR.SocksAddr()) 119 if err != nil { 120 err = NewResponseFailed().WriteTo(buf) 121 defer conn.Close() 122 } else { 123 err = NewResponseSucceed().WriteTo(buf) 124 } 125 if err != nil { 126 _ = conn.Close() 127 return err 128 } 129 _, err = buf.WriteTo(conn) 130 if err != nil { 131 _ = conn.Close() 132 return err 133 } 134 135 return 136 } 137 138 func (s *serverHandler) HandleUniStream(reader *bufio.Reader) (err error) { 139 commandHead, err := ReadCommandHead(reader) 140 if err != nil { 141 return 142 } 143 switch commandHead.TYPE { 144 case AuthenticateType: 145 var authenticate Authenticate 146 authenticate, err = ReadAuthenticateWithHead(commandHead, reader) 147 if err != nil { 148 return 149 } 150 authOk := false 151 for _, tkn := range s.Tokens { 152 if authenticate.TKN == tkn { 153 authOk = true 154 break 155 } 156 } 157 s.authOnce.Do(func() { 158 if !authOk { 159 _ = s.quicConn.CloseWithError(AuthenticationFailed, "AuthenticationFailed") 160 } 161 s.authOk.Store(authOk) 162 close(s.authCh) 163 }) 164 case PacketType: 165 var packet Packet 166 packet, err = ReadPacketWithHead(commandHead, reader) 167 if err != nil { 168 return 169 } 170 return s.parsePacket(&packet, common.QUIC) 171 case DissociateType: 172 var disassociate Dissociate 173 disassociate, err = ReadDissociateWithHead(commandHead, reader) 174 if err != nil { 175 return 176 } 177 if writeClosed, loaded := s.udpInputMap.LoadAndDelete(disassociate.ASSOC_ID); loaded { 178 writeClosed.Store(true) 179 } 180 case HeartbeatType: 181 var heartbeat Heartbeat 182 heartbeat, err = ReadHeartbeatWithHead(commandHead, reader) 183 if err != nil { 184 return 185 } 186 heartbeat.BytesLen() 187 } 188 return 189 } 190 191 type serverUDPPacket struct { 192 pc *quicStreamPacketConn 193 packet *Packet 194 rAddr net.Addr 195 } 196 197 func (s *serverUDPPacket) InAddr() net.Addr { 198 return s.pc.LocalAddr() 199 } 200 201 func (s *serverUDPPacket) LocalAddr() net.Addr { 202 return s.rAddr 203 } 204 205 func (s *serverUDPPacket) Data() []byte { 206 return s.packet.DATA 207 } 208 209 func (s *serverUDPPacket) WriteBack(b []byte, addr net.Addr) (n int, err error) { 210 return s.pc.WriteTo(b, addr) 211 } 212 213 func (s *serverUDPPacket) Drop() { 214 s.packet.DATA = nil 215 } 216 217 var _ C.UDPPacket = (*serverUDPPacket)(nil) 218 var _ C.UDPPacketInAddr = (*serverUDPPacket)(nil)