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