ajout base be reseau

This commit is contained in:
Magana Amalia 2023-03-24 16:14:31 +01:00
parent 6a07b16401
commit 7bd3dfca82
13 changed files with 1239 additions and 0 deletions

65
Makefile Normal file
View file

@ -0,0 +1,65 @@
DATE := `date +'%Y%m%d'`
TAG := moodle-$(USER)
PORT := $(shell expr `id -u` % 2000 + 12487)
PORT2 := $(shell expr $(PORT) + 1)
ifneq ($(tag),)
TAG := $(TAG)-$(tag)
endif
CC := gcc
LD := gcc
TAR_FILENAME := $(DATE)-mictcp-$(TAG).tar.gz
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) -DAPI_CS_Port=$(PORT) -DAPI_SC_Port=$(PORT2) -std=gnu99 -Wall -g -I $(INCLUDES) -c $$< -o $$@
endef
.PHONY: all checkdirs clean
all: checkdirs build/client build/server build/gateway
build/client: $(OBJ_CLI)
$(LD) $^ -o $@ -lm -lpthread
build/server: $(OBJ_SERV)
$(LD) $^ -o $@ -lm -lpthread
build/gateway: $(OBJ_GWAY)
$(LD) $^ -o $@ -lm -lpthread
checkdirs: $(BUILD_DIR)
$(BUILD_DIR):
@mkdir -p $@
clean:
@rm -rf $(BUILD_DIR)
distclean:
@rm -rf $(BUILD_DIR)
@-rm -f *.tar.gz || true
$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))
dist:
@tar --exclude=build --exclude=*tar.gz --exclude=.git* -czvf mictcp-bundle.tar.gz ../mictcp
prof:
@tar --exclude=build --exclude=.*tar.gz --exclude=video -czvf $(TAR_FILENAME) ../mictcp

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

@ -0,0 +1,49 @@
#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_pdu*, mic_tcp_sock_addr*, unsigned long timeout);
int app_buffer_get(mic_tcp_payload);
void app_buffer_put(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 *
**********************************************************************/
#ifndef API_CS_Port
#define API_CS_Port 8524
#endif
#ifndef API_SC_Port
#define API_SC_Port 8525
#endif
#define API_HD_Size 15
typedef struct ip_payload
{
char* data; /* données transport */
int size; /* taille des données */
} ip_payload;
int mic_tcp_core_send(mic_tcp_payload);
mic_tcp_payload get_full_stream(mic_tcp_pdu);
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_pdu);
int min_size(int, int);
float mod(int, float);
#endif

105
include/mictcp.h Normal file
View file

@ -0,0 +1,105 @@
#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 */
} 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, mic_tcp_sock_addr addr);
int mic_tcp_close(int socket);
#endif

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

@ -0,0 +1,347 @@
#include <api/mictcp_core.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <math.h>
#include <time.h>
#include <pthread.h>
#include <strings.h>
/*****************
* API Variables *
*****************/
int initialized = -1;
int sys_socket;
pthread_t listen_th;
pthread_mutex_t lock;
unsigned short loss_rate = 0;
struct sockaddr_in remote_addr;
/* This is for the buffer */
TAILQ_HEAD(tailhead, app_buffer_entry) app_buffer_head;
struct tailhead *headp;
struct app_buffer_entry {
mic_tcp_payload bf;
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 hostent * hp;
struct sockaddr_in local_addr;
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))
{
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);
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bnd = bind(sys_socket, (struct sockaddr *) &local_addr, sizeof(local_addr));
if (bnd == -1)
{
initialized = -1;
}
else
{
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");
memcpy (&(remote_addr.sin_addr.s_addr), hp->h_addr, hp->h_length);
initialized = 1;
}
}
else
{
if(initialized != -1)
{
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");
memcpy (&(remote_addr.sin_addr.s_addr), hp->h_addr, hp->h_length);
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);
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)
{
int result = 0;
if(initialized == -1) {
result = -1;
} else {
mic_tcp_payload tmp = get_full_stream(pk);
int sent_size = mic_tcp_core_send(tmp);
free (tmp.data);
/* Correct the sent size */
result = (sent_size == -1) ? -1 : sent_size - API_HD_Size;
}
return result;
}
int IP_recv(mic_tcp_pdu* 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;
}
/* 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;
/* Create a reception buffer */
int buffer_size = API_HD_Size + pk->payload.size;
char *buffer = malloc(buffer_size);
if ((setsockopt(sys_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) >= 0) {
result = recvfrom(sys_socket, buffer, buffer_size, 0, (struct sockaddr *)&tmp_addr, &tmp_addr_size);
}
if (result != -1) {
/* Create the mic_tcp_pdu */
memcpy (&(pk->header), buffer, API_HD_Size);
pk->payload.size = result - API_HD_Size;
memcpy (pk->payload.data, buffer + API_HD_Size, pk->payload.size);
/* Generate a stub address */
if (addr != NULL) {
addr->ip_addr = "localhost";
addr->ip_addr_size = strlen(addr->ip_addr) + 1; // don't forget '\0'
addr->port = pk->header.source_port;
}
/* Correct the receved size */
result -= API_HD_Size;
}
/* Free the reception buffer */
free(buffer);
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 = API_HD_Size + pk.payload.size;
tmp.data = malloc (tmp.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_mic_tcp_data(ip_payload buff)
{
mic_tcp_payload tmp;
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_mic_tcp_header(ip_payload packet)
{
/* Get a struct header from an incoming packet */
mic_tcp_header tmp;
memcpy(&tmp, packet.data, API_HD_Size);
return tmp;
}
int full_send(mic_tcp_payload buff)
{
int result = 0;
result = sendto(sys_socket, buff.data, buff.size, 0, (struct sockaddr *)&remote_addr, sizeof(remote_addr));
return result;
}
int mic_tcp_core_send(mic_tcp_payload buff)
{
int random = rand();
int result = buff.size;
int lr_tresh = (int) round(((float)loss_rate/100.0)*RAND_MAX);
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;
}
int app_buffer_get(mic_tcp_payload app_buff)
{
/* A pointer to a buffer entry */
struct app_buffer_entry * entry;
/* 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) {
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;
/* How much data are we going to deliver to the application ? */
result = min_size(entry->bf.size, app_buff.size);
/* We copy the actual data in the application allocated buffer */
memcpy(app_buff.data, entry->bf.data, result);
/* We remove the entry from the buffer */
TAILQ_REMOVE(&app_buffer_head, entry, entries);
/* Release the mutex */
pthread_mutex_unlock(&lock);
/* Clean up memory */
free(entry->bf.data);
free(entry);
return result;
}
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));
entry->bf.size = bf.size;
entry->bf.data = malloc(bf.size);
memcpy(entry->bf.data, bf.data, bf.size);
/* Lock a mutex to protect the buffer from corruption */
pthread_mutex_lock(&lock);
/* Insert the packet in the buffer, at the end of it */
TAILQ_INSERT_TAIL(&app_buffer_head, entry, entries);
/* 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);
}
void* listening(void* arg)
{
mic_tcp_pdu pdu_tmp;
int recv_size;
mic_tcp_sock_addr remote;
pthread_mutex_init(&lock, NULL);
printf("[MICTCP-CORE] Demarrage du thread de reception reseau...\n");
const int payload_size = 1500 - API_HD_Size;
pdu_tmp.payload.size = payload_size;
pdu_tmp.payload.data = malloc(payload_size);
while(1)
{
pdu_tmp.payload.size = payload_size;
recv_size = IP_recv(&pdu_tmp, &remote, 0);
if(recv_size != -1)
{
process_received_PDU(pdu_tmp, remote);
} else {
/* This should never happen */
printf("Error in recv\n");
}
}
}
void set_loss_rate(unsigned short rate)
{
loss_rate = rate;
}
void print_header(mic_tcp_pdu bf)
{
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);
}
unsigned long get_now_time_msec()
{
return ((unsigned long) (get_now_time_usec() / 1000));
}
unsigned long get_now_time_usec()
{
struct timespec now_time;
clock_gettime( CLOCK_REALTIME, &now_time);
return ((unsigned long)((now_time.tv_nsec / 1000) + (now_time.tv_sec * 1000000)));
}
int min_size(int s1, int s2)
{
if(s1 <= s2) return s1;
return s2;
}

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

@ -0,0 +1,48 @@
#include <mictcp.h>
#include <stdio.h>
#include <string.h>
#define MAX_SIZE 1000
int main()
{
int sockfd = 0;
char chaine[MAX_SIZE];
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");
}
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 : %lu\n", strlen(chaine)+1);
printf("[TSOCK] Appel de mic_send valeur de retour : %d\n", sent_size);
}
mic_tcp_close(sockfd);
return 0;
}

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

@ -0,0 +1,371 @@
#include <errno.h>
#include <mictcp.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
//
// Déclaration des types, constantes et macros
//
#define ENABLE_TCP_LOSS 1
#define MAX_UDP_SEGMENT_SIZE 1480
#define MICTCP_PORT 1337
#define VIDEO_FILE "../video/video.bin"
/**
* Macro utilisée pour afficher le message d'erreur msg passé en paramètre
* si la condition cond est validée, puis arrêter le programme.
* Le message affiché contient des informations supplémentaires concernant
* le fichier de provenance, la fonction et le numéro de ligne concerné.
* Si errno est set, le message d'erreur associé est aussi affiché.
*/
#define ERROR_IF(cond,msg) \
if (cond) { \
if (errno != 0) { \
fprintf(stderr, "%s:%d [%s()] -> %s (%s)\n", \
__FILE__, __LINE__, __func__, msg, strerror(errno)); \
} else { \
fprintf(stderr, "%s:%d [%s()] -> %s\n", \
__FILE__, __LINE__, __func__, msg); \
} \
exit(EXIT_FAILURE); \
}
/**
* Fonctions du programme
*/
enum gateway_function {
UND_FCT,
SOURCE,
PUITS
};
/**
* Protocoles pouvant être utilisé
*/
enum gateway_protocol {
PROTO_TCP,
PROTO_MICTCP
};
//
// Déclaration des fonctions locales
//
static void file_to_faketcp(char* filename, char *host, int port);
static void file_to_mictcp(char* filename);
static void mictcp_to_udp(char *host, int port);
static int read_rtp_packet(FILE *fd, struct timespec *timestamp, char *buffer, int buffer_size);
static struct timespec tsSubtract(struct timespec time1, struct timespec time2);
static void usage(void);
//
// Corps des fonctions publiques
//
int main(int argc, char** argv)
{
enum gateway_protocol proto = PROTO_TCP;
enum gateway_function func = UND_FCT;
int ch;
while ((ch = getopt(argc, argv, "t:sp")) != -1) {
switch (ch) {
case 't':
if (strcmp(optarg, "mictcp") == 0) {
proto = PROTO_MICTCP;
} else if (strcmp(optarg, "tcp") == 0) {
proto = PROTO_TCP;
} else {
printf("Unrecognized transport : %s\n", optarg);
usage();
}
break;
case 's':
if (func == UND_FCT) {
func = SOURCE;
} else {
usage();
}
break;
case 'p':
if (func == UND_FCT) {
func = PUITS;
} else {
usage();
}
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (func == UND_FCT || (func == PUITS && argc != 1) || (func == SOURCE && argc != 2)) {
usage();
}
if (proto == PROTO_TCP) {
if (func == SOURCE) {
file_to_faketcp(VIDEO_FILE, argv[0], atoi(argv[1]));
} else {
printf("No gateway needed for puits using UDP\n");
}
} else {
if (func == SOURCE) {
file_to_mictcp(VIDEO_FILE);
} else {
mictcp_to_udp("127.0.0.1", atoi(argv[0]));
}
}
return 0;
}
//
// Corps des fonctions privées
//
/**
* Print usage and exit
*/
static void usage(void)
{
printf("usage: gateway [-p|-s][-t tcp|mictcp] (<server>) <port>\n");
exit(EXIT_FAILURE);
}
/**
* Function that emulates TCP behavior while reading a file making it look like TCP was used.
*/
static void file_to_faketcp(char* filename, char *host, int port)
{
/* Création du socket */
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
ERROR_IF(sockfd == -1, "Socket error");
/* Construction de l'adresse du socket distant */
struct sockaddr_in s_addr = {0};
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(port);
struct hostent* host_info = gethostbyname(host);
ERROR_IF(host_info == NULL, "Error gethostbyname");
ERROR_IF(host_info->h_addrtype != AF_INET, "gethostbyname bad h_addrtype");
ERROR_IF(host_info->h_addr == NULL, "gethostbyname no addr");
memcpy(&(s_addr.sin_addr), host_info->h_addr, host_info->h_length);
/* Ouverture du fichier vidéo */
FILE *filefd = fopen(filename, "rb");
ERROR_IF(filefd == NULL, "Error fopen");
uint count = 0; // compteur de paquets
struct timespec current_time, last_time; // stockage des timestamps
char buffer[MAX_UDP_SEGMENT_SIZE]; // buffer de lecture/ecriture
last_time.tv_sec = -1;
last_time.tv_nsec = LONG_MAX;
/* Lecture jusqu'à la fin du fichier vidéo */
while (!feof(filefd)) {
/* Lecture du paquet rtp */
int nb_read = read_rtp_packet(filefd, &current_time, buffer, MAX_UDP_SEGMENT_SIZE);
/* Attente avant la prochaine lecture */
struct timespec delay = tsSubtract(current_time, last_time);
nanosleep(&delay, NULL);
/* Mise à jour du timestamp */
last_time = current_time;
if (ENABLE_TCP_LOSS) {
/* On émule les pertes de paquets en délayant l'envoi de 2 secondes */
if (count++ == 600) {
printf("Simulating TCP loss\n");
sleep(2);
count = 0;
}
}
/* Envoi du paquet rtp via faketcp */
int nb_sent = sendto(sockfd, buffer, nb_read, 0, (struct sockaddr*)&s_addr, sizeof(s_addr));
ERROR_IF(nb_sent == -1, "Error sendto");
}
/* Fermeture du socket et du fichier */
close(sockfd);
fclose(filefd);
}
/**
* Function that reads a file and delivers to MICTCP.
*/
static void file_to_mictcp(char* filename)
{
/* Création du socket MICTCP */
int sockfd = mic_tcp_socket(CLIENT);
if (sockfd == -1) {
printf("ERROR creating the MICTCP socket\n");
}
/* On effectue la connexion */
mic_tcp_sock_addr dest_addr;
dest_addr.ip_addr = "localhost";
dest_addr.ip_addr_size = strlen(dest_addr.ip_addr) + 1; // '\0'
dest_addr.port = MICTCP_PORT;
if (mic_tcp_connect(sockfd, dest_addr) == -1) {
printf("ERROR connecting the MICTCP socket\n");
}
/* Ouverture du fichier vidéo */
FILE *filefd = fopen(filename, "rb");
ERROR_IF(filefd == NULL, "Error fopen");
struct timespec current_time, last_time; // stockage des timestamps
char buffer[MAX_UDP_SEGMENT_SIZE]; // buffer de lecture/ecriture
last_time.tv_sec = -1;
last_time.tv_nsec = LONG_MAX;
/* Lecture jusqu'à la fin du fichier vidéo */
while (!feof(filefd)) {
/* Lecture du paquet rtp */
int nb_read = read_rtp_packet(filefd, &current_time, buffer, MAX_UDP_SEGMENT_SIZE);
/* Attente avant la prochaine lecture */
struct timespec delay = tsSubtract(current_time, last_time);
nanosleep(&delay, NULL);
/* Mise à jour du timestamp */
last_time = current_time;
/* Envoi du paquet rtp via mictcp */
int nb_sent = mic_tcp_send(sockfd, buffer, nb_read);
if (nb_sent < 0) {
printf("ERROR on MICTCP send\n");
}
}
/* Fermeture du socket et du fichier */
if (mic_tcp_close(sockfd) == -1) {
printf("ERROR on MICTCP close\n");
}
fclose(filefd);
}
/**
* Function that listens on MICTCP and delivers to UDP.
*/
static void mictcp_to_udp(char *host, int port)
{
/* Création du socket UDP */
int udp_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
ERROR_IF(udp_sockfd == -1, "Socket error");
/* Construction de l'adresse du socket distant */
struct sockaddr_in remote_s_addr = {0};
remote_s_addr.sin_family = AF_INET;
remote_s_addr.sin_port = htons(port);
struct hostent* host_info = gethostbyname(host);
ERROR_IF(host_info == NULL, "Error gethostbyname");
ERROR_IF(host_info->h_addrtype != AF_INET, "gethostbyname bad h_addrtype");
ERROR_IF(host_info->h_addr == NULL, "gethostbyname no addr");
memcpy(&(remote_s_addr.sin_addr), host_info->h_addr, host_info->h_length);
/* Création du socket MICTCP */
int mictcp_sockfd = mic_tcp_socket(SERVER);
if (mictcp_sockfd == -1) {
printf("ERROR creating the MICTCP socket\n");
}
/* On bind le socket mictcp à une adresse locale */
mic_tcp_sock_addr mt_local_addr;
mt_local_addr.ip_addr = NULL;
mt_local_addr.ip_addr_size = 0;
mt_local_addr.port = MICTCP_PORT;
if (mic_tcp_bind(mictcp_sockfd, mt_local_addr) == -1) {
printf("ERROR on binding the MICTCP socket\n");
}
/* Acceptation d'une demande de connexion */
mic_tcp_sock_addr mt_remote_addr;
if (mic_tcp_accept(mictcp_sockfd, &mt_remote_addr) == -1) {
printf("ERROR on accept on the MICTCP socket\n");
}
/* Lecture mictcp vers udp */
char buff[MAX_UDP_SEGMENT_SIZE]; // buffer de lecture/ecriture
while (1) {
int nb_read = mic_tcp_recv(mictcp_sockfd, buff, MAX_UDP_SEGMENT_SIZE);
if (nb_read <= 0) {
if (nb_read < 0) {
printf("ERROR on mic_recv on the MICTCP socket\n");
}
break; // Fin de la transmission
}
int nb_sent = sendto(udp_sockfd, buff, nb_read, 0, (struct sockaddr*)&remote_s_addr, sizeof(remote_s_addr));
ERROR_IF(nb_sent == -1, "Error sendto");
}
/* Fermeture des sockets */
if (mic_tcp_close(mictcp_sockfd) == -1) {
printf("ERROR on MICTCP close\n");
}
close(udp_sockfd);
}
/**
* Read one rtp packet from the video file in the buffer, as well as
* the corresponding timestamp
* Return the number of bytes read
*/
static int read_rtp_packet(FILE *fd, struct timespec *timestamp, char *buffer, int buffer_size)
{
/* Les champs du timestamp sont stockés sur 4 octets (héritage de la version 32 bits) */
timestamp->tv_sec = 0;
timestamp->tv_nsec = 0;
fread(&(timestamp->tv_sec), 1, 4, fd);
fread(&(timestamp->tv_nsec), 1, 4, fd);
/* Taille du packet rdp */
int packet_size = 0;
fread(&packet_size, 1, sizeof(int), fd);
/* Lecture du paquet rdp */
ERROR_IF(packet_size > buffer_size, "Buffer is too small to store the packet");
return fread(buffer, 1, packet_size, fd);
}
/**
* Return (time1 - time2) when (time1 > time2), 0 otherwise
*/
static 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 = 0;
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);
}

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

@ -0,0 +1,60 @@
#include <mictcp.h>
#include <stdio.h>
#define MAX_SIZE 1000
int main()
{
int sockfd;
mic_tcp_sock_addr addr;
mic_tcp_sock_addr remote_addr;
char chaine[MAX_SIZE];
addr.ip_addr = "127.0.0.1";
addr.port = 1234;
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");
}
memset(chaine, 0, MAX_SIZE);
printf("[TSOCK] Appuyez sur CTRL+C pour quitter ...\n");
while(1) {
int rcv_size = 0;
printf("[TSOCK] Attente d'une donnee, appel de mic_recv ...\n");
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;
}

90
src/mictcp.c Normal file
View file

@ -0,0 +1,90 @@
#include <mictcp.h>
#include <api/mictcp_core.h>
/*
* Permet de créer un socket entre lapplication et MIC-TCP
* Retourne le descripteur du socket ou bien -1 en cas d'erreur
*/
int mic_tcp_socket(start_mode sm)
{
int result = -1;
printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n");
result = initialize_components(sm); /* Appel obligatoire */
set_loss_rate(0);
return result;
}
/*
* Permet dattribuer une adresse à un socket.
* Retourne 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");
return -1;
}
/*
* Met le socket en état d'acceptation de connexions
* Retourne 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");
return -1;
}
/*
* Permet de réclamer létablissement dune connexion
* Retourne 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");
return -1;
}
/*
* Permet de réclamer lenvoi dune donnée applicative
* Retourne la taille des données envoyées, et -1 en cas d'erreur
*/
int mic_tcp_send (int mic_sock, char* mesg, int mesg_size)
{
printf("[MIC-TCP] Appel de la fonction: "); printf(__FUNCTION__); printf("\n");
return -1;
}
/*
* 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()
*/
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;
}
/*
* 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
*/
int mic_tcp_close (int socket)
{
printf("[MIC-TCP] Appel de la fonction : "); printf(__FUNCTION__); printf("\n");
return -1;
}
/*
* 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_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");
}

40
tsock_texte Executable 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

63
tsock_video Executable file
View file

@ -0,0 +1,63 @@
#!/bin/bash
puits=false
sourc=false
protocol="tcp"
port=`expr \`id -u\` % 3000 + 14578`
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:$port > /dev/null 2>&1 &
if [ "$protocol" = "mictcp" ]; then
cd build
./gateway -p -t $protocol $port &
cd ..
fi
fi
if [ "$sourc" = true ]; then
echo "Lancement de la source, protocol " $protocol
cd build
./gateway -s -t $protocol 127.0.0.1 $port &
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

1
video/video.bin Symbolic link
View file

@ -0,0 +1 @@
video_starwars.bin

BIN
video/video_starwars.bin Normal file

Binary file not shown.

BIN
video/video_wildlife.bin Normal file

Binary file not shown.