telebit/server/manager.go

139 lines
3.9 KiB
Go

package server
import (
"context"
"crypto/tls"
"net"
)
//ListenerRegistrationStatus - post registration status
type ListenerRegistrationStatus int
const (
listenerAdded ListenerRegistrationStatus = iota
listenerExists
listenerFault
)
//ListenerRegistration -- A connection registration structure used to bring up a connection
//connection table will then handle additing and sdtarting up the various readers
//else error.
type ListenerRegistration struct {
// The websocket connection.
listener *net.Listener
// The listener port
port int
// The status
status ListenerRegistrationStatus
// The error
err error
// communications channel between go routines
commCh chan *ListenerRegistration
}
//NewListenerRegistration -- Constructor
func NewListenerRegistration(port int) (p *ListenerRegistration) {
p = new(ListenerRegistration)
p.port = port
p.commCh = make(chan *ListenerRegistration)
return
}
// Servers -
type Servers struct {
listeners map[*net.Listener]int
ctx context.Context
connnectionTable *Table
connectionTracking *Tracking
secretKey string
certbundle tls.Certificate
register chan *ListenerRegistration
servers *Servers
wssHostName string
adminHostName string
cancelCheck int
lbDefaultMethod string
serverStatus *Status
}
// NewGenerListeners creates tcp (and https and wss?) listeners
func NewGenerListeners(ctx context.Context, secretKey string, certbundle tls.Certificate, serverStatus *Status) (p *Servers) {
p = &Servers{}
p.listeners = make(map[*net.Listener]int)
p.ctx = ctx
p.connnectionTable = serverStatus.ConnectionTable
p.connectionTracking = serverStatus.ConnectionTracking
p.secretKey = secretKey
p.certbundle = certbundle
p.register = make(chan *ListenerRegistration)
p.wssHostName = serverStatus.WssDomain
p.adminHostName = serverStatus.AdminDomain
p.cancelCheck = serverStatus.DeadTime.cancelcheck
p.lbDefaultMethod = serverStatus.LoadbalanceDefaultMethod
p.serverStatus = serverStatus
return
}
//Run -- Execute
// - execute the GenericLister
// - pass initial port, we'll announce that
func (gl *Servers) Run(ctx context.Context, initialPort int) {
loginfo.Println("ConnectionTable starting")
config := &tls.Config{Certificates: []tls.Certificate{gl.certbundle}}
ctx = context.WithValue(ctx, ctxSecretKey, gl.secretKey)
loginfo.Println(gl.connectionTracking)
ctx = context.WithValue(ctx, ctxConnectionTrack, gl.connectionTracking)
ctx = context.WithValue(ctx, ctxConfig, config)
ctx = context.WithValue(ctx, ctxListenerRegistration, gl.register)
ctx = context.WithValue(ctx, ctxWssHostName, gl.wssHostName)
ctx = context.WithValue(ctx, ctxAdminHostName, gl.adminHostName)
ctx = context.WithValue(ctx, ctxCancelCheck, gl.cancelCheck)
ctx = context.WithValue(ctx, ctxLoadbalanceDefaultMethod, gl.lbDefaultMethod)
ctx = context.WithValue(ctx, ctxServerStatus, gl.serverStatus)
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
loginfo.Println("Cancel signal hit")
return
case registration := <-gl.register:
loginfo.Println("register fired", registration.port)
// check to see if port is already running
for listener := range gl.listeners {
if gl.listeners[listener] == registration.port {
loginfo.Println("listener already running", registration.port)
registration.status = listenerExists
registration.commCh <- registration
}
}
loginfo.Println("listener starting up ", registration.port)
loginfo.Println(ctx.Value(ctxConnectionTrack).(*Tracking))
go GenericListenAndServe(ctx, registration)
status := <-registration.commCh
if status.status == listenerAdded {
gl.listeners[status.listener] = status.port
} else if status.status == listenerFault {
loginfo.Println("Unable to create a new listerer", registration.port)
}
}
}
}(ctx)
newListener := NewListenerRegistration(initialPort)
gl.register <- newListener
}