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