BAF's Ramblings » #bafirc

BAFIRC Plugins: Mostly Done?

November 25, 2010bafirc

So, after a lengthy hiatus on BAFIRC, I finally got around to doing some more work on it tonight. I worked more on the plugin system - implementing plugin enumeration using the composition provided by MEF. I’m not going to worry about the issues I brought up in the last post or two, rather, I’ll just see what happens as I move along. I also have implemented a permissions system with the plugins, which is probably overkill for the use BAFIRC will see, but it doesn’t hurt.

I’m somewhat happy with the path the plugins have taken. I also began to work on an IRC management plugin - a plugin wrapper for all of my base IRC things which manages multiple connections, reconnection, identities, etc. It has a slew of permissions to allow other plugins to interact on different levels. Once I’ve finished implementing that, I can go ahead and wrap a GUI around it and have it work. Or, create my own bot out of it.

I’ve been considering making a bot using all of this base code as well. One interesting approach to take would be to make the GUI a plugin itself, and then have the main BAFIRC executable just load plugins - and only load the GUI when it’s being used as an app (and on the end machine). This would let me do fancy things like conceivably have different UI implementations as well as do crazy things like inject the UI into a running bot. The bot could take advantage of the bouncer architecture as well - running all of the useful plugins in the “client.” This allows me to then ‘restart’ the client whenever necessary to unload/reload plugins, and not have the bot drop offline. Same idea with using it as an IRC client as well. This way, only your core plugins (which are less likely to change often) will require a total restart/reconnection.

Anyway, enough rambling for tonight. Still loaded to the brim with school work, so progress may still be slow yet for a few more weeks. Happy Thanksgiving!

BAFIRC Plugins: More Thoughts

October 19, 2010bafirc

I didn’t have much free time tonight, so I didn’t write any new code for BAFIRC, however, I did sit down with a pen and paper and think through more specific details of how the plugin system will work, with respect to loading plugins.

The list of imports provided by MEF will be used as a list of available plugins. This isn’t exactly the way MEF was designed to be used (from what I can gather), but it is an acceptable use case. We can look at all available plugins along with their metadata, and determine which ones to load. They will automatically be loaded and instantiated once we try to access the value; so this is fully automated. [Note: I am looking at the underlying APIs, most notably the catalogs and related functions. I may be able to create my own implementation that is similar to CompositionContainer, which will allow me to view types and such. I am undecided as to how detailed of data I need in order to display to the user — i.e., do I want to know the filename? fully qualified class name? trust the name reported in the metadata? what about duplicates? These issues still need to be thought out. The more I think about it, the more I think that it is a good idea to enumerate all the pieces myself and to build my own metadata.].

Any time the imports are satisfied, I can refresh my list of available plugins, and load any unloaded plugins that are trusted, have the same permissions trusted as they are requesting, and are unloaded. Once I take an instance, I store that in a separate loaded plugins area for future reference. Unloaded plugins only have their metadata stored - therefore the user can authorize and load the plugin at will. Plugins can either be loaded one time, or set for auto load (with auto loading caching the permissions granted. If the plugin changes to require more permissions, it will be put into another list, for the user to re-authorized).

MEF requires a different fundamental thinking of the plugin system. MEF composes using ‘parts’ - where one dll may contain many ‘parts.’ For our purposes, a plugin is one part, so one dll may, in fact, contain many different ‘plugins.’ This is mostly a semantics issue that may need more investigation as well - I’m not sure. I think that for the most part, it won’t matter much. The only difficulty will be in identifying what file each piece comes from, should the information be displayed to the user.

Another thing to note is that, due to the nature of Assembly loading in C#, once I load a plugin I cannot unload it without restarting the app. This issue can be ameliorated by creating a separate AppDomin and marshalling between the domains for all plugin interaction. This will cause a performance hit, however, so it may not be worth it.

BAFIRC Plugins

October 17, 2010bafirc

I was working some more on BAFIRC tonight, most notably, on the plugin system. I am going to be using MEF as a basis for my system.

The fundamental idea is that almost everything will be a plugin. There are still some unresolved issues that I need to think out, mainly in dealing with the ability to unload/reload plugins at runtime, but I can leave these features disabled until I’ve worked out what exactly will be happening.

Plugins themselves shall implement the IPlugin interface, which currently just defines an Initialize function that allows the pluginmanager to pass in a management object. This management object will know certain things about the plugin (and, therefore, a new one will be created for each plugin loaded) - including what permissions the plugin has been granted. The plugin is also tagged with an attribute, defining the plugin’s name, description, permissions requested, and some information about an optional interface, if it provides one (more on this shortly). This attribute makes up the metadata as used by the MEF system.

The permissions system is simply a list of permission names (along with a friendly name and description, to be shown to the user, and a trust level, declaring how ‘dangerous’ that permission is). Plugins that provide an interface can also provide a list of permissions that they export, and plugins that need permissions reference them by name in their metadata. The idea is that there will be an interface abstraction that takes into account the permissions granted to it, and can then throw exceptions or ignore certain actions that have not been authorized. There will be some sort of UI where the user will see all permissions required by a plugin and then be able to authorize or deny them to the plugin.

A plugin can also provide an interface, such that other plugins can interface with it. In this capacity, they also define permissions that can be used to restrict how other plugins can do things. An interface type is provided (which is just a C# interface that creates the external view of that plugin). Plugins which provide an interface should also implement another interface, IPluginInterfaceProvider<InterfaceType>, which allow functions to be implemented that return a list of exported permissions, and for an interface to be returned (given a set of granted permissions). The plugin should internally implement a class that fulfills their interface (taking into account permissions granted, if applicable) and then return copies whenever asked.

The plugin’s view to the outside world is just their individual plugin manager access layer. From this layer, they will be able to perform tasks such as gaining an interface to another plugin (from the GetInterface<T>() method). Permissions are tracked outside the scope of the plugin, within the interfaces.

I’ve implemented a good chunk of this already, what remains mostly pertains to the plugin manager access layer and the permission tracking. I have a few other kinks to work out as well, as mentioned above.

Once this system is done, I will write my first substantial plugin - one that manages IRC connections. Connections will be split up into ‘networks’ which then track their own channels, users, etc. This will be the basis for much of the other plugin functionality, so I’m sure the plugin manager will see some refactoring and tweaking while writing this.

BAFIRC Tweaks

October 15, 2010

I was reading a random article on the minor threading differences in .NET 4.0, and learned that Thread.Interrupt (what BAFIRC was using to kill its threads) was just as horrid as Thread.Abort. .NET 4 adds new cancellation methods which make it quite easy to enable your thread to be cleanly signaled to exit, so I went ahead and did some minor refactoring to fix the threading model used by the connection class.

Tomorrow, if I end up having enough free time around all the other crap I need to get done, I will lay down some new code. Right now, I am torn as to where the network/channel tracking will fit in. Part of me wants to use a plugin to manage the channels, which I am thinking I will do, but I need to figure out how exactly I want this interaction to work.

I also need to lay down the threading system. Using MEF of course, I will lay down a basic plugin model that I have in my mind and see how that works out.

BAFIRC

October 13, 2010bafirc

Yeah, it has been a few days since I have made much progress with BAFIRC. I am hoping to be able to implement something useful for it tonight. I still am not totally sure on how I want to lay out my plugin system, so I may just work on fleshing out the DCC code a little more. Either that, or spend some time considering 005 i-support or a different, seemingly more up to date CTCP spec that Sevalecan linked me to.

Anyway, that’s about it. I just felt like writing a blog post, so I did so from my phone.