blob: 3e71d3fe3d5751ac3cf0b3c63ca0823c287b8311 [file] [log] [blame]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// TODO: move to using fd_unix for fuchsia?
package net
import (
"errors"
"internal/poll"
"os"
"runtime"
"syscall"
"syscall/zx/mxnet"
"syscall/zx/zxsocket"
"time"
)
// Network file descriptor.
type netFD struct {
pfd poll.FD
// immutable until Close
sock *zxsocket.Socket
net string
family int
sotype int
isStream bool
isConnected bool
laddr Addr
raddr Addr
}
func newFD(sock *zxsocket.Socket, family, sotype int, net string) *netFD {
netfd := &netFD{
pfd: poll.FD{
Sysfd: syscall.OpenFDIO(sock),
},
sock: sock,
family: family,
sotype: sotype,
net: net,
}
return netfd
}
func (fd *netFD) init() error {
// TODO: flip to true after implementing netpoller for real
return fd.pfd.Init(fd.net, false)
}
func (fd *netFD) isTCP() bool {
return len(fd.net) >= 3 && fd.net[:3] == "tcp"
}
func (fd *netFD) Read(b []byte) (n int, err error) {
n, err = fd.pfd.Read(b)
runtime.KeepAlive(fd)
return n, err
}
func (fd *netFD) Write(b []byte) (n int, err error) {
n, err = fd.pfd.Write(b)
runtime.KeepAlive(fd)
return n, err
}
func (fd *netFD) readMsg(b []byte) (n, flags int, addr string, port uint16, err error) {
// TODO: move call to pfd
data, flags, addr, port, err := fd.sock.RecvMsg(len(b))
runtime.KeepAlive(fd)
n = copy(b, data)
return n, flags, addr, port, err
}
func (fd *netFD) sendMsg(b []byte, addr string, port uint16) (n int, err error) {
// TODO: move call to pfd
n, err = fd.sock.SendMsg(b, addr, port)
runtime.KeepAlive(fd)
return n, err
}
func (fd *netFD) closeRead() error {
return errors.New("net: closeRead not implemented on fuchsia")
}
func (fd *netFD) closeWrite() error {
return errors.New("net: closeWrite not implemented on fuchsia")
}
func (fd *netFD) Close() error {
return fd.pfd.Close()
}
func (fd *netFD) dup() (*os.File, error) {
// TODO(mknyszek): fd.sock is an FDIO so one can make an FD from it to
// implement this.
return nil, errors.New("net: dup not implemented on fuchsia")
}
func (fd *netFD) accept() (*netFD, error) {
newm, err := fd.pfd.Accept()
if err != nil {
return nil, err
}
netfd := newFD(newm, fd.family, fd.sotype, fd.net)
if err := netfd.init(); err != nil {
fd.Close()
return nil, err
}
netfd.setAddr()
return netfd, nil
}
func (fd *netFD) asAddr(code int16, b []byte, err error) sockaddr {
if err != nil {
return nil
}
if code != 0 {
return nil
}
addr, port, err := mxnet.DecodeSockaddr(b)
if err != nil {
return nil
}
ip := IP(addr)
if isZeros(ip) && port == 0 {
return nil
}
switch fd.sotype {
case syscall.SOCK_STREAM:
return &TCPAddr{IP: ip, Port: int(port)}
case syscall.SOCK_DGRAM:
return &UDPAddr{IP: ip, Port: int(port)}
}
return nil
}
func (fd *netFD) setAddr() {
fd.laddr = fd.asAddr(fd.sock.GetSockName())
fd.raddr = fd.asAddr(fd.sock.GetPeerName())
runtime.SetFinalizer(fd, (*netFD).Close)
}
func (fd *netFD) SetDeadline(t time.Time) error {
return fd.pfd.SetDeadline(t)
}
func (fd *netFD) SetReadDeadline(t time.Time) error {
return fd.pfd.SetReadDeadline(t)
}
func (fd *netFD) SetWriteDeadline(t time.Time) error {
return fd.pfd.SetWriteDeadline(t)
}