Initial Import

This commit is contained in:
Nicolas Van Wambeke 2016-06-13 23:17:19 +02:00
commit dc58e0e2d5
11 changed files with 1327 additions and 0 deletions

43
Makefile Normal file
View file

@ -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))))

31
include/api/mictcp_core.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef MICTCP_CORE_H
#define MICTCP_CORE_H
#include <mictcp.h>
#include <math.h>
// 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

106
include/mictcp.h Normal file
View file

@ -0,0 +1,106 @@
#ifndef MICTCP_H
#define MICTCP_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#include <sys/time.h>
// 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 à lusage de la fonction initialize_components()
typedef enum start_mode { CLIENT, SERVER } start_mode;
// Structure dune 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 dun 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

326
src/api/mictcp_core.c Normal file
View file

@ -0,0 +1,326 @@
#include <api/mictcp_core.h>
#include <pthread.h>
// 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;
}

46
src/apps/client.c Normal file
View file

@ -0,0 +1,46 @@
#include <mictcp.h>
#include <stdio.h>
#include <string.h>
#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;
}

544
src/apps/gateway.c Normal file
View file

@ -0,0 +1,544 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <mictcp.h>
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(&currentTime, 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(&currentTimeFile, 1, sizeof(struct timespec), fd);
if(firstValue > 0) {
// We need to sleep a while
if( clock_gettime( CLOCK_REALTIME, &currentTime) == -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<CUMULATED_BUFF_NB; iii++)
{
Buff[iii] = malloc(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 = SERVER;
mic_tcp_sock_addr mic_tcp_listen_addr, mic_tcp_remote_addr;
mic_tcp_listen_addr.ip_addr = (char* ) &(listen_on.sin_addr.s_addr);
mic_tcp_listen_addr.port = listen_on.sin_port;
// We construct the UDP and MICTCP sockets to be used by this function
sending_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");
}
if (mic_tcp_bind(mic_tcp_sockfd, mic_tcp_listen_addr) == -1) {
printf("ERROR on binding the MICTCP socket\n");
}
if(mic_tcp_accept(mic_tcp_sockfd, &mic_tcp_remote_addr) == -1) {
printf("ERROR on accept on the MICTCP socket\n");
}
// 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) {
int k;
for(k=0; k<CUMULATED_BUFF_NB; k++)
{
bzero(Buff[k], MAX_UDP_SEGMENT_SIZE);
}
for(k=0; k<CUMULATED_BUFF_NB; k++)
{
n = mic_tcp_recv(mic_tcp_sockfd, Buff[k], MAX_UDP_SEGMENT_SIZE);
if (n <= 0) {
printf("ERROR on mic_recv on the MICTCP socket\n");
}
}
// We forward the packet to its final destination
for(k=0; k<CUMULATED_BUFF_NB; k++)
{
n = sendto(sending_sockfd, Buff[k], n, 0, (struct sockaddr *) &transmit_to, len);
if (n <= 0) {
perror(0);
}
}
//sleep(1);
}
// We never execute this but anyway, for sanity
close(sending_sockfd);
// Same for MICTCP
mic_tcp_close(mic_tcp_sockfd);
}
static void usage(void) {
printf("usage: gateway [-p|-s][-t tcp|mictcp] (<server>) <port>\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);
}
}
}

58
src/apps/server.c Normal file
View file

@ -0,0 +1,58 @@
#include <mictcp.h>
#include <stdio.h>
#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;
}

71
src/mictcp.c Normal file
View file

@ -0,0 +1,71 @@
#include <mictcp.h>
#include <api/mictcp_core.h>
int mic_tcp_socket(start_mode sm)
// Permet de créer un socket entre lapplication 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 dattribuer 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 lapplication en état d'acceptation dune 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 dune 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 lenvoi dune 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 à lapplication réceptrice de réclamer la récupération dune donnée
// stockée dans les buffers de réception du socket
// Retourne le nombre doctets lu ou bien -1 en cas derreur
// 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 dun 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 dun 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");
}

40
tsock_texte Normal file
View file

@ -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

62
tsock_video Normal file
View file

@ -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

BIN
video/video.bin Normal file

Binary file not shown.