github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/net/ipsock_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 // Internet protocol family sockets for Plan 9 6 7 package net 8 9 import ( 10 "errors" 11 "os" 12 "syscall" 13 ) 14 15 func probeIPv4Stack() bool { 16 // TODO(mikio): implement this when Plan 9 supports IPv6-only 17 // kernel. 18 return true 19 } 20 21 // probeIPv6Stack returns two boolean values. If the first boolean 22 // value is true, kernel supports basic IPv6 functionality. If the 23 // second boolean value is true, kernel supports IPv6 IPv4-mapping. 24 func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) { 25 // TODO(mikio): implement this once Plan 9 gets an IPv6 26 // protocol stack implementation. 27 return false, false 28 } 29 30 // parsePlan9Addr parses address of the form [ip!]port (e.g. 127.0.0.1!80). 31 func parsePlan9Addr(s string) (ip IP, iport int, err error) { 32 addr := IPv4zero // address contains port only 33 i := byteIndex(s, '!') 34 if i >= 0 { 35 addr = ParseIP(s[:i]) 36 if addr == nil { 37 return nil, 0, errors.New("net: parsing IP failed") 38 } 39 } 40 p, _, ok := dtoi(s[i+1:], 0) 41 if !ok { 42 return nil, 0, errors.New("net: parsing port failed") 43 } 44 if p < 0 || p > 0xFFFF { 45 return nil, 0, &AddrError{"invalid port", string(p)} 46 } 47 return addr, p, nil 48 } 49 50 func readPlan9Addr(proto, filename string) (addr Addr, err error) { 51 var buf [128]byte 52 53 f, err := os.Open(filename) 54 if err != nil { 55 return 56 } 57 defer f.Close() 58 n, err := f.Read(buf[:]) 59 if err != nil { 60 return 61 } 62 ip, port, err := parsePlan9Addr(string(buf[:n])) 63 if err != nil { 64 return 65 } 66 switch proto { 67 case "tcp": 68 addr = &TCPAddr{IP: ip, Port: port} 69 case "udp": 70 addr = &UDPAddr{IP: ip, Port: port} 71 default: 72 return nil, errors.New("unknown protocol " + proto) 73 } 74 return addr, nil 75 } 76 77 func startPlan9(net string, addr Addr) (ctl *os.File, dest, proto, name string, err error) { 78 var ( 79 ip IP 80 port int 81 ) 82 switch a := addr.(type) { 83 case *TCPAddr: 84 proto = "tcp" 85 ip = a.IP 86 port = a.Port 87 case *UDPAddr: 88 proto = "udp" 89 ip = a.IP 90 port = a.Port 91 default: 92 err = UnknownNetworkError(net) 93 return 94 } 95 96 clone, dest, err := queryCS1(proto, ip, port) 97 if err != nil { 98 return 99 } 100 f, err := os.OpenFile(clone, os.O_RDWR, 0) 101 if err != nil { 102 return 103 } 104 var buf [16]byte 105 n, err := f.Read(buf[:]) 106 if err != nil { 107 f.Close() 108 return 109 } 110 return f, dest, proto, string(buf[:n]), nil 111 } 112 113 func netErr(e error) { 114 oe, ok := e.(*OpError) 115 if !ok { 116 return 117 } 118 if pe, ok := oe.Err.(*os.PathError); ok { 119 if _, ok = pe.Err.(syscall.ErrorString); ok { 120 oe.Err = pe.Err 121 } 122 } 123 } 124 125 func dialPlan9(net string, laddr, raddr Addr) (fd *netFD, err error) { 126 defer func() { netErr(err) }() 127 f, dest, proto, name, err := startPlan9(net, raddr) 128 if err != nil { 129 return nil, &OpError{"dial", net, raddr, err} 130 } 131 _, err = f.WriteString("connect " + dest) 132 if err != nil { 133 f.Close() 134 return nil, &OpError{"dial", f.Name(), raddr, err} 135 } 136 data, err := os.OpenFile("/net/"+proto+"/"+name+"/data", os.O_RDWR, 0) 137 if err != nil { 138 f.Close() 139 return nil, &OpError{"dial", net, raddr, err} 140 } 141 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") 142 if err != nil { 143 data.Close() 144 f.Close() 145 return nil, &OpError{"dial", proto, raddr, err} 146 } 147 return newFD(proto, name, f, data, laddr, raddr), nil 148 } 149 150 func listenPlan9(net string, laddr Addr) (fd *netFD, err error) { 151 defer func() { netErr(err) }() 152 f, dest, proto, name, err := startPlan9(net, laddr) 153 if err != nil { 154 return nil, &OpError{"listen", net, laddr, err} 155 } 156 _, err = f.WriteString("announce " + dest) 157 if err != nil { 158 f.Close() 159 return nil, &OpError{"announce", proto, laddr, err} 160 } 161 laddr, err = readPlan9Addr(proto, "/net/"+proto+"/"+name+"/local") 162 if err != nil { 163 f.Close() 164 return nil, &OpError{Op: "listen", Net: net, Err: err} 165 } 166 return newFD(proto, name, f, nil, laddr, nil), nil 167 } 168 169 func (l *netFD) netFD() *netFD { 170 return newFD(l.proto, l.name, l.ctl, l.data, l.laddr, l.raddr) 171 } 172 173 func (l *netFD) acceptPlan9() (fd *netFD, err error) { 174 defer func() { netErr(err) }() 175 f, err := os.Open(l.dir + "/listen") 176 if err != nil { 177 return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err} 178 } 179 var buf [16]byte 180 n, err := f.Read(buf[:]) 181 if err != nil { 182 f.Close() 183 return nil, &OpError{"accept", l.dir + "/listen", l.laddr, err} 184 } 185 name := string(buf[:n]) 186 data, err := os.OpenFile("/net/"+l.proto+"/"+name+"/data", os.O_RDWR, 0) 187 if err != nil { 188 f.Close() 189 return nil, &OpError{"accept", l.proto, l.laddr, err} 190 } 191 raddr, err := readPlan9Addr(l.proto, "/net/"+l.proto+"/"+name+"/remote") 192 if err != nil { 193 data.Close() 194 f.Close() 195 return nil, &OpError{"accept", l.proto, l.laddr, err} 196 } 197 return newFD(l.proto, name, f, data, l.laddr, raddr), nil 198 }