github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/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 "os" 11 "syscall" 12 "time" 13 ) 14 15 // A sockaddr represents a TCP, UDP, IP or Unix network endpoint 16 // address that can be converted into a syscall.Sockaddr. 17 type sockaddr interface { 18 Addr 19 20 netaddr 21 22 // family returns the platform-dependent address family 23 // identifier. 24 family() int 25 26 // isWildcard reports whether the address is a wildcard 27 // address. 28 isWildcard() bool 29 30 // sockaddr returns the address converted into a syscall 31 // sockaddr type that implements syscall.Sockaddr 32 // interface. It returns a nil interface when the address is 33 // nil. 34 sockaddr(family int) (syscall.Sockaddr, error) 35 } 36 37 // socket returns a network file descriptor that is ready for 38 // asynchronous I/O using the network poller. 39 func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time) (fd *netFD, err error) { 40 s, err := sysSocket(family, sotype, proto) 41 if err != nil { 42 return nil, err 43 } 44 if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil { 45 closesocket(s) 46 return nil, err 47 } 48 if fd, err = newFD(s, family, sotype, net); err != nil { 49 closesocket(s) 50 return nil, err 51 } 52 53 // This function makes a network file descriptor for the 54 // following applications: 55 // 56 // - An endpoint holder that opens a passive stream 57 // connenction, known as a stream listener 58 // 59 // - An endpoint holder that opens a destination-unspecific 60 // datagram connection, known as a datagram listener 61 // 62 // - An endpoint holder that opens an active stream or a 63 // destination-specific datagram connection, known as a 64 // dialer 65 // 66 // - An endpoint holder that opens the other connection, such 67 // as talking to the protocol stack inside the kernel 68 // 69 // For stream and datagram listeners, they will only require 70 // named sockets, so we can assume that it's just a request 71 // from stream or datagram listeners when laddr is not nil but 72 // raddr is nil. Otherwise we assume it's just for dialers or 73 // the other connection holders. 74 75 if laddr != nil && raddr == nil { 76 switch sotype { 77 case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET: 78 if err := fd.listenStream(laddr, listenerBacklog); err != nil { 79 fd.Close() 80 return nil, err 81 } 82 return fd, nil 83 case syscall.SOCK_DGRAM: 84 if err := fd.listenDatagram(laddr); err != nil { 85 fd.Close() 86 return nil, err 87 } 88 return fd, nil 89 } 90 } 91 if err := fd.dial(laddr, raddr, deadline); err != nil { 92 fd.Close() 93 return nil, err 94 } 95 return fd, nil 96 } 97 98 func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr { 99 switch fd.family { 100 case syscall.AF_INET, syscall.AF_INET6: 101 switch fd.sotype { 102 case syscall.SOCK_STREAM: 103 return sockaddrToTCP 104 case syscall.SOCK_DGRAM: 105 return sockaddrToUDP 106 case syscall.SOCK_RAW: 107 return sockaddrToIP 108 } 109 case syscall.AF_UNIX: 110 switch fd.sotype { 111 case syscall.SOCK_STREAM: 112 return sockaddrToUnix 113 case syscall.SOCK_DGRAM: 114 return sockaddrToUnixgram 115 case syscall.SOCK_SEQPACKET: 116 return sockaddrToUnixpacket 117 } 118 } 119 return func(syscall.Sockaddr) Addr { return nil } 120 } 121 122 func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time) error { 123 var err error 124 var lsa syscall.Sockaddr 125 if laddr != nil { 126 if lsa, err = laddr.sockaddr(fd.family); err != nil { 127 return err 128 } else if lsa != nil { 129 if err := syscall.Bind(fd.sysfd, lsa); err != nil { 130 return os.NewSyscallError("bind", err) 131 } 132 } 133 } 134 var rsa syscall.Sockaddr 135 if raddr != nil { 136 if rsa, err = raddr.sockaddr(fd.family); err != nil { 137 return err 138 } 139 if err := fd.connect(lsa, rsa, deadline); err != nil { 140 return err 141 } 142 fd.isConnected = true 143 } else { 144 if err := fd.init(); err != nil { 145 return err 146 } 147 } 148 lsa, _ = syscall.Getsockname(fd.sysfd) 149 if rsa, _ = syscall.Getpeername(fd.sysfd); rsa != nil { 150 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa)) 151 } else { 152 fd.setAddr(fd.addrFunc()(lsa), raddr) 153 } 154 return nil 155 } 156 157 func (fd *netFD) listenStream(laddr sockaddr, backlog int) error { 158 if err := setDefaultListenerSockopts(fd.sysfd); err != nil { 159 return err 160 } 161 if lsa, err := laddr.sockaddr(fd.family); err != nil { 162 return err 163 } else if lsa != nil { 164 if err := syscall.Bind(fd.sysfd, lsa); err != nil { 165 return os.NewSyscallError("bind", err) 166 } 167 } 168 if err := syscall.Listen(fd.sysfd, backlog); err != nil { 169 return os.NewSyscallError("listen", err) 170 } 171 if err := fd.init(); err != nil { 172 return err 173 } 174 lsa, _ := syscall.Getsockname(fd.sysfd) 175 fd.setAddr(fd.addrFunc()(lsa), nil) 176 return nil 177 } 178 179 func (fd *netFD) listenDatagram(laddr sockaddr) error { 180 switch addr := laddr.(type) { 181 case *UDPAddr: 182 // We provide a socket that listens to a wildcard 183 // address with reusable UDP port when the given laddr 184 // is an appropriate UDP multicast address prefix. 185 // This makes it possible for a single UDP listener to 186 // join multiple different group addresses, for 187 // multiple UDP listeners that listen on the same UDP 188 // port to join the same group address. 189 if addr.IP != nil && addr.IP.IsMulticast() { 190 if err := setDefaultMulticastSockopts(fd.sysfd); err != nil { 191 return err 192 } 193 addr := *addr 194 switch fd.family { 195 case syscall.AF_INET: 196 addr.IP = IPv4zero 197 case syscall.AF_INET6: 198 addr.IP = IPv6unspecified 199 } 200 laddr = &addr 201 } 202 } 203 if lsa, err := laddr.sockaddr(fd.family); err != nil { 204 return err 205 } else if lsa != nil { 206 if err := syscall.Bind(fd.sysfd, lsa); err != nil { 207 return os.NewSyscallError("bind", err) 208 } 209 } 210 if err := fd.init(); err != nil { 211 return err 212 } 213 lsa, _ := syscall.Getsockname(fd.sysfd) 214 fd.setAddr(fd.addrFunc()(lsa), nil) 215 return nil 216 }