go-gun/gun/server.go

61 lines
1.5 KiB
Go
Raw Normal View History

package gun
import (
"context"
)
2019-02-26 21:59:44 +00:00
// Server is the interface implemented by servers.
type Server interface {
2019-02-26 21:59:44 +00:00
// Serve is called by Gun to start the server. It should not return until
// an error occurs or Close is called.
Serve() error
// Accept is called to wait for the next peer connection or if an error
// occurs while trying.
Accept() (PeerConn, error)
2019-02-26 21:59:44 +00:00
// Close is called by Gun to stop and close this server.
Close() error
}
2019-02-26 21:59:44 +00:00
func (g *Gun) startServers(ctx context.Context, servers []Server) {
ctx, g.serversCancelFn = context.WithCancel(ctx)
for _, server := range servers {
// TODO: log error?
go g.serve(ctx, server)
}
}
func (g *Gun) serve(ctx context.Context, s Server) error {
errCh := make(chan error, 1)
ctx, cancelFn := context.WithCancel(ctx)
defer cancelFn()
// Start the server
go func() { errCh <- s.Serve() }()
defer s.Close()
// Accept connections and break off
go func() {
if conn, err := s.Accept(); err == nil {
// TODO: log error (for accept and handle)?
go g.onNewPeerConn(ctx, conn)
}
}()
// Wait for server close or context close
select {
case err := <-errCh:
return err
case <-ctx.Done():
return ctx.Err()
}
}
func (g *Gun) onNewPeerConn(ctx context.Context, conn PeerConn) error {
ctx, cancelFn := context.WithCancel(ctx)
defer cancelFn()
defer conn.Close()
// We always send a DAM req first
if err := conn.Send(ctx, &Message{DAM: "?"}); err != nil {
return err
}
// Now add the connection to Gun
panic("TODO")
}