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