Source file src/net/net_fake.go

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Fake networking for js/wasm. It is intended to allow tests of other package to pass.
     6  
     7  //go:build js && wasm
     8  
     9  package net
    10  
    11  import (
    12  	"context"
    13  	"internal/poll"
    14  	"io"
    15  	"os"
    16  	"sync"
    17  	"syscall"
    18  	"time"
    19  
    20  	"golang.org/x/net/dns/dnsmessage"
    21  )
    22  
    23  var listenersMu sync.Mutex
    24  var listeners = make(map[string]*netFD)
    25  
    26  var portCounterMu sync.Mutex
    27  var portCounter = 0
    28  
    29  func nextPort() int {
    30  	portCounterMu.Lock()
    31  	defer portCounterMu.Unlock()
    32  	portCounter++
    33  	return portCounter
    34  }
    35  
    36  // Network file descriptor.
    37  type netFD struct {
    38  	r        *bufferedPipe
    39  	w        *bufferedPipe
    40  	incoming chan *netFD
    41  
    42  	closedMu sync.Mutex
    43  	closed   bool
    44  
    45  	// immutable until Close
    46  	listener bool
    47  	family   int
    48  	sotype   int
    49  	net      string
    50  	laddr    Addr
    51  	raddr    Addr
    52  
    53  	// unused
    54  	pfd         poll.FD
    55  	isConnected bool // handshake completed or use of association with peer
    56  }
    57  
    58  // socket returns a network file descriptor that is ready for
    59  // asynchronous I/O using the network poller.
    60  func socket(ctx context.Context, net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, ctrlFn func(string, string, syscall.RawConn) error) (*netFD, error) {
    61  	fd := &netFD{family: family, sotype: sotype, net: net}
    62  
    63  	if laddr != nil && raddr == nil { // listener
    64  		l := laddr.(*TCPAddr)
    65  		fd.laddr = &TCPAddr{
    66  			IP:   l.IP,
    67  			Port: nextPort(),
    68  			Zone: l.Zone,
    69  		}
    70  		fd.listener = true
    71  		fd.incoming = make(chan *netFD, 1024)
    72  		listenersMu.Lock()
    73  		listeners[fd.laddr.(*TCPAddr).String()] = fd
    74  		listenersMu.Unlock()
    75  		return fd, nil
    76  	}
    77  
    78  	fd.laddr = &TCPAddr{
    79  		IP:   IPv4(127, 0, 0, 1),
    80  		Port: nextPort(),
    81  	}
    82  	fd.raddr = raddr
    83  	fd.r = newBufferedPipe(65536)
    84  	fd.w = newBufferedPipe(65536)
    85  
    86  	fd2 := &netFD{family: fd.family, sotype: sotype, net: net}
    87  	fd2.laddr = fd.raddr
    88  	fd2.raddr = fd.laddr
    89  	fd2.r = fd.w
    90  	fd2.w = fd.r
    91  	listenersMu.Lock()
    92  	l, ok := listeners[fd.raddr.(*TCPAddr).String()]
    93  	if !ok {
    94  		listenersMu.Unlock()
    95  		return nil, syscall.ECONNREFUSED
    96  	}
    97  	l.incoming <- fd2
    98  	listenersMu.Unlock()
    99  
   100  	return fd, nil
   101  }
   102  
   103  func (fd *netFD) Read(p []byte) (n int, err error) {
   104  	return fd.r.Read(p)
   105  }
   106  
   107  func (fd *netFD) Write(p []byte) (nn int, err error) {
   108  	return fd.w.Write(p)
   109  }
   110  
   111  func (fd *netFD) Close() error {
   112  	fd.closedMu.Lock()
   113  	if fd.closed {
   114  		fd.closedMu.Unlock()
   115  		return nil
   116  	}
   117  	fd.closed = true
   118  	fd.closedMu.Unlock()
   119  
   120  	if fd.listener {
   121  		listenersMu.Lock()
   122  		delete(listeners, fd.laddr.String())
   123  		close(fd.incoming)
   124  		fd.listener = false
   125  		listenersMu.Unlock()
   126  		return nil
   127  	}
   128  
   129  	fd.r.Close()
   130  	fd.w.Close()
   131  	return nil
   132  }
   133  
   134  func (fd *netFD) closeRead() error {
   135  	fd.r.Close()
   136  	return nil
   137  }
   138  
   139  func (fd *netFD) closeWrite() error {
   140  	fd.w.Close()
   141  	return nil
   142  }
   143  
   144  func (fd *netFD) accept() (*netFD, error) {
   145  	c, ok := <-fd.incoming
   146  	if !ok {
   147  		return nil, syscall.EINVAL
   148  	}
   149  	return c, nil
   150  }
   151  
   152  func (fd *netFD) SetDeadline(t time.Time) error {
   153  	fd.r.SetReadDeadline(t)
   154  	fd.w.SetWriteDeadline(t)
   155  	return nil
   156  }
   157  
   158  func (fd *netFD) SetReadDeadline(t time.Time) error {
   159  	fd.r.SetReadDeadline(t)
   160  	return nil
   161  }
   162  
   163  func (fd *netFD) SetWriteDeadline(t time.Time) error {
   164  	fd.w.SetWriteDeadline(t)
   165  	return nil
   166  }
   167  
   168  func newBufferedPipe(softLimit int) *bufferedPipe {
   169  	p := &bufferedPipe{softLimit: softLimit}
   170  	p.rCond.L = &p.mu
   171  	p.wCond.L = &p.mu
   172  	return p
   173  }
   174  
   175  type bufferedPipe struct {
   176  	softLimit int
   177  	mu        sync.Mutex
   178  	buf       []byte
   179  	closed    bool
   180  	rCond     sync.Cond
   181  	wCond     sync.Cond
   182  	rDeadline time.Time
   183  	wDeadline time.Time
   184  }
   185  
   186  func (p *bufferedPipe) Read(b []byte) (int, error) {
   187  	p.mu.Lock()
   188  	defer p.mu.Unlock()
   189  
   190  	for {
   191  		if p.closed && len(p.buf) == 0 {
   192  			return 0, io.EOF
   193  		}
   194  		if !p.rDeadline.IsZero() {
   195  			d := time.Until(p.rDeadline)
   196  			if d <= 0 {
   197  				return 0, syscall.EAGAIN
   198  			}
   199  			time.AfterFunc(d, p.rCond.Broadcast)
   200  		}
   201  		if len(p.buf) > 0 {
   202  			break
   203  		}
   204  		p.rCond.Wait()
   205  	}
   206  
   207  	n := copy(b, p.buf)
   208  	p.buf = p.buf[n:]
   209  	p.wCond.Broadcast()
   210  	return n, nil
   211  }
   212  
   213  func (p *bufferedPipe) Write(b []byte) (int, error) {
   214  	p.mu.Lock()
   215  	defer p.mu.Unlock()
   216  
   217  	for {
   218  		if p.closed {
   219  			return 0, syscall.ENOTCONN
   220  		}
   221  		if !p.wDeadline.IsZero() {
   222  			d := time.Until(p.wDeadline)
   223  			if d <= 0 {
   224  				return 0, syscall.EAGAIN
   225  			}
   226  			time.AfterFunc(d, p.wCond.Broadcast)
   227  		}
   228  		if len(p.buf) <= p.softLimit {
   229  			break
   230  		}
   231  		p.wCond.Wait()
   232  	}
   233  
   234  	p.buf = append(p.buf, b...)
   235  	p.rCond.Broadcast()
   236  	return len(b), nil
   237  }
   238  
   239  func (p *bufferedPipe) Close() {
   240  	p.mu.Lock()
   241  	defer p.mu.Unlock()
   242  
   243  	p.closed = true
   244  	p.rCond.Broadcast()
   245  	p.wCond.Broadcast()
   246  }
   247  
   248  func (p *bufferedPipe) SetReadDeadline(t time.Time) {
   249  	p.mu.Lock()
   250  	defer p.mu.Unlock()
   251  
   252  	p.rDeadline = t
   253  	p.rCond.Broadcast()
   254  }
   255  
   256  func (p *bufferedPipe) SetWriteDeadline(t time.Time) {
   257  	p.mu.Lock()
   258  	defer p.mu.Unlock()
   259  
   260  	p.wDeadline = t
   261  	p.wCond.Broadcast()
   262  }
   263  
   264  func sysSocket(family, sotype, proto int) (int, error) {
   265  	return 0, syscall.ENOSYS
   266  }
   267  
   268  func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
   269  	return 0, nil, syscall.ENOSYS
   270  
   271  }
   272  func (fd *netFD) readFromInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) {
   273  	return 0, syscall.ENOSYS
   274  }
   275  
   276  func (fd *netFD) readFromInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) {
   277  	return 0, syscall.ENOSYS
   278  }
   279  
   280  func (fd *netFD) readMsg(p []byte, oob []byte, flags int) (n, oobn, retflags int, sa syscall.Sockaddr, err error) {
   281  	return 0, 0, 0, nil, syscall.ENOSYS
   282  }
   283  
   284  func (fd *netFD) readMsgInet4(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet4) (n, oobn, retflags int, err error) {
   285  	return 0, 0, 0, syscall.ENOSYS
   286  }
   287  
   288  func (fd *netFD) readMsgInet6(p []byte, oob []byte, flags int, sa *syscall.SockaddrInet6) (n, oobn, retflags int, err error) {
   289  	return 0, 0, 0, syscall.ENOSYS
   290  }
   291  
   292  func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) {
   293  	return 0, 0, syscall.ENOSYS
   294  }
   295  
   296  func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) {
   297  	return 0, 0, syscall.ENOSYS
   298  }
   299  
   300  func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
   301  	return 0, syscall.ENOSYS
   302  }
   303  
   304  func (fd *netFD) writeToInet4(p []byte, sa *syscall.SockaddrInet4) (n int, err error) {
   305  	return 0, syscall.ENOSYS
   306  }
   307  
   308  func (fd *netFD) writeToInet6(p []byte, sa *syscall.SockaddrInet6) (n int, err error) {
   309  	return 0, syscall.ENOSYS
   310  }
   311  
   312  func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
   313  	return 0, 0, syscall.ENOSYS
   314  }
   315  
   316  func (fd *netFD) dup() (f *os.File, err error) {
   317  	return nil, syscall.ENOSYS
   318  }
   319  
   320  func (r *Resolver) lookup(ctx context.Context, name string, qtype dnsmessage.Type) (dnsmessage.Parser, string, error) {
   321  	panic("unreachable")
   322  }
   323  

View as plain text