github.com/imannamdari/v2ray-core/v5@v5.0.5/transport/internet/system_dialer.go (about) 1 package internet 2 3 import ( 4 "context" 5 "syscall" 6 "time" 7 8 "github.com/imannamdari/v2ray-core/v5/common/net" 9 "github.com/imannamdari/v2ray-core/v5/common/session" 10 ) 11 12 var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{} 13 14 type SystemDialer interface { 15 Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error) 16 } 17 18 type DefaultSystemDialer struct { 19 controllers []controller 20 } 21 22 func resolveSrcAddr(network net.Network, src net.Address) net.Addr { 23 if src == nil || src == net.AnyIP { 24 return nil 25 } 26 27 if network == net.Network_TCP { 28 return &net.TCPAddr{ 29 IP: src.IP(), 30 Port: 0, 31 } 32 } 33 34 return &net.UDPAddr{ 35 IP: src.IP(), 36 Port: 0, 37 } 38 } 39 40 func hasBindAddr(sockopt *SocketConfig) bool { 41 return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0 42 } 43 44 func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { 45 if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { 46 srcAddr := resolveSrcAddr(net.Network_UDP, src) 47 if srcAddr == nil { 48 srcAddr = &net.UDPAddr{ 49 IP: []byte{0, 0, 0, 0}, 50 Port: 0, 51 } 52 } 53 packetConn, err := ListenSystemPacket(ctx, srcAddr, sockopt) 54 if err != nil { 55 return nil, err 56 } 57 destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr()) 58 if err != nil { 59 return nil, err 60 } 61 return &packetConnWrapper{ 62 conn: packetConn, 63 dest: destAddr, 64 }, nil 65 } 66 goStdKeepAlive := time.Duration(0) 67 if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) { 68 goStdKeepAlive = time.Duration(-1) 69 } 70 dialer := &net.Dialer{ 71 Timeout: time.Second * 16, 72 LocalAddr: resolveSrcAddr(dest.Network, src), 73 KeepAlive: goStdKeepAlive, 74 } 75 76 if sockopt != nil || len(d.controllers) > 0 { 77 dialer.Control = func(network, address string, c syscall.RawConn) error { 78 return c.Control(func(fd uintptr) { 79 if sockopt != nil { 80 if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil { 81 newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx)) 82 } 83 if dest.Network == net.Network_UDP && hasBindAddr(sockopt) { 84 if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil { 85 newError("failed to bind source address to ", sockopt.BindAddress).Base(err).WriteToLog(session.ExportIDToError(ctx)) 86 } 87 } 88 } 89 90 for _, ctl := range d.controllers { 91 if err := ctl(network, address, fd); err != nil { 92 newError("failed to apply external controller").Base(err).WriteToLog(session.ExportIDToError(ctx)) 93 } 94 } 95 }) 96 } 97 } 98 99 return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr()) 100 } 101 102 type packetConnWrapper struct { 103 conn net.PacketConn 104 dest net.Addr 105 } 106 107 func (c *packetConnWrapper) Close() error { 108 return c.conn.Close() 109 } 110 111 func (c *packetConnWrapper) LocalAddr() net.Addr { 112 return c.conn.LocalAddr() 113 } 114 115 func (c *packetConnWrapper) RemoteAddr() net.Addr { 116 return c.dest 117 } 118 119 func (c *packetConnWrapper) Write(p []byte) (int, error) { 120 return c.conn.WriteTo(p, c.dest) 121 } 122 123 func (c *packetConnWrapper) Read(p []byte) (int, error) { 124 n, _, err := c.conn.ReadFrom(p) 125 return n, err 126 } 127 128 func (c *packetConnWrapper) SetDeadline(t time.Time) error { 129 return c.conn.SetDeadline(t) 130 } 131 132 func (c *packetConnWrapper) SetReadDeadline(t time.Time) error { 133 return c.conn.SetReadDeadline(t) 134 } 135 136 func (c *packetConnWrapper) SetWriteDeadline(t time.Time) error { 137 return c.conn.SetWriteDeadline(t) 138 } 139 140 type SystemDialerAdapter interface { 141 Dial(network string, address string) (net.Conn, error) 142 } 143 144 type SimpleSystemDialer struct { 145 adapter SystemDialerAdapter 146 } 147 148 func WithAdapter(dialer SystemDialerAdapter) SystemDialer { 149 return &SimpleSystemDialer{ 150 adapter: dialer, 151 } 152 } 153 154 func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { 155 return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr()) 156 } 157 158 // UseAlternativeSystemDialer replaces the current system dialer with a given one. 159 // Caller must ensure there is no race condition. 160 // 161 // v2ray:api:stable 162 func UseAlternativeSystemDialer(dialer SystemDialer) { 163 if dialer == nil { 164 dialer = &DefaultSystemDialer{} 165 } 166 effectiveSystemDialer = dialer 167 } 168 169 // RegisterDialerController adds a controller to the effective system dialer. 170 // The controller can be used to operate on file descriptors before they are put into use. 171 // It only works when effective dialer is the default dialer. 172 // 173 // v2ray:api:beta 174 func RegisterDialerController(ctl func(network, address string, fd uintptr) error) error { 175 if ctl == nil { 176 return newError("nil listener controller") 177 } 178 179 dialer, ok := effectiveSystemDialer.(*DefaultSystemDialer) 180 if !ok { 181 return newError("RegisterListenerController not supported in custom dialer") 182 } 183 184 dialer.controllers = append(dialer.controllers, ctl) 185 return nil 186 }