diff options
author | justanothercatgirl <sotov2070@gmail.com> | 2024-06-22 01:00:16 +0300 |
---|---|---|
committer | justanothercatgirl <sotov2070@gmail.com> | 2024-06-22 01:00:16 +0300 |
commit | b9251a3c950e75f0d69d5799da42d06dd3e41a63 (patch) | |
tree | ca957ec1baf547279138a93814337402db879743 | |
parent | b0af12b287a7c7e3cc5ba39869835126e700f792 (diff) |
Я ночью плачу и дрочу, я лишь с тобою быть хочу...
-rw-r--r-- | include/kv.h | 9 | ||||
-rw-r--r-- | include/packet.c | 12 | ||||
-rw-r--r-- | include/packet.h | 43 | ||||
-rw-r--r-- | server/channel.c | 119 | ||||
-rw-r--r-- | server/channel.h | 45 |
5 files changed, 111 insertions, 117 deletions
diff --git a/include/kv.h b/include/kv.h new file mode 100644 index 0000000..b5f9842 --- /dev/null +++ b/include/kv.h @@ -0,0 +1,9 @@ +#ifndef JUSTANOTHERCATGIRL_KV_H +#define JUSTANOTHERCATGIRL_KV_H + +#include "packet.h" + +#define KV_SERVER_ADDRESS_STRING "95.164.2.199" +#define KV_SERVER_ADDRESS_INT ((95 << 24) | (164 << 16) | (2 << 8) | (199 << 0)) + +#endif // JUSTANOTHERCATGIRL_KV_H diff --git a/include/packet.c b/include/packet.c new file mode 100644 index 0000000..db20a12 --- /dev/null +++ b/include/packet.c @@ -0,0 +1,12 @@ +#include "packet.h" + +unsigned int system_packet_checksum(struct kv_system_packet *packet) { + return (packet->user_id << 8) ^ + (packet->operation_id | (177013 << 10)); +} + +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/include/packet.h b/include/packet.h new file mode 100644 index 0000000..224469e --- /dev/null +++ b/include/packet.h @@ -0,0 +1,43 @@ +#ifndef KV_PACKET_H +#define KV_PACKET_H + +#define KV_PACKET_SIZE 512 + +#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 + +enum system_operation { + do_nothing = 0, + join_channel = -1, + leave_channel = -2, + acknowledgement = -4, +}; +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; + unsigned int checksum; + unsigned char sentinel[KV_PACKET_SIZE - 4 * sizeof(int) - sizeof(short)]; +}; + +unsigned int system_packet_checksum(struct kv_system_packet *packet); +int __user_cmp(const void* a, const void* b); + +#endif // KV_PACKET_H + 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 <container.h> -#include <errno.h> #include <stdlib.h> +#include <errno.h> 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 <stdbool.h> +#include <kv.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/ip.h> -#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 <stdbool.h> +// 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 |