diff --git a/.gitmodules b/.gitmodules index 2b492e03db..d3b021fa41 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,3 +35,7 @@ [submodule "lib/renesas-svd"] path = lib/renesas-svd url = https://github.com/tinygo-org/renesas-svd.git +[submodule "src/net"] + path = src/net + url = https://github.com/tinygo-org/net.git + branch = dev diff --git a/loader/goroot.go b/loader/goroot.go index 0da8afa0c7..33e24aaa70 100644 --- a/loader/goroot.go +++ b/loader/goroot.go @@ -232,6 +232,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool { "": true, "crypto/": true, "crypto/rand/": false, + "crypto/tls/": false, "device/": false, "examples/": false, "internal/": true, @@ -241,6 +242,7 @@ func pathsToOverride(goMinor int, needsSyscallPackage bool) map[string]bool { "internal/task/": false, "machine/": false, "net/": true, + "net/http/": false, "os/": true, "reflect/": false, "runtime/": false, diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go new file mode 100644 index 0000000000..f97c47e19c --- /dev/null +++ b/src/crypto/tls/common.go @@ -0,0 +1,12 @@ +// TINYGO: The following is copied and modified from Go 1.19.3 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 tls + +// ConnectionState records basic TLS details about the connection. +type ConnectionState struct { + // TINYGO: empty; TLS connection offloaded to device +} diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go new file mode 100644 index 0000000000..1d1eee105c --- /dev/null +++ b/src/crypto/tls/tls.go @@ -0,0 +1,63 @@ +// TINYGO: The following is copied and modified from Go 1.19.3 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 tls partially implements TLS 1.2, as specified in RFC 5246, +// and TLS 1.3, as specified in RFC 8446. +package tls + +// BUG(agl): The crypto/tls package only implements some countermeasures +// against Lucky13 attacks on CBC-mode encryption, and only on SHA1 +// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and +// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. + +import ( + "fmt" + "net" +) + +// Client returns a new TLS client side connection +// using conn as the underlying transport. +// The config cannot be nil: users must set either ServerName or +// InsecureSkipVerify in the config. +func Client(conn net.Conn, config *Config) *net.TLSConn { + panic("tls.Client() not implemented") + return nil +} + +// DialWithDialer connects to the given network address using dialer.Dial and +// then initiates a TLS handshake, returning the resulting TLS connection. Any +// timeout or deadline given in the dialer apply to connection and TLS +// handshake as a whole. +// +// DialWithDialer interprets a nil configuration as equivalent to the zero +// configuration; see the documentation of Config for the defaults. +// +// DialWithDialer uses context.Background internally; to specify the context, +// use Dialer.DialContext with NetDialer set to the desired dialer. +func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*net.TLSConn, error) { + switch network { + case "tcp", "tcp4": + default: + return nil, fmt.Errorf("Network %s not supported", network) + } + + return net.DialTLS(addr) +} + +// Dial connects to the given network address using net.Dial +// and then initiates a TLS handshake, returning the resulting +// TLS connection. +// Dial interprets a nil configuration as equivalent to +// the zero configuration; see the documentation of Config +// for the defaults. +func Dial(network, addr string, config *Config) (*net.TLSConn, error) { + return DialWithDialer(new(net.Dialer), network, addr, config) +} + +// Config is a placeholder for future compatibility with +// tls.Config. +type Config struct { +} diff --git a/src/net b/src/net new file mode 160000 index 0000000000..d6e5efd40a --- /dev/null +++ b/src/net @@ -0,0 +1 @@ +Subproject commit d6e5efd40a019c18bb78ef1ed7b5ffad5d32e990 diff --git a/src/net/conn_test.go b/src/net/conn_test.go deleted file mode 100644 index 4e1ac28c43..0000000000 --- a/src/net/conn_test.go +++ /dev/null @@ -1,478 +0,0 @@ -// The following is copied from x/net official implementation. -// Source: https://cs.opensource.google/go/x/net/+/f15817d1:nettest/conntest.go -// Changes from original the file: -// - Some variables are pulled in from nettest/nettest.go file. -// - The implementation of checkForTimeoutError() function is changed in -// accordance with error returned by the Pipe implementation. - -// 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. - -package net - -import ( - "bytes" - "encoding/binary" - "io" - "io/ioutil" - "math/rand" - "os" - "runtime" - "sync" - "testing" - "time" -) - -// The following variables are copied from nettest/nettest.go file -var ( - aLongTimeAgo = time.Unix(233431200, 0) - neverTimeout = time.Time{} -) - -// MakePipe creates a connection between two endpoints and returns the pair -// as c1 and c2, such that anything written to c1 is read by c2 and vice-versa. -// The stop function closes all resources, including c1, c2, and the underlying -// Listener (if there is one), and should not be nil. -type MakePipe func() (c1, c2 Conn, stop func(), err error) - -// testConn tests that a Conn implementation properly satisfies the interface. -// The tests should not produce any false positives, but may experience -// false negatives. Thus, some issues may only be detected when the test is -// run multiple times. For maximal effectiveness, run the tests under the -// race detector. -func testConn(t *testing.T, mp MakePipe) { - t.Run("BasicIO", func(t *testing.T) { timeoutWrapper(t, mp, testBasicIO) }) - t.Run("PingPong", func(t *testing.T) { timeoutWrapper(t, mp, testPingPong) }) - t.Run("RacyRead", func(t *testing.T) { timeoutWrapper(t, mp, testRacyRead) }) - t.Run("RacyWrite", func(t *testing.T) { timeoutWrapper(t, mp, testRacyWrite) }) - t.Run("ReadTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testReadTimeout) }) - t.Run("WriteTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testWriteTimeout) }) - t.Run("PastTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPastTimeout) }) - t.Run("PresentTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPresentTimeout) }) - t.Run("FutureTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testFutureTimeout) }) - t.Run("CloseTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testCloseTimeout) }) - t.Run("ConcurrentMethods", func(t *testing.T) { timeoutWrapper(t, mp, testConcurrentMethods) }) -} - -type connTester func(t *testing.T, c1, c2 Conn) - -func timeoutWrapper(t *testing.T, mp MakePipe, f connTester) { - t.Helper() - c1, c2, stop, err := mp() - if err != nil { - t.Fatalf("unable to make pipe: %v", err) - } - var once sync.Once - defer once.Do(func() { stop() }) - timer := time.AfterFunc(time.Minute, func() { - once.Do(func() { - t.Error("test timed out; terminating pipe") - stop() - }) - }) - defer timer.Stop() - f(t, c1, c2) -} - -// testBasicIO tests that the data sent on c1 is properly received on c2. -func testBasicIO(t *testing.T, c1, c2 Conn) { - want := make([]byte, 1<<20) - rand.New(rand.NewSource(0)).Read(want) - - dataCh := make(chan []byte) - go func() { - rd := bytes.NewReader(want) - if err := chunkedCopy(c1, rd); err != nil { - t.Errorf("unexpected c1.Write error: %v", err) - } - if err := c1.Close(); err != nil { - t.Errorf("unexpected c1.Close error: %v", err) - } - }() - - go func() { - wr := new(bytes.Buffer) - if err := chunkedCopy(wr, c2); err != nil { - t.Errorf("unexpected c2.Read error: %v", err) - } - if err := c2.Close(); err != nil { - t.Errorf("unexpected c2.Close error: %v", err) - } - dataCh <- wr.Bytes() - }() - - if got := <-dataCh; !bytes.Equal(got, want) { - t.Error("transmitted data differs") - } -} - -// testPingPong tests that the two endpoints can synchronously send data to -// each other in a typical request-response pattern. -func testPingPong(t *testing.T, c1, c2 Conn) { - var wg sync.WaitGroup - defer wg.Wait() - - pingPonger := func(c Conn) { - defer wg.Done() - buf := make([]byte, 8) - var prev uint64 - for { - if _, err := io.ReadFull(c, buf); err != nil { - if err == io.EOF { - break - } - t.Errorf("unexpected Read error: %v", err) - } - - v := binary.LittleEndian.Uint64(buf) - binary.LittleEndian.PutUint64(buf, v+1) - if prev != 0 && prev+2 != v { - t.Errorf("mismatching value: got %d, want %d", v, prev+2) - } - prev = v - if v == 1000 { - break - } - - if _, err := c.Write(buf); err != nil { - t.Errorf("unexpected Write error: %v", err) - break - } - } - if err := c.Close(); err != nil { - t.Errorf("unexpected Close error: %v", err) - } - } - - wg.Add(2) - go pingPonger(c1) - go pingPonger(c2) - - // Start off the chain reaction. - if _, err := c1.Write(make([]byte, 8)); err != nil { - t.Errorf("unexpected c1.Write error: %v", err) - } -} - -// testRacyRead tests that it is safe to mutate the input Read buffer -// immediately after cancelation has occurred. -func testRacyRead(t *testing.T, c1, c2 Conn) { - go chunkedCopy(c2, rand.New(rand.NewSource(0))) - - var wg sync.WaitGroup - defer wg.Wait() - - c1.SetReadDeadline(time.Now().Add(time.Millisecond)) - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() - - b1 := make([]byte, 1024) - b2 := make([]byte, 1024) - for j := 0; j < 100; j++ { - _, err := c1.Read(b1) - copy(b1, b2) // Mutate b1 to trigger potential race - if err != nil { - checkForTimeoutError(t, err) - c1.SetReadDeadline(time.Now().Add(time.Millisecond)) - } - } - }() - } -} - -// testRacyWrite tests that it is safe to mutate the input Write buffer -// immediately after cancelation has occurred. -func testRacyWrite(t *testing.T, c1, c2 Conn) { - go chunkedCopy(ioutil.Discard, c2) - - var wg sync.WaitGroup - defer wg.Wait() - - c1.SetWriteDeadline(time.Now().Add(time.Millisecond)) - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() - - b1 := make([]byte, 1024) - b2 := make([]byte, 1024) - for j := 0; j < 100; j++ { - _, err := c1.Write(b1) - copy(b1, b2) // Mutate b1 to trigger potential race - if err != nil { - checkForTimeoutError(t, err) - c1.SetWriteDeadline(time.Now().Add(time.Millisecond)) - } - } - }() - } -} - -// testReadTimeout tests that Read timeouts do not affect Write. -func testReadTimeout(t *testing.T, c1, c2 Conn) { - go chunkedCopy(ioutil.Discard, c2) - - c1.SetReadDeadline(aLongTimeAgo) - _, err := c1.Read(make([]byte, 1024)) - checkForTimeoutError(t, err) - if _, err := c1.Write(make([]byte, 1024)); err != nil { - t.Errorf("unexpected Write error: %v", err) - } -} - -// testWriteTimeout tests that Write timeouts do not affect Read. -func testWriteTimeout(t *testing.T, c1, c2 Conn) { - go chunkedCopy(c2, rand.New(rand.NewSource(0))) - - c1.SetWriteDeadline(aLongTimeAgo) - _, err := c1.Write(make([]byte, 1024)) - checkForTimeoutError(t, err) - if _, err := c1.Read(make([]byte, 1024)); err != nil { - t.Errorf("unexpected Read error: %v", err) - } -} - -// testPastTimeout tests that a deadline set in the past immediately times out -// Read and Write requests. -func testPastTimeout(t *testing.T, c1, c2 Conn) { - go chunkedCopy(c2, c2) - - testRoundtrip(t, c1) - - c1.SetDeadline(aLongTimeAgo) - n, err := c1.Write(make([]byte, 1024)) - if n != 0 { - t.Errorf("unexpected Write count: got %d, want 0", n) - } - checkForTimeoutError(t, err) - n, err = c1.Read(make([]byte, 1024)) - if n != 0 { - t.Errorf("unexpected Read count: got %d, want 0", n) - } - checkForTimeoutError(t, err) - - testRoundtrip(t, c1) -} - -// testPresentTimeout tests that a past deadline set while there are pending -// Read and Write operations immediately times out those operations. -func testPresentTimeout(t *testing.T, c1, c2 Conn) { - var wg sync.WaitGroup - defer wg.Wait() - wg.Add(3) - - deadlineSet := make(chan bool, 1) - go func() { - defer wg.Done() - time.Sleep(100 * time.Millisecond) - deadlineSet <- true - c1.SetReadDeadline(aLongTimeAgo) - c1.SetWriteDeadline(aLongTimeAgo) - }() - go func() { - defer wg.Done() - n, err := c1.Read(make([]byte, 1024)) - if n != 0 { - t.Errorf("unexpected Read count: got %d, want 0", n) - } - checkForTimeoutError(t, err) - if len(deadlineSet) == 0 { - t.Error("Read timed out before deadline is set") - } - }() - go func() { - defer wg.Done() - var err error - for err == nil { - _, err = c1.Write(make([]byte, 1024)) - } - checkForTimeoutError(t, err) - if len(deadlineSet) == 0 { - t.Error("Write timed out before deadline is set") - } - }() -} - -// testFutureTimeout tests that a future deadline will eventually time out -// Read and Write operations. -func testFutureTimeout(t *testing.T, c1, c2 Conn) { - var wg sync.WaitGroup - wg.Add(2) - - c1.SetDeadline(time.Now().Add(100 * time.Millisecond)) - go func() { - defer wg.Done() - _, err := c1.Read(make([]byte, 1024)) - checkForTimeoutError(t, err) - }() - go func() { - defer wg.Done() - var err error - for err == nil { - _, err = c1.Write(make([]byte, 1024)) - } - checkForTimeoutError(t, err) - }() - wg.Wait() - - go chunkedCopy(c2, c2) - resyncConn(t, c1) - testRoundtrip(t, c1) -} - -// testCloseTimeout tests that calling Close immediately times out pending -// Read and Write operations. -func testCloseTimeout(t *testing.T, c1, c2 Conn) { - go chunkedCopy(c2, c2) - - var wg sync.WaitGroup - defer wg.Wait() - wg.Add(3) - - // Test for cancelation upon connection closure. - c1.SetDeadline(neverTimeout) - go func() { - defer wg.Done() - time.Sleep(100 * time.Millisecond) - c1.Close() - }() - go func() { - defer wg.Done() - var err error - buf := make([]byte, 1024) - for err == nil { - _, err = c1.Read(buf) - } - }() - go func() { - defer wg.Done() - var err error - buf := make([]byte, 1024) - for err == nil { - _, err = c1.Write(buf) - } - }() -} - -// testConcurrentMethods tests that the methods of Conn can safely -// be called concurrently. -func testConcurrentMethods(t *testing.T, c1, c2 Conn) { - if runtime.GOOS == "plan9" { - t.Skip("skipping on plan9; see https://golang.org/issue/20489") - } - go chunkedCopy(c2, c2) - - // The results of the calls may be nonsensical, but this should - // not trigger a race detector warning. - var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(7) - go func() { - defer wg.Done() - c1.Read(make([]byte, 1024)) - }() - go func() { - defer wg.Done() - c1.Write(make([]byte, 1024)) - }() - go func() { - defer wg.Done() - c1.SetDeadline(time.Now().Add(10 * time.Millisecond)) - }() - go func() { - defer wg.Done() - c1.SetReadDeadline(aLongTimeAgo) - }() - go func() { - defer wg.Done() - c1.SetWriteDeadline(aLongTimeAgo) - }() - go func() { - defer wg.Done() - c1.LocalAddr() - }() - go func() { - defer wg.Done() - c1.RemoteAddr() - }() - } - wg.Wait() // At worst, the deadline is set 10ms into the future - - resyncConn(t, c1) - testRoundtrip(t, c1) -} - -// checkForTimeoutError checks that the error satisfies the OpError interface -// and that underlying Err is os.ErrDeadlineExceeded -func checkForTimeoutError(t *testing.T, err error) { - t.Helper() - operr, ok := err.(*OpError) - if !ok { - t.Errorf("got %T: %v, want OpError", err, err) - return - } - if operr.Err != os.ErrDeadlineExceeded { - t.Errorf("got %T: %v, want os.ErrDeadlineExceeded", err, err) - } -} - -// testRoundtrip writes something into c and reads it back. -// It assumes that everything written into c is echoed back to itself. -func testRoundtrip(t *testing.T, c Conn) { - t.Helper() - if err := c.SetDeadline(neverTimeout); err != nil { - t.Errorf("roundtrip SetDeadline error: %v", err) - } - - const s = "Hello, world!" - buf := []byte(s) - if _, err := c.Write(buf); err != nil { - t.Errorf("roundtrip Write error: %v", err) - } - if _, err := io.ReadFull(c, buf); err != nil { - t.Errorf("roundtrip Read error: %v", err) - } - if string(buf) != s { - t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s) - } -} - -// resyncConn resynchronizes the connection into a sane state. -// It assumes that everything written into c is echoed back to itself. -// It assumes that 0xff is not currently on the wire or in the read buffer. -func resyncConn(t *testing.T, c Conn) { - t.Helper() - c.SetDeadline(neverTimeout) - errCh := make(chan error) - go func() { - _, err := c.Write([]byte{0xff}) - errCh <- err - }() - buf := make([]byte, 1024) - for { - n, err := c.Read(buf) - if n > 0 && bytes.IndexByte(buf[:n], 0xff) == n-1 { - break - } - if err != nil { - t.Errorf("unexpected Read error: %v", err) - break - } - } - if err := <-errCh; err != nil { - t.Errorf("unexpected Write error: %v", err) - } -} - -// chunkedCopy copies from r to w in fixed-width chunks to avoid -// causing a Write that exceeds the maximum packet size for packet-based -// connections like "unixpacket". -// We assume that the maximum packet size is at least 1024. -func chunkedCopy(w io.Writer, r io.Reader) error { - b := make([]byte, 1024) - _, err := io.CopyBuffer(struct{ io.Writer }{w}, struct{ io.Reader }{r}, b) - return err -} diff --git a/src/net/dial.go b/src/net/dial.go deleted file mode 100644 index a1cb75d87f..0000000000 --- a/src/net/dial.go +++ /dev/null @@ -1,25 +0,0 @@ -package net - -import ( - "context" - "time" -) - -type Dialer struct { - Timeout time.Duration - Deadline time.Time - DualStack bool - KeepAlive time.Duration -} - -func Dial(network, address string) (Conn, error) { - return nil, ErrNotImplemented -} - -func Listen(network, address string) (Listener, error) { - return nil, ErrNotImplemented -} - -func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) { - return nil, ErrNotImplemented -} diff --git a/src/net/errors.go b/src/net/errors.go deleted file mode 100644 index c1dc7b31c8..0000000000 --- a/src/net/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package net - -import "errors" - -var ( - // copied from poll.ErrNetClosing - errClosed = errors.New("use of closed network connection") - - ErrNotImplemented = errors.New("operation not implemented") -) diff --git a/src/net/interface.go b/src/net/interface.go deleted file mode 100644 index 32206f78fc..0000000000 --- a/src/net/interface.go +++ /dev/null @@ -1,253 +0,0 @@ -// The following is copied from Go 1.16 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" - "internal/itoa" - "sync" - "time" -) - -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 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 -) - -var flagNames = []string{ - "up", - "broadcast", - "loopback", - "pointtopoint", - "multicast", -} - -func (f Flags) String() string { - s := "" - for i, name := range flagNames { - if f&(1< bits { - return nil - } - l := bits / 8 - m := make(IPMask, l) - n := uint(ones) - for i := 0; i < l; i++ { - if n >= 8 { - m[i] = 0xff - n -= 8 - continue - } - m[i] = ^byte(0xff >> n) - n = 0 - } - return m -} - -// Well-known IPv4 addresses -var ( - IPv4bcast = IPv4(255, 255, 255, 255) // limited broadcast - IPv4allsys = IPv4(224, 0, 0, 1) // all systems - IPv4allrouter = IPv4(224, 0, 0, 2) // all routers - IPv4zero = IPv4(0, 0, 0, 0) // all zeros -) - -// Well-known IPv6 addresses -var ( - IPv6zero = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - IPv6unspecified = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - IPv6loopback = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} - IPv6interfacelocalallnodes = IP{0xff, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01} - IPv6linklocalallnodes = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01} - IPv6linklocalallrouters = IP{0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02} -) - -// IsUnspecified reports whether ip is an unspecified address, either -// the IPv4 address "0.0.0.0" or the IPv6 address "::". -func (ip IP) IsUnspecified() bool { - return ip.Equal(IPv4zero) || ip.Equal(IPv6unspecified) -} - -// IsLoopback reports whether ip is a loopback address. -func (ip IP) IsLoopback() bool { - if ip4 := ip.To4(); ip4 != nil { - return ip4[0] == 127 - } - return ip.Equal(IPv6loopback) -} - -// IsMulticast reports whether ip is a multicast address. -func (ip IP) IsMulticast() bool { - if ip4 := ip.To4(); ip4 != nil { - return ip4[0]&0xf0 == 0xe0 - } - return len(ip) == IPv6len && ip[0] == 0xff -} - -// IsInterfaceLocalMulticast reports whether ip is -// an interface-local multicast address. -func (ip IP) IsInterfaceLocalMulticast() bool { - return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x01 -} - -// IsLinkLocalMulticast reports whether ip is a link-local -// multicast address. -func (ip IP) IsLinkLocalMulticast() bool { - if ip4 := ip.To4(); ip4 != nil { - return ip4[0] == 224 && ip4[1] == 0 && ip4[2] == 0 - } - return len(ip) == IPv6len && ip[0] == 0xff && ip[1]&0x0f == 0x02 -} - -// IsLinkLocalUnicast reports whether ip is a link-local -// unicast address. -func (ip IP) IsLinkLocalUnicast() bool { - if ip4 := ip.To4(); ip4 != nil { - return ip4[0] == 169 && ip4[1] == 254 - } - return len(ip) == IPv6len && ip[0] == 0xfe && ip[1]&0xc0 == 0x80 -} - -// IsGlobalUnicast reports whether ip is a global unicast -// address. -// -// The identification of global unicast addresses uses address type -// identification as defined in RFC 1122, RFC 4632 and RFC 4291 with -// the exception of IPv4 directed broadcast addresses. -// It returns true even if ip is in IPv4 private address space or -// local IPv6 unicast address space. -func (ip IP) IsGlobalUnicast() bool { - return (len(ip) == IPv4len || len(ip) == IPv6len) && - !ip.Equal(IPv4bcast) && - !ip.IsUnspecified() && - !ip.IsLoopback() && - !ip.IsMulticast() && - !ip.IsLinkLocalUnicast() -} - -// Is p all zeros? -func isZeros(p IP) bool { - for i := 0; i < len(p); i++ { - if p[i] != 0 { - return false - } - } - return true -} - -// To4 converts the IPv4 address ip to a 4-byte representation. -// If ip is not an IPv4 address, To4 returns nil. -func (ip IP) To4() IP { - if len(ip) == IPv4len { - return ip - } - if len(ip) == IPv6len && - isZeros(ip[0:10]) && - ip[10] == 0xff && - ip[11] == 0xff { - return ip[12:16] - } - return nil -} - -// To16 converts the IP address ip to a 16-byte representation. -// If ip is not an IP address (it is the wrong length), To16 returns nil. -func (ip IP) To16() IP { - if len(ip) == IPv4len { - return IPv4(ip[0], ip[1], ip[2], ip[3]) - } - if len(ip) == IPv6len { - return ip - } - return nil -} - -// Default route masks for IPv4. -var ( - classAMask = IPv4Mask(0xff, 0, 0, 0) - classBMask = IPv4Mask(0xff, 0xff, 0, 0) - classCMask = IPv4Mask(0xff, 0xff, 0xff, 0) -) - -// DefaultMask returns the default IP mask for the IP address ip. -// Only IPv4 addresses have default masks; DefaultMask returns -// nil if ip is not a valid IPv4 address. -func (ip IP) DefaultMask() IPMask { - if ip = ip.To4(); ip == nil { - return nil - } - switch { - case ip[0] < 0x80: - return classAMask - case ip[0] < 0xC0: - return classBMask - default: - return classCMask - } -} - -func allFF(b []byte) bool { - for _, c := range b { - if c != 0xff { - return false - } - } - return true -} - -// Mask returns the result of masking the IP address ip with mask. -func (ip IP) Mask(mask IPMask) IP { - if len(mask) == IPv6len && len(ip) == IPv4len && allFF(mask[:12]) { - mask = mask[12:] - } - if len(mask) == IPv4len && len(ip) == IPv6len && bytealg.Equal(ip[:12], v4InV6Prefix) { - ip = ip[12:] - } - n := len(ip) - if n != len(mask) { - return nil - } - out := make(IP, n) - for i := 0; i < n; i++ { - out[i] = ip[i] & mask[i] - } - return out -} - -// ubtoa encodes the string form of the integer v to dst[start:] and -// returns the number of bytes written to dst. The caller must ensure -// that dst has sufficient length. -func ubtoa(dst []byte, start int, v byte) int { - if v < 10 { - dst[start] = v + '0' - return 1 - } else if v < 100 { - dst[start+1] = v%10 + '0' - dst[start] = v/10 + '0' - return 2 - } - - dst[start+2] = v%10 + '0' - dst[start+1] = (v/10)%10 + '0' - dst[start] = v/100 + '0' - return 3 -} - -// String returns the string form of the IP address ip. -// It returns one of 4 forms: -// - "", if ip has length 0 -// - dotted decimal ("192.0.2.1"), if ip is an IPv4 or IP4-mapped IPv6 address -// - IPv6 ("2001:db8::1"), if ip is a valid IPv6 address -// - the hexadecimal form of ip, without punctuation, if no other cases apply -func (ip IP) String() string { - p := ip - - if len(ip) == 0 { - return "" - } - - // If IPv4, use dotted notation. - if p4 := p.To4(); len(p4) == IPv4len { - const maxIPv4StringLen = len("255.255.255.255") - b := make([]byte, maxIPv4StringLen) - - n := ubtoa(b, 0, p4[0]) - b[n] = '.' - n++ - - n += ubtoa(b, n, p4[1]) - b[n] = '.' - n++ - - n += ubtoa(b, n, p4[2]) - b[n] = '.' - n++ - - n += ubtoa(b, n, p4[3]) - return string(b[:n]) - } - if len(p) != IPv6len { - return "?" + hexString(ip) - } - - // Find longest run of zeros. - e0 := -1 - e1 := -1 - for i := 0; i < IPv6len; i += 2 { - j := i - for j < IPv6len && p[j] == 0 && p[j+1] == 0 { - j += 2 - } - if j > i && j-i > e1-e0 { - e0 = i - e1 = j - i = j - } - } - // The symbol "::" MUST NOT be used to shorten just one 16 bit 0 field. - if e1-e0 <= 2 { - e0 = -1 - e1 = -1 - } - - const maxLen = len("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") - b := make([]byte, 0, maxLen) - - // Print with possible :: in place of run of zeros - for i := 0; i < IPv6len; i += 2 { - if i == e0 { - b = append(b, ':', ':') - i = e1 - if i >= IPv6len { - break - } - } else if i > 0 { - b = append(b, ':') - } - b = appendHex(b, (uint32(p[i])<<8)|uint32(p[i+1])) - } - return string(b) -} - -func hexString(b []byte) string { - s := make([]byte, len(b)*2) - for i, tn := range b { - s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf] - } - return string(s) -} - -// ipEmptyString is like ip.String except that it returns -// an empty string when ip is unset. -func ipEmptyString(ip IP) string { - if len(ip) == 0 { - return "" - } - return ip.String() -} - -// MarshalText implements the encoding.TextMarshaler interface. -// The encoding is the same as returned by String, with one exception: -// When len(ip) is zero, it returns an empty slice. -func (ip IP) MarshalText() ([]byte, error) { - if len(ip) == 0 { - return []byte(""), nil - } - if len(ip) != IPv4len && len(ip) != IPv6len { - return nil, &AddrError{Err: "invalid IP address", Addr: hexString(ip)} - } - return []byte(ip.String()), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// The IP address is expected in a form accepted by ParseIP. -func (ip *IP) UnmarshalText(text []byte) error { - if len(text) == 0 { - *ip = nil - return nil - } - s := string(text) - x := ParseIP(s) - if x == nil { - return &ParseError{Type: "IP address", Text: s} - } - *ip = x - return nil -} - -// Equal reports whether ip and x are the same IP address. -// An IPv4 address and that same address in IPv6 form are -// considered to be equal. -func (ip IP) Equal(x IP) bool { - if len(ip) == len(x) { - return bytealg.Equal(ip, x) - } - if len(ip) == IPv4len && len(x) == IPv6len { - return bytealg.Equal(x[0:12], v4InV6Prefix) && bytealg.Equal(ip, x[12:]) - } - if len(ip) == IPv6len && len(x) == IPv4len { - return bytealg.Equal(ip[0:12], v4InV6Prefix) && bytealg.Equal(ip[12:], x) - } - return false -} - -func (ip IP) matchAddrFamily(x IP) bool { - return ip.To4() != nil && x.To4() != nil || ip.To16() != nil && ip.To4() == nil && x.To16() != nil && x.To4() == nil -} - -// If mask is a sequence of 1 bits followed by 0 bits, -// return the number of 1 bits. -func simpleMaskLength(mask IPMask) int { - var n int - for i, v := range mask { - if v == 0xff { - n += 8 - continue - } - // found non-ff byte - // count 1 bits - for v&0x80 != 0 { - n++ - v <<= 1 - } - // rest must be 0 bits - if v != 0 { - return -1 - } - for i++; i < len(mask); i++ { - if mask[i] != 0 { - return -1 - } - } - break - } - return n -} - -// Size returns the number of leading ones and total bits in the mask. -// If the mask is not in the canonical form--ones followed by zeros--then -// Size returns 0, 0. -func (m IPMask) Size() (ones, bits int) { - ones, bits = simpleMaskLength(m), len(m)*8 - if ones == -1 { - return 0, 0 - } - return -} - -// String returns the hexadecimal form of m, with no punctuation. -func (m IPMask) String() string { - if len(m) == 0 { - return "" - } - return hexString(m) -} - -func networkNumberAndMask(n *IPNet) (ip IP, m IPMask) { - if ip = n.IP.To4(); ip == nil { - ip = n.IP - if len(ip) != IPv6len { - return nil, nil - } - } - m = n.Mask - switch len(m) { - case IPv4len: - if len(ip) != IPv4len { - return nil, nil - } - case IPv6len: - if len(ip) == IPv4len { - m = m[12:] - } - default: - return nil, nil - } - return -} - -// Contains reports whether the network includes ip. -func (n *IPNet) Contains(ip IP) bool { - nn, m := networkNumberAndMask(n) - if x := ip.To4(); x != nil { - ip = x - } - l := len(ip) - if l != len(nn) { - return false - } - for i := 0; i < l; i++ { - if nn[i]&m[i] != ip[i]&m[i] { - return false - } - } - return true -} - -// Network returns the address's network name, "ip+net". -func (n *IPNet) Network() string { return "ip+net" } - -// String returns the CIDR notation of n like "192.0.2.0/24" -// or "2001:db8::/48" as defined in RFC 4632 and RFC 4291. -// If the mask is not in the canonical form, it returns the -// string which consists of an IP address, followed by a slash -// character and a mask expressed as hexadecimal form with no -// punctuation like "198.51.100.0/c000ff00". -func (n *IPNet) String() string { - nn, m := networkNumberAndMask(n) - if nn == nil || m == nil { - return "" - } - l := simpleMaskLength(m) - if l == -1 { - return nn.String() + "/" + m.String() - } - return nn.String() + "/" + itoa.Uitoa(uint(l)) -} - -// Parse IPv4 address (d.d.d.d). -func parseIPv4(s string) IP { - var p [IPv4len]byte - for i := 0; i < IPv4len; i++ { - if len(s) == 0 { - // Missing octets. - return nil - } - if i > 0 { - if s[0] != '.' { - return nil - } - s = s[1:] - } - n, c, ok := dtoi(s) - if !ok || n > 0xFF { - return nil - } - s = s[c:] - p[i] = byte(n) - } - if len(s) != 0 { - return nil - } - return IPv4(p[0], p[1], p[2], p[3]) -} - -// parseIPv6Zone parses s as a literal IPv6 address and its associated zone -// identifier which is described in RFC 4007. -func parseIPv6Zone(s string) (IP, string) { - s, zone := splitHostZone(s) - return parseIPv6(s), zone -} - -// parseIPv6 parses s as a literal IPv6 address described in RFC 4291 -// and RFC 5952. -func parseIPv6(s string) (ip IP) { - ip = make(IP, IPv6len) - ellipsis := -1 // position of ellipsis in ip - - // Might have leading ellipsis - if len(s) >= 2 && s[0] == ':' && s[1] == ':' { - ellipsis = 0 - s = s[2:] - // Might be only ellipsis - if len(s) == 0 { - return ip - } - } - - // Loop, parsing hex numbers followed by colon. - i := 0 - for i < IPv6len { - // Hex number. - n, c, ok := xtoi(s) - if !ok || n > 0xFFFF { - return nil - } - - // If followed by dot, might be in trailing IPv4. - if c < len(s) && s[c] == '.' { - if ellipsis < 0 && i != IPv6len-IPv4len { - // Not the right place. - return nil - } - if i+IPv4len > IPv6len { - // Not enough room. - return nil - } - ip4 := parseIPv4(s) - if ip4 == nil { - return nil - } - ip[i] = ip4[12] - ip[i+1] = ip4[13] - ip[i+2] = ip4[14] - ip[i+3] = ip4[15] - s = "" - i += IPv4len - break - } - - // Save this 16-bit chunk. - ip[i] = byte(n >> 8) - ip[i+1] = byte(n) - i += 2 - - // Stop at end of string. - s = s[c:] - if len(s) == 0 { - break - } - - // Otherwise must be followed by colon and more. - if s[0] != ':' || len(s) == 1 { - return nil - } - s = s[1:] - - // Look for ellipsis. - if s[0] == ':' { - if ellipsis >= 0 { // already have one - return nil - } - ellipsis = i - s = s[1:] - if len(s) == 0 { // can be at end - break - } - } - } - - // Must have used entire string. - if len(s) != 0 { - return nil - } - - // If didn't parse enough, expand ellipsis. - if i < IPv6len { - if ellipsis < 0 { - return nil - } - n := IPv6len - i - for j := i - 1; j >= ellipsis; j-- { - ip[j+n] = ip[j] - } - for j := ellipsis + n - 1; j >= ellipsis; j-- { - ip[j] = 0 - } - } else if ellipsis >= 0 { - // Ellipsis must represent at least one 0 group. - return nil - } - return ip -} - -// ParseIP parses s as an IP address, returning the result. -// The string s can be in IPv4 dotted decimal ("192.0.2.1"), IPv6 -// ("2001:db8::68"), or IPv4-mapped IPv6 ("::ffff:192.0.2.1") form. -// If s is not a valid textual representation of an IP address, -// ParseIP returns nil. -func ParseIP(s string) IP { - for i := 0; i < len(s); i++ { - switch s[i] { - case '.': - return parseIPv4(s) - case ':': - return parseIPv6(s) - } - } - return nil -} - -// parseIPZone parses s as an IP address, return it and its associated zone -// identifier (IPv6 only). -func parseIPZone(s string) (IP, string) { - for i := 0; i < len(s); i++ { - switch s[i] { - case '.': - return parseIPv4(s), "" - case ':': - return parseIPv6Zone(s) - } - } - return nil, "" -} - -// ParseCIDR parses s as a CIDR notation IP address and prefix length, -// like "192.0.2.0/24" or "2001:db8::/32", as defined in -// RFC 4632 and RFC 4291. -// -// It returns the IP address and the network implied by the IP and -// prefix length. -// For example, ParseCIDR("192.0.2.1/24") returns the IP address -// 192.0.2.1 and the network 192.0.2.0/24. -func ParseCIDR(s string) (IP, *IPNet, error) { - i := bytealg.IndexByteString(s, '/') - if i < 0 { - return nil, nil, &ParseError{Type: "CIDR address", Text: s} - } - addr, mask := s[:i], s[i+1:] - iplen := IPv4len - ip := parseIPv4(addr) - if ip == nil { - iplen = IPv6len - ip = parseIPv6(addr) - } - n, i, ok := dtoi(mask) - if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen { - return nil, nil, &ParseError{Type: "CIDR address", Text: s} - } - m := CIDRMask(n, 8*iplen) - return ip, &IPNet{IP: ip.Mask(m), Mask: m}, nil -} diff --git a/src/net/iprawsock.go b/src/net/iprawsock.go deleted file mode 100644 index d16d5eac1d..0000000000 --- a/src/net/iprawsock.go +++ /dev/null @@ -1,41 +0,0 @@ -// The following is copied from Go 1.16 official implementation. - -// Copyright 2010 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 - -// IPAddr represents the address of an IP end point. -type IPAddr struct { - IP IP - Zone string // IPv6 scoped addressing zone -} - -// Network returns the address's network name, "ip". -func (a *IPAddr) Network() string { return "ip" } - -func (a *IPAddr) String() string { - if a == nil { - return "" - } - ip := ipEmptyString(a.IP) - if a.Zone != "" { - return ip + "%" + a.Zone - } - return ip -} - -func (a *IPAddr) isWildcard() bool { - if a == nil || a.IP == nil { - return true - } - return a.IP.IsUnspecified() -} - -func (a *IPAddr) opAddr() Addr { - if a == nil { - return nil - } - return a -} diff --git a/src/net/ipsock.go b/src/net/ipsock.go deleted file mode 100644 index 57ceaebf09..0000000000 --- a/src/net/ipsock.go +++ /dev/null @@ -1,98 +0,0 @@ -// The following is copied from Go 1.16 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 - -import "internal/bytealg" - -// SplitHostPort splits a network address of the form "host:port", -// "host%zone:port", "[host]:port" or "[host%zone]:port" into host or -// host%zone and port. -// -// A literal IPv6 address in hostport must be enclosed in square -// brackets, as in "[::1]:80", "[::1%lo0]:80". -// -// See func Dial for a description of the hostport parameter, and host -// and port results. -func SplitHostPort(hostport string) (host, port string, err error) { - const ( - missingPort = "missing port in address" - tooManyColons = "too many colons in address" - ) - addrErr := func(addr, why string) (host, port string, err error) { - return "", "", &AddrError{Err: why, Addr: addr} - } - j, k := 0, 0 - - // The port starts after the last colon. - i := last(hostport, ':') - if i < 0 { - return addrErr(hostport, missingPort) - } - - if hostport[0] == '[' { - // Expect the first ']' just before the last ':'. - end := bytealg.IndexByteString(hostport, ']') - if end < 0 { - return addrErr(hostport, "missing ']' in address") - } - switch end + 1 { - case len(hostport): - // There can't be a ':' behind the ']' now. - return addrErr(hostport, missingPort) - case i: - // The expected result. - default: - // Either ']' isn't followed by a colon, or it is - // followed by a colon that is not the last one. - if hostport[end+1] == ':' { - return addrErr(hostport, tooManyColons) - } - return addrErr(hostport, missingPort) - } - host = hostport[1:end] - j, k = 1, end+1 // there can't be a '[' resp. ']' before these positions - } else { - host = hostport[:i] - if bytealg.IndexByteString(host, ':') >= 0 { - return addrErr(hostport, tooManyColons) - } - } - if bytealg.IndexByteString(hostport[j:], '[') >= 0 { - return addrErr(hostport, "unexpected '[' in address") - } - if bytealg.IndexByteString(hostport[k:], ']') >= 0 { - return addrErr(hostport, "unexpected ']' in address") - } - - port = hostport[i+1:] - return host, port, nil -} - -func splitHostZone(s string) (host, zone string) { - // The IPv6 scoped addressing zone identifier starts after the - // last percent sign. - if i := last(s, '%'); i > 0 { - host, zone = s[:i], s[i+1:] - } else { - host = s - } - return -} - -// JoinHostPort combines host and port into a network address of the -// form "host:port". If host contains a colon, as found in literal -// IPv6 addresses, then JoinHostPort returns "[host]:port". -// -// See func Dial for a description of the host and port parameters. -func JoinHostPort(host, port string) string { - // We assume that host is a literal IPv6 address if host has - // colons. - if bytealg.IndexByteString(host, ':') >= 0 { - return "[" + host + "]:" + port - } - return host + ":" + port -} diff --git a/src/net/mac.go b/src/net/mac.go deleted file mode 100644 index 2bad98c462..0000000000 --- a/src/net/mac.go +++ /dev/null @@ -1,88 +0,0 @@ -// The following is copied from Go 1.16 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 - -const hexDigit = "0123456789abcdef" - -// A HardwareAddr represents a physical hardware address. -type HardwareAddr []byte - -func (a HardwareAddr) String() string { - if len(a) == 0 { - return "" - } - buf := make([]byte, 0, len(a)*3-1) - for i, b := range a { - if i > 0 { - buf = append(buf, ':') - } - buf = append(buf, hexDigit[b>>4]) - buf = append(buf, hexDigit[b&0xF]) - } - return string(buf) -} - -// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet -// IP over InfiniBand link-layer address using one of the following formats: -// -// 00:00:5e:00:53:01 -// 02:00:5e:10:00:00:00:01 -// 00:00:00:00:fe:80:00:00:00:00:00:00:02:00:5e:10:00:00:00:01 -// 00-00-5e-00-53-01 -// 02-00-5e-10-00-00-00-01 -// 00-00-00-00-fe-80-00-00-00-00-00-00-02-00-5e-10-00-00-00-01 -// 0000.5e00.5301 -// 0200.5e10.0000.0001 -// 0000.0000.fe80.0000.0000.0000.0200.5e10.0000.0001 -func ParseMAC(s string) (hw HardwareAddr, err error) { - if len(s) < 14 { - goto err - } - - if s[2] == ':' || s[2] == '-' { - if (len(s)+1)%3 != 0 { - goto err - } - n := (len(s) + 1) / 3 - if n != 6 && n != 8 && n != 20 { - goto err - } - hw = make(HardwareAddr, n) - for x, i := 0, 0; i < n; i++ { - var ok bool - if hw[i], ok = xtoi2(s[x:], s[2]); !ok { - goto err - } - x += 3 - } - } else if s[4] == '.' { - if (len(s)+1)%5 != 0 { - goto err - } - n := 2 * (len(s) + 1) / 5 - if n != 6 && n != 8 && n != 20 { - goto err - } - hw = make(HardwareAddr, n) - for x, i := 0, 0; i < n; i += 2 { - var ok bool - if hw[i], ok = xtoi2(s[x:x+2], 0); !ok { - goto err - } - if hw[i+1], ok = xtoi2(s[x+2:], s[4]); !ok { - goto err - } - x += 5 - } - } else { - goto err - } - return hw, nil - -err: - return nil, &AddrError{Err: "invalid MAC address", Addr: s} -} diff --git a/src/net/net.go b/src/net/net.go deleted file mode 100644 index db4d8f117f..0000000000 --- a/src/net/net.go +++ /dev/null @@ -1,279 +0,0 @@ -// The following is copied from Go 1.18 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 - -import ( - "io" - "time" -) - -// Addr represents a network end point address. -// -// The two methods Network and String conventionally return strings -// that can be passed as the arguments to Dial, but the exact form -// and meaning of the strings is up to the implementation. -type Addr interface { - Network() string // name of the network (for example, "tcp", "udp") - String() string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80") -} - -// Conn is a generic stream-oriented network connection. -// -// Multiple goroutines may invoke methods on a Conn simultaneously. -type Conn interface { - // Read reads data from the connection. - // Read can be made to time out and return an error after a fixed - // time limit; see SetDeadline and SetReadDeadline. - Read(b []byte) (n int, err error) - - // Write writes data to the connection. - // Write can be made to time out and return an error after a fixed - // time limit; see SetDeadline and SetWriteDeadline. - Write(b []byte) (n int, err error) - - // Close closes the connection. - // Any blocked Read or Write operations will be unblocked and return errors. - Close() error - - // LocalAddr returns the local network address, if known. - LocalAddr() Addr - - // RemoteAddr returns the remote network address, if known. - RemoteAddr() 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 Read or Write 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 Read calls - // and any currently-blocked Read call. - // A zero value for t means Read will not time out. - SetReadDeadline(t time.Time) error - - // SetWriteDeadline sets the deadline for future Write calls - // and any currently-blocked Write 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 Write will not time out. - SetWriteDeadline(t time.Time) error -} - -type conn struct { - // -} - -// A Listener is a generic network listener for stream-oriented protocols. -// -// Multiple goroutines may invoke methods on a Listener simultaneously. -type Listener interface { - // Accept waits for and returns the next connection to the listener. - Accept() (Conn, error) - - // Close closes the listener. - // Any blocked Accept operations will be unblocked and return errors. - Close() error - - // Addr returns the listener's network address. - Addr() Addr -} - -// An Error represents a network error. -type Error interface { - error - Timeout() bool // Is the error a timeout? - - // Deprecated: Temporary errors are not well-defined. - // Most "temporary" errors are timeouts, and the few exceptions are surprising. - // Do not use this method. - Temporary() bool -} - -// OpError is the error type usually returned by functions in the net -// package. It describes the operation, network type, and address of -// an error. -type OpError struct { - // Op is the operation which caused the error, such as - // "read" or "write". - Op string - - // Net is the network type on which this error occurred, - // such as "tcp" or "udp6". - Net string - - // For operations involving a remote network connection, like - // Dial, Read, or Write, Source is the corresponding local - // network address. - Source Addr - - // Addr is the network address for which this error occurred. - // For local operations, like Listen or SetDeadline, Addr is - // the address of the local endpoint being manipulated. - // For operations involving a remote network connection, like - // Dial, Read, or Write, Addr is the remote address of that - // connection. - Addr Addr - - // Err is the error that occurred during the operation. - // The Error method panics if the error is nil. - Err error -} - -func (e *OpError) Unwrap() error { return e.Err } - -func (e *OpError) Error() string { - if e == nil { - return "" - } - s := e.Op - if e.Net != "" { - s += " " + e.Net - } - if e.Source != nil { - s += " " + e.Source.String() - } - if e.Addr != nil { - if e.Source != nil { - s += "->" - } else { - s += " " - } - s += e.Addr.String() - } - s += ": " + e.Err.Error() - return s -} - -// A ParseError is the error type of literal network address parsers. -type ParseError struct { - // Type is the type of string that was expected, such as - // "IP address", "CIDR address". - Type string - - // Text is the malformed text string. - Text string -} - -func (e *ParseError) Error() string { return "invalid " + e.Type + ": " + e.Text } - -type AddrError struct { - Err string - Addr string -} - -func (e *AddrError) Error() string { - if e == nil { - return "" - } - s := e.Err - if e.Addr != "" { - s = "address " + e.Addr + ": " + s - } - return s -} - -func (e *AddrError) Timeout() bool { return false } -func (e *AddrError) Temporary() bool { return false } - -// ErrClosed is the error returned by an I/O call on a network -// connection that has already been closed, or that is closed by -// another goroutine before the I/O is completed. This may be wrapped -// in another error, and should normally be tested using -// errors.Is(err, net.ErrClosed). -var ErrClosed = errClosed - -// buffersWriter is the interface implemented by Conns that support a -// "writev"-like batch write optimization. -// writeBuffers should fully consume and write all chunks from the -// provided Buffers, else it should report a non-nil error. -type buffersWriter interface { - writeBuffers(*Buffers) (int64, error) -} - -// Buffers contains zero or more runs of bytes to write. -// -// On certain machines, for certain types of connections, this is -// optimized into an OS-specific batch write operation (such as -// "writev"). -type Buffers [][]byte - -var ( - _ io.WriterTo = (*Buffers)(nil) - _ io.Reader = (*Buffers)(nil) -) - -// WriteTo writes contents of the buffers to w. -// -// WriteTo implements io.WriterTo for Buffers. -// -// WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v), -// but does not modify v[i][j] for any i, j. -func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) { - if wv, ok := w.(buffersWriter); ok { - return wv.writeBuffers(v) - } - for _, b := range *v { - nb, err := w.Write(b) - n += int64(nb) - if err != nil { - v.consume(n) - return n, err - } - } - v.consume(n) - return n, nil -} - -// Read from the buffers. -// -// Read implements io.Reader for Buffers. -// -// Read modifies the slice v as well as v[i] for 0 <= i < len(v), -// but does not modify v[i][j] for any i, j. -func (v *Buffers) Read(p []byte) (n int, err error) { - for len(p) > 0 && len(*v) > 0 { - n0 := copy(p, (*v)[0]) - v.consume(int64(n0)) - p = p[n0:] - n += n0 - } - if len(*v) == 0 { - err = io.EOF - } - return -} - -func (v *Buffers) consume(n int64) { - for len(*v) > 0 { - ln0 := int64(len((*v)[0])) - if ln0 > n { - (*v)[0] = (*v)[0][n:] - return - } - n -= ln0 - (*v)[0] = nil - *v = (*v)[1:] - } -} diff --git a/src/net/parse.go b/src/net/parse.go deleted file mode 100644 index f1f2ccb5c9..0000000000 --- a/src/net/parse.go +++ /dev/null @@ -1,90 +0,0 @@ -// The following is copied from Go 1.16 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 - -// Bigger than we need, not too big to worry about overflow -const big = 0xFFFFFF - -// Decimal to integer. -// Returns number, characters consumed, success. -func dtoi(s string) (n int, i int, ok bool) { - n = 0 - for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ { - n = n*10 + int(s[i]-'0') - if n >= big { - return big, i, false - } - } - if i == 0 { - return 0, 0, false - } - return n, i, true -} - -// Hexadecimal to integer. -// Returns number, characters consumed, success. -func xtoi(s string) (n int, i int, ok bool) { - n = 0 - for i = 0; i < len(s); i++ { - if '0' <= s[i] && s[i] <= '9' { - n *= 16 - n += int(s[i] - '0') - } else if 'a' <= s[i] && s[i] <= 'f' { - n *= 16 - n += int(s[i]-'a') + 10 - } else if 'A' <= s[i] && s[i] <= 'F' { - n *= 16 - n += int(s[i]-'A') + 10 - } else { - break - } - if n >= big { - return 0, i, false - } - } - if i == 0 { - return 0, i, false - } - return n, i, true -} - -// xtoi2 converts the next two hex digits of s into a byte. -// If s is longer than 2 bytes then the third byte must be e. -// If the first two bytes of s are not hex digits or the third byte -// does not match e, false is returned. -func xtoi2(s string, e byte) (byte, bool) { - if len(s) > 2 && s[2] != e { - return 0, false - } - n, ei, ok := xtoi(s[:2]) - return byte(n), ok && ei == 2 -} - -// Convert i to a hexadecimal string. Leading zeros are not printed. -func appendHex(dst []byte, i uint32) []byte { - if i == 0 { - return append(dst, '0') - } - for j := 7; j >= 0; j-- { - v := i >> uint(j*4) - if v > 0 { - dst = append(dst, hexDigit[v&0xf]) - } - } - return dst -} - -// Index of rightmost occurrence of b in s. -func last(s string, b byte) int { - i := len(s) - for i--; i >= 0; i-- { - if s[i] == b { - break - } - } - return i -} diff --git a/src/net/pipe.go b/src/net/pipe.go deleted file mode 100644 index 02dd07cf9a..0000000000 --- a/src/net/pipe.go +++ /dev/null @@ -1,240 +0,0 @@ -// The following is copied from Go 1.19.2 official implementation. - -// Copyright 2010 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 ( - "io" - "os" - "sync" - "time" -) - -// pipeDeadline is an abstraction for handling timeouts. -type pipeDeadline struct { - mu sync.Mutex // Guards timer and cancel - timer *time.Timer - cancel chan struct{} // Must be non-nil -} - -func makePipeDeadline() pipeDeadline { - return pipeDeadline{cancel: make(chan struct{})} -} - -// set sets the point in time when the deadline will time out. -// A timeout event is signaled by closing the channel returned by waiter. -// Once a timeout has occurred, the deadline can be refreshed by specifying a -// t value in the future. -// -// A zero value for t prevents timeout. -func (d *pipeDeadline) set(t time.Time) { - d.mu.Lock() - defer d.mu.Unlock() - - if d.timer != nil && !d.timer.Stop() { - <-d.cancel // Wait for the timer callback to finish and close cancel - } - d.timer = nil - - // Time is zero, then there is no deadline. - closed := isClosedChan(d.cancel) - if t.IsZero() { - if closed { - d.cancel = make(chan struct{}) - } - return - } - - // Time in the future, setup a timer to cancel in the future. - if dur := time.Until(t); dur > 0 { - if closed { - d.cancel = make(chan struct{}) - } - d.timer = time.AfterFunc(dur, func() { - close(d.cancel) - }) - return - } - - // Time in the past, so close immediately. - if !closed { - close(d.cancel) - } -} - -// wait returns a channel that is closed when the deadline is exceeded. -func (d *pipeDeadline) wait() chan struct{} { - d.mu.Lock() - defer d.mu.Unlock() - return d.cancel -} - -func isClosedChan(c <-chan struct{}) bool { - select { - case <-c: - return true - default: - return false - } -} - -type pipeAddr struct{} - -func (pipeAddr) Network() string { return "pipe" } -func (pipeAddr) String() string { return "pipe" } - -type pipe struct { - wrMu sync.Mutex // Serialize Write operations - - // Used by local Read to interact with remote Write. - // Successful receive on rdRx is always followed by send on rdTx. - rdRx <-chan []byte - rdTx chan<- int - - // Used by local Write to interact with remote Read. - // Successful send on wrTx is always followed by receive on wrRx. - wrTx chan<- []byte - wrRx <-chan int - - once sync.Once // Protects closing localDone - localDone chan struct{} - remoteDone <-chan struct{} - - readDeadline pipeDeadline - writeDeadline pipeDeadline -} - -// Pipe creates a synchronous, in-memory, full duplex -// network connection; both ends implement the Conn interface. -// Reads on one end are matched with writes on the other, -// copying data directly between the two; there is no internal -// buffering. -func Pipe() (Conn, Conn) { - cb1 := make(chan []byte) - cb2 := make(chan []byte) - cn1 := make(chan int) - cn2 := make(chan int) - done1 := make(chan struct{}) - done2 := make(chan struct{}) - - p1 := &pipe{ - rdRx: cb1, rdTx: cn1, - wrTx: cb2, wrRx: cn2, - localDone: done1, remoteDone: done2, - readDeadline: makePipeDeadline(), - writeDeadline: makePipeDeadline(), - } - p2 := &pipe{ - rdRx: cb2, rdTx: cn2, - wrTx: cb1, wrRx: cn1, - localDone: done2, remoteDone: done1, - readDeadline: makePipeDeadline(), - writeDeadline: makePipeDeadline(), - } - return p1, p2 -} - -func (*pipe) LocalAddr() Addr { return pipeAddr{} } -func (*pipe) RemoteAddr() Addr { return pipeAddr{} } - -func (p *pipe) Read(b []byte) (int, error) { - n, err := p.read(b) - if err != nil && err != io.EOF && err != io.ErrClosedPipe { - err = &OpError{Op: "read", Net: "pipe", Err: err} - } - return n, err -} - -func (p *pipe) read(b []byte) (n int, err error) { - switch { - case isClosedChan(p.localDone): - return 0, io.ErrClosedPipe - case isClosedChan(p.remoteDone): - return 0, io.EOF - case isClosedChan(p.readDeadline.wait()): - return 0, os.ErrDeadlineExceeded - } - - select { - case bw := <-p.rdRx: - nr := copy(b, bw) - p.rdTx <- nr - return nr, nil - case <-p.localDone: - return 0, io.ErrClosedPipe - case <-p.remoteDone: - return 0, io.EOF - case <-p.readDeadline.wait(): - return 0, os.ErrDeadlineExceeded - } -} - -func (p *pipe) Write(b []byte) (int, error) { - n, err := p.write(b) - if err != nil && err != io.ErrClosedPipe { - err = &OpError{Op: "write", Net: "pipe", Err: err} - } - return n, err -} - -func (p *pipe) write(b []byte) (n int, err error) { - switch { - case isClosedChan(p.localDone): - return 0, io.ErrClosedPipe - case isClosedChan(p.remoteDone): - return 0, io.ErrClosedPipe - case isClosedChan(p.writeDeadline.wait()): - return 0, os.ErrDeadlineExceeded - } - - p.wrMu.Lock() // Ensure entirety of b is written together - defer p.wrMu.Unlock() - for once := true; once || len(b) > 0; once = false { - select { - case p.wrTx <- b: - nw := <-p.wrRx - b = b[nw:] - n += nw - case <-p.localDone: - return n, io.ErrClosedPipe - case <-p.remoteDone: - return n, io.ErrClosedPipe - case <-p.writeDeadline.wait(): - return n, os.ErrDeadlineExceeded - } - } - return n, nil -} - -func (p *pipe) SetDeadline(t time.Time) error { - if isClosedChan(p.localDone) || isClosedChan(p.remoteDone) { - return io.ErrClosedPipe - } - p.readDeadline.set(t) - p.writeDeadline.set(t) - return nil -} - -func (p *pipe) SetReadDeadline(t time.Time) error { - if isClosedChan(p.localDone) || isClosedChan(p.remoteDone) { - return io.ErrClosedPipe - } - p.readDeadline.set(t) - return nil -} - -func (p *pipe) SetWriteDeadline(t time.Time) error { - if isClosedChan(p.localDone) || isClosedChan(p.remoteDone) { - return io.ErrClosedPipe - } - p.writeDeadline.set(t) - return nil -} - -func (p *pipe) Close() error { - p.once.Do(func() { close(p.localDone) }) - return nil -} diff --git a/src/net/pipe_test.go b/src/net/pipe_test.go deleted file mode 100644 index 7978fc6aa0..0000000000 --- a/src/net/pipe_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// The following is copied from Go 1.19.2 official implementation. - -// Copyright 2010 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 ( - "io" - "testing" - "time" -) - -func TestPipe(t *testing.T) { - testConn(t, func() (c1, c2 Conn, stop func(), err error) { - c1, c2 = Pipe() - stop = func() { - c1.Close() - c2.Close() - } - return - }) -} - -func TestPipeCloseError(t *testing.T) { - c1, c2 := Pipe() - c1.Close() - - if _, err := c1.Read(nil); err != io.ErrClosedPipe { - t.Errorf("c1.Read() = %v, want io.ErrClosedPipe", err) - } - if _, err := c1.Write(nil); err != io.ErrClosedPipe { - t.Errorf("c1.Write() = %v, want io.ErrClosedPipe", err) - } - if err := c1.SetDeadline(time.Time{}); err != io.ErrClosedPipe { - t.Errorf("c1.SetDeadline() = %v, want io.ErrClosedPipe", err) - } - if _, err := c2.Read(nil); err != io.EOF { - t.Errorf("c2.Read() = %v, want io.EOF", err) - } - if _, err := c2.Write(nil); err != io.ErrClosedPipe { - t.Errorf("c2.Write() = %v, want io.ErrClosedPipe", err) - } - if err := c2.SetDeadline(time.Time{}); err != io.ErrClosedPipe { - t.Errorf("c2.SetDeadline() = %v, want io.ErrClosedPipe", err) - } -} diff --git a/src/net/tcpsock.go b/src/net/tcpsock.go deleted file mode 100644 index d6aa602a9a..0000000000 --- a/src/net/tcpsock.go +++ /dev/null @@ -1,65 +0,0 @@ -package net - -import ( - "internal/itoa" - "net/netip" -) - -// TCPAddr represents the address of a TCP end point. -type TCPAddr struct { - IP IP - Port int - Zone string // IPv6 scoped addressing zone -} - -// AddrPort returns the TCPAddr a as a netip.AddrPort. -// -// If a.Port does not fit in a uint16, it's silently truncated. -// -// If a is nil, a zero value is returned. -func (a *TCPAddr) AddrPort() netip.AddrPort { - if a == nil { - return netip.AddrPort{} - } - na, _ := netip.AddrFromSlice(a.IP) - na = na.WithZone(a.Zone) - return netip.AddrPortFrom(na, uint16(a.Port)) -} - -// Network returns the address's network name, "tcp". -func (a *TCPAddr) Network() string { return "tcp" } - -func (a *TCPAddr) String() string { - if a == nil { - return "" - } - ip := ipEmptyString(a.IP) - if a.Zone != "" { - return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port)) - } - return JoinHostPort(ip, itoa.Itoa(a.Port)) -} - -func (a *TCPAddr) isWildcard() bool { - if a == nil || a.IP == nil { - return true - } - return a.IP.IsUnspecified() -} - -func (a *TCPAddr) opAddr() Addr { - if a == nil { - return nil - } - return a -} - -// TCPConn is an implementation of the Conn interface for TCP network -// connections. -type TCPConn struct { - conn -} - -func (c *TCPConn) CloseWrite() error { - return &OpError{"close", "", nil, nil, ErrNotImplemented} -} diff --git a/src/net/udpsock.go b/src/net/udpsock.go deleted file mode 100644 index f10800220c..0000000000 --- a/src/net/udpsock.go +++ /dev/null @@ -1,55 +0,0 @@ -package net - -import ( - "internal/itoa" - "net/netip" -) - -// UDPAddr represents the address of a UDP end point. -type UDPAddr struct { - IP IP - Port int - Zone string // IPv6 scoped addressing zone -} - -// AddrPort returns the UDPAddr a as a netip.AddrPort. -// -// If a.Port does not fit in a uint16, it's silently truncated. -// -// If a is nil, a zero value is returned. -func (a *UDPAddr) AddrPort() netip.AddrPort { - if a == nil { - return netip.AddrPort{} - } - na, _ := netip.AddrFromSlice(a.IP) - na = na.WithZone(a.Zone) - return netip.AddrPortFrom(na, uint16(a.Port)) -} - -// Network returns the address's network name, "udp". -func (a *UDPAddr) Network() string { return "udp" } - -func (a *UDPAddr) String() string { - if a == nil { - return "" - } - ip := ipEmptyString(a.IP) - if a.Zone != "" { - return JoinHostPort(ip+"%"+a.Zone, itoa.Itoa(a.Port)) - } - return JoinHostPort(ip, itoa.Itoa(a.Port)) -} - -func (a *UDPAddr) isWildcard() bool { - if a == nil || a.IP == nil { - return true - } - return a.IP.IsUnspecified() -} - -func (a *UDPAddr) opAddr() Addr { - if a == nil { - return nil - } - return a -} diff --git a/src/net/writev_test.go b/src/net/writev_test.go deleted file mode 100644 index 3a2c3efa3c..0000000000 --- a/src/net/writev_test.go +++ /dev/null @@ -1,132 +0,0 @@ -// The following is copied from Go 1.17 official implementation and -// modified to accommodate TinyGo. - -// 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. - -package net - -import ( - "bytes" - "fmt" - "io" - "reflect" - "testing" -) - -func TestBuffers_read(t *testing.T) { - const story = "once upon a time in Gopherland ... " - buffers := Buffers{ - []byte("once "), - []byte("upon "), - []byte("a "), - []byte("time "), - []byte("in "), - []byte("Gopherland ... "), - } - got, err := io.ReadAll(&buffers) - if err != nil { - t.Fatal(err) - } - if string(got) != story { - t.Errorf("read %q; want %q", got, story) - } - if len(buffers) != 0 { - t.Errorf("len(buffers) = %d; want 0", len(buffers)) - } -} - -func TestBuffers_consume(t *testing.T) { - tests := []struct { - in Buffers - consume int64 - want Buffers - }{ - { - in: Buffers{[]byte("foo"), []byte("bar")}, - consume: 0, - want: Buffers{[]byte("foo"), []byte("bar")}, - }, - { - in: Buffers{[]byte("foo"), []byte("bar")}, - consume: 2, - want: Buffers{[]byte("o"), []byte("bar")}, - }, - { - in: Buffers{[]byte("foo"), []byte("bar")}, - consume: 3, - want: Buffers{[]byte("bar")}, - }, - { - in: Buffers{[]byte("foo"), []byte("bar")}, - consume: 4, - want: Buffers{[]byte("ar")}, - }, - { - in: Buffers{nil, nil, nil, []byte("bar")}, - consume: 1, - want: Buffers{[]byte("ar")}, - }, - { - in: Buffers{nil, nil, nil, []byte("foo")}, - consume: 0, - want: Buffers{[]byte("foo")}, - }, - { - in: Buffers{nil, nil, nil}, - consume: 0, - want: Buffers{}, - }, - } - for i, tt := range tests { - in := tt.in - in.consume(tt.consume) - if !reflect.DeepEqual(in, tt.want) { - t.Errorf("%d. after consume(%d) = %+v, want %+v", i, tt.consume, in, tt.want) - } - } -} - -func TestBuffers_WriteTo(t *testing.T) { - for _, name := range []string{"WriteTo", "Copy"} { - for _, size := range []int{0, 10, 1023, 1024, 1025} { - t.Run(fmt.Sprintf("%s/%d", name, size), func(t *testing.T) { - testBuffer_writeTo(t, size, name == "Copy") - }) - } - } -} - -func testBuffer_writeTo(t *testing.T, chunks int, useCopy bool) { - var want bytes.Buffer - for i := 0; i < chunks; i++ { - want.WriteByte(byte(i)) - } - - var b bytes.Buffer - buffers := make(Buffers, chunks) - for i := range buffers { - buffers[i] = want.Bytes()[i : i+1] - } - var n int64 - var err error - if useCopy { - n, err = io.Copy(&b, &buffers) - } else { - n, err = buffers.WriteTo(&b) - } - if err != nil { - t.Fatal(err) - } - if len(buffers) != 0 { - t.Fatal(fmt.Errorf("len(buffers) = %d; want 0", len(buffers))) - } - if n != int64(want.Len()) { - t.Fatal(fmt.Errorf("Buffers.WriteTo returned %d; want %d", n, want.Len())) - } - all, err := io.ReadAll(&b) - if !bytes.Equal(all, want.Bytes()) || err != nil { - t.Fatal(fmt.Errorf("read %q, %v; want %q, nil", all, err, want.Bytes())) - } -} diff --git a/src/os/file_other.go b/src/os/file_other.go index d093e3d184..0ceee0020b 100644 --- a/src/os/file_other.go +++ b/src/os/file_other.go @@ -42,6 +42,14 @@ func NewFile(fd uintptr, name string) *File { return &File{&file{handle: stdioFileHandle(fd), name: name}} } +// Rename renames (moves) oldpath to newpath. +// If newpath already exists and is not a directory, Rename replaces it. +// OS-specific restrictions may apply when oldpath and newpath are in different directories. +// If there is an error, it will be of type *LinkError. +func Rename(oldpath, newpath string) error { + return ErrNotImplemented +} + // Read reads up to len(b) bytes from machine.Serial. // It returns the number of bytes read and any error encountered. func (f stdioFileHandle) Read(b []byte) (n int, err error) {