Source file
src/net/udpsock_posix.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "net/netip"
12 "syscall"
13 )
14
15 func sockaddrToUDP(sa syscall.Sockaddr) Addr {
16 switch sa := sa.(type) {
17 case *syscall.SockaddrInet4:
18 return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
19 case *syscall.SockaddrInet6:
20 return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
21 }
22 return nil
23 }
24
25 func (a *UDPAddr) family() int {
26 if a == nil || len(a.IP) <= IPv4len {
27 return syscall.AF_INET
28 }
29 if a.IP.To4() != nil {
30 return syscall.AF_INET
31 }
32 return syscall.AF_INET6
33 }
34
35 func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
36 if a == nil {
37 return nil, nil
38 }
39 return ipToSockaddr(family, a.IP, a.Port, a.Zone)
40 }
41
42 func (a *UDPAddr) toLocal(net string) sockaddr {
43 return &UDPAddr{loopbackIP(net), a.Port, a.Zone}
44 }
45
46 func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
47 var n int
48 var err error
49 switch c.fd.family {
50 case syscall.AF_INET:
51 var from syscall.SockaddrInet4
52 n, err = c.fd.readFromInet4(b, &from)
53 if err == nil {
54 ip := from.Addr
55 *addr = UDPAddr{IP: ip[:], Port: from.Port}
56 }
57 case syscall.AF_INET6:
58 var from syscall.SockaddrInet6
59 n, err = c.fd.readFromInet6(b, &from)
60 if err == nil {
61 ip := from.Addr
62 *addr = UDPAddr{IP: ip[:], Port: from.Port, Zone: zoneCache.name(int(from.ZoneId))}
63 }
64 }
65 if err != nil {
66
67 addr = nil
68 }
69 return n, addr, err
70 }
71
72 func (c *UDPConn) readFromAddrPort(b []byte) (n int, addr netip.AddrPort, err error) {
73 var ip netip.Addr
74 var port int
75 switch c.fd.family {
76 case syscall.AF_INET:
77 var from syscall.SockaddrInet4
78 n, err = c.fd.readFromInet4(b, &from)
79 if err == nil {
80 ip = netip.AddrFrom4(from.Addr)
81 port = from.Port
82 }
83 case syscall.AF_INET6:
84 var from syscall.SockaddrInet6
85 n, err = c.fd.readFromInet6(b, &from)
86 if err == nil {
87 ip = netip.AddrFrom16(from.Addr).WithZone(zoneCache.name(int(from.ZoneId)))
88 port = from.Port
89 }
90 }
91 if err == nil {
92 addr = netip.AddrPortFrom(ip, uint16(port))
93 }
94 return n, addr, err
95 }
96
97 func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) {
98 switch c.fd.family {
99 case syscall.AF_INET:
100 var sa syscall.SockaddrInet4
101 n, oobn, flags, err = c.fd.readMsgInet4(b, oob, 0, &sa)
102 ip := netip.AddrFrom4(sa.Addr)
103 addr = netip.AddrPortFrom(ip, uint16(sa.Port))
104 case syscall.AF_INET6:
105 var sa syscall.SockaddrInet6
106 n, oobn, flags, err = c.fd.readMsgInet6(b, oob, 0, &sa)
107 ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId)))
108 addr = netip.AddrPortFrom(ip, uint16(sa.Port))
109 }
110 return
111 }
112
113 func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
114 if c.fd.isConnected {
115 return 0, ErrWriteToConnected
116 }
117 if addr == nil {
118 return 0, errMissingAddress
119 }
120
121 switch c.fd.family {
122 case syscall.AF_INET:
123 sa, err := ipToSockaddrInet4(addr.IP, addr.Port)
124 if err != nil {
125 return 0, err
126 }
127 return c.fd.writeToInet4(b, &sa)
128 case syscall.AF_INET6:
129 sa, err := ipToSockaddrInet6(addr.IP, addr.Port, addr.Zone)
130 if err != nil {
131 return 0, err
132 }
133 return c.fd.writeToInet6(b, &sa)
134 default:
135 return 0, &AddrError{Err: "invalid address family", Addr: addr.IP.String()}
136 }
137 }
138
139 func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) {
140 if c.fd.isConnected {
141 return 0, ErrWriteToConnected
142 }
143 if !addr.IsValid() {
144 return 0, errMissingAddress
145 }
146
147 switch c.fd.family {
148 case syscall.AF_INET:
149 sa, err := addrPortToSockaddrInet4(addr)
150 if err != nil {
151 return 0, err
152 }
153 return c.fd.writeToInet4(b, &sa)
154 case syscall.AF_INET6:
155 sa, err := addrPortToSockaddrInet6(addr)
156 if err != nil {
157 return 0, err
158 }
159 return c.fd.writeToInet6(b, &sa)
160 default:
161 return 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
162 }
163 }
164
165 func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
166 if c.fd.isConnected && addr != nil {
167 return 0, 0, ErrWriteToConnected
168 }
169 if !c.fd.isConnected && addr == nil {
170 return 0, 0, errMissingAddress
171 }
172 sa, err := addr.sockaddr(c.fd.family)
173 if err != nil {
174 return 0, 0, err
175 }
176 return c.fd.writeMsg(b, oob, sa)
177 }
178
179 func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) {
180 if c.fd.isConnected && addr.IsValid() {
181 return 0, 0, ErrWriteToConnected
182 }
183 if !c.fd.isConnected && !addr.IsValid() {
184 return 0, 0, errMissingAddress
185 }
186
187 switch c.fd.family {
188 case syscall.AF_INET:
189 sa, err := addrPortToSockaddrInet4(addr)
190 if err != nil {
191 return 0, 0, err
192 }
193 return c.fd.writeMsgInet4(b, oob, &sa)
194 case syscall.AF_INET6:
195 sa, err := addrPortToSockaddrInet6(addr)
196 if err != nil {
197 return 0, 0, err
198 }
199 return c.fd.writeMsgInet6(b, oob, &sa)
200 default:
201 return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
202 }
203 }
204
205 func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) {
206 ctrlCtxFn := sd.Dialer.ControlContext
207 if ctrlCtxFn == nil && sd.Dialer.Control != nil {
208 ctrlCtxFn = func(ctx context.Context, network, address string, c syscall.RawConn) error {
209 return sd.Dialer.Control(network, address, c)
210 }
211 }
212 fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial", ctrlCtxFn)
213 if err != nil {
214 return nil, err
215 }
216 return newUDPConn(fd), nil
217 }
218
219 func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn, error) {
220 var ctrlCtxFn func(ctx context.Context, network, address string, c syscall.RawConn) error
221 if sl.ListenConfig.Control != nil {
222 ctrlCtxFn = func(ctx context.Context, network, address string, c syscall.RawConn) error {
223 return sl.ListenConfig.Control(network, address, c)
224 }
225 }
226 fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_DGRAM, 0, "listen", ctrlCtxFn)
227 if err != nil {
228 return nil, err
229 }
230 return newUDPConn(fd), nil
231 }
232
233 func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
234 var ctrlCtxFn func(ctx context.Context, network, address string, c syscall.RawConn) error
235 if sl.ListenConfig.Control != nil {
236 ctrlCtxFn = func(ctx context.Context, network, address string, c syscall.RawConn) error {
237 return sl.ListenConfig.Control(network, address, c)
238 }
239 }
240 fd, err := internetSocket(ctx, sl.network, gaddr, nil, syscall.SOCK_DGRAM, 0, "listen", ctrlCtxFn)
241 if err != nil {
242 return nil, err
243 }
244 c := newUDPConn(fd)
245 if ip4 := gaddr.IP.To4(); ip4 != nil {
246 if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
247 c.Close()
248 return nil, err
249 }
250 } else {
251 if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
252 c.Close()
253 return nil, err
254 }
255 }
256 return c, nil
257 }
258
259 func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
260 if ifi != nil {
261 if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
262 return err
263 }
264 }
265 if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
266 return err
267 }
268 if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
269 return err
270 }
271 return nil
272 }
273
274 func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
275 if ifi != nil {
276 if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
277 return err
278 }
279 }
280 if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
281 return err
282 }
283 if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
284 return err
285 }
286 return nil
287 }
288
View as plain text