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