I'm trying to code my own IRC server. I'm referencing the IRC RFC but it's a little confusing to me. If I were to go strictly off the RFC, I don't think any of the popular clients would work with my server, like mIRC. For example, the RFC says that the server should respond to a successful MODE command one of the following numeric responses:RPL_BANLIST
, RPL_CHANNELMODEIS
, RPL_ENDOFBANLIST
, RPL_UMODEIS
. This would lead me to believe that on a successful user mode change, I'd respond with RPL_UMODEIS, although the RFC doesn't seem to explicitly state so.
But, when I check the source code to another open source IRC server, I see that it responds with a non-numeric command of 'MODE'. It just echos back the MODE command it looks like.
How are you supposed to respond to the MODE command? Is there a better formatted RFC that has a simple command and response chart, or something?
RFC 1459 is famously sparse. It does not tell you everything you need to know to write a server.
In this case, what's missing is the distinction between a MODE
command that queries an existing mode, and a MODE
command that sets a new mode. In the case of a mode query, a client will receive a numeric reply that indicates the existing mode; in the case of altering a mode, a client will not receive a direct numeric reply unless there was an error. However, if the mode was successfully altered, then a client will recieve a MODE
from the server informing it of the change.
So for example, if the client's nick is foo
and it sends:
MODE foo
then this is querying its current usermode - it will expect a RPL_UMODEIS
reply like:
:irc.example.org 221 foo :+i
If the client then sends:
MODE foo :+w
then this is altering its usermode - it will either get a numeric error like ERR_USERSDONTMATCH
or an acknowledgement of the mode change:
:foo!foo@bar.com MODE foo :+w
Note that this acknowledgement is technically not a direct reply to the MODE
- it's the server informing the client of a relevant change in its state, which happens to have been triggered by a client command.
A similar situation exists with channel modes. If a client queries the current channel modes with:
MODE #channel
then it will expect a RPL_CHANNELMODEIS
response containing the current "simple" channel modes, and perhaps a RPL_CREATIONTIME
response giving the channel creation time. If it queries for the current ban list with:
MODE #channel b
then should get zero or more RPL_BANLIST
responses, followed by a RPL_ENDOFBANLIST
.
If instead a client tries to change a channel mode:
MODE #channel :+k zounds
then the direct reply will either be an error reply or nothing; and if the channel mode was actually changed, it will see the MODE
command echoed back. In the latter case the successful MODE
command will also be sent to the other members of the channel - this helps to illustrate that it's not really a direct reply to the initial MODE
command, but an indirect response to it.