github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/src/net/sock_posix.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris windows 6 7 package net 8 9 import ( 10 "context" 11 "internal/poll" 12 "os" 13 "syscall" 14 ) 15 16 // A sockaddr represents a TCP, UDP, IP or Unix network endpoint 17 // address that can be converted into a syscall.Sockaddr. 18 type sockaddr interface { 19 Addr 20 21 // family returns the platform-dependent address family 22 // identifier. 23 family() int 24 25 // isWildcard reports whether the address is a wildcard 26 // address. 27 isWildcard() bool 28 29 // sockaddr returns the address converted into a syscall 30 // sockaddr type that implements syscall.Sockaddr 31 // interface. It returns a nil interface when the address is 32 // nil. 33 sockaddr(family int) (syscall.Sockaddr, error) 34 35 // toLocal maps the zero address to a local system address (127.0.0.1 or ::1) 36 toLocal(net string) sockaddr 37 } 38 39 // socket returns a network file descriptor that is ready for 40 // asynchronous I/O using the network poller. 41 func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr) (fd *netFD, err error) { 42 s, err := sysSocket(family, sotype, proto) 43 if err != nil { 44 return nil, err 45 } 46 if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil { 47 poll.CloseFunc(s) 48 return nil, err 49 } 50 if fd, err = newFD(s, family, sotype, net); err != nil { 51 poll.CloseFunc(s) 52 return nil, err 53 } 54 55 // This function makes a network file descriptor for the 56 // following applications: 57 // 58 // - An endpoint holder that opens a passive stream 59 // connection, known as a stream listener 60 // 61 // - An endpoint holder that opens a destination-unspecific 62 // datagram connection, known as a datagram listener 63 // 64 // - An endpoint holder that opens an active stream or a 65 // destination-specific datagram connection, known as a 66 // dialer 67 // 68 // - An endpoint holder that opens the other connection, such 69 // as talking to the protocol stack inside the kernel 70 // 71 // For stream and datagram listeners, they will only require 72 // named sockets, so we can assume that it's just a request 73 // from stream or datagram listeners when laddr is not nil but 74 // raddr is nil. Otherwise we assume it's just for dialers or 75 // the other connection holders. 76 77 if laddr != nil && raddr == nil { 78 switch sotype { 79 case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET: 80 if err := fd.listenStream(laddr, listenerBacklog); err != nil { 81 fd.Close() 82 return nil, err 83 } 84 return fd, nil 85 case syscall.SOCK_DGRAM: 86 if err := fd.listenDatagram(laddr); err != nil { 87 fd.Close() 88 return nil, err 89 } 90 return fd, nil 91 } 92 } 93 if err := fd.dial(ctx, laddr, raddr); err != nil { 94 fd.Close() 95 return nil, err 96 } 97 return fd, nil 98 } 99 100 func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr { 101 switch fd.family { 102 case syscall.AF_INET, syscall.AF_INET6: 103 switch fd.sotype { 104 case syscall.SOCK_STREAM: 105 return sockaddrToTCP 106 case syscall.SOCK_DGRAM: 107 return sockaddrToUDP 108 case syscall.SOCK_RAW: 109 return sockaddrToIP 110 } 111 case syscall.AF_UNIX: 112 switch fd.sotype { 113 case syscall.SOCK_STREAM: 114 return sockaddrToUnix 115 case syscall.SOCK_DGRAM: 116 return sockaddrToUnixgram 117 case syscall.SOCK_SEQPACKET: 118 return sockaddrToUnixpacket 119 } 120 } 121 return func(syscall.Sockaddr) Addr { return nil } 122 } 123 124 func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr) error { 125 var err error 126 var lsa syscall.Sockaddr 127 if laddr != nil { 128 if lsa, err = laddr.sockaddr(fd.family); err != nil { 129 return err 130 } else if lsa != nil { 131 if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil { 132 return os.NewSyscallError("bind", err) 133 } 134 } 135 } 136 var rsa syscall.Sockaddr // remote address from the user 137 var crsa syscall.Sockaddr // remote address we actually connected to 138 if raddr != nil { 139 if rsa, err = raddr.sockaddr(fd.family); err != nil { 140 return err 141 } 142 if crsa, err = fd.connect(ctx, lsa, rsa); err != nil { 143 return err 144 } 145 fd.isConnected = true 146 } else { 147 if err := fd.init(); err != nil { 148 return err 149 } 150 } 151 // Record the local and remote addresses from the actual socket. 152 // Get the local address by calling Getsockname. 153 // For the remote address, use 154 // 1) the one returned by the connect method, if any; or 155 // 2) the one from Getpeername, if it succeeds; or 156 // 3) the one passed to us as the raddr parameter. 157 lsa, _ = syscall.Getsockname(fd.pfd.Sysfd) 158 if crsa != nil { 159 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa)) 160 } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil { 161 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa)) 162 } else { 163 fd.setAddr(fd.addrFunc()(lsa), raddr) 164 } 165 return nil 166 } 167 168 func (fd *netFD) listenStream(laddr sockaddr, backlog int) error { 169 if err := setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil { 170 return err 171 } 172 if lsa, err := laddr.sockaddr(fd.family); err != nil { 173 return err 174 } else if lsa != nil { 175 if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil { 176 return os.NewSyscallError("bind", err) 177 } 178 } 179 if err := listenFunc(fd.pfd.Sysfd, backlog); err != nil { 180 return os.NewSyscallError("listen", err) 181 } 182 if err := fd.init(); err != nil { 183 return err 184 } 185 lsa, _ := syscall.Getsockname(fd.pfd.Sysfd) 186 fd.setAddr(fd.addrFunc()(lsa), nil) 187 return nil 188 } 189 190 func (fd *netFD) listenDatagram(laddr sockaddr) error { 191 switch addr := laddr.(type) { 192 case *UDPAddr: 193 // We provide a socket that listens to a wildcard 194 // address with reusable UDP port when the given laddr 195 // is an appropriate UDP multicast address prefix. 196 // This makes it possible for a single UDP listener to 197 // join multiple different group addresses, for 198 // multiple UDP listeners that listen on the same UDP 199 // port to join the same group address. 200 if addr.IP != nil && addr.IP.IsMulticast() { 201 if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil { 202 return err 203 } 204 addr := *addr 205 switch fd.family { 206 case syscall.AF_INET: 207 addr.IP = IPv4zero 208 case syscall.AF_INET6: 209 addr.IP = IPv6unspecified 210 } 211 laddr = &addr 212 } 213 } 214 if lsa, err := laddr.sockaddr(fd.family); err != nil { 215 return err 216 } else if lsa != nil { 217 if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil { 218 return os.NewSyscallError("bind", err) 219 } 220 } 221 if err := fd.init(); err != nil { 222 return err 223 } 224 lsa, _ := syscall.Getsockname(fd.pfd.Sysfd) 225 fd.setAddr(fd.addrFunc()(lsa), nil) 226 return nil 227 }