diff --git a/TODO b/TODO index 270e4ca..970004d 100644 --- a/TODO +++ b/TODO @@ -4,8 +4,11 @@ - Use string for network exchanges? - Mark arguments as const in function headers if needed That is done in the owlps-positioning C++ code, but not constantly - in C modules. -- Allow to use hostnames instead of IP addresses. + in C modules. [Done in libowlps & libowlps-client.] +- Allow to use hostnames instead of IP addresses in all modules + getaddrinfo(3) (or gethostbyname(3)) should be used when opening + sockets in libowlps, then string buffer size have to be adapted in + all modules to be able to contain a long hostname. - Use struct ether_addr to store MAC addresses? We could use the struct ether_addr to store binary MAC addresses, and convert them to strings with ether_ntoa() instead of @@ -14,14 +17,18 @@ * libowlps -- Delete timestamp_is_null()? - This function is currently not used. +- Currently unused functions: + ° owl_timestamp_is_null() + ° owl_iface_channel_hop() + ° owl_iface_set_channel() (except by owl_iface_channel_hop()) +- Move owl_iface_mode_monitor() in owlps-listenerd.c. * Aggregator - inet_ntoa() is not secure with threads - Use inet_ntop() instead? + (But it is currently used by only one thread.) Use inet_ntop() + instead? - Use locks to read/write the AP list Currently, several threads can access the list simultaneously, and that's not cool! @@ -34,17 +41,14 @@ request. We should define an option to allow user to choose the time he wants. - Allow blank parameters for output options. -- Fix segfault on SIGINT. * Listener -- Send coordinates in autocalibration requests - The listener should be able to know its own position and transmit - it in autocalibration requests. +- Refactor and review read_packet(). +- Listen for autocalibration requests without sending requests? - read_packet(): use ieee80211_header_size for all implicit packets Currently the size is corrected only for data packets. -- Fix segfault when rtap_iface is not in monitor mode (?) on Foneras. - Move endianess #defines in libowlps? - Merge Makefile and Makefile_atheros? Use autohell? @@ -55,7 +59,7 @@ * Client -- Allow to use a string for the direction +- Allow to use a string for the direction? Could be nice, but probably useless. diff --git a/libowlps-client/libowlps-client.c b/libowlps-client/libowlps-client.c index 0c4f19b..dd043f4 100644 --- a/libowlps-client/libowlps-client.c +++ b/libowlps-client/libowlps-client.c @@ -16,9 +16,10 @@ * 'iface' if specified (if you want the interface to be selected, * automatically, this parameter should be NULL or an empty string). */ -int owlclient_create_trx_socket(char *dest_ip, uint_fast16_t dest_port, - struct sockaddr_in *server, - char *iface) +int owlclient_create_trx_socket(const char *const dest_ip, + const uint_fast16_t dest_port, + struct sockaddr_in *const server, + const char *const iface) { struct sockaddr_in client ; @@ -41,7 +42,7 @@ int owlclient_create_trx_socket(char *dest_ip, uint_fast16_t dest_port, /* Selects 'iface' as sending interface for the socket 'sockfd'. */ -void owlclient_use_iface(int sockfd, char *iface) +void owlclient_use_iface(const int sockfd, const char *const iface) { if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, iface, strlen(iface) + 1) == -1) @@ -55,12 +56,18 @@ void owlclient_use_iface(int sockfd, char *iface) -void owlclient_send_request(int sockfd, struct sockaddr_in *server, - void *packet, uint_fast16_t packet_size, - uint_fast16_t nb_pkt, uint_fast32_t delay) +void owlclient_send_request(const int sockfd, + const struct sockaddr_in *const server, + const void *const packet, + const uint_fast16_t packet_size, + const uint_fast16_t nb_pkt, + const uint_fast32_t delay) { uint_fast16_t i ; + if (nb_pkt == 0) + return ; + #ifdef DEBUG printf("Sent packets: ") ; #endif // DEBUG @@ -82,8 +89,10 @@ void owlclient_send_request(int sockfd, struct sockaddr_in *server, -void owlclient_send_packet(int sockfd, struct sockaddr_in *server, - void *packet, uint_fast16_t packet_size) +void owlclient_send_packet(const int sockfd, + const struct sockaddr_in *const server, + const void *const packet, + const uint_fast16_t packet_size) { ssize_t nsent = sendto(sockfd, packet, packet_size, 0, (struct sockaddr *) server, diff --git a/libowlps-client/owlps-client.h b/libowlps-client/owlps-client.h index 1cc6c20..b005d78 100644 --- a/libowlps-client/owlps-client.h +++ b/libowlps-client/owlps-client.h @@ -14,15 +14,21 @@ /* Function headers */ -int owlclient_create_trx_socket(char *dest_ip, uint_fast16_t dest_port, - struct sockaddr_in *server, - char *iface) ; -void owlclient_use_iface(int sockfd, char *iface) ; -void owlclient_send_request(int sockfd, struct sockaddr_in *server, - void *packet, uint_fast16_t packet_size, - uint_fast16_t nb_pkt, uint_fast32_t delay) ; -void owlclient_send_packet(int sockfd, struct sockaddr_in *server, - void *packet, uint_fast16_t packet_size) ; +int owlclient_create_trx_socket(const char *const dest_ip, + const uint_fast16_t dest_port, + struct sockaddr_in *const server, + const char *const iface) ; +void owlclient_use_iface(const int sockfd, const char *const iface) ; +void owlclient_send_request(const int sockfd, + const struct sockaddr_in *const server, + const void *const packet, + const uint_fast16_t packet_size, + const uint_fast16_t nb_pkt, + const uint_fast32_t delay) ; +void owlclient_send_packet(const int sockfd, + const struct sockaddr_in *const server, + const void *const packet, + const uint_fast16_t packet_size) ; #endif // _LIBOWLPS_CLIENT_ diff --git a/libowlps/libowlps.c b/libowlps/libowlps.c index df88676..c11aea9 100644 --- a/libowlps/libowlps.c +++ b/libowlps/libowlps.c @@ -17,6 +17,8 @@ #include #include +#include + #define DEBUG @@ -24,13 +26,16 @@ owl_bool owl_run = TRUE ; +/* *** Miscellaneous functions *** */ + + /* * Converts a MAC address from bytes to string. * The string is allocated in a static buffer, and will be overwritten * each time this function is called. * This function is not thread-safe! */ -const char* owl_mac_bytes_to_string(uint8_t *mac_binary) +const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary) { static char mac_str[OWL_ETHER_ADDR_STRLEN] ; owl_mac_bytes_to_string_r(mac_binary, mac_str) ; @@ -38,13 +43,12 @@ const char* owl_mac_bytes_to_string(uint8_t *mac_binary) } - /* * Converts a MAC address from bytes to string. * 'mac_str' must be allocated by the caller. * This function is thread-safe. */ -void owl_mac_bytes_to_string_r(uint8_t *mac_binary, +void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary, char mac_str[OWL_ETHER_ADDR_STRLEN]) { sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", @@ -53,12 +57,26 @@ void owl_mac_bytes_to_string_r(uint8_t *mac_binary, } +/* + * Compares two MAC addresses. + * Returns TRUE if they are identical, FALSE otherwise. + */ +owl_bool owl_mac_equals(const uint8_t *const mac1, + const uint8_t *const mac2) +{ + int i ; + for (i = 0 ; i < ETHER_ADDR_LEN ; ++i) + if(mac1[i] != mac2[i]) + return FALSE ; + return TRUE ; +} + /* * Converts a IEEE 802.11 frequency into a channel number. * Returns 0 if the frequency does not correspond to an official channel. */ -uint_fast8_t owl_frequency_to_channel(uint_fast16_t channel) +uint_fast8_t owl_frequency_to_channel(const uint_fast16_t channel) { uint_fast8_t c = 0 ; // Result @@ -113,11 +131,14 @@ uint_fast8_t owl_frequency_to_channel(uint_fast16_t channel) +/* *** Time *** */ + + /* * Sets the owl_timestamp 'now' at the current time. * Returns 0 in case of success non-zero otherwise. */ -int owl_timestamp_now(owl_timestamp *now) +int owl_timestamp_now(owl_timestamp *const now) { int ret ; struct timespec now_ts ; @@ -133,7 +154,6 @@ int owl_timestamp_now(owl_timestamp *now) } - /* * Returns a owl_timestamp from a struct timespec. */ @@ -146,7 +166,6 @@ owl_timestamp owl_timespec_to_timestamp(const struct timespec d) } - /* * Returns a owl_timestamp from a struct timeval. */ @@ -159,44 +178,40 @@ owl_timestamp owl_timeval_to_timestamp(const struct timeval d) } - -owl_bool owl_timestamp_equals(owl_timestamp d1, owl_timestamp d2) +owl_bool owl_timestamp_equals(const owl_timestamp d1, + const owl_timestamp d2) { return d1.tv_sec == d2.tv_sec && d1.tv_nsec == d2.tv_nsec ; } - -owl_bool owl_timestamp_is_null(owl_timestamp d) +owl_bool owl_timestamp_is_null(const owl_timestamp d) { return d.tv_sec == 0 && d.tv_nsec == 0 ; } - /* * Converts a owl_timestamp date value into milliseconds. */ -uint64_t owl_timestamp_to_ms(owl_timestamp d) +uint64_t owl_timestamp_to_ms(const owl_timestamp d) { return (uint64_t) d.tv_sec * 1000u + (uint64_t) d.tv_nsec / 1000000lu ; } - /* * Converts a owl_timestamp date value into a printable string. * 'dst' must be an allocated array of at least owl_timestamp_STR_LEN * characters. */ -void owl_timestamp_to_string(char *dst, owl_timestamp src) +void owl_timestamp_to_string(char *const dst, const owl_timestamp src) { snprintf(dst, OWL_TIMESTAMP_STR_LEN, "%"PRIu32".%"PRIu32, src.tv_sec, src.tv_nsec) ; } - /* * Returns the time (in milliseconds) between two dates. */ @@ -207,7 +222,6 @@ uint_fast32_t owl_time_elapsed_ms(const owl_timestamp d1, } - /* * Returns a owl_timestamp storing the time between two dates. */ @@ -226,47 +240,60 @@ owl_timestamp owl_time_elapsed(const owl_timestamp d1, +/* *** Endianess *** */ + + /* * Converts a owl_timestamp from host endianess to network endianess. */ -owl_timestamp owl_hton_timestamp(owl_timestamp date) +owl_timestamp owl_hton_timestamp(const owl_timestamp d) { - owl_timestamp d ; - d.tv_sec = htonl(date.tv_sec) ; - d.tv_nsec = htonl(date.tv_nsec) ; - return d ; + owl_timestamp date ; + date.tv_sec = htonl(d.tv_sec) ; + date.tv_nsec = htonl(d.tv_nsec) ; + return date ; } - /* * Converts a owl_timestamp from network endianess to host endianess. */ -owl_timestamp owl_ntoh_timestamp(owl_timestamp date) +owl_timestamp owl_ntoh_timestamp(const owl_timestamp d) { - owl_timestamp d ; - d.tv_sec = ntohl(date.tv_sec) ; - d.tv_nsec = ntohl(date.tv_nsec) ; - return d ; + owl_timestamp date ; + date.tv_sec = ntohl(d.tv_sec) ; + date.tv_nsec = ntohl(d.tv_nsec) ; + return date ; } - /* - * Compares two MAC addresses. - * Returns TRUE if they are identical, FALSE otherwise. + * Swap bytes composing a float. + * You probably want to use the macros owl_htonf() and owl_ntohf() + * instead of this function. */ -owl_bool owl_mac_equals(uint8_t *mac1, uint8_t *mac2) +float owl_swap_float(const float f) { - int i ; - for (i = 0 ; i < ETHER_ADDR_LEN ; ++i) - if(mac1[i] != mac2[i]) - return FALSE ; - return TRUE ; + float ret ; + char + *f_bytes = (char*) &f, + *ret_bytes = (char*) &ret ; + + assert(sizeof(float) == 4) ; + + ret_bytes[0] = f_bytes[3] ; + ret_bytes[1] = f_bytes[2] ; + ret_bytes[2] = f_bytes[1] ; + ret_bytes[3] = f_bytes[0] ; + + return ret ; } +/* *** Network *** */ + + /* * Creates a UDP transmission socket and returns its descriptor. * Parameters: @@ -277,14 +304,14 @@ owl_bool owl_mac_equals(uint8_t *mac1, uint8_t *mac2) * - client_description (in/out): the structure in which the client * description will be saved. */ -int owl_create_udp_trx_socket(char *server_address, - uint_fast16_t server_port, - struct sockaddr_in *server_description, - struct sockaddr_in *client_description) +int owl_create_udp_trx_socket(const char *const server_address, + const uint_fast16_t server_port, + struct sockaddr_in *const server_description, + struct sockaddr_in *const client_description) { int sockfd ; // Socket descriptor - /* Ceate the UDP socket */ + /* Create the UDP socket */ sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; if (sockfd < 0) { @@ -309,13 +336,12 @@ int owl_create_udp_trx_socket(char *server_address, } - /* * Creates a UDP reception socket and returns its descriptor. * Parameters: * - port: port on which the socket listens. */ -int owl_create_udp_listening_socket(uint_fast16_t port) +int owl_create_udp_listening_socket(const uint_fast16_t port) { int sockfd ; // Socket descriptor struct sockaddr_in server_description ; // Server structure @@ -350,11 +376,10 @@ int owl_create_udp_listening_socket(uint_fast16_t port) } - /* * Switches the IEEE 802.11 interface 'iface' to Monitor mode. */ -int owl_iface_mode_monitor(char *iface) +int owl_iface_mode_monitor(const char *const iface) { struct iwreq wrq ; int sockfd = iw_sockets_open() ; @@ -384,12 +409,12 @@ int owl_iface_mode_monitor(char *iface) } - /* * Sets the IEEE 802.11 channel of the interface 'iface'. * 'channel' must be an integer between 1 and 14. */ -int owl_iface_set_channel(char *iface, uint_fast8_t channel) +int owl_iface_set_channel(const char *const iface, + const uint_fast8_t channel) { struct iwreq wrq ; int sockfd = iw_sockets_open() ; @@ -410,12 +435,11 @@ int owl_iface_set_channel(char *iface, uint_fast8_t channel) } - /* * Switches alternatively the Wi-Fi channel of the IEEE 802.11 interface * 'iface' to 4 or 11. */ -int owl_iface_channel_hop(char *iface) +int owl_iface_channel_hop(const char *const iface) { uint_fast16_t channel ; struct iwreq wrq ; @@ -425,7 +449,7 @@ int owl_iface_channel_hop(char *iface) if (ioctl(sockfd, SIOCGIWFREQ, &wrq) == -1) { - perror("Erreur lors de la lecture de la fréquence ") ; + perror("Error reading the frequency") ; return ERR_READING_CHANNEL ; } // The following is not very clean: we should use iw_freq2float(), @@ -447,10 +471,13 @@ int owl_iface_channel_hop(char *iface) +/* *** Signals *** */ + + /* * Generic signal handler for SIGINT. */ -void owl_sigint_handler(int num) +void owl_sigint_handler(const int num) { if (num != SIGINT) { @@ -468,9 +495,10 @@ void owl_sigint_handler(int num) } - -/* Gestionnaire de signal générique pour SIGTERM */ -void owl_sigterm_handler(int num) +/* + * Generic signal handler for SIGTERM. + */ +void owl_sigterm_handler(const int num) { if (num != SIGTERM) { @@ -484,16 +512,19 @@ void owl_sigterm_handler(int num) +/* *** Thread-related functions *** */ + + /* * Closes the file descriptor 'fd'. * 'fd' must be passed as an int pointer (int*). */ -void owl_close_fd(void *fd) +void owl_close_fd(void *const fd) { if (fd == NULL) return ; - int *file_desc = fd ; + const int *const file_desc = fd ; if (close(*file_desc) != 0) perror("Error closing file descriptor") ; #ifdef DEBUG @@ -504,13 +535,12 @@ void owl_close_fd(void *fd) } - /* * Closes the stream 'file'. * 'file' must be passed as a pointer on a pointer of FILE (FILE**). * If *file either stdout, stderr or stdin, it will not be closed. */ -void owl_close_file(void *file) +void owl_close_file(void *const file) { if (file == NULL) return ; diff --git a/libowlps/owlps.h b/libowlps/owlps.h index b28e324..25e8700 100644 --- a/libowlps/owlps.h +++ b/libowlps/owlps.h @@ -232,44 +232,59 @@ extern owl_bool owl_run ; /* Function headers */ // Misc -const char* owl_mac_bytes_to_string(uint8_t *mac_binary) ; -void owl_mac_bytes_to_string_r(uint8_t *mac_binary, +const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary) ; +void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary, char mac_str[OWL_ETHER_ADDR_STRLEN]) ; -owl_bool owl_mac_equals(uint8_t *mac1, uint8_t *mac2) ; -uint_fast8_t owl_frequency_to_channel(uint_fast16_t channel) ; +owl_bool owl_mac_equals(const uint8_t *const mac1, + const uint8_t *const mac2) ; +uint_fast8_t owl_frequency_to_channel(const uint_fast16_t channel) ; // Time -int owl_timestamp_now(owl_timestamp *now) ; +int owl_timestamp_now(owl_timestamp *const now) ; owl_timestamp owl_timespec_to_timestamp(const struct timespec d) ; owl_timestamp owl_timeval_to_timestamp(const struct timeval d) ; -void owl_timestamp_to_string(char *dst, owl_timestamp src) ; -owl_bool owl_timestamp_equals(owl_timestamp d1, owl_timestamp d2) ; -owl_bool owl_timestamp_is_null(owl_timestamp d) ; -uint64_t owl_timestamp_to_ms(owl_timestamp date) ; +owl_bool owl_timestamp_equals(const owl_timestamp d1, + const owl_timestamp d2) ; +owl_bool owl_timestamp_is_null(const owl_timestamp d) ; +uint64_t owl_timestamp_to_ms(const owl_timestamp d) ; +void owl_timestamp_to_string(char *const dst, const owl_timestamp src) ; uint_fast32_t owl_time_elapsed_ms(const owl_timestamp d1, const owl_timestamp d2) ; owl_timestamp owl_time_elapsed(const owl_timestamp d1, const owl_timestamp d2) ; -owl_timestamp owl_hton_timestamp(owl_timestamp date) ; -owl_timestamp owl_ntoh_timestamp(owl_timestamp date) ; + +// Endianess +owl_timestamp owl_hton_timestamp(const owl_timestamp d) ; +owl_timestamp owl_ntoh_timestamp(const owl_timestamp d) ; +float owl_swap_float(const float f) ; +#if __BYTE_ORDER == __BIG_ENDIAN +# define owl_htonf(f) (f) +# define owl_ntohf(f) (f) +#else // __BYTE_ORDER == __BIG_ENDIAN +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define owl_htonf(f) owl_swap_float(f) +# define owl_ntohf(f) owl_swap_float(f) +# endif // __BYTE_ORDER == __LITTLE_ENDIAN +#endif // __BYTE_ORDER == __BIG_ENDIAN // Network -int owl_create_udp_trx_socket(char *server_address, - uint_fast16_t server_port, - struct sockaddr_in *server_description, - struct sockaddr_in *client_description) ; -int owl_create_udp_listening_socket(uint_fast16_t port) ; -int owl_iface_mode_monitor(char *iface) ; -int owl_iface_set_channel(char *iface, uint_fast8_t channel) ; -int owl_iface_channel_hop(char *iface) ; +int owl_create_udp_trx_socket(const char *const server_address, + const uint_fast16_t server_port, + struct sockaddr_in *const server_description, + struct sockaddr_in *const client_description) ; +int owl_create_udp_listening_socket(const uint_fast16_t port) ; +int owl_iface_mode_monitor(const char *const iface) ; +int owl_iface_set_channel(const char *const iface, + const uint_fast8_t channel) ; +int owl_iface_channel_hop(const char *const iface) ; // Signals -void owl_sigint_handler(int num) ; -void owl_sigterm_handler(int num) ; +void owl_sigint_handler(const int num) ; +void owl_sigterm_handler(const int num) ; // Threads -void owl_close_fd(void *fd) ; -void owl_close_file(void *file) ; +void owl_close_fd(void *const fd) ; +void owl_close_file(void *const file) ; /* Macros */ diff --git a/owlps-aggregator/Makefile b/owlps-aggregator/Makefile index f5bf98a..74abb2a 100644 --- a/owlps-aggregator/Makefile +++ b/owlps-aggregator/Makefile @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Répertoire d'installation PREFIX=/usr/local INSTALL_DIR= $(PREFIX)/bin @@ -25,7 +30,7 @@ CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O -I$(LIBOWLPS_DIR) DEPFLAGS=-MMD XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) PICFLAG=-fPIC -#OWLPSFLAGS = +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" LIBS = -pthread -lconfuse -L$(LIBOWLPS_DIR) -lowlps LDFLAGS = $(LIBS) $(OWLPSFLAGS) diff --git a/owlps-aggregator/owlps-aggregator.h b/owlps-aggregator/owlps-aggregator.h index b4bba4b..0060b59 100644 --- a/owlps-aggregator/owlps-aggregator.h +++ b/owlps-aggregator/owlps-aggregator.h @@ -11,7 +11,7 @@ /* Arguments & program configuration */ -#define OPTIONS "Aa:c:C:f:hi:k:K:l:o:p:t:v" // getopt string +#define OPTIONS "Aa:c:C:f:hi:k:K:l:o:p:t:vV" // getopt string #define DEFAULT_CONFIG_FILE "/usr/local/etc/owlps/owlps-aggregator.conf" #define DEFAULT_AGGREGATE_TIMEOUT 1500 // milliseconds #define DEFAULT_KEEP_TIMEOUT 3000 // milliseconds @@ -112,5 +112,6 @@ void order_send(ap_list *ap) ; void free_ap_list(void) ; void print_usage(void) ; +void print_version(void) ; #endif // _OWLPS_AGGREGATOR_H_ diff --git a/owlps-aggregator/owlps-aggregatord.c b/owlps-aggregator/owlps-aggregatord.c index 277a5b1..e98a408 100644 --- a/owlps-aggregator/owlps-aggregatord.c +++ b/owlps-aggregator/owlps-aggregatord.c @@ -188,19 +188,30 @@ void parse_config_file(int argc, char **argv) CFG_END() } ; - char *config_file ; + char *config_file = NULL ; // Configuration file name - // Option -f specifies a config file, so we search for it first + // Option -f specifies a config file, options -h and -V exit the + // program, so we search for them first int opt ; - do - opt = getopt(argc, argv, OPTIONS) ; - while (opt != 'f' && opt != -1) ; - if (opt == 'f') + while ((opt = getopt(argc, argv, OPTIONS)) != -1) { - config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ; - strcpy(config_file, optarg) ; + switch (opt) + { + case 'f' : + config_file = malloc((strlen(optarg) + 1) * sizeof(char)) ; + strcpy(config_file, optarg) ; + break ; + case 'h' : + print_usage() ; + exit(0) ; + case 'V' : + print_version() ; + exit(0) ; + } } - else // If -f isn't found, we use the default config file + + // If -f isn't found, we use the default config file + if (config_file == NULL) { config_file = malloc((strlen(DEFAULT_CONFIG_FILE) + 1) * sizeof(char)) ; @@ -415,6 +426,9 @@ int read_loop(int sockfd) // Endianess conversions: request.request_time = owl_ntoh_timestamp(request.request_time) ; request.start_time = owl_ntoh_timestamp(request.start_time) ; + request.x_position = owl_ntohf(request.x_position) ; + request.y_position = owl_ntohf(request.y_position) ; + request.z_position = owl_ntohf(request.z_position) ; if (cfg_getbool(cfg, "verbose")) { @@ -436,7 +450,7 @@ int read_loop(int sockfd) "\tPosition X: %f\n" "\tPosition Y: %f\n" "\tPosition Z: %f\n" - "\tDirection: %hhd\n" + "\tDirection: %"PRIu8"\n" , request.type, owl_mac_bytes_to_string(request.ap_mac_addr_bytes), @@ -1228,9 +1242,12 @@ void print_usage() " [-K ap_keep_timeout]" " [-C ap_check_interval]" "\n" + "\t%s -h\n" + "\t%s -V\n" "Main options:\n" "\t-h\t\tPrint this help.\n" + "\t-V\t\tShow version information.\n" "\t-f config_file\tUse 'config_file' instead of the default" " configuration file (%s).\n" "\t-v\t\tBe verbose (print detailed info on each received" @@ -1249,7 +1266,7 @@ void print_usage() " treated (default: %d).\n" "\t-t aggregate_timeout\tRequests are stored during" " 'aggregate_timeout' milliseconds before to be grouped" - " (default: %d ms).\n" + " (default: %d ms).\n" "\t-k keep_timeout\t\tAggregated requests are kept during" " 'keep_timeout' milliseconds (default: %d ms).\n" "\t-c check_interval\tTime between two checks of the stored" @@ -1265,6 +1282,8 @@ void print_usage() " checks of the stored APs (default: %d ms).\n" , program_name, + program_name, + program_name, DEFAULT_CONFIG_FILE, POSITIONER_DEFAULT_IP, POSITIONER_DEFAULT_PORT, @@ -1277,3 +1296,17 @@ void print_usage() DEFAULT_AP_CHECK_INTERVAL ) ; } + + +void print_version() +{ + printf("This is OwlPS Aggregator, part of the Open Wireless" + " Positioning System project.\n" + "Version: %s.\n", +#ifdef OWLPS_VERSION + OWLPS_VERSION +#else // OWLPS_VERSION + "unknown version" +#endif // OWLPS_VERSION + ) ; +} diff --git a/owlps-ardrone/Makefile b/owlps-ardrone/Makefile index 382d962..b18f508 100644 --- a/owlps-ardrone/Makefile +++ b/owlps-ardrone/Makefile @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Répertoire d'installation PREFIX=/usr/local INSTALL_DIR= $(PREFIX)/bin @@ -29,7 +34,7 @@ XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) PICFLAG = -fPIC LIBS = -L$(LIBOWLPS_DIR) -lowlps -L$(LIBOWLPSCLIENT_DIR) -lowlps-client STATIC_LIBS = -liw -lm -lrt - +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" ## Cibles de compilation standard ## @@ -42,7 +47,7 @@ all : dynamic static % : %.o $(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS) %.o : %.c $(HEADER) - $(CC) $(XCFLAGS) -c $< + $(CC) $(XCFLAGS) $(OWLPSFLAGS) -c $< # Compilation du programme $(TARGET) : $(TARGET).o $(HEADER) diff --git a/owlps-ardrone/Makefile_drone b/owlps-ardrone/Makefile_drone index edd5c2a..2428288 100644 --- a/owlps-ardrone/Makefile_drone +++ b/owlps-ardrone/Makefile_drone @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Emplacement de la suite de cross-compilation TOOLCHAIN_PREFIX = /arm TOOLCHAIN_BIN = $(TOOLCHAIN_PREFIX)/bin @@ -39,7 +44,7 @@ STATIC_LIBS = $(LOWLPSA) $(LIBS) LATHEROS = -L$(TOOLCHAIN_USR)/lib -L$(TOOLCHAIN_USR_2)/lib IATHEROS = -I$(TOOLCHAIN_USR)/include -I$(TOOLCHAIN_USR_2)/include LDFLAGS = $(IATHEROS) $(LATHEROS) - +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" ## Cibles de compilation standard ## @@ -56,7 +61,7 @@ all: semistatic static # $(CC) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LDFLAGS) $(DYNAMIC_LIBS) %: %.o - $(CC) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LDFLAGS) $(SEMISTATIC_LIBS) + $(CC) $(STRIPFLAGS) $(XCFLAGS) $(OWLPSFLAGS) -o $@ $^ $(LDFLAGS) $(SEMISTATIC_LIBS) %.static: %.o $(CC) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LDFLAGS) $(STATIC_LIBS) \ diff --git a/owlps-ardrone/owlps-drone.c b/owlps-ardrone/owlps-drone.c index 8c7a65d..ac7ff08 100644 --- a/owlps-ardrone/owlps-drone.c +++ b/owlps-ardrone/owlps-drone.c @@ -146,6 +146,9 @@ void parse_main_options(int argc, char **argv) case 't' : options.delay = strtol(optarg, NULL, 0) ; break ; + case 'V' : + print_version() ; + exit(0) ; default : print_usage() ; exit(ERR_BAD_USAGE) ; @@ -219,7 +222,7 @@ void check_configuration() else options.nb_pkt = DEFAULT_NBPKT_NORMAL ; } - + // Calibration request but bad direction if (is_calibration_request) if (options.direction < OWL_DIRECTION_MIN || @@ -271,7 +274,7 @@ void print_configuration() "\tDelay: %"PRIuFAST32"\n" "\tNumber of packets: %"PRIuFAST16"\n" "\tListening port: %"PRIuFAST16"\n" - "\tDirection: %d\n" + "\tDirection: %"PRIu8"\n" "\tX: %f\n" "\tY: %f\n" "\tZ: %f\n" @@ -341,6 +344,9 @@ void make_packet() printf("Direction = %d, X = %f, Y = %f, Z = %f\n", packet[offset - 1], options.x, options.y, options.z) ; #endif // DEBUG + options.x = owl_htonf(options.x) ; + options.y = owl_htonf(options.y) ; + options.z = owl_htonf(options.z) ; memcpy(&packet[offset], &options.x, sizeof(float)) ; offset += sizeof(float) ; memcpy(&packet[offset], &options.y, sizeof(float)) ; @@ -546,6 +552,7 @@ void print_usage() "\n" "Options:\n" "\t-h\t\tPrint this help.\n" + "\t-V\t\tPrint version information.\n" "\t-d dest_ip\tDestination IP address of the localisation request.\n" "\t-p dest_port\tDestination port of the localisation request" " (default: %d).\n" @@ -572,3 +579,17 @@ void print_usage() MOBILE_DEFAULT_PORT ) ; } + + +void print_version() +{ + printf("This is OwlPS Client for AR.Drone, part of the Open Wireless" + " Positioning System project.\n" + "Version: %s.\n", +#ifdef OWLPS_VERSION + OWLPS_VERSION +#else // OWLPS_VERSION + "unknown version" +#endif // OWLPS_VERSION:w + ) ; +} diff --git a/owlps-ardrone/owlps-drone.h b/owlps-ardrone/owlps-drone.h index f16112d..ee1119c 100644 --- a/owlps-ardrone/owlps-drone.h +++ b/owlps-ardrone/owlps-drone.h @@ -16,7 +16,7 @@ #define DEFAULT_DELAY_NORMAL 25000 // Localisation request /* Program arguments (getopt string) */ -#define OPTIONS "d:hi:l::n:p:t:" +#define OPTIONS "d:hi:l::n:p:t:V" /* Function headers */ @@ -37,6 +37,7 @@ void send_labview(char*) ; void string2data(char*) ; void* thread_send(void*) ; void print_error(char*) ; +void print_version(void) ; typedef struct result result; /* Struct */ diff --git a/owlps-client/Makefile b/owlps-client/Makefile index 92578b6..dd00660 100644 --- a/owlps-client/Makefile +++ b/owlps-client/Makefile @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Répertoire d'installation PREFIX=/usr/local INSTALL_DIR= $(PREFIX)/bin @@ -27,6 +32,7 @@ CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \ DEPFLAGS = -MMD XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) PICFLAG = -fPIC +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" LIBS = -L$(LIBOWLPS_DIR) -lowlps -L$(LIBOWLPSCLIENT_DIR) -lowlps-client STATIC_LIBS = -liw -lm -lrt @@ -42,7 +48,7 @@ all : dynamic static % : %.o $(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS) %.o : %.c $(HEADER) - $(CC) $(XCFLAGS) -c $< + $(CC) $(XCFLAGS) $(OWLPSFLAGS) -c $< # Compilation du programme $(TARGET) : $(TARGET).o $(HEADER) diff --git a/owlps-client/Makefile_atheros b/owlps-client/Makefile_atheros index feeaeeb..8cb08e9 100644 --- a/owlps-client/Makefile_atheros +++ b/owlps-client/Makefile_atheros @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Emplacement de la suite de cross-compilation TOOLCHAIN_PREFIX = $$HOME/openwrt/atheros/8.09 TOOLCHAIN_BIN = $(TOOLCHAIN_PREFIX)/staging_dir/toolchain-mips_gcc4.1.2/bin @@ -40,6 +45,7 @@ STATIC_LIBS = $(LOWLPSA) $(LIBS) LATHEROS = -L$(TOOLCHAIN_USR)/lib -L$(TOOLCHAIN_USR_2)/lib IATHEROS = -I$(TOOLCHAIN_USR)/include -I$(TOOLCHAIN_USR_2)/include LDFLAGS = $(IATHEROS) $(LATHEROS) +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" ## Cibles de compilation standard ## diff --git a/owlps-client/Makefile_atheros_openwrt-10.03 b/owlps-client/Makefile_atheros_openwrt-10.03 index 69cabdc..9b57248 100644 --- a/owlps-client/Makefile_atheros_openwrt-10.03 +++ b/owlps-client/Makefile_atheros_openwrt-10.03 @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Emplacement de la suite de cross-compilation TOOLCHAIN_PREFIX = $$HOME/openwrt/atheros/10.03 TOOLCHAIN_BIN = $(TOOLCHAIN_PREFIX)/staging_dir/toolchain-mips_gcc-4.3.3+cs_uClibc-0.9.30.1/usr/bin @@ -40,6 +45,7 @@ STATIC_LIBS = $(LOWLPSA) $(LIBS) LATHEROS = -L$(TOOLCHAIN_USR)/lib -L$(TOOLCHAIN_USR_2)/lib IATHEROS = -I$(TOOLCHAIN_USR)/include -I$(TOOLCHAIN_USR_2)/include LDFLAGS = $(IATHEROS) $(LATHEROS) +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" ## Cibles de compilation standard ## diff --git a/owlps-client/owlps-client.c b/owlps-client/owlps-client.c index 5f77440..f9d7c2e 100644 --- a/owlps-client/owlps-client.c +++ b/owlps-client/owlps-client.c @@ -26,7 +26,7 @@ #define DEFAULT_DELAY_NORMAL 25000 // Localisation request /* Program arguments (getopt string) */ -#define OPTIONS "d:hi:l::n:p:t:" +#define OPTIONS "d:hi:l::n:p:t:V" /* Function headers */ @@ -43,6 +43,7 @@ void make_packet(void) ; void send_request(void) ; void receive_position(void) ; void print_usage(void) ; +void print_version(void) ; /* Options */ @@ -162,6 +163,9 @@ void parse_main_options(int argc, char **argv) case 't' : options.delay = strtol(optarg, NULL, 0) ; break ; + case 'V' : + print_version() ; + exit(0) ; default : print_usage() ; exit(ERR_BAD_USAGE) ; @@ -287,7 +291,7 @@ void print_configuration() "\tDelay: %"PRIuFAST32"\n" "\tNumber of packets: %"PRIuFAST16"\n" "\tListening port: %"PRIuFAST16"\n" - "\tDirection: %d\n" + "\tDirection: %"PRIu8"\n" "\tX: %f\n" "\tY: %f\n" "\tZ: %f\n" @@ -348,6 +352,9 @@ void make_packet() printf("Direction = %d, X = %f, Y = %f, Z = %f\n", packet[offset - 1], options.x, options.y, options.z) ; #endif // DEBUG + options.x = owl_htonf(options.x) ; + options.y = owl_htonf(options.y) ; + options.z = owl_htonf(options.z) ; memcpy(&packet[offset], &options.x, sizeof(float)) ; offset += sizeof(float) ; memcpy(&packet[offset], &options.y, sizeof(float)) ; @@ -405,6 +412,7 @@ void print_usage() "\n" "Options:\n" "\t-h\t\tPrint this help.\n" + "\t-V\t\tPrint version information.\n" "\t-d dest_ip\tDestination IP address of the localisation request.\n" "\t-p dest_port\tDestination port of the localisation request" " (default: %d).\n" @@ -431,3 +439,17 @@ void print_usage() MOBILE_DEFAULT_PORT ) ; } + + +void print_version() +{ + printf("This is OwlPS Client, part of the Open Wireless" + " Positioning System project.\n" + "Version: %s.\n", +#ifdef OWLPS_VERSION + OWLPS_VERSION +#else // OWLPS_VERSION + "unknown version" +#endif // OWLPS_VERSION + ) ; +} diff --git a/owlps-listener/Makefile b/owlps-listener/Makefile index 5d536c7..fd217dd 100644 --- a/owlps-listener/Makefile +++ b/owlps-listener/Makefile @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif + # Répertoire d'installation PREFIX=/usr/local INSTALL_DIR= $(PREFIX)/sbin @@ -27,7 +32,8 @@ CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \ DEPFLAGS = -MMD XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS) PICFLAG = -fPIC -OWLPSFLAGS = -D USE_CONFIG_FILE -lconfuse -D USE_PTHREAD -pthread +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" \ + -D USE_CONFIG_FILE -lconfuse -D USE_PTHREAD -pthread LIBS = -L$(LIBOWLPS_DIR) -lowlps \ -L$(LIBOWLPSCLIENT_DIR) -lowlps-client \ -lpcap diff --git a/owlps-listener/Makefile_atheros b/owlps-listener/Makefile_atheros index 02ca335..2604b04 100644 --- a/owlps-listener/Makefile_atheros +++ b/owlps-listener/Makefile_atheros @@ -1,3 +1,8 @@ +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe) +endif + # Emplacement de la suite de cross-compilation TOOLCHAIN_PREFIX = $$HOME/openwrt/atheros/8.09 TOOLCHAIN_BIN = $(TOOLCHAIN_PREFIX)/staging_dir/toolchain-mips_gcc4.1.2/bin @@ -36,7 +41,8 @@ LOWLPSCLIENTA = $(LIBOWLPSCLIENT_DIR)/libowlps-client.a LIBS = -lpcap -liw -lm $(LOWLPSCLIENTA) LATHEROS = -L$(TOOLCHAIN_USR)/lib -L$(TOOLCHAIN_USR_2)/lib IATHEROS = -I$(TOOLCHAIN_USR)/include -I$(TOOLCHAIN_USR_2)/include -OWLPSFLAGS = -D USE_PTHREAD -pthread +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" \ + -D USE_PTHREAD -pthread #OWLPSFLAGS += -D USE_CONFIG_FILE -lconfuse LDFLAGS = $(OWLPSFLAGS) $(LIBS) diff --git a/owlps-listener/owlps-listener.h b/owlps-listener/owlps-listener.h index 47af346..fd8c1f9 100644 --- a/owlps-listener/owlps-listener.h +++ b/owlps-listener/owlps-listener.h @@ -24,23 +24,25 @@ * version of glibc, or another libc (e.g. uClibc), we must define them * manually. */ -#ifndef le32toh -# if __BYTE_ORDER == __LITTLE_ENDIAN +#if __BYTE_ORDER == __LITTLE_ENDIAN +# ifndef le32toh # define le32toh(x) (x) -# else // __BYTE_ORDER == __LITTLE_ENDIAN -# include -# define le32toh(x) bswap_32(x) -# endif // __BYTE_ORDER == __LITTLE_ENDIAN -#endif // le32toh - -#ifndef le16toh -# if __BYTE_ORDER == __LITTLE_ENDIAN +# endif // le32toh +# ifndef le16toh # define le16toh(x) (x) -# else // __BYTE_ORDER == __LITTLE_ENDIAN -# include -# define le16toh(x) bswap_16(x) -# endif // __BYTE_ORDER == __LITTLE_ENDIAN -#endif // le16toh +# endif // le16toh +#else // __BYTE_ORDER == __LITTLE_ENDIAN +# if __BYTE_ORDER == __BIG_ENDIAN +# ifndef le32toh +# include +# define le32toh(x) bswap_32(x) +# endif // le32toh +# ifndef le16toh +# include +# define le16toh(x) bswap_16(x) +# endif // le16toh +# endif // __BYTE_ORDER == __BIG_ENDIAN +#endif // __BYTE_ORDER == __LITTLE_ENDIAN /* Arguments & program configuration */ @@ -63,6 +65,8 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ; void initialise_configuration(int argc, char **argv) ; void parse_config_file(int argc, char **argv) ; void parse_command_line(int argc, char **argv) ; +void parse_main_options(int argc, char **argv) ; +void parse_calibration_data(int argc, char **argv) ; void check_configuration(void) ; #ifdef DEBUG void print_configuration(void) ; @@ -157,6 +161,22 @@ void print_version(void) ; (cfg_setint(cfg, "autocalibration_nb_packets", (NBPKT))) #define GET_AUTOCALIBRATION_NBPKT() \ (cfg_getint(cfg, "autocalibration_nb_packets")) +#define SET_MY_DIRECTION(DIRECTION) \ + (cfg_setint(cfg, "my_direction", (DIRECTION))) +#define GET_MY_DIRECTION() \ + (cfg_getint(cfg, "my_direction")) +#define SET_MY_POSITION_X(POSITION) \ + (cfg_setfloat(cfg, "my_position_x", (POSITION))) +#define GET_MY_POSITION_X() \ + (cfg_getfloat(cfg, "my_position_x")) +#define SET_MY_POSITION_Y(POSITION) \ + (cfg_setfloat(cfg, "my_position_y", (POSITION))) +#define GET_MY_POSITION_Y() \ + (cfg_getfloat(cfg, "my_position_y")) +#define SET_MY_POSITION_Z(POSITION) \ + (cfg_setfloat(cfg, "my_position_z", (POSITION))) +#define GET_MY_POSITION_Z() \ + (cfg_getfloat(cfg, "my_position_z")) #endif // USE_PTHREAD #define SET_VERBOSE() \ @@ -234,6 +254,22 @@ void print_version(void) ; (options.autocalibration_nb_packets = (NBPKT)) #define GET_AUTOCALIBRATION_NBPKT() \ (options.autocalibration_nb_packets) +#define SET_MY_DIRECTION(DIRECTION) \ + (options.my_direction = (DIRECTION)) +#define GET_MY_DIRECTION() \ + (options.my_direction) +#define SET_MY_POSITION_X(POSITION) \ + (options.my_position_x = (POSITION)) +#define GET_MY_POSITION_X() \ + (options.my_position_x) +#define SET_MY_POSITION_Y(POSITION) \ + (options.my_position_y = (POSITION)) +#define GET_MY_POSITION_Y() \ + (options.my_position_y) +#define SET_MY_POSITION_Z(POSITION) \ + (options.my_position_z = (POSITION)) +#define GET_MY_POSITION_Z() \ + (options.my_position_z) #endif // USE_PTHREAD #define SET_VERBOSE() \ diff --git a/owlps-listener/owlps-listenerd.c b/owlps-listener/owlps-listenerd.c index 033fae3..e26898a 100644 --- a/owlps-listener/owlps-listenerd.c +++ b/owlps-listener/owlps-listenerd.c @@ -28,6 +28,8 @@ #include #include +#include + char *program_name = NULL ; uint8_t my_mac_bytes[ETHER_ADDR_LEN] ; // AP MAC address @@ -36,8 +38,13 @@ char my_ip[INET_ADDRSTRLEN] ; // AP IP address pcap_t *capture_handler = NULL ; // Packet capture descriptor int aggregation_sockfd ; struct sockaddr_in aggregation_server ; + +#ifdef USE_PTHREAD int autocalibration_send_sockfd ; struct sockaddr_in autocalibration_send_server ; +// TRUE if the coordinates of the listener were provided by the user: +owl_bool coordinates_provided = FALSE ; +#endif // USE_PTHREAD #ifdef USE_CONFIG_FILE cfg_t *cfg ; // Configuration structure @@ -64,6 +71,10 @@ struct { uint_fast32_t autocalibration_hello_delay ; uint_fast32_t autocalibration_delay ; uint_fast16_t autocalibration_nb_packets ; + owl_direction my_direction ; + float my_position_x ; + float my_position_y ; + float my_position_z ; #endif // USE_PTHREAD owl_bool verbose ; owl_bool display_captured ; @@ -85,6 +96,7 @@ struct { DEFAULT_AUTOCALIBRATION_HELLO_DELAY, DEFAULT_AUTOCALIBRATION_DELAY, DEFAULT_AUTOCALIBRATION_NBPKT, + 0, 0, 0, 0, #endif // USE_PTHREAD FALSE, FALSE @@ -278,6 +290,14 @@ void parse_config_file(int argc, char **argv) // Number of packets for a calibration request: CFG_INT("autocalibration_nb_packets", DEFAULT_AUTOCALIBRATION_NBPKT, CFGF_NONE), + // Direction + CFG_INT("my_direction", 0, CFGF_NONE), + // Position X + CFG_FLOAT("my_position_x", 0, CFGF_NONE), + // Position Y + CFG_FLOAT("my_position_y", 0, CFGF_NONE), + // Position Z + CFG_FLOAT("my_position_z", 0, CFGF_NONE), #endif // USE_PTHREAD // Be verbose, or not: CFG_BOOL("verbose", cfg_false, CFGF_NONE), @@ -306,6 +326,7 @@ void parse_config_file(int argc, char **argv) " You must specify all options on the command line," " or default value will be used.\n") ; #endif // USE_CONFIG_FILE + break ; case 'h' : print_usage() ; exit(0) ; @@ -347,6 +368,14 @@ void parse_config_file(int argc, char **argv) void parse_command_line(int argc, char **argv) +{ + parse_main_options(argc, argv) ; + parse_calibration_data(argc, argv) ; +} + + + +void parse_main_options(int argc, char **argv) { int opt ; @@ -450,6 +479,29 @@ void parse_command_line(int argc, char **argv) +void parse_calibration_data(int argc, char **argv) +{ + /* Parse remaining arguments (possible calibration data) */ + if (argc - optind != 0) + { + if (argc - optind == 4) + { + coordinates_provided = TRUE ; + SET_MY_DIRECTION(strtoul(argv[optind++], NULL, 0)) ; + SET_MY_POSITION_X(strtod(argv[optind++], NULL)) ; + SET_MY_POSITION_Y(strtod(argv[optind++], NULL)) ; + SET_MY_POSITION_Z(strtod(argv[optind], NULL)) ; + } + else // Bad number of arguments + { + print_usage() ; + exit(ERR_BAD_USAGE) ; + } + } +} + + + void check_configuration() { switch (GET_MODE()) @@ -481,15 +533,6 @@ void check_configuration() SET_WIFI_IFACE(GET_RTAP_IFACE()) ; } - if (GET_AUTOCALIBRATION() && GET_AUTOCALIBRATION_IP()[0] == '\0') - { - if (GET_VERBOSE()) - fprintf(stderr, "No autocalibration IP specified, we will use" - " the aggregation IP as the destination of" - " autocalibration requests.\n") ; - SET_AUTOCALIBRATION_IP(GET_AGGREGATION_IP()) ; - } - // Port numbers // if (GET_AGGREGATION_PORT() < 1 || GET_AGGREGATION_PORT() > 65535) { @@ -505,22 +548,49 @@ void check_configuration() " failing back to the default value.\n") ; SET_LISTENING_PORT(LOC_REQUEST_DEFAULT_PORT) ; } - if (GET_AUTOCALIBRATION_REQUEST_PORT() < 1 || - GET_AUTOCALIBRATION_REQUEST_PORT() > 65535) + + // Autocalibration stuff // +#ifdef USE_PTHREAD + if (GET_AUTOCALIBRATION()) { - if (GET_VERBOSE()) - fprintf(stderr, "Warning! Bad autocalibration_request_port:" - " failing back to the default value.\n") ; - SET_AUTOCALIBRATION_REQUEST_PORT(DEFAULT_AUTOCALIBRATION_REQUEST_PORT) ; - } - if (GET_AUTOCALIBRATION_PORT() < 1 || - GET_AUTOCALIBRATION_PORT() > 65535) - { - if (GET_VERBOSE()) - fprintf(stderr, "Warning! Bad autocalibration_port:" - " failing back to the default value.\n") ; - SET_AUTOCALIBRATION_PORT(DEFAULT_AUTOCALIBRATION_PORT) ; + if (GET_AUTOCALIBRATION_IP()[0] == '\0') + { + if (GET_VERBOSE()) + fprintf(stderr, "No autocalibration IP specified, we will" + " use the aggregation IP as the destination of" + " autocalibration requests.\n") ; + SET_AUTOCALIBRATION_IP(GET_AGGREGATION_IP()) ; + } + + if (GET_AUTOCALIBRATION_NBPKT() < 1) + fprintf(stderr, "Warning! autocalibration_nb_packets is null," + " no autocalibration request will be sent!\n") ; + + if (coordinates_provided) + if (GET_MY_DIRECTION() < OWL_DIRECTION_MIN || + GET_MY_DIRECTION() > OWL_DIRECTION_MAX) + fprintf(stderr, "Warning! « %d » is not a valid" + " direction.\n", (int) GET_MY_DIRECTION()) ; + + // Autocalibration port numbers + if (GET_AUTOCALIBRATION_REQUEST_PORT() < 1 || + GET_AUTOCALIBRATION_REQUEST_PORT() > 65535) + { + if (GET_VERBOSE()) + fprintf(stderr, "Warning! Bad autocalibration_request_port:" + " failing back to the default value.\n") ; + SET_AUTOCALIBRATION_REQUEST_PORT(DEFAULT_AUTOCALIBRATION_REQUEST_PORT) ; + } + if (GET_AUTOCALIBRATION_PORT() < 1 || + GET_AUTOCALIBRATION_PORT() > 65535) + { + if (GET_VERBOSE()) + fprintf(stderr, "Warning! Bad autocalibration_port:" + " failing back to the default value.\n") ; + SET_AUTOCALIBRATION_PORT(DEFAULT_AUTOCALIBRATION_PORT) ; + } } +#endif // USE_PTHREAD } @@ -548,6 +618,10 @@ void print_configuration() "autocalibration_hello_delay = %"PRIuFAST32"\n" "autocalibration_delay = %"PRIuFAST32"\n" "autocalibration_nb_packets = %"PRIuFAST16"\n" + "my_direction = %"PRIu8"\n" + "my_position_x = %f\n" + "my_position_y = %f\n" + "my_position_z = %f\n" #endif // USE_PTHREAD "verbose = %s\n" "display_captured = %s\n" @@ -567,6 +641,10 @@ void print_configuration() GET_AUTOCALIBRATION_HELLO_DELAY(), GET_AUTOCALIBRATION_DELAY(), GET_AUTOCALIBRATION_NBPKT(), + GET_MY_DIRECTION(), + GET_MY_POSITION_X(), + GET_MY_POSITION_Y(), + GET_MY_POSITION_Z(), #endif // USE_PTHREAD OWL_BOOL_TO_STRING(GET_VERBOSE()), OWL_BOOL_TO_STRING(GET_DISPLAY_CAPTURED()) @@ -812,6 +890,21 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, printf(".. on the wrong port!") ; putchar('\n') ; } + request.direction = + packet[rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE + + sizeof(struct iphdr) + sizeof(struct udphdr) + 9]; + memcpy(&request.x_position, + &packet[rtap_bytes + ieee80211_header_size + + LLC_HEADER_SIZE + sizeof(struct iphdr) + + sizeof(struct udphdr) + 10], sizeof(float)) ; + memcpy(&request.y_position, + &packet[rtap_bytes + ieee80211_header_size + + LLC_HEADER_SIZE + sizeof(struct iphdr) + + sizeof(struct udphdr) + 14], sizeof(float)) ; + memcpy(&request.z_position, + &packet[rtap_bytes + ieee80211_header_size + + LLC_HEADER_SIZE + sizeof(struct iphdr) + + sizeof(struct udphdr) + 18], sizeof(float)) ; break ; default : @@ -973,9 +1066,9 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header, request_time_str, start_time_str, request.antenna_signal_dbm - 0x100, - request.x_position, - request.y_position, - request.z_position, + owl_ntohf(request.x_position), + owl_ntohf(request.y_position), + owl_ntohf(request.z_position), request.direction ) ; } @@ -1172,7 +1265,12 @@ uint_fast16_t make_packet(uint8_t **packet) { uint8_t *pkt ; uint_fast16_t size ; // Packet size + uint_fast16_t offset ; // Index used to create the packet owl_timestamp request_time ; + float + my_position_x = owl_htonf(GET_MY_POSITION_X()), + my_position_y = owl_htonf(GET_MY_POSITION_Y()), + my_position_z = owl_htonf(GET_MY_POSITION_Z()) ; owl_timestamp_now(&request_time) ; @@ -1185,11 +1283,29 @@ uint_fast16_t make_packet(uint8_t **packet) request_time = owl_hton_timestamp(request_time) ; - size = sizeof(char) + sizeof(owl_timestamp) ; + offset = 0 ; + size = + sizeof(uint8_t) * 2 + sizeof(owl_timestamp) + sizeof(float) * 3 ; pkt = malloc(size) ; - memset(&pkt[0], OWL_REQUEST_AUTOCALIBRATION, 1) ; // Packet type - memcpy(&pkt[1], &request_time, sizeof(request_time)) ; + // Request type: + memset(&pkt[offset], OWL_REQUEST_AUTOCALIBRATION, 1) ; + ++offset ; + // Timestamp: + memcpy(&pkt[offset], &request_time, sizeof(request_time)) ; + offset += sizeof(request_time) ; + // Coordinates: + pkt[offset] = GET_MY_DIRECTION() ; + ++offset ; + memcpy(&pkt[offset], &my_position_x, sizeof(float)) ; + offset += sizeof(float) ; + memcpy(&pkt[offset], &my_position_y, sizeof(float)) ; + offset += sizeof(float) ; + memcpy(&pkt[offset], &my_position_z, sizeof(float)) ; +#ifdef DEBUG + offset += sizeof(float) ; + assert(offset == size) ; +#endif // DEBUG *packet = pkt ; return size ; @@ -1225,13 +1341,13 @@ void print_usage() " [-D autocalibration_ip]" " [-P autocalibration_request_port ] [-a autocalibration_port]" " [-H autocalibration_hello_delay] [-t autocalibration_delay]" - " [-n autocalibration_nb_packets]\n" + " [-n autocalibration_nb_packets] [direction x y z]\n" "\t%s -h\n" "\t%s -V\n" "Main options:\n" "\t-h\t\tPrint this help.\n" - "\t-V\t\tShow version.\n" + "\t-V\t\tShow version information.\n" "\t-f config_file\tUse 'config_file' instead of the default" " configuration file (%s). Available only if program was" " compiled with libconfuse.\n" @@ -1255,16 +1371,19 @@ void print_usage() "\t-A\t\t\tEnable autocalibration (default: disabled).\n" "\t-D autocalib_ip\t\tDestination IP of the autocalibration" "requests (default: aggregation_ip).\n" - "\t-P autocalib_req_port\tPort on which autocalibration positioning" - " requests are sent (default: %d).\n" - "\t-a autocalib_port\tPort on which autocalibration data (hello & orders)" - " are exchanged with the aggregation server (default: %d).\n" + "\t-P autocalib_req_port\tPort on which autocalibration" + " positioning requests are sent (default: %d).\n" + "\t-a autocalib_port\tPort on which autocalibration data (hello" + " & orders) are exchanged with the aggregation server" + " (default: %d).\n" "\t-H hello_delay\t\tTime between each hello" " message sent to the aggregation server (default: %d s).\n" "\t-t delay\t\tTime between each autocalibration" " packet transmission (default: %d µs).\n" "\t-n nb_packets\t\tNumber of packet transmitted" " for one autocalibration request (default: %d).\n" + "\tdirection x y z\t\tThe coordinates of the listener" + " (direction is an integer; x, y, z are floats).\n" "Other options:\n" "\t-k\tKeep the monitor mode up on wifi_iface. Use it with buggy" @@ -1293,12 +1412,18 @@ void print_usage() void print_version() { - printf("This is OWLPS Listener, part of the Open Wireless Positioning" + printf("This is OwlPS Listener, part of the Open Wireless Positioning" " System project.\n" - "\n" + "Version: %s.\n" "Compilation-time options:\n" "\tSupport for POSIX threads: %s.\n" "\tSupport for configuration file (libconfuse): %s.\n", +#ifdef OWLPS_VERSION + OWLPS_VERSION +#else // OWLPS_VERSION + "unknown version" +#endif // OWLPS_VERSION + , #ifdef USE_PTHREAD "YES" #else // USE_PTHREAD diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index ad2121f..5545c48 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -1,5 +1,9 @@ -.PHONY : all test doc prepare clean purge install uninstall style check +# Source version +ifndef OWLPS_VERSION + OWLPS_VERSION = $$(git describe || echo 'UNKNOWN_VERSION') +endif +# Directories & files SRC_DIR = src OBJ_DIR = obj TESTS_DIR = tests @@ -8,7 +12,7 @@ DOXYFILE = Doxyfile # Installation directory PREFIX = /usr/local -INSTALL_DIR = $(PREFIX)/bin +INSTALL_DIR = $(PREFIX)/bin # System tools RM = rm -fv @@ -19,7 +23,7 @@ MKDIR = mkdir -pv # Other tools STYLE = astyle --style=gnu --formatted -CPPCHECK = cppcheck --enable=all +CPPCHECK = cppcheck --quiet --enable=all DOXYGEN = doxygen >/dev/null # Compilation tools @@ -36,8 +40,11 @@ GXXFLAGS = $(DEBUG) -Wall -Wextra -I$(LIBOWLPS_DIR) LD = $(CXX) LDFLAGS = -lstdc++ -lm -lrt -lboost_program_options \ -L$(LIBOWLPS_DIR) -lowlps +OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\" # Targets +.PHONY : all test doc clean purge install uninstall style check + TARGET = owlps-positioning OBJ_TARGET = $(OBJ_DIR)/$(TARGET).o SOURCE_TARGET = $(SRC_DIR)/$(TARGET).cc @@ -113,14 +120,14 @@ SOURCE_TESTS = $(OBJ:$(OBJ_DIR)/%.o=$(TESTS_DIR)/%_test.hh) OBJ_TESTS = $(TESTUTIL_OBJ) $(TESTSETUP_OBJ) INCLUDES_TESTS = $(TESTS_DIR)/valuetraits.hh -all: prepare $(TARGET) +all: $(TARGET) # Generic targets $(TESTS_DIR)/%.o: $(TESTS_DIR)/%.cc $(TESTS_DIR)/%.hh $(CXX) $(GXXFLAGS) $(TESTSGXXFLAGS) -o $@ -c $< $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc $(SRC_DIR)/%.hh - $(CXX) $(GXXFLAGS) -o $@ -c $< + $(MKDIR) $(OBJ_DIR) && $(CXX) $(GXXFLAGS) $(OWLPSFLAGS) -o $@ -c $< %: $(OBJ_DIR)/%.o $(LD) $(LDFLAGS) -o $@ $^ @@ -289,15 +296,12 @@ $(TESTS_OBJ): $(TESTS_XX) $(INCLUDES_TESTS) $(TESTS_TARGET): $(TESTS_OBJ) $(OBJ_TESTS) $(OBJ) $(OBJ_NOTEST) $(LD) $(LDFLAGS) -o $@ $^ -test: prepare $(TESTS_TARGET) +test: $(TESTS_TARGET) @$(TESTS_TARGET) doc: @$(DOXYGEN) $(DOXYFILE) -prepare: - @$(MKDIR) $(OBJ_DIR) - clean: @$(RM) *~ */*~ *.orig */*.orig @$(RM_RECURSIVE_VERBOSE) $(OBJ_DIR) diff --git a/owlps-positioning/TODO b/owlps-positioning/TODO index bae3bfb..edec94a 100644 --- a/owlps-positioning/TODO +++ b/owlps-positioning/TODO @@ -1,7 +1,4 @@ -- Fix Makefile - The 'prepare' target *must* be called before the *.o targets. - - Write a class for Request::type? CalibrationRequest::direction uses a dedicated class Direction, why not Request::type? That would simplify writing of the type to @@ -38,9 +35,6 @@ ° Différencier le pas pour X, Y et Z ? ° Régler le start & stop dans MultilaterationAlgorithm. -- Mobile - Attributs Viterbi ? (Cf. l'ancien clientinfo.hh.) - - Renommages de membres ° InputMedium : °° current_line_nb et get_current_line_nb() @@ -48,10 +42,6 @@ ° Input : get_next_request() −> read_next_request() ° Area : p_min et p_max −> coord_min et coord_max -- Doxygen - ° Pourquoi une description détaillée placée dans un .cc ne s'affiche - pas pour operator<<() ? - - « C++ en action » ° Espaces de noms ? 109 ° Réserver l'espace mémoire des vector avec reserve(). 217 diff --git a/owlps-positioning/src/csvfilereader.cc b/owlps-positioning/src/csvfilereader.cc index 275f888..81607a2 100644 --- a/owlps-positioning/src/csvfilereader.cc +++ b/owlps-positioning/src/csvfilereader.cc @@ -117,7 +117,7 @@ bool CSVFileReader::read_point3d(Point3D &p) } -void CSVFileReader::print_error_cast() +void CSVFileReader::print_error_cast() const { cerr << "Bad value « " diff --git a/owlps-positioning/src/csvfilereader.hh b/owlps-positioning/src/csvfilereader.hh index 7bf5662..87cd41e 100644 --- a/owlps-positioning/src/csvfilereader.hh +++ b/owlps-positioning/src/csvfilereader.hh @@ -21,7 +21,7 @@ protected: token_iterator ; unsigned int current_field_nb ; - void print_error_cast(void) ; + void print_error_cast(void) const ; public: CSVFileReader(const std::string &filename, diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index e9b0be9..d2028bf 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -150,9 +150,9 @@ const Request& InputUDPSocket::get_next_request() calib_request->set_direction(Direction(request.direction)) ; - ReferencePoint position(request.x_position, - request.y_position, - request.z_position) ; + ReferencePoint position(owl_ntohf(request.x_position), + owl_ntohf(request.y_position), + owl_ntohf(request.z_position)) ; const ReferencePoint &reference_point = Stock::find_create_reference_point(position) ; calib_request->set_reference_point(&reference_point) ; diff --git a/owlps-positioning/src/outputcsv.cc b/owlps-positioning/src/outputcsv.cc index e83b9bf..3347963 100644 --- a/owlps-positioning/src/outputcsv.cc +++ b/owlps-positioning/src/outputcsv.cc @@ -1,53 +1,15 @@ #include "outputcsv.hh" -#include "request.hh" #include "resultlist.hh" -#include "mobile.hh" - -#include - -using namespace std ; -/* *** Operations *** */ - - -const string OutputCSV::result_to_csv(const Result &result) +void OutputCSV::write(const Result &result) { - ostringstream csv_line ; - - csv_line << result.get_algorithm() ; - - Point3D position = result.get_position() ; - csv_line - << ';' << position.get_x() - << ';' << position.get_y() - << ';' << position.get_z() ; - - return csv_line.str() ; + file.write_text(result.to_csv() + '\n') ; } -const string OutputCSV::results_to_csv(const ResultList &results) +void OutputCSV::write(const ResultList &results) { - ostringstream csv_line ; - - const Request *const request = results.get_request() ; - if (request != NULL) - { - if (request->get_mobile() != NULL) - csv_line << request->get_mobile()->get_mac_addr() ; - csv_line - << ';' << static_cast(request->get_type()) - << ';' << request->get_time_sent() ; - } - else - csv_line << ";;;" ; - - const vector &res = results.get_results() ; - for (vector::const_iterator r = res.begin() ; r != res.end() ; - ++r) - csv_line << ';' << result_to_csv(*r) ; - - return csv_line.str() ; + file.write_text(results.to_csv() + '\n') ; } diff --git a/owlps-positioning/src/outputcsv.hh b/owlps-positioning/src/outputcsv.hh index 1a3b0dc..4588377 100644 --- a/owlps-positioning/src/outputcsv.hh +++ b/owlps-positioning/src/outputcsv.hh @@ -14,9 +14,6 @@ class OutputCSV: public OutputMedium protected: TextFileWriter file ; - const std::string result_to_csv(const Result &result) ; - const std::string results_to_csv(const ResultList &results) ; - public: OutputCSV(const std::string &filename): file(filename) {} @@ -30,17 +27,5 @@ public: /* *** Operations *** */ -inline void OutputCSV::write(const Result &result) -{ - file.write_text(result_to_csv(result) + '\n') ; -} - - -inline void OutputCSV::write(const ResultList &results) -{ - file.write_text(results_to_csv(results) + '\n') ; -} - - #endif // _OWLPS_POSITIONING_OUTPUTCSV_HH_ diff --git a/owlps-positioning/src/outputudpsocket.cc b/owlps-positioning/src/outputudpsocket.cc index b605209..6093286 100644 --- a/owlps-positioning/src/outputudpsocket.cc +++ b/owlps-positioning/src/outputudpsocket.cc @@ -1,18 +1,15 @@ #include "outputudpsocket.hh" #include "request.hh" #include "resultlist.hh" +#include "posexcept.hh" + +#include #include -#include - -#include -#include +#include // For perror() using namespace std ; -struct hostent *hostInfo ; -struct sockaddr_in serverAddress ; - /* *** Constructors *** */ @@ -22,13 +19,15 @@ OutputUDPSocket::OutputUDPSocket(const string &_remote_host, const uint_fast16_t _remote_port): remote_host(_remote_host), remote_port(_remote_port) { - init_socket() ; + if (! init_socket()) + throw error_opening_output_file("UDP socket") ; + } OutputUDPSocket::~OutputUDPSocket() { - kill_socket() ; + close_socket() ; } @@ -36,56 +35,63 @@ OutputUDPSocket::~OutputUDPSocket() /* *** Operations *** */ -void OutputUDPSocket::write(const ResultList &results) +/** + * @return true if the socket were successfully opened, false in case of + * error. + */ +bool OutputUDPSocket::init_socket() { - // Not implemented + sockfd = owl_create_udp_trx_socket(remote_host.c_str(), remote_port, + &server_info, &client_info) ; + return sockfd >= 0 ; +} + + +/** + * Normally, the socket is closed automatically by the destructor. Use + * this if you want to close the socket prematurely. + * #sockfd is set to -1, even in case of error. + * @return \em true if the socket were successfully closed or were not + * opened. + * @return \em false in case of error. + */ +bool OutputUDPSocket::close_socket() +{ + if (sockfd >= 0) + { + if (close(sockfd)) + { + perror("Cannot close UDP socket") ; + return false ; + } + + sockfd = -1 ; + } + + return true ; } void OutputUDPSocket::write(const Result &result) { - string timestampXYZ; - ostringstream os; - - Point3D position = result.get_position() ; - - os - << position.get_x() << ';' - << position.get_y() << ';' - << position.get_z() ; - timestampXYZ = os.str() ; - - cout << timestampXYZ << '\n' ; - send_data(timestampXYZ); + send_data(result.to_csv()) ; } -void OutputUDPSocket::init_socket() +void OutputUDPSocket::write(const ResultList &results) { - cout << "Initialisation socket..." << endl; - hostInfo = gethostbyname(remote_host.c_str()); - socketDescriptor = socket(AF_INET, SOCK_DGRAM, 0); - serverAddress.sin_family = hostInfo->h_addrtype; - memcpy((char *) &serverAddress.sin_addr.s_addr, - hostInfo->h_addr_list[0], hostInfo->h_length); - serverAddress.sin_port = htons(remote_port); + send_data(results.to_csv()) ; } -void OutputUDPSocket::send_data(string data) +/** + * Sends the text buffer 'data'. + */ +void OutputUDPSocket::send_data(const string &data) { - if (sendto(socketDescriptor, data.c_str(), data.size(), 0, - (struct sockaddr *) &serverAddress, - sizeof(serverAddress)) < 0) - { - cerr << "Émission du message impossible\n"; - close(socketDescriptor); - } -} - - -void OutputUDPSocket::kill_socket() -{ - cout << "Fermeture de la socket..." << endl; - close(socketDescriptor); + ssize_t nsent = sendto(sockfd, data.c_str(), data.size(), 0, + (struct sockaddr *) &server_info, + sizeof(server_info)) ; + if (nsent != static_cast(data.size())) + perror("Error sending result data") ; } diff --git a/owlps-positioning/src/outputudpsocket.hh b/owlps-positioning/src/outputudpsocket.hh index 9502f75..2e8b681 100644 --- a/owlps-positioning/src/outputudpsocket.hh +++ b/owlps-positioning/src/outputudpsocket.hh @@ -5,21 +5,28 @@ #include #include // is not C++ 98 compliant +#include -/// Sends results to an UDP socket +/// Sends results to a remote host by UDP +/** + * The results are sent through an UDP socket as a CSV string value. The + * format used is the same as in OutputCSV. + */ class OutputUDPSocket: public OutputMedium { -private: - int socketDescriptor ; +protected: + int sockfd ; std::string remote_host ; uint_fast16_t remote_port ; + struct sockaddr_in server_info ; + struct sockaddr_in client_info ; + /** @name Operations */ //@{ /// Initialises the socket - void init_socket(void) ; - void kill_socket(void) ; - void send_data(std::string msg) ; + bool init_socket(void) ; + void send_data(const std::string &data) ; //@} public: @@ -29,9 +36,10 @@ public: /** @name Operations */ //@{ - /// Initialises the socket void write(const Result &result) ; void write(const ResultList &results) ; + /// Closes the socket + bool close_socket(void) ; //@} } ; diff --git a/owlps-positioning/src/result.cc b/owlps-positioning/src/result.cc index a3f3ea3..1173b0c 100644 --- a/owlps-positioning/src/result.cc +++ b/owlps-positioning/src/result.cc @@ -1,6 +1,10 @@ #include "result.hh" #include "request.hh" +#include + +using namespace std ; + /* *** Operators *** */ @@ -27,7 +31,25 @@ bool Result::operator==(const Result &source) const -std::ostream& operator<<(std::ostream &os, const Result &r) +/** + * @return the result as a CSV string, \em without trailing '\n'. + */ +const string Result::to_csv() const +{ + ostringstream csv_line ; + + csv_line + << algorithm + << ';' << position.get_x() + << ';' << position.get_y() + << ';' << position.get_z() ; + + return csv_line.str() ; +} + + + +std::ostream& operator<<(ostream &os, const Result &r) { os << "The result of the algorithm " << r.algorithm diff --git a/owlps-positioning/src/result.hh b/owlps-positioning/src/result.hh index 13783a1..ac7f223 100644 --- a/owlps-positioning/src/result.hh +++ b/owlps-positioning/src/result.hh @@ -32,6 +32,12 @@ public: bool operator!=(const Result &source) const ; //@} + /** @name Conversion accessors */ + //@{ + /// Convert to a CSV string + const std::string to_csv(void) const ; + //@} + /// Displays a Result friend std::ostream& operator<<(std::ostream &os, const Result &r) ; } ; diff --git a/owlps-positioning/src/resultlist.cc b/owlps-positioning/src/resultlist.cc index a9492a5..58a6953 100644 --- a/owlps-positioning/src/resultlist.cc +++ b/owlps-positioning/src/resultlist.cc @@ -1,5 +1,8 @@ #include "resultlist.hh" #include "request.hh" +#include "mobile.hh" + +#include using namespace std ; @@ -39,6 +42,36 @@ bool ResultList::operator==(const ResultList &source) const +/* *** Conversion accessors *** */ + + +/** + * @return the results as a CSV string, \em without trailing '\n'. + */ +const string ResultList::to_csv() const +{ + ostringstream csv_line ; + + if (request != NULL) + { + if (request->get_mobile() != NULL) + csv_line << request->get_mobile()->get_mac_addr() ; + csv_line + << ';' << static_cast(request->get_type()) + << ';' << request->get_time_sent() ; + } + else + csv_line << ";;;" ; + + for (vector::const_iterator r = results.begin() ; + r != results.end() ; ++r) + csv_line << ';' << r->to_csv() ; + + return csv_line.str() ; +} + + + ostream& operator<<(ostream &os, const ResultList &r) { if (r.request == NULL) diff --git a/owlps-positioning/src/resultlist.hh b/owlps-positioning/src/resultlist.hh index 63a453d..84a98b1 100644 --- a/owlps-positioning/src/resultlist.hh +++ b/owlps-positioning/src/resultlist.hh @@ -7,6 +7,8 @@ class Request ; #include #include +/// \brief List of \link Result results \endlink of a single Request, +/// computed by one or more positioning algorithm class ResultList { protected: @@ -39,6 +41,12 @@ public: bool operator!=(const ResultList &source) const ; //@} + /** @name Conversion accessors */ + //@{ + /// Convert to a CSV string + const std::string to_csv(void) const ; + //@} + /// Displays a ResultList friend std::ostream& operator<<(std::ostream &os, const ResultList &r) ; diff --git a/owlps-positioning/src/textfilereader.cc b/owlps-positioning/src/textfilereader.cc index 6ae90c6..9f9f2cb 100644 --- a/owlps-positioning/src/textfilereader.cc +++ b/owlps-positioning/src/textfilereader.cc @@ -1,6 +1,8 @@ #include "textfilereader.hh" #include "posexcept.hh" +#include + using namespace std ; @@ -15,15 +17,26 @@ using namespace std ; TextFileReader::TextFileReader(const string &_file_name): file_name(_file_name), current_line_nb(0) { - file.open(file_name.c_str()) ; - if (! file) - throw error_opening_input_file(file_name) ; + if (file_name == "-") + { + file_buf = file.rdbuf() ; + file.std::ios::rdbuf(std::cin.rdbuf()) ; + } + else + { + file.open(file_name.c_str()) ; + if (! file) + throw error_opening_input_file(file_name) ; + } } TextFileReader::~TextFileReader() { - file.close() ; + if (file_name == "-") + file.std::ios::rdbuf(file_buf) ; + else + file.close() ; } diff --git a/owlps-positioning/src/textfilereader.hh b/owlps-positioning/src/textfilereader.hh index 9a55f53..7b5fdae 100644 --- a/owlps-positioning/src/textfilereader.hh +++ b/owlps-positioning/src/textfilereader.hh @@ -4,12 +4,20 @@ #include #include -/// Read text from a file, line by line +/// Reads text from a file, line by line +/** + * If the file name is a dash ('-'), the standard input is used. + */ class TextFileReader { protected: + /// Name of the input file std::string file_name ; + /// Stream associated with the file std::ifstream file ; +/// Original rdbuf of the stream + std::streambuf *file_buf ; + /// Number of the last line read unsigned int current_line_nb ; /// Checks if the file is readable and closes it if not diff --git a/owlps-positioning/src/textfilewriter.cc b/owlps-positioning/src/textfilewriter.cc index 30aadb1..a347c31 100644 --- a/owlps-positioning/src/textfilewriter.cc +++ b/owlps-positioning/src/textfilewriter.cc @@ -2,6 +2,8 @@ #include "configuration.hh" #include "posexcept.hh" +#include + using namespace std ; @@ -10,21 +12,33 @@ using namespace std ; /** - * @param _file_name The name of the file to open. + * @param _file_name The name of the file to open ('-' for the standard + * output). * @throw error_opening_input_file if the file cannot be opened. */ TextFileWriter::TextFileWriter(const string &_file_name): file_name(_file_name) { - file.open(file_name.c_str()) ; - if (! file) - throw error_opening_output_file(file_name) ; + if (file_name == "-") + { + file_buf = file.rdbuf() ; + file.std::ios::rdbuf(std::cout.rdbuf()) ; + } + else + { + file.open(file_name.c_str()) ; + if (! file) + throw error_opening_output_file(file_name) ; + } } TextFileWriter::~TextFileWriter() { - file.close() ; + if (file_name == "-") + file.std::ios::rdbuf(file_buf) ; + else + file.close() ; } diff --git a/owlps-positioning/src/textfilewriter.hh b/owlps-positioning/src/textfilewriter.hh index cd2fff6..09a5466 100644 --- a/owlps-positioning/src/textfilewriter.hh +++ b/owlps-positioning/src/textfilewriter.hh @@ -4,12 +4,19 @@ #include #include -/// Write text to a file +/// Writes text to a file +/** + * If the file name is a dash ('-'), the standard output is used. + */ class TextFileWriter { private: + /// Name of the output file std::string file_name ; + /// Stream associated with the file std::ofstream file ; + /// Original rdbuf of the stream + std::streambuf *file_buf ; public: TextFileWriter(const std::string &_file_name) ; diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 0d777ec..4e96d09 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -72,10 +72,11 @@ void UserInterface::fill_options() void UserInterface::fill_cli_options() { cli_options->add_options() - ("help,h", "Print help") + ("help,h", "Print help.") + ("version,V", "Print version information.") ("config-file,f", po::value() ->default_value(DEFAULT_CONFIG_FILE_NAME), - "Alternative configuration file") + "Alternative configuration file.") ; // End of options } @@ -187,7 +188,7 @@ this option more than once. Allowed: Terminal, CSV, UDP. \ If this option is absent, results will be printed on the terminal.") ("output.csv-file", po::value(), "CSV file to use for output (when output.medium = CSV).") - ("output.udp-host", po::value(), + ("output.udp-host", po::value(), "Host to which the UDP data is sent (when output.medium = UDP).") ("output.udp-port", po::value() ->default_value(MOBILE_DEFAULT_PORT), @@ -214,7 +215,7 @@ void UserInterface::fill_misc_options() void UserInterface::parse_options() { parse_command_line() ; - print_usage_and_exit_if_requested() ; + print_information_and_exit_if_requested() ; parse_file() ; @@ -231,13 +232,34 @@ void UserInterface::parse_command_line() const } -void UserInterface::print_usage_and_exit_if_requested() const +void UserInterface::print_information_and_exit_if_requested() const { + bool exit_program = false ; + + // Print version if requested + if (Configuration::is_configured("version")) + { + cout + << "This is OwlPS Positioning, part of the Open Wireless" + << " Positioning System project.\nVersion: " << +#ifdef OWLPS_VERSION + OWLPS_VERSION +#else // OWLPS_VERSION + "unknown version" +#endif // OWLPS_VERSION + << ".\n" ; + exit_program = true ; + } + + // Print usage if requested if (Configuration::is_configured("help")) { cout << *cli_options ; - exit(0) ; + exit_program = true ; } + + if (exit_program) + exit(0) ; } diff --git a/owlps-positioning/src/userinterface.hh b/owlps-positioning/src/userinterface.hh index c57bfd8..bf0890e 100644 --- a/owlps-positioning/src/userinterface.hh +++ b/owlps-positioning/src/userinterface.hh @@ -36,8 +36,8 @@ protected: void parse_command_line(void) const ; void parse_file(void) const ; - /// If help was requested by user, displays accepted options and exit - void print_usage_and_exit_if_requested(void) const ; + /// Print usage and/or version information if requested by the user + void print_information_and_exit_if_requested(void) const ; //@} public: diff --git a/owlps-positioning/src/waypoint.cc b/owlps-positioning/src/waypoint.cc index 07af7fe..506c86c 100644 --- a/owlps-positioning/src/waypoint.cc +++ b/owlps-positioning/src/waypoint.cc @@ -76,7 +76,7 @@ bool Waypoint::operator==(const Waypoint &wp) const } -Waypoint::operator string() const +Waypoint::operator std::string() const { ostringstream csv ; csv << (Point3D) *this ;