From b9251a3c950e75f0d69d5799da42d06dd3e41a63 Mon Sep 17 00:00:00 2001 From: justanothercatgirl Date: Sat, 22 Jun 2024 01:00:16 +0300 Subject: Я ночью плачу и дрочу, я лишь с тобою быть хочу... MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/channel.c | 119 ++++++++++++++++++++----------------------------------- server/channel.h | 45 ++------------------- 2 files changed, 47 insertions(+), 117 deletions(-) (limited to 'server') diff --git a/server/channel.c b/server/channel.c index ca16ce0..4dc1f7b 100644 --- a/server/channel.c +++ b/server/channel.c @@ -1,30 +1,23 @@ #include "channel.h" #include -#include #include +#include void thread_loop(void) { struct channel_handle *channel = channel_init(); struct kv_packet **recvd_data = array_new(struct kv_packet*, 100); - size_t recvd_index = 0; struct kv_packet work_buffer; - while (1) { - int recvlength = recvfrom(channel->sockfd, &work_buffer, KV_PACKET_SIZE, 0, NULL, NULL); + size_t recvd_index = 0; + while (true) { + struct sockaddr_in client_addr; + socklen_t client_addr_len; + int recvlength = recvfrom(channel->sockfd, &work_buffer, + KV_PACKET_SIZE, MSG_DONTWAIT, + (struct sockaddr*)&client_addr, &client_addr_len); if (recvlength > 0) { DEBUGF("rec_id = %i\n", work_buffer.id); - if (work_buffer.id <= 0) { // <= 0 is for system messages - switch (handle_system_packet(&work_buffer, channel)) { - case do_nothing: continue; - case shutdown_socket: { - clear_packet_array(recvd_data); - send_cancellation_messages(channel); - channel_uninit(channel); - } FALLTHROUGH; - default: break; - } - continue; - } + if (work_buffer.id <= 0) handle_system_packet(&work_buffer, channel); struct kv_packet *kv_copy = malloc(KV_PACKET_SIZE); memcpy(kv_copy, &work_buffer, KV_PACKET_SIZE); ++recvd_index; @@ -35,8 +28,8 @@ void thread_loop(void) { } } else if (errno == EWOULDBLOCK) { if (array_size(recvd_data) == 0) { - // TODO: unset O_NONBLOCK and wait for data - assert(0); + // TODO: don't set O_NONBLOCK and wait for data + continue; } send_packets_back(recvd_data, channel); clear_packet_array(recvd_data); @@ -46,6 +39,38 @@ void thread_loop(void) { } channel_uninit(channel); } + +struct channel_handle *channel_init(void) { + struct sockaddr_in thread_local_address = { + .sin_family = AF_INET, + .sin_port = 0, + .sin_addr = {INADDR_ANY} + }; + struct channel_handle *handle = NULL; + char chain_result = /* This is evil, but */ + (handle = (struct channel_handle*)calloc(1, sizeof(struct channel_handle))) != NULL + && (handle->users = array_new(struct user, 0)) != NULL + && (handle->sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0 + && bind(handle->sockfd, (struct sockaddr*)&thread_local_address, sizeof(thread_local_address)) == 0; + if (!chain_result) { + perror("channel init failed"); + if (handle) { + if (handle->users) array_free(handle->users); + if (handle->sockfd >= 0) close(handle->sockfd); + free(handle); + } + return NULL; + } + DEBUGF("Channel [%i] created\n", handle->sockfd); + return handle; +} + +void channel_uninit(struct channel_handle *handle) { + array_free(handle->users); + if (close(handle->sockfd) == -1) perror("could not gracefully uninitialize channel"); + free(handle); +} + enum system_operation handle_system_packet(struct kv_packet* packet, struct channel_handle* handle) { struct kv_system_packet* spacket = (struct kv_system_packet*) packet; if (system_packet_checksum(spacket) != spacket->checksum) return do_nothing; @@ -95,69 +120,11 @@ void send_packets_back(struct kv_packet** packets, struct channel_handle* handle } } -unsigned int system_packet_checksum(struct kv_system_packet *packet) { - return (packet->user_id << 8) ^ - (packet->return_port ^ 0x1608) ^ - (packet->operation_id | (177013 << 10)) ^ - (packet->return_address & 0xF0F0F0F0); -} - -struct channel_handle *channel_init(void) { - struct sockaddr_in thread_local_address = {.sin_family = AF_INET, .sin_port = 6969, .sin_addr = {INADDR_ANY}}; - int sock = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); - if (sock < 0) { - perror("channel_init: create socket"); - return NULL; - } - if (bind(sock, (struct sockaddr*)&thread_local_address, sizeof(thread_local_address)) < 0) { - close(sock); - perror("channel_init: bind socket"); - return NULL; - }; - struct user *users = array_new(struct user, 0); - if (users == NULL) { - close(sock); - perror("channel_init: create users"); - return NULL; - } - struct channel_handle *ret = (struct channel_handle*)calloc(1, sizeof(struct channel_handle)); - ret->sockfd = sock; - ret->users = users; - DEBUGF("channel initialized\n"); - return ret; -} - -void channel_uninit(struct channel_handle *handle) { - array_free(handle->users); - if (close(handle->sockfd) == -1) perror("could not gracefully uninitialize channel"); - free(handle); -} - -void send_cancellation_messages(struct channel_handle *handle) { - struct kv_system_packet packet = { - .user_id = 0, - .return_address = 0, - .operation_id = shutdown_socket - }; - packet.checksum = system_packet_checksum(&packet); - struct user* users = handle->users; - for (size_t i = 0; i < array_size(users); ++i) { - struct sockaddr_in dest_addr = {.sin_family = AF_INET, .sin_port = htons(users[i].port), .sin_addr = {htonl(users[i].ip)} }; - sendto(handle->sockfd, &packet, KV_PACKET_SIZE, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); - } -} - void clear_packet_array(struct kv_packet **array) { for (size_t i = 0 ; i < array_size(array); ++i) { if (array[i] == NULL) return; free(array[i]); array[i] = NULL; } - /*memset(array, 0, array_element_size(array) * array_size(array));*/ } -int __user_cmp(const void* a, const void* b) { - struct user *_a = (struct user*)a, - *_b = (struct user*)b; - return _a->id - _b->id; -} diff --git a/server/channel.h b/server/channel.h index a577638..4943887 100644 --- a/server/channel.h +++ b/server/channel.h @@ -1,62 +1,25 @@ #ifndef KV_SERVER_CHANNEL_H #define KV_SERVER_CHANNEL_H -#include +#include #include #include #include #include -#ifdef DEBUG -#define DEBUGF(fmt, ...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__) -#else -#define DEBUGF(fmt, ...) \ - do { } while (0) -#endif - -#define KV_PACKET_SIZE 512 - -enum system_operation { - do_nothing = 0, - join_channel = -1, - shutdown_socket = -2, - acknowledgement = -3, -}; -struct user { - unsigned int ip; - unsigned short port; - int id; -}; -struct channel_handle { - int sockfd; - struct user* users; -}; -struct kv_packet { - int id; - unsigned char data[KV_PACKET_SIZE - sizeof(unsigned int)]; -}; -struct kv_system_packet { - int operation_id; - int user_id; - int return_address; - unsigned short return_port; - unsigned int checksum; - unsigned char sentinel[KV_PACKET_SIZE - 4 * sizeof(int) - sizeof(short)]; -}; +#include +// main function that manages every channel void thread_loop(void); struct channel_handle *channel_init(void); void channel_uninit(struct channel_handle *handle); -enum system_operation handle_system_packet(struct kv_packet* packet, struct channel_handle* handle); -unsigned int system_packet_checksum(struct kv_system_packet *packet); void send_packets_back(struct kv_packet** packets, struct channel_handle *handle); +void handle_system_packet(struct kv_packet* packet, struct channel_handle* handle); -void send_cancellation_messages(struct channel_handle *handle) ; void clear_packet_array(struct kv_packet **array); -int __user_cmp(const void* a, const void* b); #endif // KV_SERVER_CHANNEL_H -- cgit v1.2.3-70-g09d2