Client for negotiating supported clients
This branch adds a client for negotiating which clients can be used with each contact.
Each client has a major version and a minor version. The major version is included in the derivation of group IDs, so changing the major version causes the client to generate a new, distinct set of groups. This is meant for backward-incompatible changes in the client protocol. The minor version is meant for changes that are backward-compatible, i.e. the new version of the client can interoperate with the old and new versions.
Clients register with the ClientVersioningManager at injection time, and when services are started the manager compares the list of registered clients to the list from the previous startup. If the list has changed or this is the first startup, the manager sends an update message to each contact containing the current list of clients. The updates sent to each contact are numbered sequentially. Any update that's delivered after a higher-numbered update from the same contact is ignored.
Each update contains a flag for each client, indicating whether the client is active with respect to the contact receiving the update. The flag is initially lowered. It's raised on receipt of an update from the contact listing the same major version of the client. Raising the flag causes a new update to be sent to the contact. This mechanism allows each side to make the client's groups visible without any messages in those groups being sent before the contact is ready to receive them, which would cause the messages to be dropped and retransmitted.
Closes #237 (closed)