github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/service/listenerpipe.go (about)

     1  package service
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  	"sync"
     7  )
     8  
     9  // ListenerPipe returns a full-duplex in-memory connection, like net.Pipe.
    10  // Unlike net.Pipe one end of the connection is returned as an object
    11  // satisfying the net.Listener interface.
    12  // The first call to the Accept method of this object will return a net.Conn
    13  // connected to the other net.Conn returned by ListenerPipe.
    14  // Any subsequent calls to Accept will block until the listener is closed.
    15  func ListenerPipe() (net.Listener, net.Conn) {
    16  	conn0, conn1 := net.Pipe()
    17  	return &preconnectedListener{conn: conn0, closech: make(chan struct{})}, conn1
    18  }
    19  
    20  // preconnectedListener satisfies the net.Listener interface by accepting a
    21  // single pre-established connection.
    22  // The first call to Accept will return the conn field, any subsequent call
    23  // will block until the listener is closed.
    24  type preconnectedListener struct {
    25  	accepted bool
    26  	conn     net.Conn
    27  	closech  chan struct{}
    28  	closeMu  sync.Mutex
    29  	acceptMu sync.Mutex
    30  }
    31  
    32  // Accept returns the pre-established connection the first time it's called,
    33  // it blocks until the listener is closed on every subsequent call.
    34  func (l *preconnectedListener) Accept() (net.Conn, error) {
    35  	l.acceptMu.Lock()
    36  	defer l.acceptMu.Unlock()
    37  	if !l.accepted {
    38  		l.accepted = true
    39  		return l.conn, nil
    40  	}
    41  	<-l.closech
    42  	return nil, errors.New("accept failed: listener closed")
    43  }
    44  
    45  // Close closes the listener.
    46  func (l *preconnectedListener) Close() error {
    47  	l.closeMu.Lock()
    48  	defer l.closeMu.Unlock()
    49  	if l.closech == nil {
    50  		return nil
    51  	}
    52  	close(l.closech)
    53  	l.closech = nil
    54  	return nil
    55  }
    56  
    57  // Addr returns the listener's network address.
    58  func (l *preconnectedListener) Addr() net.Addr {
    59  	return l.conn.LocalAddr()
    60  }