github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/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 }