Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(691)

Delta Between Two Patch Sets: src/pkg/net/udpsock_posix.go

Issue 6849045: code review 6849045: net, cmd/fix: add IPv6 scoped addressing zone to INET, ... (Closed)
Left Patch Set: diff -r fc4e67d82024 https://code.google.com/p/go Created 11 years, 4 months ago
Right Patch Set: diff -r c200281fac50 https://code.google.com/p/go Created 11 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/net/udpsock_plan9.go ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 1
5 // +build darwin freebsd linux netbsd openbsd windows 2 // +build darwin freebsd linux netbsd openbsd windows
6 3
7 // UDP sockets for POSIX 4 // UDP sockets
8 5
9 package net 6 package net
10 7
11 import (
12 "syscall"
13 "time"
14 )
15
16 func sockaddrToUDP(sa syscall.Sockaddr) Addr {
17 switch sa := sa.(type) {
18 case *syscall.SockaddrInet4:
19 return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
20 case *syscall.SockaddrInet6:
21 return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, ZoneId: zoneIdTo String(int(sa.ZoneId))}
22 }
23 return nil
24 }
25
26 func (a *UDPAddr) family() int {
27 if a == nil || len(a.IP) <= IPv4len {
28 return syscall.AF_INET
29 }
30 if a.IP.To4() != nil {
31 return syscall.AF_INET
32 }
33 return syscall.AF_INET6
34 }
35
36 func (a *UDPAddr) isWildcard() bool {
37 if a == nil || a.IP == nil {
38 return true
39 }
40 return a.IP.IsUnspecified()
41 }
42
43 func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
44 return ipToSockaddr(family, a.IP, a.Port, a.ZoneId)
45 }
46
47 func (a *UDPAddr) toAddr() sockaddr {
48 if a == nil { // nil *UDPAddr
49 return nil // nil interface
50 }
51 return a
52 }
53
54 // UDPConn is the implementation of the Conn and PacketConn
55 // interfaces for UDP network connections.
56 type UDPConn struct {
57 conn
58 }
59
60 func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
61
62 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
63 // It returns the number of bytes copied into b and the return address
64 // that was on the packet.
65 //
66 // ReadFromUDP can be made to time out and return an error with Timeout() == tru e
67 // after a fixed time limit; see SetDeadline and SetReadDeadline.
68 func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
69 if !c.ok() {
70 return 0, nil, syscall.EINVAL
71 }
72 n, sa, err := c.fd.ReadFrom(b)
73 switch sa := sa.(type) {
74 case *syscall.SockaddrInet4:
75 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
76 case *syscall.SockaddrInet6:
77 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, ZoneId: zoneIdTo String(int(sa.ZoneId))}
78 }
79 return
80 }
81
82 // ReadFrom implements the PacketConn ReadFrom method.
83 func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
84 if !c.ok() {
85 return 0, nil, syscall.EINVAL
86 }
87 n, addr, err := c.ReadFromUDP(b)
88 return n, addr.toAddr(), err
89 }
90
91 // ReadMsgUDP reads a packet from c, copying the payload into b and
92 // the associdated out-of-band data into oob. It returns the number
93 // of bytes copied into b, the number of bytes copied into oob, the
94 // flags that were set on the packet and the source address of the
95 // packet.
96 func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
97 if !c.ok() {
98 return 0, 0, 0, nil, syscall.EINVAL
99 }
100 var sa syscall.Sockaddr
101 n, oobn, flags, sa, err = c.fd.ReadMsg(b, oob)
102 switch sa := sa.(type) {
103 case *syscall.SockaddrInet4:
104 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
105 case *syscall.SockaddrInet6:
106 addr = &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, ZoneId: zoneIdTo String(int(sa.ZoneId))}
107 }
108 return
109 }
110
111 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
112 //
113 // WriteToUDP can be made to time out and return
114 // an error with Timeout() == true after a fixed time limit;
115 // see SetDeadline and SetWriteDeadline.
116 // On packet-oriented connections, write timeouts are rare.
117 func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
118 if !c.ok() {
119 return 0, syscall.EINVAL
120 }
121 if c.fd.isConnected {
122 return 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnected}
123 }
124 sa, err := addr.sockaddr(c.fd.family)
125 if err != nil {
126 return 0, &OpError{"write", c.fd.net, addr, err}
127 }
128 return c.fd.WriteTo(b, sa)
129 }
130
131 // WriteTo implements the PacketConn WriteTo method.
132 func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
133 if !c.ok() {
134 return 0, syscall.EINVAL
135 }
136 a, ok := addr.(*UDPAddr)
137 if !ok {
138 return 0, &OpError{"write", c.fd.net, addr, syscall.EINVAL}
139 }
140 return c.WriteToUDP(b, a)
141 }
142
143 // WriteMsgUDP writes a packet to addr via c, copying the payload from
144 // b and the associated out-of-band data from oob. It returns the
145 // number of payload and out-of-band bytes written.
146 func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err er ror) {
147 if !c.ok() {
148 return 0, 0, syscall.EINVAL
149 }
150 if c.fd.isConnected {
151 return 0, 0, &OpError{"write", c.fd.net, addr, ErrWriteToConnect ed}
152 }
153 sa, err := addr.sockaddr(c.fd.family)
154 if err != nil {
155 return 0, 0, &OpError{"write", c.fd.net, addr, err}
156 }
157 return c.fd.WriteMsg(b, oob, sa)
158 }
159
160 // DialUDP connects to the remote address raddr on the network net,
161 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used
162 // as the local address for the connection.
163 func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
164 return dialUDP(net, laddr, raddr, noDeadline)
165 }
166
167 func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, e rror) {
168 switch net {
169 case "udp", "udp4", "udp6":
170 default:
171 return nil, UnknownNetworkError(net)
172 }
173 if raddr == nil {
174 return nil, &OpError{"dial", net, nil, errMissingAddress}
175 }
176 fd, err := internetSocket(net, laddr.toAddr(), raddr.toAddr(), deadline, syscall.SOCK_DGRAM, 0, "dial", sockaddrToUDP)
177 if err != nil {
178 return nil, err
179 }
180 return newUDPConn(fd), nil
181 }
182
183 // ListenUDP listens for incoming UDP packets addressed to the
184 // local address laddr. The returned connection c's ReadFrom
185 // and WriteTo methods can be used to receive and send UDP
186 // packets with per-packet addressing.
187 func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
188 switch net {
189 case "udp", "udp4", "udp6":
190 default:
191 return nil, UnknownNetworkError(net)
192 }
193 if laddr == nil {
194 laddr = &UDPAddr{}
195 }
196 fd, err := internetSocket(net, laddr.toAddr(), nil, noDeadline, syscall. SOCK_DGRAM, 0, "listen", sockaddrToUDP)
197 if err != nil {
198 return nil, err
199 }
200 return newUDPConn(fd), nil
201 }
202
203 // ListenMulticastUDP listens for incoming multicast UDP packets
204 // addressed to the group address gaddr on ifi, which specifies
205 // the interface to join. ListenMulticastUDP uses default
206 // multicast interface if ifi is nil.
207 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e rror) {
208 switch net {
209 case "udp", "udp4", "udp6":
210 default:
211 return nil, UnknownNetworkError(net)
212 }
213 if gaddr == nil || gaddr.IP == nil {
214 return nil, &OpError{"listenmulticast", net, nil, errMissingAddr ess}
215 }
216 fd, err := internetSocket(net, gaddr.toAddr(), nil, noDeadline, syscall. SOCK_DGRAM, 0, "listen", sockaddrToUDP)
217 if err != nil {
218 return nil, err
219 }
220 c := newUDPConn(fd)
221 ip4 := gaddr.IP.To4()
222 if ip4 != nil {
223 err := listenIPv4MulticastUDP(c, ifi, ip4)
224 if err != nil {
225 c.Close()
226 return nil, err
227 }
228 } else {
229 err := listenIPv6MulticastUDP(c, ifi, gaddr.IP)
230 if err != nil {
231 c.Close()
232 return nil, err
233 }
234 }
235 return c, nil
236 }
237
238 func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
239 if ifi != nil {
240 err := setIPv4MulticastInterface(c.fd, ifi)
241 if err != nil {
242 return err
243 }
244 }
245 err := setIPv4MulticastLoopback(c.fd, false)
246 if err != nil {
247 return err
248 }
249 err = joinIPv4GroupUDP(c, ifi, ip)
250 if err != nil {
251 return err
252 }
253 return nil
254 }
255
256 func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
257 if ifi != nil {
258 err := setIPv6MulticastInterface(c.fd, ifi)
259 if err != nil {
260 return err
261 }
262 }
263 err := setIPv6MulticastLoopback(c.fd, false)
264 if err != nil {
265 return err
266 }
267 err = joinIPv6GroupUDP(c, ifi, ip)
268 if err != nil {
269 return err
270 }
271 return nil
272 }
273
274 func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
275 err := joinIPv4Group(c.fd, ifi, ip)
276 if err != nil {
277 return &OpError{"joinipv4group", c.fd.net, &IPAddr{IP: ip}, err}
278 }
279 return nil
280 }
281
282 func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) error {
283 err := joinIPv6Group(c.fd, ifi, ip)
284 if err != nil {
285 return &OpError{"joinipv6group", c.fd.net, &IPAddr{IP: ip}, err}
286 }
287 return nil
288 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b