summaryrefslogtreecommitdiffstats
path: root/src/net/net_fake.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:19:13 +0000
commitccd992355df7192993c666236047820244914598 (patch)
treef00fea65147227b7743083c6148396f74cd66935 /src/net/net_fake.go
parentInitial commit. (diff)
downloadgolang-1.21-ccd992355df7192993c666236047820244914598.tar.xz
golang-1.21-ccd992355df7192993c666236047820244914598.zip
Adding upstream version 1.21.8.upstream/1.21.8
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/net/net_fake.go')
-rw-r--r--src/net/net_fake.go406
1 files changed, 406 insertions, 0 deletions
diff --git a/src/net/net_fake.go b/src/net/net_fake.go
new file mode 100644
index 0000000..908767a
--- /dev/null
+++ b/src/net/net_fake.go
@@ -0,0 +1,406 @@
+// Copyright 2018 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.
+
+// Fake networking for js/wasm and wasip1/wasm. It is intended to allow tests of other package to pass.
+
+//go:build (js && wasm) || wasip1
+
+package net
+
+import (
+ "context"
+ "io"
+ "os"
+ "sync"
+ "syscall"
+ "time"
+)
+
+var listenersMu sync.Mutex
+var listeners = make(map[fakeNetAddr]*netFD)
+
+var portCounterMu sync.Mutex
+var portCounter = 0
+
+func nextPort() int {
+ portCounterMu.Lock()
+ defer portCounterMu.Unlock()
+ portCounter++
+ return portCounter
+}
+
+type fakeNetAddr struct {
+ network string
+ address string
+}
+
+type fakeNetFD struct {
+ listener fakeNetAddr
+ r *bufferedPipe
+ w *bufferedPipe
+ incoming chan *netFD
+ closedMu sync.Mutex
+ closed bool
+}
+
+// socket returns a network file descriptor that is ready for
+// asynchronous I/O using the network poller.
+func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, ctrlCtxFn func(context.Context, string, string, syscall.RawConn) error) (*netFD, error) {
+ fd := &netFD{family: family, sotype: sotype, net: net}
+ if laddr != nil && raddr == nil {
+ return fakelistener(fd, laddr)
+ }
+ fd2 := &netFD{family: family, sotype: sotype, net: net}
+ return fakeconn(fd, fd2, laddr, raddr)
+}
+
+func fakeIPAndPort(ip IP, port int) (IP, int) {
+ if ip == nil {
+ ip = IPv4(127, 0, 0, 1)
+ }
+ if port == 0 {
+ port = nextPort()
+ }
+ return ip, port
+}
+
+func fakeTCPAddr(addr *TCPAddr) *TCPAddr {
+ var ip IP
+ var port int
+ var zone string
+ if addr != nil {
+ ip, port, zone = addr.IP, addr.Port, addr.Zone
+ }
+ ip, port = fakeIPAndPort(ip, port)
+ return &TCPAddr{IP: ip, Port: port, Zone: zone}
+}
+
+func fakeUDPAddr(addr *UDPAddr) *UDPAddr {
+ var ip IP
+ var port int
+ var zone string
+ if addr != nil {
+ ip, port, zone = addr.IP, addr.Port, addr.Zone
+ }
+ ip, port = fakeIPAndPort(ip, port)
+ return &UDPAddr{IP: ip, Port: port, Zone: zone}
+}
+
+func fakeUnixAddr(sotype int, addr *UnixAddr) *UnixAddr {
+ var net, name string
+ if addr != nil {
+ name = addr.Name
+ }
+ switch sotype {
+ case syscall.SOCK_DGRAM:
+ net = "unixgram"
+ case syscall.SOCK_SEQPACKET:
+ net = "unixpacket"
+ default:
+ net = "unix"
+ }
+ return &UnixAddr{Net: net, Name: name}
+}
+
+func fakelistener(fd *netFD, laddr sockaddr) (*netFD, error) {
+ switch l := laddr.(type) {
+ case *TCPAddr:
+ laddr = fakeTCPAddr(l)
+ case *UDPAddr:
+ laddr = fakeUDPAddr(l)
+ case *UnixAddr:
+ if l.Name == "" {
+ return nil, syscall.ENOENT
+ }
+ laddr = fakeUnixAddr(fd.sotype, l)
+ default:
+ return nil, syscall.EOPNOTSUPP
+ }
+
+ listener := fakeNetAddr{
+ network: laddr.Network(),
+ address: laddr.String(),
+ }
+
+ fd.fakeNetFD = &fakeNetFD{
+ listener: listener,
+ incoming: make(chan *netFD, 1024),
+ }
+
+ fd.laddr = laddr
+ listenersMu.Lock()
+ defer listenersMu.Unlock()
+ if _, exists := listeners[listener]; exists {
+ return nil, syscall.EADDRINUSE
+ }
+ listeners[listener] = fd
+ return fd, nil
+}
+
+func fakeconn(fd *netFD, fd2 *netFD, laddr, raddr sockaddr) (*netFD, error) {
+ switch r := raddr.(type) {
+ case *TCPAddr:
+ r = fakeTCPAddr(r)
+ raddr = r
+ laddr = fakeTCPAddr(laddr.(*TCPAddr))
+ case *UDPAddr:
+ r = fakeUDPAddr(r)
+ raddr = r
+ laddr = fakeUDPAddr(laddr.(*UDPAddr))
+ case *UnixAddr:
+ r = fakeUnixAddr(fd.sotype, r)
+ raddr = r
+ laddr = &UnixAddr{Net: r.Net, Name: r.Name}
+ default:
+ return nil, syscall.EAFNOSUPPORT
+ }
+ fd.laddr = laddr
+ fd.raddr = raddr
+
+ fd.fakeNetFD = &fakeNetFD{
+ r: newBufferedPipe(65536),
+ w: newBufferedPipe(65536),
+ }
+ fd2.fakeNetFD = &fakeNetFD{
+ r: fd.fakeNetFD.w,
+ w: fd.fakeNetFD.r,
+ }
+
+ fd2.laddr = fd.raddr
+ fd2.raddr = fd.laddr
+
+ listener := fakeNetAddr{
+ network: fd.raddr.Network(),
+ address: fd.raddr.String(),
+ }
+ listenersMu.Lock()
+ defer listenersMu.Unlock()
+ l, ok := listeners[listener]
+ if !ok {
+ return nil, syscall.ECONNREFUSED
+ }
+ l.incoming <- fd2
+ return fd, nil
+}
+
+func (fd *fakeNetFD) Read(p []byte) (n int, err error) {
+ return fd.r.Read(p)
+}
+
+func (fd *fakeNetFD) Write(p []byte) (nn int, err error) {
+ return fd.w.Write(p)
+}
+
+func (fd *fakeNetFD) Close() error {
+ fd.closedMu.Lock()
+ if fd.closed {
+ fd.closedMu.Unlock()
+ return nil
+ }
+ fd.closed = true
+ fd.closedMu.Unlock()
+
+ if fd.listener != (fakeNetAddr{}) {
+ listenersMu.Lock()
+ delete(listeners, fd.listener)
+ close(fd.incoming)
+ fd.listener = fakeNetAddr{}
+ listenersMu.Unlock()
+ return nil
+ }
+
+ fd.r.Close()
+ fd.w.Close()
+ return nil
+}
+
+func (fd *fakeNetFD) closeRead() error {
+ fd.r.Close()
+ return nil
+}
+
+func (fd *fakeNetFD) closeWrite() error {
+ fd.w.Close()
+ return nil
+}
+
+func (fd *fakeNetFD) accept() (*netFD, error) {
+ c, ok := <-fd.incoming
+ if !ok {
+ return nil, syscall.EINVAL
+ }
+ return c, nil
+}
+
+func (fd *fakeNetFD) SetDeadline(t time.Time) error {
+ fd.r.SetReadDeadline(t)
+ fd.w.SetWriteDeadline(t)
+ return nil
+}
+
+func (fd *fakeNetFD) SetReadDeadline(t time.Time) error {
+ fd.r.SetReadDeadline(t)
+ return nil
+}
+
+func (fd *fakeNetFD) SetWriteDeadline(t time.Time) error {
+ fd.w.SetWriteDeadline(t)
+ return nil
+}
+
+func newBufferedPipe(softLimit int) *bufferedPipe {
+ p := &bufferedPipe{softLimit: softLimit}
+ p.rCond.L = &p.mu
+ p.wCond.L = &p.mu
+ return p
+}
+
+type bufferedPipe struct {
+ softLimit int
+ mu sync.Mutex
+ buf []byte
+ closed bool
+ rCond sync.Cond
+ wCond sync.Cond
+ rDeadline time.Time
+ wDeadline time.Time
+}
+
+func (p *bufferedPipe) Read(b []byte) (int, error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ for {
+ if p.closed && len(p.buf) == 0 {
+ return 0, io.EOF
+ }
+ if !p.rDeadline.IsZero() {
+ d := time.Until(p.rDeadline)
+ if d <= 0 {
+ return 0, os.ErrDeadlineExceeded
+ }
+ time.AfterFunc(d, p.rCond.Broadcast)
+ }
+ if len(p.buf) > 0 {
+ break
+ }
+ p.rCond.Wait()
+ }
+
+ n := copy(b, p.buf)
+ p.buf = p.buf[n:]
+ p.wCond.Broadcast()
+ return n, nil
+}
+
+func (p *bufferedPipe) Write(b []byte) (int, error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ for {
+ if p.closed {
+ return 0, syscall.ENOTCONN
+ }
+ if !p.wDeadline.IsZero() {
+ d := time.Until(p.wDeadline)
+ if d <= 0 {
+ return 0, os.ErrDeadlineExceeded
+ }
+ time.AfterFunc(d, p.wCond.Broadcast)
+ }
+ if len(p.buf) <= p.softLimit {
+ break
+ }
+ p.wCond.Wait()
+ }
+
+ p.buf = append(p.buf, b...)
+ p.rCond.Broadcast()
+ return len(b), nil
+}
+
+func (p *bufferedPipe) Close() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ p.closed = true
+ p.rCond.Broadcast()
+ p.wCond.Broadcast()
+}
+
+func (p *bufferedPipe) SetReadDeadline(t time.Time) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ p.rDeadline = t
+ p.rCond.Broadcast()
+}
+
+func (p *bufferedPipe) SetWriteDeadline(t time.Time) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+
+ p.wDeadline = t
+ p.wCond.Broadcast()
+}
+
+func sysSocket(family, sotype, proto int) (int, error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (syscall.Sockaddr, error) {
+ return nil, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
+ return 0, nil, syscall.ENOSYS
+
+}
+func (fd *fakeNetFD) readFromInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) readFromInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
+ return 0, 0, 0, nil, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) {
+ return 0, 0, 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) {
+ return 0, 0, 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) {
+ return 0, 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) {
+ return 0, 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) writeToInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) writeToInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
+ return 0, 0, syscall.ENOSYS
+}
+
+func (fd *fakeNetFD) dup() (f *os.File, err error) {
+ return nil, syscall.ENOSYS
+}