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.
16 // UDPConn is the implementation of the Conn and PacketConn
17 // interfaces for UDP network connections.
22 // SetDeadline implements the Conn SetDeadline method.
23 func (c *UDPConn) SetDeadline(t time.Time) error {
27 // SetReadDeadline implements the Conn SetReadDeadline method.
28 func (c *UDPConn) SetReadDeadline(t time.Time) error {
32 // SetWriteDeadline implements the Conn SetWriteDeadline method.
33 func (c *UDPConn) SetWriteDeadline(t time.Time) error {
37 // UDP-specific methods.
39 // ReadFromUDP reads a UDP packet from c, copying the payload into b.
40 // It returns the number of bytes copied into b and the return address
41 // that was on the packet.
43 // ReadFromUDP can be made to time out and return an error with Timeout() == true
44 // after a fixed time limit; see SetDeadline and SetReadDeadline.
45 func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
47 return 0, nil, syscall.EINVAL
50 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
55 buf := make([]byte, udpHeaderSize+len(b))
56 m, err := c.data.Read(buf)
60 if m < udpHeaderSize {
61 return 0, nil, errors.New("short read reading UDP header")
65 h, buf := unmarshalUDPHeader(buf)
67 return n, &UDPAddr{h.raddr, int(h.rport)}, nil
70 // ReadFrom implements the PacketConn ReadFrom method.
71 func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
73 return 0, nil, syscall.EINVAL
75 return c.ReadFromUDP(b)
78 // WriteToUDP writes a UDP packet to addr via c, copying the payload from b.
80 // WriteToUDP can be made to time out and return
81 // an error with Timeout() == true after a fixed time limit;
82 // see SetDeadline and SetWriteDeadline.
83 // On packet-oriented connections, write timeouts are rare.
84 func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
86 return 0, syscall.EINVAL
89 c.data, err = os.OpenFile(c.dir+"/data", os.O_RDWR, 0)
95 h.raddr = addr.IP.To16()
96 h.laddr = c.laddr.(*UDPAddr).IP.To16()
97 h.ifcaddr = IPv6zero // ignored (receive only)
98 h.rport = uint16(addr.Port)
99 h.lport = uint16(c.laddr.(*UDPAddr).Port)
101 buf := make([]byte, udpHeaderSize+len(b))
102 i := copy(buf, h.Bytes())
104 return c.data.Write(buf)
107 // WriteTo implements the PacketConn WriteTo method.
108 func (c *UDPConn) WriteTo(b []byte, addr Addr) (n int, err error) {
110 return 0, syscall.EINVAL
112 a, ok := addr.(*UDPAddr)
114 return 0, &OpError{"write", c.dir, addr, syscall.EINVAL}
116 return c.WriteToUDP(b, a)
119 // DialUDP connects to the remote address raddr on the network net,
120 // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used
121 // as the local address for the connection.
122 func DialUDP(net string, laddr, raddr *UDPAddr) (c *UDPConn, err error) {
124 case "udp", "udp4", "udp6":
126 return nil, UnknownNetworkError(net)
129 return nil, &OpError{"dial", net, nil, errMissingAddress}
131 c1, err := dialPlan9(net, laddr, raddr)
135 return &UDPConn{*c1}, nil
138 const udpHeaderSize = 16*3 + 2*2
140 type udpHeader struct {
141 raddr, laddr, ifcaddr IP
145 func (h *udpHeader) Bytes() []byte {
146 b := make([]byte, udpHeaderSize)
148 i += copy(b[i:i+16], h.raddr)
149 i += copy(b[i:i+16], h.laddr)
150 i += copy(b[i:i+16], h.ifcaddr)
151 b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2
152 b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2
156 func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
158 h.raddr, b = IP(b[:16]), b[16:]
159 h.laddr, b = IP(b[:16]), b[16:]
160 h.ifcaddr, b = IP(b[:16]), b[16:]
161 h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
162 h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
166 // ListenUDP listens for incoming UDP packets addressed to the
167 // local address laddr. The returned connection c's ReadFrom
168 // and WriteTo methods can be used to receive and send UDP
169 // packets with per-packet addressing.
170 func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err error) {
172 case "udp", "udp4", "udp6":
174 return nil, UnknownNetworkError(net)
177 return nil, &OpError{"listen", net, nil, errMissingAddress}
179 l, err := listenPlan9(net, laddr)
183 _, err = l.ctl.WriteString("headers")
187 return &UDPConn{*l.plan9Conn()}, nil
190 // ListenMulticastUDP listens for incoming multicast UDP packets
191 // addressed to the group address gaddr on ifi, which specifies
192 // the interface to join. ListenMulticastUDP uses default
193 // multicast interface if ifi is nil.
194 func ListenMulticastUDP(net string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
195 return nil, syscall.EPLAN9