github.com/xmplusdev/xray-core@v1.8.10/transport/internet/kcp/dialer.go (about) 1 package kcp 2 3 import ( 4 "context" 5 "io" 6 "sync/atomic" 7 8 "github.com/xmplusdev/xray-core/common" 9 "github.com/xmplusdev/xray-core/common/buf" 10 "github.com/xmplusdev/xray-core/common/dice" 11 "github.com/xmplusdev/xray-core/common/net" 12 "github.com/xmplusdev/xray-core/transport/internet" 13 "github.com/xmplusdev/xray-core/transport/internet/stat" 14 "github.com/xmplusdev/xray-core/transport/internet/tls" 15 ) 16 17 var globalConv = uint32(dice.RollUint16()) 18 19 func fetchInput(_ context.Context, input io.Reader, reader PacketReader, conn *Connection) { 20 cache := make(chan *buf.Buffer, 1024) 21 go func() { 22 for { 23 payload := buf.New() 24 if _, err := payload.ReadFrom(input); err != nil { 25 payload.Release() 26 close(cache) 27 return 28 } 29 select { 30 case cache <- payload: 31 default: 32 payload.Release() 33 } 34 } 35 }() 36 37 for payload := range cache { 38 segments := reader.Read(payload.Bytes()) 39 payload.Release() 40 if len(segments) > 0 { 41 conn.Input(segments) 42 } 43 } 44 } 45 46 // DialKCP dials a new KCP connections to the specific destination. 47 func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) { 48 dest.Network = net.Network_UDP 49 newError("dialing mKCP to ", dest).WriteToLog() 50 51 rawConn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings) 52 if err != nil { 53 return nil, newError("failed to dial to dest: ", err).AtWarning().Base(err) 54 } 55 56 kcpSettings := streamSettings.ProtocolSettings.(*Config) 57 58 header, err := kcpSettings.GetPackerHeader() 59 if err != nil { 60 return nil, newError("failed to create packet header").Base(err) 61 } 62 security, err := kcpSettings.GetSecurity() 63 if err != nil { 64 return nil, newError("failed to create security").Base(err) 65 } 66 reader := &KCPPacketReader{ 67 Header: header, 68 Security: security, 69 } 70 writer := &KCPPacketWriter{ 71 Header: header, 72 Security: security, 73 Writer: rawConn, 74 } 75 76 conv := uint16(atomic.AddUint32(&globalConv, 1)) 77 session := NewConnection(ConnMetadata{ 78 LocalAddr: rawConn.LocalAddr(), 79 RemoteAddr: rawConn.RemoteAddr(), 80 Conversation: conv, 81 }, writer, rawConn, kcpSettings) 82 83 go fetchInput(ctx, rawConn, reader, session) 84 85 var iConn stat.Connection = session 86 87 if config := tls.ConfigFromStreamSettings(streamSettings); config != nil { 88 iConn = tls.Client(iConn, config.GetTLSConfig(tls.WithDestination(dest))) 89 } 90 91 return iConn, nil 92 } 93 94 func init() { 95 common.Must(internet.RegisterTransportDialer(protocolName, DialKCP)) 96 }