360 lines
10 KiB
C
360 lines
10 KiB
C
|
/*
|
||
|
* This file is part of the rtap localisation project.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include "rtapaggregate.h"
|
||
|
|
||
|
|
||
|
char *out_file ;
|
||
|
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
int ret = 0 ; // Valeur de retour du programme
|
||
|
couple_list *couples = NULL ; // Liste des données traitées
|
||
|
struct sigaction action ; // Structure de mise en place des gestionnaires de signaux
|
||
|
int sockfd ; // Socket d'écoute UDP
|
||
|
int nread ; // Retour de recvfrom
|
||
|
struct sockaddr_in client; // Structure pour le client UDP
|
||
|
socklen_t client_len = sizeof(client) ; // Taille du client pour la socket
|
||
|
couple_message message ; // Message lu sur la socket
|
||
|
pthread_t thread ; // Thread pour la fonction de surveillance de la liste d'informations agrégées
|
||
|
char *ap_mac_string, *mobile_mac_string ; // Pointeurs pour retour de mac_bytes_to_string()
|
||
|
|
||
|
if (argc != 2)
|
||
|
{
|
||
|
print_usage(argv[0]) ;
|
||
|
return ERR_BAD_USAGE ;
|
||
|
}
|
||
|
|
||
|
run = TRUE ;
|
||
|
|
||
|
|
||
|
/* Fichier de sortie */
|
||
|
out_file = malloc((strlen(argv[1]) + 1) * sizeof(char)) ;
|
||
|
strcpy(out_file, argv[1]) ;
|
||
|
|
||
|
|
||
|
/* Mise en place des gestionnaires de signaux */
|
||
|
sigemptyset(&action.sa_mask) ;
|
||
|
action.sa_handler = sigint_handler ;
|
||
|
sigaction(SIGINT, &action, NULL) ;
|
||
|
action.sa_handler = sigterm_handler ;
|
||
|
sigaction(SIGTERM, &action, NULL) ;
|
||
|
|
||
|
/* Création de la socket UDP */
|
||
|
if ((sockfd = create_udp_listening_socket(AGGREGATE_DEFAULT_PORT)) < 0)
|
||
|
{
|
||
|
fprintf(stderr, "Erreur ! Impossible d'écouter sur le port %d.\n", AGGREGATE_DEFAULT_PORT) ;
|
||
|
exit(ERR_CREATING_SOCKET) ;
|
||
|
}
|
||
|
|
||
|
/* Création du thread */
|
||
|
pthread_create(&thread, NULL, (void *) &monitor_couple_list, &couples) ;
|
||
|
|
||
|
/* Lecture sur la socket */
|
||
|
while (run)
|
||
|
{
|
||
|
nread = recvfrom(sockfd, &message, sizeof(message), 0, (struct sockaddr *) &client, &client_len) ;
|
||
|
|
||
|
if (nread <= 0)
|
||
|
{
|
||
|
if (run)
|
||
|
{
|
||
|
fprintf(stderr, "Aucun message reçu du client !\n") ;
|
||
|
ret = ERR_NO_MESSAGE_RECEIVED ;
|
||
|
}
|
||
|
break ;
|
||
|
}
|
||
|
ap_mac_string = mac_bytes_to_string(message.ap_mac_addr_bytes) ;
|
||
|
mobile_mac_string = mac_bytes_to_string(message.mobile_mac_addr_bytes) ;
|
||
|
printf("\n\
|
||
|
*** Message reçu du client ***\n\
|
||
|
\tMAC AP : %s\n\
|
||
|
\tMAC mobile : %s\n\
|
||
|
\tNuméro de séquence (heure de la demande) : %lu\n\
|
||
|
\tHeure d'arrivée de la demande de localisation sur l'AP : %lu\n\
|
||
|
\tSignal : %d dBm\n\
|
||
|
\tPosition X : %f\n\
|
||
|
\tPosition Y : %f\n\
|
||
|
\tPosition Z : %f\n\
|
||
|
\tDirection : %hhd\n\
|
||
|
",
|
||
|
ap_mac_string,
|
||
|
mobile_mac_string,
|
||
|
timeval_to_ms(message.request_time),
|
||
|
timeval_to_ms(message.start_time),
|
||
|
message.antenna_signal_dbm - 0x100,
|
||
|
message.x_position,
|
||
|
message.y_position,
|
||
|
message.z_position,
|
||
|
message.direction
|
||
|
) ;
|
||
|
free(ap_mac_string) ;
|
||
|
free(mobile_mac_string) ;
|
||
|
|
||
|
got_couple_info(&couples, message) ;
|
||
|
}
|
||
|
|
||
|
(void) close(sockfd) ; // Fermeture de la socket
|
||
|
free_couple_list(&couples) ; // Nettoyage
|
||
|
free(out_file) ;
|
||
|
|
||
|
printf("%s : fin.\n", argv[0]) ;
|
||
|
return ret ;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Fonction du thread, qui surveille la liste et envoie les infos au serveur de localisation au bout du timeout */
|
||
|
void* monitor_couple_list(couple_list **couples)
|
||
|
{
|
||
|
couple_list *couple_ptr, *couple_prev ;
|
||
|
couple_info_list *couple_info_ptr ;
|
||
|
struct timeval current_time ;
|
||
|
FILE *fd = NULL ;
|
||
|
char *ap_mac_string ;
|
||
|
|
||
|
fd = fopen(out_file, "a") ; // Ouverture du fichier de sortie en ajout
|
||
|
if (fd == NULL) // Si ouverture échouée,
|
||
|
{
|
||
|
perror("Impossible d'ouvrir le fichier de sortie ") ;
|
||
|
fprintf(stderr, "Redirection de la sortie sur la sortie standard.") ;
|
||
|
fd = stdout ; // on redirige sur stdout
|
||
|
}
|
||
|
|
||
|
while (run)
|
||
|
{
|
||
|
couple_ptr = *couples ;
|
||
|
couple_prev = NULL ;
|
||
|
couple_info_ptr = NULL ;
|
||
|
gettimeofday(¤t_time, NULL) ;
|
||
|
|
||
|
while (couple_ptr != NULL) // Parcours de la liste
|
||
|
{
|
||
|
if (couple_ptr->info != NULL) // Si le couple atteint n'a pas déjà été traité
|
||
|
{
|
||
|
if (sub_date(couple_ptr->start_time, current_time) > AGGREGATE_TIMEOUT) // Si le timeout est atteint,
|
||
|
{
|
||
|
printf("* Timeout dépassé.\n") ;
|
||
|
fprintf(fd, "%f;%f;%f;%hhd", couple_ptr->x_position, couple_ptr->y_position, couple_ptr->z_position, couple_ptr->direction) ; // Inscription des infos du couple dans le fichier
|
||
|
|
||
|
couple_info_ptr = couple_ptr->info ;
|
||
|
while (couple_info_ptr != NULL) // On vide la liste des infos
|
||
|
{
|
||
|
// Inscription des infos de l'AP dans le fichier
|
||
|
ap_mac_string = mac_bytes_to_string(couple_info_ptr->ap_mac_addr_bytes) ;
|
||
|
fprintf(fd, ";%s;%d", ap_mac_string, couple_info_ptr->antenna_signal_dbm - 0x100) ;
|
||
|
free(ap_mac_string) ;
|
||
|
|
||
|
// Suppression du maillon
|
||
|
couple_info_ptr = couple_info_ptr->next ;
|
||
|
free(couple_ptr->info) ;
|
||
|
couple_ptr->info = couple_info_ptr ;
|
||
|
}
|
||
|
|
||
|
fprintf(fd, "\n") ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
else if (sub_date(couple_ptr->start_time, current_time) > KEEP_TIMEOUT) // Si le couple a été traité et que le temps de garde est écoulé
|
||
|
{
|
||
|
couple_list *couple_tmp = couple_ptr ;
|
||
|
|
||
|
printf("* Délai de garde dépassé.\n") ;
|
||
|
|
||
|
couple_ptr = couple_ptr->next ;
|
||
|
|
||
|
if (couple_prev == NULL) // Si on est en tête de liste,
|
||
|
*couples = couple_ptr ; // on positionne la tête sur le suivant
|
||
|
else
|
||
|
couple_prev->next = couple_ptr ; // sinon on positionne le suivant du précédent sur le suivant.
|
||
|
|
||
|
free(couple_tmp) ;
|
||
|
|
||
|
continue ; // On saute les instructions pour aller au suivant puisque c'est déjà fait
|
||
|
}
|
||
|
|
||
|
// Couple suivant
|
||
|
couple_prev = couple_ptr ;
|
||
|
couple_ptr = couple_ptr->next ;
|
||
|
}
|
||
|
|
||
|
fflush(NULL) ;
|
||
|
usleep(CHECK_INTERVAL) ; // On attend avant de vérifier à nouveau
|
||
|
}
|
||
|
|
||
|
fclose(fd) ;
|
||
|
|
||
|
return NULL ;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Fonction appelée lors de la réception d'un paquet */
|
||
|
void got_couple_info(couple_list **couples, couple_message message)
|
||
|
{
|
||
|
couple_list *tmp_couple = NULL ;
|
||
|
couple_info_list *tmp_info = NULL ;
|
||
|
|
||
|
tmp_info = malloc(sizeof(couple_info_list)) ;
|
||
|
memcpy(tmp_info->ap_mac_addr_bytes, message.ap_mac_addr_bytes, 6) ;
|
||
|
tmp_info->antenna_signal_dbm = message.antenna_signal_dbm ;
|
||
|
tmp_info->next = NULL ;
|
||
|
|
||
|
tmp_couple = *couples ;
|
||
|
if (*couples == NULL) // Si la liste de couples n'existe pas encore,
|
||
|
{
|
||
|
printf("Création de la liste des couples.\n") ;
|
||
|
tmp_couple = malloc(sizeof(couple_list)) ; // on la crée.
|
||
|
memcpy(tmp_couple->mobile_mac_addr_bytes, message.mobile_mac_addr_bytes, 6) ;
|
||
|
tmp_couple->request_time = message.request_time ;
|
||
|
tmp_couple->start_time = message.start_time ;
|
||
|
tmp_couple->x_position = message.x_position ;
|
||
|
tmp_couple->y_position = message.y_position ;
|
||
|
tmp_couple->z_position = message.z_position ;
|
||
|
tmp_couple->direction = message.direction ;
|
||
|
tmp_couple->next = NULL ;
|
||
|
tmp_couple->info = tmp_info ;
|
||
|
*couples = tmp_couple ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
while (tmp_couple != NULL) // Sinon on cherche si le couple existe déjà dans la liste
|
||
|
{
|
||
|
if(mac_cmp(message.mobile_mac_addr_bytes, tmp_couple->mobile_mac_addr_bytes) == 1
|
||
|
&& message.request_time.tv_usec == tmp_couple->request_time.tv_usec) // Si le couple existe déjà,
|
||
|
break ; // on s'arrête dessus.
|
||
|
tmp_couple = tmp_couple->next ;
|
||
|
}
|
||
|
|
||
|
if (tmp_couple == NULL) // Si couple inexistant dans la liste
|
||
|
{
|
||
|
printf("Création du couple.\n") ;
|
||
|
tmp_couple = malloc(sizeof(couple_list)) ; // on crée un nouveau couple.
|
||
|
memcpy(tmp_couple->mobile_mac_addr_bytes, message.mobile_mac_addr_bytes, 6) ;
|
||
|
tmp_couple->request_time = message.request_time ;
|
||
|
tmp_couple->start_time = message.start_time ;
|
||
|
tmp_couple->x_position = message.x_position ;
|
||
|
tmp_couple->y_position = message.y_position ;
|
||
|
tmp_couple->z_position = message.z_position ;
|
||
|
tmp_couple->direction = message.direction ;
|
||
|
tmp_couple->next = *couples ;
|
||
|
tmp_couple->info = tmp_info ;
|
||
|
*couples = tmp_couple ;
|
||
|
}
|
||
|
else // Si couple trouvé dans la liste
|
||
|
{
|
||
|
if (tmp_couple->info == NULL) // Si on a déjà envoyé les infos de ce couple au serveur
|
||
|
{
|
||
|
printf("Demande déjà traitée.\n") ;
|
||
|
free(tmp_info) ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("Ajout des informations au couple.\n") ;
|
||
|
tmp_info->next = tmp_couple->info ; // on ajoute l'info.
|
||
|
tmp_couple->info = tmp_info ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Vide la liste chaînée de couples */
|
||
|
void free_couple_list(couple_list **couples)
|
||
|
{
|
||
|
couple_list *couple_ptr = *couples ;
|
||
|
couple_info_list *couple_info_ptr = NULL ;
|
||
|
|
||
|
if (*couples != NULL)
|
||
|
{
|
||
|
while (couple_ptr != NULL)
|
||
|
{
|
||
|
couple_info_ptr = couple_ptr->info ;
|
||
|
while (couple_info_ptr != NULL)
|
||
|
{
|
||
|
couple_info_ptr = couple_info_ptr->next ;
|
||
|
free(couple_ptr->info) ;
|
||
|
couple_ptr->info = couple_info_ptr ;
|
||
|
}
|
||
|
couple_ptr = couple_ptr->next ;
|
||
|
free(*couples) ;
|
||
|
*couples = couple_ptr ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Affiche la liste des couples */
|
||
|
void print_couple_list(couple_list *couples)
|
||
|
{
|
||
|
couple_list *couple_ptr = couples ;
|
||
|
couple_info_list *info_ptr = NULL ;
|
||
|
char *mobile_mac_string ;
|
||
|
|
||
|
if (couples == NULL) // Si la liste est vide
|
||
|
{
|
||
|
printf("Aucun couple.\n") ; // on l'affiche.
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
while (couple_ptr != NULL)
|
||
|
{
|
||
|
info_ptr = couple_ptr->info ; // On récupère le pointeur de la sous-liste
|
||
|
|
||
|
mobile_mac_string = mac_bytes_to_string(couple_ptr->mobile_mac_addr_bytes) ;
|
||
|
printf("MAC du mobile : %s\n\
|
||
|
Numéro de séquence : %lu\n\
|
||
|
Heure de réception de la demande de localisation : %lu\n\
|
||
|
\n",
|
||
|
mobile_mac_string,
|
||
|
couple_ptr->request_time.tv_usec,
|
||
|
couple_ptr->start_time.tv_usec
|
||
|
) ;
|
||
|
free(mobile_mac_string) ;
|
||
|
|
||
|
while (info_ptr != NULL) // On parcourt toutes les informations relative au couple courant
|
||
|
{
|
||
|
print_couple_info(info_ptr) ;
|
||
|
putchar('\n') ;
|
||
|
info_ptr = info_ptr->next ;
|
||
|
}
|
||
|
|
||
|
printf("\n\n") ;
|
||
|
|
||
|
couple_ptr = couple_ptr->next ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Affiche un maillon d'une couple_info_list */
|
||
|
void print_couple_info(couple_info_list *info)
|
||
|
{
|
||
|
char *ap_mac_string ;
|
||
|
if (info == NULL)
|
||
|
return ;
|
||
|
|
||
|
ap_mac_string = mac_bytes_to_string(info->ap_mac_addr_bytes) ;
|
||
|
printf("\tMAC de l'AP : %s\n\
|
||
|
\tPuissance du signal : %d dBm\n",
|
||
|
ap_mac_string,
|
||
|
info->antenna_signal_dbm - 0x100
|
||
|
) ;
|
||
|
free(ap_mac_string) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Affiche le mode d'emploi du programme */
|
||
|
void print_usage(char *prog)
|
||
|
{
|
||
|
printf("Usage :\n\
|
||
|
\t%s fichier_sortie\n\
|
||
|
", prog) ;
|
||
|
}
|