Source file
src/net/sock_posix.go
Documentation: net
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "internal/poll"
12 "os"
13 "syscall"
14 )
15
16
17
18 type sockaddr interface {
19 Addr
20
21
22
23 family() int
24
25
26
27 isWildcard() bool
28
29
30
31
32
33 sockaddr(family int) (syscall.Sockaddr, error)
34
35
36 toLocal(net string) sockaddr
37 }
38
39
40
41 func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr) (fd *netFD, err error) {
42 s, err := sysSocket(family, sotype, proto)
43 if err != nil {
44 return nil, err
45 }
46 if err = setDefaultSockopts(s, family, sotype, ipv6only); err != nil {
47 poll.CloseFunc(s)
48 return nil, err
49 }
50 if fd, err = newFD(s, family, sotype, net); err != nil {
51 poll.CloseFunc(s)
52 return nil, err
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 if laddr != nil && raddr == nil {
78 switch sotype {
79 case syscall.SOCK_STREAM, syscall.SOCK_SEQPACKET:
80 if err := fd.listenStream(laddr, listenerBacklog); err != nil {
81 fd.Close()
82 return nil, err
83 }
84 return fd, nil
85 case syscall.SOCK_DGRAM:
86 if err := fd.listenDatagram(laddr); err != nil {
87 fd.Close()
88 return nil, err
89 }
90 return fd, nil
91 }
92 }
93 if err := fd.dial(ctx, laddr, raddr); err != nil {
94 fd.Close()
95 return nil, err
96 }
97 return fd, nil
98 }
99
100 func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
101 switch fd.family {
102 case syscall.AF_INET, syscall.AF_INET6:
103 switch fd.sotype {
104 case syscall.SOCK_STREAM:
105 return sockaddrToTCP
106 case syscall.SOCK_DGRAM:
107 return sockaddrToUDP
108 case syscall.SOCK_RAW:
109 return sockaddrToIP
110 }
111 case syscall.AF_UNIX:
112 switch fd.sotype {
113 case syscall.SOCK_STREAM:
114 return sockaddrToUnix
115 case syscall.SOCK_DGRAM:
116 return sockaddrToUnixgram
117 case syscall.SOCK_SEQPACKET:
118 return sockaddrToUnixpacket
119 }
120 }
121 return func(syscall.Sockaddr) Addr { return nil }
122 }
123
124 func (fd *netFD) dial(ctx context.Context, laddr, raddr sockaddr) error {
125 var err error
126 var lsa syscall.Sockaddr
127 if laddr != nil {
128 if lsa, err = laddr.sockaddr(fd.family); err != nil {
129 return err
130 } else if lsa != nil {
131 if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
132 return os.NewSyscallError("bind", err)
133 }
134 }
135 }
136 var rsa syscall.Sockaddr
137 var crsa syscall.Sockaddr
138 if raddr != nil {
139 if rsa, err = raddr.sockaddr(fd.family); err != nil {
140 return err
141 }
142 if crsa, err = fd.connect(ctx, lsa, rsa); err != nil {
143 return err
144 }
145 fd.isConnected = true
146 } else {
147 if err := fd.init(); err != nil {
148 return err
149 }
150 }
151
152
153
154
155
156
157 lsa, _ = syscall.Getsockname(fd.pfd.Sysfd)
158 if crsa != nil {
159 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(crsa))
160 } else if rsa, _ = syscall.Getpeername(fd.pfd.Sysfd); rsa != nil {
161 fd.setAddr(fd.addrFunc()(lsa), fd.addrFunc()(rsa))
162 } else {
163 fd.setAddr(fd.addrFunc()(lsa), raddr)
164 }
165 return nil
166 }
167
168 func (fd *netFD) listenStream(laddr sockaddr, backlog int) error {
169 if err := setDefaultListenerSockopts(fd.pfd.Sysfd); err != nil {
170 return err
171 }
172 if lsa, err := laddr.sockaddr(fd.family); err != nil {
173 return err
174 } else if lsa != nil {
175 if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
176 return os.NewSyscallError("bind", err)
177 }
178 }
179 if err := listenFunc(fd.pfd.Sysfd, backlog); err != nil {
180 return os.NewSyscallError("listen", err)
181 }
182 if err := fd.init(); err != nil {
183 return err
184 }
185 lsa, _ := syscall.Getsockname(fd.pfd.Sysfd)
186 fd.setAddr(fd.addrFunc()(lsa), nil)
187 return nil
188 }
189
190 func (fd *netFD) listenDatagram(laddr sockaddr) error {
191 switch addr := laddr.(type) {
192 case *UDPAddr:
193
194
195
196
197
198
199
200 if addr.IP != nil && addr.IP.IsMulticast() {
201 if err := setDefaultMulticastSockopts(fd.pfd.Sysfd); err != nil {
202 return err
203 }
204 addr := *addr
205 switch fd.family {
206 case syscall.AF_INET:
207 addr.IP = IPv4zero
208 case syscall.AF_INET6:
209 addr.IP = IPv6unspecified
210 }
211 laddr = &addr
212 }
213 }
214 if lsa, err := laddr.sockaddr(fd.family); err != nil {
215 return err
216 } else if lsa != nil {
217 if err := syscall.Bind(fd.pfd.Sysfd, lsa); err != nil {
218 return os.NewSyscallError("bind", err)
219 }
220 }
221 if err := fd.init(); err != nil {
222 return err
223 }
224 lsa, _ := syscall.Getsockname(fd.pfd.Sysfd)
225 fd.setAddr(fd.addrFunc()(lsa), nil)
226 return nil
227 }
228
View as plain text