github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/direct/tcp.go (about) 1 package direct 2 3 import ( 4 "context" 5 6 "github.com/database64128/shadowsocks-go/conn" 7 "github.com/database64128/shadowsocks-go/socks5" 8 "github.com/database64128/shadowsocks-go/zerocopy" 9 ) 10 11 // TCPClient implements the zerocopy TCPClient interface. 12 type TCPClient struct { 13 name string 14 network string 15 dialer conn.Dialer 16 } 17 18 func NewTCPClient(name, network string, dialer conn.Dialer) *TCPClient { 19 return &TCPClient{ 20 name: name, 21 network: network, 22 dialer: dialer, 23 } 24 } 25 26 // Info implements the zerocopy.TCPClient Info method. 27 func (c *TCPClient) Info() zerocopy.TCPClientInfo { 28 return zerocopy.TCPClientInfo{ 29 Name: c.name, 30 NativeInitialPayload: !c.dialer.DisableTFO, 31 } 32 } 33 34 // Dial implements the zerocopy.TCPClient Dial method. 35 func (c *TCPClient) Dial(ctx context.Context, targetAddr conn.Addr, payload []byte) (rawRW zerocopy.DirectReadWriteCloser, rw zerocopy.ReadWriter, err error) { 36 rawRW, err = c.dialer.DialTCP(ctx, c.network, targetAddr.String(), payload) 37 if err != nil { 38 return 39 } 40 rw = &DirectStreamReadWriter{rw: rawRW} 41 return 42 } 43 44 // TCPServer is the client-side tunnel server. 45 // 46 // TCPServer implements the zerocopy TCPServer interface. 47 type TCPServer struct { 48 targetAddr conn.Addr 49 } 50 51 func NewTCPServer(targetAddr conn.Addr) *TCPServer { 52 return &TCPServer{ 53 targetAddr: targetAddr, 54 } 55 } 56 57 // Info implements the zerocopy.TCPServer Info method. 58 func (s *TCPServer) Info() zerocopy.TCPServerInfo { 59 return zerocopy.TCPServerInfo{ 60 NativeInitialPayload: false, 61 DefaultTCPConnCloser: zerocopy.JustClose, 62 } 63 } 64 65 // Accept implements the zerocopy.TCPServer Accept method. 66 func (s *TCPServer) Accept(rawRW zerocopy.DirectReadWriteCloser) (rw zerocopy.ReadWriter, targetAddr conn.Addr, payload []byte, username string, err error) { 67 return &DirectStreamReadWriter{rw: rawRW}, s.targetAddr, nil, "", nil 68 } 69 70 // ShadowsocksNoneTCPClient implements the zerocopy TCPClient interface. 71 type ShadowsocksNoneTCPClient struct { 72 name string 73 tco *zerocopy.TCPConnOpener 74 } 75 76 func NewShadowsocksNoneTCPClient(name, network, address string, dialer conn.Dialer) *ShadowsocksNoneTCPClient { 77 return &ShadowsocksNoneTCPClient{ 78 name: name, 79 tco: zerocopy.NewTCPConnOpener(dialer, network, address), 80 } 81 } 82 83 // Info implements the zerocopy.TCPClient Info method. 84 func (c *ShadowsocksNoneTCPClient) Info() zerocopy.TCPClientInfo { 85 return zerocopy.TCPClientInfo{ 86 Name: c.name, 87 NativeInitialPayload: true, 88 } 89 } 90 91 // Dial implements the zerocopy.TCPClient Dial method. 92 func (c *ShadowsocksNoneTCPClient) Dial(ctx context.Context, targetAddr conn.Addr, payload []byte) (rawRW zerocopy.DirectReadWriteCloser, rw zerocopy.ReadWriter, err error) { 93 rw, rawRW, err = NewShadowsocksNoneStreamClientReadWriter(ctx, c.tco, targetAddr, payload) 94 return 95 } 96 97 // ShadowsocksNoneTCPServer implements the zerocopy TCPServer interface. 98 type ShadowsocksNoneTCPServer struct{} 99 100 func NewShadowsocksNoneTCPServer() ShadowsocksNoneTCPServer { 101 return ShadowsocksNoneTCPServer{} 102 } 103 104 // Info implements the zerocopy.TCPServer Info method. 105 func (ShadowsocksNoneTCPServer) Info() zerocopy.TCPServerInfo { 106 return zerocopy.TCPServerInfo{ 107 NativeInitialPayload: false, 108 DefaultTCPConnCloser: zerocopy.JustClose, 109 } 110 } 111 112 // Accept implements the zerocopy.TCPServer Accept method. 113 func (ShadowsocksNoneTCPServer) Accept(rawRW zerocopy.DirectReadWriteCloser) (rw zerocopy.ReadWriter, targetAddr conn.Addr, payload []byte, username string, err error) { 114 rw, targetAddr, err = NewShadowsocksNoneStreamServerReadWriter(rawRW) 115 return 116 } 117 118 // Socks5TCPClient implements the zerocopy TCPClient interface. 119 type Socks5TCPClient struct { 120 name string 121 network string 122 address string 123 dialer conn.Dialer 124 } 125 126 func NewSocks5TCPClient(name, network, address string, dialer conn.Dialer) *Socks5TCPClient { 127 return &Socks5TCPClient{ 128 name: name, 129 network: network, 130 address: address, 131 dialer: dialer, 132 } 133 } 134 135 // Info implements the zerocopy.TCPClient Info method. 136 func (c *Socks5TCPClient) Info() zerocopy.TCPClientInfo { 137 return zerocopy.TCPClientInfo{ 138 Name: c.name, 139 NativeInitialPayload: false, 140 } 141 } 142 143 // Dial implements the zerocopy.TCPClient Dial method. 144 func (c *Socks5TCPClient) Dial(ctx context.Context, targetAddr conn.Addr, payload []byte) (rawRW zerocopy.DirectReadWriteCloser, rw zerocopy.ReadWriter, err error) { 145 rawRW, err = c.dialer.DialTCP(ctx, c.network, c.address, nil) 146 if err != nil { 147 return 148 } 149 150 rw, err = NewSocks5StreamClientReadWriter(rawRW, targetAddr) 151 if err != nil { 152 rawRW.Close() 153 return 154 } 155 156 if len(payload) > 0 { 157 if _, err = rw.WriteZeroCopy(payload, 0, len(payload)); err != nil { 158 rawRW.Close() 159 } 160 } 161 return 162 } 163 164 // Socks5TCPServer implements the zerocopy TCPServer interface. 165 type Socks5TCPServer struct { 166 enableTCP bool 167 enableUDP bool 168 } 169 170 func NewSocks5TCPServer(enableTCP, enableUDP bool) *Socks5TCPServer { 171 return &Socks5TCPServer{ 172 enableTCP: enableTCP, 173 enableUDP: enableUDP, 174 } 175 } 176 177 // Info implements the zerocopy.TCPServer Info method. 178 func (s *Socks5TCPServer) Info() zerocopy.TCPServerInfo { 179 return zerocopy.TCPServerInfo{ 180 NativeInitialPayload: false, 181 DefaultTCPConnCloser: zerocopy.JustClose, 182 } 183 } 184 185 // Accept implements the zerocopy.TCPServer Accept method. 186 func (s *Socks5TCPServer) Accept(rawRW zerocopy.DirectReadWriteCloser) (rw zerocopy.ReadWriter, targetAddr conn.Addr, payload []byte, username string, err error) { 187 rw, targetAddr, err = NewSocks5StreamServerReadWriter(rawRW, s.enableTCP, s.enableUDP) 188 if err == socks5.ErrUDPAssociateDone { 189 err = zerocopy.ErrAcceptDoneNoRelay 190 } 191 return 192 }