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