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