owlps/infrastructure-centred/owlps-client/owlps-client.c

168 lines
5.5 KiB
C
Raw Normal View History

/*
* This file is part of the rtap localisation project.
*/
#include "../../libowlps/owlps.h"
#define DEBUG
/* Codes d'erreurs */
#define ERR_CREATING_SOCKET 1 // Erreur lors de la création de la socket d'envoi
#define ERR_BAD_NUMBER_OF_ARGS 2 // Mauvais nombre d'arguments lors de l'appel au programme
#define ERR_SENDING_INFO 3 // Erreur lors de l'envoi de l'une des demandes de positionnement
/* Nombre d'arguments du programme */
#define ARGC_NORMAL 2
#define ARGC_CALIB 6
/* Nombre de paquets envoyés */
#define NBPKT_CALIB 20 // Rafale de 20 paquets lors de la calibration
#define NBPKT_NORMAL 10 // Nombre de paquets envoyés dans le cas d'une demande de localisation
/* Délai entre chaque paquet envoyé */
#define DELAY_CALIB 50000 // Délai entre chaque émission de paquet lors de la calibration (en microsecondes)
#define DELAY_NORMAL 25000 // Délai entre chaque émission de paquet dans le cas d'une demande de localisation (en microsecondes)
/* Affiche le mode d'emploi du programme */
void print_usage(char *prog)
{
printf("Usage :\n\
\t- Demande de localisation : %s [iface] ip_serveur\n\
\t- Requête de calibration : %s [iface] ip_serveur direction x y z\n\
iface est une chaîne désignant le nom de interface réseau à partir de laquelle envoyer la demande (par exemple \"eth2\"). Si elle n'est pas spécifiée, le choix de l'interface source est automatique. Vous devez être root pour utiliser cette option.\n\
", prog, prog) ;
}
int main(int argc, char *argv[])
{
struct timeval request_time ;
char *buf = NULL ; // Paquet à envoyer
int buf_offset ; // Indice dans le paquet à envoyer, utilisé lors de sa création
int buf_size ; // Taille du paquet envoyé
struct sockaddr_in server, client ;
int sockfd ; // Descripteur de la socket d'envoi
ssize_t nsent ; // Retour de sendto
char iface[IFNAMSIZ + 1] = "" ; // Interface réseau depuis laquelle on envoit le paquet
int i ; // Compteur
int delay = (argc == ARGC_NORMAL ? DELAY_NORMAL : DELAY_CALIB) ; // Temps d'attente entre chaque émission de paquet
/* Test du nombre d'arguments */
if (argc == ARGC_NORMAL + 1 || argc == ARGC_CALIB + 1) // Si on a spécifié un nom d'interface
{
strncpy(iface, argv[1], IFNAMSIZ + 1) ;
argv++ ;
argc-- ;
}
/* Test du nombre d'arguments (suite) */
if (argc != ARGC_NORMAL && argc != ARGC_CALIB)
{
print_usage(argv[0]) ;
return ERR_BAD_NUMBER_OF_ARGS ;
}
/* Ouverture de la socket UDP vers le serveur d'aggrégation */
sockfd = create_udp_sending_socket(argv[1], LOC_REQUEST_DEFAULT_PORT, &server, &client) ;
if (sockfd < 0)
{
perror("Erreur ! Impossible de créer la socket vers le serveur d'aggrégation \n");
return ERR_CREATING_SOCKET ;
}
if (iface[0] != '\0') // Si on a spécifié un nom d'interface
{
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1)
{
fprintf(stderr, "Erreur ! Impossible de sélectionner l'interface %s pour l'envoi du paquet : ", iface) ;
perror("") ;
fprintf(stderr, "Envoi sur l'interface par défaut.\n") ;
}
}
/* Création du paquet à envoyer */
gettimeofday(&request_time, NULL) ;
if (argc == ARGC_NORMAL) // Paquet normal
{
printf("Envoi normal effectué à : %llu\n", timeval_to_ms(request_time)) ;
buf_size = sizeof(char) + sizeof(struct timeval) ;
buf = malloc(buf_size) ;
buf[0] = PACKET_TYPE_NORMAL ; // Type de paquet = demande
memcpy(&buf[1], &request_time, sizeof(request_time)) ;
}
else // Paquet calibration
{
printf("Envoi Calibration effectué à : %llu\n", timeval_to_ms(request_time)) ;
buf_offset = 0 ;
buf_size = sizeof(char) * 2 + sizeof(struct timeval) + sizeof(float) * 3 ;
buf = malloc(buf_size) ;
buf[buf_offset++] = PACKET_TYPE_CALIBRATION ; // Type de paquet = calibration
memcpy(&buf[buf_offset], &request_time, sizeof(request_time)) ;
buf_offset += sizeof(request_time) ;
buf[buf_offset++] = atoi(argv[2]) ; // Direction
float posX = atof(argv[3]) ;
float posY = atof(argv[4]) ;
float posZ = atof(argv[5]) ;
#ifdef DEBUG
printf("direction = %d, posX = %f, posY = %f, posZ = %f\n", buf[buf_offset - 1], posX, posY, posZ) ;
#endif
memcpy(&buf[buf_offset], &posX, sizeof(float)) ;
buf_offset += sizeof(float) ;
memcpy(&buf[buf_offset], &posY, sizeof(float)) ;
buf_offset += sizeof(float) ;
memcpy(&buf[buf_offset], &posZ, sizeof(float)) ;
}
/* Envoi des infos au serveur d'aggrégation */
nsent = sendto(sockfd, (void *) buf, buf_size, 0, (struct sockaddr *) &server, (socklen_t) sizeof(server)) ; // Envoi d'un paquet.
if (nsent != (ssize_t) buf_size)
{
perror("Erreur lors de l'envoi des informations au serveur ") ;
return ERR_SENDING_INFO ;
}
#ifdef DEBUG
printf("Paquets envoyés : .") ;
fflush(stdout) ;
#endif
for (i = 0 ; i < (argc == ARGC_NORMAL ? NBPKT_NORMAL : NBPKT_CALIB) - 1 ; i++) // Si tels sont les paramètres, on envoit éventuellement la suite de la rafale de paquets :
{
usleep(delay) ; // On attend le temps voulu entre chaque paquet.
nsent = sendto(sockfd, (void *) buf, buf_size, 0, (struct sockaddr *) &server, (socklen_t) sizeof(server)) ;
if (nsent != (ssize_t) buf_size)
{
perror("Erreur lors de l'envoi des infos au serveur ") ;
return ERR_SENDING_INFO ;
}
#ifdef DEBUG
putchar('.') ;
fflush(stdout) ;
#endif
}
#ifdef DEBUG
putchar('\n') ;
#endif
(void) close(sockfd) ;
return 0 ;
}