| 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) |
| } |