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.
14 // UDPConn is the implementation of the Conn and PacketConn interfaces
15 // for UDP network connections.
20 func newUDPConn(fd
*netFD
) *UDPConn
{ return &UDPConn
{conn
{fd
}} }
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
) {
30 if !c
.ok() || c
.fd
.data
== nil {
31 return 0, nil, syscall
.EINVAL
33 buf
:= make([]byte, udpHeaderSize
+len(b
))
34 m
, err
:= c
.fd
.data
.Read(buf
)
38 if m
< udpHeaderSize
{
39 return 0, nil, errors
.New("short read reading UDP header")
43 h
, buf
:= unmarshalUDPHeader(buf
)
45 return n
, &UDPAddr
{IP
: h
.raddr
, Port
: int(h
.rport
)}, nil
48 // ReadFrom implements the PacketConn ReadFrom method.
49 func (c
*UDPConn
) ReadFrom(b
[]byte) (int, Addr
, error
) {
51 return 0, nil, syscall
.EINVAL
53 return c
.ReadFromUDP(b
)
56 // ReadMsgUDP reads a packet from c, copying the payload into b and
57 // the associated out-of-band data into oob. It returns the number
58 // of bytes copied into b, the number of bytes copied into oob, the
59 // flags that were set on the packet and the source address of the
61 func (c
*UDPConn
) ReadMsgUDP(b
, oob
[]byte) (n
, oobn
, flags
int, addr
*UDPAddr
, err error
) {
62 return 0, 0, 0, nil, syscall
.EPLAN9
65 // WriteToUDP writes a UDP packet to addr via c, copying the payload
68 // WriteToUDP can be made to time out and return an error with
69 // Timeout() == true after a fixed time limit; see SetDeadline and
70 // SetWriteDeadline. On packet-oriented connections, write timeouts
72 func (c
*UDPConn
) WriteToUDP(b
[]byte, addr
*UDPAddr
) (int, error
) {
73 if !c
.ok() || c
.fd
.data
== nil {
74 return 0, syscall
.EINVAL
77 return 0, &OpError
{Op
: "write", Net
: c
.fd
.dir
, Addr
: nil, Err
: errMissingAddress
}
80 h
.raddr
= addr
.IP
.To16()
81 h
.laddr
= c
.fd
.laddr
.(*UDPAddr
).IP
.To16()
82 h
.ifcaddr
= IPv6zero
// ignored (receive only)
83 h
.rport
= uint16(addr
.Port
)
84 h
.lport
= uint16(c
.fd
.laddr
.(*UDPAddr
).Port
)
86 buf
:= make([]byte, udpHeaderSize
+len(b
))
87 i
:= copy(buf
, h
.Bytes())
89 return c
.fd
.data
.Write(buf
)
92 // WriteTo implements the PacketConn WriteTo method.
93 func (c
*UDPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
95 return 0, syscall
.EINVAL
97 a
, ok
:= addr
.(*UDPAddr
)
99 return 0, &OpError
{"write", c
.fd
.dir
, addr
, syscall
.EINVAL
}
101 return c
.WriteToUDP(b
, a
)
104 // WriteMsgUDP writes a packet to addr via c, copying the payload from
105 // b and the associated out-of-band data from oob. It returns the
106 // number of payload and out-of-band bytes written.
107 func (c
*UDPConn
) WriteMsgUDP(b
, oob
[]byte, addr
*UDPAddr
) (n
, oobn
int, err error
) {
108 return 0, 0, syscall
.EPLAN9
111 // DialUDP connects to the remote address raddr on the network net,
112 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
113 // used as the local address for the connection.
114 func DialUDP(net
string, laddr
, raddr
*UDPAddr
) (*UDPConn
, error
) {
115 return dialUDP(net
, laddr
, raddr
, noDeadline
)
118 func dialUDP(net
string, laddr
, raddr
*UDPAddr
, deadline time
.Time
) (*UDPConn
, error
) {
119 if !deadline
.IsZero() {
120 panic("net.dialUDP: deadline not implemented on Plan 9")
123 case "udp", "udp4", "udp6":
125 return nil, UnknownNetworkError(net
)
128 return nil, &OpError
{"dial", net
, nil, errMissingAddress
}
130 fd
, err
:= dialPlan9(net
, laddr
, raddr
)
134 return newUDPConn(fd
), nil
137 const udpHeaderSize
= 16*3 + 2*2
139 type udpHeader
struct {
140 raddr
, laddr
, ifcaddr IP
144 func (h
*udpHeader
) Bytes() []byte {
145 b
:= make([]byte, udpHeaderSize
)
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
155 func unmarshalUDPHeader(b
[]byte) (*udpHeader
, []byte) {
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:]
165 // ListenUDP listens for incoming UDP packets addressed to the local
166 // address laddr. Net must be "udp", "udp4", or "udp6". If laddr has
167 // a port of 0, ListenUDP will choose an available port.
168 // The LocalAddr method of the returned UDPConn can be used to
169 // discover the port. The returned connection's ReadFrom and WriteTo
170 // methods can be used to receive and send UDP packets with per-packet
172 func ListenUDP(net
string, laddr
*UDPAddr
) (*UDPConn
, error
) {
174 case "udp", "udp4", "udp6":
176 return nil, UnknownNetworkError(net
)
181 l
, err
:= listenPlan9(net
, laddr
)
185 _
, err
= l
.ctl
.WriteString("headers")
189 l
.data
, err
= os
.OpenFile(l
.dir
+"/data", os
.O_RDWR
, 0)
194 return newUDPConn(fd
), err
197 // ListenMulticastUDP listens for incoming multicast UDP packets
198 // addressed to the group address gaddr on ifi, which specifies the
199 // interface to join. ListenMulticastUDP uses default multicast
200 // interface if ifi is nil.
201 func ListenMulticastUDP(net
string, ifi
*Interface
, gaddr
*UDPAddr
) (*UDPConn
, error
) {
202 return nil, syscall
.EPLAN9