diff options
author | justanothercatgirl <sotov@twistea.su> | 2025-02-08 22:13:52 +0300 |
---|---|---|
committer | justanothercatgirl <sotov@twistea.su> | 2025-02-08 22:13:52 +0300 |
commit | cab382db088d9f240253466a1c5a26c62f3967c8 (patch) | |
tree | c5502f1b49211dccd3e29e163e708708495a6407 /doc | |
parent | 3eeee14d5d5c93ae3d156aabae5a96d1c09f185a (diff) |
TODO: Implement multiplexing in worker threads (UDP loops), implement
channel_pool interface.
Diffstat (limited to 'doc')
-rw-r--r-- | doc/PROTOCOLS | 10 | ||||
-rw-r--r-- | doc/channel_multiplexing | 84 |
2 files changed, 89 insertions, 5 deletions
diff --git a/doc/PROTOCOLS b/doc/PROTOCOLS index c15a83d..996bf0c 100644 --- a/doc/PROTOCOLS +++ b/doc/PROTOCOLS @@ -72,11 +72,11 @@ permission required. 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. +| 5 | 69 | 70 | 71 | 727 | 420 | 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 diff --git a/doc/channel_multiplexing b/doc/channel_multiplexing new file mode 100644 index 0000000..a1ba681 --- /dev/null +++ b/doc/channel_multiplexing @@ -0,0 +1,84 @@ +This document is mostly for the developer to settle down ideas that are sitting +in his mind. + +Server structure: +Main thread: accepting TCP socket and reading-writing TCP sockets created by +an accepting one. TODO: rewrite so that the entire system is using poll. + +Other `get_nprocs() - 1` threads (if `get_nprocs() == 1`, then only 1 +additional thread) are channel pools. + +Additionally, main thread maintains a list of all channels and threads +associated with them. When new channel is requested, is is created on a thread +that is maintaining the least amount of channels at the time. + +Each channel pool consists of an anonymous UNIX domain socket (which is used +for recieving system messages from main thread) and some amount of INET domain +sockets. All of them are switched on using `poll` system call. + +Each channel in the channel pool has an associated list of peers with it. When +data is recieved on a channel, it is forwarded to every peer (except the +sender). + +The basic structure of the loop should look something like this: + +``` +fds = {timerfd, master socket, udp1, udp2, ...}; +while (poll(fds, nfds, -1) > 0) { + if (socket is master and has data) process_system_commands(); + if (timerfd is ready) check_keepalives(all sockets); + for (every socket that has data) + handle_peers(socket); +} + +void process_system_commands() { + command = read(master); + switch (parse_command()) { + case add_user: addto(channel, user); break; + case add_channel: array_append(channels, new_channel()); break; + case remove_user: rmfrom(channel, user); break; + case remove_channel: array_pop(channel); break; + } +} + +void handle_peers(int socket) { + data = read(socket); + for (every peer of socket) + sendto(socket, data, peer, O_NONBLOCK); // MSG_DONTWAIT, maybe? +} + +void check_keepalives(int socket) { + for (every peer of socket) { + if (keepalive of peer too old) rmfrom(channel, user); + } +} +``` + +Data structures: +inside main thread: + struct channel{u64 id, int port}; + struct channel_pool { + u16 num, + int master_pipe, + u64 thread_id, + array<struct channel> chs + }; + // modern linux kernel has limit on maximim amount of cores: + // 8192. this would break 65535 port limit very fast anyways. + array<struct channel_pool> threads; +inside pool: + struct ch_user { u64 id, u32 ip, u16 port, u64 last_keepalive }; + struct channel { + u64 id, + u64 owner, + int udo, + hash_set<ch_user>* users + }; + array<struct channel> channels; + int master = pipe + +Communication between threads will be done through pipes. Yes, this will be +inefficient in a sense that there will be 2 file descriptors opened for each +thread, but what are other options? Yes, none. If there are, mail this to me +please + |