diff --git a/README.md b/README.md index 6d1e0a0..9cb957d 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,11 @@ src/net │   ├── status.go │   ├── transfer.go * │   └── transport.go * +├── interface.go * ├── ip.go ├── iprawsock.go * ├── ipsock.go * +├── lookup.go * ├── mac.go ├── mac_test.go ├── netdev.go + @@ -61,10 +63,12 @@ src/net ├── README.md ├── tcpsock.go * ├── tlssock.go + -└── udpsock.go * +├── udpsock.go * +└── unixsock.go * src/crypto/tls/ ├── common.go * +├── ticket.go * └── tls.go * ``` diff --git a/dial.go b/dial.go index df6a43c..b92a798 100644 --- a/dial.go +++ b/dial.go @@ -14,7 +14,9 @@ package net import ( "context" + "errors" "fmt" + "syscall" "time" ) @@ -24,6 +26,9 @@ const ( defaultTCPKeepAlive = 15 * time.Second ) +// mptcpStatus is a tristate for Multipath TCP, see go.dev/issue/56539 +type mptcpStatus uint8 + // A Dialer contains options for connecting to an address. // // The zero value for each field is equivalent to dialing @@ -146,6 +151,46 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn return nil, fmt.Errorf("Network %s not supported", network) } +// ListenConfig contains options for listening to an address. +type ListenConfig struct { + // If Control is not nil, it is called after creating the network + // connection but before binding it to the operating system. + // + // Network and address parameters passed to Control method are not + // necessarily the ones passed to Listen. For example, passing "tcp" to + // Listen will cause the Control function to be called with "tcp4" or "tcp6". + Control func(network, address string, c syscall.RawConn) error + + // KeepAlive specifies the keep-alive period for network + // connections accepted by this listener. + // If zero, keep-alives are enabled if supported by the protocol + // and operating system. Network protocols or operating systems + // that do not support keep-alives ignore this field. + // If negative, keep-alives are disabled. + KeepAlive time.Duration + + // If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be + // used, any call to Listen with "tcp(4|6)" as network will use MPTCP if + // supported by the operating system. + mptcpStatus mptcpStatus +} + +// Listen announces on the local network address. +// +// See func Listen for a description of the network and address +// parameters. +func (lc *ListenConfig) Listen(ctx context.Context, network, address string) (Listener, error) { + return nil, errors.New("dial:ListenConfig:Listen not implemented") +} + +// ListenPacket announces on the local network address. +// +// See func ListenPacket for a description of the network and address +// parameters. +func (lc *ListenConfig) ListenPacket(ctx context.Context, network, address string) (PacketConn, error) { + return nil, errors.New("dial:ListenConfig:ListenPacket not implemented") +} + // Listen announces on the local network address. // // See Go "net" package Listen() for more information. diff --git a/interface.go b/interface.go new file mode 100644 index 0000000..a4bfc5f --- /dev/null +++ b/interface.go @@ -0,0 +1,86 @@ +// TINYGO: The following is copied and modified from Go 1.21.4 official implementation. + +// Copyright 2011 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. + +package net + +import ( + "errors" +) + +// BUG(mikio): On JS, methods and functions related to +// Interface are not implemented. + +// BUG(mikio): On AIX, DragonFly BSD, NetBSD, OpenBSD, Plan 9 and +// Solaris, the MulticastAddrs method of Interface is not implemented. + +var ( + errInvalidInterface = errors.New("invalid network interface") + errInvalidInterfaceIndex = errors.New("invalid network interface index") + errInvalidInterfaceName = errors.New("invalid network interface name") + errNoSuchInterface = errors.New("no such network interface") + errNoSuchMulticastInterface = errors.New("no such multicast network interface") +) + +// Interface represents a mapping between network interface name +// and index. It also represents network interface facility +// information. +type Interface struct { + Index int // positive integer that starts at one, zero is never used + MTU int // maximum transmission unit + Name string // e.g., "en0", "lo0", "eth0.100" + HardwareAddr HardwareAddr // IEEE MAC-48, EUI-48 and EUI-64 form + Flags Flags // e.g., FlagUp, FlagLoopback, FlagMulticast +} + +type Flags uint + +const ( + FlagUp Flags = 1 << iota // interface is administratively up + FlagBroadcast // interface supports broadcast access capability + FlagLoopback // interface is a loopback interface + FlagPointToPoint // interface belongs to a point-to-point link + FlagMulticast // interface supports multicast access capability + FlagRunning // interface is in running state +) + +var flagNames = []string{ + "up", + "broadcast", + "loopback", + "pointtopoint", + "multicast", + "running", +} + +func (f Flags) String() string { + s := "" + for i, name := range flagNames { + if f&(1< 0 bytes returned before considering the error err. + // ReadFrom can be made to time out and return an error after a + // fixed time limit; see SetDeadline and SetReadDeadline. + ReadFrom(p []byte) (n int, addr Addr, err error) + + // WriteTo writes a packet with payload p to addr. + // WriteTo can be made to time out and return an Error after a + // fixed time limit; see SetDeadline and SetWriteDeadline. + // On packet-oriented connections, write timeouts are rare. + WriteTo(p []byte, addr Addr) (n int, err error) + + // Close closes the connection. + // Any blocked ReadFrom or WriteTo operations will be unblocked and return errors. + Close() error + + // LocalAddr returns the local network address, if known. + LocalAddr() Addr + + // SetDeadline sets the read and write deadlines associated + // with the connection. It is equivalent to calling both + // SetReadDeadline and SetWriteDeadline. + // + // A deadline is an absolute time after which I/O operations + // fail instead of blocking. The deadline applies to all future + // and pending I/O, not just the immediately following call to + // Read or Write. After a deadline has been exceeded, the + // connection can be refreshed by setting a deadline in the future. + // + // If the deadline is exceeded a call to Read or Write or to other + // I/O methods will return an error that wraps os.ErrDeadlineExceeded. + // This can be tested using errors.Is(err, os.ErrDeadlineExceeded). + // The error's Timeout method will return true, but note that there + // are other possible errors for which the Timeout method will + // return true even if the deadline has not been exceeded. + // + // An idle timeout can be implemented by repeatedly extending + // the deadline after successful ReadFrom or WriteTo calls. + // + // A zero value for t means I/O operations will not time out. + SetDeadline(t time.Time) error + + // SetReadDeadline sets the deadline for future ReadFrom calls + // and any currently-blocked ReadFrom call. + // A zero value for t means ReadFrom will not time out. + SetReadDeadline(t time.Time) error + + // SetWriteDeadline sets the deadline for future WriteTo calls + // and any currently-blocked WriteTo call. + // Even if write times out, it may return n > 0, indicating that + // some of the data was successfully written. + // A zero value for t means WriteTo will not time out. + SetWriteDeadline(t time.Time) error +} + // A Listener is a generic network listener for stream-oriented protocols. // // Multiple goroutines may invoke methods on a Listener simultaneously. diff --git a/netdev.go b/netdev.go index c6bfb71..cdd8694 100644 --- a/netdev.go +++ b/netdev.go @@ -13,6 +13,7 @@ const ( _SOCK_DGRAM = 0x2 _SOL_SOCKET = 0x1 _SO_KEEPALIVE = 0x9 + _SO_LINGER = 0xd _SOL_TCP = 0x6 _TCP_KEEPINTVL = 0x5 _IPPROTO_TCP = 0x6 diff --git a/tcpsock.go b/tcpsock.go index be50a7a..5acc2b8 100644 --- a/tcpsock.go +++ b/tcpsock.go @@ -13,6 +13,7 @@ import ( "io" "net/netip" "strconv" + "syscall" "time" ) @@ -178,6 +179,12 @@ func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error) { // TINYGO: Use netdev for Conn methods: Read = Recv, Write = Send, etc. +// SyscallConn returns a raw network connection. +// This implements the syscall.Conn interface. +func (c *TCPConn) SyscallConn() (syscall.RawConn, error) { + return nil, errors.New("SyscallConn not implemented") +} + func (c *TCPConn) Read(b []byte) (int, error) { n, err := netdev.Recv(c.fd, b, 0, c.readDeadline) // Turn the -1 socket error into 0 and let err speak for error @@ -220,10 +227,31 @@ func (c *TCPConn) SetDeadline(t time.Time) error { return nil } +// SetLinger sets the behavior of Close on a connection which still +// has data waiting to be sent or to be acknowledged. +// +// If sec < 0 (the default), the operating system finishes sending the +// data in the background. +// +// If sec == 0, the operating system discards any unsent or +// unacknowledged data. +// +// If sec > 0, the data is sent in the background as with sec < 0. +// On some operating systems including Linux, this may cause Close to block +// until all data has been sent or discarded. +// On some operating systems after sec seconds have elapsed any remaining +// unsent data may be discarded. +func (c *TCPConn) SetLinger(sec int) error { + return netdev.SetSockOpt(c.fd, _SOL_SOCKET, _SO_LINGER, sec) +} + +// SetKeepAlive sets whether the operating system should send +// keep-alive messages on the connection. func (c *TCPConn) SetKeepAlive(keepalive bool) error { return netdev.SetSockOpt(c.fd, _SOL_SOCKET, _SO_KEEPALIVE, keepalive) } +// SetKeepAlivePeriod sets period between keep-alives. func (c *TCPConn) SetKeepAlivePeriod(d time.Duration) error { // Units are 1/2 seconds return netdev.SetSockOpt(c.fd, _SOL_TCP, _TCP_KEEPINTVL, 2*d.Seconds()) diff --git a/udpsock.go b/udpsock.go index 271a68d..a2f9b1a 100644 --- a/udpsock.go +++ b/udpsock.go @@ -7,11 +7,13 @@ package net import ( + "errors" "fmt" "internal/itoa" "io" "net/netip" "strconv" + "syscall" "time" ) @@ -198,6 +200,12 @@ func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) { }, nil } +// SyscallConn returns a raw network connection. +// This implements the syscall.Conn interface. +func (c *UDPConn) SyscallConn() (syscall.RawConn, error) { + return nil, errors.New("SyscallConn not implemented") +} + // TINYGO: Use netdev for Conn methods: Read = Recv, Write = Send, etc. func (c *UDPConn) Read(b []byte) (int, error) { @@ -224,6 +232,40 @@ func (c *UDPConn) Write(b []byte) (int, error) { return n, err } +// ReadFrom implements the PacketConn ReadFrom method. +func (c *UDPConn) ReadFrom(b []byte) (int, Addr, error) { + return 0, nil, errors.New("ReadFrom not implemented") +} + +// ReadMsgUDP reads a message from c, copying the payload into b and +// the associated out-of-band data into oob. It returns the number of +// bytes copied into b, the number of bytes copied into oob, the flags +// that were set on the message and the source address of the message. +// +// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be +// used to manipulate IP-level socket options in oob. +func (c *UDPConn) ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { + err = errors.New("ReadMsgUDP not implemented") + return +} + +// WriteTo implements the PacketConn WriteTo method. +func (c *UDPConn) WriteTo(b []byte, addr Addr) (int, error) { + return 0, errors.New("WriteTo not implemented") +} + +// WriteMsgUDP writes a message to addr via c if c isn't connected, or +// to c's remote address if c is connected (in which case addr must be +// nil). The payload is copied from b and the associated out-of-band +// data is copied from oob. It returns the number of payload and +// out-of-band bytes written. +// +// The packages golang.org/x/net/ipv4 and golang.org/x/net/ipv6 can be +// used to manipulate IP-level socket options in oob. +func (c *UDPConn) WriteMsgUDP(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { + return 0, 0, errors.New("WriteMsgUDP not implemented") +} + func (c *UDPConn) Close() error { return netdev.Close(c.fd) } diff --git a/unixsock.go b/unixsock.go new file mode 100644 index 0000000..849789b --- /dev/null +++ b/unixsock.go @@ -0,0 +1,43 @@ +// TINYGO: The following is copied and modified from Go 1.21.4 official implementation. + +// Copyright 2009 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. + +package net + +// BUG(mikio): On JS, WASIP1 and Plan 9, methods and functions related +// to UnixConn and UnixListener are not implemented. + +// BUG(mikio): On Windows, methods and functions related to UnixConn +// and UnixListener don't work for "unixgram" and "unixpacket". + +// UnixAddr represents the address of a Unix domain socket end point. +type UnixAddr struct { + Name string + Net string +} + +// Network returns the address's network name, "unix", "unixgram" or +// "unixpacket". +func (a *UnixAddr) Network() string { + return a.Net +} + +func (a *UnixAddr) String() string { + if a == nil { + return "" + } + return a.Name +} + +func (a *UnixAddr) isWildcard() bool { + return a == nil || a.Name == "" +} + +func (a *UnixAddr) opAddr() Addr { + if a == nil { + return nil + } + return a +}