diff --git a/internal/protocol/constants.go b/internal/protocol/constants.go index 09e76a6..28c7e17 100644 --- a/internal/protocol/constants.go +++ b/internal/protocol/constants.go @@ -33,4 +33,5 @@ const ( MessageUnknownCommand = "500 Unknown command" MessageErrorHappened = "403 Failed to process command:" MessageListOfNewsgroupsFollows = "215 list of newsgroups follows" + MessageSyntaxError = "501 Syntax Error" ) diff --git a/internal/server/handler.go b/internal/server/handler.go index a8448d8..b0af816 100644 --- a/internal/server/handler.go +++ b/internal/server/handler.go @@ -22,12 +22,13 @@ func NewHandler(db *sqlx.DB) *Handler { protocol.CommandDate: h.handleDate, protocol.CommandQuit: h.handleQuit, protocol.CommandList: h.handleList, + protocol.CommandMode: h.handleModeReader, } return h } func (h *Handler) handleCapabilities(s *Session, arguments []string) error { - return s.tconn.PrintfLine(Capabilities.String()) + return s.tconn.PrintfLine(s.capabilities.String()) } func (h *Handler) handleDate(s *Session, arguments []string) error { @@ -81,7 +82,7 @@ func (h *Handler) handleList(s *Session, arguments []string) error { } default: { - return s.tconn.PrintfLine(protocol.MessageUnknownCommand) + return s.tconn.PrintfLine(protocol.MessageSyntaxError) } } @@ -90,6 +91,18 @@ func (h *Handler) handleList(s *Session, arguments []string) error { return s.tconn.PrintfLine(sb.String()) } +func (h *Handler) handleModeReader(s *Session, arguments []string) error { + if len(arguments) == 0 || arguments[0] != "READER" { + return s.tconn.PrintfLine(protocol.MessageSyntaxError) + } + + (&s.capabilities).Remove(protocol.ModeReaderCapability) + (&s.capabilities).Add(protocol.Capability{Type: protocol.ReaderCapability}) + s.mode = SessionModeReader + + return s.tconn.PrintfLine(protocol.MessageReaderModePostingProhibited) // TODO vary on auth status +} + func (h *Handler) Handle(s *Session, message string) error { splittedMessage := strings.Split(message, " ") for i, v := range splittedMessage { diff --git a/internal/server/session.go b/internal/server/session.go index 1b78d89..ce9b159 100644 --- a/internal/server/session.go +++ b/internal/server/session.go @@ -9,6 +9,13 @@ import ( "net/textproto" ) +type SessionMode int + +const ( + SessionModeTransit = iota + SessionModeReader +) + type Session struct { ctx context.Context capabilities protocol.Capabilities @@ -17,6 +24,7 @@ type Session struct { id string closed chan<- bool h *Handler + mode SessionMode } func NewSession(ctx context.Context, conn net.Conn, caps protocol.Capabilities, id string, closed chan<- bool, handler *Handler) (*Session, error) { @@ -37,6 +45,7 @@ func NewSession(ctx context.Context, conn net.Conn, caps protocol.Capabilities, id: id, closed: closed, h: handler, + mode: SessionModeTransit, } go s.loop() @@ -49,7 +58,7 @@ func (s *Session) loop() { close(s.closed) }() - err := s.tconn.PrintfLine(protocol.MessageReaderModePostingProhibited) // by default access mode is read-only + err := s.tconn.PrintfLine(protocol.MessageNNTPServiceReadyPostingProhibited) // by default access mode is read-only if err != nil { s.conn.Close() return