diff options
author | Runxi Yu <me@runxiyu.org> | 2024-12-08 10:32:29 +0800 |
---|---|---|
committer | Runxi Yu <me@runxiyu.org> | 2024-12-08 10:32:29 +0800 |
commit | 6bbe00f0c7aae6c468b1a3e12983a74a170e92b8 (patch) | |
tree | 970b43288cdbb8c05cf5df2aaaf79e94019d13af | |
parent | Remove another unnecessary anonymous function (diff) | |
download | meseircd-6bbe00f0c7aae6c468b1a3e12983a74a170e92b8.tar.gz meseircd-6bbe00f0c7aae6c468b1a3e12983a74a170e92b8.tar.zst meseircd-6bbe00f0c7aae6c468b1a3e12983a74a170e92b8.zip |
Handle send failures
-rw-r--r-- | clients.go | 10 | ||||
-rw-r--r-- | cmd.go | 2 | ||||
-rw-r--r-- | cmd_cap.go | 16 | ||||
-rw-r--r-- | cmd_nick.go | 25 | ||||
-rw-r--r-- | cmd_ping.go | 8 | ||||
-rw-r--r-- | cmd_user.go | 17 | ||||
-rw-r--r-- | errors.go | 2 | ||||
-rw-r--r-- | main.go | 34 |
8 files changed, 75 insertions, 39 deletions
@@ -23,8 +23,6 @@ func (client *Client) Send(msg SMsg) error { return client.SendRaw(msg.ClientSerialize()) } -// Send failures are not returned; broken connections detected and severed on -// the next receive. func (client *Client) SendRaw(s string) error { if client.conn == nil { panic("not implemented") @@ -35,6 +33,7 @@ func (client *Client) SendRaw(s string) error { // TODO: Should shut down the netFd instead but the stdlib // doesn't expose a way to do this. (*client.conn).Close() + return err } return nil } @@ -86,14 +85,15 @@ func NewLocalClient(conn *net.Conn) (*Client, error) { return nil, ErrUIDBusy } -func (client *Client) checkRegistration() { +func (client *Client) checkRegistration() error { if client.State != ClientStatePreRegistration { slog.Error("spurious call to checkRegistration", "client", client) - return // TODO: Return an error? + return ErrCallState } if client.Nick != "*" && client.Ident != "" { - client.Send(MakeMsg(self, RPL_WELCOME, client.Nick, "Welcome")) + return client.Send(MakeMsg(self, RPL_WELCOME, client.Nick, "Welcome")) } + return nil } type ClientState uint8 @@ -1,5 +1,5 @@ package main -var commandHandlers = map[string](func(RMsg, *Client) bool){} +var commandHandlers = map[string](func(RMsg, *Client) error){} /* Maybe we should make command handlers return their values for easier labelled-reply? */ @@ -8,15 +8,21 @@ func init() { commandHandlers["CAP"] = handleClientCap } -func handleClientCap(msg RMsg, client *Client) bool { +func handleClientCap(msg RMsg, client *Client) error { if len(msg.Params) < 1 { - client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "CAP", "Not enough parameters")) - return true + err := client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "CAP", "Not enough parameters")) + if err != nil { + return err + } + return nil } switch strings.ToUpper(msg.Params[0]) { case "LS": - client.Send(MakeMsg(self, "CAP", client.Nick, "LS", "sasl=PLAIN,EXTERNAL")) + err := client.Send(MakeMsg(self, "CAP", client.Nick, "LS", "sasl=PLAIN,EXTERNAL")) + if err != nil { + return err + } case "REQ": } - return true + return nil } diff --git a/cmd_nick.go b/cmd_nick.go index 1c847e5..0d844b8 100644 --- a/cmd_nick.go +++ b/cmd_nick.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log/slog" ) @@ -8,28 +9,36 @@ func init() { commandHandlers["NICK"] = handleClientNick } -func handleClientNick(msg RMsg, client *Client) bool { +func handleClientNick(msg RMsg, client *Client) error { if len(msg.Params) < 1 { - client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "NICK", "Not enough parameters")) - return true + return client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "NICK", "Not enough parameters")) } already, exists := nickToClient.LoadOrStore(msg.Params[0], client) if exists { if already != client { - client.Send(MakeMsg(self, ERR_NICKNAMEINUSE, client.Nick, msg.Params[0], "Nickname is already in use")) + err := client.Send(MakeMsg(self, ERR_NICKNAMEINUSE, client.Nick, msg.Params[0], "Nickname is already in use")) + if err != nil { + return err + } } } else { if client.State == ClientStateRegistered { if !nickToClient.CompareAndDelete(client.Nick, client) { slog.Error("nick inconsistent", "nick", client.Nick, "client", client) - return false + return fmt.Errorf("%w: %v", ErrInconsistent, client) + } + err := client.Send(MakeMsg(client, "NICK", msg.Params[0])) + if err != nil { + return err } - client.Send(MakeMsg(client, "NICK", msg.Params[0])) } client.Nick = msg.Params[0] } if client.State == ClientStatePreRegistration { - client.checkRegistration() + err := client.checkRegistration() + if err != nil { + return err + } } - return true + return nil } diff --git a/cmd_ping.go b/cmd_ping.go index dc7131f..9da4ee9 100644 --- a/cmd_ping.go +++ b/cmd_ping.go @@ -4,11 +4,9 @@ func init() { commandHandlers["PING"] = handleClientPing } -func handleClientPing(msg RMsg, client *Client) bool { +func handleClientPing(msg RMsg, client *Client) error { if len(msg.Params) < 1 { - client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "PING", "Not enough parameters")) - return true + return client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "PING", "Not enough parameters")) } - client.Send(MakeMsg(self, "PONG", self.Name, msg.Params[0])) - return true + return client.Send(MakeMsg(self, "PONG", self.Name, msg.Params[0])) } diff --git a/cmd_user.go b/cmd_user.go index 06fd7a3..4c4c86a 100644 --- a/cmd_user.go +++ b/cmd_user.go @@ -8,19 +8,24 @@ func init() { commandHandlers["USER"] = handleClientUser } -func handleClientUser(msg RMsg, client *Client) bool { +func handleClientUser(msg RMsg, client *Client) error { if len(msg.Params) < 4 { - client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "USER", "Not enough parameters")) - return true + return client.Send(MakeMsg(self, ERR_NEEDMOREPARAMS, "USER", "Not enough parameters")) } switch client.State { case ClientStatePreRegistration: client.Ident = "~" + msg.Params[0] client.Gecos = msg.Params[3] - client.checkRegistration() + err := client.checkRegistration() + if err != nil { + return err + } case ClientStateRegistered: - client.Send(MakeMsg(self, ERR_ALREADYREGISTERED, client.Nick, "You may not reregister")) + err := client.Send(MakeMsg(self, ERR_ALREADYREGISTERED, client.Nick, "You may not reregister")) + if err != nil { + return err + } case ClientStateRemote: } - return true + return nil } @@ -13,4 +13,6 @@ var ( ErrNotConnectedServer = errors.New("not connected server") ErrSendToSelf = errors.New("attempt to send message to self") ErrUIDBusy = errors.New("too many busy uids") + ErrInconsistent = errors.New("inconsistent state") + ErrCallState = errors.New("invalid call state") ) @@ -65,28 +65,44 @@ messageLoop: case ErrEmptyMessage: continue messageLoop case ErrIllegalByte: - client.Send(MakeMsg(self, "ERROR", err.Error())) - break messageLoop + err := client.Send(MakeMsg(self, "ERROR", err.Error())) + if err != nil { + slog.Error("error while reporting illegal byte", "error", err, "client", client) + return + } + return case ErrTagsTooLong: fallthrough case ErrBodyTooLong: - client.Send(MakeMsg(self, ERR_INPUTTOOLONG, err.Error())) + err := client.Send(MakeMsg(self, ERR_INPUTTOOLONG, err.Error())) + if err != nil { + slog.Error("error while reporting body too long", "error", err, "client", client) + return + } continue messageLoop default: - client.Send(MakeMsg(self, "ERROR", err.Error())) - break messageLoop + err := client.Send(MakeMsg(self, "ERROR", err.Error())) + if err != nil { + slog.Error("error while reporting parser error", "error", err, "client", client) + } + return } } handler, ok := commandHandlers[msg.Command] if !ok { - client.Send(MakeMsg(self, ERR_UNKNOWNCOMMAND, msg.Command, "Unknown command")) + err := client.Send(MakeMsg(self, ERR_UNKNOWNCOMMAND, msg.Command, "Unknown command")) + if err != nil { + slog.Error("error while reporting unknown command", "error", err, "client", client) + return + } continue } - cont := handler(msg, client) - if !cont { - break + err = handler(msg, client) + if err != nil { + slog.Error("handler error", "error", err, "client", client) + return } } } |