commit ba988fd4461e70f94f59ed0790095bfd4b2eef1c from: Oliver Lowe date: Thu Mar 28 01:24:27 2024 UTC nntp: move errors to nntp package There's nothing special about the error codes and server implementation. It's just part of the protocol commit - de59b21200a5aa169b2dc799bca29b8f75c8e231 commit + ba988fd4461e70f94f59ed0790095bfd4b2eef1c blob - 986166c75750032eb3c68b01d704d36055641c2b blob + 3d07cce51101dcc008d1f0806b065ebcd30c8852 --- examples/server/exampleserver.go +++ examples/server/exampleserver.go @@ -12,7 +12,7 @@ import ( "strings" "github.com/dustin/go-nntp" - "github.com/dustin/go-nntp/server" + nntpserver "github.com/dustin/go-nntp/server" ) const maxArticles = 100 @@ -85,7 +85,7 @@ func (tb *testBackendType) GetGroup(name string) (*nnt } if group == nil { - return nil, nntpserver.ErrNoSuchGroup + return nil, nntp.ErrNoSuchGroup } return group, nil @@ -138,7 +138,7 @@ func (tb *testBackendType) GetArticle(group *nntp.Grou a = tb.articles[msgID] if a == nil { - return nil, nntpserver.ErrInvalidMessageID + return nil, nntp.ErrInvalidMessageID } return mkArticle(a), nil @@ -164,7 +164,7 @@ func (tb *testBackendType) GetArticles(group *nntp.Gro gs, ok := tb.groups[group.Name] if !ok { - return nil, nntpserver.ErrNoSuchGroup + return nil, nntp.ErrNoSuchGroup } log.Printf("Getting articles from %d to %d", from, to) @@ -225,7 +225,7 @@ func (tb *testBackendType) Post(article *nntp.Article) msgID := a.headers.Get("Message-Id") if _, ok := tb.articles[msgID]; ok { - return nntpserver.ErrPostingFailed + return nntp.ErrPostingFailed } for _, g := range article.Header["Newsgroups"] { @@ -254,7 +254,7 @@ func (tb *testBackendType) Post(article *nntp.Article) if a.refcount > 0 { tb.articles[msgID] = &a } else { - return nntpserver.ErrPostingFailed + return nntp.ErrPostingFailed } return nil @@ -265,7 +265,7 @@ func (tb *testBackendType) Authorized() bool { } func (tb *testBackendType) Authenticate(user, pass string) (nntpserver.Backend, error) { - return nil, nntpserver.ErrAuthRejected + return nil, nntp.ErrAuthRejected } func maybefatal(err error, f string, a ...interface{}) { blob - /dev/null blob + aa319ede4dac0b44e0e93bc27e3368768113f529 (mode 644) --- /dev/null +++ error.go @@ -0,0 +1,58 @@ +package nntp + +import "fmt" + +// An NNTPError is a coded NNTP error message. +type Error struct { + Code int + Msg string +} + +func (e *Error) Error() string { + return fmt.Sprintf("%d %s", e.Code, e.Msg) +} + +// ErrNoSuchGroup is returned for a request for a group that can't be found. +var ErrNoSuchGroup = &Error{411, "No such newsgroup"} + +// ErrNoSuchGroup is returned for a request that requires a current +// group when none has been selected. +var ErrNoGroupSelected = &Error{412, "No newsgroup selected"} + +// ErrInvalidMessageID is returned when a message is requested that can't be found. +var ErrInvalidMessageID = &Error{430, "No article with that message-id"} + +// ErrInvalidArticleNumber is returned when an article is requested that can't be found. +var ErrInvalidArticleNumber = &Error{423, "No article with that number"} + +// ErrNoCurrentArticle is returned when a command is executed that +// requires a current article when one has not been selected. +var ErrNoCurrentArticle = &Error{420, "Current article number is invalid"} + +// ErrUnknownCommand is returned for unknown comands. +var ErrUnknownCommand = &Error{500, "Unknown command"} + +// ErrSyntax is returned when a command can't be parsed. +var ErrSyntax = &Error{501, "not supported, or syntax error"} + +// ErrPostingNotPermitted is returned as the response to an attempt to +// post an article where posting is not permitted. +var ErrPostingNotPermitted = &Error{440, "posting not permitted"} + +// ErrPostingFailed is returned when an attempt to post an article fails. +var ErrPostingFailed = &Error{441, "posting failed"} + +// ErrNotWanted is returned when an attempt to post an article is +// rejected due the server not wanting the article. +var ErrNotWanted = &Error{435, "Article not wanted"} + +// ErrAuthRequired is returned to indicate authentication is required +// to proceed. +var ErrAuthRequired = &Error{450, "authorization required"} + +// ErrAuthRejected is returned for invalid authentication. +var ErrAuthRejected = &Error{452, "authorization rejected"} + +// ErrNotAuthenticated is returned when a command is issued that requires +// authentication, but authentication was not provided. +var ErrNotAuthenticated = &Error{480, "authentication required"} blob - 4c249503a10c86d5b80142da1f95f02c833d54c5 blob + 3f5fbb77ebe31a1bb210cdb48e37043595f04711 --- server/server.go +++ server/server.go @@ -13,58 +13,7 @@ import ( "github.com/dustin/go-nntp" ) - -// An NNTPError is a coded NNTP error message. -type NNTPError struct { - Code int - Msg string -} - -// ErrNoSuchGroup is returned for a request for a group that can't be found. -var ErrNoSuchGroup = &NNTPError{411, "No such newsgroup"} - -// ErrNoSuchGroup is returned for a request that requires a current -// group when none has been selected. -var ErrNoGroupSelected = &NNTPError{412, "No newsgroup selected"} - -// ErrInvalidMessageID is returned when a message is requested that can't be found. -var ErrInvalidMessageID = &NNTPError{430, "No article with that message-id"} - -// ErrInvalidArticleNumber is returned when an article is requested that can't be found. -var ErrInvalidArticleNumber = &NNTPError{423, "No article with that number"} - -// ErrNoCurrentArticle is returned when a command is executed that -// requires a current article when one has not been selected. -var ErrNoCurrentArticle = &NNTPError{420, "Current article number is invalid"} - -// ErrUnknownCommand is returned for unknown comands. -var ErrUnknownCommand = &NNTPError{500, "Unknown command"} - -// ErrSyntax is returned when a command can't be parsed. -var ErrSyntax = &NNTPError{501, "not supported, or syntax error"} - -// ErrPostingNotPermitted is returned as the response to an attempt to -// post an article where posting is not permitted. -var ErrPostingNotPermitted = &NNTPError{440, "Posting not permitted"} - -// ErrPostingFailed is returned when an attempt to post an article fails. -var ErrPostingFailed = &NNTPError{441, "posting failed"} - -// ErrNotWanted is returned when an attempt to post an article is -// rejected due the server not wanting the article. -var ErrNotWanted = &NNTPError{435, "Article not wanted"} - -// ErrAuthRequired is returned to indicate authentication is required -// to proceed. -var ErrAuthRequired = &NNTPError{450, "authorization required"} - -// ErrAuthRejected is returned for invalid authentication. -var ErrAuthRejected = &NNTPError{452, "authorization rejected"} -// ErrNotAuthenticated is returned when a command is issued that requires -// authentication, but authentication was not provided. -var ErrNotAuthenticated = &NNTPError{480, "authentication required"} - // Handler is a low-level protocol handler type Handler func(args []string, s *session, c *textproto.Conn) error @@ -129,10 +78,6 @@ func NewServer(backend Backend) *Server { return &rv } -func (e *NNTPError) Error() string { - return fmt.Sprintf("%d %s", e.Code, e.Msg) -} - func (s *session) dispatchCommand(cmd string, args []string, c *textproto.Conn) (err error) { @@ -161,7 +106,7 @@ func (s *Server) Process(nc net.Conn) { for { l, err := c.ReadLine() if err != nil { - log.Printf("Error reading from client, dropping conn: %v", err) + log.Printf("nntp.Error reading from client, dropping conn: %v", err) return } cmd := strings.Split(l, " ") @@ -172,16 +117,15 @@ func (s *Server) Process(nc net.Conn) { } err = sess.dispatchCommand(cmd[0], args, c) if err != nil { - _, isNNTPError := err.(*NNTPError) + _, ok := err.(*nntp.Error) switch { case err == io.EOF: // Drop this connection silently. They hung up return - case isNNTPError: + case ok: c.PrintfLine(err.Error()) default: - log.Printf("Error dispatching command, dropping conn: %v", - err) + log.Printf("nntp.Error dispatching command, dropping conn: %v", err) return } } @@ -221,7 +165,7 @@ func parseRange(spec string) (low, high int64) { func handleOver(args []string, s *session, c *textproto.Conn) error { if s.group == nil { - return ErrNoGroupSelected + return nntp.ErrNoGroupSelected } from, to := parseRange(args[0]) articles, err := s.backend.GetArticles(s.group, from, to) @@ -297,7 +241,7 @@ func handleNewGroups(args []string, s *session, c *tex } func handleDefault(args []string, s *session, c *textproto.Conn) error { - return ErrUnknownCommand + return nntp.ErrUnknownCommand } func handleQuit(args []string, s *session, c *textproto.Conn) error { @@ -307,7 +251,7 @@ func handleQuit(args []string, s *session, c *textprot func handleGroup(args []string, s *session, c *textproto.Conn) error { if len(args) < 1 { - return ErrNoSuchGroup + return nntp.ErrNoSuchGroup } group, err := s.backend.GetGroup(args[0]) @@ -324,7 +268,7 @@ func handleGroup(args []string, s *session, c *textpro func (s *session) getArticle(args []string) (*nntp.Article, error) { if s.group == nil { - return nil, ErrNoGroupSelected + return nil, nntp.ErrNoGroupSelected } return s.backend.GetArticle(s.group, args[0]) } @@ -469,7 +413,7 @@ func handleArticle(args []string, s *session, c *textp func handlePost(args []string, s *session, c *textproto.Conn) error { if !s.backend.AllowPost() { - return ErrPostingNotPermitted + return nntp.ErrPostingNotPermitted } c.PrintfLine("340 Go ahead") @@ -477,7 +421,7 @@ func handlePost(args []string, s *session, c *textprot var article nntp.Article article.Header, err = c.ReadMIMEHeader() if err != nil { - return ErrPostingFailed + return nntp.ErrPostingFailed } article.Body = c.DotReader() err = s.backend.Post(&article) @@ -490,20 +434,20 @@ func handlePost(args []string, s *session, c *textprot func handleIHave(args []string, s *session, c *textproto.Conn) error { if !s.backend.AllowPost() { - return ErrNotWanted + return nntp.ErrNotWanted } // XXX: See if we have it. article, err := s.backend.GetArticle(nil, args[0]) if article != nil { - return ErrNotWanted + return nntp.ErrNotWanted } c.PrintfLine("335 send it") article = &nntp.Article{} article.Header, err = c.ReadMIMEHeader() if err != nil { - return ErrPostingFailed + return nntp.ErrPostingFailed } article.Body = c.DotReader() err = s.backend.Post(article) @@ -542,10 +486,10 @@ func handleMode(args []string, s *session, c *textprot func handleAuthInfo(args []string, s *session, c *textproto.Conn) error { if len(args) < 2 { - return ErrSyntax + return nntp.ErrSyntax } if strings.ToLower(args[0]) != "user" { - return ErrSyntax + return nntp.ErrSyntax } if s.backend.Authorized() { @@ -556,7 +500,7 @@ func handleAuthInfo(args []string, s *session, c *text a, err := c.ReadLine() parts := strings.SplitN(a, " ", 3) if strings.ToLower(parts[0]) != "authinfo" || strings.ToLower(parts[1]) != "pass" { - return ErrSyntax + return nntp.ErrSyntax } b, err := s.backend.Authenticate(args[1], parts[2]) if err == nil {