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 h
.raddr
= addr
.IP
.To16()
78 h
.laddr
= c
.fd
.laddr
.(*UDPAddr
).IP
.To16()
79 h
.ifcaddr
= IPv6zero
// ignored (receive only)
80 h
.rport
= uint16(addr
.Port
)
81 h
.lport
= uint16(c
.fd
.laddr
.(*UDPAddr
).Port
)
83 buf
:= make([]byte, udpHeaderSize
+len(b
))
84 i
:= copy(buf
, h
.Bytes())
86 return c
.fd
.data
.Write(buf
)
89 // WriteTo implements the PacketConn WriteTo method.
90 func (c
*UDPConn
) WriteTo(b
[]byte, addr Addr
) (int, error
) {
92 return 0, syscall
.EINVAL
94 a
, ok
:= addr
.(*UDPAddr
)
96 return 0, &OpError
{"write", c
.fd
.dir
, addr
, syscall
.EINVAL
}
98 return c
.WriteToUDP(b
, a
)
101 // WriteMsgUDP writes a packet to addr via c, copying the payload from
102 // b and the associated out-of-band data from oob. It returns the
103 // number of payload and out-of-band bytes written.
104 func (c
*UDPConn
) WriteMsgUDP(b
, oob
[]byte, addr
*UDPAddr
) (n
, oobn
int, err error
) {
105 return 0, 0, syscall
.EPLAN9
108 // DialUDP connects to the remote address raddr on the network net,
109 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
110 // used as the local address for the connection.
111 func DialUDP(net
string, laddr
, raddr
*UDPAddr
) (*UDPConn
, error
) {
112 return dialUDP(net
, laddr
, raddr
, noDeadline
)
115 func dialUDP(net
string, laddr
, raddr
*UDPAddr
, deadline time
.Time
) (*UDPConn
, error
) {
116 if !deadline
.IsZero() {
117 panic("net.dialUDP: deadline not implemented on Plan 9")
120 case "udp", "udp4", "udp6":
122 return nil, UnknownNetworkError(net
)
125 return nil, &OpError
{"dial", net
, nil, errMissingAddress
}
127 fd
, err
:= dialPlan9(net
, laddr
, raddr
)
131 return newUDPConn(fd
), nil
134 const udpHeaderSize
= 16*3 + 2*2
136 type udpHeader
struct {
137 raddr
, laddr
, ifcaddr IP
141 func (h
*udpHeader
) Bytes() []byte {
142 b
:= make([]byte, udpHeaderSize
)
144 i
+= copy(b
[i
:i
+16], h
.raddr
)
145 i
+= copy(b
[i
:i
+16], h
.laddr
)
146 i
+= copy(b
[i
:i
+16], h
.ifcaddr
)
147 b
[i
], b
[i
+1], i
= byte(h
.rport
>>8), byte(h
.rport
), i
+2
148 b
[i
], b
[i
+1], i
= byte(h
.lport
>>8), byte(h
.lport
), i
+2
152 func unmarshalUDPHeader(b
[]byte) (*udpHeader
, []byte) {
154 h
.raddr
, b
= IP(b
[:16]), b
[16:]
155 h
.laddr
, b
= IP(b
[:16]), b
[16:]
156 h
.ifcaddr
, b
= IP(b
[:16]), b
[16:]
157 h
.rport
, b
= uint16(b
[0])<<8|
uint16(b
[1]), b
[2:]
158 h
.lport
, b
= uint16(b
[0])<<8|
uint16(b
[1]), b
[2:]
162 // ListenUDP listens for incoming UDP packets addressed to the local
163 // address laddr. Net must be "udp", "udp4", or "udp6". If laddr has
164 // a port of 0, ListenUDP will choose an available port.
165 // The LocalAddr method of the returned UDPConn can be used to
166 // discover the port. The returned connection's ReadFrom and WriteTo
167 // methods can be used to receive and send UDP packets with per-packet
169 func ListenUDP(net
string, laddr
*UDPAddr
) (*UDPConn
, error
) {
171 case "udp", "udp4", "udp6":
173 return nil, UnknownNetworkError(net
)
178 l
, err
:= listenPlan9(net
, laddr
)
182 _
, err
= l
.ctl
.WriteString("headers")
186 l
.data
, err
= os
.OpenFile(l
.dir
+"/data", os
.O_RDWR
, 0)
190 return newUDPConn(l
.netFD()), nil
193 // ListenMulticastUDP listens for incoming multicast UDP packets
194 // addressed to the group address gaddr on ifi, which specifies the
195 // interface to join. ListenMulticastUDP uses default multicast
196 // interface if ifi is nil.
197 func ListenMulticastUDP(net
string, ifi
*Interface
, gaddr
*UDPAddr
) (*UDPConn
, error
) {
198 return nil, syscall
.EPLAN9