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 chs }; // modern linux kernel has limit on maximim amount of cores: // 8192. this would break 65535 port limit very fast anyways. array 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* users }; array 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