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

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

Issue 5562048: code review 5562048: net: ListenMulticastUDP to listen concurrently across m... (Closed)
Left Patch Set: diff -r 49bf7083ea05 https://go.googlecode.com/hg/ Created 12 years, 2 months ago
Right Patch Set: diff -r 48a0594d7375 https://go.googlecode.com/hg/ Created 12 years, 2 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/sockopt_windows.go ('k') | src/pkg/net/udpsock_posix.go » ('j') | 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
5 // UDP for Plan 9
6
7 package net
8
9 import (
10 "errors"
11 "os"
12 "time"
13 )
14
15 // UDPConn is the implementation of the Conn and PacketConn
16 // interfaces for UDP network connections.
17 type UDPConn struct {
18 plan9Conn
19 }
20
21 // SetDeadline implements the Conn SetDeadline method.
22 func (c *UDPConn) SetDeadline(t time.Time) error {
23 return os.EPLAN9
24 }
25
26 // SetReadDeadline implements the Conn SetReadDeadline method.
27 func (c *UDPConn) SetReadDeadline(t time.Time) error {
28 return os.EPLAN9
29 }
30
31 // SetWriteDeadline implements the Conn SetWriteDeadline method.
32 func (c *UDPConn) SetWriteDeadline(t time.Time) error {
33 return os.EPLAN9
34 }
35
36 // UDP-specific methods.
37
38 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
39 // It returns the number of bytes copied into b and the return address
40 // that was on the packet.
41 //
42 // ReadFromUDP can be made to time out and return an error with Timeout() == tru e
43 // after a fixed time limit; see SetDeadline and SetReadDeadline.
44 func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
45 if !c.ok() {
46 return 0, nil, os.EINVAL
47 }
48 if c.data == nil {
49 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
50 if err != nil {
51 return 0, nil, err
52 }
53 }
54 buf := make([]byte, udpHeaderSize+len(b))
55 m, err := c.data.Read(buf)
56 if err != nil {
57 return
58 }
59 if m < udpHeaderSize {
60 return 0, nil, errors.New("short read reading UDP header")
61 }
62 buf = buf[:m]
63
64 h, buf := unmarshalUDPHeader(buf)
65 n = copy(b, buf)
66 return n, &UDPAddr{h.raddr, int(h.rport)}, nil
67 }
68
69 // ReadFrom implements the PacketConn ReadFrom method.
70 func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
71 if !c.ok() {
72 return 0, nil, os.EINVAL
73 }
74 return c.ReadFromUDP(b)
75 }
76
77 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
78 //
79 // WriteToUDP can be made to time out and return
80 // an error with Timeout() == true after a fixed time limit;
81 // see SetDeadline and SetWriteDeadline.
82 // On packet-oriented connections, write timeouts are rare.
83 func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
84 if !c.ok() {
85 return 0, os.EINVAL
86 }
87 if c.data == nil {
88 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
89 if err != nil {
90 return 0, err
91 }
92 }
93 h := new(udpHeader)
94 h.raddr = addr.IP.To16()
95 h.laddr = c.laddr.(*UDPAddr).IP.To16()
96 h.ifcaddr = IPv6zero // ignored (receive only)
97 h.rport = uint16(addr.Port)
98 h.lport = uint16(c.laddr.(*UDPAddr).Port)
99
100 buf := make([]byte, udpHeaderSize+len(b))
101 i := copy(buf, h.Bytes())
102 copy(buf[i:], b)
103 return c.data.Write(buf)
104 }
105
106 // WriteTo implements the PacketConn WriteTo method.
107 func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
108 if !c.ok() {
109 return 0, os.EINVAL
110 }
111 a, ok := addr.(*UDPAddr)
112 if !ok {
113 return 0, &OpError{"write", c.dir, addr, os.EINVAL}
114 }
115 return c.WriteToUDP(b, a)
116 }
117
118 // DialUDP connects to the remote address raddr on the network net,
119 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used
120 // as the local address for the connection.
121 func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
122 switch net {
123 case "udp", "udp4", "udp6":
124 default:
125 return nil, UnknownNetworkError(net)
126 }
127 if raddr == nil {
128 return nil, &OpError{"dial", net, nil, errMissingAddress}
129 }
130 c1, err := dialPlan9(net, laddr, raddr)
131 if err != nil {
132 return
133 }
134 return &UDPConn{*c1}, nil
135 }
136
137 const udpHeaderSize = 16*3 + 2*2
138
139 type udpHeader struct {
140 raddr, laddr, ifcaddr IP
141 rport, lport uint16
142 }
143
144 func (h *udpHeader) Bytes() []byte {
145 b := make([]byte, udpHeaderSize)
146 i := 0
147 i += copy(b[i:i+16], h.raddr)
148 i += copy(b[i:i+16], h.laddr)
149 i += copy(b[i:i+16], h.ifcaddr)
150 b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2
151 b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2
152 return b
153 }
154
155 func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
156 h := new(udpHeader)
157 h.raddr, b = IP(b[:16]), b[16:]
158 h.laddr, b = IP(b[:16]), b[16:]
159 h.ifcaddr, b = IP(b[:16]), b[16:]
160 h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
161 h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
162 return h, b
163 }
164
165 // ListenUDP listens for incoming UDP packets addressed to the
166 // local address laddr. The returned connection c's ReadFrom
167 // and WriteTo methods can be used to receive and send UDP
168 // packets with per-packet addressing.
169 func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
170 switch net {
171 case "udp", "udp4", "udp6":
172 default:
173 return nil, UnknownNetworkError(net)
174 }
175 if laddr == nil {
176 return nil, &OpError{"listen", net, nil, errMissingAddress}
177 }
178 l, err := listenPlan9(net, laddr)
179 if err != nil {
180 return
181 }
182 _, err = l.ctl.WriteString("headers")
183 if err != nil {
184 return
185 }
186 return &UDPConn{*l.plan9Conn()}, nil 1 return &UDPConn{*l.plan9Conn()}, nil
187 }
188
189 // ListenMulticastUDP listens for incoming multicast UDP packets
190 // addressed to the group address gaddr on ifi, which specifies
191 // the interface to join. ListenMulticastUDP uses default
192 // multicast interface if ifi is nil.
193 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, e rror) {
194 return nil, os.EPLAN9
195 } 2 }
196 3
197 // JoinGroup joins the IP multicast group named by addr on ifi, 4 // JoinGroup joins the IP multicast group named by addr on ifi,
198 // which specifies the interface to join. JoinGroup uses the 5 // which specifies the interface to join. JoinGroup uses the
199 // default multicast interface if ifi is nil. 6 // default multicast interface if ifi is nil.
200 func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error { 7 func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) error {
201 if !c.ok() { 8 if !c.ok() {
202 return os.EINVAL 9 return os.EINVAL
203 } 10 }
204 return os.EPLAN9 11 return os.EPLAN9
205 } 12 }
206 13
207 // LeaveGroup exits the IP multicast group named by addr on ifi. 14 // LeaveGroup exits the IP multicast group named by addr on ifi.
208 func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error { 15 func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) error {
209 if !c.ok() { 16 if !c.ok() {
210 return os.EINVAL 17 return os.EINVAL
211 } 18 }
212 return os.EPLAN9 19 return os.EPLAN9
213 } 20 }
LEFTRIGHT

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