// Backwards-compatible protocol version. const VERSION = 1; // From the frontend to the relay. struct CommandMessage { // The command sequence number will be repeated in responses // in the respective fields. u32 command_seq; union CommandData switch (enum Command { HELLO, ACTIVE, BUFFER_ACTIVATE, BUFFER_INPUT, BUFFER_TOGGLE_UNIMPORTANT, PING_RESPONSE, PING, BUFFER_COMPLETE, BUFFER_LOG, } command) { // If the version check succeeds, the client will receive // an initial stream of SERVER_UPDATE, BUFFER_UPDATE, BUFFER_STATS, // BUFFER_LINE, and finally a BUFFER_ACTIVATE message. case HELLO: u32 version; case ACTIVE: void; case BUFFER_ACTIVATE: string buffer_name; case BUFFER_INPUT: string buffer_name; string text; // XXX: Perhaps this should rather be handled through a /buffer command. case BUFFER_TOGGLE_UNIMPORTANT: string buffer_name; case PING_RESPONSE: u32 event_seq; // Only these commands may produce Event.RESPONSE, as below, // but any command may produce an error. case PING: void; case BUFFER_COMPLETE: string buffer_name; string text; u32 position; case BUFFER_LOG: string buffer_name; } data; }; // From the relay to the frontend. struct EventMessage { u32 event_seq; union EventData switch (enum Event { PING, BUFFER_LINE, BUFFER_UPDATE, BUFFER_STATS, BUFFER_RENAME, BUFFER_REMOVE, BUFFER_ACTIVATE, BUFFER_INPUT, BUFFER_CLEAR, SERVER_UPDATE, SERVER_RENAME, SERVER_REMOVE, ERROR, RESPONSE, } event) { case PING: void; case BUFFER_LINE: string buffer_name; // Whether the line should also be displayed in the active buffer. bool leak_to_active; bool is_unimportant; bool is_highlight; enum Rendition { BARE, INDENT, STATUS, ERROR, JOIN, PART, ACTION, } rendition; // Unix timestamp in milliseconds. u64 when; // Broken-up text, with in-band formatting. union ItemData switch (enum Item { TEXT, RESET, FG_COLOR, BG_COLOR, FLIP_BOLD, FLIP_ITALIC, FLIP_UNDERLINE, FLIP_INVERSE, FLIP_CROSSED_OUT, FLIP_MONOSPACE, } kind) { case TEXT: string text; case RESET: void; case FG_COLOR: i16 color; case BG_COLOR: i16 color; case FLIP_BOLD: case FLIP_ITALIC: case FLIP_UNDERLINE: case FLIP_INVERSE: case FLIP_CROSSED_OUT: case FLIP_MONOSPACE: void; } items<>; case BUFFER_UPDATE: string buffer_name; bool hide_unimportant; union BufferContext switch (enum BufferKind { GLOBAL, SERVER, CHANNEL, PRIVATE_MESSAGE, } kind) { case GLOBAL: void; case SERVER: string server_name; case CHANNEL: string server_name; ItemData topic<>; // This includes parameters, separated by spaces. string modes; case PRIVATE_MESSAGE: string server_name; } context; case BUFFER_STATS: string buffer_name; // These are cumulative, even for lines flushed out from buffers. // Updates to these values aren't broadcasted, thus handle: // - BUFFER_LINE by bumping/setting them as appropriate, // - BUFFER_ACTIVATE by clearing them for the previous buffer // (this way, they can be used to mark unread messages). u32 new_messages; u32 new_unimportant_messages; bool highlighted; case BUFFER_RENAME: string buffer_name; string new; case BUFFER_REMOVE: string buffer_name; case BUFFER_ACTIVATE: string buffer_name; case BUFFER_INPUT: string buffer_name; string text; case BUFFER_CLEAR: string buffer_name; case SERVER_UPDATE: string server_name; union ServerData switch (enum ServerState { DISCONNECTED, CONNECTING, CONNECTED, REGISTERED, DISCONNECTING, } state) { case DISCONNECTED: case CONNECTING: case CONNECTED: void; case REGISTERED: string user; string user_modes; // Theoretically, we could also send user information in this state, // but we'd have to duplicate both fields. case DISCONNECTING: void; } data; case SERVER_RENAME: // Buffers aren't sent updates for in this circumstance, // as that wouldn't be sufficiently atomic anyway. string server_name; string new; case SERVER_REMOVE: string server_name; // Restriction: command_seq strictly follows the sequence received // by the relay, across both of these replies. case ERROR: u32 command_seq; string error; case RESPONSE: u32 command_seq; union ResponseData switch (Command command) { case PING: void; case BUFFER_COMPLETE: u32 start; string completions<>; case BUFFER_LOG: // UTF-8, but not guaranteed. u8 log<>; } data; } data; };