This document describes protocols that are implemented on the server-side of "KV" for real-time communication. 0. General structure. The server uses a single TCP socket for all control packets: It manages channels, users, and in theory the database, though this is not currently implemented. This socket has a private-public key pair associated with it, which is used by channels to authorize messages from the system. Each channel is a separate UDP socket (Optionally on the same thread via poll syscall). UDP sockets receive all data, process system packets and send data back to all peers. Note: In future, the UDP organisation may change so that 1 socket handles several connections. For now, for simplicity purposes, this will not be implemented. The same applies to TCP connections. Note note: EVERYTHING related to SSL is going to be implemented AFTER the working prototype of the server is available. Which is to say, not too soon. 1. The TCP interface. Defined in header `server/tcp.h`. Each connection is a request-response exchange. When the peer connects, it sends data in the following order: the TYPE of the command as defined in `enum commd_type` and `struct commd` (possibly casted from commd_* structs). Then server responds with success status (`uint64`): it is positive if command executed normally, and is zero if anything went wrong. If returned status is zero, further information on the error is sent (see `struct commd_error_report` and `enum commd_error`). Refer to documentation of specific functions for more details on return status. 1.1. Permissions. `enum permissions` is a flag-enum, which means that each permission is 1 bit, and to combine them you use bitwise-or. `perm_none`: placeholder for no permissions `perm_add_channel`: create any channels. `perm_rm_channel`: remove any channels. Note that you don't need it if you are owner of the channel (the one who created it). `perm_add_user`: add any user to any channel. `perm_kick_user`: remove any user from any channel. `perm_register_user`: register new user in a system. Usually only admin has this. `perm_delete_user`: unregister any user in a system. `perm_admin`: All permissions, an equivalent of root user. 1.2. Available commands. `CMD_CREATE`: create a new channel. `struct commd_create` has only one field, uid (user id of one performing request). Returns Channel ID of newly created channel (which is posix thread ID under the hood). Needed permissions for the uid: `perm_add_channel`. `CMD_DELETE`: terminate a channel. `struct commd_delete` has 2 fiels, uid (who is deleting a channel) and chid (channel id). Returns ID of the deleted channel. uid must either have `perm_rm_channel` or be owner of the channel to be able to perform the request. `CMD_JOIN`: Join a channel. `struct commd_join` has 3 fields: uid, juid and chid. uid is the id of user performing the request, juid is user that is joining channel with id chid. if uid != juid, uid must have `perm_add_user` permission. Rerurns port of channel socket. `CMD_LEAVE`: Leave a channel. `struct commd_leave` has same fields as join command, except instead of juid the field is called luid (leaving user id). returns 1. if uid != luid, uid must have `perm_kick_user`. `CMD_REGISTER`: Register new user. `struct commd_register` has 2 fields: auid (administrator user id) and perm (permissions). If auid == 0, this is a regular register request, and perm field will be ignored. If auid is set and auid has `perm_register_user`, the new user with permissions perm is created. returns User ID of created user. `CMD_UNREGISTER`: Delete a user. `struct commd_unregister` has 2 fields: auid (admin user ID) and uid (ID to be deleted). if auid == uid, no permissions are reuqired. Otherwise, auid must have `perm_delete_user`. Returns ID of deleted user. `CMD_GET_PORT`: Get a port of UDP socket of a channel. `struct commd_get_port` has 1 field: chid (ID of a channel). Returns port number of UDP socket. No permission required. `CMD_GET_CHANNELS`: Get a list of all active channels. `struct commd_get_channels` is a typedef to void, which means it takes no arguments. Returns an array as follows: first 8 bytes are uint64 array_size, next 8*array_size bytes are channels. Last 8 bytes are zeroes (they are after the last channel). Possible memory layout (divided in 8 byte [64 bit] blocks): | 5 | 69 | 70 | 71 | 72 | 42 | 0 | ^ ^ ^ ^ | |-start of data | |-leading zero |-size of array |-end of data 1.3. Functions. As the interface mainly uses `uint64` type for communications, there are 2 functions that are for some reason not present in linux api: `uint64 hton64(uint64)`: Host TO Network: convert uint64 to network byte order. `uint64 ntoh64(uint64)`: Network TO Host: convert uint64 from network byte order. 1.4. Notes. As The project is still heavily under development, things may change drastically. For example, it is planned that each `CMD_*` that requires authiorization will be using a signing scheme, so that the server can verify source of the request. For now this is not a top-priority because the develper still needs to at least get this thing up and workingm even without security. Basically templeOS level of security for now, good to guard against accidental errors, bad against targeted attacks. 2. The UDP interface. As it was mentioned before, each channel is a pthread running a UDP socket. UDP has a `packet` (defined in `inclue/packet.h`). There are 2 types of packets: system paclets and user packets. Most system packets must come from the main server and must be signed in order to be processed. ALL PACKETS MUST BE OF SIZE "KV_PACKET_SIZE" WHICH IS 512 BYTES CURRENTLY. Each regular packet consists of uid of sender and acutal data, which is UNCHECKED by the server in ANY way. If UID hasn't joined channel, the packet is discarded. Otherwise, the packet is forwarded to every joined UID. Each system packet is magic bytes (which are 0xFFFFFFFF), then negative int `operation_id` (as defined in `enum system_operation`), then uid, then checksum (calculated with `system_packet_checksum` function). 2.1. System packet operations available to users. `keepalive`: channel removes peers that haven't sent packets for 60 seconds. required fields: all except sentinel, it's unchecked. 3. UDP data specification It is expected that data sent over UDP will be opus-encoded audio. As to how this would be done, there is no information yet because development hasn't reached this point. Also, server doesn't care what you send to it, it only checks for permissions. 4. Registration/Authorization. UID MUST NOT HAVE LOWER OR UPPER 4 BYTES BE EQUAL TO 0xFF - okay, i think i implemented this 5. Noise suppression This documentation section is more like a note to developer in the future: all of the audio processing of any kind will be done on client-side. Server will be busy enough bouncing packets back-and-forth, and it does not care which data is being sent anyways. The complexity must be somewhat balanced between the server and client implementations. # vim: textwidth=80