github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/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 closed bool 40 connectionMapLock sync.Mutex 41 connectionMap map[ip4Address]uint 42 } 43 44 // ReverseListenerConfig describes the configuration for a remote server for 45 // which connections are requested. 46 type ReverseListenerConfig struct { 47 Network string // May be empty or "tcp". 48 ServerAddress string // Address of the remote server. 49 MinimumInterval time.Duration // Minimum interval to request connections. 50 MaximumInterval time.Duration // Maximum interval to request connections. 51 } 52 53 // Listen creates a listener which may be used to accept incoming connections. 54 // It listens on all available IP addresses on the local system. 55 func Listen(network string, portNumber uint, logger log.DebugLogger) ( 56 *Listener, error) { 57 return listen(network, portNumber, logger) 58 } 59 60 func (l *Listener) Accept() (net.Conn, error) { 61 return l.accept() 62 } 63 64 func (l *Listener) Addr() net.Addr { 65 return l.listener.Addr() 66 } 67 68 func (l *Listener) Close() error { 69 return l.close() 70 } 71 72 // RequestConnections starts a goroutine which will periodically attempt to 73 // establish a connection with a remote server if there is no incoming 74 // connection from the remote server. The connection that is established will be 75 // returned by the Accept method. The configuration information for the remote 76 // server is read from the JSON-encoded file with filename: 77 // "/etc/reverse-listeners/"+serviceName with the format ReverseListenerConfig. 78 func (l *Listener) RequestConnections(serviceName string) error { 79 return l.requestConnections(serviceName) 80 } 81 82 // NewDialer creates a dialer that may be used to make connections. It also 83 // registers a HTTP handler for receiving connections from remote systems which 84 // have requested connections. When the Dial method is called, if a new 85 // connection has been received it is used instead of dialing out the normal 86 // way. If rawDialer is nil, the default dialer is used to dial out when needed. 87 // If serveMux is nil then the default http.ServeMux is used. NewDialer may be 88 // called only once per serveMux. 89 // The minimumInterval and maximumInterval parameters are passed back to remote 90 // systems which are making connections, overriding their default configuration. 91 func NewDialer(rawDialer *net.Dialer, serveMux *http.ServeMux, 92 minimumInterval, maximumInterval time.Duration, 93 logger log.DebugLogger) *Dialer { 94 return newDialer(rawDialer, serveMux, minimumInterval, maximumInterval, 95 logger) 96 } 97 98 // Dial makes a connection to a remote address, possibly consuming a connection 99 // that was initiated by the remote address. 100 func (d *Dialer) Dial(network, address string) (net.Conn, error) { 101 return d.dial(network, address) 102 }