90 lines
2.1 KiB
Go
90 lines
2.1 KiB
Go
package network
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"sync/atomic"
|
|
|
|
"github.com/gorilla/websocket"
|
|
|
|
"a301_game_server/config"
|
|
"a301_game_server/pkg/logger"
|
|
)
|
|
|
|
// Server listens for WebSocket connections and creates Connection objects.
|
|
type Server struct {
|
|
cfg *config.Config
|
|
upgrader websocket.Upgrader
|
|
handler PacketHandler
|
|
nextID atomic.Uint64
|
|
srv *http.Server
|
|
}
|
|
|
|
// NewServer creates a new WebSocket server.
|
|
func NewServer(cfg *config.Config, handler PacketHandler) *Server {
|
|
return &Server{
|
|
cfg: cfg,
|
|
handler: handler,
|
|
upgrader: websocket.Upgrader{
|
|
ReadBufferSize: cfg.Network.ReadBufferSize,
|
|
WriteBufferSize: cfg.Network.WriteBufferSize,
|
|
CheckOrigin: func(r *http.Request) bool { return true },
|
|
},
|
|
}
|
|
}
|
|
|
|
// Start begins listening for connections. Blocks until the context is cancelled.
|
|
func (s *Server) Start(ctx context.Context) error {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/ws", s.handleWebSocket)
|
|
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte("ok"))
|
|
})
|
|
|
|
addr := s.cfg.Server.Address()
|
|
s.srv = &http.Server{
|
|
Addr: addr,
|
|
Handler: mux,
|
|
}
|
|
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
logger.Info("websocket server starting", "address", addr)
|
|
if err := s.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
errCh <- fmt.Errorf("listen: %w", err)
|
|
}
|
|
}()
|
|
|
|
select {
|
|
case err := <-errCh:
|
|
return err
|
|
case <-ctx.Done():
|
|
logger.Info("shutting down websocket server")
|
|
return s.srv.Shutdown(context.Background())
|
|
}
|
|
}
|
|
|
|
func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|
ws, err := s.upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
logger.Error("websocket upgrade failed", "error", err, "remote", r.RemoteAddr)
|
|
return
|
|
}
|
|
|
|
connID := s.nextID.Add(1)
|
|
conn := NewConnection(
|
|
connID,
|
|
ws,
|
|
s.handler,
|
|
s.cfg.Network.SendChannelSize,
|
|
s.cfg.Network.MaxMessageSize,
|
|
s.cfg.Network.HeartbeatInterval,
|
|
s.cfg.Network.HeartbeatTimeout,
|
|
)
|
|
|
|
logger.Info("client connected", "connID", connID, "remote", r.RemoteAddr)
|
|
conn.Start()
|
|
}
|