This document describes the functions of a xPL hub on a system using ethernet networking to tie one or more xPL applications or devices toghether on the same computer. All computers running xPL applications must be running a hub (there are a number available for download on the Downloadable Packages page). The hub acts like a "switchboard", allowing all xPL applications on a computer to receive xPL messages from the network.
For network-centric xPL apps (that is, nearly any xPL program that runs on a PC), xPL requires a hub to be running. A hub acts as a single contact point for the network and handles dispatching messages to other xPL programs on a computer. When xPL programs send messages, they broadcast them directly on to the network, the hub plays no role in sending whatsoever.
Every computer running xPL apps must have a hub on it. If there is no hub or the hub is not running, xPL applications may be able to send messages, but will not be able to receive them.
A hub must be a separate program/task from any xPL based application. An xPL application, either directly or via it's framework, should not be responsible for nor try to start a hub if none is detected. If the app were to take on responsibility for starting/monitoring a hub, the hub becomes susceptible to that applications lifecycle and health. Given other xPL apps are going to also depend on the hub, such embedding would put xPL on that computer in jeopardy should anything happen to the app (or apps) that are also trying to manage the hub.
To quote Paul Robinson, "Keep the hub simple and separate".
Hub Technical Description
The primary purpose of a xPL hub is to bind to port 3865, receive xPL messages from the network at that port and redistribute those messages to all xPL applications running on the same computer. A hub must perform the following functions:
- Receive xPL network messages
- Deliver/Rebroadcast those messages to all xPL applications on the same computer
- Discovery of new xPL applications on the computer and adding them to the list of recipients of received xPL messages
- Track known local xPL applications and determine when they have died and remove them from the list of local applications
- The hub is only involved in receiving messages, it is not involved in sending messages whatsoever.
A distinction is to be made between 'applications' and 'xPL devices'. Be aware that a single application may host multiple xPL devices. So each port # may represent multiple xPL devices. And eventhough from a hub perspective each port # respresents a single application, any application could have multiple port # allocated.
When an xPL application starts up, it allocates a network port that it will receive xPL messages on. It then begins broadcasting "heartbeat" xPL messages on to the xPL network that contain the IP address and port # the application is listening.
The hub will "discover" new xPL applications on the local computer (based on the IP address and port # in the heartbeat message), make note of the port # and, from that point on, will forward all received xPL messages to that applications port.
When the hub starts up, the first thing it must do is bind to port 3865 (UDP) and start listening for messages. Unless otherwise instructed not to, the hub should bind this port for all network interfaces on the computer. Whether automatically binding all interfaces or being instructed to bind to specific interfaces, the hub should have a list of IP address representing each interface it is bound to (these are needed to detect local vs. network messages).
Discovery of new xPL applications
When the hub receives a hbeat.app or config.app message, the hub should extract the "remote-ip" value from the message body and compare the IP address with the list of addresses the hub is currently bound to for the local computer. If the address does not match any local addresses, the packet moves on to the delivery/rebroadcast step.
If the message is a local heartbeat message, the "port" value is extracted from the heartbeat message. Each xPL application on a computer will have a unique port # that it will receives xPL messages on. There is a one-to-one relationship between an application and a port the application receives xPL messages on. The hub consults it's list of known applications using the port # as the key. If it find an existing application with this port #, it simply updates a timestamp indicating when the hub last heard from the application. Then the packet moves on to the delivery/rebroadcast step.
If the application/port is not found, a new xPL application has been "discovered". The application/port is added to the hubs internal list of clients/applications along with a timestamp used to track when the hub last heard from the application. In addition, the "interval" value is extracted from the heartbeat message and that value is stored with the applications other information (a typical application entry in a hubs client list includes the port #, the interval and a timestamp indicating when the hub last heard from the application/client).
The packet then moves to the delivery/rebroadcast step.
Track local xPL applications lifecycle
As mentioned in the section on discovery, everytime a heartbeat (hbeat.app or config.app) is received by the hub and the hub confirms the message is from the same computer the hub is on, an internal "last heard from" timestamp for that specific hub client (i.e. port) is updated before the packet is rebroadcast.
At an interval of 1 minute, the hub should review the lists of clients to compare the elapsed time since the hub has last heard activity on the client to the applications heartbeat interval (set and reset from each received hbeat.app or config.app from that client). The heartbeat interval is always specified in minutes and a protocol "standard" minimum of 5 minutes.
If the hub has not heard any heartbeat activity (config.app or hbeat.app) from the client in (interval * 2) + 1 minutes, it should assume the client has died. The clients information is then removed from the hubs internal list of clients and the hub will stop rebroadcasting to that clients port.
Keep in mind a single client port may in fact be connected to (or be "hosting") several xPL devices. So when you are looking for hbeat.app or config.app, you are looking only for heartbeat activity of anything using that port. Don't filter by the source/target info of messages, simply look for config/hbeat.app messages. You should update the interval each time you get a message (not just at initial client discovery) as intervals can change (via configuration) as well as when hosting multiple xPL Devices on the same client, without getting needlessly complicated, you can't otherwise know which interval is related to which device on a clients port. One effective way is to compare each interval you receive against the current "interval" value you've set for the client and if the "new" one is larger than the installed/current one, then it becomes the new/current one.
Rebroadcasting/Delivery of xPL messages packets
All received xPL messages are then sent to each known client/application the hub is aware of. There is no filtering of messages -- a blind redistribution of messages is required. For example, the hub MUST NOT suppress sending a message it received from a particular client back to that client. The hub must be transparent. In fact, in the device discovery process and application startup, the applications reception of it's own heartbeat message is important as it signifies the application has confirmed there is a working xPL hub on the computer.
Hub Author Notes
Hubs should be designed to be as simple and stable as possible. Failure of the hub will result in the all xPL apps running on a computer to be unable to hear each other or the rest of the network, As such the hub program needs to be written in as "safe" a manor as possible (do all possible exception checking, make sure you are using the right APIs in the right way and that there are no shortcuts, insure code is written with no assumptions and as defensively as possible, etc).
Even the best written programs can (and usually do) have bugs, it's important that the hub has some separate supervisory process that insures the hub is running and when it detects the hub has stopped, restarts the hub immediately (optionally logging the problem so that eventually, the cause of the failure can be diagnosed).
Ideally, the supervisory role would be played by a standard system mechanism. For example, under windows, the hub could be installed as a service and be set such that the windows service manager will automatically restart the hub if it dies. Under linux, this would have to be done by an additional program that launched the hub and then watches it or instead of a program, with scripts. Similar solutions exist in other operating systems.
When a supervisory program needs to be used (for systems that do not provide their own), it's important to keep that program as short and simple as possible. For something like unix-y based systems, this could be a simple program that just forks off the hub, then waits for the forked process to die and forks again (probably 10 lines of C code).
Between a short, simple, stable supervisor and a responsibly written hub, there should be sufficient redundancy and failure traps for all but the most disastrous cases.
Hubs must not be deployed as part of an xPL application. If multiple applications are installed on a computer and each one installs a hub, chaos could reign. And since there are multiple xPL application frameworks, there is no good way for them to all agree on a "check and if missing, install a hub" method.
The user of the xPL application should be made aware, in notes about the application and even on the download page for the application, that an xPL hub is required and if they don't have one, they should be provided a link to a webpage listing hubs for different platforms (maintained on the xPL website).
Separate Hub impact on xPL frameworks and applications
xPL applications and frameworks must not provide any sort of hub service, at least not automatically. There can, of course, be code for a hub in a framework, but it should not be run automatically as any part of normal xPL application startup without some special/explicit setting to do so.
An xPL application should not come bundled with hub -- either as part of the application or as a bundled, separate hub install. Hubs can evolve and the user should be directed to a webpage of hubs instead of packaging what may become an obsolete program. Additionally, this helps to keep this whole issue of separate hubs clear in the mind of the user (one consistent message).
Application Startup and xPL Hub interaction
In order for an xPL application to have meaningful use of the xPL protocol on a computer, there must be a hub running. If there is none, the application may be able to send xPL messages, but will not be able to receive them. Additionally, when a hub is running, the hub has to hear from an application sending messages before it knows the application exists and registers it to receive messages.
Keep in mind that depending on how applications are started, it is possible the xPL application will start before the hub is up and running. Until the hub is noticed, the application really cannot do a lot, so determining that the hub is active and working is a critical detail.
Here is an outline of how an xPL based application (or more likely, the underlying framework) should handle hub detection at startup:
Upon startup, the xPL application (or more likely, it's framework) needs to start sending standard xPL heartbeat messages. These messages can be of the schema class "hbeat" or "config" -- whichever is appropriate to the xPL device.
The app should send out the heartbeat message fairly quickly. That shouldn't be any faster than every 3 seconds and likely no longer than every 30 seconds. The recommended default is every 3 seconds. This is distinctly different from the normal hbeat (usually every 5 minutes or so) and config (usually every minute) sending rate. The idea with this rate is that we are looking to notice a hub being active as quickly as possible to speed app startup.
The "every 3 second" sending rate terminates on one of two conditions:
1) The application receives one of it's own hbeat messages. This is only possible when the hub sees the message (which only happens if the hub is running and listening), adds the application to it's list of clients and echoes the message back. It's important that you check the remote-ip and port parameter to confirm the message really is from yourself. It's possible, though uncommon, that in the early stages of startup, there may be more than one device/app with the same source identifier (pre-configuration, for example).
Once the echo is heard, the application is ready to go and the heartbeat rate can go back to normal (every minute for config, every few minutes for hbeat).
2) A 2 minute timers expires without receiving an echo (2 minutes is a recomended rate -- you could increase or descres this a bit). At this point, the hub is still not ready and may never be. Because hope springs eternal, hbeat/config messages are still sent out at an accelerated rate, but after that first 2 minutes, the rate should drop to once every 30 seconds (another recommended value that could be increased/reduced if needed) and remain there indefinitely until the hub finally answers or the application is terminated. If possible, it would be wise to alert the user (if appropriate) that there may be a problem after 1 or 2 minutes with no response so they can be aware and take action (like starting the hub). If appropriate/possible, it may also be wise to log a message to the system event log and/or console as well (for future diagnostics).