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  }