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.
5 // UDP sockets for Plan 9
16 // UDPConn is the implementation of the Conn and PacketConn
17 // interfaces for UDP network connections.
22 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
23 // It returns the number of bytes copied into b and the return address
24 // that was on the packet.
26 // ReadFromUDP can be made to time out and return an error with
27 // Timeout() == true after a fixed time limit; see SetDeadline and
29 func (c
*UDPConn
) ReadFromUDP(b
[]byte) (n
int, addr
*UDPAddr
, err error
) {
31 return 0, nil, syscall
.EINVAL
34 c
.fd
.data
, err
= os
.OpenFile(c
.fd
.dir
+"/data", os
.O_RDWR
, 0)
39 buf
:= make([]byte, udpHeaderSize
+len(b
))
40 m
, err
:= c
.fd
.data
.Read(buf
)
44 if m
< udpHeaderSize
{
45 return 0, nil, errors
.New("short read reading UDP header")
49 h
, buf
:= unmarshalUDPHeader(buf
)
51 return n
, &UDPAddr
{IP
: h
.raddr
, Port
: int(h
.rport
)}, nil
54 // ReadFrom implements the PacketConn ReadFrom method.
55 func (c
*UDPConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
57 return 0, nil, syscall
.EINVAL
59 return c
.ReadFromUDP(b
)
62 // ReadMsgUDP reads a packet from c, copying the payload into b and
63 // the associdated out-of-band data into oob. It returns the number
64 // of bytes copied into b, the number of bytes copied into oob, the
65 // flags that were set on the packet and the source address of the
67 func (c
*UDPConn
) ReadMsgUDP(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UDPAddr
, err error
) {
68 return 0, 0, 0, nil, syscall
.EPLAN9
71 // WriteToUDP writes a UDP packet to addr via c, copying the payload
74 // WriteToUDP can be made to time out and return an error with
75 // Timeout() == true after a fixed time limit; see SetDeadline and
76 // SetWriteDeadline. On packet-oriented connections, write timeouts
78 func (c
*UDPConn
) WriteToUDP(b
[]byte, addr
*UDPAddr
) (int, error
) {
80 return 0, syscall
.EINVAL
83 f
, err
:= os
.OpenFile(c
.fd
.dir
+"/data", os
.O_RDWR
, 0)
90 h
.raddr
= addr
.IP
.To16()
91 h
.laddr
= c
.fd
.laddr
.(*UDPAddr
).IP
.To16()
92 h
.ifcaddr
= IPv6zero
// ignored (receive only)
93 h
.rport
= uint16(addr
.Port
)
94 h
.lport
= uint16(c
.fd
.laddr
.(*UDPAddr
).Port
)
96 buf
:= make([]byte, udpHeaderSize
+len(b
))
97 i
:= copy(buf
, h
.Bytes())
99 return c
.fd
.data
.Write(buf
)
102 // WriteTo implements the PacketConn WriteTo method.
103 func (c
*UDPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
105 return 0, syscall
.EINVAL
107 a
, ok
:= addr
.(*UDPAddr
)
109 return 0, &OpError
{"write", c
.fd
.dir
, addr
, syscall
.EINVAL
}
111 return c
.WriteToUDP(b
, a
)
114 // WriteMsgUDP writes a packet to addr via c, copying the payload from
115 // b and the associated out-of-band data from oob. It returns the
116 // number of payload and out-of-band bytes written.
117 func (c
*UDPConn
) WriteMsgUDP(b
, oob
[]byte, addr
*UDPAddr
) (n
, oobn
int, err error
) {
118 return 0, 0, syscall
.EPLAN9
121 // DialUDP connects to the remote address raddr on the network net,
122 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
123 // used as the local address for the connection.
124 func DialUDP(net
string, laddr
, raddr
*UDPAddr
) (*UDPConn
, error
) {
125 return dialUDP(net
, laddr
, raddr
, noDeadline
)
128 func dialUDP(net
string, laddr
, raddr
*UDPAddr
, deadline time
.Time
) (*UDPConn
, error
) {
129 if !deadline
.IsZero() {
130 panic("net.dialUDP: deadline not implemented on Plan 9")
133 case "udp", "udp4", "udp6":
135 return nil, UnknownNetworkError(net
)
138 return nil, &OpError
{"dial", net
, nil, errMissingAddress
}
140 fd
, err
:= dialPlan9(net
, laddr
, raddr
)
144 return &UDPConn
{conn
{fd
}}, nil
147 const udpHeaderSize
= 16*3 + 2*2
149 type udpHeader
struct {
150 raddr
, laddr
, ifcaddr IP
154 func (h
*udpHeader
) Bytes() []byte {
155 b
:= make([]byte, udpHeaderSize
)
157 i
+= copy(b
[i
:i
+16], h
.raddr
)
158 i
+= copy(b
[i
:i
+16], h
.laddr
)
159 i
+= copy(b
[i
:i
+16], h
.ifcaddr
)
160 b
[i
], b
[i
+1], i
= byte(h
.rport
>>8), byte(h
.rport
), i
+2
161 b
[i
], b
[i
+1], i
= byte(h
.lport
>>8), byte(h
.lport
), i
+2
165 func unmarshalUDPHeader(b
[]byte) (*udpHeader
, []byte) {
167 h
.raddr
, b
= IP(b
[:16]), b
[16:]
168 h
.laddr
, b
= IP(b
[:16]), b
[16:]
169 h
.ifcaddr
, b
= IP(b
[:16]), b
[16:]
170 h
.rport
, b
= uint16(b
[0])<<8|
uint16(b
[1]), b
[2:]
171 h
.lport
, b
= uint16(b
[0])<<8|
uint16(b
[1]), b
[2:]
175 // ListenUDP listens for incoming UDP packets addressed to the local
176 // address laddr. The returned connection c's ReadFrom and WriteTo
177 // methods can be used to receive and send UDP packets with per-packet
179 func ListenUDP(net
string, laddr
*UDPAddr
) (*UDPConn
, error
) {
181 case "udp", "udp4", "udp6":
183 return nil, UnknownNetworkError(net
)
188 l
, err
:= listenPlan9(net
, laddr
)
192 _
, err
= l
.ctl
.WriteString("headers")
196 return &UDPConn
{conn
{l
.netFD()}}, nil
199 // ListenMulticastUDP listens for incoming multicast UDP packets
200 // addressed to the group address gaddr on ifi, which specifies the
201 // interface to join. ListenMulticastUDP uses default multicast
202 // interface if ifi is nil.
203 func ListenMulticastUDP(net
string, ifi
*Interface
, gaddr
*UDPAddr
) (*UDPConn
, error
) {
204 return nil, syscall
.EPLAN9