207 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| // 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_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_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;
 | |
| };
 |