diff --git a/Makefile b/Makefile index 7a711d6..9a4e8c9 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ vpath %.c $(SRC_DIR) define make-goal $1/%.o: %.c - $(CC) -ansi -Wall -m32 -g -I $(INCLUDES) -c $$< -o $$@ + $(CC) -std=gnu99 -Wall -m32 -g -I $(INCLUDES) -c $$< -o $$@ endef .PHONY: all checkdirs clean @@ -33,13 +33,13 @@ endef all: checkdirs build/client build/server build/gateway build/client: $(OBJ_CLI) - $(LD) -m32 $^ -o $@ -lpthread + $(LD) -m32 $^ -o $@ -lm -lpthread build/server: $(OBJ_SERV) - $(LD) -m32 $^ -o $@ -lpthread + $(LD) -m32 $^ -o $@ -lm -lpthread build/gateway: $(OBJ_GWAY) - $(LD) -m32 $^ -o $@ -lpthread + $(LD) -m32 $^ -o $@ -lm -lpthread checkdirs: $(BUILD_DIR) diff --git a/include/api/mictcp_core.h b/include/api/mictcp_core.h index 558fa6a..7b43a33 100644 --- a/include/api/mictcp_core.h +++ b/include/api/mictcp_core.h @@ -11,9 +11,9 @@ int initialize_components(start_mode sm); int IP_send(mic_tcp_pdu, mic_tcp_sock_addr); -int IP_recv(mic_tcp_payload*, mic_tcp_sock_addr*, unsigned long delay); +int IP_recv(ip_payload*, mic_tcp_sock_addr*, unsigned long timeout); int app_buffer_get(mic_tcp_payload); -void app_buffer_set(mic_tcp_payload); +void app_buffer_put(mic_tcp_payload); void set_loss_rate(unsigned short); unsigned long get_now_time_msec(); @@ -25,14 +25,14 @@ unsigned long get_now_time_usec(); #define API_CS_Port 8524 #define API_SC_Port 8525 +#define API_HD_Size 15 -int full_send(mic_tcp_payload); -int partial_send(mic_tcp_payload); +int mic_tcp_core_send(mic_tcp_payload); mic_tcp_payload get_full_stream(mic_tcp_pdu); -mic_tcp_payload get_data_stream(mic_tcp_payload); -mic_tcp_header get_header(char*); +mic_tcp_payload get_mic_tcp_data(ip_payload); +mic_tcp_header get_mic_tcp_header(ip_payload); void* listening(void*); -void print_header(mic_tcp_payload); +void print_header(mic_tcp_pdu); int min_size(int, int); float mod(int, float); diff --git a/include/mictcp.h b/include/mictcp.h index b7d7c66..2df4a12 100644 --- a/include/mictcp.h +++ b/include/mictcp.h @@ -82,6 +82,16 @@ typedef struct mic_tcp_pdu mic_tcp_payload payload; /* charge utile du PDU */ } mic_tcp_pdu; +/* + * Structure des données utiles d’un PDU IP + */ +typedef struct ip_payload +{ + char* data; /* données transport */ + int size; /* taille des données */ +} ip_payload; + + typedef struct app_buffer { mic_tcp_payload packet; @@ -102,23 +112,4 @@ int mic_tcp_recv (int socket, char* mesg, int max_mesg_size); void process_received_PDU(mic_tcp_pdu pdu); int mic_tcp_close(int socket); -/********************** - * Variables globales * - **********************/ -mic_tcp_sock local_sock_src; -mic_tcp_sock local_sock_dest; -unsigned long timer; -unsigned long RTT1; -unsigned long RTT2; -int PE; -int PA; -float pourcentage_perte_client; -float pourcentage_perte_serveur; -float compteurDT; -float DTperdu; -mic_tcp_pdu DT; -mic_tcp_pdu Syn; -mic_tcp_pdu Ack; -mic_tcp_pdu Syn_Ack; - #endif diff --git a/src/api/mictcp_core.c b/src/api/mictcp_core.c index 6499abb..624c42c 100644 --- a/src/api/mictcp_core.c +++ b/src/api/mictcp_core.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -12,12 +13,8 @@ int initialized = -1; int sys_socket; pthread_t listen_th; pthread_mutex_t lock; -float loss_rate = 0.0f; -float jump = 0; -float range = 0; -int count = 0; -int reverse = 1; - +unsigned short loss_rate = 0; +struct sockaddr_in remote_addr; /* This is for the buffer */ TAILQ_HEAD(tailhead, app_buffer_entry) app_buffer_head; @@ -27,15 +24,17 @@ struct app_buffer_entry { TAILQ_ENTRY(app_buffer_entry) entries; }; +/* Condition variable used for passive wait when buffer is empty */ +pthread_cond_t buffer_empty_cond; + /************************* * Fonctions Utilitaires * *************************/ int initialize_components(start_mode mode) { int bnd; - struct sockaddr_in local_addr; - struct sockaddr_in remote_addr; struct hostent * hp; + struct sockaddr_in local_addr; if(initialized != -1) return initialized; if((sys_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return -1; @@ -44,6 +43,7 @@ int initialize_components(start_mode mode) if((mode == SERVER) & (initialized != -1)) { TAILQ_INIT(&app_buffer_head); + pthread_cond_init(&buffer_empty_cond, 0); memset((char *) &local_addr, 0, sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(API_CS_Port); @@ -56,7 +56,7 @@ int initialize_components(start_mode mode) } else { - memset((char *) &remote_addr, 0, sizeof(local_addr)); + memset((char *) &remote_addr, 0, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(API_SC_Port); hp = gethostbyname("localhost"); @@ -70,7 +70,7 @@ int initialize_components(start_mode mode) { if(initialized != -1) { - memset((char *) &remote_addr, 0, sizeof(local_addr)); + memset((char *) &remote_addr, 0, sizeof(remote_addr)); remote_addr.sin_family = AF_INET; remote_addr.sin_port = htons(API_CS_Port); hp = gethostbyname("localhost"); @@ -96,101 +96,100 @@ int initialize_components(start_mode mode) int IP_send(mic_tcp_pdu pk, mic_tcp_sock_addr addr) { - if(initialized == -1) return -1; - if(loss_rate == 0) - { + + int result = 0; + + if(initialized == -1) { + result = -1; + + } else { mic_tcp_payload tmp = get_full_stream(pk); - int sent_size = full_send(tmp); + int sent_size = mic_tcp_core_send(tmp); free (tmp.data); - return sent_size; + result = sent_size; } - else return partial_send(get_full_stream(pk)); + + return result; } -int IP_recv(mic_tcp_payload* pk,mic_tcp_sock_addr* addr, unsigned long delay) +int IP_recv(ip_payload* pk,mic_tcp_sock_addr* addr, unsigned long timeout) { + int result = -1; + struct timeval tv; struct sockaddr_in tmp_addr; socklen_t tmp_addr_size = sizeof(struct sockaddr); /* Send data over a fake IP */ - if(initialized == -1) return -1; - - if(delay == 0) {tv.tv_sec = 3600; tv.tv_usec = 0;} - else {tv.tv_sec = 0; tv.tv_usec = delay;} - if (setsockopt(sys_socket, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0) { + if(initialized == -1) { return -1; - } - - else - { - int recv_size = recvfrom(sys_socket, pk->data, pk->size, 0, (struct sockaddr *)&tmp_addr, &tmp_addr_size); - pk->size = recv_size; - return recv_size; } + + /* Compute the number of entire seconds */ + tv.tv_sec = timeout / 1000; + /* Convert the remainder to microseconds */ + tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000; + if ((setsockopt(sys_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) >= 0) { + result = recvfrom(sys_socket, pk->data, pk->size, 0, (struct sockaddr *)&tmp_addr, &tmp_addr_size); + pk->size = result; + } + + return result; } mic_tcp_payload get_full_stream(mic_tcp_pdu pk) { /* Get a full packet from data and header */ mic_tcp_payload tmp; - tmp.size = 15 + pk.payload.size; + tmp.size = API_HD_Size + pk.payload.size; tmp.data = malloc (tmp.size); - memcpy (tmp.data, &pk.header, 15); - memcpy (tmp.data + 15, pk.payload.data, pk.payload.size); + memcpy (tmp.data, &pk.header, API_HD_Size); + memcpy (tmp.data + API_HD_Size, pk.payload.data, pk.payload.size); return tmp; } -mic_tcp_payload get_data_stream(mic_tcp_payload buff) +mic_tcp_payload get_mic_tcp_data(ip_payload buff) { mic_tcp_payload tmp; - tmp.data = malloc(buff.size-15); - memcpy(tmp.data, buff.data+15, tmp.size); + tmp.size = buff.size-API_HD_Size; + tmp.data = malloc(tmp.size); + memcpy(tmp.data, buff.data+API_HD_Size, tmp.size); return tmp; } -mic_tcp_header get_header(char* packet) +mic_tcp_header get_mic_tcp_header(ip_payload packet) { /* Get a struct header from an incoming packet */ mic_tcp_header tmp; - memcpy(&tmp, packet, 15); - return tmp; -} - -mic_tcp_payload get_data(mic_tcp_payload packet) -{ - mic_tcp_payload tmp; - tmp.size = packet.size - 15; - tmp.data = malloc(tmp.size); - memcpy(tmp.data, packet.data + 15, tmp.size); + memcpy(&tmp, packet.data, API_HD_Size); return tmp; } int full_send(mic_tcp_payload buff) { - struct sockaddr_in remote_addr; int result = 0; - result = sendto(sys_socket, buff.data, buff.size, 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)); + result = sendto(sys_socket, buff.data, buff.size, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr)); return result; } -int partial_send(mic_tcp_payload buff) +int mic_tcp_core_send(mic_tcp_payload buff) { - struct sockaddr_in remote_addr; int random = rand(); int result = buff.size; - int lr_tresh = (int) round(loss_rate*RAND_MAX); + int lr_tresh = (int) round(((float)loss_rate/100.0)*RAND_MAX); - if(random > lr_thresh) { + if(random > lr_tresh) { result = sendto(sys_socket, buff.data, buff.size, 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)); + } else { + printf("[MICTCP-CORE] Perte du paquet\n"); } return result; @@ -204,11 +203,19 @@ int app_buffer_get(mic_tcp_payload app_buff) /* The actual size passed to the application */ int result = 0; + /* Lock a mutex to protect the buffer from corruption */ + pthread_mutex_lock(&lock); + /* If the buffer is empty, we wait for insertion */ while(app_buffer_head.tqh_first == NULL) { - usleep(1000); + pthread_cond_wait(&buffer_empty_cond, &lock); } + /* When we execute the code below, the following conditions are true: + - The buffer contains at least 1 element + - We hold the lock on the mutex + */ + /* The entry we want is the first one in the buffer */ entry = app_buffer_head.tqh_first; @@ -218,9 +225,6 @@ int app_buffer_get(mic_tcp_payload app_buff) /* We copy the actual data in the application allocated buffer */ memcpy(app_buff.data, entry->bf.data, result); - /* Lock a mutex to protect the buffer from corruption */ - pthread_mutex_lock(&lock); - /* We remove the entry from the buffer */ TAILQ_REMOVE(&app_buffer_head, entry, entries); @@ -234,7 +238,7 @@ int app_buffer_get(mic_tcp_payload app_buff) return result; } -void app_buffer_set(mic_tcp_payload bf) +void app_buffer_put(mic_tcp_payload bf) { /* Prepare a buffer entry to store the data */ struct app_buffer_entry * entry = malloc(sizeof(struct app_buffer_entry)); @@ -248,6 +252,10 @@ void app_buffer_set(mic_tcp_payload bf) /* Release the mutex */ pthread_mutex_unlock(&lock); + + /* We can now signal to any potential thread waiting that the buffer is + no longer empty */ + pthread_cond_broadcast(&buffer_empty_cond); } @@ -257,7 +265,7 @@ void* listening(void* arg) mic_tcp_pdu pdu_tmp; int recv_size; mic_tcp_sock_addr remote; - mic_tcp_payload tmp_buff; + ip_payload tmp_buff; pthread_mutex_init(&lock, NULL); @@ -274,9 +282,12 @@ void* listening(void* arg) if(recv_size > 0) { - pdu_tmp.header = get_header (tmp_buff.data); - pdu_tmp.payload = get_data (tmp_buff); + pdu_tmp.header = get_mic_tcp_header (tmp_buff); + pdu_tmp.payload = get_mic_tcp_data (tmp_buff); process_received_PDU(pdu_tmp); + } else { + /* This should never happen */ + printf("Error in recv\n"); } } } @@ -284,12 +295,12 @@ void* listening(void* arg) void set_loss_rate(unsigned short rate) { - loss_rate = ((float) rate) / 100.0; + loss_rate = rate; } -void print_header(mic_tcp_payload bf) +void print_header(mic_tcp_pdu bf) { - mic_tcp_header hd = get_header(bf.data); + mic_tcp_header hd = bf.header; printf("\nSP: %d, DP: %d, SEQ: %d, ACK: %d", hd.source_port, hd.dest_port, hd.seq_num, hd.ack_num); } diff --git a/src/mictcp.c b/src/mictcp.c index d89b824..10f3db6 100644 --- a/src/mictcp.c +++ b/src/mictcp.c @@ -7,9 +7,12 @@ */ int mic_tcp_socket(start_mode sm) { + int result = -1; printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); - initialize_components(sm); /* Appel obligatoire */ - return -1; + result = initialize_components(sm); /* Appel obligatoire */ + set_loss_rate(0); + + return result; } /* @@ -45,7 +48,6 @@ int mic_tcp_connect(int socket, mic_tcp_sock_addr addr) /* * Permet de réclamer l’envoi d’une donnée applicative * Retourne la taille des données envoyées, et -1 en cas d'erreur - * Dans le cas de la vidéo, seul la source va envoyer au puits */ int mic_tcp_send (int mic_sock, char* mesg, int mesg_size) { @@ -62,7 +64,7 @@ int mic_tcp_send (int mic_sock, char* mesg, int mesg_size) int mic_tcp_recv (int socket, char* mesg, int max_mesg_size) { printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); - return -1; + return -1; } /* @@ -80,7 +82,7 @@ int mic_tcp_close (int socket) * Traitement d’un PDU MIC-TCP reçu (mise à jour des numéros de séquence * et d'acquittement, etc.) puis insère les données utiles du PDU dans * le buffer de réception du socket. Cette fonction utilise la fonction - * app_buffer_add(). + * app_buffer_put(). */ void process_received_PDU(mic_tcp_pdu pdu) { diff --git a/tsock_texte b/tsock_texte old mode 100644 new mode 100755 diff --git a/tsock_video b/tsock_video old mode 100644 new mode 100755 diff --git a/video/video_starwars.bin b/video/video_starwars.bin new file mode 100644 index 0000000..8d70bc7 Binary files /dev/null and b/video/video_starwars.bin differ diff --git a/video/video_wildlife.bin b/video/video_wildlife.bin new file mode 100644 index 0000000..79ec6df Binary files /dev/null and b/video/video_wildlife.bin differ