BAF's Ramblings » #bafirc

BAFIRC: Tonight's Plan

October 5, 2010bafirc

This post is mostly a short plan to myself, but I don’t think I have any pressing school work that needs to be done tonight. Being so, I’d like to get some more code going on BAFIRC.

I plan to finish the IRC connection layer and write a short test to play with it a bit. I will probably borrow a bit from the cbots IRC layer, at least as far as the queue management and connection loop go, just because it’s solid code that’s seen several iterations and works well already. That’s all I’m aiming for tonight though, I don’t want to spend too much time on it. After that, I need to plan out the DCC and CTCP support modules, and begin figuring out the plugin system and API for that. After that, I can begin building the core.

Look for my nightly update/status report later!

BAFIRC: IRC Layer Progress

October 5, 2010bafirc

I spent a chunk of time working on my IRC layer some more tonight. I did the busy work of ensuring my list of commands and replies was fairly exhaustive according to the RFCs, and implemented static functions for almost every possible command/parameter combination allowed by the RFC. This was not strictly necessary, just more of syntactic sugar for use in plugins/etc, but it makes the interface a lot nicer - i.e., rather than calling ‘new IrcMessage(IrcCommand.Privmsg, “#channel”, “hi”);’ you can call ‘IrcMessage.Privmsg(“#channel”, “hi”);’). This makes it easier to use without any knowledge of the RFC, and less error prone.

After completing that, I moved on to begin laying the framework for the IrcConnection class. I did a rough layout of the class and its members and methods, and began implementing a little. The guts of the connection management thread still need to be filled in, as do the relevant chunks of code to handle the management thread itself. Other than that, I wrote the event management system. So far, there are only four events (remember, this is a very thin layer above the IRC protocol) - ConnectionStateChanged, MessageReceived, MessageSent, and MessageSending. Note the difference between the sent and sending events - MessageSent is fired after a message is queued for sending, whereas MessageSending is fired before the message is queued, giving plugins the chance to review the message, possibly editing it or throwing it away all together. This may sound risky from a security standpoint, but remember, plugins should already be trusted by you anyway. They’re compiled code running on your machine, and have access to all messages sent and received anyway.

Hopefully I will have time tomorrow night to finish implementing what needs to be done on the connection class. It will support SSL and binding to a particular local IP, and will have configurable queuing settings. I haven’t figured out what these configurations will consist of, but likely will involve a flag to turn on or off queuing, and some values to specify what the maximum sustained rate of sending and burst rates are. I’m thinking number of messages (or bytes?) per second will be the values. It will track how much you are sending, and once you exceed the burst rate, it will kick in and throttle messages back to the sustained rate, until the queue is empty (and perhaps, a configurable penalty time has passed).

That’s all for now! Once I’ve implemented my IRC layer (and implementing, or at least stubbing out, the CTCP and DCC layers) and tested it a bunch, I will begin building the plugin system, implementing the pieces required for dealing with IRC.

BAFIRC: Design Architecture

October 4, 2010bafirc

I’ve made a very important design decision in regards to BAFIRC and how processing of IRC actions (and, really, most anything else) will be handled. Perhaps some of you are familiar with *nix, and how, generally, everything is treated as a file. I’m adopting a similar approach - everything is a plugin.

Handling user registration and server ping/pongs? A plugin. Handling CTCP requests and replies? A plugin. Handling DCC? A plugin. Organizing messages into their respective user/channel buffers? You guessed it, a plugin.

I will implement a basic API that allows the plugins to interact with and control most anything in the core/client. Beyond that, a plugin will handle the rest. This allows me to keep everything very modular, and have no problems with figuring out where certain control logic fits in. The various layers in the code (such as the IRC layer) will be very minimal, and anything beyond the most basic of functionality will be implemented in a plugin.

I have, on paper, sketched out how some various pieces will look like, but nothing has been set in stone. I will implement my base plugin system using MEF (which, if I am not mistaken, was added to .NET as of 4.0). Plugins will be able to act on the core or on the client. There will be a basic API that will be the same whether the plugin is on the core or on the client, and there will be specific API extensions for core- and client- specific plugins. An example of a core-specific plugin would be the logging plugin, whereas an example of a client-specific plugin would be a /sysinfo or /winamp type of deal. It is also conceivable that a plugin could run on both the core and the client, and establish a communication channel between the two.

I have not yet decided how I am going to implement the core/client communications, but I do plan on supporting named channels between the two, so that plugins may talk with themselves, and other similar uses. I may just go with an XML channel, but I need to analyze whether or not this will fit my needs without being too wasteful. It’s an obvious solution for ease in developing clients for different platforms, but there is a bit of overhead, both in the XML itself, and the construction/parsing of it on either end.

DCC will be handled by the core and the client. I will likely support DCC proxying from the core, and for performance sake, support direct connection to the client in some cases. The core will be configurable with a default action, and clients will be able to override this action. I haven’t decided on how the client will be able to do this yet - whether there will be a notion of an ‘active client’ where the most recently used client can either handle or defer it to someone else, or if it will be more of a race, first client to respond gets it. In the case that all clients defer or none respond within a certain timeout (or if no clients are connected), the core performs its default action. Files can be sent from/received to either the core or the client (and transferred to/from core storage), though chats will likely always be proxied through the core.

I may have written down more things than I am remembering right now, but this is all that comes to mind. Perhaps I’ll be able to muster up the time to do some more coding tonight.

BAFIRC: Distracting

October 4, 2010

BAFIRC is too distracting to think about. During class, I was sketching out the architecture of my irc layer, plugins system, and core/client responsibilities. Yes, sketching on plain old analog paper.

I am posting this now from my phone. A more detailed posting with my thoughts will appear shortly, when I am on my laptop, rather than typing on my phone.

BAFIRC: IRC Message Parser

October 4, 2010bafirc

I began working on the IRC layer tonight. Part of that was implementing an IRC message parser.

I tested out the use regular expressions in writing it. I have a fairly complex expression that can capture the values from any RFC-compliant message. Works great!

I put this up against a non-regular expression implementation (from cbots) to benchmark. The non-regex version is roughly two times faster than my new regex version. I am currently debating if I should keep the regular expression parser (which has cleaner looking code, coupled with an ugly expression) or adopt an approach similar to what cbots does (which gives uglier code, but is faster). On my machine, the difference, in practice, is negligible. Regular expression parsing takes 77ms to parse 11000 messages, whereas the same set run through the cbots parser takes 33ms. Performance will be good enough in either case. So it comes down to which implementation I should use, and I’m not sure what I’m going to do.

On a side note, with school and work, it may be a few more nights before I can set aside enough time to make any more notable progress.