gitlab.com/Raven-IO/raven-delve@v1.22.4/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 }