diff --git a/src/mictcp.c b/src/mictcp.c index aaaf766..0d932a4 100644 --- a/src/mictcp.c +++ b/src/mictcp.c @@ -6,21 +6,137 @@ #define COLOR_BOLD "\x1b[1m" #define COLOR_RESET "\x1b[0m" -#define LOSS_RATE 5 +#define DEBUG 1 + +#define LOSS_RATE 2 #define TIMEOUT 2 +#define MAX_LOSS_RATE 2 +#define LIST_LENGTH 200 struct mic_tcp_sock g_sock; int next_msg_num; +struct node { + int isSuccess; + struct node *previous; +}; + +struct { + struct node *head; + struct node *tail; + int size; + int errorNumber; +} list; + +/** + * Gets current loss rate + * + * @return + */ +int getLossRate() { + if (list.size > 0) + return (100 * list.errorNumber / list.size); + else + return 1; +} + +/** + * Checks if the current loss rate is acceptable + * + * @return + */ +int isLossAcceptable() { + return getLossRate() <= MAX_LOSS_RATE; +} + +/** + * Remove last element from the list and remove a success from count if removed element was a success + */ +void popLast() { + if (list.size > 0 ) { + struct node *last = list.tail; + list.tail = last->previous; + list.size--; + if (last->isSuccess != 1) + list.errorNumber--; + free(last); + } +} + +/** + * Inserts a new link at the front of the list. + * If the list has reached its max length after insertion, remove last element + * + * @param isSuccess + */ +void insertFirst(int isSuccess) { + struct node *link = (struct node*) malloc(sizeof(struct node)); + link->isSuccess = isSuccess; + link->previous = NULL; + + if (list.size > 0) + list.head->previous = link; + else + list.tail = link; + list.head = link; + + if (isSuccess != 1) + list.errorNumber++; + + list.size++; + + if (list.size > LIST_LENGTH) + popLast(); +} + +void clearList() { + while (list.size > 0) { + popLast(); + } +} + +/** + * Saves a network error in the list + */ +void saveError() { + insertFirst(0); +} + +/** + * Saves a network success in the list + */ +void saveSuccess() { + insertFirst(1); +} + +void printList() { + if (DEBUG) { + printf("========= LIST =========\n"); + printf("size: %d\n", list.size); + printf("errorNumber: %d\n", list.errorNumber); + printf("lossRate: %d\n", getLossRate()); + printf("isLossAcceptable: %d\n", isLossAcceptable()); + + if (list.size > 0) { + printf("head: %d\n", list.head->isSuccess); + printf("tail: %d\n", list.tail->isSuccess); + } + printf("========================\n"); + } +} + /** * Permet de créer un socket entre l’application et MIC-TCP. * @return le descripteur du socket ou bien -1 en cas d'erreur. */ int mic_tcp_socket(start_mode sm) { int result; - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } + result = initialize_components(sm); /* Appel obligatoire */ set_loss_rate(LOSS_RATE); @@ -28,6 +144,9 @@ int mic_tcp_socket(start_mode sm) { g_sock.state = IDLE; next_msg_num = 1; + list.size = 0; + list.errorNumber = 0; + return result; } @@ -36,9 +155,11 @@ int mic_tcp_socket(start_mode sm) { * @return 0 si succès, et -1 en cas d’échec. */ int mic_tcp_bind(int socket, mic_tcp_sock_addr addr) { - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } int result = 0; @@ -52,9 +173,11 @@ int mic_tcp_bind(int socket, mic_tcp_sock_addr addr) { * @return 0 si succès, -1 si erreur. */ int mic_tcp_accept(int socket, mic_tcp_sock_addr *addr) { - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } int result = 0; @@ -68,9 +191,11 @@ int mic_tcp_accept(int socket, mic_tcp_sock_addr *addr) { * @return 0 si la connexion est établie, et -1 en cas d’échec */ int mic_tcp_connect(int socket, mic_tcp_sock_addr addr) { - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } int result = 0; @@ -85,12 +210,15 @@ int mic_tcp_connect(int socket, mic_tcp_sock_addr addr) { * @return la taille des données envoyées, et -1 en cas d'erreur */ int mic_tcp_send(int socket, char *mesg, int mesg_size) { - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); - int result = -1; + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } + int result; + int errorDetected = 0; - while (result == -1) { + do { struct mic_tcp_pdu pdu; pdu.payload.data = mesg; pdu.payload.size = mesg_size; @@ -103,27 +231,39 @@ int mic_tcp_send(int socket, char *mesg, int mesg_size) { pdu.header.ack = 0; pdu.header.fin = 0; - printf("\n[MIC-TCP] Sending PDU\n"); + if (DEBUG) + printf("\n[MIC-TCP] Sending PDU\n"); + if ((result = IP_send(pdu, g_sock.addr)) != -1) { struct mic_tcp_pdu rcv_pdu; struct mic_tcp_sock_addr rcv_sock_addr; - printf("[MIC-TCP] Waiting for ACK\n"); + if (DEBUG) + printf("[MIC-TCP] Waiting for ACK\n"); + result = IP_recv(&rcv_pdu, &rcv_sock_addr, TIMEOUT); - if (result == -1) + if (result == -1 && DEBUG) printf("[MIC-TCP] "COLOR_BOLD"Timeout"COLOR_RESET"\n"); else if (rcv_pdu.header.ack_num != next_msg_num + 1) { - printf("[MIC-TCP] Received ACK: %d | "COLOR_RED"INVALID"COLOR_RESET"\n", rcv_pdu.header.ack_num); - printf("[MIC-TCP] | Expected: %d\n", next_msg_num + 1); - printf("[MIC-TCP] | Received: %d\n", rcv_pdu.header.ack_num); + if (DEBUG) { + printf("[MIC-TCP] Received ACK: %d | "COLOR_RED"INVALID"COLOR_RESET"\n", rcv_pdu.header.ack_num); + printf("[MIC-TCP] | Expected: %d\n", next_msg_num + 1); + printf("[MIC-TCP] | Received: %d\n", rcv_pdu.header.ack_num); + } result = -1; - } else + } else if (DEBUG) printf("[MIC-TCP] Received ACK: "COLOR_GREEN"VALID"COLOR_RESET"\n"); - } else + } else if (DEBUG) printf("[MIC-TCP] Ip_send "COLOR_RED"ERROR"COLOR_RESET"\n"); - } + + if (result == -1 && errorDetected == 0) { + errorDetected = 1; + saveError(); + }else + saveSuccess(); + printList(); + } while (result == -1 && isLossAcceptable() == 0); next_msg_num = next_msg_num + 1; - return result; } @@ -134,9 +274,11 @@ int mic_tcp_send(int socket, char *mesg, int mesg_size) { * NB : cette fonction fait appel à la fonction app_buffer_get() */ int mic_tcp_recv(int socket, char *mesg, int max_mesg_size) { - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } int result = -1; @@ -157,12 +299,14 @@ int mic_tcp_recv(int socket, char *mesg, int max_mesg_size) { * @return 0 si tout se passe bien et -1 en cas d'erreur */ int mic_tcp_close(int socket) { - printf("[MIC-TCP] Appel de la fonction : "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction : "); + printf(__FUNCTION__); + printf("\n"); + } g_sock.state = CLOSED; - + clearList(); return -1; } @@ -173,9 +317,11 @@ int mic_tcp_close(int socket) { * app_buffer_put(). */ void process_received_PDU(mic_tcp_pdu pdu, mic_tcp_sock_addr addr) { - printf("[MIC-TCP] Appel de la fonction: "); - printf(__FUNCTION__); - printf("\n"); + if (DEBUG) { + printf("[MIC-TCP] Appel de la fonction: "); + printf(__FUNCTION__); + printf("\n"); + } struct mic_tcp_pdu ack_pdu; ack_pdu.header.source_port = 0; @@ -185,17 +331,20 @@ void process_received_PDU(mic_tcp_pdu pdu, mic_tcp_sock_addr addr) { ack_pdu.header.ack = 0; ack_pdu.header.fin = 0; - if (pdu.header.seq_num == next_msg_num) { - next_msg_num = next_msg_num + 1; + if (pdu.header.seq_num >= next_msg_num) { + next_msg_num = pdu.header.seq_num + 1; app_buffer_put(pdu.payload); - printf("[MIC-TCP] Received PDU: "COLOR_GREEN"VALID"COLOR_RESET"\n"); - } else { + if (DEBUG) + printf("[MIC-TCP] Received PDU: "COLOR_GREEN"VALID"COLOR_RESET"\n"); + } else if (DEBUG) { printf("[MIC-TCP] Received PDU: "COLOR_RED"INVALID"COLOR_RESET"\n"); printf("[MIC-TCP] | Expected: %d\n", next_msg_num); printf("[MIC-TCP] | Received: %d\n", pdu.header.seq_num); } + if (DEBUG) + printf("[MIC-TCP] Sending ack: %d\n", next_msg_num); + ack_pdu.header.ack_num = next_msg_num; - printf("[MIC-TCP] Sending ack: %d\n", next_msg_num); IP_send(ack_pdu, addr); }