Netfraction Hub Architecture

A key goal in the architecture of the hub is to make the overall code structure easy to understand and extend. To this end, the source code is broken into quite a number of subfolders and attempts to use descriptive naming conventions for source files and variables, rather than the flat structure and sometimes arcane naming present in some other hubs.

The core of the hub is in the Network namespace. The ConnectionManager handles all user connections and is the point through which all protocol messages are handled before being passed to the lower-level networking code. Users are referred to as a Client, but most of the code operates on the concept of a Node, which may be either a Client, a Bot, or the Hub itself.

A potential fallacy of the design at present is that the ConnectionManager refers specifically to ADC BASE protocol messages. This was not the original intention, but it has made development of the hub easier.

Network Protocol

The Network.Protocol namespace defines a number of generic classes for Protocol Features, Protocol Messages, Action Handlers and Message Factory's.

ADC is comprised of a set of Protocol Features. In ADC/1.0 the core feature is named BASE. Extensions are added view new Protocol Features which may be used by hubs, clients, or both. The usage of these features is determined during protocol negotiation. The most common extensions include TIGR (Tiger hashing) and BZIP (BZip2 compression). The hub supports BASE and TIGR via classes which inherit the ProtocolFeature base class.

Each ProtocolFeature contains a FeatureActions struct declaring which messages it can handle. To actually handle a message it must also add a class inheriting ProtocolMessageActionHandler to the ProtocolFeature's ProtocolMessageHandlers dictionary collection, which registers which FeatureAction the ActionHandler is intended for.

When the hub receives a message it iterates through the ProtocolFeatures registered in LocalMachine.Hub. If the ProtocolFeature's FeatureActions include the type of message which was received, then the ProtocolFeature.HandleFeatureMessage() function is called, which in turn checks if a ProtocolMessageActionHandler is registered, and if so, passes the ProtocolMessage along to that handler.

For example, ProtocolFeatureBASE, which implements the BASE feature, includes a FeatureAction called ActionINF, which is triggered by and "INF" message. It is declared to be a primary message handler, not an Extension via the ProtocolFeatureAction Attribute. Additionally, in the ProtocolFeatureBASE constructor, a handler for the ActionINF message, the Handler.HandlerINF class, is registered. HandlerINF then deals with the specifics of the INF ProtocolMessage.


The most common security architecture in Direct Connect hubs appears to revolve around levels from 1-10 encompassing normal users, registered users, operators, administrators and owners. Netfraction Hub does not use the 1-10 concept, but instead uses Roles and Identities. Each Identity is a member of a Role. Identity X outranks Identity Y if X's Role is an 'ancestor' of Y's Role. The default status of any permission is Deny, so Allow must specifically be granted. A child Role does not inherit any permissions from it's ancestor, they must be explicitly granted. However, an Identity inherits all the permissions from the Role it is a member of. The permissions set specifically for the Identity override those for it's parent Role. The Role and Identity data are stored in XML files in the settings folder.

Application Settings

Settings are stored in the user's Application Data folder, which on Windows Vista is C:\Users\user\AppData\Roaming\DG Solutions\NetfractionHub, or on Windows XP C:\Documents and Settings\user\Application Data\DG Solutions\NetfractionHub. On Mono the base path is most likely /home/.config/DG Solutions/NetfractionHub/. The key file here is Hub.xml, where the listening IP and port number are defined.


The LocalMachine namespace defines a type of Node called a BotNode which is simply a Node with no socket connection. It is intended that all bots should inherit from this class.

The only bot currently defined is the SecurityBot. A SessionID is also reserved for an OperatorBot, but this is not yet implemented. An interface for creating bots via a Lua extension is planned for the future. At this stage, a bot is created by calling the RegisterBot method from the ConnectionManager constructor. Bots receive chat messages like any other user. They cannot at present do anything like altering a chat message before other users receive it.

The SecurityBot overrides the BotNode's HandleMessage method and uses the ParseMessage function to parse the chat message into a command, if possible, which is then executed. The ParseMessage function defines command messages as being in the format:
// !commandName --toggleParameter -parameter:"value"
A toggleParameter is used for toggling a boolean value, whereas a regular parameter accepts string values. The SecurityBot constructor registers a set of CommandHandlers e.g. the 'kick' command is handled by the BotCommands.Handler.Kick class. The kick command takes the following format:
// !kick -user:"username" -reason:"reason for kicking"
Where 'username' is the NickName of the client to be kicked, and 'reason' is an optional parameter whose value will be broadcast to all users as part of the kick notification. The Kick CommandHandler checks if the user sending the command has the KickIdentity permission, and then uses Security.RoleManager.IsInAncestorTree(roleX, roleY) to check if the command issuer outranks the target user. If these security checks are passed, it performs the kick operation and broadcasts a message to this effect. If it fails, it echos a message to the user attempting the kick, with a reason for failure.

Last edited Mar 3, 2009 at 12:42 AM by darkKlor, version 4


No comments yet.