diff --git a/.gitignore b/.gitignore index 4e55331..b553309 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,6 @@ compile_commands.json /build/output/ +**/run_tests + *.dSYM/ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9f8aa5d..1ab3a31 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(SOURCE_FILES internal/get_default_interface_and_mac.c internal/datatype_allocator.c internal/datatype_vector.c + internal/datatype_hashmap.c internal/pcap_open.c internal/pcap_send.c internal/check_existing_listener.c diff --git a/src/cleanup_connection.c b/src/cleanup_connection.c index ea1eff8..e8c57e2 100644 --- a/src/cleanup_connection.c +++ b/src/cleanup_connection.c @@ -3,6 +3,7 @@ #include #include #include +#include #include static inline void cleanup_connection_resources(const enum ConnectionType connection_type, void* const connection) { @@ -13,9 +14,9 @@ static inline void cleanup_connection_resources(const enum ConnectionType connec allocator_destroy(&client->pending_messages_memory_allocator); allocator_destroy(&client->packets_completed_memory_allocator); - vector_destroy(&client->packets_sending); - vector_destroy(&client->pending_messages); - vector_destroy(&client->packets_completed); + hashmap_destroy(&client->pending_messages); + hashmap_destroy(&client->packets_sending); + hashmap_destroy(&client->packets_completed); } else { struct SwiftNetServer* const server = (struct SwiftNetServer*)connection; @@ -23,55 +24,39 @@ static inline void cleanup_connection_resources(const enum ConnectionType connec allocator_destroy(&server->pending_messages_memory_allocator); allocator_destroy(&server->packets_completed_memory_allocator); - vector_destroy(&server->packets_sending); - vector_destroy(&server->pending_messages); - vector_destroy(&server->packets_completed); + hashmap_destroy(&server->pending_messages); + hashmap_destroy(&server->packets_sending); + hashmap_destroy(&server->packets_completed); } } -static inline void remove_listener(const enum ConnectionType connection_type, const char* interface_name, void* const connection) { - vector_lock(&listeners); +static inline void remove_listener(const enum ConnectionType connection_type, const char* const interface_name, void* const connection) { + LOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - for (uint16_t i = 0; i < listeners.size; i++) { - struct Listener* const current_listener = vector_get(&listeners, i); - if (strcmp(interface_name, current_listener->interface_name) == 0) { - if (connection_type == CONNECTION_TYPE_CLIENT) { - vector_lock(¤t_listener->client_connections); + const uint32_t interface_len = strlen(interface_name); - for (uint16_t inx = 0; inx < current_listener->client_connections.size; inx++) { - struct SwiftNetClientConnection* const current_connection = vector_get(¤t_listener->client_connections, i); - if (current_connection != connection) { - continue; - } + struct Listener* const listener = hashmap_get(interface_name, interface_len, &listeners); + if (listener == NULL) { + UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - vector_remove(¤t_listener->client_connections, inx); - - break; - } - - vector_unlock(¤t_listener->client_connections); - } else { - vector_lock(¤t_listener->servers); + return; + } - for (uint16_t inx = 0; inx < current_listener->servers.size; inx++) { - struct SwiftNetClientConnection* const current_connection = vector_get(¤t_listener->servers, i); - if (current_connection != connection) { - continue; - } + if (connection_type == CONNECTION_TYPE_CLIENT) { + LOCK_ATOMIC_DATA_TYPE(&listener->client_connections.atomic_lock); - vector_remove(¤t_listener->servers, inx); + hashmap_remove(&((struct SwiftNetClientConnection*)connection)->port_info.source_port, sizeof(uint16_t), &listener->client_connections); - break; - } + UNLOCK_ATOMIC_DATA_TYPE(&listener->client_connections.atomic_lock); + } else { + LOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); - vector_unlock(¤t_listener->servers); - } + hashmap_remove(&((struct SwiftNetServer*)connection)->server_port, sizeof(uint16_t), &listener->servers); - break; - } + UNLOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); } - vector_unlock(&listeners); + UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); } static inline const char* get_interface_name(const bool loopback) { @@ -127,7 +112,7 @@ static inline void close_threads(const enum ConnectionType connection_type, void void swiftnet_client_cleanup(struct SwiftNetClientConnection* const client) { cleanup_connection_resources(CONNECTION_TYPE_CLIENT, client); - const char* interface_name = get_interface_name(client->loopback); + const char* const interface_name = get_interface_name(client->loopback); remove_listener(CONNECTION_TYPE_CLIENT, interface_name, client); diff --git a/src/cleanup_swiftnet.c b/src/cleanup_swiftnet.c index 7774eac..d2981e9 100644 --- a/src/cleanup_swiftnet.c +++ b/src/cleanup_swiftnet.c @@ -5,10 +5,12 @@ #include static inline void close_listeners() { - vector_lock(&listeners); + LOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - for (uint16_t i = 0; i < listeners.size; i++) { - struct Listener* const current_listener = vector_get(&listeners, i); + struct SwiftNetHashMap* const listeners_map = &listeners; + + LOOP_HASHMAP(listeners_map, + struct Listener* const current_listener = hashmap_data; pcap_breakloop(current_listener->pcap); @@ -16,11 +18,11 @@ static inline void close_listeners() { pcap_close(current_listener->pcap); - vector_destroy(¤t_listener->client_connections); - vector_destroy(¤t_listener->servers); - } + hashmap_destroy(¤t_listener->client_connections); + hashmap_destroy(¤t_listener->servers); + ) - vector_destroy(&listeners); + hashmap_destroy(&listeners); } static inline void close_background_service() { @@ -35,11 +37,12 @@ void swiftnet_cleanup() { allocator_destroy(&server_packet_data_memory_allocator); allocator_destroy(&client_packet_data_memory_allocator); allocator_destroy(&packet_buffer_memory_allocator); + allocator_destroy(&hashmap_item_memory_allocator); #ifdef SWIFT_NET_REQUESTS allocator_destroy(&requests_sent_memory_allocator); - vector_destroy(&requests_sent); + hashmap_destroy(&requests_sent); #endif close_listeners(); @@ -48,6 +51,7 @@ void swiftnet_cleanup() { allocator_destroy(&client_connection_memory_allocator); allocator_destroy(&listener_memory_allocator); + allocator_destroy(&uint16_memory_allocator); #ifdef SWIFT_NET_INTERNAL_TESTING printf("Bytes leaked: %d\nItems leaked: %d\n", bytes_leaked, items_leaked); diff --git a/src/execute_packet_callback.c b/src/execute_packet_callback.c index 28e2a16..1c9ff1b 100644 --- a/src/execute_packet_callback.c +++ b/src/execute_packet_callback.c @@ -7,18 +7,11 @@ #include #include -static inline void lock_packet_queue(struct PacketCallbackQueue* const packet_queue) { - enum PacketQueueOwner owner_none = NONE; - while(!atomic_compare_exchange_strong_explicit(&packet_queue->owner, &owner_none, SOME, memory_order_acquire, memory_order_relaxed)) { - owner_none = NONE; - } -} - static struct PacketCallbackQueueNode* const wait_for_next_packet_callback(struct PacketCallbackQueue* const packet_queue) { - lock_packet_queue(packet_queue); + LOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); if(packet_queue->first_node == NULL) { - atomic_store_explicit(&packet_queue->owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return NULL; } @@ -28,29 +21,24 @@ static struct PacketCallbackQueueNode* const wait_for_next_packet_callback(struc packet_queue->first_node = NULL; packet_queue->last_node = NULL; - atomic_store_explicit(&packet_queue->owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return node_to_process; } packet_queue->first_node = node_to_process->next; - atomic_store_explicit(&packet_queue->owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return node_to_process; } -static inline void remove_pending_message_from_vector(struct SwiftNetVector* const pending_messages, struct SwiftNetPendingMessage* const pending_message) { - vector_lock(pending_messages); +static inline void remove_pending_message_from_hashmap(struct SwiftNetHashMap* const pending_messages, struct SwiftNetPendingMessage* const pending_message) { + LOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); - for (uint32_t i = 0; i < pending_messages->size; i++) { - const struct SwiftNetPendingMessage* const current_pending_message = vector_get(pending_messages, i); - if (current_pending_message == pending_message) { - vector_remove(pending_messages, i); - } - } + hashmap_remove(&pending_message->packet_id, sizeof(uint16_t), pending_messages); - vector_unlock(pending_messages); + UNLOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); } void execute_packet_callback( @@ -61,7 +49,7 @@ void execute_packet_callback( struct SwiftNetMemoryAllocator* const pending_message_memory_allocator, _Atomic bool* closing, void* const connection, - struct SwiftNetVector* const pending_messages, + struct SwiftNetHashMap* const pending_messages, _Atomic(void*)* user_data, pthread_mutex_t* const execute_callback_mtx, pthread_cond_t* const execute_callback_cond @@ -92,7 +80,7 @@ void execute_packet_callback( } if(node->pending_message != NULL) { - remove_pending_message_from_vector(pending_messages, node->pending_message); + remove_pending_message_from_hashmap(pending_messages, node->pending_message); } void (*const packet_handler_loaded)(void* const, void* const) = atomic_load(packet_handler); diff --git a/src/handle_packets.c b/src/handle_packets.c index 440b94d..c78a9b5 100644 --- a/src/handle_packets.c +++ b/src/handle_packets.c @@ -10,17 +10,6 @@ #include "internal/internal.h" #include -static inline void lock_packet_queue(struct PacketQueue* const packet_queue) { - enum PacketQueueOwner owner_none = NONE; - while(!atomic_compare_exchange_strong_explicit(&packet_queue->owner, &owner_none, SOME, memory_order_acquire, memory_order_relaxed)) { - owner_none = NONE; - } -} - -static inline void unlock_packet_queue(struct PacketQueue* const packet_queue) { - atomic_store_explicit(&packet_queue->owner, NONE, memory_order_release); -} - static inline void insert_queue_node( struct PacketQueueNode* const new_node, struct PacketQueue* const packet_queue, @@ -31,7 +20,7 @@ static inline void insert_queue_node( return; } - lock_packet_queue(packet_queue); + LOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); if(packet_queue->last_node == NULL) { packet_queue->last_node = new_node; @@ -45,7 +34,7 @@ static inline void insert_queue_node( packet_queue->first_node = new_node; } - unlock_packet_queue(packet_queue); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return; } @@ -174,41 +163,33 @@ static void handle_client_init(struct SwiftNetClientConnection* user, const stru atomic_store_explicit(&client_connection->initialized, true, memory_order_release); } -static inline void handle_correct_receiver(const enum ConnectionType connection_type, struct Listener* const listener, const struct pcap_pkthdr* const hdr, const uint8_t* const packet, const struct SwiftNetPortInfo* const port_info) { +static inline void handle_correct_receiver(const enum ConnectionType connection_type, struct Listener* const listener, const struct pcap_pkthdr* const hdr, const uint8_t* const packet, struct SwiftNetPortInfo* const port_info) { if (connection_type == CONNECTION_TYPE_CLIENT) { - vector_lock(&listener->client_connections); - - for (uint16_t i = 0; i < listener->client_connections.size; i++) { - struct SwiftNetClientConnection* const client_connection = vector_get(&listener->client_connections, i); - if (client_connection->port_info.source_port == port_info->destination_port) { - vector_unlock(&listener->client_connections); + LOCK_ATOMIC_DATA_TYPE(&listener->client_connections.atomic_lock); - if (client_connection->initialized == false) { - handle_client_init(client_connection, hdr, packet); - } else { - swiftnet_handle_packets(client_connection->port_info.source_port, &client_connection->process_packets_thread, client_connection, CONNECTION_TYPE_CLIENT, &client_connection->packet_queue, &client_connection->closing, client_connection->loopback, client_connection->addr_type, hdr, packet, &client_connection->process_packets_mtx, &client_connection->process_packets_cond); - } + struct SwiftNetClientConnection* const client_connection = hashmap_get(&port_info->destination_port, sizeof(uint16_t), &listener->client_connections); + UNLOCK_ATOMIC_DATA_TYPE(&listener->client_connections.atomic_lock); - return; - } + if (client_connection == NULL) { + return; } - vector_unlock(&listener->client_connections); + if (client_connection->initialized == false) { + handle_client_init(client_connection, hdr, packet); + } else { + swiftnet_handle_packets(client_connection->port_info.source_port, &client_connection->process_packets_thread, client_connection, CONNECTION_TYPE_CLIENT, &client_connection->packet_queue, &client_connection->closing, client_connection->loopback, client_connection->addr_type, hdr, packet, &client_connection->process_packets_mtx, &client_connection->process_packets_cond); + } } else { - vector_lock(&listener->servers); + LOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); - for (uint16_t i = 0; i < listener->servers.size; i++) { - struct SwiftNetServer* const server = vector_get(&listener->servers, i); - if (server->server_port == port_info->destination_port) { - vector_unlock(&listener->servers); + struct SwiftNetServer* const server = hashmap_get(&port_info->destination_port, sizeof(uint16_t), &listener->servers); + UNLOCK_ATOMIC_DATA_TYPE(&listener->servers.atomic_lock); - swiftnet_handle_packets(server->server_port, &server->process_packets_thread, server, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->closing, server->loopback, server->addr_type, hdr, packet, &server->process_packets_mtx, &server->process_packets_cond); - - return; - } + if (server == NULL) { + return; } - vector_unlock(&listener->servers); + swiftnet_handle_packets(server->server_port, &server->process_packets_thread, server, CONNECTION_TYPE_SERVER, &server->packet_queue, &server->closing, server->loopback, server->addr_type, hdr, packet, &server->process_packets_mtx, &server->process_packets_cond); } } diff --git a/src/initialize_client_connection.c b/src/initialize_client_connection.c index 64ab933..aa09571 100644 --- a/src/initialize_client_connection.c +++ b/src/initialize_client_connection.c @@ -84,39 +84,35 @@ static inline struct SwiftNetClientConnection* const construct_client_connection new_connection->prepend_size = PACKET_PREPEND_SIZE(new_connection->addr_type); new_connection->pending_messages_memory_allocator = allocator_create(sizeof(struct SwiftNetPendingMessage), 100); - new_connection->pending_messages = vector_create(100); new_connection->packets_sending_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketSending), 100); - new_connection->packets_sending = vector_create(100); new_connection->packets_completed_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketCompleted), 100); - new_connection->packets_completed = vector_create(100); + new_connection->packets_completed = hashmap_create(&uint16_memory_allocator); + new_connection->packets_sending = hashmap_create(&uint16_memory_allocator); + new_connection->pending_messages = hashmap_create(&uint16_memory_allocator); new_connection->packet_queue = (struct PacketQueue){ .first_node = NULL, .last_node = NULL }; - atomic_store_explicit(&new_connection->packet_queue.owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&new_connection->packet_queue.locked); + UNLOCK_ATOMIC_DATA_TYPE(&new_connection->packet_callback_queue.locked); + atomic_store_explicit(&new_connection->closing, false, memory_order_release); atomic_store_explicit(&new_connection->initialized, false, memory_order_release); atomic_store_explicit(&new_connection->packet_handler_user_arg, NULL, memory_order_release); memset(&new_connection->packet_callback_queue, 0x00, sizeof(struct PacketCallbackQueue)); - atomic_store_explicit(&new_connection->packet_callback_queue.owner, NONE, memory_order_release); return new_connection; } -static inline void remove_con_from_listener(const struct SwiftNetClientConnection* const con, struct Listener* const listener) { - vector_lock(&listener->client_connections); +static inline void remove_con_from_listener(struct SwiftNetClientConnection* const con, struct Listener* const listener) { + LOCK_ATOMIC_DATA_TYPE(&listener->client_connections.atomic_lock); - for (uint16_t i = 0; i < listener->client_connections.size; i++) { - struct SwiftNetClientConnection* const client_connection = vector_get(&listener->client_connections, i); - if (client_connection == con) { - vector_remove(&listener->client_connections, i); - } - } + hashmap_remove(&con->port_info.source_port, sizeof(uint16_t), &listener->client_connections); - vector_unlock(&listener->client_connections); + UNLOCK_ATOMIC_DATA_TYPE(&listener->client_connections.atomic_lock); } struct SwiftNetClientConnection* swiftnet_create_client(const char* const ip_address, const uint16_t port, const uint32_t timeout_ms) { diff --git a/src/initialize_server.c b/src/initialize_server.c index 8540ef6..c2958ff 100644 --- a/src/initialize_server.c +++ b/src/initialize_server.c @@ -36,18 +36,20 @@ static inline struct SwiftNetServer* const construct_server(const bool loopback, memset(&new_server->packet_callback_queue, 0x00, sizeof(struct PacketCallbackQueue)); - atomic_store_explicit(&new_server->packet_queue.owner, NONE, memory_order_release); - atomic_store_explicit(&new_server->packet_callback_queue.owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&new_server->packet_queue.locked); + UNLOCK_ATOMIC_DATA_TYPE(&new_server->packet_callback_queue.locked); + atomic_store_explicit(&new_server->packet_handler, NULL, memory_order_release); atomic_store_explicit(&new_server->packet_handler_user_arg, NULL, memory_order_release); atomic_store_explicit(&new_server->closing, false, memory_order_release); new_server->pending_messages_memory_allocator = allocator_create(sizeof(struct SwiftNetPendingMessage), 100); - new_server->pending_messages = vector_create(100); new_server->packets_sending_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketSending), 100); - new_server->packets_sending = vector_create(100); new_server->packets_completed_memory_allocator = allocator_create(sizeof(struct SwiftNetPacketCompleted), 100); - new_server->packets_completed = vector_create(100); + + new_server->packets_completed = hashmap_create(&uint16_memory_allocator); + new_server->packets_sending = hashmap_create(&uint16_memory_allocator); + new_server->pending_messages = hashmap_create(&uint16_memory_allocator); return new_server; } diff --git a/src/initialize_swiftnet.c b/src/initialize_swiftnet.c index b10e7b5..f6ed84c 100644 --- a/src/initialize_swiftnet.c +++ b/src/initialize_swiftnet.c @@ -33,13 +33,15 @@ struct SwiftNetMemoryAllocator packet_buffer_memory_allocator; struct SwiftNetMemoryAllocator server_memory_allocator; struct SwiftNetMemoryAllocator client_connection_memory_allocator; struct SwiftNetMemoryAllocator listener_memory_allocator; +struct SwiftNetMemoryAllocator hashmap_item_memory_allocator; +struct SwiftNetMemoryAllocator uint16_memory_allocator; #ifdef SWIFT_NET_REQUESTS struct SwiftNetMemoryAllocator requests_sent_memory_allocator; - struct SwiftNetVector requests_sent; + struct SwiftNetHashMap requests_sent; #endif -struct SwiftNetVector listeners; +struct SwiftNetHashMap listeners; pthread_t memory_cleanup_thread; @@ -54,6 +56,8 @@ static inline void initialize_allocators() { server_memory_allocator = allocator_create(sizeof(struct SwiftNetServer), 10); client_connection_memory_allocator = allocator_create(sizeof(struct SwiftNetClientConnection), 10); listener_memory_allocator = allocator_create(sizeof(struct Listener), 100); + hashmap_item_memory_allocator = allocator_create(sizeof(struct SwiftNetHashMapItem), 0xFF); + uint16_memory_allocator = allocator_create(sizeof(uint16_t), 0xFF); #ifdef SWIFT_NET_REQUESTS requests_sent_memory_allocator = allocator_create(sizeof(struct RequestSent), 100); @@ -63,10 +67,10 @@ static inline void initialize_allocators() { static inline void initialize_vectors() { #ifdef SWIFT_NET_REQUESTS - requests_sent = vector_create(100); + requests_sent = hashmap_create(&uint16_memory_allocator); #endif - listeners = vector_create(10); + listeners = hashmap_create(NULL); } static inline void initialize_memory_cleanup_thread() { @@ -74,6 +78,8 @@ static inline void initialize_memory_cleanup_thread() { } void swiftnet_initialize() { + seed = rand(); + atomic_store_explicit(&swiftnet_closing, false, memory_order_release); const int temp_socket = socket(AF_INET, SOCK_DGRAM, 0); diff --git a/src/internal/check_existing_listener.c b/src/internal/check_existing_listener.c index 9da0f79..656683b 100644 --- a/src/internal/check_existing_listener.c +++ b/src/internal/check_existing_listener.c @@ -1,48 +1,68 @@ #include "internal.h" +#include +#include +#include void* check_existing_listener(const char* interface_name, void* const connection, const enum ConnectionType connection_type, const bool loopback) { - vector_lock(&listeners); + LOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - for (uint16_t i = 0; i < listeners.size; i++) { - struct Listener* const current_listener = vector_get(&listeners, i); - if (strcmp(interface_name, current_listener->interface_name) == 0) { - if (connection_type == CONNECTION_TYPE_CLIENT) { - vector_lock(¤t_listener->client_connections); + const uint32_t interface_len = strlen(interface_name); - vector_push(¤t_listener->client_connections, connection); + struct Listener* const existing_listener = hashmap_get(interface_name, interface_len, &listeners); - vector_unlock(¤t_listener->client_connections); - } else { - vector_lock(¤t_listener->servers); + if (existing_listener != NULL) { + if (connection_type == CONNECTION_TYPE_CLIENT) { + LOCK_ATOMIC_DATA_TYPE(&existing_listener->client_connections.atomic_lock); - vector_push(¤t_listener->servers, connection); + uint16_t* const restrict key_allocated_mem = allocator_allocate(&uint16_memory_allocator); + *key_allocated_mem = ((struct SwiftNetClientConnection*)connection)->port_info.source_port; - vector_unlock(¤t_listener->servers); - } + hashmap_insert(key_allocated_mem, sizeof(uint16_t), connection, &existing_listener->client_connections); - vector_unlock(&listeners); + UNLOCK_ATOMIC_DATA_TYPE(&existing_listener->client_connections.atomic_lock); + } else { + LOCK_ATOMIC_DATA_TYPE(&existing_listener->servers.atomic_lock); - return current_listener; + uint16_t* const restrict key_allocated_mem = allocator_allocate(&uint16_memory_allocator); + *key_allocated_mem = ((struct SwiftNetServer*)connection)->server_port; + + hashmap_insert(key_allocated_mem, sizeof(uint16_t), connection, &existing_listener->servers); + + UNLOCK_ATOMIC_DATA_TYPE(&existing_listener->servers.atomic_lock); } + + UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); + + return existing_listener; } struct Listener* const new_listener = allocator_allocate(&listener_memory_allocator); - new_listener->servers = vector_create(10); - new_listener->client_connections = vector_create(10); + new_listener->servers = hashmap_create(&uint16_memory_allocator); + new_listener->client_connections = hashmap_create(&uint16_memory_allocator); new_listener->pcap = swiftnet_pcap_open(interface_name); new_listener->addr_type = pcap_datalink(new_listener->pcap); - memcpy(new_listener->interface_name, interface_name, strlen(interface_name) + 1); + memcpy(new_listener->interface_name, interface_name, interface_len + 1); new_listener->loopback = loopback; if (connection_type == CONNECTION_TYPE_CLIENT) { - vector_push(&new_listener->client_connections, connection); + uint16_t* const restrict key_allocated_mem = allocator_allocate(&uint16_memory_allocator); + *key_allocated_mem = ((struct SwiftNetClientConnection*)connection)->port_info.source_port; + + hashmap_insert(key_allocated_mem, sizeof(uint16_t), connection, &new_listener->client_connections); } else { - vector_push(&new_listener->servers, connection); + uint16_t* const restrict key_allocated_mem = allocator_allocate(&uint16_memory_allocator); + *key_allocated_mem = ((struct SwiftNetServer*)connection)->server_port; + + hashmap_insert(key_allocated_mem, sizeof(uint16_t), connection, &new_listener->servers); } - vector_push(&listeners, new_listener); + char* const restrict listener_key = malloc(interface_len); + + memcpy(listener_key, interface_name, interface_len); + + hashmap_insert(listener_key, interface_len, new_listener, &listeners); - vector_unlock(&listeners); + UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); pthread_create(&new_listener->listener_thread, NULL, interface_start_listening, new_listener); diff --git a/src/internal/datatype_hashmap.c b/src/internal/datatype_hashmap.c new file mode 100644 index 0000000..ab391b2 --- /dev/null +++ b/src/internal/datatype_hashmap.c @@ -0,0 +1,245 @@ +#include +#include +#include +#include "internal.h" +#include +#include +#include + +// Initialized in swiftnet_initialize function with rand +uint64_t seed; + +// This hashing function is not really as random as I would want it to be, but it's performant. +// Can cause some collisions. +static inline uint64_t hash64(const uint8_t* const data, const uint32_t data_size) { + // Manual SIMD optimization would be preffered in the future. + uint64_t res = 0; + + for (uint32_t i = 0; i < data_size; i++) { + res = (res ^ *(data + i)) * seed; + } + + return res; +} + +static inline uint32_t get_key(const void* const key_data, const uint32_t data_size, struct SwiftNetHashMap* const hashmap) { + // Mapping to max value of items allocated + // Must rehash when scalling hashmap + return ((__uint128_t)hash64(key_data, data_size) * hashmap->capacity) >> 64; +} + +// Must rehash every key. Takes many cpu cycles. +static inline void hashmap_resize(struct SwiftNetHashMap* const hashmap) { + // Multiply value should be changed by -D flag in the future. + // For now just literal + const uint32_t old_capacity = hashmap->capacity; + const uint32_t new_capacity = hashmap->capacity * 4; + struct SwiftNetHashMapItem* const old_data_location = hashmap->items; + + hashmap->capacity = new_capacity; + + // Realloc doesn't make sense here bcs we have to rehash and copy rehashed keys. + hashmap->items = calloc(sizeof(struct SwiftNetHashMapItem), new_capacity); + + free(hashmap->item_occupation); + + hashmap->item_occupation = calloc(sizeof(uint32_t), (new_capacity + 31) / 32); + + for (uint32_t i = 0; i < old_capacity; i++) { + struct SwiftNetHashMapItem* const current_hashmap_item = old_data_location + i; + if (current_hashmap_item->value == NULL) { + continue; + } + + for (struct SwiftNetHashMapItem* current_linked_item = current_hashmap_item; current_linked_item != NULL; current_linked_item = current_linked_item->next) { + void* const key_original_data = current_linked_item->key_original_data; + const uint32_t key_original_data_size = current_linked_item->key_original_data_size; + + const uint64_t new_key = get_key(key_original_data, key_original_data_size, hashmap); + + struct SwiftNetHashMapItem* new_mem_hashmap_item = hashmap->items + new_key; + + const uint32_t byte = new_key / 32; + const uint8_t bit = new_key % 32; + + *(hashmap->item_occupation + byte) |= 1 << bit; + + if (new_mem_hashmap_item->value != NULL) { + // Get last item + while (new_mem_hashmap_item->next != NULL) { + new_mem_hashmap_item = new_mem_hashmap_item->next; + } + + struct SwiftNetHashMapItem* const hashmap_item_new_allocation = allocator_allocate(&hashmap_item_memory_allocator); + *hashmap_item_new_allocation = (struct SwiftNetHashMapItem){ + .key_original_data = key_original_data, + .key_original_data_size = key_original_data_size, + .next = NULL, + .value = current_linked_item->value + }; + + new_mem_hashmap_item->next = hashmap_item_new_allocation; + } else { + *new_mem_hashmap_item = (struct SwiftNetHashMapItem){ + .key_original_data = key_original_data, + .key_original_data_size = key_original_data_size, + .next = NULL, + .value = current_linked_item->value + }; + } + } + } + + free(old_data_location); +} + +struct SwiftNetHashMap hashmap_create(struct SwiftNetMemoryAllocator* key_memory_allocator) { + return (struct SwiftNetHashMap){ + .capacity = 0x40 * SWIFT_NET_MEMORY_USAGE, + .items = calloc(sizeof(struct SwiftNetHashMapItem), 0x40 * SWIFT_NET_MEMORY_USAGE), + .size = 0, + .item_occupation = calloc(sizeof(uint32_t), ((0x40 * SWIFT_NET_MEMORY_USAGE) + 31) / 32), + .key_memory_allocator = key_memory_allocator + }; +} + +void* hashmap_get(const void* const key_data, const uint32_t data_size, struct SwiftNetHashMap* const hashmap) { + const uint64_t key = get_key(key_data, data_size, hashmap); + + struct SwiftNetHashMapItem* current_item = hashmap->items + key; + + while (current_item != NULL) { + if (data_size == current_item->key_original_data_size && memcmp(current_item->key_original_data, key_data, data_size) == 0) { + return current_item->value; + } + + current_item = current_item->next; + + continue; + } + + return NULL; +} + +void hashmap_insert(void* const key_data, const uint32_t data_size, void* const value, struct SwiftNetHashMap* const hashmap) { + const uint64_t key = get_key(key_data, data_size, hashmap); + + struct SwiftNetHashMapItem* current_target_item = hashmap->items + key; + + while (current_target_item->value != NULL) { + if (current_target_item->next == NULL) { + struct SwiftNetHashMapItem* const new_item = allocator_allocate(&hashmap_item_memory_allocator); + + current_target_item->next = new_item; + + current_target_item = new_item; + + break; + } else { + current_target_item = current_target_item->next; + } + } + + *current_target_item = (struct SwiftNetHashMapItem){ + .key_original_data = key_data, + .key_original_data_size = data_size, + .value = value, + .next = NULL + }; + + hashmap->size++; + + const uint32_t byte = key / 32; + const uint8_t bit = key % 32; + + *(hashmap->item_occupation + byte) |= 0 << bit; + + if (hashmap->size >= hashmap->capacity) { + hashmap_resize(hashmap); + } +} + +void free_hashmap_item_key(struct SwiftNetHashMap* const restrict hashmap, struct SwiftNetHashMapItem* const restrict hashmap_item) { + if (hashmap->key_memory_allocator == NULL) { + free(hashmap_item->key_original_data); + } else { + allocator_free(hashmap->key_memory_allocator, hashmap_item->key_original_data); + } +} + +void hashmap_remove(void* const key_data, const uint32_t data_size, struct SwiftNetHashMap* const restrict hashmap) { + const uint64_t key = get_key(key_data, data_size, hashmap); + + struct SwiftNetHashMapItem* previous_target_item = hashmap->items + key; + struct SwiftNetHashMapItem* current_target_item = hashmap->items + key; + + if (current_target_item->next == NULL) { + const uint32_t byte = key / 32; + const uint8_t bit = key % 32; + + *(hashmap->item_occupation + byte) &= ~(0 << bit); + } + + while (current_target_item != NULL) { + if (data_size == current_target_item->key_original_data_size && memcmp(current_target_item->key_original_data, key_data, data_size) == 0) { + break; + } + + previous_target_item = current_target_item; + current_target_item = current_target_item->next; + + continue; + } + + if (current_target_item == previous_target_item) { + current_target_item->value = NULL; + + struct SwiftNetHashMapItem* const next = current_target_item->next; + + if (next != NULL) { + free_hashmap_item_key(hashmap, current_target_item); + + memcpy(current_target_item, next, sizeof(struct SwiftNetHashMapItem)); + + next->value = NULL; + next->next = NULL; + + allocator_free(&hashmap_item_memory_allocator, next); + } + } else { + previous_target_item->next = current_target_item->next; + + current_target_item->value = NULL; + current_target_item->next = NULL; + + free_hashmap_item_key(hashmap, current_target_item); + + allocator_free(&hashmap_item_memory_allocator, current_target_item); + } + + hashmap->size--; +} + +void hashmap_destroy(struct SwiftNetHashMap* const hashmap) { + for (uint32_t i = 0; i < hashmap->capacity; i++) { + struct SwiftNetHashMapItem* const current_item = hashmap->items + i; + if (current_item->value == NULL) { + continue; + } + + // Dealloc all ->next + for (struct SwiftNetHashMapItem* current_linked_item = current_item->next; current_linked_item != NULL;) { + struct SwiftNetHashMapItem* const next_item = current_linked_item->next; + + free_hashmap_item_key(hashmap, current_linked_item); + + allocator_free(&hashmap_item_memory_allocator, current_linked_item); + + current_linked_item = next_item; + + continue; + } + } + + free(hashmap->items); +} diff --git a/src/internal/datatype_vector.c b/src/internal/datatype_vector.c index 5960e82..dc0da36 100644 --- a/src/internal/datatype_vector.c +++ b/src/internal/datatype_vector.c @@ -2,17 +2,6 @@ #include #include -void vector_lock(struct SwiftNetVector* const vector) { - uint8_t owner_none = 0; - while(!atomic_compare_exchange_strong_explicit(&vector->locked, &owner_none, UINT8_MAX, memory_order_acquire, memory_order_relaxed)) { - owner_none = 0; - } -} - -void vector_unlock(struct SwiftNetVector* const vector) { - atomic_store_explicit(&vector->locked, 0, memory_order_release); -} - struct SwiftNetVector vector_create(const uint32_t starting_amount) { void* const data_ptr = malloc(sizeof(void*) * starting_amount); if (unlikely(data_ptr == NULL)) { diff --git a/src/internal/internal.h b/src/internal/internal.h index 85dec02..0189233 100644 --- a/src/internal/internal.h +++ b/src/internal/internal.h @@ -19,11 +19,44 @@ #define LOOPBACK_INTERFACE_NAME "lo0\0" #endif -typedef enum { +enum RequestLostPacketsReturnType { REQUEST_LOST_PACKETS_RETURN_UPDATED_BIT_ARRAY = 0x00, REQUEST_LOST_PACKETS_RETURN_COMPLETED_PACKET = 0x01 -} RequestLostPacketsReturnType; +}; + +// in body use variables "hashmap_item" and "hashmap_data" +// "hashmap_item" contains pointer to current struct SwiftNetHashMapItem +// "hashmap_data" contains data stored inside struct SwiftNetHashMapItem +#define LOOP_HASHMAP(hashmap, loop_body) \ + for(uint32_t i = 0; i < (hashmap->capacity + 31) / 32; i++) { \ + uint32_t current_index = *(hashmap->item_occupation + i); \ + if(current_index == 0x00) { \ + continue; \ + } \ + uint32_t inverted = ~(current_index); \ + while(inverted != UINT32_MAX) { \ + uint32_t bit_index = __builtin_ctz(inverted); \ + inverted |= 1 << bit_index; \ + for(struct SwiftNetHashMapItem* hashmap_item = hashmap->items + ((i * 32) + bit_index); hashmap_item != NULL; hashmap_item = hashmap_item->next) { \ + void* const hashmap_data = hashmap_item->value; \ + loop_body \ + } \ + } \ + } + +#define LOCK_ATOMIC_DATA_TYPE(atomic_field) \ + do { \ + bool locked = false; \ + while(!atomic_compare_exchange_strong_explicit(atomic_field, &locked, true, memory_order_acquire, memory_order_relaxed)) { \ + locked = false; \ + } \ + } while(0); +#define UNLOCK_ATOMIC_DATA_TYPE(atomic_field) \ + atomic_store_explicit(atomic_field, false, memory_order_release); + +// Size of memory allocated before ip header. +// Memory should contain either an eth hdr or any specific data depending on addr type (loopback or real interface) #define PACKET_PREPEND_SIZE(addr_type) ((addr_type == DLT_NULL) ? sizeof(uint32_t) : addr_type == DLT_EN10MB ? sizeof(struct ether_header) : 0) #define PACKET_HEADER_SIZE (sizeof(struct ip) + sizeof(struct SwiftNetPacketInfo)) #define HANDLE_PACKET_CONSTRUCTION(ip_header, packet_info, addr_type, eth_hdr, buffer_size, buffer_name) \ @@ -39,14 +72,18 @@ typedef enum { memcpy(buffer_name + sizeof(*eth_hdr) + sizeof(*ip_header), packet_info, sizeof(*packet_info)); \ } \ +// Simple crc16 call with proper memory order #define HANDLE_CHECKSUM(buffer, size, prepend_size) \ uint16_t checksum = htons(crc16(buffer, size)); \ memcpy(buffer + prepend_size + offsetof(struct ip, ip_sum), &checksum, sizeof(checksum)); +// Number used in ip.proto #define PROT_NUMBER 253 +// Size of struct field #define SIZEOF_FIELD(type, field) sizeof(((type *)0)->field) +// How many seconds between each memory cleanup. #define PACKET_HISTORY_STORE_TIME 5 #define PRINT_ERROR(fmt, ...) \ @@ -113,8 +150,8 @@ enum AllocatorStackState { struct Listener { pcap_t* pcap; pthread_t listener_thread; - struct SwiftNetVector servers; - struct SwiftNetVector client_connections; + struct SwiftNetHashMap servers; + struct SwiftNetHashMap client_connections; char interface_name[IFNAMSIZ]; uint16_t addr_type; bool loopback; @@ -125,7 +162,9 @@ enum ConnectionType { CONNECTION_TYPE_CLIENT }; -extern struct SwiftNetVector listeners; +extern uint64_t seed; + +extern struct SwiftNetHashMap listeners; extern pthread_t memory_cleanup_thread; extern _Atomic bool swiftnet_closing; @@ -193,6 +232,8 @@ static inline void send_debug_message(const char* message, ...) { extern uint32_t semaphore_counter; +extern struct SwiftNetMemoryAllocator uint16_memory_allocator; + extern struct SwiftNetMemoryAllocator allocator_create(const uint32_t item_size, const uint32_t chunk_item_amount); extern void* allocator_allocate(struct SwiftNetMemoryAllocator* const memory_allocator); extern void allocator_free(struct SwiftNetMemoryAllocator* const memory_allocator, void* const memory_location); @@ -206,6 +247,7 @@ extern struct SwiftNetMemoryAllocator packet_buffer_memory_allocator; extern struct SwiftNetMemoryAllocator server_memory_allocator; extern struct SwiftNetMemoryAllocator client_connection_memory_allocator; extern struct SwiftNetMemoryAllocator listener_memory_allocator; +extern struct SwiftNetMemoryAllocator hashmap_item_memory_allocator; extern void* interface_start_listening(void* listener_void); @@ -214,8 +256,12 @@ extern void vector_remove(struct SwiftNetVector* const vector, const uint32_t in extern void vector_push(struct SwiftNetVector* const vector, void* const data); extern void vector_destroy(struct SwiftNetVector* const vector); extern struct SwiftNetVector vector_create(const uint32_t starting_amount); -extern void vector_lock(struct SwiftNetVector* const vector); -extern void vector_unlock(struct SwiftNetVector* const vector); + +extern struct SwiftNetHashMap hashmap_create(struct SwiftNetMemoryAllocator* key_memory_allocator); +extern void hashmap_insert(void* const key_data, const uint32_t data_size, void* const value, struct SwiftNetHashMap* restrict const hashmap); +extern void hashmap_remove(void* const key_data, const uint32_t data_size, struct SwiftNetHashMap* const hashmap); +extern void hashmap_destroy(struct SwiftNetHashMap* const hashmap); +extern void* hashmap_get(const void* const key_data, const uint32_t data_size, struct SwiftNetHashMap* restrict const hashmap); extern void* server_start_pcap(void* server_void); extern void* client_start_pcap(void* client_void); @@ -228,7 +274,7 @@ struct RequestSent { }; extern struct SwiftNetMemoryAllocator requests_sent_memory_allocator; -extern struct SwiftNetVector requests_sent; +extern struct SwiftNetHashMap requests_sent; #endif extern void swiftnet_send_packet( @@ -238,7 +284,7 @@ extern void swiftnet_send_packet( const struct SwiftNetPacketBuffer* const packet, const uint32_t packet_length, const struct in_addr* const target_addr, - struct SwiftNetVector* const packets_sending, + struct SwiftNetHashMap* const packets_sending, struct SwiftNetMemoryAllocator* const packets_sending_memory_allocator, pcap_t* const pcap, const struct ether_header eth_hdr, diff --git a/src/make_request.c b/src/make_request.c index b56223a..ac63024 100644 --- a/src/make_request.c +++ b/src/make_request.c @@ -1,6 +1,7 @@ #include "internal/internal.h" #include "swift_net.h" #include +#include #include #include #include @@ -8,15 +9,11 @@ #ifdef SWIFT_NET_REQUESTS static inline void delete_request_sent(struct RequestSent* request_sent) { - vector_lock(&requests_sent); + LOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock) - for (uint32_t i = 0; i < requests_sent.size; i++) { - if (vector_get(&requests_sent, i) == request_sent) { - vector_remove(&requests_sent, i); - } - } + hashmap_remove(&request_sent->packet_id, sizeof(uint16_t), &requests_sent); - vector_unlock(&requests_sent); + UNLOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock) allocator_free(&requests_sent_memory_allocator, request_sent); } diff --git a/src/memory_cleanup_background_service.c b/src/memory_cleanup_background_service.c index b8068af..e2180bf 100644 --- a/src/memory_cleanup_background_service.c +++ b/src/memory_cleanup_background_service.c @@ -1,60 +1,61 @@ #include "swift_net.h" #include "internal/internal.h" #include +#include #include #include -static inline void cleanup_packets_completed(struct SwiftNetVector* packets_completed, struct SwiftNetMemoryAllocator* const packets_completed_allocator) { - vector_lock(packets_completed); +static inline void cleanup_packets_completed(struct SwiftNetHashMap* packets_completed, struct SwiftNetMemoryAllocator* const packets_completed_allocator) { + LOCK_ATOMIC_DATA_TYPE(&packets_completed->atomic_lock); - for (uint32_t i = 0; i < packets_completed->size; i++) { - struct SwiftNetPacketCompleted* const current_packet_completed = vector_get(packets_completed, i); + LOOP_HASHMAP(packets_completed, + if (((struct SwiftNetPacketCompleted*)hashmap_data)->marked_cleanup == true) { + hashmap_remove(hashmap_item->key_original_data, hashmap_item->key_original_data_size, packets_completed); - if (current_packet_completed->marked_cleanup == true) { - vector_remove(packets_completed, i); - - allocator_free(packets_completed_allocator, current_packet_completed); + allocator_free(packets_completed_allocator, hashmap_data); } else { - current_packet_completed->marked_cleanup = true; + ((struct SwiftNetPacketCompleted*)hashmap_data)->marked_cleanup = true; } - } + ) - vector_unlock(packets_completed); + UNLOCK_ATOMIC_DATA_TYPE(&packets_completed->atomic_lock); } -void* memory_cleanup_background_service() { - while(atomic_load_explicit(&swiftnet_closing, memory_order_acquire) == false) { - struct timeval start, end; - gettimeofday(&start, NULL); - - vector_lock(&listeners); +static inline void handle_listener(struct Listener* const current_listener) { + struct SwiftNetHashMap* const client_connections = ¤t_listener->client_connections; + struct SwiftNetHashMap* const servers = ¤t_listener->servers; - for (uint32_t i = 0; i < listeners.size; i++) { - struct Listener* const current_listener = vector_get(&listeners, i); + LOCK_ATOMIC_DATA_TYPE(&servers->atomic_lock); + LOCK_ATOMIC_DATA_TYPE(&client_connections->atomic_lock); - struct SwiftNetVector* const client_connections = ¤t_listener->client_connections; - struct SwiftNetVector* const servers = ¤t_listener->servers; + LOOP_HASHMAP(client_connections, + struct SwiftNetClientConnection* const client_connection = hashmap_data; + cleanup_packets_completed(&client_connection->packets_completed, &client_connection->packets_completed_memory_allocator); + ) - vector_lock(servers); - vector_lock(client_connections); + LOOP_HASHMAP(servers, + struct SwiftNetServer* const server = hashmap_data; + cleanup_packets_completed(&server->packets_completed, &server->packets_completed_memory_allocator); + ) - for (uint32_t client_connection_index = 0; client_connection_index < client_connections->size; client_connection_index++) { - struct SwiftNetClientConnection* const current_con = vector_get(client_connections, client_connection_index); + UNLOCK_ATOMIC_DATA_TYPE(&servers->atomic_lock); + UNLOCK_ATOMIC_DATA_TYPE(&client_connections->atomic_lock); +} - cleanup_packets_completed(¤t_con->packets_completed, ¤t_con->packets_completed_memory_allocator); - } +void* memory_cleanup_background_service() { + while(atomic_load_explicit(&swiftnet_closing, memory_order_acquire) == false) { + struct timeval start, end; + gettimeofday(&start, NULL); - for (uint32_t server_index = 0; server_index < servers->size; server_index++) { - struct SwiftNetServer* const current_server = vector_get(servers, server_index); + LOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); - cleanup_packets_completed(¤t_server->packets_completed, ¤t_server->packets_completed_memory_allocator); - } + struct SwiftNetHashMap* const listeners_map = &listeners; - vector_unlock(client_connections); - vector_unlock(servers); - } + LOOP_HASHMAP(listeners_map, + handle_listener(hashmap_data); + ) - vector_unlock(&listeners); + UNLOCK_ATOMIC_DATA_TYPE(&listeners.atomic_lock); gettimeofday(&end, NULL); diff --git a/src/process_packets.c b/src/process_packets.c index e41145e..c9a8d00 100644 --- a/src/process_packets.c +++ b/src/process_packets.c @@ -25,17 +25,6 @@ static inline bool is_private_ip(struct in_addr ip) { return !(octet1 == 192 && octet2 == 168) == false && (octet1 == 127 && octet2 == 0 && octet3 == 0); } -static inline void lock_packet_sending(struct SwiftNetPacketSending* const packet_sending) { - bool locked = false; - while(!atomic_compare_exchange_strong_explicit(&packet_sending->locked, &locked, true, memory_order_acquire, memory_order_relaxed)) { - locked = false; - } -} - -static inline void unlock_packet_sending(struct SwiftNetPacketSending* const packet_sending) { - atomic_store_explicit(&packet_sending->locked, false, memory_order_release); -} - // Returns an array of 4 byte uint32_t, that contain indexes of lost chunks static inline const uint32_t return_lost_chunk_indexes(const uint8_t* const chunks_received, const uint32_t chunk_amount, const uint32_t buffer_size, uint32_t* const buffer) { uint32_t byte = 0; @@ -82,53 +71,37 @@ static inline const uint32_t return_lost_chunk_indexes(const uint8_t* const chun return offset; } -static inline void packet_completed(const uint16_t packet_id, struct SwiftNetVector* const packets_completed_history, struct SwiftNetMemoryAllocator* const packets_completed_history_memory_allocator) { +static inline void packet_completed(uint16_t packet_id, struct SwiftNetHashMap* const packets_completed_history, struct SwiftNetMemoryAllocator* const packets_completed_history_memory_allocator) { struct SwiftNetPacketCompleted* const new_packet_completed = allocator_allocate(packets_completed_history_memory_allocator); new_packet_completed->packet_id = packet_id; new_packet_completed->marked_cleanup = false; - vector_lock(packets_completed_history); + uint16_t* heap_key_data_location = allocator_allocate(&uint16_memory_allocator); + *heap_key_data_location = packet_id; - vector_push(packets_completed_history, new_packet_completed); + LOCK_ATOMIC_DATA_TYPE(&packets_completed_history->atomic_lock); - vector_unlock(packets_completed_history); + hashmap_insert(heap_key_data_location, sizeof(uint16_t), new_packet_completed, packets_completed_history); + + UNLOCK_ATOMIC_DATA_TYPE(&packets_completed_history->atomic_lock); return; } -static inline bool check_packet_already_completed(const uint16_t packet_id, struct SwiftNetVector* const packets_completed_history) { - vector_lock(packets_completed_history); - - for(uint32_t i = 0; i < packets_completed_history->size; i++) { - const struct SwiftNetPacketCompleted* const current = vector_get((struct SwiftNetVector*)packets_completed_history, i); - - if(current->packet_id == packet_id) { - vector_unlock(packets_completed_history); - - return true; - } - } - - vector_unlock(packets_completed_history); +static inline bool check_packet_already_completed(uint16_t packet_id, struct SwiftNetHashMap* const packets_completed_history) { + const struct SwiftNetPacketCompleted* const item = hashmap_get(&packet_id, sizeof(packet_id), packets_completed_history); - return false; + return item != NULL; } -static inline struct SwiftNetPendingMessage* const get_pending_message(struct SwiftNetVector* const pending_messages_vector, const enum ConnectionType connection_type, const uint16_t packet_id) { - vector_lock(pending_messages_vector); +static inline struct SwiftNetPendingMessage* const get_pending_message(struct SwiftNetHashMap* const pending_messages, const enum ConnectionType connection_type, uint16_t packet_id) { + LOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); - for(uint32_t i = 0; i < pending_messages_vector->size; i++) { - struct SwiftNetPendingMessage* const current_pending_message = vector_get((struct SwiftNetVector*)pending_messages_vector, i); + struct SwiftNetPendingMessage* const pending_message = hashmap_get(&packet_id, sizeof(uint16_t), pending_messages); - if(current_pending_message->packet_id == packet_id) { - vector_unlock((struct SwiftNetVector*)pending_messages_vector); - return current_pending_message; - } - } + UNLOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); - vector_unlock((struct SwiftNetVector*)pending_messages_vector); - - return NULL; + return pending_message; } static inline void insert_callback_queue_node(struct PacketCallbackQueueNode* const new_node, struct PacketCallbackQueue* const packet_queue) { @@ -136,10 +109,7 @@ static inline void insert_callback_queue_node(struct PacketCallbackQueueNode* co return; } - enum PacketQueueOwner owner_none = NONE; - while(!atomic_compare_exchange_strong_explicit(&packet_queue->owner, &owner_none, SOME, memory_order_acquire, memory_order_relaxed)) { - owner_none = NONE; - } + LOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); if(packet_queue->last_node == NULL) { packet_queue->last_node = new_node; @@ -153,50 +123,39 @@ static inline void insert_callback_queue_node(struct PacketCallbackQueueNode* co packet_queue->first_node = new_node; } - atomic_store_explicit(&packet_queue->owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return; } #ifdef SWIFT_NET_REQUESTS -static inline void handle_request_response(const uint16_t packet_id, struct SwiftNetPendingMessage* const pending_message, void* const packet_data, struct SwiftNetVector* const pending_messages, struct SwiftNetMemoryAllocator* const pending_message_memory_allocator, const enum ConnectionType connection_type, const bool loopback) { +static inline void handle_request_response(uint16_t packet_id, struct SwiftNetPendingMessage* const pending_message, void* const packet_data, struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_message_memory_allocator, const enum ConnectionType connection_type, const bool loopback) { bool is_valid_response = false; - vector_lock(&requests_sent); - - for (uint32_t i = 0; i < requests_sent.size; i++) { - struct RequestSent* const current_request_sent = vector_get(&requests_sent, i); + LOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock); - if (current_request_sent == NULL) { - continue; - } + struct RequestSent* const request_sent = hashmap_get(&packet_id, sizeof(uint16_t), &requests_sent); + if (request_sent == NULL) { + UNLOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock); + return; + } - if (current_request_sent->packet_id == packet_id) { - atomic_store_explicit(¤t_request_sent->packet_data, packet_data, memory_order_release); + atomic_store_explicit(&request_sent->packet_data, packet_data, memory_order_release); - vector_remove(&requests_sent, i); + hashmap_remove(&packet_id, sizeof(uint16_t), &requests_sent); - is_valid_response = true; + is_valid_response = true; - break; - } - } - - vector_unlock(&requests_sent); + UNLOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock); if (is_valid_response == true) { if (pending_message != NULL) { - vector_lock(pending_messages); + LOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); - for (uint32_t i = 0; i < pending_messages->size; i++) { - const struct SwiftNetPendingMessage* const current_pending_message = vector_get(pending_messages, i); - if (current_pending_message == pending_message) { - vector_remove(pending_messages, i); - } - } + hashmap_remove(&packet_id, sizeof(uint16_t), pending_messages); - vector_unlock(pending_messages); + UNLOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); } return; @@ -237,7 +196,7 @@ static inline void chunk_received(uint8_t* const chunks_received, const uint32_t chunks_received[byte] |= 1 << bit; } -static inline struct SwiftNetPendingMessage* const create_new_pending_message(struct SwiftNetVector* const pending_messages, struct SwiftNetMemoryAllocator* const pending_messages_memory_allocator, const struct SwiftNetPacketInfo* const packet_info, const enum ConnectionType connection_type, const uint16_t packet_id) { +static inline struct SwiftNetPendingMessage* const create_new_pending_message(struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_messages_memory_allocator, const struct SwiftNetPacketInfo* const packet_info, const enum ConnectionType connection_type, const uint16_t packet_id) { struct SwiftNetPendingMessage* const new_pending_message = allocator_allocate(pending_messages_memory_allocator); uint8_t* const allocated_memory = malloc(packet_info->packet_length); @@ -254,41 +213,33 @@ static inline struct SwiftNetPendingMessage* const create_new_pending_message(st new_pending_message->packet_id = packet_id; - vector_lock(pending_messages); + LOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); + + uint16_t* const packet_id_mem = allocator_allocate(&uint16_memory_allocator); + *packet_id_mem = packet_id; - vector_push((struct SwiftNetVector*)pending_messages, new_pending_message); + hashmap_insert(packet_id_mem, sizeof(uint16_t), new_pending_message, pending_messages); - vector_unlock(pending_messages); + UNLOCK_ATOMIC_DATA_TYPE(&pending_messages->atomic_lock); return new_pending_message; } -static inline struct SwiftNetPacketSending* const get_packet_sending(struct SwiftNetVector* const packet_sending_array, const uint16_t target_id) { - vector_lock(packet_sending_array); - - for(uint32_t i = 0; i < packet_sending_array->size; i++) { - struct SwiftNetPacketSending* const current_packet_sending = vector_get((struct SwiftNetVector*)packet_sending_array, i); +static inline struct SwiftNetPacketSending* const get_packet_sending(struct SwiftNetHashMap* const packet_sending_array, uint16_t target_id) { + LOCK_ATOMIC_DATA_TYPE(&packet_sending_array->atomic_lock); - if(current_packet_sending->packet_id == target_id) { - vector_unlock(packet_sending_array); + struct SwiftNetPacketSending* const result = hashmap_get(&target_id, sizeof(target_id), packet_sending_array); - return current_packet_sending; - } - } + UNLOCK_ATOMIC_DATA_TYPE(&packet_sending_array->atomic_lock); - vector_unlock(packet_sending_array); - - return NULL; + return result; } struct PacketQueueNode* const wait_for_next_packet(struct PacketQueue* const packet_queue) { - enum PacketQueueOwner owner_none = NONE; - while(!atomic_compare_exchange_strong_explicit(&packet_queue->owner, &owner_none, SOME, memory_order_acquire, memory_order_relaxed)) { - owner_none = NONE; - } + LOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); if(packet_queue->first_node == NULL) { - atomic_store(&packet_queue->owner, NONE); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return NULL; } @@ -298,14 +249,14 @@ struct PacketQueueNode* const wait_for_next_packet(struct PacketQueue* const pac packet_queue->first_node = NULL; packet_queue->last_node = NULL; - atomic_store(&packet_queue->owner, NONE); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return node_to_process; } packet_queue->first_node = node_to_process->next; - atomic_store_explicit(&packet_queue->owner, NONE, memory_order_release); + UNLOCK_ATOMIC_DATA_TYPE(&packet_queue->locked); return node_to_process; } @@ -321,11 +272,11 @@ static inline void swiftnet_process_packets( const uint16_t source_port, const bool loopback, const uint16_t addr_type, - struct SwiftNetVector* const packets_sending, + struct SwiftNetHashMap* const packets_sending, struct SwiftNetMemoryAllocator* const packets_sending_messages_memory_allocator, - struct SwiftNetVector* const pending_messages, + struct SwiftNetHashMap* const pending_messages, struct SwiftNetMemoryAllocator* const pending_messages_memory_allocator, - struct SwiftNetVector* const packets_completed_history, + struct SwiftNetHashMap* const packets_completed_history, struct SwiftNetMemoryAllocator* const packets_completed_history_memory_allocator, enum ConnectionType connection_type, struct PacketQueue* const packet_queue, @@ -515,7 +466,7 @@ static inline void swiftnet_process_packets( goto next_packet; } - lock_packet_sending(target_packet_sending); + LOCK_ATOMIC_DATA_TYPE(&target_packet_sending->locked); if(target_packet_sending->lost_chunks == NULL) { target_packet_sending->lost_chunks = malloc(maximum_transmission_unit - PACKET_HEADER_SIZE); @@ -531,7 +482,7 @@ static inline void swiftnet_process_packets( allocator_free(&packet_buffer_memory_allocator, packet_buffer); - unlock_packet_sending(target_packet_sending); + UNLOCK_ATOMIC_DATA_TYPE(&target_packet_sending->locked); goto next_packet; } @@ -561,7 +512,6 @@ static inline void swiftnet_process_packets( } struct SwiftNetClientAddrData sender = { - .maximum_transmission_unit = packet_info.maximum_transmission_unit, .port = packet_info.port_info.source_port, }; diff --git a/src/send_packet.c b/src/send_packet.c index 10b9ca7..46cd5e4 100644 --- a/src/send_packet.c +++ b/src/send_packet.c @@ -15,18 +15,7 @@ #include "internal/internal.h" #include -static inline void lock_packet_sending(struct SwiftNetPacketSending* const packet_sending) { - bool locked = false; - while(!atomic_compare_exchange_strong_explicit(&packet_sending->locked, &locked, true, memory_order_acquire, memory_order_relaxed)) { - locked = false; - } -} - -static inline void unlock_packet_sending(struct SwiftNetPacketSending* const packet_sending) { - atomic_store_explicit(&packet_sending->locked, false, memory_order_release); -} - -static inline uint8_t request_lost_packets_bitarray(const uint8_t* const raw_data, const uint32_t data_size, const struct sockaddr* const destination, pcap_t* const pcap, struct SwiftNetPacketSending* const packet_sending) { +static inline enum RequestLostPacketsReturnType request_lost_packets_bitarray(const uint8_t* const raw_data, const uint32_t data_size, const struct sockaddr* const destination, pcap_t* const pcap, struct SwiftNetPacketSending* const packet_sending) { while(1) { if(check_debug_flag(LOST_PACKETS)) { send_debug_message("Requested list of lost packets: {\"packet_id\": %d}\n", packet_sending->packet_id); @@ -58,13 +47,13 @@ static inline void handle_lost_packets( struct SwiftNetPacketSending* const packet_sending, const uint32_t mtu, const struct SwiftNetPacketBuffer* const packet, - pcap_t* pcap, + pcap_t* const pcap, const struct ether_header eth_hdr, const struct in_addr* const destination_address, const uint16_t source_port, const uint16_t destination_port, struct SwiftNetMemoryAllocator* const packets_sending_memory_allocator, - struct SwiftNetVector* const packets_sending, + struct SwiftNetHashMap* const packets_sending, const bool loopback, const uint16_t addr_type, const uint8_t prepend_size @@ -112,9 +101,9 @@ static inline void handle_lost_packets( HANDLE_PACKET_CONSTRUCTION(&resend_chunk_ip_header, &resend_chunk_packet_info, addr_type, ð_hdr, mtu + prepend_size, resend_chunk_buffer) while(1) { - const uint8_t request_lost_packets_bitarray_response = request_lost_packets_bitarray(request_lost_packets_buffer, PACKET_HEADER_SIZE + prepend_size, (const struct sockaddr*)destination_address, pcap, packet_sending); + const enum RequestLostPacketsReturnType request_lost_packets_bitarray_response = request_lost_packets_bitarray(request_lost_packets_buffer, PACKET_HEADER_SIZE + prepend_size, (const struct sockaddr*)destination_address, pcap, packet_sending); - lock_packet_sending(packet_sending); + LOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); switch (request_lost_packets_bitarray_response) { case REQUEST_LOST_PACKETS_RETURN_UPDATED_BIT_ARRAY: @@ -122,19 +111,9 @@ static inline void handle_lost_packets( case REQUEST_LOST_PACKETS_RETURN_COMPLETED_PACKET: free((void*)packet_sending->lost_chunks); - vector_lock(packets_sending); - - for (uint32_t i = 0; i < packets_sending->size; i++) { - if (((struct SwiftNetPacketSending*)vector_get(packets_sending, i))->packet_id == packet_sending->packet_id) { - vector_remove(packets_sending, i); + hashmap_remove(&packet_sending->packet_id, sizeof(packet_sending->packet_id), packets_sending); - break; - } - } - - vector_unlock(packets_sending); - - unlock_packet_sending(packet_sending); + UNLOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); allocator_free(packets_sending_memory_allocator, packet_sending); @@ -175,7 +154,7 @@ static inline void handle_lost_packets( } } - unlock_packet_sending(packet_sending); + UNLOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); } } @@ -186,7 +165,7 @@ inline void swiftnet_send_packet( const struct SwiftNetPacketBuffer* const packet, const uint32_t packet_length, const struct in_addr* const target_addr, - struct SwiftNetVector* const packets_sending, + struct SwiftNetHashMap* const packets_sending, struct SwiftNetMemoryAllocator* const packets_sending_memory_allocator, pcap_t* const pcap, const struct ether_header eth_hdr, @@ -218,11 +197,14 @@ inline void swiftnet_send_packet( if (request_sent != NULL) { request_sent->packet_id = packet_id; - vector_lock(&requests_sent); + LOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock); + + uint16_t* const restrict hashmap_key_mem = allocator_allocate(&uint16_memory_allocator); + *hashmap_key_mem = packet_id; - vector_push(&requests_sent, request_sent); + hashmap_insert(hashmap_key_mem, sizeof(uint16_t), request_sent, &requests_sent); - vector_unlock(&requests_sent); + UNLOCK_ATOMIC_DATA_TYPE(&requests_sent.atomic_lock); } #else const uint16_t packet_id = rand(); @@ -255,17 +237,21 @@ inline void swiftnet_send_packet( return; } - vector_lock(packets_sending); + LOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); - vector_push((struct SwiftNetVector*)packets_sending, (struct SwiftNetPacketSending*)new_packet_sending); - - vector_unlock(packets_sending); + uint16_t* const key_data_mem = allocator_allocate(&uint16_memory_allocator); + *key_data_mem = packet_id; new_packet_sending->lost_chunks = NULL; new_packet_sending->locked = false; new_packet_sending->lost_chunks = NULL; new_packet_sending->lost_chunks_size = 0; new_packet_sending->packet_id = packet_id; + atomic_store_explicit(&new_packet_sending->updated, NO_UPDATE, memory_order_release); + + hashmap_insert(key_data_mem, sizeof(uint16_t), new_packet_sending, packets_sending); + + UNLOCK_ATOMIC_DATA_TYPE(&packets_sending->atomic_lock); HANDLE_PACKET_CONSTRUCTION(&ip_header, &packet_info, addr_type, ð_hdr, mtu + prepend_size, buffer) diff --git a/src/swift_net.h b/src/swift_net.h index d202097..554ec9f 100644 --- a/src/swift_net.h +++ b/src/swift_net.h @@ -29,10 +29,9 @@ extern "C" { #define SWIFT_NET_DEBUG #endif -enum PacketQueueOwner { - NONE = 0x00, - SOME = 0xFF -}; +// Multiplication of memory pre allocated. +// More memory = better performance +#define SWIFT_NET_MEMORY_USAGE 5 enum PacketType { MESSAGE = 0x01, @@ -156,7 +155,7 @@ struct PacketQueueNode { struct PacketQueue { struct PacketQueueNode* first_node; struct PacketQueueNode* last_node; - _Atomic enum PacketQueueOwner owner; + _Atomic bool locked; }; struct PacketCallbackQueueNode { @@ -183,7 +182,7 @@ struct SwiftNetClientPacketData { struct PacketCallbackQueue { struct PacketCallbackQueueNode* first_node; struct PacketCallbackQueueNode* last_node; - _Atomic enum PacketQueueOwner owner; + _Atomic bool locked; }; struct SwiftNetSentSuccessfullyCompletedPacketSignal { @@ -220,7 +219,24 @@ struct SwiftNetVector { void** data; uint32_t size; uint32_t capacity; - _Atomic uint8_t locked; + _Atomic bool locked; +}; + +struct SwiftNetHashMapItem { + uint32_t key_original_data_size; + struct SwiftNetHashMapItem* next; // Contains next element with same key. + void* key_original_data; // Dynamically allocated original key data + void* value; // Data stored in item +}; + +// Custom implementation of a hashmap +struct SwiftNetHashMap { + _Atomic bool atomic_lock; + uint32_t capacity; + uint32_t size; + struct SwiftNetHashMapItem* items; + struct SwiftNetMemoryAllocator* key_memory_allocator; + uint32_t* item_occupation; // Bitset tracking which indexes of items array are occupied for looping through items without many cycles. }; // Connection data @@ -228,15 +244,15 @@ struct SwiftNetClientConnection { pcap_t* pcap; _Atomic(void (*)(struct SwiftNetClientPacketData* const, void* const user)) packet_handler; _Atomic(void*) packet_handler_user_arg; - struct SwiftNetVector packets_completed; + struct SwiftNetHashMap packets_completed; struct SwiftNetMemoryAllocator packets_completed_memory_allocator; struct PacketQueue packet_queue; pthread_mutex_t process_packets_mtx; pthread_cond_t process_packets_cond; pthread_t process_packets_thread; - struct SwiftNetVector pending_messages; + struct SwiftNetHashMap pending_messages; struct SwiftNetMemoryAllocator pending_messages_memory_allocator; - struct SwiftNetVector packets_sending; + struct SwiftNetHashMap packets_sending; struct SwiftNetMemoryAllocator packets_sending_memory_allocator; struct PacketCallbackQueue packet_callback_queue; pthread_mutex_t execute_callback_mtx; @@ -262,11 +278,11 @@ struct SwiftNetServer { pthread_mutex_t process_packets_mtx; pthread_cond_t process_packets_cond; pthread_t process_packets_thread; - struct SwiftNetVector pending_messages; + struct SwiftNetHashMap pending_messages; struct SwiftNetMemoryAllocator pending_messages_memory_allocator; - struct SwiftNetVector packets_sending; + struct SwiftNetHashMap packets_sending; struct SwiftNetMemoryAllocator packets_sending_memory_allocator; - struct SwiftNetVector packets_completed; + struct SwiftNetHashMap packets_completed; struct SwiftNetMemoryAllocator packets_completed_memory_allocator; struct PacketCallbackQueue packet_callback_queue; pthread_mutex_t execute_callback_mtx; diff --git a/tests/integration_tests/output/run_tests b/tests/integration_tests/output/run_tests deleted file mode 100755 index 941b291..0000000 Binary files a/tests/integration_tests/output/run_tests and /dev/null differ diff --git a/tests/performance_tests/output/run_tests b/tests/performance_tests/output/run_tests deleted file mode 100755 index 3ac504c..0000000 Binary files a/tests/performance_tests/output/run_tests and /dev/null differ