owlps/loc-bts/client/locclient.c

161 lines
4.8 KiB
C
Raw Normal View History

/*
* This file is part of the rtap localisation project.
*/
#include "../../librtaputil/rtaputil.h"
#define DEBUG
/* Codes d'erreurs */
#define ERR_CREATING_SOCKET 1
#define ERR_BAD_NUMBER_OF_ARGS 2
#define ERR_SENDING_INFO 3
/* 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
/* 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
/* 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 if(argc == ARGC_CALIB) // 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)) ;
#ifdef DEBUG
printf("Paquets envoyés : .") ;
#endif
if (nsent != (ssize_t) buf_size)
{
perror("Erreur lors de l'envoi des infos au serveur ") ;
return ERR_SENDING_INFO ;
}
if (argc == ARGC_CALIB) // Dans le cas d'un paquet de calibration, on envoit une rafale de NBPKT_CALIB paquets?
{
int i ;
for (i = 0 ; i < NBPKT_CALIB - 1 ; i++)
{
usleep(50000) ; // On attend 50 ms entre chaque paquet.
nsent = sendto(sockfd, (void *) buf, buf_size, 0, (struct sockaddr *) &server, (socklen_t) sizeof(server)) ;
#ifdef DEBUG
putchar('.') ;
fflush(stdout) ;
#endif
if (nsent != (ssize_t) buf_size)
{
perror("Erreur lors de l'envoi des infos au serveur ") ;
return ERR_SENDING_INFO ;
}
}
}
#ifdef DEBUG
putchar('\n') ;
#endif
(void) close(sockfd) ;
return 0 ;
}