diff options
-rw-r--r-- | TODO.txt | 2 | ||||
-rw-r--r-- | protocol.md | 161 |
2 files changed, 163 insertions, 0 deletions
diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..554ee05 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,2 @@ +- Somehow communicate (push? poll?) to room members whether a particular user is currently _active_, not just online. +- A session is marked inactive 2 minutes after the latest activity on that session. Make the number "2" configurable and not a hard-coded constant. diff --git a/protocol.md b/protocol.md new file mode 100644 index 0000000..aa6de82 --- /dev/null +++ b/protocol.md @@ -0,0 +1,161 @@ +# tomsg protocol + +The underlying transport of the protocol is a plain TCP socket. The individual +messages are all line-based; this means that a single message, both +client->server and server->client, always ends with a newline (ASCII 10) +character. + +Preliminary definitions: +- A _string_ is a series of non-zero bytes. To allow for clients written in + languages that automatically parse strings as UTF-8, argument strings should + always be valid UTF-8. However, the server currently does not care. +- A _word_ is a string without spaces (ASCII 32) or newlines. Note that the + empty string is also a valid word. + +There are three kinds of messages: commands from the client, command responses +from the server, and push messages from the server (not to be confused with push +_notifications_). These three kinds are described below. + +In the syntax descriptions below, `<name>` indicates an argument called "name"; +the angle brackets are not part of the syntax. The type of the argument may be +indicated with the notation `<name:type>`; possible types are `i64` (a 64-bit +signed integer in decimal notation), `word` (a word), and `string...` (a string +stretching until the end of the line). + +A message from client to server consists of a _tag_, a space, the command name, +a space, and finally the arguments to the command. The tag is a word, and may be +arbitrarily chosen by the client; it will be returned by the server in its +response to the client's message, so that the client can easily link requests +and responses. + +All client commands, if not syntactically invalid, will be replied to with a +server response. + +A _response_ from the server will be in one of the following forms: +- `<tag> ok` + - The message from the client was successfully processed. +- `<tag> number <num:i64>` + - A numeric value was returned. +- `<tag> error <message:string...>` + - The client's message was successfully parsed, but handling resulted in an + error described in the message. +- `<tag> list <count:i64> words...` + - A list of words was returned. The number of words returned is given in + `<count>`; the words themselves are space-separated further arguments to + `list`. +- `<tag> pong` + - Response to the client's `ping` command. +- `<tag> history <count:i64>` + - Response to the client's `history` command; is followed by exactly `<count>` + messages of type `history_message` with the same tag. The messages are + returned in reverse chronological order (newest first). +- `<tag> history_message <index:i64> <roomname:word> <user:word> <timestamp:i64> <msgid:i64> <message:string...>` + - Part of the response to the client's `history` command. Index 0 is the + newest message; index (`<count>` - 1) (from the `history` response) is the + oldest message in the fragment requested. Timestamps are microseconds since + the UNIX epoch. The message id for each message is globally unique for the + entire server. + +A command is identified by its name, which can be found in the list below. Its +arguments are zero or more words, except if for the command in question the last +argument is of type `string...` (in which case it may contain spaces and +ranges until the end of the line). + +- `<tag> register <user:word> <pass:string...>` + - Register a new user on the server. The password may contain spaces. + - Returns `ok` or `error`. +- `<tag> login <user:word> <pass:string...>` + - Logs in as the specified user. + - Returns `ok` or `error`. +- `<tag> logout` + - Logs out of the user the client is currently logged in as. If the client is + not logged in, does nothing. + - Returns `ok`. +- `<tag> list_rooms` + - Lists all rooms the user is a member of. + - Returns `list` or `error`. +- `<tag> list_members <roomname:word>` + - Lists all members of the given room, if the user is also a member. + - Returns `list` or `error`. +- `<tag> create_room` + - Creates a new room, and enters the room. The id of the room is returned to + the client. Returns an error if the client is not logged in. + + Also marks the current session as active. + - Returns `name` or `error`. +- `<tag> invite <roomname:word> <user:word>` + - Invites the given user to the given room, if the client is currently a + member of that room. The invited user is immediately added to the room. + + If the invite succeeds, the invited user receives a `_push invite` push + message on all its sessions, and all current room members receive a + `_push join` push message on all their sessions (except the session the + `invite` message was sent from). + + Also marks the current session as active. + - Returns `ok` or `error`. +- `<tag> send <roomname:word> <message:string...>` + - Sends a message to the given room. All room members receive a + `_push message` push message on all their sessions (except the session the + `send` message was sent from). + + Also marks the current session as active. + - Returns `ok` or `error`. +- `<tag> history <roomname:word> <number:i64>` + - Requests the last `<number>` messages in the given room, if the client is a + member of the room. In the `history` response, `<count>` will be at most + `<number>`, and may be less if the room does not yet have `<number>` + messages. Each message will be returned in a `history_message` response + after the `history` response, in reverse chronological order. + - Returns `history`, followed by zero or more `history_message`. +- `<tag> history_before <roomname:word> <number:i64> <msgid:i64>` + - Same as `history`, except the returned messages are the last `<number>` + strictly before the timestamp of the message with id `<msgid>`. + - Returns `history`, followed by zero or more `history_message`. +- `<tag> ping` + - Asks for a `pong` response. + - Returns `pong`. +- `<tag> is_online <user:word>` + - Returns with how many sessions the given user is currently online. + - Returns `number` or `error`. +- `<tag> firebase_token <token:word>` + - Adds the given Firebase token to the account of the current user. This is + used for new-message push notifications for Android-based clients. + - Returns `ok` or `error`. +- `<tag> delete_firebase_token <token:word>` + - Removes the given Firebase token from the account of the current user. + - Returns `ok` or `error`. +- `<tag> user_active <active:i64>` + - Marks the user as active (if `active` > 0) or inactive (if `active` + <= 0) on the current session. This does not influence whether the user is + marked active on any of the other sessions on which they are currently + logged in. + + A session is automatically marked inactive 2 minutes after the latest + activity on that session. + + This is used for Firebase notifications: a user will only receive Firebase + notifications if they are marked inactive on all their sessions, or if they + have no active sessions. + - Returns `ok` or `error`. + +Push messages from the server are formatted like responses with tag `_push`. +These are not sent in response to a particular client message, but are sent by +the server due to other events. Some have already been mentioned above, but all +are listed below. + +- `_push online <numonline:i64> <user:word>` + - When user X logs in or logs out in a session, all sessions of all members + (excluding user X) of all rooms user X is a member of receive a `_push + online` push message stating that `<user>` (user X) is now online with + `<numonline>` sessions. +- `_push message <roomname:word> <user:word> <timestamp:i64> <message:string...>` + - Sent to all sessions of all members of a room in which a message is + posted, except the session that sent the message. +- `_push invite <roomname:word>` + - Sent to all sessions of the invited user after an `invite` command. +- `_push join <roomname:word> <user:word>` + - Sent to all sessions of all members of a room (except the session sending + the `invite` command) in which a new user entered. +- `_push ping` + - Sent by the server once in a while. Please ignore. |