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