aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2024-12-08 10:32:29 +0800
committerRunxi Yu <me@runxiyu.org>2024-12-08 10:32:29 +0800
commit6bbe00f0c7aae6c468b1a3e12983a74a170e92b8 (patch)
tree970b43288cdbb8c05cf5df2aaaf79e94019d13af
parentRemove another unnecessary anonymous function (diff)
downloadmeseircd-6bbe00f0c7aae6c468b1a3e12983a74a170e92b8.tar.gz
meseircd-6bbe00f0c7aae6c468b1a3e12983a74a170e92b8.tar.zst
meseircd-6bbe00f0c7aae6c468b1a3e12983a74a170e92b8.zip
Handle send failures
-rw-r--r--clients.go10
-rw-r--r--cmd.go2
-rw-r--r--cmd_cap.go16
-rw-r--r--cmd_nick.go25
-rw-r--r--cmd_ping.go8
-rw-r--r--cmd_user.go17
-rw-r--r--errors.go2
-rw-r--r--main.go34
8 files changed, 75 insertions, 39 deletions
diff --git a/clients.go b/clients.go
index 0588184..07dc532 100644
--- a/clients.go
+++ b/clients.go
@@ -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
diff --git a/cmd.go b/cmd.go
index 6cdcaa0..badd5b7 100644
--- a/cmd.go
+++ b/cmd.go
@@ -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? */
diff --git a/cmd_cap.go b/cmd_cap.go
index a984c07..328bce6 100644
--- a/cmd_cap.go
+++ b/cmd_cap.go
@@ -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
}
diff --git a/errors.go b/errors.go
index 8ce604a..7c0a037 100644
--- a/errors.go
+++ b/errors.go
@@ -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")
)
diff --git a/main.go b/main.go
index 96b9b02..bd96e5d 100644
--- a/main.go
+++ b/main.go
@@ -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
}
}
}