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, ¬ifier{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 }