github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/runtime/ppapi/syscall_net_nacl.go (about) 1 // Copyright 2014 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 ppapi 6 7 import ( 8 "fmt" 9 "io" 10 "net" 11 "strconv" 12 "syscall" 13 ) 14 15 type netConnFile struct { 16 conn net.Conn 17 listener net.Listener 18 protoType string 19 addr string // set by Bind() 20 } 21 22 func (*netConnFile) stat(*syscall.Stat_t) error { 23 panic("stat not yet implemented") 24 } 25 func (n *netConnFile) read(b []byte) (int, error) { 26 count, err := n.conn.Read(b) 27 if err != nil && err != io.EOF { 28 switch err.Error() { 29 case "connection reset", "aborted", "Reading from closed connection": 30 return 0, err 31 } 32 panic(fmt.Sprintf("Failed to read: %v", err)) 33 } 34 remoteaddr := n.conn.RemoteAddr() 35 if err == io.EOF { 36 fmt.Printf("Network read to %v resulted in EOF!", remoteaddr) 37 } else { 38 fmt.Printf("Network read to %v: %s", remoteaddr, string(b[:count])) 39 } 40 return count, err 41 } 42 func (n *netConnFile) write(b []byte) (int, error) { 43 count, err := n.conn.Write(b) 44 if err != nil && err != io.EOF { 45 switch err.Error() { 46 case "connection reset", "aborted", "Reading from closed connection": 47 return 0, err 48 } 49 panic(fmt.Sprintf("Failed to write: %v", err)) 50 } 51 remoteaddr := n.conn.RemoteAddr() 52 if err == io.EOF { 53 fmt.Printf("Network write to %v resulted in EOF!", remoteaddr) 54 } else { 55 fmt.Printf("Network write to %v: %s", remoteaddr, string(b[:count])) 56 } 57 return count, err 58 } 59 func (*netConnFile) seek(int64, int) (int64, error) { 60 panic("seek not yet implemented") 61 } 62 func (*netConnFile) pread([]byte, int64) (int, error) { 63 panic("pread not yet implemented") 64 } 65 func (*netConnFile) pwrite([]byte, int64) (int, error) { 66 panic("pwrite not yet implemented") 67 } 68 func (n *netConnFile) close() error { 69 if n.conn != nil { 70 return n.conn.Close() 71 } else if n.listener != nil { 72 return n.listener.Close() 73 } 74 return nil 75 } 76 77 func fdToNetConnFile(fd int) (*netConnFile, error) { 78 f, err := fdToFile(fd) 79 if err != nil { 80 return nil, err 81 } 82 if netFile, ok := f.(*netConnFile); ok { 83 return netFile, nil 84 } 85 return nil, fmt.Errorf("FD: %v Resolved to a file that does not represent a net connection. Type: %T", fd, f) 86 } 87 88 func sockaddrToStr(sa syscall.Sockaddr, allowZeroPort bool) (string, error) { 89 switch vsa := sa.(type) { 90 case *syscall.SockaddrInet4: 91 ip := net.IP(vsa.Addr[:]) 92 if vsa.Port == 0 && !allowZeroPort { 93 return "", fmt.Errorf("No port specified for %s", ip.String()) 94 } 95 return fmt.Sprintf("%v:%d", ip, vsa.Port), nil 96 case *syscall.SockaddrInet6: 97 ip := net.IP(vsa.Addr[:]) 98 if vsa.Port == 0 && !allowZeroPort { 99 return "", fmt.Errorf("No port specified for %s", ip.String()) 100 } 101 return fmt.Sprintf("[%v]:%d", ip, vsa.Port), nil 102 default: 103 panic(fmt.Sprintf("Unsupported Sockaddr type: %v", vsa)) 104 } 105 } 106 107 func strToSockaddr(addr string) (syscall.Sockaddr, error) { 108 hostStr, portStr, err := net.SplitHostPort(addr) 109 if err != nil { 110 hostStr = addr 111 portStr = "" 112 } 113 114 ip := net.ParseIP(hostStr) 115 if ip == nil { 116 return nil, fmt.Errorf("Failed to parse address: %s", addr) 117 } 118 119 uport, err := strconv.ParseUint(portStr, 0, 16) 120 if err != nil { 121 return nil, fmt.Errorf("Failed to parse port: %d", uport) 122 } 123 124 port := int(uport) 125 126 ipv4 := ip.To4() 127 if ipv4 != nil { 128 if len(ipv4) != 4 { 129 panic("Invalid length for ipv4 address") 130 } 131 var addrArray [4]byte 132 copy(addrArray[:], []byte(ipv4)) 133 return &syscall.SockaddrInet4{ 134 Port: port, 135 Addr: addrArray, 136 }, nil 137 } 138 139 ipv6 := ip.To16() 140 if ipv6 != nil { 141 if len(ipv6) != 16 { 142 panic("Invalid length for ipv6 address") 143 } 144 var addrArray [16]byte 145 copy(addrArray[:], []byte(ipv6)) 146 return &syscall.SockaddrInet6{ 147 Port: port, 148 Addr: addrArray, 149 }, nil 150 } 151 152 panic("Invalid parsed address") 153 } 154 155 func (PPAPISyscallImpl) Socket(domain, typ, proto int) (fd int, err error) { 156 fmt.Printf("Socket(%v, %v, %v)", domain, typ, proto) 157 switch domain { 158 case syscall.AF_INET, syscall.AF_INET6: 159 default: 160 return -1, syscall.EPROTONOSUPPORT 161 } 162 var protoType string 163 if typ == syscall.SOCK_STREAM { 164 protoType = "tcp" 165 } else if typ == syscall.SOCK_DGRAM { 166 protoType = "udp" 167 } else { 168 return -1, syscall.ESOCKTNOSUPPORT 169 } 170 if proto != 0 { 171 return -1, syscall.EPROTONOSUPPORT 172 } 173 f := &netConnFile{ 174 protoType: protoType, 175 } 176 return newFD(f), nil 177 } 178 179 func (PPAPISyscallImpl) Bind(fd int, sa syscall.Sockaddr) (err error) { 180 netFile, err := fdToNetConnFile(fd) 181 if err != nil { 182 return err 183 } 184 addrStr, err := sockaddrToStr(sa, true) 185 if err != nil { 186 return err 187 } 188 fmt.Printf("Binding to %s", addrStr) 189 netFile.addr = addrStr 190 return nil 191 } 192 193 func (pi PPAPISyscallImpl) Listen(fd int, backlog int) (err error) { 194 // backlog is ignored 195 netFile, err := fdToNetConnFile(fd) 196 if err != nil { 197 return err 198 } 199 if netFile.addr == "" { 200 panic("Bind() must be called before listen") 201 } 202 fmt.Printf("Listening on address: %s", netFile.addr) 203 listener, err := pi.Instance.Listen(netFile.protoType, netFile.addr) 204 if err != nil { 205 return err 206 } 207 netFile.listener = listener 208 return nil 209 } 210 211 func (PPAPISyscallImpl) Accept(fd int) (nfd int, sa syscall.Sockaddr, err error) { 212 netFile, err := fdToNetConnFile(fd) 213 if err != nil { 214 return -1, nil, err 215 } 216 conn, err := netFile.listener.Accept() 217 if err != nil { 218 return -1, nil, err 219 } 220 connFd := newFD(&netConnFile{ 221 conn: conn, 222 }) 223 addr := conn.RemoteAddr() 224 if addr == nil { 225 panic("Failed to get remote endpoint address in accept. This should always be possible.") 226 } 227 straddr := addr.String() 228 fmt.Printf("straddr: %v", straddr) 229 sa, err = strToSockaddr(straddr) 230 if err != nil { 231 return -1, nil, err 232 } 233 return connFd, sa, nil 234 } 235 236 func (pi PPAPISyscallImpl) Connect(fd int, sa syscall.Sockaddr) (err error) { 237 netFile, err := fdToNetConnFile(fd) 238 if err != nil { 239 return err 240 } 241 addrStr, err := sockaddrToStr(sa, false) 242 if err != nil { 243 return err 244 } 245 fmt.Printf("Connecting to %s", addrStr) 246 conn, err := pi.Instance.Dial(netFile.protoType, addrStr) 247 if err != nil { 248 fmt.Printf("Error connecting to %s: %v", addrStr, err) 249 return err 250 } 251 netFile.conn = conn 252 return nil 253 } 254 255 func (PPAPISyscallImpl) Getsockname(fd int) (sa syscall.Sockaddr, err error) { 256 netFile, err := fdToNetConnFile(fd) 257 if err != nil { 258 return nil, err 259 } 260 if netFile.conn == nil && netFile.listener == nil { 261 } 262 var addr net.Addr 263 if netFile.listener != nil { 264 addr = netFile.listener.Addr() 265 } else if netFile.conn != nil { 266 addr = netFile.conn.LocalAddr() 267 } else { 268 return nil, fmt.Errorf("Cannot Getsockname on unconnected socket.") 269 } 270 if addr == nil { 271 panic("Addr is nil") 272 //return nil, nil 273 } 274 return strToSockaddr(addr.String()) 275 } 276 277 func (PPAPISyscallImpl) Getpeername(fd int) (sa syscall.Sockaddr, err error) { 278 netFile, err := fdToNetConnFile(fd) 279 if err != nil { 280 return nil, err 281 } 282 var addr net.Addr 283 if netFile.conn != nil { 284 addr = netFile.conn.RemoteAddr() 285 } else { 286 return nil, fmt.Errorf("Cannot Getpeername on unconnected socket.") 287 } 288 if addr == nil { 289 panic("Addr is nil") 290 //return nil, nil 291 } 292 return strToSockaddr(addr.String()) 293 } 294 295 func (PPAPISyscallImpl) StopIO(fd int) error { 296 f, err := fdToNetConnFile(fd) 297 if err != nil { 298 return err 299 } 300 f.close() 301 return nil 302 }