github.com/Cloud-Foundations/Dominator@v0.3.4/lib/net/reverseconnection/api.go (about)

     1  package reverseconnection
     2  
     3  import (
     4  	"net"
     5  	"net/http"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/Cloud-Foundations/Dominator/lib/log"
    10  	libnet "github.com/Cloud-Foundations/Dominator/lib/net"
    11  )
    12  
    13  type acceptEvent struct {
    14  	conn  *listenerConn
    15  	error error
    16  }
    17  
    18  type listenerConn struct {
    19  	libnet.TCPConn
    20  	listener *Listener
    21  }
    22  
    23  type Dialer struct {
    24  	dialer            *net.Dialer
    25  	minimumInterval   time.Duration
    26  	maximumInterval   time.Duration
    27  	logger            log.DebugLogger
    28  	connectionMapLock sync.Mutex
    29  	connectionMap     map[string]net.Conn // Key: address (ip:port).
    30  }
    31  
    32  type ip4Address [4]byte
    33  
    34  type Listener struct {
    35  	listener          net.Listener
    36  	portNumber        uint
    37  	logger            log.DebugLogger
    38  	acceptChannel     chan acceptEvent
    39  	closedLock        sync.Mutex
    40  	closed            bool
    41  	connectionMapLock sync.Mutex
    42  	connectionMap     map[ip4Address]uint
    43  }
    44  
    45  // ReverseListenerConfig describes the configuration for a remote server for
    46  // which connections are requested.
    47  type ReverseListenerConfig struct {
    48  	Network         string        // May be empty or "tcp".
    49  	ServerAddress   string        // Address of the remote server.
    50  	MinimumInterval time.Duration // Minimum interval to request connections.
    51  	MaximumInterval time.Duration // Maximum interval to request connections.
    52  }
    53  
    54  // Listen creates a listener which may be used to accept incoming connections.
    55  // It listens on all available IP addresses on the local system.
    56  func Listen(network string, portNumber uint, logger log.DebugLogger) (
    57  	*Listener, error) {
    58  	return listen(network, portNumber, logger)
    59  }
    60  
    61  func (l *Listener) Accept() (net.Conn, error) {
    62  	return l.accept()
    63  }
    64  
    65  func (l *Listener) Addr() net.Addr {
    66  	return l.listener.Addr()
    67  }
    68  
    69  func (l *Listener) Close() error {
    70  	return l.close()
    71  }
    72  
    73  // RequestConnections starts a goroutine which will periodically attempt to
    74  // establish a connection with a remote server if there is no incoming
    75  // connection from the remote server. The connection that is established will be
    76  // returned by the Accept method. The configuration information for the remote
    77  // server is read from the JSON-encoded file with filename:
    78  // "/etc/reverse-listeners/"+serviceName with the format ReverseListenerConfig.
    79  func (l *Listener) RequestConnections(serviceName string) error {
    80  	return l.requestConnections(serviceName)
    81  }
    82  
    83  // NewDialer creates a dialer that may be used to make connections. It also
    84  // registers a HTTP handler for receiving connections from remote systems which
    85  // have requested connections. When the Dial method is called, if a new
    86  // connection has been received it is used instead of dialing out the normal
    87  // way. If rawDialer is nil, the default dialer is used to dial out when needed.
    88  // If serveMux is nil then the default http.ServeMux is used. NewDialer may be
    89  // called only once per serveMux.
    90  // The minimumInterval and maximumInterval parameters are passed back to remote
    91  // systems which are making connections, overriding their default configuration.
    92  func NewDialer(rawDialer *net.Dialer, serveMux *http.ServeMux,
    93  	minimumInterval, maximumInterval time.Duration,
    94  	logger log.DebugLogger) *Dialer {
    95  	return newDialer(rawDialer, serveMux, minimumInterval, maximumInterval,
    96  		logger)
    97  }
    98  
    99  // Dial makes a connection to a remote address, possibly consuming a connection
   100  // that was initiated by the remote address.
   101  func (d *Dialer) Dial(network, address string) (net.Conn, error) {
   102  	return d.dial(network, address)
   103  }