2019-02-25 22:28:19 +00:00
|
|
|
package gun
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
)
|
|
|
|
|
2019-02-26 21:59:44 +00:00
|
|
|
// Server is the interface implemented by servers.
|
2019-02-25 22:28:19 +00:00
|
|
|
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.
|
2019-02-25 22:28:19 +00:00
|
|
|
Accept() (PeerConn, error)
|
2019-02-26 21:59:44 +00:00
|
|
|
// Close is called by Gun to stop and close this server.
|
2019-02-25 22:28:19 +00:00
|
|
|
Close() error
|
|
|
|
}
|
|
|
|
|
2019-02-26 21:59:44 +00:00
|
|
|
func (g *Gun) startServers(ctx context.Context, servers []Server) {
|
2019-02-25 22:28:19 +00:00
|
|
|
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")
|
|
|
|
}
|