[Aggregator] Code refactoring (conf parsing, loop)

This commit is contained in:
Matteo Cypriani 2010-07-12 12:50:02 +02:00
parent a955467c83
commit 1863bd9e9f
2 changed files with 225 additions and 160 deletions

View File

@ -58,13 +58,21 @@ typedef struct _couple_list
/* En-têtes de fonctions */
void initialise_configuration(int argc, char **argv) ;
void parse_config_file(int argc, char **argv) ;
void parse_command_line(int argc, char **argv) ;
void check_configuration(void) ;
int read_loop(int sockfd) ;
void got_couple_info(couple_list **couples, couple_message message) ;
void free_couple_list(couple_list **couples) ;
#ifdef DEBUG
void print_couple_list(couple_list *couples) ;
void print_couple_info(couple_info_list *info) ;
#endif // DEBUG
void* monitor_couple_list(couple_list **couples) ;
void print_usage(char *prog) ;
char* ip_bytes_to_string(unsigned char *ip_binary) ;
void print_usage(void) ;
#endif

View File

@ -7,163 +7,21 @@
cfg_t *cfg ; // Structure contenant la configuration
char* ip_bytes_to_string(unsigned char *ip_binary)
{
int taille = 16, i = 0;
for(i = 0; i < 4; i++)
{
if(ip_binary[i] < 0x64)
taille--;
if(ip_binary[i] < 0x10)
taille--;
}
char *ret = malloc(sizeof(char) * taille) ;
char *program_name = NULL ;
cfg_t *cfg = NULL ; // Configuration structure
couple_list *couples = NULL ; // Computed data list
sprintf(ret, "%d.%d.%d.%d", ip_binary[0], ip_binary[1], ip_binary[2], ip_binary[3]) ;
ret[taille-1] = '\0' ;
return ret ;
}
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()
char *mobile_ip_string ;
int sockfd ; // Socket d'écoute UDP
cfg_opt_t opts[] = { // Options reconnues par confuse dans le fichier de config
CFG_INT("listening_port", AGGREGATE_DEFAULT_PORT, CFGF_NONE), // Port d'écoute
CFG_INT("positioner_port", POSITIONER_DEFAULT_PORT, CFGF_NONE), // Port d'envoi sur le serveur de calcul
CFG_STR("positioner_ip", POSITIONER_DEFAULT_IP, CFGF_NONE), // Adresse IP du serveur de géolocalisation
CFG_STR("output_file", "", CFGF_NONE), // Fichier de sortie
CFG_INT("aggregate_timeout", DEFAULT_AGGREGATE_TIMEOUT, CFGF_NONE), // Timeout d'agrégation (en millisecondes)
CFG_INT("keep_timeout", DEFAULT_KEEP_TIMEOUT, CFGF_NONE), // Temps que l'on conserve les données dans la liste (en millisecondes)
CFG_INT("check_interval", DEFAULT_CHECK_INTERVAL, CFGF_NONE), // Temps entre deux vérifications de la liste (en micro-secondes)
CFG_END() } ;
char *config_file ; // Nom du fichier de configuration
int opt ; // Retour de getopt
/* L'option -f sert à spécifier un fichier de configuration alternatif,
* on regarde en premier si elle est présente */
do
opt = getopt(argc, argv, OPTIONS) ;
while (opt != 'f' && opt != -1) ;
if (opt == 'f')
{
config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ;
strcpy(config_file, optarg) ;
}
else // Si -f n'est pas présente, on utilise le fichier de config par défaut
{
config_file = malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ;
strcpy(config_file, DEFAULT_CONFIG_FILE) ;
}
/* Lecture du fichier de configuration */
cfg = cfg_init(opts, CFGF_NONE) ; // Initialisation des options
if (cfg_parse(cfg, config_file) == CFG_PARSE_ERROR)
{
free(config_file) ;
return ERR_PARSING_CONFIG_FILE ;
}
free(config_file) ;
/* Lecture des arguments de la ligne de commandes */
optind = 1 ; // On reprend l'analyse des arguments au début
while ((opt = getopt(argc, argv, OPTIONS)) != -1)
{
switch (opt)
{
case 'a' :
cfg_setint(cfg, "aggregate_timeout", strtol(optarg, NULL, 0)) ;
break ;
case 'c' :
cfg_setint(cfg, "check_interval", strtol(optarg, NULL, 0)) ;
break ;
case 'f' : // Fichier de configuration
// Déjà traité.
break ;
case 'i' :
cfg_setstr(cfg, "positioner_ip", optarg) ;
break ;
case 'k' :
cfg_setint(cfg, "keep_timeout", strtol(optarg, NULL, 0)) ;
break ;
case 'l' :
cfg_setint(cfg, "listening_port", strtol(optarg, NULL, 0)) ;
break ;
case 'o' :
cfg_setstr(cfg, "output_file", optarg) ;
break ;
case 'p' :
cfg_setint(cfg, "positioner_port", strtol(optarg, NULL, 0)) ;
break ;
default :
print_usage(argv[0]) ;
return ERR_BAD_USAGE ;
}
}
/* Vérification des arguments */
// output_file //
if (cfg_getstr(cfg, "output_file")[0] == '\0')
{
fprintf(stderr, "Erreur ! Vous devez spécifier un fichier de sortie.\n") ;
print_usage(argv[0]) ;
return ERR_BAD_USAGE ;
}
// positioner_ip //
if (cfg_getstr(cfg, "positioner_ip")[0] == '\0')
{
fprintf(stderr, "Erreur ! Vous devez spécifier l'adresse IP du serveur de géolocalisation.\n") ;
print_usage(argv[0]) ;
return ERR_BAD_USAGE ;
}
// aggregate_timeout //
if (cfg_getint(cfg, "aggregate_timeout") < 0)
{
#ifdef DEBUG
fprintf(stderr, "Attention ! aggregate_timeout n'admet pas de valeur négative : application de la valeur par défaut.\n") ;
#endif // DEBUG
cfg_setint(cfg, "aggregate_timeout", DEFAULT_AGGREGATE_TIMEOUT) ;
}
// keep_timeout //
if (cfg_getint(cfg, "keep_timeout") < 0)
{
#ifdef DEBUG
fprintf(stderr, "Attention ! keep_timeout n'admet pas de valeur négative : application de la valeur par défaut.\n") ;
#endif // DEBUG
cfg_setint(cfg, "keep_timeout", DEFAULT_KEEP_TIMEOUT) ;
}
// check_interval //
if (cfg_getint(cfg, "check_interval") < 0)
{
#ifdef DEBUG
fprintf(stderr, "Attention ! check_interval n'admet pas de valeur négative : application de la valeur par défaut.\n") ;
#endif // DEBUG
cfg_setint(cfg, "check_interval", DEFAULT_CHECK_INTERVAL) ;
}
#ifdef DEBUG
/* Affichage de la configuration */
fprintf(stderr, "Configuration :\n") ;
cfg_print(cfg, stderr) ;
#endif // DEBUG
run = TRUE ;
program_name = argv[0] ;
initialise_configuration(argc, argv) ;
/* Mise en place des gestionnaires de signaux */
sigemptyset(&action.sa_mask) ;
@ -182,7 +40,188 @@ int main(int argc, char **argv)
/* Création du thread */
pthread_create(&thread, NULL, (void *) &monitor_couple_list, &couples) ;
/* Lecture sur la socket */
run = TRUE ;
ret = read_loop(sockfd) ;
(void) close(sockfd) ; // Fermeture de la socket
free_couple_list(&couples) ; // Nettoyage de la liste
cfg_free(cfg) ; // Nettoyage de la configuration
printf("%s : fin.\n", argv[0]) ;
return ret ;
}
void initialise_configuration(int argc, char **argv)
{
parse_config_file(argc, argv) ;
parse_command_line(argc, argv) ;
check_configuration() ;
#ifdef DEBUG
/* Configuration printing */
fprintf(stderr, "Configuration :\n") ;
cfg_print(cfg, stderr) ;
#endif // DEBUG
}
void parse_config_file(int argc, char **argv)
{
// Config file options for confuse
cfg_opt_t opts[] =
{
CFG_INT("listening_port", AGGREGATE_DEFAULT_PORT, CFGF_NONE),
// Port and IP address of the localisation server:
CFG_INT("positioner_port", POSITIONER_DEFAULT_PORT, CFGF_NONE),
CFG_STR("positioner_ip", POSITIONER_DEFAULT_IP, CFGF_NONE),
CFG_STR("output_file", "", CFGF_NONE),
// Timeouts (in milliseconds):
CFG_INT("aggregate_timeout", DEFAULT_AGGREGATE_TIMEOUT, CFGF_NONE),
CFG_INT("keep_timeout", DEFAULT_KEEP_TIMEOUT, CFGF_NONE),
// Time between two list checks (in microseconds):
CFG_INT("check_interval", DEFAULT_CHECK_INTERVAL, CFGF_NONE),
CFG_END()
} ;
char *config_file ;
// Option -f specifies a config file, so we search for it first
int opt ;
do
opt = getopt(argc, argv, OPTIONS) ;
while (opt != 'f' && opt != -1) ;
if (opt == 'f')
{
config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ;
strcpy(config_file, optarg) ;
}
else // If -f isn't found, we use the default config file
{
config_file = malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ;
strcpy(config_file, DEFAULT_CONFIG_FILE) ;
}
/* Parse config file */
cfg = cfg_init(opts, CFGF_NONE) ; // Initialise options
if (cfg_parse(cfg, config_file) == CFG_PARSE_ERROR)
{
free(config_file) ;
exit(ERR_PARSING_CONFIG_FILE) ;
}
free(config_file) ;
}
void parse_command_line(int argc, char **argv)
{
int opt ;
optind = 1 ; // Rewind argument parsing
while ((opt = getopt(argc, argv, OPTIONS)) != -1)
{
switch (opt)
{
case 'a' :
cfg_setint(cfg, "aggregate_timeout", strtol(optarg, NULL, 0)) ;
break ;
case 'c' :
cfg_setint(cfg, "check_interval", strtol(optarg, NULL, 0)) ;
break ;
case 'f' : // Config file
break ; // (already parsed)
case 'i' :
cfg_setstr(cfg, "positioner_ip", optarg) ;
break ;
case 'k' :
cfg_setint(cfg, "keep_timeout", strtol(optarg, NULL, 0)) ;
break ;
case 'l' :
cfg_setint(cfg, "listening_port", strtol(optarg, NULL, 0)) ;
break ;
case 'o' :
cfg_setstr(cfg, "output_file", optarg) ;
break ;
case 'p' :
cfg_setint(cfg, "positioner_port", strtol(optarg, NULL, 0)) ;
break ;
default :
print_usage() ;
exit(ERR_BAD_USAGE) ;
}
}
}
void check_configuration()
{
// output_file //
if (cfg_getstr(cfg, "output_file")[0] == '\0')
{
fprintf(stderr, "Error! You must specify an output file.\n") ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
}
// positioner_ip //
if (cfg_getstr(cfg, "positioner_ip")[0] == '\0')
{
fprintf(stderr, "Error! You must specify the IP address of the"
" localisation server.\n") ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
}
// aggregate_timeout //
if (cfg_getint(cfg, "aggregate_timeout") < 0)
{
#ifdef DEBUG
fprintf(stderr, "Warning! aggregate_timeout cannot be negative:"
" failing back to default value.\n") ;
#endif // DEBUG
cfg_setint(cfg, "aggregate_timeout", DEFAULT_AGGREGATE_TIMEOUT) ;
}
// keep_timeout //
if (cfg_getint(cfg, "keep_timeout") < 0)
{
#ifdef DEBUG
fprintf(stderr, "Warning! keep_timeout cannot be negative:"
" failing back to default value.\n") ;
#endif // DEBUG
cfg_setint(cfg, "keep_timeout", DEFAULT_KEEP_TIMEOUT) ;
}
// check_interval //
if (cfg_getint(cfg, "check_interval") < 0)
{
#ifdef DEBUG
fprintf(stderr, "Warning! check_interval cannot be negative:"
" failing back to default value.\n") ;
#endif // DEBUG
cfg_setint(cfg, "check_interval", DEFAULT_CHECK_INTERVAL) ;
}
}
int read_loop(int sockfd)
{
int ret = 0 ; // Return value
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
char *ap_mac_string, *mobile_mac_string ; // Pointeurs pour retour de mac_bytes_to_string()
char *mobile_ip_string ;
while (run)
{
nread = recvfrom(sockfd, &message, sizeof(message), 0, (struct sockaddr *) &client, &client_len) ;
@ -230,17 +269,11 @@ int main(int argc, char **argv)
got_couple_info(&couples, message) ;
}
(void) close(sockfd) ; // Fermeture de la socket
free_couple_list(&couples) ; // Nettoyage de la liste
cfg_free(cfg) ; // Nettoyage de la configuration
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)
{
@ -556,8 +589,32 @@ void print_couple_info(couple_info_list *info)
char* ip_bytes_to_string(unsigned char *ip_binary)
{
int
taille = 16,
i = 0 ;
for (i = 0 ; i < 4 ; ++i)
{
if (ip_binary[i] < 0x64)
taille-- ;
if (ip_binary[i] < 0x10)
taille-- ;
}
char *ret = malloc(sizeof(char) * taille) ;
sprintf(ret, "%d.%d.%d.%d", ip_binary[0], ip_binary[1], ip_binary[2], ip_binary[3]) ;
ret[taille-1] = '\0' ;
return ret ;
}
/* Affiche le mode d'emploi du programme */
void print_usage(char *prog)
void print_usage()
{
printf("Usage :\n\
\t%s [-f config_file] [-l listening_port] [-i positionner_ip] [-p positioner_port] [-a aggregate_timeout] [-k keep_timeout] [-c check_interval] [-o output_file]\n\
@ -569,10 +626,10 @@ Options serveur :\n\
\t-p positioner_port : les demandes agrégées seront transmises sur ce port du serveur de calcul (défaut : %d).\n\
Options d'agrégation :\n\
\t-a aggregate_timeout : temps d'agrégation (défaut : %d millisecondes)\n\
\t-a keep_timeout : temps de garde des demandes (défaut : %d millisecondes)\n\
\t-a check_interval : délai entre deux vérifications des demandes en mémoire, et agrégation (défaut : %d micro-secondes)\n\
\t-k keep_timeout : temps de garde des demandes (défaut : %d millisecondes)\n\
\t-c check_interval : délai entre deux vérifications des demandes en mémoire, et agrégation (défaut : %d micro-secondes)\n\
",
prog,
program_name,
AGGREGATE_DEFAULT_PORT,
POSITIONER_DEFAULT_IP,
POSITIONER_DEFAULT_PORT,