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