You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
81 lines
1.9 KiB
81 lines
1.9 KiB
package sockets |
|
|
|
import ( |
|
"errors" |
|
"net" |
|
"sync" |
|
) |
|
|
|
var errClosed = errors.New("use of closed network connection") |
|
|
|
// InmemSocket implements net.Listener using in-memory only connections. |
|
type InmemSocket struct { |
|
chConn chan net.Conn |
|
chClose chan struct{} |
|
addr string |
|
mu sync.Mutex |
|
} |
|
|
|
// dummyAddr is used to satisfy net.Addr for the in-mem socket |
|
// it is just stored as a string and returns the string for all calls |
|
type dummyAddr string |
|
|
|
// NewInmemSocket creates an in-memory only net.Listener |
|
// The addr argument can be any string, but is used to satisfy the `Addr()` part |
|
// of the net.Listener interface |
|
func NewInmemSocket(addr string, bufSize int) *InmemSocket { |
|
return &InmemSocket{ |
|
chConn: make(chan net.Conn, bufSize), |
|
chClose: make(chan struct{}), |
|
addr: addr, |
|
} |
|
} |
|
|
|
// Addr returns the socket's addr string to satisfy net.Listener |
|
func (s *InmemSocket) Addr() net.Addr { |
|
return dummyAddr(s.addr) |
|
} |
|
|
|
// Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn. |
|
func (s *InmemSocket) Accept() (net.Conn, error) { |
|
select { |
|
case conn := <-s.chConn: |
|
return conn, nil |
|
case <-s.chClose: |
|
return nil, errClosed |
|
} |
|
} |
|
|
|
// Close closes the listener. It will be unavailable for use once closed. |
|
func (s *InmemSocket) Close() error { |
|
s.mu.Lock() |
|
defer s.mu.Unlock() |
|
select { |
|
case <-s.chClose: |
|
default: |
|
close(s.chClose) |
|
} |
|
return nil |
|
} |
|
|
|
// Dial is used to establish a connection with the in-mem server |
|
func (s *InmemSocket) Dial(network, addr string) (net.Conn, error) { |
|
srvConn, clientConn := net.Pipe() |
|
select { |
|
case s.chConn <- srvConn: |
|
case <-s.chClose: |
|
return nil, errClosed |
|
} |
|
|
|
return clientConn, nil |
|
} |
|
|
|
// Network returns the addr string, satisfies net.Addr |
|
func (a dummyAddr) Network() string { |
|
return string(a) |
|
} |
|
|
|
// String returns the string form |
|
func (a dummyAddr) String() string { |
|
return string(a) |
|
}
|
|
|