lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xnet/virtnet/virtnet.go (about)

     1  // Copyright (C) 2017-2020  Nexedi SA and Contributors.
     2  //                          Kirill Smelkov <kirr@nexedi.com>
     3  //
     4  // This program is free software: you can Use, Study, Modify and Redistribute
     5  // it under the terms of the GNU General Public License version 3, or (at your
     6  // option) any later version, as published by the Free Software Foundation.
     7  //
     8  // You can also Link and Combine this program with other software covered by
     9  // the terms of any of the Free Software licenses or any of the Open Source
    10  // Initiative approved licenses and Convey the resulting work. Corresponding
    11  // source of such a combination shall include the source code for all other
    12  // software used.
    13  //
    14  // This program is distributed WITHOUT ANY WARRANTY; without even the implied
    15  // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16  //
    17  // See COPYING file for full licensing terms.
    18  // See https://www.nexedi.com/licensing for rationale and options.
    19  
    20  // Package virtnet provides infrastructure for TCP-like virtual networks.
    21  //
    22  // For testing distributed systems it is sometimes handy to imitate network of
    23  // several TCP hosts. It is also handy that ports allocated on Dial/Listen/Accept
    24  // on that hosts be predictable - that would help tests to verify network
    25  // events against expected sequence.
    26  //
    27  // Package virtnet provides infrastructure for using and implementing such
    28  // TCP-like virtual networks.
    29  //
    30  // # Using virtnet networks
    31  //
    32  // Addresses on a virtnet network are host:port pairs represented by Addr.
    33  // A network conceptually consists of several SubNetworks each being home for
    34  // multiple Hosts. Host is xnet.Networker and so can be worked with similarly
    35  // to regular TCP network access-point with Dial/Listen/Accept. Host's ports
    36  // allocation is predictable: ports of a host are contiguous integer sequence
    37  // starting from 1 that are all initially free, and whenever autobind is
    38  // requested the first free port of the host will be used.
    39  // Virtnet ensures that host names are unique throughout whole network.
    40  //
    41  // To work with a virtnet network, one uses corresponding package for
    42  // particular virtnet network implementation. Such packages provide a way to
    43  // join particular network and after joining give back SubNetwork to user.
    44  // Starting from SubNetwork one can create Hosts and from those exchange data
    45  // throughout whole network.
    46  //
    47  // Please see packages lab.nexedi.com/kirr/go123/xnet/lonet and
    48  // lab.nexedi.com/kirr/go123/xnet/pipenet for particular well-known
    49  // virtnet-based networks.
    50  //
    51  // # Implementing virtnet networks
    52  //
    53  // To implement a virtnet-based network one need to implement Engine and Registry.
    54  //
    55  // A virtnet network implementation should provide Engine and Registry
    56  // instances to SubNetwork when creating it. The subnetwork will use provided
    57  // engine and registry for its operations. A virtnet network implementation
    58  // receives instance of Notifier together with SubNetwork when creating it. The
    59  // network implementation should use provided Notifier to notify the subnetwork
    60  // to handle incoming events.
    61  //
    62  // Please see Engine, Registry and Notifier documentation for details.
    63  package virtnet
    64  
    65  // TODO Fix virtnet for TCP semantic: there port(accepted) = port(listen), i.e.
    66  //	When we connect www.nexedi.com:80, remote addr of socket will have port 80.
    67  //	Likewise on server side accepted socket will have local port 80.
    68  //	The connection should be thus fully identified by src-dst address pair.
    69  
    70  import (
    71  	"context"
    72  	"errors"
    73  	"io"
    74  	"net"
    75  	"strconv"
    76  	"sync"
    77  	"sync/atomic"
    78  
    79  	"lab.nexedi.com/kirr/go123/xcontext"
    80  	"lab.nexedi.com/kirr/go123/xerr"
    81  	"lab.nexedi.com/kirr/go123/xnet"
    82  )
    83  
    84  var (
    85  	ErrNetDown         = errors.New("network is down")
    86  	ErrHostDown        = errors.New("host is down")
    87  	ErrSockDown        = errors.New("socket is down")
    88  	ErrAddrAlreadyUsed = errors.New("address already in use")
    89  	ErrAddrNoListen    = errors.New("cannot listen on requested address")
    90  	ErrConnRefused     = errors.New("connection refused")
    91  )
    92  
    93  // Addr represents address of a virtnet endpoint.
    94  type Addr struct {
    95  	Net  string // full network name, e.g. "pipeα" or "lonetβ"
    96  	Host string // name of host access point on the network
    97  	Port int    // port on host
    98  }
    99  
   100  // SubNetwork represents one subnetwork of a virtnet network.
   101  //
   102  // Multiple Hosts could be created on one subnetwork.
   103  // Multiple subnetworks could be part of a single virtnet network.
   104  //
   105  // Host names are unique through whole virtnet network.
   106  //
   107  // SubNetwork should be created by a particular virtnet network implementation
   108  // via NewSubNetwork.
   109  type SubNetwork struct {
   110  	// full network name, e.g. "pipeα" or "lonetβ"
   111  	network string
   112  
   113  	// virtnet network implementation and registry given to us
   114  	engine   Engine
   115  	registry Registry
   116  
   117  	// {} hostname -> Host
   118  	hostMu     sync.Mutex
   119  	hostMap    map[string]*Host
   120  	nopenHosts int  // #(hosts-in-open-state) in hostMap
   121  	autoClose  bool // close SubNetwork when last host is Closed
   122  
   123  	down     chan struct{} // closed when no longer operational
   124  	downErr  error
   125  	downOnce sync.Once
   126  }
   127  
   128  // Host represents named access point on a virtnet network.
   129  //
   130  // A Host belongs to a SubNetwork.
   131  // It has name and array of sockets indexed by port.
   132  // It implements xnet.Networker.
   133  //
   134  // It is safe to use Host from multiple goroutines simultaneously.
   135  type Host struct {
   136  	subnet *SubNetwork
   137  	name   string
   138  
   139  	// [] port -> listener | conn  ; [0] is always nil
   140  	sockMu  sync.Mutex
   141  	socketv []*socket
   142  
   143  	down      chan struct{} // closed when no longer operational
   144  	downOnce  sync.Once
   145  	closeOnce sync.Once
   146  }
   147  
   148  var _ xnet.Networker = (*Host)(nil)
   149  
   150  // socket represents one endpoint entry on Host.
   151  //
   152  // it can be either already connected or listening.
   153  type socket struct {
   154  	host *Host // host/port this socket is bound to
   155  	port int
   156  
   157  	conn     *conn     // connection endpoint is here if != nil
   158  	listener *listener // listener is waiting here if != nil
   159  }
   160  
   161  // conn represents one endpoint of a virtnet connection.
   162  //
   163  // conn is the net.Conn implementation that Host.Dial and listener.Accept return.
   164  type conn struct {
   165  	socket   *socket // local socket
   166  	peerAddr *Addr   // address of the remote side of this connection
   167  
   168  	net.Conn
   169  
   170  	down      uint32    // 1 after shutdown
   171  	downOnce  sync.Once
   172  	errClose  error     // error we got from closing underlying net.Conn
   173  	closeOnce sync.Once
   174  }
   175  
   176  // listener implements xnet.Listener for Host.Listen .
   177  type listener struct {
   178  	// subnetwork/host/port we are listening on
   179  	socket *socket
   180  
   181  	dialq chan dialReq // Dial requests to our port go here
   182  
   183  	down      chan struct{} // closed when no longer operational
   184  	downOnce  sync.Once
   185  	closeOnce sync.Once
   186  }
   187  
   188  // dialReq represents one dial request to listener from acceptor.
   189  type dialReq struct {
   190  	from *Addr
   191  	conn net.Conn
   192  	resp chan *Accept
   193  }
   194  
   195  // notifier implements Notifier for SubNetwork.
   196  //
   197  // it is separate from SubNetwork not to generally expose Notifier as API
   198  // virtnet users (contrary to virtnet network implementers) should use.
   199  type notifier struct {
   200  	subnet *SubNetwork
   201  }
   202  
   203  
   204  // ----------------------------------------
   205  
   206  // NewSubNetwork creates new SubNetwork with given name.
   207  //
   208  // It should be used by virtnet network implementations who should provide it
   209  // with Engine and Registry instances.
   210  //
   211  // Together with returned SubNetwork an instance of Notifier is provided that
   212  // should be used by virtnet network implementation to notify created
   213  // subnetwork to handle incoming events.
   214  func NewSubNetwork(network string, engine Engine, registry Registry) (*SubNetwork, Notifier) {
   215  	// XXX prefix network with "virtnet/" ?
   216  	subnet := &SubNetwork{
   217  		network:  network,
   218  		engine:   engine,
   219  		registry: registry,
   220  		hostMap:  make(map[string]*Host),
   221  		down:     make(chan struct{}),
   222  	}
   223  
   224  	return subnet, &notifier{subnet}
   225  }
   226  
   227  
   228  // shutdown shutdowns subnetwork.
   229  //
   230  // It is worker for Close and VNetDown.
   231  //
   232  // The error provided is the cause of shutdown - e.g. IO error from engine, or
   233  // nil on plain close.
   234  //
   235  // It is safe to call shutdown multiple times and from multiple goroutines
   236  // simultaneously - only the first call has the effect.
   237  //
   238  // The error returned is cumulative shutdown error - the cause + any error from
   239  // closing engine and registry for the call when shutdown was actually performed.
   240  func (n *SubNetwork) shutdown(err error) error { return n._shutdown(err, true) }
   241  func (n *SubNetwork) _shutdown(err error, withHosts bool) error {
   242  	n.downOnce.Do(func() {
   243  		close(n.down)
   244  
   245  		// shutdown hosts
   246  		if withHosts {
   247  			n.hostMu.Lock()
   248  			for _, host := range n.hostMap {
   249  				host.shutdown()
   250  			}
   251  			n.hostMu.Unlock()
   252  		}
   253  
   254  		var errv xerr.Errorv
   255  		errv.Appendif( err )
   256  		errv.Appendif( n.engine.Close() )
   257  		errv.Appendif( n.registry.Close() )
   258  
   259  		n.downErr = errv.Err()
   260  	})
   261  
   262  	return n.downErr
   263  }
   264  
   265  // Close shutdowns subnetwork.
   266  //
   267  // It recursively interrupts all blocking operations on the subnetwork and
   268  // shutdowns all subnetwork's hosts and connections.
   269  func (n *SubNetwork) Close()             (err error) { return n._close(true)  }
   270  func (n *SubNetwork) closeWithoutHosts() (err error) { return n._close(false) }
   271  func (n *SubNetwork) _close(withHosts bool) (err error) {
   272  	defer xerr.Contextf(&err, "virtnet %q: close", n.network)
   273  	return n._shutdown(nil, withHosts)
   274  }
   275  
   276  // VNetDown implements Notifier by shutting subnetwork down upon engine error.
   277  func (nn *notifier) VNetDown(err error) {
   278  	nn.subnet.shutdown(err)
   279  }
   280  
   281  
   282  // NewHost creates new Host with given name.
   283  //
   284  // The host will be associated with SubNetwork via which it was created.
   285  //
   286  // Host names should be unique through whole virtnet network.
   287  // If not - an error with ErrHostDup cause will be returned.
   288  func (n *SubNetwork) NewHost(ctx context.Context, name string) (_ *Host, err error) {
   289  	defer xerr.Contextf(&err, "virtnet %q: new host %q", n.network, name)
   290  
   291  	// cancel on network shutdown
   292  	origCtx := ctx
   293  	ctx, cancel := xcontext.MergeChan(ctx, n.down); defer cancel()
   294  
   295  	// announce new host
   296  	err = n.engine.VNetNewHost(ctx, name, n.registry)
   297  	if err != nil {
   298  		if ctx.Err() != nil && origCtx.Err() == nil {
   299  			// error due to subnetwork shutdown
   300  			err = ErrNetDown
   301  		}
   302  		return nil, err
   303  	}
   304  
   305  	// announced ok -> host can be created
   306  	n.hostMu.Lock()
   307  	defer n.hostMu.Unlock()
   308  
   309  	if n.hostMap[name] != nil {
   310  		panic("announced ok but .hostMap already !empty")
   311  	}
   312  
   313  	host := &Host{subnet: n, name: name, down: make(chan struct{})}
   314  	n.hostMap[name] = host
   315  	n.nopenHosts++
   316  
   317  	return host, nil
   318  }
   319  
   320  // Host returns host on the subnetwork by name.
   321  //
   322  // If there is no such host - nil is returned.
   323  func (n *SubNetwork) Host(name string) *Host {
   324  	n.hostMu.Lock()
   325  	defer n.hostMu.Unlock()
   326  
   327  	return n.hostMap[name]
   328  }
   329  
   330  // shutdown is underlying worker for Close.
   331  func (h *Host) shutdown() {
   332  	h.downOnce.Do(func() {
   333  		close(h.down)
   334  
   335  		// shutdown all sockets
   336  		h.sockMu.Lock()
   337  		defer h.sockMu.Unlock()
   338  
   339  		for _, sk := range h.socketv {
   340  			if sk == nil {
   341  				continue
   342  			}
   343  			if sk.conn != nil {
   344  				sk.conn.shutdown()
   345  			}
   346  			if sk.listener != nil {
   347  				sk.listener.shutdown()
   348  			}
   349  		}
   350  	})
   351  }
   352  
   353  // Close shutdowns host.
   354  //
   355  // After host is shutdown connections to it cannot be established and all
   356  // currently-established connections are shut down.
   357  //
   358  // Close interrupts all currently in-flight blocked I/O operations on Host or
   359  // objects created from it: connections and listeners.
   360  func (h *Host) Close() (err error) {
   361  	defer xerr.Contextf(&err, "virtnet %q: host %q: close", h.subnet.network, h.name)
   362  	h.shutdown()
   363  
   364  	// close subnet if autoclose=y and we were the last open host
   365  	h.closeOnce.Do(func() {
   366  		n := h.subnet
   367  		n.hostMu.Lock()
   368  		defer n.hostMu.Unlock()
   369  		n.nopenHosts--
   370  		if n.nopenHosts < 0 {
   371  			panic("SubNetwork.nopenHosts < 0")
   372  		}
   373  		if n.autoClose && n.nopenHosts == 0 {
   374  			err = n.closeWithoutHosts()
   375  		}
   376  	})
   377  
   378  	return err
   379  }
   380  
   381  // AutoClose schedules Close to be called after last host on this subnetwork is closed.
   382  //
   383  // It is an error to call AutoClose with no opened hosts - this will panic.
   384  func (n *SubNetwork) AutoClose() {
   385  	n.hostMu.Lock()
   386  	defer n.hostMu.Unlock()
   387  	if n.nopenHosts == 0 {
   388  		panic("BUG: no opened hosts")
   389  	}
   390  	n.autoClose = true
   391  }
   392  
   393  
   394  // Listen starts new listener on the host.
   395  //
   396  // It either allocates free port if laddr is "" or with 0 port, or binds to laddr.
   397  // Once listener is started, Dials could connect to listening address.
   398  // Connection requests created by Dials could be accepted via Accept.
   399  func (h *Host) Listen(ctx context.Context, laddr string) (_ xnet.Listener, err error) {
   400  	var netladdr net.Addr
   401  	defer func() {
   402  		if err != nil {
   403  			err = &net.OpError{Op: "listen", Net: h.Network(), Addr: netladdr, Err: err}
   404  		}
   405  	}()
   406  
   407  	if laddr == "" {
   408  		laddr = ":0"
   409  	}
   410  
   411  	if err := ctx.Err(); err != nil {
   412  		return nil, err
   413  	}
   414  
   415  	a, err := h.parseAddr(laddr)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  	netladdr = a
   420  
   421  	// cannot listen on other hosts
   422  	if a.Host != h.name {
   423  		return nil, ErrAddrNoListen
   424  	}
   425  
   426  	if ready(h.down) {
   427  		return nil, h.errDown()
   428  	}
   429  
   430  	h.sockMu.Lock()
   431  	defer h.sockMu.Unlock()
   432  
   433  	var sk *socket
   434  
   435  	// find first free port if autobind requested
   436  	if a.Port == 0 {
   437  		sk = h.allocFreeSocket()
   438  
   439  	// else allocate socket in-place
   440  	} else {
   441  		// grow if needed
   442  		for a.Port >= len(h.socketv) {
   443  			h.socketv = append(h.socketv, nil)
   444  		}
   445  
   446  		if h.socketv[a.Port] != nil {
   447  			return nil, ErrAddrAlreadyUsed
   448  		}
   449  
   450  		sk = &socket{host: h, port: a.Port}
   451  		h.socketv[a.Port] = sk
   452  	}
   453  
   454  	// create listener under socket
   455  	l := &listener{
   456  		socket: sk,
   457  		dialq:  make(chan dialReq),
   458  		down:   make(chan struct{}),
   459  	}
   460  	sk.listener = l
   461  
   462  	return l, nil
   463  }
   464  
   465  // shutdown shutdowns the listener.
   466  //
   467  // It interrupts all currently in-flight calls to Accept, but does not
   468  // unregister listener from host's socket map.
   469  func (l *listener) shutdown() {
   470  	l.downOnce.Do(func() {
   471  		close(l.down)
   472  	})
   473  }
   474  
   475  // Close closes the listener.
   476  //
   477  // It interrupts all currently in-flight calls to Accept.
   478  func (l *listener) Close() error {
   479  	l.shutdown()
   480  	l.closeOnce.Do(func() {
   481  		sk := l.socket
   482  		h := sk.host
   483  
   484  		h.sockMu.Lock()
   485  		defer h.sockMu.Unlock()
   486  
   487  		sk.listener = nil
   488  		if sk.empty() {
   489  			h.socketv[sk.port] = nil
   490  		}
   491  	})
   492  	return nil
   493  }
   494  
   495  // Accept tries to connect to Dial called with addr corresponding to our listener.
   496  func (l *listener) Accept(ctx context.Context) (_ net.Conn, err error) {
   497  	h := l.socket.host
   498  
   499  	defer func() {
   500  		if err != nil {
   501  			err = &net.OpError{Op: "accept", Net: h.Network(), Addr: l.Addr(), Err: err}
   502  		}
   503  	}()
   504  
   505  	for {
   506  		var req dialReq
   507  
   508  		select {
   509  		case <-ctx.Done():
   510  			return nil, ctx.Err()
   511  		case <-l.down:
   512  			return nil, l.errDown()
   513  
   514  		case req = <-l.dialq:
   515  			// ok
   516  		}
   517  
   518  		// acceptor dials us - allocate empty socket so that we know accept address.
   519  		h.sockMu.Lock()
   520  		sk := h.allocFreeSocket()
   521  		h.sockMu.Unlock()
   522  
   523  		// give acceptor feedback that we are accepting the connection.
   524  		ack := make(chan error)
   525  		req.resp <- &Accept{sk.addr(), ack}
   526  
   527  		// wait for ack from acceptor.
   528  		var noack error
   529  		select {
   530  		case <-ctx.Done():
   531  			noack = ctx.Err()
   532  		case <-l.down:
   533  			noack = l.errDown()
   534  
   535  		case err = <-ack:
   536  			// ok
   537  		}
   538  		if noack != nil {
   539  			// acceptor was slow.
   540  			// we have to make sure we still receive on ack and
   541  			// close req.conn / unallocate the socket appropriately.
   542  			go func() {
   543  				err := <-ack
   544  				if err == nil {
   545  					// acceptor conveyed us the connection - close it
   546  					req.conn.Close()
   547  				}
   548  				h.sockMu.Lock()
   549  				h.socketv[sk.port] = nil
   550  				h.sockMu.Unlock()
   551  			}()
   552  
   553  			return nil, noack
   554  		}
   555  
   556  		// we got feedback from acceptor
   557  		// if there is an error - unallocate the socket and continue waiting.
   558  		if err != nil {
   559  			h.sockMu.Lock()
   560  			h.socketv[sk.port] = nil
   561  			h.sockMu.Unlock()
   562  			continue
   563  		}
   564  
   565  		// all ok - allocate conn, bind it to socket and we are done.
   566  		c := &conn{socket: sk, peerAddr: req.from, Conn: req.conn}
   567  		h.sockMu.Lock()
   568  		sk.conn = c
   569  		h.sockMu.Unlock()
   570  
   571  		return c, nil
   572  	}
   573  }
   574  
   575  // VNetAccept implements Notifier by accepting or rejecting incoming connection.
   576  func (nn *notifier) VNetAccept(ctx context.Context, src, dst *Addr, netconn net.Conn) (*Accept, error) {
   577  	n := nn.subnet
   578  
   579  	n.hostMu.Lock()
   580  	host := n.hostMap[dst.Host]
   581  	n.hostMu.Unlock()
   582  	if host == nil {
   583  		return nil, &net.AddrError{Err: "no such host", Addr: dst.String()}
   584  	}
   585  
   586  	host.sockMu.Lock()
   587  
   588  	if dst.Port >= len(host.socketv) {
   589  		host.sockMu.Unlock()
   590  		return nil, ErrConnRefused
   591  	}
   592  
   593  	sk := host.socketv[dst.Port]
   594  	if sk == nil || sk.listener == nil {
   595  		host.sockMu.Unlock()
   596  		return nil, ErrConnRefused
   597  	}
   598  
   599  	// there is listener corresponding to dst - let's connect it
   600  	l := sk.listener
   601  	host.sockMu.Unlock()
   602  
   603  	resp := make(chan *Accept)
   604  	select {
   605  	case <-ctx.Done():
   606  		return nil, ctx.Err()
   607  
   608  	case <-l.down:
   609  		return nil, ErrConnRefused
   610  
   611  	case l.dialq <- dialReq{from: src, conn: netconn, resp: resp}:
   612  		return <-resp, nil
   613  	}
   614  }
   615  
   616  
   617  // Dial dials address on the network.
   618  //
   619  // It tries to connect to Accept called on listener corresponding to addr.
   620  func (h *Host) Dial(ctx context.Context, addr string) (_ net.Conn, err error) {
   621  	// allocate socket in empty state early, so we can see in the error who
   622  	// tries to dial.
   623  	h.sockMu.Lock()
   624  	sk := h.allocFreeSocket()
   625  	h.sockMu.Unlock()
   626  	defer func() {
   627  		if err != nil {
   628  			h.sockMu.Lock()
   629  			h.socketv[sk.port] = nil
   630  			h.sockMu.Unlock()
   631  		}
   632  	}()
   633  
   634  	var netdst net.Addr
   635  	defer func() {
   636  		if err != nil {
   637  			err = &net.OpError{Op: "dial", Net: h.Network(), Source: sk.addr(), Addr: netdst, Err: err}
   638  		}
   639  
   640  	}()
   641  
   642  
   643  	dst, err := h.parseAddr(addr)
   644  	if err != nil {
   645  		return nil, err
   646  	}
   647  	netdst = dst
   648  
   649  	n := h.subnet
   650  
   651  	// cancel on host shutdown
   652  	origCtx := ctx
   653  	ctx, cancel := xcontext.MergeChan(ctx, h.down); defer cancel()
   654  	errOrDown := func(err error) error {
   655  		if ctx.Err() != nil && origCtx.Err() == nil {
   656  			// error due to shutdown
   657  			return h.errDown()
   658  		}
   659  		return err
   660  	}
   661  
   662  	// query registry
   663  	dstdata, err := n.registry.Query(ctx, dst.Host)
   664  	if err != nil {
   665  		return nil, errOrDown(err)
   666  	}
   667  
   668  	// dial engine
   669  	netconn, acceptAddr, err := n.engine.VNetDial(ctx, sk.addr(), dst, dstdata)
   670  	if err != nil {
   671  		return nil, errOrDown(err)
   672  	}
   673  
   674  	// handshake performed ok - we are done.
   675  	c := &conn{socket: sk, peerAddr: acceptAddr, Conn: netconn}
   676  	h.sockMu.Lock()
   677  	sk.conn = c
   678  	h.sockMu.Unlock()
   679  
   680  	return c, nil
   681  }
   682  
   683  // ---- conn ----
   684  
   685  // shutdown closes underlying network connection.
   686  func (c *conn) shutdown() {
   687  	c.downOnce.Do(func() {
   688  		atomic.StoreUint32(&c.down, 1)
   689  		c.errClose = c.Conn.Close()
   690  	})
   691  }
   692  
   693  // Close closes network endpoint and unregisters conn from Host.
   694  //
   695  // All currently in-flight blocked IO is interrupted with an error.
   696  func (c *conn) Close() error {
   697  	c.shutdown()
   698  	c.closeOnce.Do(func() {
   699  		sk := c.socket
   700  		h := sk.host
   701  
   702  		h.sockMu.Lock()
   703  		defer h.sockMu.Unlock()
   704  
   705  		sk.conn = nil
   706  		if sk.empty() {
   707  			h.socketv[sk.port] = nil
   708  		}
   709  	})
   710  
   711  	return c.errClose
   712  }
   713  
   714  
   715  // Read implements net.Conn .
   716  //
   717  // it delegates the read to underlying net.Conn but amends error if it was due
   718  // to conn shutdown.
   719  func (c *conn) Read(p []byte) (int, error) {
   720  	n, err := c.Conn.Read(p)
   721  	if err != nil && err != io.EOF {
   722  		if !errIsTimeout(err) {
   723  			// an error that might be due to shutdown
   724  			err = c.errOrDown(err)
   725  		}
   726  
   727  		// wrap error to be at virtnet level.
   728  		// net.OpError preserve .Timeout() value if .Err has it.
   729  		err = &net.OpError{
   730  			Op:     "read",
   731  			Net:    c.socket.host.Network(),
   732  			Addr:   c.LocalAddr(),
   733  			Source: c.RemoteAddr(),
   734  			Err:    err,
   735  		}
   736  	}
   737  	return n, err
   738  }
   739  
   740  // Write implements net.Conn .
   741  //
   742  // it delegates the write to underlying net.Conn but amends error if it was due
   743  // to conn shutdown.
   744  func (c *conn) Write(p []byte) (int, error) {
   745  	n, err := c.Conn.Write(p)
   746  	if err != nil {
   747  		if !errIsTimeout(err) {
   748  			err = c.errOrDown(err)
   749  		}
   750  
   751  		err = &net.OpError{
   752  			Op:     "write",
   753  			Net:    c.socket.host.Network(),
   754  			Addr:   c.RemoteAddr(),
   755  			Source: c.LocalAddr(),
   756  			Err:    err,
   757  		}
   758  	}
   759  	return n, err
   760  }
   761  
   762  
   763  // LocalAddr implements net.Conn.
   764  //
   765  // it returns virtnet address of local end of connection.
   766  func (c *conn) LocalAddr() net.Addr {
   767  	return c.socket.addr()
   768  }
   769  
   770  // RemoteAddr implements net.Conn .
   771  //
   772  // it returns virtnet address of remote end of connection.
   773  func (c *conn) RemoteAddr() net.Addr {
   774  	return c.peerAddr
   775  }
   776  
   777  // ----------------------------------------
   778  
   779  // allocFreeSocket finds first free port and allocates socket entry for it.
   780  //
   781  // must be called with SubNetwork.mu held.
   782  func (h *Host) allocFreeSocket() *socket {
   783  	// find first free port
   784  	port := 1 // never allocate port 0 - it is used for autobind on listen only
   785  	for ; port < len(h.socketv); port++ {
   786  		if h.socketv[port] == nil {
   787  			break
   788  		}
   789  	}
   790  	// if all busy it exits with port >= len(h.socketv)
   791  
   792  	// grow if needed
   793  	for port >= len(h.socketv) {
   794  		h.socketv = append(h.socketv, nil)
   795  	}
   796  
   797  	sk := &socket{host: h, port: port}
   798  	h.socketv[port] = sk
   799  	return sk
   800  }
   801  
   802  // empty checks whether socket's both conn and listener are all nil.
   803  func (sk *socket) empty() bool {
   804  	return sk.conn == nil && sk.listener == nil
   805  }
   806  
   807  // addr returns address corresponding to socket.
   808  func (sk *socket) addr() *Addr {
   809  	h := sk.host
   810  	return &Addr{Net: h.Network(), Host: h.name, Port: sk.port}
   811  }
   812  
   813  // Network implements net.Addr .
   814  func (a *Addr) Network() string { return a.Net }
   815  
   816  // String implements net.Addr .
   817  func (a *Addr) String() string { return net.JoinHostPort(a.Host, strconv.Itoa(a.Port)) }
   818  
   819  // ParseAddr parses addr into virtnet address for named network.
   820  func ParseAddr(network, addr string) (*Addr, error) {
   821  	host, portstr, err := net.SplitHostPort(addr)
   822  	if err != nil {
   823  		return nil, err
   824  	}
   825  	port, err := strconv.Atoi(portstr)
   826  	if err != nil || port < 0 {
   827  		return nil, &net.AddrError{Err: "invalid port", Addr: addr}
   828  	}
   829  	return &Addr{Net: network, Host: host, Port: port}, nil
   830  }
   831  
   832  // parseAddr parses addr into virtnet address from host point of view.
   833  //
   834  // It is the same as ParseAddr except empty host string - e.g. as in ":0" -
   835  // is resolved to the host itself.
   836  func (h *Host) parseAddr(addr string) (*Addr, error) {
   837  	a, err := ParseAddr(h.Network(), addr)
   838  	if err != nil {
   839  		return nil, err
   840  	}
   841  
   842  	// local host if host name omitted
   843  	if a.Host == "" {
   844  		a.Host = h.name
   845  	}
   846  
   847  	return a, nil
   848  }
   849  
   850  // Addr returns address where listener is accepting incoming connections.
   851  func (l *listener) Addr() net.Addr {
   852  	return l.socket.addr()
   853  }
   854  
   855  // Network returns full network name this subnetwork is part of.
   856  func (n *SubNetwork) Network() string { return n.network }
   857  
   858  // Network returns full network name of underlying network.
   859  func (h *Host) Network() string { return h.subnet.Network() }
   860  
   861  // Name returns host name.
   862  func (h *Host) Name() string { return h.name }
   863  
   864  // ----------------------------------------
   865  
   866  // errDown returns appropriate error cause when h.down is found ready.
   867  func (h *Host) errDown() error {
   868  	switch {
   869  	case ready(h.subnet.down):
   870  		return ErrNetDown
   871  	default:
   872  		return ErrHostDown
   873  	}
   874  }
   875  
   876  // errDown returns appropriate error cause when l.down is found ready.
   877  func (l *listener) errDown() error {
   878  	h := l.socket.host
   879  	n := h.subnet
   880  
   881  	switch {
   882  	case ready(n.down):
   883  		return ErrNetDown
   884  	case ready(h.down):
   885  		return ErrHostDown
   886  	default:
   887  		return ErrSockDown
   888  	}
   889  }
   890  
   891  // errOrDown returns err or shutdown cause if c.shutdown was called.
   892  func (c *conn) errOrDown(err error) error {
   893  	// shutdown was not yet called - leave it as is.
   894  	if atomic.LoadUint32(&c.down) == 0 {
   895  		return err
   896  	}
   897  
   898  	// shutdown was called - find out the reason.
   899  	h := c.socket.host
   900  	n := h.subnet
   901  	switch {
   902  	case ready(n.down):
   903  		return ErrNetDown
   904  	case ready(h.down):
   905  		return ErrHostDown
   906  	default:
   907  		return ErrSockDown
   908  	}
   909  }
   910  
   911  
   912  // ready returns whether chan struct{} is ready.
   913  func ready(ch <-chan struct{}) bool {
   914  	select {
   915  	case <-ch:
   916  		return true
   917  	default:
   918  		return false
   919  	}
   920  }
   921  
   922  // errIsTimeout checks whether error is due to timeout.
   923  //
   924  // useful to check because net.Conn says:
   925  //
   926  //	"Read/Write can be made to time out and return an Error with Timeout() == true"
   927  func errIsTimeout(err error) bool {
   928  	e, ok := err.(interface{ Timeout() bool })
   929  	if ok {
   930  		return e.Timeout()
   931  	}
   932  	return false
   933  }