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

View as plain text