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