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