Hybrid Chat Monstrosity

This project probably won’t take shape for quite some time, but I wanted to get down the basic ideas for it now, while I’m thinking about them. And I figured, why not here, where others can chime in? I’m certain there are plethoras of things I’m overlooking that will make this more tricky to actually implement than I currently believe, but I also think it’ll be worth having in the end, so I’d like to at least try to resolve them. Also, maybe something like this already exists, and I just haven’t been able to find it. Anyway, here goes.

While spending some time on IRC (something I was getting back into after a few years of being away from it), a visitor started talking about features they missed from newer protocols. The conversation that followed was … less than productive, we’ll say … but once the dust settled, it left me wondering how I’d go about bringing those features to the community server the conversation took place on at the time. Various bridges either already exist, or are simple to construct, to allow using (for example) XMPP/Jingle clients to talk to IRC servers, or IRC clients to talk to XMPP/Jingle servers. But those bridges leave out numerous features of the protocols they bridge (often resorting to lowest common denominator), and require an extra piece of software be running, along with all the other drawbacks of proxy server interfaces. Even ZNC, the leading attempt to extend IRC’s feature set to include more modern capabilities, is itself a proxy (the specialized sort known as a bouncer). What I really wanted to see was a single server that spoke both protocols.

Here, too, there are a couple of options. Each revolves around a plugin of some sort or another that basically glues the secondary protocol onto the internal workings of the server itself, which is only actually designed to handle one of them. This works, in many cases, but the overall architectural differences between protocols, and between the servers designed to support them, make this approach just as hacky and incomplete as separate gateway/bouncer/proxy servers. Things will be left out, and users connecting through the plugin will have a limited experience compared to connecting to a network that speaks their protocol natively. So that further refined my goal – I wanted a server that spoke both protocols natively, and handled things internally in a way that allowed both to provide the full spectrum of their feature sets, without compromise. (And if I could emulate the features present in one but missing in the other in a clean way, so much the better.)

Not having found any such server, I set out to gain a solid enough understanding of the protocols to properly design such a project. I’m currently in the early stages of this process, so I fully expect a number of my design decisions to need changing as I learn more, but I feel I have a good enough grasp to get started. Feel free to comment if you have any blanks to fill, or corrections to make!

Base protocol support:

  • IRC
  • XMPP/Jingle

Potential expanded protocol support:

  • BitMessage
  • Ring (SIP + DHT)
  • Slack (and/or Mattermost)
  • Discord (this is a big maybe; the API is awkward)
  • Probably others

Basic architecture:

  • Users
    • Store identifier components individually so they can be reassembled into whatever pattern a given protocol expects.
    • Since all protocols besides IRC require registration of user credentials prior to being able to access the network, IRC services will be built in, allowing direct access to the common user data set. Channels can be set to only permit registered users access, but for maximum flexibility, any info required by other protocols that isn’t available from an unregistered IRC user will be filled with placeholder info indicating the user is unregistered.
  • Chatting
    • All messages sent to the server are translated into a protocol-agnostic format. Each protocol handler is responsible for translation between it and their own distinct protocol.
    • Content messages are stored for later retrieval by backlog requests.
    • Event messages (join/part/login/quit/etc) are also stored in the backlog.
    • Control messages are not stored, but rather handled directly by whichever subsystem they reference.
  • Group Chats
    • Group conversations, no matter their name in a given protocol, will be exposed via all protocols.
    • Private chats will generally be hidden from listings, and users without invitations (in whatever form those take in a given protocol) will be denied access if they attempt to join anyway. Protocols which don’t support joining unlisted chats will have them listed, but with indicators of privacy attached.
    • The name of a given group chat must be unique across the server. Though some protocols allow non-unique naming, others – IRC in particular – do not.
  • Direct Chats
    • Some protocols support a p2p chat style, bypassing the server entirely. If both users are connected via the same protocol, the system doesn’t have to do anything, but obviously, attempting to contact a user who isn’t connected using the same protocol in this fashion simply won’t work. In these cases, the server will need to act as a middle man, so there are a number of caveats to how it works in this mode:
      1. No messages are saved to the backlog.
      2. The server signals both sides to activate message encryption, so that even if a message leaked somehow, it wouldn’t be readable by any but the two clients.
      3. This means translation of certain message artifacts won’t be possible, so users would see these artifacts directly (mostly formatting codes, in this case).
      4. Most control messages would be disabled until p2p mode was ended, as the server shouldn’t be able to hear them anyway.
  • Advanced Features
    • Features not directly supported by all protocols should be emulated in those which don’t.
    • For certain features, such as voice and video chat, this amounts to a simple rejection of the request to start using said feature, though most protocols also support indications of when such features are not enabled by the other user.

Obviously, as stated earlier, this is in the earliest stages of development, so there are many of the finer points I’m either missing entirely, or simply misunderstanding. But I still feel this can be done, and should. What are your thoughts?