title | layout | wip | copyrights | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
So You're Implementing IRC Software? |
default |
true |
|
{% include copyrights.html %}
This document's going to be updated as we find more pitfalls.
If you think of a new one, or find an error with this document, please open an issue.
IRC is touted as being one of the easiest protocols to implement. Just send NICK
and USER
and a few JOIN
commands and you're done, right?
Well, yes! But also, no. There are some common pitfalls, fragile patterns, and bad habits that IRC software tends to fall into. Here, we outline those and try to describe why and how to avoid them. We've also written up some nice-to-haves that are relatively common, but not really described anywhere.
Message parameters normally can't contain spaces (since parameters are separated by spaces). But if the last parameter on a message is prefixed by a colon (":"
), then it's called a 'trailing' parameter and it can include space characters.
Many clients and libraries split parameters into two sections: Normal parameters, and the Trailing parameter. You should NEVER DO THIS, EVER. The 'trailing' parameter is just a normal parameter, and MUST ALWAYS be just added on to the list of parameters.
Here's how your IRC Message class should expose parameters to your IRC software, in a C-like language:
IRCMessage {
[]string Parameters
// there is NO separate TrailingParameter variable
}
The list of parameters that your IRC software uses and passes around should contain every normal parameter, and also the 'trailing' parameter. Treating the 'trailing' parameter as special or separate in any other way means that you WILL create broken, fragile software.
- "Various command parsers do not handle a colon before the last parameter"
- "PR: Rework MODE/RPL_CHANMODEIS handling for trailing args"
- "PR: Moving away from Event.Trailing"
- "PR: strip colon, if present, from ACCOUNT value"
- "PR: Remove Trailing param"
You can test your message parser against the parser-tests repo. Specifically the msg-split
test file, which includes tests for this specific issue.
A good practice for IRC software is to parse incoming IRC lines into a data structure, and then use that data structure everywhere. If your software, instead, just passes the raw line and then matches bytes and strings from the line, you're probably going to run into this issue.
The gist is that if you enable a capability like server-time
, then ANY line from the server can contain a @time
tag. You need to make sure that every command handler including CAP
, AUTHENTICATE
, JOIN
, PRIVMSG
, etc, can handle having a tag on the message. Along the same lines, any message can contain a :server.example.com
prefix.