aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjustanothercatgirl <sotov2070@gmail.com>2024-06-22 01:00:16 +0300
committerjustanothercatgirl <sotov2070@gmail.com>2024-06-22 01:00:16 +0300
commitb9251a3c950e75f0d69d5799da42d06dd3e41a63 (patch)
treeca957ec1baf547279138a93814337402db879743
parentb0af12b287a7c7e3cc5ba39869835126e700f792 (diff)
Я ночью плачу и дрочу, я лишь с тобою быть хочу...
-rw-r--r--include/kv.h9
-rw-r--r--include/packet.c12
-rw-r--r--include/packet.h43
-rw-r--r--server/channel.c119
-rw-r--r--server/channel.h45
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