IRC: Satanic (mulling over possiblity of true queries)

Talk about pretty much anything here, but DO NOT USE FOR SUPPORT.

Moderator: Supporters

Posts: 4
Joined: Sun Aug 06, 2006 10:46 pm

IRC: Satanic (mulling over possiblity of true queries)

Post by MalcolmCarmen » Sat Jul 28, 2007 3:54 am

(This concerns a central IRC client library idea that appears impossible to implement that has a backstory to it -- if you want the central idea, skip down a bit...)

I'm working on an IRC library and three of the good important parts are more or less finished: parsing (transforming IRC lines into events), tracking (keeping track of user information for later retrieval), and command sending (similarly to the events, this is also object-oriented).

It all began when I wanted to the tracker to use an extended feature that appears to have originated with ircu; WHOX. Basically, it is a regular WHO with more possible parameters/flags. However, it gives you so much control that you can specify the fields you want returned. This means you can do the following:
1. WHO all nicknames like J*m, get ident(user) and nickname
2. WHO all nicknames like R*n, get nickname and hostname

There's a problem already; the replies you get back will match both of the original WHO queries perfectly. That is, if you are *only* listening to WHOX replies, you can mistake the reply for the first query to be the one for the second. Sure, you can use basic logic to determine if it is the reply that you really want, but there are certain cases that are basically impossible to use deduction on (this will be covered later -- it concerns conflicting numeric replies for different commands). I know that the WHOX specification has a trick you can use to avoid this problem entirely, but this is disabled on a major network (GameSurge), and it brings about a good question in its broken form: why can't IRC just be treated as queries, where each command (or a set of query-oriented commands) results in a concrete reply of some sort that we can work with ("this WHOIS failed" or "this is the data in the LINKS reply")

The idea
WHO/WHOIS/NAMES, etc. are all query commands; you send them, and either get back some listing or an error. They're the perfect sort of thing to design code around where you can do something like the following:

Code: Select all

WhoisReply userWhois = performAWhoisOnNickname("Jill");
This one line would result in a WHOIS query being performed on Jill, the code blocking until the server replies, and then returning the result. You can keep track of the outbound queries that you make in a queue so that you know which reply numerics go with which original query. Sounds pretty straightforward.

Nope, it never can be. The problem is that WHOIS (and many other commands) share numeric replies with *other* commands. So, consider this:

Code: Select all

You WHOIS Jill (using that cool sort of query code like above)

The server replies with a single ERR_NOSUCHNICK. 
Now, which does the ERR_NOSUCHNICK reply belong to -- the PRIVMSG or the WHOIS?

I realize that you can use further deduction to deal with this dilemma, but it illustrates a key problem; commands share numerics with other commands, so numeric replies become useless, and you can never decide if a query failed or not. A human won't send outbound commands fast enough to normally run into this problem -- the human can also keep retrying commands based on the situation, although this is less-than-ideal for a bot.

Well, there's an obvious solution that won't work, either:
Turn *every* command into a query. That is, make sure you know all the possible replies for a command, that way you can match the reply to the command that was sent. This theoretically fixes the whole shared-numerics problem quite nicely and allows for even more neat querying abilities.

The monkeywrench thrown into this idea is PRIVMSGs and similar commands. Sure, it has well-defined reply numerics, but they are only for errors. If a PRIVMSG succeeds, you will never know. This breaks the whole send-a-command-wait-for-reply(ies)-to-it model, making it impossible to stack up commands to wait for their replies.

Maybe I am overlooking something that is obvious, but I believe it is essentially impossible to perform queries like that one line of code I provided. Sure, it could be done, but not safely. I believe I will be forced to give up and resort to dangerous guesses for my original issue with the whole WHOX thing, not to mention lack a neat way to pull bans lists and such. Perhaps someone else who's taken up similar endeavors has found a brilliant way to deal with this, or at least a way to minimize potential mixup of numerics!

Former UnrealIRCd head coder
Posts: 23
Joined: Mon Mar 20, 2006 9:24 pm
Location: Hell, On, Earth

Post by Stskeeps » Sat Jul 28, 2007 2:46 pm

Yes, admittedly there's no such thing as proper result tracking, but in most cases you can live without it .. Not sure what you're trying to do, but making a services bot instead might do it better.

Posts: 4
Joined: Sun Aug 06, 2006 10:46 pm

Post by MalcolmCarmen » Sat Jul 28, 2007 11:54 pm

It's just a general-use IRC client library (for java -- good libraries are quite lacking currently). After thinking about it more, it appears you are indeed correct. Luckily, for specific commands such as WHOIS, it is possible to simply allow one to perform the query with a timeout (numeric replies to WHOIS that are shared with other commands will be ignored, causing the timeout to be reached).

It's not ideal, but it allows for easier querying of information without falling into the classic intuitive event-listening.

As for my WHOX problem, I'll be stuck with re-writing the parsing mechanism so that it can make a highly educated guess as to validity of the data it is receiving. I'll have to do that well, since it has the potential of filling the tracking system with garbage information!

I'll hopefully chronicle my journies in a wiki some time in the future for the fun of others to read.