commit dc58e0e2d56bbbaca1d982752478338165fab7cb Author: Nicolas Van Wambeke Date: Mon Jun 13 23:17:19 2016 +0200 Initial Import diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3724c06 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +CC := gcc +LD := gcc + +MODULES := api apps +SRC_DIR := $(addprefix src/,$(MODULES)) src +BUILD_DIR := $(addprefix build/,$(MODULES)) build + +SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) +OBJ := $(patsubst src/%.c,build/%.o,$(SRC)) +OBJ_CLI := $(patsubst build/apps/gateway.o,,$(patsubst build/apps/server.o,,$(OBJ))) +OBJ_SERV := $(patsubst build/apps/gateway.o,,$(patsubst build/apps/client.o,,$(OBJ))) +OBJ_GWAY := $(patsubst build/apps/server.o,,$(patsubst build/apps/client.o,,$(OBJ))) +INCLUDES := include + +vpath %.c $(SRC_DIR) + +define make-goal +$1/%.o: %.c + $(CC) -m32 -g -I $(INCLUDES) -c $$< -o $$@ +endef + +.PHONY: all checkdirs clean + +all: checkdirs build/client build/server build/gateway + +build/client: $(OBJ_CLI) + $(LD) -m32 $^ -o $@ -lpthread + +build/server: $(OBJ_SERV) + $(LD) -m32 $^ -o $@ -lpthread + +build/gateway: $(OBJ_GWAY) + $(LD) -m32 $^ -o $@ -lpthread + +checkdirs: $(BUILD_DIR) + +$(BUILD_DIR): + @mkdir -p $@ + +clean: + @rm -rf $(BUILD_DIR) + +$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir)))) diff --git a/include/api/mictcp_core.h b/include/api/mictcp_core.h new file mode 100644 index 0000000..5e07c3b --- /dev/null +++ b/include/api/mictcp_core.h @@ -0,0 +1,31 @@ +#ifndef MICTCP_CORE_H +#define MICTCP_CORE_H + +#include +#include + +// Public core functions, can be used for implementing mictcp +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 app_buffer_get(mic_tcp_payload); +int app_buffer_set(mic_tcp_payload); + +void set_loss_rate(unsigned short); +unsigned long get_now_time_msec(); +unsigned long get_now_time_usec(); + +// Private core functions, should not be used for implementing mictcp +int full_send(mic_tcp_payload); +int partial_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*); +void* listening(void*); +void print_header(mic_tcp_payload); + +int min_size(int, int); +float mod(int, float); + +#endif diff --git a/include/mictcp.h b/include/mictcp.h new file mode 100644 index 0000000..cda91a0 --- /dev/null +++ b/include/mictcp.h @@ -0,0 +1,106 @@ +#ifndef MICTCP_H +#define MICTCP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Etats du protocole (les noms des états sont donnés à titre indicatif +// et peuvent être modifiés) +typedef enum protocol_state +{ + IDLE, CLOSED, SYN_SENT, SYN_RECEIVED, ESTABLISHED, CLOSING +} protocol_state; + +// Mode de démarrage du protocole +// NB : nécessaire à l’usage de la fonction initialize_components() +typedef enum start_mode { CLIENT, SERVER } start_mode; + +// Structure d’une adresse de socket +typedef struct mic_tcp_sock_addr +{ + char * ip_addr; + int ip_addr_size; + unsigned short port; +} mic_tcp_sock_addr; + +// Structure d'un socket +typedef struct mic_tcp_sock +{ + int fd; // descripteur du socket + protocol_state state; // état du protocole + mic_tcp_sock_addr addr; // adresse du socket +} mic_tcp_sock; + +// Structure des données utiles d’un PDU MIC-TCP +typedef struct mic_tcp_payload +{ + char* data; // données applicatives + int size; // taille des données +} mic_tcp_payload; + +// Structure de l'entête d'un PDU MIC-TCP +typedef struct mic_tcp_header +{ + unsigned short source_port; // numéro de port source + unsigned short dest_port; // numéro de port de destination + unsigned int seq_num; // numéro de séquence + unsigned int ack_num; // numéro d'acquittement + unsigned char syn; // flag SYN (valeur 1 si activé et 0 si non) + unsigned char ack; // flag ACK (valeur 1 si activé et 0 si non) + unsigned char fin; // flag FIN (valeur 1 si activé et 0 si non) +} mic_tcp_header; + +// Structure d'un PDU MIC-TCP +typedef struct mic_tcp_pdu +{ + mic_tcp_header header ; // entête du PDU + mic_tcp_payload payload; // charge utile du PDU ⇔ données applicatives +} mic_tcp_pdu; + +typedef struct app_buffer +{ + mic_tcp_payload packet; + struct app_buffer* next; + unsigned short id; +} app_buffer; + + +// Fonctions de l'interface +int mic_tcp_socket(start_mode sm); +int mic_tcp_bind(int socket, mic_tcp_sock_addr addr); +int mic_tcp_accept(int socket, mic_tcp_sock_addr* addr); +int mic_tcp_connect(int socket, mic_tcp_sock_addr addr); +int mic_tcp_send (int socket, char* mesg, int mesg_size); +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 new file mode 100644 index 0000000..6323a22 --- /dev/null +++ b/src/api/mictcp_core.c @@ -0,0 +1,326 @@ +#include +#include + +// API Variables +int first_free = 0; +int initialized = -1; +int sys_socket; +unsigned short API_CS_Port = 8524; +unsigned short API_SC_Port = 8525; +float reliability = 100; +mic_tcp_sock current_socket; +int exite_status = -1; +pthread_t listen_th; +pthread_mutex_t lock; +unsigned int global_id = 0; +unsigned short loss_rate = 0; +float jump = 0; +float range = 0; +int count = 0; +int reverse = 1; + +struct sockaddr_in local_addr, remote_addr, tmp_addr; +int local_size, remote_size, tmp_addr_size; + +app_buffer* app_buffer_first = NULL; +app_buffer* app_buffer_last = NULL; +unsigned int app_buffer_size = 0; +unsigned int app_buffer_count = 0; + +// Fonctions Utilitaires + +int initialize_components(start_mode mode) +{ + int s; + if(initialized != -1) return initialized; + if((sys_socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return -1; + else initialized = 1; + + if((mode == SERVER) & (initialized != -1)) + { + memset((char *) &local_addr, 0, sizeof(local_addr)); + local_addr.sin_family = AF_INET; + local_addr.sin_port = htons(API_CS_Port); + local_addr.sin_addr.s_addr = htonl(INADDR_ANY); + int bnd = bind(sys_socket, (struct sockaddr *) &local_addr, sizeof(local_addr)); + + if (bnd == -1) + { + initialized = -1; + } + else + { + memset((char *) &remote_addr, 0, sizeof(local_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(API_SC_Port); + struct hostent * hp = gethostbyname("localhost"); + bcopy ( hp->h_addr, &(remote_addr.sin_addr.s_addr), hp->h_length); + remote_size = sizeof(remote_addr); + initialized = 1; + } + + + } + else + { + if(initialized != -1) + { + memset((char *) &remote_addr, 0, sizeof(local_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(API_CS_Port); + struct hostent * hp = gethostbyname("localhost"); + bcopy ( hp->h_addr, &(remote_addr.sin_addr.s_addr), hp->h_length); + remote_size = sizeof(remote_addr); + + memset((char *) &local_addr, 0, sizeof(local_addr)); + local_addr.sin_family = AF_INET; + local_addr.sin_port = htons(API_SC_Port); + local_addr.sin_addr.s_addr = htonl(INADDR_ANY); + int bnd = bind(sys_socket, (struct sockaddr *) &local_addr, sizeof(local_addr)); + } + } + + if((initialized == 1) && (mode == SERVER)) + { + pthread_create (&listen_th, NULL, listening, "1"); + } + + return initialized; +} + + + +int IP_send(mic_tcp_pdu pk, mic_tcp_sock_addr addr) +{ + if(initialized == -1) return -1; + if(loss_rate == 0) + { + mic_tcp_payload tmp = get_full_stream(pk); + int sent_size = full_send(tmp); + + free (tmp.data); + + return sent_size; + } + else return partial_send(get_full_stream(pk)); +} + +int IP_recv(mic_tcp_payload* pk,mic_tcp_sock_addr* addr, unsigned long delay) +{ + // Send data over a fake IP + if(initialized == -1) return -1; + + struct timeval tv; + + 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) { + 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; + } + +} + +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.data = malloc (tmp.size); + + memcpy (tmp.data, &pk.header, 15); + memcpy (tmp.data + 15, pk.payload.data, pk.payload.size); + + return tmp; +} + +mic_tcp_payload get_data_stream(mic_tcp_payload buff) +{ + mic_tcp_payload tmp; + tmp.data = malloc(buff.size-15); + memcpy(tmp.data, buff.data+15, tmp.size); + return tmp; +} + + +mic_tcp_header get_header(char* 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); + return tmp; +} + +int full_send(mic_tcp_payload buff) +{ + return sendto(sys_socket, buff.data, buff.size, 0, (struct sockaddr *)&remote_addr, remote_size); +} + +int partial_send(mic_tcp_payload buff) +{ + count ++; + + if(range == 0) + { + jump = 1000.0 /((float) loss_rate); + range += jump; + } + + + if(((int)range) == count) + { + reverse = -reverse; + jump = 1000.0 /((float) loss_rate); + range += jump + ( (jump / 4) * reverse); + printf("\n -- Lost\n"); + return buff.size; + } + else + { + return sendto(sys_socket, buff.data, buff.size, 0, (struct sockaddr *)&remote_addr, remote_size); + } + +} + +int app_buffer_get(mic_tcp_payload app_buff) +{ + while(app_buffer_count == 0) + { + usleep(1000); + } + + mic_tcp_payload tmp; + + app_buffer* current; + if(app_buffer_count > 0) + { + pthread_mutex_lock(&lock); + tmp.size = app_buffer_first->packet.size; + tmp.data = app_buffer_first->packet.data; + + current = app_buffer_first; + if(app_buffer_count == 1) + { + app_buffer_first = app_buffer_last = NULL; + } + else + { + app_buffer_first = app_buffer_first->next; + } + + memcpy(app_buff.data, tmp.data, min_size(tmp.size, app_buff.size)); + + app_buffer_size -= tmp.size; + app_buffer_count --; + free(current); + free(tmp.data); + + pthread_mutex_unlock(&lock); + + return tmp.size; + } +} + +int app_buffer_set(mic_tcp_payload bf) +{ + + pthread_mutex_lock(&lock); + + app_buffer* tmp = malloc(sizeof(app_buffer)); + tmp->packet.size = bf.size; + tmp->packet.data = malloc(bf.size); + tmp->id = global_id++; + memcpy(tmp->packet.data, bf.data, bf.size); + tmp->next = NULL; + + if(app_buffer_count == 0) + { + app_buffer_first = app_buffer_last = tmp; + } + else + { + app_buffer_last->next = tmp; + app_buffer_last = tmp; + } + + app_buffer_size += bf.size; + app_buffer_count ++; + + pthread_mutex_unlock(&lock); +} + + + +void* listening(void* arg) +{ + pthread_mutex_init(&lock, NULL); + + printf("[MICTCP-CORE] Demarrage du thread de reception reseau...\n"); + + mic_tcp_payload tmp_buff; + tmp_buff.size = 1500; + tmp_buff.data = malloc(1500); + + mic_tcp_pdu pdu_tmp; + int recv_size; + mic_tcp_sock_addr remote; + + while(1) + { + tmp_buff.size = 1500; + recv_size = IP_recv(&tmp_buff, &remote, 0); + + if(recv_size > 0) + { + pdu_tmp.header = get_header (tmp_buff.data); + pdu_tmp.payload = get_data (tmp_buff); + process_received_PDU(pdu_tmp); + } + } + +} + + +void set_loss_rate(unsigned short rate) +{ + loss_rate = rate; +} + +void print_header(mic_tcp_payload bf) +{ + mic_tcp_header hd = get_header(bf.data); + printf("\nSP: %d, DP: %d, SEQ: %d, ACK: %d, Count: %d, Size: %d.", hd.source_port, hd.dest_port, hd.seq_num, hd.ack_num, app_buffer_count, app_buffer_size); +} + +unsigned long get_now_time_msec() +{ + return ((unsigned long) (get_now_time_usec() / 1000)); +} + +unsigned long get_now_time_usec() +{ + struct timeval now_time; + gettimeofday(&now_time, NULL); + return ((unsigned long)(now_time.tv_usec +(now_time.tv_sec * 1000000))); +} + +int min_size(int s1, int s2) +{ + if(s1 <= s2) return s1; + return s2; +} diff --git a/src/apps/client.c b/src/apps/client.c new file mode 100644 index 0000000..1df1353 --- /dev/null +++ b/src/apps/client.c @@ -0,0 +1,46 @@ +#include +#include +#include + +#define MAX_SIZE 1000 + +int main() +{ + + int sockfd = 0; + mic_tcp_sock_addr addr; + addr.ip_addr = "127.0.0.1"; + addr.port = 1234; + + if ((sockfd = mic_tcp_socket(CLIENT)) == -1) + { + printf("[TSOCK] Erreur a la creation du socket MICTCP!\n"); + return 1; + } + else + { + printf("[TSOCK] Creation du socket MICTCP: OK\n"); + } + + if (mic_tcp_connect(sockfd, addr) == -1) + { + printf("[TSOCK] Erreur a la connexion du socket MICTCP!\n"); + return 1; + } + else + { + printf("[TSOCK] Connexion du socket MICTCP: OK\n"); + } + + char chaine[MAX_SIZE]; + memset(chaine, 0, MAX_SIZE); + + printf("[TSOCK] Entrez vos message a envoyer, CTRL+D pour quitter\n"); + while(fgets(chaine, MAX_SIZE , stdin) != NULL) { + int sent_size = mic_tcp_send(sockfd, chaine, strlen(chaine)+1); + printf("[TSOCK] Appel de mic_send avec un message de taille : %d\n", strlen(chaine)+1); + printf("[TSOCK] Appel de mic_send valeur de retour : %d\n", sent_size); + } + + return 0; +} diff --git a/src/apps/gateway.c b/src/apps/gateway.c new file mode 100644 index 0000000..21cb7db --- /dev/null +++ b/src/apps/gateway.c @@ -0,0 +1,544 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern errno; + +#define MAX_UDP_SEGMENT_SIZE 1480 +#define CUMULATED_BUFF_NB 1 + +/** + * Function that performs UDP to TCP behavioral adaptation making it look like TCP was used. + * Losses can be emulated by setting the loss paramter to 1. + * returns void + */ +void udp_to_tcp(struct sockaddr_in listen_on, struct sockaddr_in transmit_to, int loss) { + + // Define the socket on which we listen and which we use for sending packets out + int listen_sockfd; + + // A buffer used to store received segments before they are forwarded + char buffer[MAX_UDP_SEGMENT_SIZE]; + + + // Addresses for the work to be performed + struct sockaddr_in serv_addr = listen_on; + struct sockaddr_in cliaddr; + socklen_t len = sizeof(cliaddr); + + // We construct the socket to be used by this function + listen_sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (bind(listen_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + printf("ERROR on binding: "); + perror(0); + printf("\n"); + } + + listen(listen_sockfd,5); + + + // Initialize a packet count variable used when loss emulation is active + int count = 0; + ssize_t n = -1; + + // Main activity loop, we never exit this, user terminates with SIGKILL + while(1) { + bzero(buffer,MAX_UDP_SEGMENT_SIZE); + + n = recvfrom(listen_sockfd, buffer, MAX_UDP_SEGMENT_SIZE, 0, (struct sockaddr *) &cliaddr, &len); + if (n < 0) { + perror(0); + } + + if(loss == 1) { + // We emulate losses every 600 packets by delaying the processing by 2 seconds. + if(count++ == 600) { + printf("Simulating TCP loss\n"); + sleep(2); + count = 0; + } + } + + // We forward the packet to its final destination + n = sendto(listen_sockfd, buffer, n, 0, (struct sockaddr *) &transmit_to, len); + if (n < 0) { + perror(0); + } + } + + // We never execute this but anyway, for sanity + close(listen_sockfd); +} + +struct timespec tsSubtract (struct timespec time1, struct timespec time2) { + struct timespec result ; + + /* Subtract the second time from the first. */ + if ((time1.tv_sec < time2.tv_sec) || ((time1.tv_sec == time2.tv_sec) && + (time1.tv_nsec <= time2.tv_nsec))) { + /* TIME1 <= TIME2? */ + result.tv_sec = result.tv_nsec = 0 ; + } else { /* TIME1 > TIME2 */ + result.tv_sec = time1.tv_sec - time2.tv_sec ; + if (time1.tv_nsec < time2.tv_nsec) { + result.tv_nsec = time1.tv_nsec + 1000000000L - time2.tv_nsec ; + result.tv_sec-- ; /* Borrow a second. */ + } else { + result.tv_nsec = time1.tv_nsec - time2.tv_nsec ; + } + } + + return (result) ; + +} + +/** + * Function that emulates TCP behavior while reading a file making it look like TCP was used. + * Losses can be emulated by setting the loss paramter to 1. + * returns void + */ +void file_to_tcp(struct sockaddr_in listen_on, struct sockaddr_in transmit_to, int loss) { + + // Define the socket on which we listen and which we use for sending packets out + int listen_sockfd; + + // A buffer used to store received segments before they are forwarded + char buffer[MAX_UDP_SEGMENT_SIZE]; + + // Addresses for the work to be performed + struct sockaddr_in serv_addr = listen_on; + struct sockaddr_in cliaddr; + socklen_t len = sizeof(cliaddr); + + // We construct the socket to be used by this function + listen_sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + //if (bind(listen_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + // printf("ERROR on binding: "); + // perror(0); + // printf("\n"); + //} + + //listen(listen_sockfd,5); + + + // Initialize a packet count variable used when loss emulation is active + int count = 0; + ssize_t n = -1; + + FILE * fd = fopen("../video/video.bin", "rb"); + + struct timespec currentTime; + struct timespec lastTime; + struct timespec rem; + int firstValue = 0; + + // Main activity loop, we never exit this, user terminates with SIGKILL + while(!feof(fd)) { + bzero(buffer,MAX_UDP_SEGMENT_SIZE); + + n = fread(¤tTime, 1, sizeof(struct timespec), fd); + if(firstValue > 0) { + // We need to sleep a while + struct timespec difference = tsSubtract(currentTime, lastTime); + nanosleep(&difference, &rem); + } else { + firstValue++; + } + lastTime = currentTime; + n = fread(buffer, 1, sizeof(n), fd); + n = fread(buffer, 1, *((int *)buffer), fd); + if (n < 0) { + perror(0); + } + + if(loss == 1) { + // We emulate losses every 600 packets by delaying the processing by 2 seconds. + if(count++ == 600) { + printf("Simulating TCP loss\n"); + sleep(2); + count = 0; + } + } + + // We forward the packet to its final destination + n = sendto(listen_sockfd, buffer, n, 0, (struct sockaddr *) &transmit_to, len); + if (n < 0) { + perror(0); + } + } + + // We never execute this but anyway, for sanity + close(listen_sockfd); +} + +/** + * Function that reads a file and delivers to MICTCP. + * returns void + */ +void file_to_mictcp(struct sockaddr_in listen_on, struct sockaddr_in transmit_to) { + + // Define the socket on which we listen + int listen_sockfd; + + // A buffer used to store received segments before they are forwarded + char buffer[MAX_UDP_SEGMENT_SIZE]; + + // Addresses for the work to be performed + struct sockaddr_in serv_addr = listen_on; + struct sockaddr_in cliaddr; + socklen_t len = sizeof(cliaddr); + + // MICTCP stuff + int mic_tcp_sockfd; + start_mode start_mode_mic_tcp = CLIENT; + mic_tcp_sock_addr mic_tcp_dest_addr; + mic_tcp_dest_addr.ip_addr = (char* ) &(transmit_to.sin_addr.s_addr); + mic_tcp_dest_addr.port = transmit_to.sin_port; + + // We construct the UDP and MICTCP sockets to be used by this function + listen_sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if((mic_tcp_sockfd = mic_tcp_socket(start_mode_mic_tcp)) == -1) { + printf("ERROR creating the MICTCP socket\n"); + } + + // We now connect the MICTCP socket + if(mic_tcp_connect(mic_tcp_sockfd, mic_tcp_dest_addr) == -1) { + printf("ERROR connecting the MICTCP socket\n"); + } + +// if (bind(listen_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { +// printf("ERROR on binding the UDP socket: "); +// perror(0); +// printf("\n"); +// } + +// listen(listen_sockfd,5); + + + // Initialize a packet count variable used when loss emulation is active + int count = 0; + ssize_t n = -1; + + FILE * fd = fopen("../video/video.bin", "rb"); + + struct timespec currentTimeFile; + struct timespec firstTimeFile; + struct timespec lastTimeFile; + struct timespec timeFirstPacket; + struct timespec currentTime; + struct timespec rem; + int firstValue = 0; + + // Main activity loop, we never exit this, user terminates with SIGKILL + while(1) { + bzero(buffer, MAX_UDP_SEGMENT_SIZE); + + n = fread(¤tTimeFile, 1, sizeof(struct timespec), fd); + if(firstValue > 0) { + // We need to sleep a while + if( clock_gettime( CLOCK_REALTIME, ¤tTime) == -1 ) { + perror( "clock gettime" ); + } + struct timespec timeSinceFirstPacket = tsSubtract(currentTime, timeFirstPacket); + struct timespec timeSinceFirstTimeFile = tsSubtract(currentTimeFile, firstTimeFile); + struct timespec difference = tsSubtract(timeSinceFirstTimeFile, timeSinceFirstPacket); + nanosleep(&difference, &rem); + } else { + firstTimeFile = currentTimeFile; + if( clock_gettime( CLOCK_REALTIME, &timeFirstPacket) == -1 ) { + perror( "clock gettime" ); + } + firstValue++; + } + lastTimeFile = currentTimeFile; + n = fread(buffer, 1, sizeof(n), fd); + n = fread(buffer, 1, *((int *)buffer), fd); + if (n < 0) { + perror(0); + } + + // We forward the packet to its final destination + n = mic_tcp_send(mic_tcp_sockfd, buffer, n); + if (n <= 0) { + printf("ERROR on MICTCP send\n"); + } + } + + // We never execute this but anyway, for sanity + close(listen_sockfd); + + // Same for MICTCP + mic_tcp_close(mic_tcp_sockfd); +} + + + +/** + * Function that listens on UDP and delivers to MICTCP. + * returns void + */ +void udp_to_mictcp(struct sockaddr_in listen_on, struct sockaddr_in transmit_to) { + + // Define the socket on which we listen + int listen_sockfd; + + // A buffer used to store received segments before they are forwarded + char buffer[MAX_UDP_SEGMENT_SIZE]; + + // Addresses for the work to be performed + struct sockaddr_in serv_addr = listen_on; + struct sockaddr_in cliaddr; + socklen_t len = sizeof(cliaddr); + + // MICTCP stuff + int mic_tcp_sockfd; + start_mode start_mode_mic_tcp = CLIENT; + mic_tcp_sock_addr mic_tcp_dest_addr; + mic_tcp_dest_addr.ip_addr = (char* ) &(transmit_to.sin_addr.s_addr); + mic_tcp_dest_addr.port = transmit_to.sin_port; + + // We construct the UDP and MICTCP sockets to be used by this function + listen_sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + if((mic_tcp_sockfd = mic_tcp_socket(start_mode_mic_tcp)) == -1) { + printf("ERROR creating the MICTCP socket\n"); + } + + // We now connect the MICTCP socket + if(mic_tcp_connect(mic_tcp_sockfd, mic_tcp_dest_addr) == -1) { + printf("ERROR connecting the MICTCP socket\n"); + } + + if (bind(listen_sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + printf("ERROR on binding the UDP socket: "); + perror(0); + printf("\n"); + } + + listen(listen_sockfd,5); + + + // Initialize a packet count variable used when loss emulation is active + int count = 0; + ssize_t n = -1; + + // Main activity loop, we never exit this, user terminates with SIGKILL + while(1) { + bzero(buffer, MAX_UDP_SEGMENT_SIZE); + + n = recvfrom(listen_sockfd, buffer, MAX_UDP_SEGMENT_SIZE, 0, (struct sockaddr *) &cliaddr, &len); + if (n < 0) { + perror(0); + } + + // We forward the packet to its final destination + n = mic_tcp_send(mic_tcp_sockfd, buffer, n); + if (n <= 0) { + printf("ERROR on MICTCP send\n"); + } + } + + // We never execute this but anyway, for sanity + close(listen_sockfd); + + // Same for MICTCP + mic_tcp_close(mic_tcp_sockfd); +} + +/** + * Function that listens on MICTCP and delivers to UDP. + * returns void + */ +void mictcp_to_udp(struct sockaddr_in listen_on, struct sockaddr_in transmit_to) { + + // Define the socket on which we listen + int sending_sockfd; + + // A buffer used to store received segments before they are forwarded + char buffer[MAX_UDP_SEGMENT_SIZE]; + int rcv_values [CUMULATED_BUFF_NB]; + char* Buff [CUMULATED_BUFF_NB]; + int iii; + for (iii=0; iii) \n"); +} + + +int main(int argc, char ** argv) { + + // Should losses be emulated? + int loss = 1; + int transport = 0; + int puits = -1; + + // What sockaddr should this program listen on? + // Always on port 1234 (data from VLC arrives there using UDP) + struct sockaddr_in serv_addr; + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(1234); + + // Where should this program send the received data? + struct sockaddr_in dest_addr; + bzero((char *) &dest_addr, sizeof(dest_addr)); + dest_addr.sin_family = AF_INET; + struct hostent * hp = gethostbyname("127.0.0.1"); + bcopy ( hp->h_addr, &(dest_addr.sin_addr.s_addr), hp->h_length); + dest_addr.sin_port = htons(1234); + + extern int optind; + int ch; + + while ((ch = getopt(argc, argv, "t:sp")) != -1) { + switch (ch) { + case 't': + if(strcmp(optarg, "mictcp") == 0) { + transport = 1; + } else if(strcmp(optarg, "tcp") == 0) { + transport = 0; + } else { + printf("Unrecognized transport : %s\n", optarg); + } + break; + case 's': + if(puits == -1) { + puits = 0; + } else { + puits = -2; + } + break; + case 'p': + if(puits == -1) { + puits = 1; + } else { + puits = -2; + } + break; + default: + usage(); + } + } + if(puits < 0) { + usage(); + return -1; + } + argc -= optind; + argv += optind; + + if((puits == 1 && argc != 1) || ((puits == 0) && argc != 2)) { + usage(); + return -1; + } + + if(puits == 0) { + hp = gethostbyname(argv[0]); + bcopy ( hp->h_addr, &(dest_addr.sin_addr.s_addr), hp->h_length); + dest_addr.sin_port = htons(atoi(argv[1])); + } else { + serv_addr.sin_port = htons(atoi(argv[0])); + } + + if(transport == 0) { + if(puits == 0) { + // We receive on UDP and emulate TCP behavior before sending the data out + file_to_tcp(serv_addr, dest_addr, loss); + } else { + printf("No gateway needed for puits using UDP\n"); + } + } else if(transport == 1) { + if(puits == 0) { + // We receive on UDP and send the data using MICTCP + file_to_mictcp(serv_addr, dest_addr); + } else { + // We receive on MICTCP and send the data using UDP + mictcp_to_udp(serv_addr, dest_addr); + } + + } +} diff --git a/src/apps/server.c b/src/apps/server.c new file mode 100644 index 0000000..2618dc3 --- /dev/null +++ b/src/apps/server.c @@ -0,0 +1,58 @@ +#include +#include + +#define MAX_SIZE 1000 + +int main() +{ + int sockfd; + mic_tcp_sock_addr addr; + addr.ip_addr = "127.0.0.1"; + addr.port = 1234; + + mic_tcp_sock_addr remote_addr; + + if ((sockfd = mic_tcp_socket(SERVER)) == -1) + { + printf("[TSOCK] Erreur a la creation du socket MICTCP!\n"); + return 1; + } + else + { + printf("[TSOCK] Creation du socket MICTCP: OK\n"); + } + + if (mic_tcp_bind(sockfd, addr) == -1) + { + printf("[TSOCK] Erreur lors du bind du socket MICTCP!\n"); + return 1; + } + else + { + printf("[TSOCK] Bind du socket MICTCP: OK\n"); + } + + if (mic_tcp_accept(sockfd, &remote_addr) == -1) + { + printf("[TSOCK] Erreur lors de l'accept sur le socket MICTCP!\n"); + return 1; + } + else + { + printf("[TSOCK] Accept sur le socket MICTCP: OK\n"); + } + + + char chaine[MAX_SIZE]; + memset(chaine, 0, MAX_SIZE); + + printf("[TSOCK] Appuyez sur CTRL+C pour quitter ...\n"); + + while(1) { + printf("[TSOCK] Attente d'une donnee, appel de mic_recv ...\n"); + int rcv_size = mic_tcp_recv(sockfd, chaine, MAX_SIZE); + printf("[TSOCK] Reception d'un message de taille : %d\n", rcv_size); + printf("[TSOCK] Message Recu : %s", chaine); + } + return 0; +} diff --git a/src/mictcp.c b/src/mictcp.c new file mode 100644 index 0000000..669a523 --- /dev/null +++ b/src/mictcp.c @@ -0,0 +1,71 @@ +#include +#include + +int mic_tcp_socket(start_mode sm) +// Permet de créer un socket entre l’application et MIC-TCP +// Retourne le descripteur du socket ou bien -1 en cas d'erreur +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); + initialize_components(sm); // Appel obligatoire + return -1; +} + +int mic_tcp_bind(int socket, mic_tcp_sock_addr addr) +// Permet d’attribuer une adresse à un socket. Retourne 0 si succès, et -1 en cas d’échec +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); +} + +int mic_tcp_accept(int socket, mic_tcp_sock_addr* addr) +// Met l’application en état d'acceptation d’une requête de connexion entrante +// Retourne 0 si succès, -1 si erreur +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); + return -1; +} + +int mic_tcp_connect(int socket, mic_tcp_sock_addr addr) +// Permet de réclamer l’établissement d’une connexion +// Retourne 0 si la connexion est établie, et -1 en cas d’échec +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); + return -1; +} + +int mic_tcp_send (int mic_sock, char* mesg, int mesg_size) +// 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 +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); + return -1; +} + + +int mic_tcp_recv (int socket, char* mesg, int max_mesg_size) +// Permet à l’application réceptrice de réclamer la récupération d’une donnée +// stockée dans les buffers de réception du socket +// Retourne le nombre d’octets lu ou bien -1 en cas d’erreur +// NB : cette fonction fait appel à la fonction app_buffer_get() +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); + return -1; +} + +int mic_tcp_close (int socket) +// Permet de réclamer la destruction d’un socket. +// Engendre la fermeture de la connexion suivant le modèle de TCP. +// Retourne 0 si tout se passe bien et -1 en cas d'erreur +{ + printf("[MIC-TCP] Appel de la fonction : "); printf(__FUNCTION__); printf("\n"); + return -1; +} + + +void process_received_PDU(mic_tcp_pdu pdu) +// Gère le 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(). +{ + printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n"); +} diff --git a/tsock_texte b/tsock_texte new file mode 100644 index 0000000..2253e3c --- /dev/null +++ b/tsock_texte @@ -0,0 +1,40 @@ +#!/bin/bash + +puits=false +sourc=false +protocol="tcp" + +usage() { echo "Usage: $0 [-p|-s]" 1>&2; exit 1; } + +while getopts "pst:" o; do + case "${o}" in + p) + puits=true + ;; + s) + sourc=true + ;; + *) + usage + ;; + esac +done + +if ([ "$puits" = true ] && [ "$sourc" = true ]) || ([ "$puits" = false ] && [ "$sourc" = false ]) ; then + usage + exit 1 +fi + +if [ "$puits" = true ]; then + cd build + ./server + cd .. +fi + +if [ "$sourc" = true ]; then + + cd build + ./client + cd .. +fi + diff --git a/tsock_video b/tsock_video new file mode 100644 index 0000000..714c273 --- /dev/null +++ b/tsock_video @@ -0,0 +1,62 @@ +#!/bin/bash + +puits=false +sourc=false +protocol="tcp" + +usage() { echo "Usage: $0 [[-p|-s] [-t (tcp|mictcp)]" 1>&2; exit 1; } + +while getopts "pst:" o; do + case "${o}" in + t) + protocol=${OPTARG} + if [ "$protocol" != "tcp" ] && [ "$protocol" != "mictcp" ]; then + usage + exit 1 + fi + ;; + p) + puits=true + ;; + s) + sourc=true + ;; + *) + usage + ;; + esac +done + +if ([ "$puits" = true ] && [ "$sourc" = true ]) || ([ "$puits" = false ] && [ "$sourc" = false ]) ; then + usage + exit 1 +fi + +if [ "$puits" = true ]; then + + echo "Lancement du puits, protocole " $protocol + cvlc rtp://127.0.0.1:1234 > /dev/null 2>&1 & + + if [ "$protocol" = "mictcp" ]; then + cd build + ./gateway -p -t $protocol 1234 & + cd .. + fi +fi + +if [ "$sourc" = true ]; then + + echo "Lancement de la source, protocol " $protocol + cd build + ./gateway -s -t $protocol 127.0.0.1 1234 & + cd .. +fi + +echo "Appuyez sur ENTREE pour arreter" +read line + +echo "Arret" +killall -9 cvlc > /dev/null 2>&1 +killall -9 vlc > /dev/null 2>&1 +killall -9 gateway > /dev/null 2>&1 + diff --git a/video/video.bin b/video/video.bin new file mode 100644 index 0000000..8d70bc7 Binary files /dev/null and b/video/video.bin differ