/* * 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 != ARGC) { print_usage(argv[0]) ; return ERR_BAD_USAGE ; } run = TRUE ; /* Fichier de sortie */ out_file = malloc((strlen(argv[ARGV_OUTPUT_FILE]) + 1) * sizeof(char)) ; strcpy(out_file, argv[ARGV_OUTPUT_FILE]) ; /* 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, "%0.2f;%0.2f;%0.2f;%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 } /* Fermeture du fichier */ if (fclose(fd) != 0) perror("Erreur lors de la fermeture du fichier de sortie ") ; 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) ; }