diff --git a/CMakeLists.txt b/CMakeLists.txt index 620ed08..472d62c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5) project(RN-Praxis) set(CMAKE_C_STANDARD 11) -add_executable(webserver webserver.c http.c util.c data.c) +add_executable(webserver webserver.c http.c util.c data.c dht.c lookup.c) target_compile_options(webserver PRIVATE -Wall -Wextra -Wpedantic) target_link_libraries(webserver PRIVATE -lm) diff --git a/dht.c b/dht.c index 6792f3d..b0d1502 100644 --- a/dht.c +++ b/dht.c @@ -1,14 +1,77 @@ #include "dht.h" +#include +#include +#include +#include +#include +#include +#include -#define cpy(x, y, z) char *x_c = x; char *y_c = y; while(*y_c && z--) *x_c++ = *y_c++ +// #define cpy(x, y, z) char *x_c = x; char *y_c = y; while(*y_c && z--) *x_c++ = *y_c++ -void lookup_request_init(lookup_request* lr, int node_id, char *node_ip, int node_port, uint16_t hash_id, char *node_request) +void build_lookup_request(lookup_request* lr){ + char *lrreq = lr->node_request; + snprintf(lr->node_request, HTTP_MAX_SIZE, "%d|%hd|%d|%s|%d\r\n\r\n", lr->message_type, lr->hash_id, lr->node_id, lr->node_ip, lr->node_port); +} + +void lookup_request_init(lookup_request* lr, int message_type, int node_id, char *node_ip, int node_port, uint16_t hash_id, char *node_request) { - int size = NODE_IP_MAX_SIZE; + lr->message_type = message_type; lr->node_id = node_id; - { cpy(lr->node_ip, node_ip, size); } + strncpy(lr->node_ip, node_ip, NODE_IP_MAX_SIZE); lr->node_port = node_port; lr->hash_id = hash_id; - size = HTTP_MAX_SIZE; - cpy(lr->node_request, node_request, size); + if(node_request != NULL) + strncpy(lr->node_request, node_request, HTTP_MAX_SIZE); + build_lookup_request(lr); +} + +void extract_lookup_request(lookup_request* lr, char* request){ + sscanf(request, "%d|%hd|%d|%s|%d\r\n\r\n", &lr->message_type, &lr->hash_id, &lr->node_id, lr->node_ip, &lr->node_port); +} + +int call_network(lookup_request* lr, char *ip, int port){ + int succ_sock; + struct addrinfo hints, *servinfo, *p; + int rv; + int numbytes; + + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + + char port_str[6]; + snprintf(port_str, sizeof port_str, "%d", port); + + if ((rv = getaddrinfo(ip, port_str, &hints, &servinfo)) != 0) { + fprintf(stderr, "Func: call_network - getaddrinfo: %s\n", gai_strerror(rv)); + return 1; + } + + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((succ_sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + perror("Func: call_network - socket"); + continue; + } + break; + } + + if (p == NULL) { + fprintf(stderr, "Func: call_network - failed to create socket\n"); + return 2; + } + + if ((numbytes = sendto(succ_sock, lr->node_request, strlen(lr->node_request), 0, p->ai_addr, p->ai_addrlen)) == -1) { + perror("Func: call_network - sendto"); + exit(1); + } + + freeaddrinfo(servinfo); + close(succ_sock); + + return 0; +} + +void clone_lookup_request(lookup_request* dest, lookup_request* source){ + memcpy(dest, source, sizeof(lookup_request)); } diff --git a/dht.h b/dht.h index 2a7839d..3b1cd30 100644 --- a/dht.h +++ b/dht.h @@ -5,6 +5,7 @@ #define NODE_IP_MAX_SIZE 16 typedef struct{ + int message_type; int node_id; char node_ip[NODE_IP_MAX_SIZE]; int node_port; @@ -14,7 +15,13 @@ typedef struct{ char node_request[HTTP_MAX_SIZE]; }lookup_request; -void lookup_request_init(lookup_request*, int node_id, char *node_ip, int node_port, uint16_t hash_id, char *node_request); -void create_lookup_request(lookup_request*, char *request); +void lookup_request_init(lookup_request*, int message_type, int node_id, char *node_ip, int node_port, uint16_t hash_id, char *node_request); +void build_lookup_request(lookup_request*); + +void extract_lookup_request(lookup_request*, char*); + +int call_network(lookup_request*, char*, int); + +void clone_lookup_request(lookup_request* dest, lookup_request* source); #endif //DHT_H diff --git a/lookup.c b/lookup.c new file mode 100644 index 0000000..4b82bb4 --- /dev/null +++ b/lookup.c @@ -0,0 +1,58 @@ +#include "lookup.h" + +void init_lookup_table() +{ + table = malloc(sizeof(lookup_head)); + if (table == NULL) return; + table->head = NULL; +} + +void push_lookup(lookup_request *request) +{ + if (free_space == 0) + { + lookup_table *infront = table->head; + while (infront->next != NULL && infront->next->next != NULL) + { + infront = infront->next; + } + + free(infront->next->request); + free(infront->next); + infront->next = NULL; + // if malloc fails this does not leak space + free_space++; + } + + lookup_table *new = (lookup_table*)malloc(sizeof(lookup_table)); + if (new == NULL) return; + new->request = request; + new->next = table->head; + table->head = new; + free_space--; +} + +lookup_request *find_lookup(const uint16_t hash_id) +{ + const lookup_table *current = table->head; + while (current != NULL && current->request->hash_id != hash_id) + current = current->next; + return current == NULL ? NULL : current->request; +} + +void free_lookup_table() +{ + if (table == NULL) return; + lookup_table *current = table->head; + + while (current != NULL) + { + lookup_table *temp = current; + current = current->next; + free(temp->request); + free(temp); + } + free(table); + table = NULL; + free_space = TABLE_SIZE; +} diff --git a/lookup.h b/lookup.h new file mode 100644 index 0000000..6454592 --- /dev/null +++ b/lookup.h @@ -0,0 +1,29 @@ +#ifndef LOOKUP_H +#define LOOKUP_H +#include "dht.h" + +#define TABLE_SIZE 10 + +typedef struct lookup_table +{ + lookup_request *request; + struct lookup_table *next; +}lookup_table; + +typedef struct lookup_head +{ + lookup_table *head; +}lookup_head; + +static lookup_head *table; +static int free_space = TABLE_SIZE; + +void init_lookup_table(); + +void push_lookup(lookup_request *request); + +lookup_request *find_lookup(const uint16_t hash_id); + +void free_lookup_table(); + +#endif //LOOKUP_H diff --git a/webserver.c b/webserver.c index dd78eb7..16353eb 100644 --- a/webserver.c +++ b/webserver.c @@ -16,6 +16,8 @@ #include "data.h" #include "http.h" #include "util.h" +#include "dht.h" +#include "lookup.h" #define elif else if @@ -31,7 +33,7 @@ bool _DO_UDP = false; int _NODE_ID; const char *_NODE_IP; -const char *_NODE_PORT; +int _NODE_PORT; #define MAX_RESOURCES 100 @@ -87,6 +89,21 @@ void send_reply(int conn, struct request *request) { uint16_t resource_hash = hash_uri(request->uri); neighbor responsible = check_neighborhood(resource_hash); + lookup_request *req = find_lookup(resource_hash); + if (req != NULL) + { + if (req->message_type != 1) + { + printf("404\n"); + reply = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"; + offset = strlen(reply); + } + else + { + + } + } + if (responsible == res) { sprintf(reply, "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); offset = strlen(reply); @@ -94,9 +111,19 @@ void send_reply(int conn, struct request *request) { } elif(responsible == res_303) { - sprintf(reply, "HTTP/1.1 303 See Other\r\nLocation: http://%s:%d%s\r\nContent-Length: 0\r\n\r\n", _SUCC_IP, _SUCC_PORT, request->uri); - offset = strlen(reply); - printf("303\n"); + int suc_id = _SUCC_ID; + if (resource_hash <= suc_id || suc_id >= 0 && suc_id < _NODE_ID) + { + printf("404\n"); + reply = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"; + offset = strlen(reply); + } + else + { + sprintf(reply, "HTTP/1.1 303 See Other\r\nLocation: http://%s:%d%s\r\nContent-Length: 0\r\n\r\n", _SUCC_IP, _SUCC_PORT, request->uri); + offset = strlen(reply); + printf("303\n"); + } } elif(responsible == not_res) { @@ -104,6 +131,10 @@ void send_reply(int conn, struct request *request) { offset = strlen(reply); printf("503\n"); // TODO: Call other dht + lookup_request lookreq; + lookup_request_init(&lookreq, 0, _NODE_ID, (char*)_NODE_IP, _NODE_PORT, resource_hash, NULL); + + call_network(&lookreq, _SUCC_IP, _SUCC_PORT); } else { printf("404\n"); @@ -364,16 +395,15 @@ neighbor check_neighborhood(uint16_t hash) { int suc_id = _SUCC_ID; if(pre_id == suc_id){ - if(hash <= id && hash > suc_id) return res_303; - if(hash > id && hash <= suc_id) return not_res; - return res_303; // hash is in between suc and 0 + if(hash > id && hash <= suc_id) return res_303; + return res; } // TODO: check correctness if ((pre_id == id && suc_id == id) || (id < pre_id && ((hash > pre_id && hash < 65535)) || hash <= id) || (hash > pre_id && hash <= id)) return res; - if ((id < suc_id && hash > id && hash <= suc_id) || (hash > id || hash <= suc_id)) + if ((id < suc_id && hash > id && hash <= suc_id) || (id > suc_id && (hash > id || hash <= suc_id))) return not_res; return dunno; @@ -403,45 +433,60 @@ static void handle_udp_request(int _sock){ // HASH Received // TODO: alter buffer - uint16_t hash = atoi(buffer); - printf("Hash: %u\n", hash); - // Check belonging - int pre_id = _PRED_ID; - int suc_id = _SUCC_ID; - neighbor responsibility = check_neighborhood(hash); + lookup_request lr = {0}; + extract_lookup_request(&lr, buffer); - if (responsibility == res) { - char res[] = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"; - if (sendto(_sock, res, strlen(res), 0, (struct sockaddr *) &caller_addr, addrlen) == -1) { - perror("Func: handle_udp_request - failed to send 200 data to caller!"); - exit(EXIT_FAILURE); - } - printf("Sent: %s", res); - } -/* - TODO: return 404 - elif (responsibility == res_303) { - fprintf(stderr, "Sent 303!\n"); - char res[1024] = {0}; - snprintf(res, 1024, "HTTP/1.1 303 See Other\r\nLocation: http://%s:%s/%d\r\nContent-Length: 0\r\n\r\n", _NODE_IP, _NODE_PORT, suc_id); - if(sendto(_sock, res, strlen(res), 0, (struct sockaddr *) &caller_addr, addrlen) == -1){ - perror("Func: handle_udp_request - failed to send 303 data to caller!"); - exit(EXIT_FAILURE); - } - printf("Sent: %s", res); - } - */ - elif (responsibility == not_res) { - // TODO: DIRECT TO NEXT NODE - const char res[] = "HTTP/1.1 503 Service Unavailable\r\nRetry-After: 1\r\nContent-Length: 0\r\n\r\n"; - if(sendto(_sock, res, strlen(res), 0, (struct sockaddr *) &caller_addr, addrlen) == -1) + printf("Received:\n\tMessage-type: %d\n\tlookup-hash: %hd\n", lr.message_type, lr.hash_id); + + // DO LOOKUP + if (lr.message_type == 0) + { + // Check belonging + const int suc_id = _SUCC_ID; + char *callback_ip = lr.node_ip; + int callback_port = lr.node_port; + + lookup_request backfire = {0}; + + if (lr.node_id == suc_id) { - perror("Func: handle_udp_request - failed to send 503 data to caller!"); - exit(EXIT_FAILURE); + // Send back 404 not found + clone_lookup_request(&backfire, &lr); + backfire.message_type = -1; } - printf("Sent: %s", res); + else + { + const neighbor responsibility = check_neighborhood(lr.hash_id); + + if (responsibility == res) { + lookup_request_init(&backfire, 1, _NODE_ID, (char*)_NODE_IP, _NODE_PORT, _PRED_ID, lr.node_request); + } + elif (responsibility == not_res) { + // is succ responsible + if (lr.hash_id <= suc_id) + { + lookup_request_init(&backfire, 1, suc_id, _SUCC_IP, _SUCC_PORT, _NODE_ID, lr.node_request); + } + else + { + lookup_request_init(&backfire, 1, suc_id, _SUCC_IP, _SUCC_PORT, _NODE_ID, lr.node_request); + callback_ip = _SUCC_IP; // TODO: Check validity + callback_port = _SUCC_PORT; + } + } + } + call_network(&backfire, callback_ip, callback_port); + } + elif (lr.message_type == 1) + { + lookup_request *toLookup = malloc(sizeof(lookup_request)); + clone_lookup_request(toLookup, &lr); + + push_lookup(toLookup); + } + else + { - //call_other_dht(); } } @@ -457,11 +502,13 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + init_lookup_table(); + if(argc == 3) _NODE_ID = 0; elif(argc == 4) _NODE_ID = atoi(argv[3]); // Set this DHT-Nodes ID - _NODE_PORT = argv[2]; + _NODE_PORT = atoi(argv[2]); _NODE_IP = argv[1]; struct sockaddr_in addr = derive_sockaddr(argv[1], argv[2]); @@ -534,6 +581,6 @@ int main(int argc, char **argv) { } } } - + free_lookup_table(); return EXIT_SUCCESS; }