2008-02-14 08:54:51 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the rtap localisation project.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2008-10-06 17:27:33 +02:00
|
|
|
#include "owlps-aggregator.h"
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-08-06 12:29:39 +02:00
|
|
|
#include <assert.h>
|
|
|
|
|
2008-03-14 11:31:04 +01:00
|
|
|
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
char *program_name = NULL ;
|
|
|
|
cfg_t *cfg = NULL ; // Configuration structure
|
|
|
|
couple_list *couples = NULL ; // Computed data list
|
2010-10-26 14:53:24 +02:00
|
|
|
ap_list *token_aps = NULL ; // Token ring of the APs
|
2010-08-06 12:29:39 +02:00
|
|
|
unsigned int nb_aps = 0 ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
2009-05-29 17:02:20 +02:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
int ret = 0 ; // Program return value
|
|
|
|
struct sigaction action ; // Signal handler structure
|
2010-10-11 09:54:35 +02:00
|
|
|
pthread_t
|
|
|
|
monitor_thread, // Aggregated data monitoring thread
|
2010-10-26 10:24:29 +02:00
|
|
|
monitor_aps_thread, // APs monitoring thread
|
2010-10-11 09:54:35 +02:00
|
|
|
autocalibration_hello_thread ; // Hello messages reception thread
|
2010-07-12 16:34:25 +02:00
|
|
|
unsigned int listening_port ;
|
|
|
|
int sockfd ; // UDP listening socket
|
2010-07-12 12:50:02 +02:00
|
|
|
|
|
|
|
program_name = argv[0] ;
|
|
|
|
initialise_configuration(argc, argv) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/* Set up signal handlers */
|
2010-07-12 12:50:02 +02:00
|
|
|
sigemptyset(&action.sa_mask) ;
|
|
|
|
action.sa_handler = sigint_handler ;
|
|
|
|
sigaction(SIGINT, &action, NULL) ;
|
|
|
|
action.sa_handler = sigterm_handler ;
|
|
|
|
sigaction(SIGTERM, &action, NULL) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/* Create UDP socket */
|
|
|
|
listening_port = cfg_getint(cfg, "listening_port") ;
|
|
|
|
if ((sockfd = create_udp_listening_socket(listening_port)) < 0)
|
2009-05-29 17:02:20 +02:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
fprintf(stderr,
|
|
|
|
"Error! Cannot listen on port %u.\n", listening_port) ;
|
2010-07-12 12:50:02 +02:00
|
|
|
return ERR_CREATING_SOCKET ;
|
2009-05-29 17:02:20 +02:00
|
|
|
}
|
|
|
|
|
2010-10-11 09:54:35 +02:00
|
|
|
/* Set up threads */
|
|
|
|
pthread_create(&monitor_thread, NULL,
|
|
|
|
(void *) &monitor_couples, NULL) ;
|
|
|
|
pthread_create(&autocalibration_hello_thread, NULL,
|
2010-10-25 16:36:55 +02:00
|
|
|
(void *) &listen_for_aps, NULL) ;
|
2010-10-26 10:24:29 +02:00
|
|
|
pthread_create(&monitor_aps_thread, NULL,
|
|
|
|
(void *) &monitor_aps, NULL) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
run = TRUE ;
|
|
|
|
ret = read_loop(sockfd) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
(void) close(sockfd) ; // Close socket
|
2010-08-06 09:42:22 +02:00
|
|
|
free_couple_list() ;
|
2010-08-06 12:29:39 +02:00
|
|
|
free_ap_list() ;
|
2010-07-12 16:34:25 +02:00
|
|
|
cfg_free(cfg) ; // Clean configuration
|
2009-05-29 17:02:20 +02:00
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("%s: end.\n", program_name) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
return ret ;
|
|
|
|
}
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
void initialise_configuration(int argc, char **argv)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 12:50:02 +02:00
|
|
|
parse_config_file(argc, argv) ;
|
|
|
|
parse_command_line(argc, argv) ;
|
|
|
|
check_configuration() ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
/* Configuration printing */
|
2010-07-12 16:34:25 +02:00
|
|
|
fprintf(stderr, "Configuration:\n") ;
|
2010-07-12 12:50:02 +02:00
|
|
|
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),
|
|
|
|
|
2010-10-11 09:54:35 +02:00
|
|
|
// Autocalibration activated?
|
|
|
|
CFG_BOOL("autocalibration", cfg_false, CFGF_NONE),
|
|
|
|
// Port on which autocalibration data are exchanged:
|
2010-10-25 16:36:55 +02:00
|
|
|
CFG_INT("autocalibration_port", DEFAULT_AUTOCALIBRATION_PORT,
|
2010-10-11 09:54:35 +02:00
|
|
|
CFGF_NONE),
|
2010-10-14 18:30:41 +02:00
|
|
|
// Time we keep APs in the list (in seconds):
|
|
|
|
CFG_INT("ap_keep_timeout", DEFAULT_AP_KEEP_TIMEOUT, CFGF_NONE),
|
|
|
|
// Time between two checks of the AP list (in milliseconds):
|
|
|
|
CFG_INT("ap_check_interval", DEFAULT_AP_CHECK_INTERVAL, CFGF_NONE),
|
2010-10-11 09:54:35 +02:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
CFG_END()
|
|
|
|
} ;
|
|
|
|
|
|
|
|
char *config_file ;
|
|
|
|
|
|
|
|
// Option -f specifies a config file, so we search for it first
|
|
|
|
int opt ;
|
2009-04-15 14:15:49 +02:00
|
|
|
do
|
|
|
|
opt = getopt(argc, argv, OPTIONS) ;
|
|
|
|
while (opt != 'f' && opt != -1) ;
|
|
|
|
if (opt == 'f')
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2009-04-15 14:15:49 +02:00
|
|
|
config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ;
|
|
|
|
strcpy(config_file, optarg) ;
|
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
else // If -f isn't found, we use the default config file
|
2009-04-15 14:15:49 +02:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
config_file =
|
|
|
|
malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
strcpy(config_file, DEFAULT_CONFIG_FILE) ;
|
|
|
|
}
|
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
/* Parse config file */
|
|
|
|
cfg = cfg_init(opts, CFGF_NONE) ; // Initialise options
|
2010-07-13 14:36:28 +02:00
|
|
|
switch (cfg_parse(cfg, config_file))
|
2009-04-15 14:15:49 +02:00
|
|
|
{
|
2010-07-13 14:36:28 +02:00
|
|
|
case CFG_FILE_ERROR :
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error! Cannot open configuration file « %s »: %s.\n",
|
|
|
|
config_file, strerror(errno)) ;
|
|
|
|
break ;
|
|
|
|
case CFG_PARSE_ERROR :
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error! Parsing of configuration file « %s » failed!\n",
|
|
|
|
config_file) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
free(config_file) ;
|
2010-07-12 12:50:02 +02:00
|
|
|
exit(ERR_PARSING_CONFIG_FILE) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
}
|
|
|
|
free(config_file) ;
|
2010-07-12 12:50:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void parse_command_line(int argc, char **argv)
|
|
|
|
{
|
|
|
|
int opt ;
|
|
|
|
|
|
|
|
optind = 1 ; // Rewind argument parsing
|
2009-04-15 14:15:49 +02:00
|
|
|
|
|
|
|
while ((opt = getopt(argc, argv, OPTIONS)) != -1)
|
|
|
|
{
|
|
|
|
switch (opt)
|
|
|
|
{
|
2010-10-11 09:54:35 +02:00
|
|
|
case 'A' :
|
|
|
|
cfg_setbool(cfg, "autocalibration", cfg_true) ;
|
|
|
|
break ;
|
|
|
|
case 'a' :
|
|
|
|
cfg_setint(cfg, "autocalibration_port",
|
|
|
|
strtol(optarg, NULL, 0)) ;
|
|
|
|
break ;
|
2009-07-02 13:12:51 +02:00
|
|
|
case 'c' :
|
|
|
|
cfg_setint(cfg, "check_interval", strtol(optarg, NULL, 0)) ;
|
|
|
|
break ;
|
2010-10-14 18:30:41 +02:00
|
|
|
case 'C' :
|
|
|
|
cfg_setint(cfg, "ap_check_interval", strtol(optarg, NULL, 0)) ;
|
|
|
|
break ;
|
2010-07-12 12:50:02 +02:00
|
|
|
case 'f' : // Config file
|
|
|
|
break ; // (already parsed)
|
2010-07-12 16:57:32 +02:00
|
|
|
case 'h' :
|
|
|
|
print_usage() ;
|
|
|
|
exit(0) ;
|
2010-07-09 16:57:37 +02:00
|
|
|
case 'i' :
|
2009-07-02 13:12:51 +02:00
|
|
|
cfg_setstr(cfg, "positioner_ip", optarg) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
break ;
|
|
|
|
case 'k' :
|
|
|
|
cfg_setint(cfg, "keep_timeout", strtol(optarg, NULL, 0)) ;
|
|
|
|
break ;
|
2010-10-14 18:30:41 +02:00
|
|
|
case 'K' :
|
|
|
|
cfg_setint(cfg, "ap_keep_timeout", strtol(optarg, NULL, 0)) ;
|
|
|
|
break ;
|
2009-07-02 13:12:51 +02:00
|
|
|
case 'l' :
|
|
|
|
cfg_setint(cfg, "listening_port", strtol(optarg, NULL, 0)) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
break ;
|
2009-07-02 13:12:51 +02:00
|
|
|
case 'o' :
|
|
|
|
cfg_setstr(cfg, "output_file", optarg) ;
|
|
|
|
break ;
|
2009-05-29 17:02:20 +02:00
|
|
|
case 'p' :
|
2009-07-02 13:12:51 +02:00
|
|
|
cfg_setint(cfg, "positioner_port", strtol(optarg, NULL, 0)) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
break ;
|
2010-10-11 09:54:35 +02:00
|
|
|
case 't' :
|
|
|
|
cfg_setint(cfg, "aggregate_timeout", strtol(optarg, NULL, 0)) ;
|
|
|
|
break ;
|
2009-04-15 14:15:49 +02:00
|
|
|
default :
|
2010-07-12 12:50:02 +02:00
|
|
|
print_usage() ;
|
|
|
|
exit(ERR_BAD_USAGE) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
}
|
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
}
|
|
|
|
|
2009-04-15 14:15:49 +02:00
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
void check_configuration()
|
|
|
|
{
|
2009-04-15 14:15:49 +02:00
|
|
|
// output_file //
|
|
|
|
if (cfg_getstr(cfg, "output_file")[0] == '\0')
|
|
|
|
{
|
2010-07-12 12:50:02 +02:00
|
|
|
fprintf(stderr, "Error! You must specify an output file.\n") ;
|
|
|
|
print_usage() ;
|
|
|
|
exit(ERR_BAD_USAGE) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
|
2009-07-02 13:12:51 +02:00
|
|
|
// positioner_ip //
|
|
|
|
if (cfg_getstr(cfg, "positioner_ip")[0] == '\0')
|
2009-05-29 17:02:20 +02:00
|
|
|
{
|
2010-07-12 12:50:02 +02:00
|
|
|
fprintf(stderr, "Error! You must specify the IP address of the"
|
|
|
|
" localisation server.\n") ;
|
|
|
|
print_usage() ;
|
|
|
|
exit(ERR_BAD_USAGE) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
|
2009-04-15 14:15:49 +02:00
|
|
|
// aggregate_timeout //
|
|
|
|
if (cfg_getint(cfg, "aggregate_timeout") < 0)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
2010-07-12 12:50:02 +02:00
|
|
|
fprintf(stderr, "Warning! aggregate_timeout cannot be negative:"
|
|
|
|
" failing back to default value.\n") ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#endif // DEBUG
|
|
|
|
cfg_setint(cfg, "aggregate_timeout", DEFAULT_AGGREGATE_TIMEOUT) ;
|
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
|
2009-04-15 14:15:49 +02:00
|
|
|
// keep_timeout //
|
|
|
|
if (cfg_getint(cfg, "keep_timeout") < 0)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
2010-07-12 12:50:02 +02:00
|
|
|
fprintf(stderr, "Warning! keep_timeout cannot be negative:"
|
|
|
|
" failing back to default value.\n") ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#endif // DEBUG
|
|
|
|
cfg_setint(cfg, "keep_timeout", DEFAULT_KEEP_TIMEOUT) ;
|
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
|
2009-04-15 14:15:49 +02:00
|
|
|
// check_interval //
|
|
|
|
if (cfg_getint(cfg, "check_interval") < 0)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
2010-07-12 12:50:02 +02:00
|
|
|
fprintf(stderr, "Warning! check_interval cannot be negative:"
|
|
|
|
" failing back to default value.\n") ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#endif // DEBUG
|
|
|
|
cfg_setint(cfg, "check_interval", DEFAULT_CHECK_INTERVAL) ;
|
|
|
|
}
|
2010-10-14 18:30:41 +02:00
|
|
|
|
|
|
|
// ap_keep_timeout //
|
|
|
|
if (cfg_getint(cfg, "ap_keep_timeout") < 0)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Warning! ap_keep_timeout cannot be negative:"
|
|
|
|
" failing back to default value.\n") ;
|
|
|
|
#endif // DEBUG
|
|
|
|
cfg_setint(cfg, "ap_keep_timeout", DEFAULT_AP_KEEP_TIMEOUT) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ap_check_interval //
|
|
|
|
if (cfg_getint(cfg, "ap_check_interval") < 0)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Warning! ap_check_interval cannot be negative:"
|
|
|
|
" failing back to default value.\n") ;
|
|
|
|
#endif // DEBUG
|
|
|
|
cfg_setint(cfg, "ap_check_interval", DEFAULT_AP_CHECK_INTERVAL) ;
|
|
|
|
}
|
2010-07-12 12:50:02 +02:00
|
|
|
}
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/*
|
|
|
|
* Reads packets while the program is not stopped.
|
|
|
|
*/
|
2010-07-12 12:50:02 +02:00
|
|
|
int read_loop(int sockfd)
|
|
|
|
{
|
|
|
|
int ret = 0 ; // Return value
|
2010-07-12 16:34:25 +02:00
|
|
|
int nread ; // recvfrom return value
|
|
|
|
struct sockaddr_in client; // UDP client structure
|
|
|
|
socklen_t client_len = sizeof(client) ; // Size of clients
|
|
|
|
couple_message message ; // Message read on the socket
|
|
|
|
char
|
|
|
|
*ap_mac_string, // Return pointers for mac_bytes_to_string()
|
|
|
|
*mobile_mac_string,
|
|
|
|
*mobile_ip_string ; // and ip_bytes_to_string()
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
while (run)
|
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
nread = recvfrom(sockfd, &message, sizeof(message), 0,
|
|
|
|
(struct sockaddr *) &client, &client_len) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
if (nread <= 0)
|
|
|
|
{
|
|
|
|
if (run)
|
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
fprintf(stderr, "No message received from client!\n") ;
|
2008-02-14 08:54:51 +01:00
|
|
|
ret = ERR_NO_MESSAGE_RECEIVED ;
|
|
|
|
}
|
|
|
|
break ;
|
|
|
|
}
|
2010-07-12 16:34:25 +02:00
|
|
|
ap_mac_string =
|
|
|
|
mac_bytes_to_string(message.ap_mac_addr_bytes) ;
|
|
|
|
mobile_mac_string =
|
|
|
|
mac_bytes_to_string(message.mobile_mac_addr_bytes) ;
|
|
|
|
mobile_ip_string =
|
|
|
|
ip_bytes_to_string(message.mobile_ip_addr_bytes) ;
|
|
|
|
printf("\n"
|
|
|
|
"*** Message received from client ***\n"
|
|
|
|
"\tAP MAC: %s\n"
|
|
|
|
"\tMobile MAC: %s\n"
|
|
|
|
"\tMobile IP: %s\n"
|
|
|
|
"\tSequence number (request timestamp): %llu\n"
|
|
|
|
"\tRequest arrival time on the AP: %llu\n"
|
|
|
|
"\tSignal: %d dBm\n"
|
|
|
|
"\tPosition X: %f\n"
|
|
|
|
"\tPosition Y: %f\n"
|
|
|
|
"\tPosition Z: %f\n"
|
|
|
|
"\tDirection: %hhd\n"
|
|
|
|
,
|
2008-02-14 08:54:51 +01:00
|
|
|
ap_mac_string,
|
|
|
|
mobile_mac_string,
|
2009-05-29 17:02:20 +02:00
|
|
|
mobile_ip_string,
|
2008-02-14 08:54:51 +01:00
|
|
|
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) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
free(mobile_ip_string) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-08-06 09:42:22 +02:00
|
|
|
got_couple_info(message) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/*
|
|
|
|
* Thread function. Monitors the list and sends information to the
|
|
|
|
* localisation server when the timeout is reached.
|
|
|
|
*/
|
2010-08-06 09:42:22 +02:00
|
|
|
void* monitor_couples()
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
couple_list *couple_ptr, *couple_prev ;
|
|
|
|
couple_info_list *couple_info_ptr ;
|
|
|
|
struct timeval current_time ;
|
|
|
|
FILE *fd = NULL ;
|
|
|
|
char *ap_mac_string ;
|
2010-07-12 16:34:25 +02:00
|
|
|
unsigned long sub ; // sub_date() result
|
|
|
|
|
|
|
|
unsigned long aggregate_timeout =
|
|
|
|
(unsigned long) cfg_getint(cfg, "aggregate_timeout") ;
|
|
|
|
unsigned long keep_timeout =
|
|
|
|
(unsigned long) cfg_getint(cfg, "keep_timeout") ;
|
2010-07-09 16:57:37 +02:00
|
|
|
|
2009-05-29 17:02:20 +02:00
|
|
|
struct sockaddr_in serv;
|
|
|
|
struct sockaddr_in client ;
|
|
|
|
socklen_t serv_len = sizeof(serv);
|
|
|
|
request demande;
|
|
|
|
couple_info info;
|
Incorporation de la dernière version de Julien
Extrait de son courriel :
« Par rapport à la précédente j'ai surtout corrigé des bugs. »
Note : la version du listener portable sur Fonera, envoyée en même temps
par Julien, viendra plus tard (le temps que je l'incorpore).
Détail des changements après analyse du code :
aggregator : correction de bogues.
positioning :
* Ajout d'un fichier de config format boost (cfg/config.cfg).
* Makefile : implantation des cibles "install" et "uninstall" ; la cible
"astyle" devient "style".
* accesspoint.{hh,cc}, area.cc, measurement.hh, point.{hh,cc},
referencepoint.{hh,cc} : cosmétique.
* owlps-positioning.c : correction de la lecture du fichier de config
(ajout d'une option permettant de spécifier un fichier alternatif).
* server.cc : essentiellement correction des requêtes.
* libowlps-positioning.{hh,cc} : passage de "unsigned long long" à
"uint64_t" comme type de retour de timeval_to_ms().
writeInDb :
* Ajout de la gestion d'un fichier de config.
* Ajout de deux scripts pour la BDD.
git-svn-id: https://pif.pu-pm.univ-fcomte.fr/svn/loc@96 785a6c6c-259e-4ff1-8b91-dc31627914f0
2009-07-01 15:39:58 +02:00
|
|
|
int sockfd;
|
2009-05-29 17:02:20 +02:00
|
|
|
|
2010-10-25 16:36:55 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Monitor couples thread launched.\n") ;
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
sockfd = create_udp_sending_socket(cfg_getstr(cfg, "positioner_ip"),
|
|
|
|
cfg_getint(cfg, "positioner_port"),
|
|
|
|
&serv, &client) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/* Open output file */
|
|
|
|
fd = fopen(cfg_getstr(cfg, "output_file"), "a") ; // We use add mode
|
|
|
|
if (fd == NULL) // If we failed to open the file,
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
perror("Cannot open output file") ;
|
|
|
|
fprintf(stderr, "Redirecting output to standard output.") ;
|
|
|
|
fd = stdout ; // we fail back to stdout.
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
while (run)
|
|
|
|
{
|
2010-08-06 09:42:22 +02:00
|
|
|
couple_ptr = couples ;
|
2008-02-14 08:54:51 +01:00
|
|
|
couple_prev = NULL ;
|
|
|
|
couple_info_ptr = NULL ;
|
|
|
|
gettimeofday(¤t_time, NULL) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
while (couple_ptr != NULL) // Parsing list
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2008-03-14 11:31:04 +01:00
|
|
|
sub = sub_date(couple_ptr->start_time, current_time) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// If the couple was not treated already
|
|
|
|
if (couple_ptr->info != NULL)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
// If the timeout is reached
|
|
|
|
if (sub > aggregate_timeout)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("* Timeout reached.") ;
|
2008-03-14 11:31:04 +01:00
|
|
|
#ifdef DEBUG
|
2010-07-12 16:34:25 +02:00
|
|
|
printf(" sub=%lu > aggregate_timeout=%ld\n",
|
|
|
|
sub, aggregate_timeout) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#else // DEBUG
|
2008-03-14 11:31:04 +01:00
|
|
|
putchar('\n') ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#endif // DEBUG
|
2008-03-14 11:31:04 +01:00
|
|
|
|
2008-07-17 10:21:41 +02:00
|
|
|
#ifdef TIMESTAMP
|
2010-07-12 16:34:25 +02:00
|
|
|
// Print request mobile timestamp to the output file
|
|
|
|
fprintf(fd, "%llu;",
|
|
|
|
timeval_to_ms(couple_ptr->request_time)) ;
|
2008-07-17 10:21:41 +02:00
|
|
|
#endif // TIMESTAMP
|
2010-07-12 16:34:25 +02:00
|
|
|
// Print couple info to the output file
|
|
|
|
fprintf(fd, "%0.2f;%0.2f;%0.2f;%hhd",
|
|
|
|
couple_ptr->x_position, couple_ptr->y_position,
|
|
|
|
couple_ptr->z_position, couple_ptr->direction) ;
|
|
|
|
|
|
|
|
memcpy(demande.mobile_mac_addr_bytes,
|
|
|
|
couple_ptr->mobile_mac_addr_bytes, 6) ;
|
|
|
|
demande.request_time = couple_ptr->request_time ;
|
2009-05-29 17:02:20 +02:00
|
|
|
demande.nb_couples = 0 ;
|
|
|
|
|
2008-02-14 08:54:51 +01:00
|
|
|
couple_info_ptr = couple_ptr->info ;
|
2009-05-29 17:02:20 +02:00
|
|
|
while (couple_info_ptr != NULL)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2009-05-29 17:02:20 +02:00
|
|
|
demande.nb_couples++;
|
|
|
|
couple_info_ptr = couple_info_ptr->next ;
|
|
|
|
}
|
2010-07-12 16:34:25 +02:00
|
|
|
sendto(sockfd, (void *)&demande, sizeof(request), 0,
|
|
|
|
(struct sockaddr *)&serv, serv_len) ;
|
2009-05-29 17:02:20 +02:00
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// Send couples to the server and empty the list
|
2009-05-29 17:02:20 +02:00
|
|
|
couple_info_ptr = couple_ptr->info ;
|
2010-07-12 16:34:25 +02:00
|
|
|
while (couple_info_ptr != NULL)
|
2009-05-29 17:02:20 +02:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
// Send AP info to the localisation server
|
|
|
|
memcpy(info.ap_mac_addr_bytes,
|
|
|
|
couple_info_ptr->ap_mac_addr_bytes, 6) ;
|
|
|
|
info.antenna_signal_dbm =
|
|
|
|
couple_info_ptr->antenna_signal_dbm - 0x100 ;
|
|
|
|
sendto(sockfd, (void *)&info, sizeof(couple_info),
|
|
|
|
0, (struct sockaddr *)&serv, serv_len) ;
|
|
|
|
|
|
|
|
// Print AP info to the output file
|
|
|
|
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) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
free(ap_mac_string) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// Delete couple
|
2008-02-14 08:54:51 +01:00
|
|
|
couple_info_ptr = couple_info_ptr->next ;
|
|
|
|
free(couple_ptr->info) ;
|
|
|
|
couple_ptr->info = couple_info_ptr ;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fd, "\n") ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// If the couple was treated and keep timeout is reached
|
|
|
|
else if (sub > keep_timeout)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
couple_list *couple_tmp = couple_ptr ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("* Keep timeout reached.") ;
|
2008-03-14 11:31:04 +01:00
|
|
|
#ifdef DEBUG
|
2010-07-12 16:34:25 +02:00
|
|
|
printf(" sub=%lu > keep_timeout=%ld\n",
|
|
|
|
sub, keep_timeout) ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#else // DEBUG
|
2008-03-14 11:31:04 +01:00
|
|
|
putchar('\n') ;
|
2009-04-15 14:15:49 +02:00
|
|
|
#endif // DEBUG
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
couple_ptr = couple_ptr->next ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// If it is the first couple of the list
|
|
|
|
if (couple_prev == NULL)
|
2010-08-06 09:42:22 +02:00
|
|
|
couples = couple_ptr ; // we shift the head
|
2010-07-12 16:34:25 +02:00
|
|
|
else // else we put the next of the previous on the next
|
|
|
|
couple_prev->next = couple_ptr ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
free(couple_tmp) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
continue ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// Next couple
|
2008-02-14 08:54:51 +01:00
|
|
|
couple_prev = couple_ptr ;
|
|
|
|
couple_ptr = couple_ptr->next ;
|
|
|
|
}
|
|
|
|
|
|
|
|
fflush(NULL) ;
|
2010-07-12 16:34:25 +02:00
|
|
|
usleep(cfg_getint(cfg, "check_interval")) ; // Wait to check again
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2010-10-11 09:54:35 +02:00
|
|
|
/* Close output file & socket */
|
2008-02-22 16:04:49 +01:00
|
|
|
if (fclose(fd) != 0)
|
2010-07-12 16:34:25 +02:00
|
|
|
perror("Error closing output file") ;
|
2010-10-11 09:54:35 +02:00
|
|
|
(void) close(sockfd) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
return NULL ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/*
|
|
|
|
* Treats a received packet.
|
|
|
|
*/
|
2010-08-06 09:42:22 +02:00
|
|
|
void got_couple_info(couple_message message)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
couple_list *tmp_couple = NULL ;
|
|
|
|
couple_info_list *tmp_info = NULL ;
|
2010-07-12 16:34:25 +02:00
|
|
|
struct timeval start_time ; // Reception time on the aggregator
|
2008-03-14 11:31:04 +01:00
|
|
|
|
|
|
|
gettimeofday(&start_time, NULL) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/* Create a new couple */
|
2008-02-14 08:54:51 +01:00
|
|
|
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 ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
/* Add it in the list */
|
2010-08-06 09:42:22 +02:00
|
|
|
tmp_couple = couples ;
|
|
|
|
if (couples == NULL) // If the couple list does not exist,
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("Creating couple list.\n") ;
|
|
|
|
tmp_couple = malloc(sizeof(couple_list)) ; // create it.
|
|
|
|
memcpy(tmp_couple->mobile_mac_addr_bytes,
|
|
|
|
message.mobile_mac_addr_bytes, 6) ;
|
|
|
|
if (timeval_to_ms(message.request_time) != 0) // Explicit packet
|
|
|
|
// Transmission time on the mobile:
|
|
|
|
tmp_couple->request_time = message.request_time ;
|
|
|
|
else // Implicit packet
|
|
|
|
// Reception time on the AP:
|
|
|
|
tmp_couple->request_time = message.start_time ;
|
|
|
|
// Save locale time on the aggregator (not the reception time
|
|
|
|
// on the AP):
|
|
|
|
tmp_couple->start_time = start_time ;
|
2008-02-14 08:54:51 +01:00
|
|
|
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 ;
|
2010-08-06 09:42:22 +02:00
|
|
|
couples = tmp_couple ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
2010-07-12 16:34:25 +02:00
|
|
|
|
|
|
|
else // If the couple list exists already
|
|
|
|
{ // we search the list for the couple
|
|
|
|
if (timeval_to_ms(message.request_time) != 0) // Explicit packet
|
2009-09-03 11:09:48 +02:00
|
|
|
{
|
|
|
|
while (tmp_couple != NULL)
|
2010-07-12 16:34:25 +02:00
|
|
|
{ // Research criterion: MAC and transmission time
|
|
|
|
if(mac_cmp(message.mobile_mac_addr_bytes,
|
|
|
|
tmp_couple->mobile_mac_addr_bytes) == 1
|
|
|
|
&& sub_date(message.request_time,
|
|
|
|
tmp_couple->request_time) == 0)
|
|
|
|
break ; // If the couple exists, we stop on it
|
2009-09-03 11:09:48 +02:00
|
|
|
tmp_couple = tmp_couple->next ;
|
|
|
|
}
|
|
|
|
}
|
2010-07-12 16:34:25 +02:00
|
|
|
else // Implicit packet
|
2009-09-03 11:09:48 +02:00
|
|
|
{
|
|
|
|
while (tmp_couple != NULL)
|
2010-07-12 16:34:25 +02:00
|
|
|
{ // Research criterion: MAC addresses equals and reception
|
|
|
|
// times on the APs less than 10 ms
|
|
|
|
// TODO : define an option for the maximal difference time.
|
|
|
|
if(mac_cmp(message.mobile_mac_addr_bytes,
|
|
|
|
tmp_couple->mobile_mac_addr_bytes) == 1
|
|
|
|
&& sub_date(message.start_time,
|
|
|
|
tmp_couple->request_time) <= 10)
|
|
|
|
break ; // If the couple exists, we stop on it
|
2009-09-03 11:09:48 +02:00
|
|
|
tmp_couple = tmp_couple->next ;
|
|
|
|
}
|
|
|
|
}
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
if (tmp_couple == NULL) // If the couple does not exist in the list,
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("Create new couple.\n") ;
|
|
|
|
tmp_couple = malloc(sizeof(couple_list)) ; // create it.
|
|
|
|
memcpy(tmp_couple->mobile_mac_addr_bytes,
|
|
|
|
message.mobile_mac_addr_bytes, 6) ;
|
|
|
|
if (timeval_to_ms(message.request_time) != 0) // Explicit packet
|
|
|
|
// Transmission time on the mobile:
|
|
|
|
tmp_couple->request_time = message.request_time ;
|
|
|
|
else // Implicit packet
|
|
|
|
// Reception time on the AP:
|
|
|
|
tmp_couple->request_time = message.start_time ;
|
|
|
|
// Save locale time on the aggregator (not the reception time
|
|
|
|
// on the AP):
|
|
|
|
tmp_couple->start_time = start_time ;
|
2008-02-14 08:54:51 +01:00
|
|
|
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 ;
|
2010-08-06 09:42:22 +02:00
|
|
|
tmp_couple->next = couples ;
|
2008-02-14 08:54:51 +01:00
|
|
|
tmp_couple->info = tmp_info ;
|
2010-08-06 09:42:22 +02:00
|
|
|
couples = tmp_couple ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
2010-07-12 16:34:25 +02:00
|
|
|
else // If the couple was found in the list
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
if (tmp_couple->info == NULL)
|
|
|
|
{ // We already sent to the server data for this couple
|
|
|
|
printf("Request already treated.\n") ;
|
2008-02-14 08:54:51 +01:00
|
|
|
free(tmp_info) ;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("Add information to the couple.\n") ;
|
|
|
|
tmp_info->next = tmp_couple->info ; // Add data
|
2008-02-14 08:54:51 +01:00
|
|
|
tmp_couple->info = tmp_info ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Empties the couple list.
|
|
|
|
*/
|
2010-08-06 09:42:22 +02:00
|
|
|
void free_couple_list()
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-08-06 12:30:17 +02:00
|
|
|
couple_list *next_couple ;
|
|
|
|
couple_info_list *next_couple_info ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2010-08-06 12:30:17 +02:00
|
|
|
while (couples != NULL)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-08-06 12:30:17 +02:00
|
|
|
while (couples->info != NULL)
|
|
|
|
{
|
|
|
|
next_couple_info = couples->info->next ;
|
|
|
|
free(couples->info) ;
|
|
|
|
couples->info = next_couple_info ;
|
|
|
|
}
|
|
|
|
next_couple = couples->next ;
|
|
|
|
free(couples) ;
|
|
|
|
couples = next_couple ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-10-11 09:54:35 +02:00
|
|
|
/*
|
|
|
|
* Thread function. Listens for hello messages from APs.
|
|
|
|
*/
|
|
|
|
void listen_for_aps(void)
|
|
|
|
{
|
|
|
|
int listen_sockfd ;
|
|
|
|
int nread ; // recvfrom return value
|
|
|
|
struct sockaddr_in client; // UDP client structure
|
|
|
|
socklen_t client_len = sizeof(client) ; // Size of clients
|
|
|
|
autocalibration_hello message ;
|
|
|
|
|
2010-10-25 16:36:55 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Autocalibration Hello thread launched.\n") ;
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2010-10-11 09:54:35 +02:00
|
|
|
listen_sockfd =
|
|
|
|
create_udp_listening_socket(cfg_getint(cfg,
|
|
|
|
"autocalibration_port")) ;
|
|
|
|
if (listen_sockfd < 0)
|
|
|
|
{
|
|
|
|
perror("Error! Cannot create UDP listening socket from the"
|
|
|
|
" listeners") ;
|
|
|
|
exit(ERR_CREATING_SOCKET) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (run)
|
|
|
|
{
|
|
|
|
nread = recvfrom(listen_sockfd, &message, sizeof(message), 0,
|
|
|
|
(struct sockaddr *) &client, &client_len) ;
|
|
|
|
|
|
|
|
if (nread <= 0 && run)
|
|
|
|
{
|
|
|
|
if (run)
|
|
|
|
fprintf(stderr, "No message received from aggregator!\n") ;
|
|
|
|
continue ;
|
|
|
|
}
|
2010-10-25 17:03:16 +02:00
|
|
|
|
2010-10-25 16:36:55 +02:00
|
|
|
#ifdef DEBUG
|
2010-10-25 17:03:16 +02:00
|
|
|
fprintf(stderr, "Got a Hello message.\n") ;
|
2010-10-25 16:36:55 +02:00
|
|
|
#endif // DEBUG
|
2010-10-11 09:54:35 +02:00
|
|
|
|
2010-10-14 12:05:11 +02:00
|
|
|
update_ap(message.ap_mac_addr_bytes, message.ap_ip_addr) ;
|
2010-10-11 09:54:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
(void) close(listen_sockfd) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-08-06 12:29:39 +02:00
|
|
|
/*
|
|
|
|
* Updates the timestamp of the AP with the given MAC address if it is in
|
|
|
|
* the AP list, or add a new AP with this MAC address to the AP list.
|
|
|
|
*/
|
2010-10-14 12:05:11 +02:00
|
|
|
void update_ap(unsigned char mac_addr_bytes[6], char ip_addr[16])
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
|
|
|
ap_list *found ;
|
|
|
|
|
2010-10-12 15:09:14 +02:00
|
|
|
if ((found = find_ap(mac_addr_bytes)) == NULL)
|
2010-10-14 12:05:11 +02:00
|
|
|
{
|
|
|
|
ap_list *new_ap = add_ap_front(mac_addr_bytes) ;
|
|
|
|
update_ap_ip_addr(new_ap, ip_addr) ;
|
|
|
|
}
|
2010-08-06 12:29:39 +02:00
|
|
|
|
|
|
|
else
|
|
|
|
update_ap_seen(found) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Searches the AP list for an AP with the given MAC address and returns
|
|
|
|
* it.
|
|
|
|
*/
|
2010-10-12 15:09:14 +02:00
|
|
|
ap_list* find_ap(unsigned char mac_addr_bytes[6])
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
2010-10-26 14:53:24 +02:00
|
|
|
ap_list *found ;
|
|
|
|
|
|
|
|
if (token_aps == NULL)
|
|
|
|
return NULL ;
|
2010-08-06 12:29:39 +02:00
|
|
|
|
2010-10-26 14:53:24 +02:00
|
|
|
found = token_aps ;
|
|
|
|
do
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
2010-10-12 15:09:14 +02:00
|
|
|
if (mac_cmp(found->mac_addr_bytes, mac_addr_bytes))
|
2010-08-06 12:29:39 +02:00
|
|
|
return found ;
|
|
|
|
found = found->next ;
|
|
|
|
}
|
2010-10-26 14:53:24 +02:00
|
|
|
while (found != token_aps) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
|
|
|
|
return NULL ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Adds a new AP in front of the AP list.
|
|
|
|
*/
|
2010-10-25 15:04:57 +02:00
|
|
|
ap_list* add_ap_front(unsigned char mac_addr_bytes[6])
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
|
|
|
ap_list *ap = malloc(sizeof(ap_list)) ;
|
2010-10-12 15:09:14 +02:00
|
|
|
memcpy(ap->mac_addr_bytes, mac_addr_bytes, 6) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
update_ap_seen(ap) ;
|
|
|
|
push_ap(ap) ;
|
|
|
|
++nb_aps ;
|
2010-10-14 12:05:11 +02:00
|
|
|
return ap ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Change the IP address of the AP 'ap' with 'ip_addr'.
|
|
|
|
*/
|
2010-10-25 15:04:57 +02:00
|
|
|
void update_ap_ip_addr(ap_list *ap, char ip_addr[16])
|
2010-10-14 12:05:11 +02:00
|
|
|
{
|
|
|
|
strncpy(ap->ip_addr, ip_addr, 16) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Updates the timestamp of the given AP.
|
|
|
|
*/
|
2010-10-25 15:04:57 +02:00
|
|
|
void update_ap_seen(ap_list *ap)
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
|
|
|
assert(ap) ;
|
|
|
|
gettimeofday(&ap->last_seen, NULL) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Puts an existing AP in front of the AP list. The AP must not be in
|
|
|
|
* the list yet.
|
|
|
|
*/
|
2010-10-25 15:04:57 +02:00
|
|
|
void push_ap(ap_list *ap)
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
|
|
|
assert(ap) ;
|
2010-10-26 14:53:24 +02:00
|
|
|
|
|
|
|
if (token_aps == NULL) // List does not exist yet
|
|
|
|
{
|
|
|
|
token_aps = ap ;
|
|
|
|
ap->next = ap ;
|
|
|
|
ap->previous = ap ;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
ap->previous = token_aps->previous ;
|
|
|
|
ap->previous->next = ap ;
|
|
|
|
ap->next = token_aps ;
|
|
|
|
token_aps->previous = ap ;
|
|
|
|
token_aps = ap ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Monitors the AP list: sends orders to APs following their order in
|
|
|
|
* the list, and deletes old APs.
|
|
|
|
*/
|
|
|
|
void monitor_aps()
|
|
|
|
{
|
2010-10-26 10:24:29 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Monitor AP thread launched.\n") ;
|
|
|
|
#endif // DEBUG
|
|
|
|
|
2010-08-06 12:29:39 +02:00
|
|
|
while (run)
|
|
|
|
{
|
|
|
|
delete_old_aps() ;
|
|
|
|
|
|
|
|
if (nb_aps > 1)
|
2010-10-26 14:53:24 +02:00
|
|
|
{
|
|
|
|
order_send(token_aps) ;
|
|
|
|
token_aps = token_aps->next ;
|
|
|
|
}
|
2010-08-06 12:29:39 +02:00
|
|
|
|
2010-10-14 18:30:41 +02:00
|
|
|
usleep(cfg_getint(cfg, "ap_check_interval") * 1000) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deletes APs that did not send any Hello packet for a while, following
|
|
|
|
* the list order. Stops on the first not-to-be-deleted AP.
|
|
|
|
*/
|
|
|
|
void delete_old_aps()
|
|
|
|
{
|
|
|
|
struct timeval now ;
|
2010-10-26 14:53:24 +02:00
|
|
|
|
|
|
|
if (token_aps == NULL)
|
|
|
|
return ;
|
|
|
|
|
2010-08-06 12:29:39 +02:00
|
|
|
gettimeofday(&now, NULL) ;
|
|
|
|
|
2010-10-26 14:53:24 +02:00
|
|
|
while (token_aps != token_aps->next)
|
|
|
|
if (sub_date(token_aps->last_seen, now) >
|
2010-10-14 18:30:41 +02:00
|
|
|
(unsigned long) cfg_getint(cfg, "ap_keep_timeout") * 1000)
|
2010-10-26 14:53:24 +02:00
|
|
|
delete_ap(token_aps) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
else
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Deletes the given AP from the AP list.
|
|
|
|
*/
|
2010-10-25 15:04:57 +02:00
|
|
|
void delete_ap(ap_list *ap)
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
|
|
|
unlink_ap(ap) ;
|
|
|
|
free(ap) ;
|
|
|
|
--nb_aps ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Extracts the given AP from the AP list (it will not be linked to any
|
|
|
|
* other element of the list).
|
|
|
|
*/
|
2010-08-06 12:29:39 +02:00
|
|
|
void unlink_ap(ap_list *ap)
|
|
|
|
{
|
|
|
|
assert(ap) ;
|
|
|
|
ap_list
|
|
|
|
*ap_previous = ap->previous,
|
|
|
|
*ap_next = ap->next ;
|
|
|
|
|
2010-10-26 14:53:24 +02:00
|
|
|
assert(ap_previous) ;
|
|
|
|
assert(ap_next) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
|
2010-10-26 14:53:24 +02:00
|
|
|
ap_previous->next = ap_next ;
|
|
|
|
ap_next->previous = ap_previous ;
|
2010-08-06 12:29:39 +02:00
|
|
|
|
2010-10-26 14:53:24 +02:00
|
|
|
if (ap == token_aps)
|
|
|
|
token_aps = ap_next ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 18:30:41 +02:00
|
|
|
/*
|
|
|
|
* Sends a send order to the given AP.
|
|
|
|
*/
|
2010-08-06 12:29:39 +02:00
|
|
|
void order_send(ap_list *ap)
|
|
|
|
{
|
2010-10-14 18:30:41 +02:00
|
|
|
autocalibration_order message ;
|
|
|
|
struct sockaddr_in serv;
|
|
|
|
struct sockaddr_in client ;
|
|
|
|
socklen_t serv_len = sizeof(serv);
|
2010-10-25 17:03:16 +02:00
|
|
|
int sockfd ;
|
|
|
|
ssize_t nsent ;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
fprintf(stderr, "Sending an order to %s...\n", ap->ip_addr) ;
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
sockfd =
|
2010-10-14 18:30:41 +02:00
|
|
|
create_udp_sending_socket(ap->ip_addr,
|
|
|
|
cfg_getint(cfg, "autocalibration_port"),
|
|
|
|
&serv, &client) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
|
2010-10-26 10:36:23 +02:00
|
|
|
message.order = htonl(AUTOCALIBRATION_ORDER_SEND) ;
|
2010-10-25 17:03:16 +02:00
|
|
|
nsent = sendto(sockfd, (void *)&message, sizeof(message), 0,
|
|
|
|
(struct sockaddr *)&serv, serv_len) ;
|
|
|
|
if (nsent != (ssize_t) sizeof(message))
|
|
|
|
{
|
|
|
|
perror("Error sending order to the listener") ;
|
|
|
|
exit(ERR_SENDING_INFO) ;
|
|
|
|
}
|
2010-10-14 18:30:41 +02:00
|
|
|
|
|
|
|
(void) close(sockfd) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Empties the AP list.
|
|
|
|
*/
|
2010-08-06 12:29:39 +02:00
|
|
|
void free_ap_list()
|
|
|
|
{
|
2010-10-26 14:53:24 +02:00
|
|
|
ap_list *ap_ptr ;
|
|
|
|
|
|
|
|
if (token_aps == NULL)
|
|
|
|
return ;
|
2010-08-06 12:29:39 +02:00
|
|
|
|
2010-10-26 14:53:24 +02:00
|
|
|
ap_ptr = token_aps->next ;
|
|
|
|
assert(ap_ptr) ;
|
|
|
|
|
|
|
|
while (ap_ptr != token_aps)
|
2010-08-06 12:29:39 +02:00
|
|
|
{
|
2010-10-26 14:53:24 +02:00
|
|
|
ap_list *ap_tmp = ap_ptr ;
|
2010-08-06 12:29:39 +02:00
|
|
|
ap_ptr = ap_ptr->next ;
|
2010-10-26 14:53:24 +02:00
|
|
|
free(ap_tmp) ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
2010-10-26 14:53:24 +02:00
|
|
|
|
|
|
|
free(token_aps) ;
|
|
|
|
token_aps = NULL ;
|
2010-08-06 12:29:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-09-03 11:09:48 +02:00
|
|
|
#ifdef DEBUG
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Prints the couple list.
|
|
|
|
*/
|
2010-08-06 09:42:22 +02:00
|
|
|
void print_couple_list()
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
couple_list *couple_ptr = couples ;
|
|
|
|
couple_info_list *info_ptr = NULL ;
|
|
|
|
char *mobile_mac_string ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
if (couples == NULL) // Empty list
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("Aucun couple.\n") ;
|
2008-02-14 08:54:51 +01:00
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (couple_ptr != NULL)
|
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
info_ptr = couple_ptr->info ; // Get the sub-list pointer
|
|
|
|
|
|
|
|
mobile_mac_string =
|
|
|
|
mac_bytes_to_string(couple_ptr->mobile_mac_addr_bytes) ;
|
|
|
|
printf("Mobile MAC: %s\n"
|
|
|
|
"Sequence number: %llu\n"
|
|
|
|
"Reception timestamp: %llu\n"
|
|
|
|
"\n",
|
2008-02-14 08:54:51 +01:00
|
|
|
mobile_mac_string,
|
2008-10-10 15:00:34 +02:00
|
|
|
timeval_to_ms(couple_ptr->request_time),
|
2009-02-17 14:47:07 +01:00
|
|
|
timeval_to_ms(couple_ptr->start_time)
|
2008-02-14 08:54:51 +01:00
|
|
|
) ;
|
|
|
|
free(mobile_mac_string) ;
|
|
|
|
|
2010-07-12 16:34:25 +02:00
|
|
|
// Parse information relative to the current couple
|
|
|
|
while (info_ptr != NULL)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
print_couple_info(info_ptr) ;
|
|
|
|
putchar('\n') ;
|
|
|
|
info_ptr = info_ptr->next ;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n\n") ;
|
|
|
|
|
|
|
|
couple_ptr = couple_ptr->next ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-10-14 16:19:29 +02:00
|
|
|
/*
|
|
|
|
* Prints an element of a couple_info_list.
|
|
|
|
*/
|
2008-02-14 08:54:51 +01:00
|
|
|
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) ;
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("\tAP MAC: %s\n"
|
|
|
|
"\tSignal strength: %d dBm\n",
|
2008-02-14 08:54:51 +01:00
|
|
|
ap_mac_string,
|
|
|
|
info->antenna_signal_dbm - 0x100
|
|
|
|
) ;
|
|
|
|
free(ap_mac_string) ;
|
|
|
|
}
|
2009-09-03 11:09:48 +02:00
|
|
|
#endif // DEBUG
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2010-07-12 12:50:02 +02:00
|
|
|
char* ip_bytes_to_string(unsigned char *ip_binary)
|
|
|
|
{
|
|
|
|
int
|
2010-10-12 15:09:14 +02:00
|
|
|
size = 16,
|
2010-07-12 12:50:02 +02:00
|
|
|
i = 0 ;
|
|
|
|
|
|
|
|
for (i = 0 ; i < 4 ; ++i)
|
|
|
|
{
|
|
|
|
if (ip_binary[i] < 0x64)
|
2010-10-12 15:09:14 +02:00
|
|
|
size-- ;
|
2010-07-12 12:50:02 +02:00
|
|
|
if (ip_binary[i] < 0x10)
|
2010-10-12 15:09:14 +02:00
|
|
|
size-- ;
|
2010-07-12 12:50:02 +02:00
|
|
|
}
|
|
|
|
|
2010-10-12 15:09:14 +02:00
|
|
|
char *ret = malloc(sizeof(char) * size) ;
|
2010-07-12 12:50:02 +02:00
|
|
|
|
2010-10-12 15:09:14 +02:00
|
|
|
sprintf(ret, "%d.%d.%d.%d",
|
|
|
|
ip_binary[0], ip_binary[1],
|
|
|
|
ip_binary[2], ip_binary[3]) ;
|
|
|
|
ret[size-1] = '\0' ;
|
2010-07-12 12:50:02 +02:00
|
|
|
|
|
|
|
return ret ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void print_usage()
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2010-07-12 16:34:25 +02:00
|
|
|
printf("Usage:\n"
|
|
|
|
"\t%s [-f config_file] [-l listening_port] [-i positionner_ip]"
|
2010-10-11 09:54:35 +02:00
|
|
|
" [-p positioner_port] [-t aggregate_timeout] [-k keep_timeout]"
|
|
|
|
" [-c check_interval] [-o output_file] [-A]"
|
2010-10-25 17:03:16 +02:00
|
|
|
" [-a autocalibration_port] [-K ap_keep_timeout]"
|
|
|
|
" [-C ap_check_interval]\n"
|
2010-07-12 16:34:25 +02:00
|
|
|
|
|
|
|
"Main options:\n"
|
2010-07-12 16:57:32 +02:00
|
|
|
"\t-h\t\tPrint this help.\n"
|
2010-07-12 16:34:25 +02:00
|
|
|
"\t-f config_file\tUse 'config_file' instead of the default"
|
|
|
|
" configuration file.\n"
|
|
|
|
|
|
|
|
"Server options:\n"
|
|
|
|
"\t-l listening_port\tOnly requests sent on this port will be"
|
|
|
|
" treated (default: %d).\n"
|
|
|
|
"\t-i positionner_ip\tIP address of the localisation server"
|
|
|
|
" (default: %s).\n"
|
|
|
|
"\t-p positioner_port\tAggregated requests are transmitted to"
|
|
|
|
" the localisation server on this port (default: %d).\n"
|
|
|
|
|
|
|
|
"Aggregation options:\n"
|
2010-10-11 09:54:35 +02:00
|
|
|
"\t-t aggregate_timeout\tRequests are stored during"
|
2010-10-14 18:30:41 +02:00
|
|
|
" 'aggregate_timeout' milliseconds before to be grouped"
|
|
|
|
" (default: %d ms).\n"
|
2010-07-12 16:34:25 +02:00
|
|
|
"\t-k keep_timeout\t\tAggregated requests are kept during"
|
2010-10-25 17:03:16 +02:00
|
|
|
" 'keep_timeout' milliseconds (default: %d ms).\n"
|
2010-07-12 16:34:25 +02:00
|
|
|
"\t-c check_interval\tTime between two checks of the stored"
|
|
|
|
" requests (default\t%d microseconds).\n"
|
2010-10-11 09:54:35 +02:00
|
|
|
|
|
|
|
"Autocalibration options:\n"
|
|
|
|
"\t-A\tEnable autocalibration (default: disabled).\n"
|
|
|
|
"\t-a port\tPort on which autocalibration data"
|
|
|
|
" are exchanged with the listeners (default: %d).\n"
|
2010-10-14 18:30:41 +02:00
|
|
|
"\t-K ap_keep_timeout\tInactive APs are kept during"
|
|
|
|
" 'ap_keep_timeout' seconds (default: %d s).\n"
|
|
|
|
"\t-C ap_check_interval\tTime (in milliseconds) between two"
|
|
|
|
" checks of the stored APs (default: %d ms).\n"
|
2010-07-12 16:34:25 +02:00
|
|
|
,
|
2010-07-12 12:50:02 +02:00
|
|
|
program_name,
|
2009-07-02 13:12:51 +02:00
|
|
|
AGGREGATE_DEFAULT_PORT,
|
|
|
|
POSITIONER_DEFAULT_IP,
|
|
|
|
POSITIONER_DEFAULT_PORT,
|
|
|
|
DEFAULT_AGGREGATE_TIMEOUT,
|
|
|
|
DEFAULT_KEEP_TIMEOUT,
|
2010-10-11 09:54:35 +02:00
|
|
|
DEFAULT_CHECK_INTERVAL,
|
2010-10-14 18:30:41 +02:00
|
|
|
DEFAULT_AUTOCALIBRATION_PORT,
|
|
|
|
DEFAULT_AP_KEEP_TIMEOUT,
|
|
|
|
DEFAULT_AP_CHECK_INTERVAL
|
2009-07-02 13:12:51 +02:00
|
|
|
) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|