Source file
src/net/udpsock_posix.go
Documentation: net
1
2
3
4
5
6
7
8 package net
9
10 import (
11 "context"
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 n, sa, err := c.fd.readFrom(b)
48 switch sa := sa.(type) {
49 case *syscall.SockaddrInet4:
50 *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
51 case *syscall.SockaddrInet6:
52 *addr = UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
53 default:
54
55 addr = nil
56 }
57 return n, addr, err
58 }
59
60 func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
61 var sa syscall.Sockaddr
62 n, oobn, flags, sa, err = c.fd.readMsg(b, oob, 0)
63 switch sa := sa.(type) {
64 case *syscall.SockaddrInet4:
65 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
66 case *syscall.SockaddrInet6:
67 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
68 }
69 return
70 }
71
72 func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
73 if c.fd.isConnected {
74 return 0, ErrWriteToConnected
75 }
76 if addr == nil {
77 return 0, errMissingAddress
78 }
79 sa, err := addr.sockaddr(c.fd.family)
80 if err != nil {
81 return 0, err
82 }
83 return c.fd.writeTo(b, sa)
84 }
85
86 func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
87 if c.fd.isConnected && addr != nil {
88 return 0, 0, ErrWriteToConnected
89 }
90 if !c.fd.isConnected && addr == nil {
91 return 0, 0, errMissingAddress
92 }
93 sa, err := addr.sockaddr(c.fd.family)
94 if err != nil {
95 return 0, 0, err
96 }
97 return c.fd.writeMsg(b, oob, sa)
98 }
99
100 func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) {
101 fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial", sd.Dialer.Control)
102 if err != nil {
103 return nil, err
104 }
105 return newUDPConn(fd), nil
106 }
107
108 func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn, error) {
109 fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_DGRAM, 0, "listen", sl.ListenConfig.Control)
110 if err != nil {
111 return nil, err
112 }
113 return newUDPConn(fd), nil
114 }
115
116 func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
117 fd, err := internetSocket(ctx, sl.network, gaddr, nil, syscall.SOCK_DGRAM, 0, "listen", sl.ListenConfig.Control)
118 if err != nil {
119 return nil, err
120 }
121 c := newUDPConn(fd)
122 if ip4 := gaddr.IP.To4(); ip4 != nil {
123 if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
124 c.Close()
125 return nil, err
126 }
127 } else {
128 if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
129 c.Close()
130 return nil, err
131 }
132 }
133 return c, nil
134 }
135
136 func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
137 if ifi != nil {
138 if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
139 return err
140 }
141 }
142 if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
143 return err
144 }
145 if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
146 return err
147 }
148 return nil
149 }
150
151 func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
152 if ifi != nil {
153 if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
154 return err
155 }
156 }
157 if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
158 return err
159 }
160 if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
161 return err
162 }
163 return nil
164 }
165
View as plain text