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