GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — netpoll/net_tcpsock.go at main · stop-coding/netpoll Expand file tree/ Copy pathnet_tcpsock.goMore file actions 246 lines (225 loc) · 7.76 KB / Copy pathnet_tcpsock.goFile metadata and controls246 lines (225 loc) · 7.76 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // // This file may have been modified by CloudWeGo authors. (“CloudWeGo Modifications”). // All CloudWeGo Modifications are Copyright 2021 CloudWeGo authors. // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows package netpoll import ( "context" "net" "os" "syscall" ) // TCPAddr represents the address of a TCP end point. type TCPAddr struct { net.TCPAddr } func (a *TCPAddr) isWildcard() bool { if a == nil || a.IP == nil { return true } return a.IP.IsUnspecified() } func (a *TCPAddr) opAddr() net.Addr { if a == nil { return nil } return a } func (a *TCPAddr) family() int { if a == nil || len(a.IP) <= net.IPv4len { return syscall.AF_INET } if a.IP.To4() != nil { return syscall.AF_INET } return syscall.AF_INET6 } func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) { if a == nil { return nil, nil } return ipToSockaddr(family, a.IP, a.Port, a.Zone) } func (a *TCPAddr) toLocal(network string) sockaddr { addr := &TCPAddr{} addr.IP = loopbackIP(network) addr.Port = a.Port addr.Zone = a.Zone return addr } func loopbackIP(network string) net.IP { if network != "" && network[len(network)-1] == '6' { return net.IPv6loopback } return net.IP{127, 0, 0, 1} } func ipToSockaddr(family int, ip net.IP, port int, zone string) (syscall.Sockaddr, error) { switch family { case syscall.AF_INET: if len(ip) == 0 { ip = net.IPv4zero } ip4 := ip.To4() if ip4 == nil { return nil, &net.AddrError{Err: "non-IPv4 address", Addr: ip.String()} } sa := &syscall.SockaddrInet4{Port: port} copy(sa.Addr[:], ip4) return sa, nil case syscall.AF_INET6: // In general, an IP wildcard address, which is either // "0.0.0.0" or "::", means the entire IP addressing // space. For some historical reason, it is used to // specify "any available address" on some operations // of IP node. // // When the IP node supports IPv4-mapped IPv6 address, // we allow an listener to listen to the wildcard // address of both IP addressing spaces by specifying // IPv6 wildcard address. if len(ip) == 0 || ip.Equal(net.IPv4zero) { ip = net.IPv6zero } // We accept any IPv6 address including IPv4-mapped // IPv6 address. ip6 := ip.To16() if ip6 == nil { return nil, &net.AddrError{Err: "non-IPv6 address", Addr: ip.String()} } // TODO: sa := &syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))} sa := &syscall.SockaddrInet6{Port: port} copy(sa.Addr[:], ip6) return sa, nil } return nil, &net.AddrError{Err: "invalid address family", Addr: ip.String()} } // ResolveTCPAddr returns an address of TCP end point. // // The network must be a TCP network name. // // If the host in the address parameter is not a literal IP address or // the port is not a literal port number, ResolveTCPAddr resolves the // address to an address of TCP end point. // Otherwise, it parses the address as a pair of literal IP address // and port number. // The address parameter can use a host name, but this is not // recommended, because it will return at most one of the host name's // IP addresses. // // See func Dial for a description of the network and address // parameters. func ResolveTCPAddr(network, address string) (*TCPAddr, error) { addr, err := net.ResolveTCPAddr(network, address) if err != nil { return nil, err } return &TCPAddr{*addr}, nil } // TCPConnection implements Connection. type TCPConnection struct { connection } // newTCPConnection wraps *TCPConnection. func newTCPConnection(conn Conn) (connection *TCPConnection, err error) { connection = &TCPConnection{} err = connection.init(conn, nil) if err != nil { return nil, err } return connection, nil } // DialTCP acts like Dial for TCP networks. // // The network must be a TCP network name; see func Dial for details. // // If laddr is nil, a local address is automatically chosen. // If the IP field of raddr is nil or an unspecified IP address, the // local system is assumed. func DialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*TCPConnection, error) { switch network { case "tcp", "tcp4", "tcp6": default: return nil, &net.OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: net.UnknownNetworkError(network)} } if raddr == nil { return nil, &net.OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress} } if ctx == nil { ctx = context.Background() } sd := &sysDialer{network: network, address: raddr.String()} c, err := sd.dialTCP(ctx, laddr, raddr) if err != nil { return nil, &net.OpError{Op: "dial", Net: network, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err} } return c, nil } func (sd *sysDialer) dialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConnection, error) { conn, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial") // TCP has a rarely used mechanism called a 'simultaneous connection' in // which Dial("tcp", addr1, addr2) run on the machine at addr1 can // connect to a simultaneous Dial("tcp", addr2, addr1) run on the machine // at addr2, without either machine executing Listen. If laddr == nil, // it means we want the kernel to pick an appropriate originating local // address. Some Linux kernels cycle blindly through a fixed range of // local ports, regardless of destination port. If a kernel happens to // pick local port 50001 as the source for a Dial("tcp", "", "localhost:50001"), // then the Dial will succeed, having simultaneously connected to itself. // This can only happen when we are letting the kernel pick a port (laddr == nil) // and when there is no listener for the destination address. // It's hard to argue this is anything other than a kernel bug. If we // see this happen, rather than expose the buggy effect to users, we // close the conn and try again. If it happens twice more, we relent and // use the result. See also: // https://golang.org/issue/2690 // https://stackoverflow.com/questions/4949858/ // // The opposite can also happen: if we ask the kernel to pick an appropriate // originating local address, sometimes it picks one that is already in use. // So if the error is EADDRNOTAVAIL, we have to try again too, just for // a different reason. // // The kernel socket code is no doubt enjoying watching us squirm. for i := 0; i < 2 && (laddr == nil || laddr.Port == 0) && (selfConnect(conn, err) || spuriousENOTAVAIL(err)); i++ { if err == nil { conn.Close() } conn, err = internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_STREAM, 0, "dial") } if err != nil { return nil, err } return newTCPConnection(conn) } func selfConnect(conn *netFD, err error) bool { // If the connect failed, we clearly didn't connect to ourselves. if err != nil { return false } // The socket constructor can return an conn with raddr nil under certain // unknown conditions. The errors in the calls there to Getpeername // are discarded, but we can't catch the problem there because those // calls are sometimes legally erroneous with a "socket not connected". // Since this code (selfConnect) is already trying to work around // a problem, we make sure if this happens we recognize trouble and // ask the DialTCP routine to try again. // TODO: try to understand what's really going on. if conn.localAddr == nil || conn.remoteAddr == nil { return true } l := conn.localAddr.(*net.TCPAddr) r := conn.remoteAddr.(*net.TCPAddr) return l.Port == r.Port && l.IP.Equal(r.IP) } func spuriousENOTAVAIL(err error) bool { if op, ok := err.(*net.OpError); ok { err = op.Err } if sys, ok := err.(*os.SyscallError); ok { err = sys.Err } return err == syscall.EADDRNOTAVAIL } |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |