Black Lives Matter. Support the Equal Justice Initiative.

Source file src/net/net_fake.go

Documentation: net

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

View as plain text