github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/net/udpsock_plan9.go (about)

     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  
     5  package net
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"os"
    11  	"syscall"
    12  )
    13  
    14  func (c *UDPConn) readFrom(b []byte) (n int, addr *UDPAddr, err error) {
    15  	buf := make([]byte, udpHeaderSize+len(b))
    16  	m, err := c.fd.Read(buf)
    17  	if err != nil {
    18  		return 0, nil, err
    19  	}
    20  	if m < udpHeaderSize {
    21  		return 0, nil, errors.New("short read reading UDP header")
    22  	}
    23  	buf = buf[:m]
    24  
    25  	h, buf := unmarshalUDPHeader(buf)
    26  	n = copy(b, buf)
    27  	return n, &UDPAddr{IP: h.raddr, Port: int(h.rport)}, nil
    28  }
    29  
    30  func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
    31  	return 0, 0, 0, nil, syscall.EPLAN9
    32  }
    33  
    34  func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
    35  	if addr == nil {
    36  		return 0, errMissingAddress
    37  	}
    38  	h := new(udpHeader)
    39  	h.raddr = addr.IP.To16()
    40  	h.laddr = c.fd.laddr.(*UDPAddr).IP.To16()
    41  	h.ifcaddr = IPv6zero // ignored (receive only)
    42  	h.rport = uint16(addr.Port)
    43  	h.lport = uint16(c.fd.laddr.(*UDPAddr).Port)
    44  
    45  	buf := make([]byte, udpHeaderSize+len(b))
    46  	i := copy(buf, h.Bytes())
    47  	copy(buf[i:], b)
    48  	if _, err := c.fd.Write(buf); err != nil {
    49  		return 0, err
    50  	}
    51  	return len(b), nil
    52  }
    53  
    54  func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
    55  	return 0, 0, syscall.EPLAN9
    56  }
    57  
    58  func dialUDP(ctx context.Context, net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
    59  	fd, err := dialPlan9(ctx, net, laddr, raddr)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return newUDPConn(fd), nil
    64  }
    65  
    66  const udpHeaderSize = 16*3 + 2*2
    67  
    68  type udpHeader struct {
    69  	raddr, laddr, ifcaddr IP
    70  	rport, lport          uint16
    71  }
    72  
    73  func (h *udpHeader) Bytes() []byte {
    74  	b := make([]byte, udpHeaderSize)
    75  	i := 0
    76  	i += copy(b[i:i+16], h.raddr)
    77  	i += copy(b[i:i+16], h.laddr)
    78  	i += copy(b[i:i+16], h.ifcaddr)
    79  	b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2
    80  	b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2
    81  	return b
    82  }
    83  
    84  func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) {
    85  	h := new(udpHeader)
    86  	h.raddr, b = IP(b[:16]), b[16:]
    87  	h.laddr, b = IP(b[:16]), b[16:]
    88  	h.ifcaddr, b = IP(b[:16]), b[16:]
    89  	h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
    90  	h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:]
    91  	return h, b
    92  }
    93  
    94  func listenUDP(ctx context.Context, network string, laddr *UDPAddr) (*UDPConn, error) {
    95  	l, err := listenPlan9(ctx, network, laddr)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	_, err = l.ctl.WriteString("headers")
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	fd, err := l.netFD()
   108  	return newUDPConn(fd), err
   109  }
   110  
   111  func listenMulticastUDP(ctx context.Context, network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
   112  	l, err := listenPlan9(ctx, network, gaddr)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	_, err = l.ctl.WriteString("headers")
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	var addrs []Addr
   121  	if ifi != nil {
   122  		addrs, err = ifi.Addrs()
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  	} else {
   127  		addrs, err = InterfaceAddrs()
   128  		if err != nil {
   129  			return nil, err
   130  		}
   131  	}
   132  	for _, addr := range addrs {
   133  		if ipnet, ok := addr.(*IPNet); ok {
   134  			_, err = l.ctl.WriteString("addmulti " + ipnet.IP.String() + " " + gaddr.IP.String())
   135  			if err != nil {
   136  				return nil, err
   137  			}
   138  		}
   139  	}
   140  	l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  	fd, err := l.netFD()
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  	return newUDPConn(fd), nil
   149  }