diff options
Diffstat (limited to 'internal/net/server.go')
| -rw-r--r-- | internal/net/server.go | 153 |
1 files changed, 113 insertions, 40 deletions
diff --git a/internal/net/server.go b/internal/net/server.go index 08d427f..7e73bc9 100644 --- a/internal/net/server.go +++ b/internal/net/server.go @@ -1,11 +1,13 @@ package net import ( - "bufio" + "crypto/tls" "fmt" "log" "net" - "strings" + "net/http" + + "thirdcollapse/internal/config" ) type SessionState int @@ -30,14 +32,13 @@ const ( ) type Session struct { - Conn net.Conn - Reader *bufio.Reader - State SessionState - Account *AccountEntry - Player interface{} // *player.Player once character is selected - PendingChar string // char being renamed/deleted - PendingPass string // first password during signup - Disconnecting bool + Conn Conn + State SessionState + Account *AccountEntry + Player interface{} + PendingChar string + PendingPass string + Disconnecting bool DisconnectTicks int } @@ -49,14 +50,18 @@ type AccountEntry struct { } type Server struct { - listener net.Listener - hub *Hub + config *config.Config + telnetLn net.Listener + httpServer *http.Server + httpsServer *http.Server + hub *Hub + handler func(*Session, string) } type Hub struct { - sessions map[*Session]bool - rooms map[int]map[*Session]bool - onRemove func(*Session) + sessions map[*Session]bool + rooms map[int]map[*Session]bool + onRemove func(*Session) } func NewHub() *Hub { @@ -125,12 +130,40 @@ func (h *Hub) PlayersInRoom(roomID int) []*Session { return out } -func NewServer(addr string) (*Server, error) { - l, err := net.Listen("tcp", addr) - if err != nil { - return nil, err +func NewServer(cfg *config.Config) (*Server, error) { + s := &Server{ + config: cfg, + hub: NewHub(), + } + + if cfg.Telnet.Enabled { + addr := fmt.Sprintf(":%d", cfg.Telnet.Port) + ln, err := net.Listen("tcp", addr) + if err != nil { + return nil, fmt.Errorf("telnet listen: %w", err) + } + s.telnetLn = ln + } + + if cfg.HTTP.Enabled { + s.httpServer = &http.Server{ + Addr: fmt.Sprintf(":%d", cfg.HTTP.Port), + Handler: newHTTPMux(s), + } + } + + if cfg.HTTPS.Enabled { + if cfg.HTTPS.CertFile == "" || cfg.HTTPS.KeyFile == "" { + return nil, fmt.Errorf("https enabled but cert_file and key_file are required") + } + s.httpsServer = &http.Server{ + Addr: fmt.Sprintf(":%d", cfg.HTTPS.Port), + Handler: newHTTPMux(s), + TLSConfig: &tls.Config{MinVersion: tls.VersionTLS12}, + } } - return &Server{listener: l, hub: NewHub()}, nil + + return s, nil } func (s *Server) Hub() *Hub { @@ -138,31 +171,66 @@ func (s *Server) Hub() *Hub { } func (s *Server) ListenAndServe(handler func(*Session, string)) error { + s.handler = handler + + if s.telnetLn != nil { + go s.serveTelnet() + } + + if s.httpServer != nil { + go s.serveHTTP() + } + + if s.httpsServer != nil { + go s.serveHTTPS() + } + + if s.telnetLn == nil && s.httpServer == nil && s.httpsServer == nil { + return fmt.Errorf("no listeners configured") + } + + select {} +} + +func (s *Server) serveTelnet() { for { - conn, err := s.listener.Accept() + conn, err := s.telnetLn.Accept() if err != nil { - return err + return } - session := &Session{ - Conn: conn, - Reader: bufio.NewReader(conn), - State: StateAccountName, + sess := &Session{ + Conn: newTCPConn(conn), + State: StateAccountName, } - s.hub.Add(session) - go s.handleSession(session, handler) + s.hub.Add(sess) + go s.handleSession(sess, s.handler) } } -func (s *Server) handleSession(session *Session, handler func(*Session, string)) { +func (s *Server) serveHTTP() { + err := s.httpServer.ListenAndServe() + if err != nil && err != http.ErrServerClosed { + log.Printf("http server error: %v", err) + } +} + +func (s *Server) serveHTTPS() { + err := s.httpsServer.ListenAndServeTLS(s.config.HTTPS.CertFile, s.config.HTTPS.KeyFile) + if err != nil && err != http.ErrServerClosed { + log.Printf("https server error: %v", err) + } +} + +func (s *Server) handleSession(sess *Session, handler func(*Session, string)) { defer func() { if r := recover(); r != nil { log.Printf("session panic: %v", r) } - s.hub.Remove(session) - session.Conn.Close() + s.hub.Remove(sess) + sess.Close() }() - _, _ = session.Conn.Write([]byte("\033[2J\033[H")) // clear screen + sess.Conn.Write([]byte("\033[2J\033[H")) welcomeart := ` , 3333333 333 333 333 3333333 3333333 @@ -179,29 +247,30 @@ func (s *Server) handleSession(session *Session, handler func(*Session, string)) :!! !!: !!! !!: !!: !!: !!! !!: !:! !!: :: :: : : :. : : ::.: : : ::.: : : : : : ::.: : : :: ::: - ` - session.Write(welcomeart) - session.Write("ACCOUNT NAME> ") + sess.Write(welcomeart) + sess.Write("What's your account name? ") for { - line, err := session.Reader.ReadString('\n') + line, err := sess.Conn.ReadMessage() if err != nil { log.Printf("session read error: %v", err) return } - line = strings.TrimSpace(line) - handler(session, line) + if len(line) > 1024 { + line = line[:1024] + } + handler(sess, line) } } func (sess *Session) Write(msg string) { - _, _ = sess.Conn.Write([]byte(msg)) + sess.Conn.Write([]byte(msg)) } func (sess *Session) WriteLine(msg string) { - _, _ = sess.Conn.Write([]byte(msg + "\r\n")) + sess.Conn.Write([]byte(msg + "\r\n")) } func (sess *Session) WriteLines(lines ...string) { @@ -213,3 +282,7 @@ func (sess *Session) WriteLines(lines ...string) { func (sess *Session) Writef(format string, args ...interface{}) { sess.Write(fmt.Sprintf(format, args...)) } + +func (sess *Session) Close() error { + return sess.Conn.Close() +} |
