PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/gofrontend/libgo/go/net/udpsock_plan9.go

http://github.com/axw/llgo
Go | 215 lines | 143 code | 20 blank | 52 comment | 31 complexity | 8f52bf0be2e037284ac4403a68608ab3 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  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. package net
  5. import (
  6. "errors"
  7. "os"
  8. "syscall"
  9. "time"
  10. )
  11. // UDPConn is the implementation of the Conn and PacketConn interfaces
  12. // for UDP network connections.
  13. type UDPConn struct {
  14. conn
  15. }
  16. func newUDPConn(fd *netFD) *UDPConn { return &UDPConn{conn{fd}} }
  17. // ReadFromUDP reads a UDP packet from c, copying the payload into b.
  18. // It returns the number of bytes copied into b and the return address
  19. // that was on the packet.
  20. //
  21. // ReadFromUDP can be made to time out and return an error with
  22. // Timeout() == true after a fixed time limit; see SetDeadline and
  23. // SetReadDeadline.
  24. func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
  25. if !c.ok() || c.fd.data == nil {
  26. return 0, nil, syscall.EINVAL
  27. }
  28. buf := make([]byte, udpHeaderSize+len(b))
  29. m, err := c.fd.data.Read(buf)
  30. if err != nil {
  31. return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
  32. }
  33. if m < udpHeaderSize {
  34. return 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: errors.New("short read reading UDP header")}
  35. }
  36. buf = buf[:m]
  37. h, buf := unmarshalUDPHeader(buf)
  38. n = copy(b, buf)
  39. return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil
  40. }
  41. // ReadFrom implements the PacketConn ReadFrom method.
  42. func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) {
  43. if !c.ok() {
  44. return 0, nil, syscall.EINVAL
  45. }
  46. return c.ReadFromUDP(b)
  47. }
  48. // ReadMsgUDP reads a packet from c, copying the payload into b and
  49. // the associated out-of-band data into oob. It returns the number
  50. // of bytes copied into b, the number of bytes copied into oob, the
  51. // flags that were set on the packet and the source address of the
  52. // packet.
  53. func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
  54. return 0, 0, 0, nil, &OpError{Op: "read", Net: c.fd.dir, Source: c.fd.laddr, Addr: c.fd.raddr, Err: syscall.EPLAN9}
  55. }
  56. // WriteToUDP writes a UDP packet to addr via c, copying the payload
  57. // from b.
  58. //
  59. // WriteToUDP can be made to time out and return an error with
  60. // Timeout() == true after a fixed time limit; see SetDeadline and
  61. // SetWriteDeadline. On packet-oriented connections, write timeouts
  62. // are rare.
  63. func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error) {
  64. if !c.ok() || c.fd.data == nil {
  65. return 0, syscall.EINVAL
  66. }
  67. if addr == nil {
  68. return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: nil, Err: errMissingAddress}
  69. }
  70. h := new(udpHeader)
  71. h.raddr = addr.IP.To16()
  72. h.laddr = c.fd.laddr.(*UDPAddr).IP.To16()
  73. h.ifcaddr = IPv6zero // ignored (receive only)
  74. h.rport = uint16(addr.Port)
  75. h.lport = uint16(c.fd.laddr.(*UDPAddr).Port)
  76. buf := make([]byte, udpHeaderSize+len(b))
  77. i := copy(buf, h.Bytes())
  78. copy(buf[i:], b)
  79. if _, err := c.fd.data.Write(buf); err != nil {
  80. return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: err}
  81. }
  82. return len(b), nil
  83. }
  84. // WriteTo implements the PacketConn WriteTo method.
  85. func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) {
  86. if !c.ok() {
  87. return 0, syscall.EINVAL
  88. }
  89. a, ok := addr.(*UDPAddr)
  90. if !ok {
  91. return 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr, Err: syscall.EINVAL}
  92. }
  93. return c.WriteToUDP(b, a)
  94. }
  95. // WriteMsgUDP writes a packet to addr via c if c isn't connected, or
  96. // to c's remote destination address if c is connected (in which case
  97. // addr must be nil). The payload is copied from b and the associated
  98. // out-of-band data is copied from oob. It returns the number of
  99. // payload and out-of-band bytes written.
  100. func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
  101. return 0, 0, &OpError{Op: "write", Net: c.fd.dir, Source: c.fd.laddr, Addr: addr.opAddr(), Err: syscall.EPLAN9}
  102. }
  103. // DialUDP connects to the remote address raddr on the network net,
  104. // which must be "udp", "udp4", or "udp6". If laddr is not nil, it is
  105. // used as the local address for the connection.
  106. func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
  107. return dialUDP(net, laddr, raddr, noDeadline)
  108. }
  109. func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
  110. if !deadline.IsZero() {
  111. panic("net.dialUDP: deadline not implemented on Plan 9")
  112. }
  113. switch net {
  114. case "udp", "udp4", "udp6":
  115. default:
  116. return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: UnknownNetworkError(net)}
  117. }
  118. if raddr == nil {
  119. return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
  120. }
  121. fd, err := dialPlan9(net, laddr, raddr)
  122. if err != nil {
  123. return nil, err
  124. }
  125. return newUDPConn(fd), nil
  126. }
  127. const udpHeaderSize = 16*3 + 2*2
  128. type udpHeader struct {
  129. raddr, laddr, ifcaddr IP
  130. rport, lport uint16
  131. }
  132. func (h *udpHeader) Bytes() []byte {
  133. b := make([]byte, udpHeaderSize)
  134. i := 0
  135. i += copy(b[i:i+16], h.raddr)
  136. i += copy(b[i:i+16], h.laddr)
  137. i += copy(b[i:i+16], h.ifcaddr)
  138. b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2
  139. b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2
  140. return b
  141. }
  142. func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
  143. h := new(udpHeader)
  144. h.raddr, b = IP(b[:16]), b[16:]
  145. h.laddr, b = IP(b[:16]), b[16:]
  146. h.ifcaddr, b = IP(b[:16]), b[16:]
  147. h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
  148. h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
  149. return h, b
  150. }
  151. // ListenUDP listens for incoming UDP packets addressed to the local
  152. // address laddr. Net must be "udp", "udp4", or "udp6". If laddr has
  153. // a port of 0, ListenUDP will choose an available port.
  154. // The LocalAddr method of the returned UDPConn can be used to
  155. // discover the port. The returned connection's ReadFrom and WriteTo
  156. // methods can be used to receive and send UDP packets with per-packet
  157. // addressing.
  158. func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
  159. switch net {
  160. case "udp", "udp4", "udp6":
  161. default:
  162. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(net)}
  163. }
  164. if laddr == nil {
  165. laddr = &UDPAddr{}
  166. }
  167. l, err := listenPlan9(net, laddr)
  168. if err != nil {
  169. return nil, err
  170. }
  171. _, err = l.ctl.WriteString("headers")
  172. if err != nil {
  173. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
  174. }
  175. l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
  176. if err != nil {
  177. return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
  178. }
  179. fd, err := l.netFD()
  180. return newUDPConn(fd), err
  181. }
  182. // ListenMulticastUDP listens for incoming multicast UDP packets
  183. // addressed to the group address gaddr on the interface ifi.
  184. // Network must be "udp", "udp4" or "udp6".
  185. // ListenMulticastUDP uses the system-assigned multicast interface
  186. // when ifi is nil, although this is not recommended because the
  187. // assignment depends on platforms and sometimes it might require
  188. // routing configuration.
  189. //
  190. // ListenMulticastUDP is just for convenience of simple, small
  191. // applications. There are golang.org/x/net/ipv4 and
  192. // golang.org/x/net/ipv6 packages for general purpose uses.
  193. func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
  194. return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: syscall.EPLAN9}
  195. }