Merge branch dev (v1.1.8) into dev-drone

Use new constants', types' and functions' names.

Conflicts:
	owlps-client/owlps-client.c
This commit is contained in:
Matteo Cypriani 2011-12-01 16:29:12 +01:00
commit 7b7766ab5b
39 changed files with 1962 additions and 375 deletions

View File

@ -1,20 +1,28 @@
ifndef MAKE
MAKE = make
endif
.PHONY: \
all c clean purge help \
libowlps \
libowlps-client \
libowlps-resultreader \
owlps-client \
owlps-listener \
owlps-aggregator \
owlps-udp-to-http \
owlps-positioning \
install \
install-owlps-client \
install-owlps-listener \
install-owlps-aggregator \
install-owlps-udp-to-http \
install-owlps-positioning \
uninstall \
uninstall-owlps-client \
uninstall-owlps-listener \
uninstall-owlps-aggregator \
uninstall-owlps-udp-to-http \
uninstall-owlps-positioning
## Compilation ##
@ -26,22 +34,28 @@ all: \
c: \
libowlps \
libowlps-client \
libowlps-resultreader \
owlps-client \
owlps-listener \
owlps-aggregator
owlps-aggregator \
owlps-udp-to-http
libowlps:
@make -C $@
@$(MAKE) -C $@
libowlps-client: libowlps
@make -C $@
@$(MAKE) -C $@
libowlps-resultreader: libowlps
@$(MAKE) -C $@
owlps-client: libowlps libowlps-client
@make -C $@
@$(MAKE) -C $@
owlps-listener: libowlps libowlps-client
@make -C $@
@$(MAKE) -C $@
owlps-aggregator: libowlps
@make -C $@
@$(MAKE) -C $@
owlps-udp-to-http: libowlps libowlps-resultreader
@$(MAKE) -C $@
owlps-positioning: libowlps
@make -C $@
@$(MAKE) -C $@
## Installation ##
@ -51,18 +65,21 @@ install : \
install-owlps-client \
install-owlps-listener \
install-owlps-aggregator \
install-owlps-udp-to-http \
install-owlps-positioning
install-libowlps:
@make -C $(subst install-,,$@) install
@$(MAKE) -C $(subst install-,,$@) install
install-owlps-client: install-libowlps
@make -C $(subst install-,,$@) install
@$(MAKE) -C $(subst install-,,$@) install
install-owlps-listener: install-libowlps
@make -C $(subst install-,,$@) install
@$(MAKE) -C $(subst install-,,$@) install
install-owlps-aggregator: install-libowlps
@make -C $(subst install-,,$@) install
@$(MAKE) -C $(subst install-,,$@) install
install-owlps-udp-to-http: install-libowlps
@$(MAKE) -C $(subst install-,,$@) install
install-owlps-positioning: install-libowlps
@make -C $(subst install-,,$@) install
@$(MAKE) -C $(subst install-,,$@) install
## Uninstallation ##
@ -72,37 +89,44 @@ uninstall : \
uninstall-owlps-client \
uninstall-owlps-listener \
uninstall-owlps-aggregator \
uninstall-owlps-udp-to-http \
uninstall-owlps-positioning
uninstall-libowlps:
@make -C $(subst uninstall-,,$@) uninstall
@$(MAKE) -C $(subst uninstall-,,$@) uninstall
uninstall-owlps-client:
@make -C $(subst uninstall-,,$@) uninstall
@$(MAKE) -C $(subst uninstall-,,$@) uninstall
uninstall-owlps-listener:
@make -C $(subst uninstall-,,$@) uninstall
@$(MAKE) -C $(subst uninstall-,,$@) uninstall
uninstall-owlps-aggregator:
@make -C $(subst uninstall-,,$@) uninstall
@$(MAKE) -C $(subst uninstall-,,$@) uninstall
uninstall-owlps-udp-to-http:
@$(MAKE) -C $(subst uninstall-,,$@) uninstall
uninstall-owlps-positioning:
@make -C $(subst uninstall-,,$@) uninstall
@$(MAKE) -C $(subst uninstall-,,$@) uninstall
## Cleaning ##
clean :
@make -C libowlps clean
@make -C libowlps-client clean
@make -C owlps-client clean
@make -C owlps-listener clean
@make -C owlps-aggregator clean
@make -C owlps-positioning clean
@$(MAKE) -C libowlps clean
@$(MAKE) -C libowlps-client clean
@$(MAKE) -C libowlps-resultreader clean
@$(MAKE) -C owlps-client clean
@$(MAKE) -C owlps-listener clean
@$(MAKE) -C owlps-aggregator clean
@$(MAKE) -C owlps-udp-to-http clean
@$(MAKE) -C owlps-positioning clean
purge :
@make -C libowlps purge
@make -C libowlps-client purge
@make -C owlps-client purge
@make -C owlps-listener purge
@make -C owlps-aggregator purge
@make -C owlps-positioning purge
@$(MAKE) -C libowlps purge
@$(MAKE) -C libowlps-client purge
@$(MAKE) -C libowlps-resultreader purge
@$(MAKE) -C owlps-client purge
@$(MAKE) -C owlps-listener purge
@$(MAKE) -C owlps-aggregator purge
@$(MAKE) -C owlps-udp-to-http purge
@$(MAKE) -C owlps-positioning purge
## Help ##

49
TODO
View File

@ -1,11 +1,21 @@
* Global
- Known bugs
° libconfuse bugs (Listener & Aggregator):
. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=639074
. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=639115
- Rename some fields in the structures
° start_time -> rx_time, first_rx_time
- Eliminate remaining exit() calls to avoid memory leaks on exit.
- Add option dump-configuration (displays the config & exits).
- Makefiles:
° Translate comments & help.
° Merge Makefile and Makefile_atheros*. Use template makefiles,
autohell, cmake…?
- Use string for network exchanges?
- Use a string for positioning requests
Instead of a binary packet, use a CSV string containing the request
information. This will allow easy developments of clients in other
languages.
- Mark arguments as const in function headers if needed
Mostly done in the owlps-positioning C++ code (should check that),
but not constantly in C modules.
@ -52,30 +62,56 @@
Get rid of the "Cannot open configuration file" error, in quiet
mode and when the default configuration file has to be used (no
file specified by the user with -f).
- Listen for autocalibration requests without sending requests?
- Filter the number of implicit packets per mobile?
Currently, in passive or mixed mode, *all* the receive packets are
transmitted to the aggregator.
- Option "read-only autocalibration"?
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.
- BSD port
http://www.unixgarden.com/index.php/programmation/introduction-a-la-programmation-wifi-en-c-sous-netbsd
- Use the "official" radiotap parser? (Expat license)
http://git.sipsolutions.net/?p=radiotap.git
* Client
- Handle signals.
- Add verbose & quiet options.
- Log sent requests?
- Allow to use a string for the direction?
Could be nice, but probably useless.
* UDP to HTTP
- Command-line options (port numbers, -v/-q, -h, -V).
- Delete inactive clients after a given amount of time.
- Refactor prepare_answer().
* Positioning
- Known bugs
° Cannot compute the error (Real) with autocalibration requests.
- Algorithms
° Add to the result the information "area error" (whether on not the
computed result is in the same room as the real position).
° Delete reference points after a given amount of time. This is to
avoid meaningless old reference points, for instance if an AP was
shut down.
° Handle the power and antenna gain difference between the
calibration mobile (or pseudo-mobile, for autocalibration) and the
mobile to position.
° MinMax: use a different step for X, Y and Z?
- Autocalibration
° Generate reference points in 3D.
° Check what happens with >4 APs, and fix it. We certainly should
select APs not only by the angle proximity, but also by the
distance proximity. Maybe implement three options: angle, distance,
and angle + distance.
° Handle 2 APs, not only >2 APs.
° Find why some CalibrationRequest were not deleted when
calling Stock::delete_calibration_request() (via
@ -109,7 +145,12 @@
with relative path in owlps-positioning.cfg in the same directory).
- Optimisation & code improvement
° Multithread algorithm calls.
° Multithreading:
. algorithm (parallelize computation of the different algorithms
for the same request) ;
. and/or requests (parallelize computation of several requests).
It would be possible (overkill?) to have a group of worker threads
and a job queue.
° ReferencePoint: the request list should be an unordered_set
instead of a vector, to guarantee the unicity of the elements.
° Pre-allocate vectors' memory with reserve().

View File

@ -23,6 +23,7 @@ OBJS=$(LIB_CIBLE).o
# Flags
LIBOWLPS_DIR = ../libowlps
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O -I$(LIBOWLPS_DIR)
#CFLAGS += -g -O0
CFLAGS += -D DEBUG
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)

View File

@ -26,6 +26,7 @@ OBJS=$(LIB_CIBLE).o
# Flags
LIBOWLPS_DIR = ../libowlps
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O -I$(LIBOWLPS_DIR)
#CFLAGS += -g -O0
CFLAGS += -D DEBUG
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)

View File

@ -26,6 +26,7 @@ OBJS=$(LIB_CIBLE).o
# Flags
LIBOWLPS_DIR = ../libowlps
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O -I$(LIBOWLPS_DIR)
#CFLAGS += -g -O0
CFLAGS += -D DEBUG
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)

View File

@ -16,10 +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(const char *const dest_ip,
const uint_fast16_t dest_port,
struct sockaddr_in *const server,
const char *const iface)
int owl_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 ;
@ -29,12 +29,12 @@ int owlclient_create_trx_socket(const char *const dest_ip,
{
perror("Error! Cannot create UDP sending socket to the aggregation"
" server") ;
exit(ERR_CREATING_SOCKET) ;
exit(OWL_ERR_SOCKET_CREATE) ;
}
// If we specified an interface name
if (iface != NULL && iface[0] != '\0')
owlclient_use_iface(sockfd, iface) ;
owl_use_iface(sockfd, iface) ;
return sockfd ;
}
@ -42,7 +42,7 @@ int owlclient_create_trx_socket(const char *const dest_ip,
/* Selects 'iface' as sending interface for the socket 'sockfd'. */
void owlclient_use_iface(const int sockfd, const char *const iface)
void owl_use_iface(const int sockfd, const char *const iface)
{
#ifdef __GLIBC__
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, iface,
@ -66,12 +66,12 @@ void owlclient_use_iface(const int sockfd, const char *const iface)
* nb_pkt: number of packets to transmit.
* delay: delay between two transmissions, in milliseconds.
*/
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 owl_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 ;
@ -83,13 +83,13 @@ void owlclient_send_request(const int sockfd,
#endif // DEBUG
// Transmit first packet:
owlclient_send_packet(sockfd, server, packet, packet_size) ;
owl_send_packet(sockfd, server, packet, packet_size) ;
// Transmit remaining packets (if any):
for (i = 0 ; i < nb_pkt - 1 ; ++i)
{
usleep(delay * 1000) ; // Wait during the wanted delay
owlclient_send_packet(sockfd, server, packet, packet_size) ;
owl_msleep(delay) ; // Wait during the wanted delay
owl_send_packet(sockfd, server, packet, packet_size) ;
}
#ifdef DEBUG
@ -99,10 +99,10 @@ void owlclient_send_request(const int sockfd,
void owlclient_send_packet(const int sockfd,
const struct sockaddr_in *const server,
const void *const packet,
const uint_fast16_t packet_size)
void owl_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,
@ -110,7 +110,7 @@ void owlclient_send_packet(const int sockfd,
if (nsent != (ssize_t) packet_size)
{
perror("Error sending data to the aggregation server") ;
exit(ERR_SENDING_INFO) ;
exit(OWL_ERR_SOCKET_SEND) ;
}
#ifdef DEBUG

View File

@ -8,27 +8,23 @@
#include <owlps.h>
/* Error codes */
#define ERR_CREATING_SOCKET 151 // Error when creating output socket
#define ERR_SENDING_INFO 152 // Error sending a localisation request
/* Function headers */
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) ;
int owl_create_trx_socket(const char *const dest_ip,
const uint_fast16_t dest_port,
struct sockaddr_in *const server,
const char *const iface) ;
void owl_use_iface(const int sockfd, const char *const iface) ;
void owl_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 owl_send_packet(const int sockfd,
const struct sockaddr_in *const server,
const void *const packet,
const uint_fast16_t packet_size) ;
#endif // _LIBOWLPS_CLIENT_

View File

@ -0,0 +1,82 @@
# Compilateur
COLORGCC := $(shell which colorgcc >/dev/null 2>&1 ; echo $$?)
ifeq ($(COLORGCC), 0)
CC = colorgcc
endif
# Autres outils
AR = ar
RANLIB = ranlib
RM = rm -f
# Variables générales
LIB_CIBLE = libowlps-resultreader
VERSION = 1.0
# Cibles à construire
STATIC = $(LIB_CIBLE).a
HEADER = owlps-resultreader.h
EXAMPLE = owlps-resultreader-udp
# Composition de la bibliothèque
OBJS = $(LIB_CIBLE).o
# Flags
LIBOWLPS_DIR = ../libowlps
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O -I$(LIBOWLPS_DIR)
#CFLAGS += -g -O0
CFLAGS += -D DEBUG
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC
#STRIPFLAGS = -Wl,-s
#LDFLAGS =
## Cibles de compilation standard ##
.PHONY : all static clean purge help
all : static example
static : $(STATIC)
example : $(EXAMPLE)
# Cancel implicit make rule
%: %.c
%.o : %.c $(HEADER)
$(CC) $(XCFLAGS) -c $<
% : %.o $(HEADER) $(STATIC)
$(CC) $(STRIPFLAGS) $(XCFLAGS) -o $@ $< \
$(STATIC) -L$(LIBOWLPS_DIR) -lowlps -lrt
# Compilation de la bibliothèque statique
$(STATIC) : $(OBJS)
$(RM) $@
$(AR) cru $@ $^
$(RANLIB) $@
## Nettoyage ##
clean :
@$(RM) *~ *.o *.d
purge : clean
@$(RM) $(STATIC) $(EXAMPLE)
## Aide ##
help :
@echo "Bibliothèques nécessaires à la compilation :"
@echo " libowlps-dev"
@echo
@echo "Cibles possibles :"
@echo " static : Compile la bibliothèque statique (.a)."
@echo " example : Compile le programme d'exemple."
@echo " (Cible par défaut : static et example.)"
@echo
@echo " clean : Supprime les fichiers temporaires."
@echo " purge : Supprime le résultat de la compilation."

View File

@ -0,0 +1,438 @@
#include "owlps-resultreader.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#define CSV_DELIMITER ";"
/*
* Receives a result from the socket of file descriptor 'sockfd', fills
* an owl_result structure with the received information, and returns a
* pointer to it.
*
* Note that the new owl_result is allocated with malloc() and must be
* deleted using free().
*
* In case of error, a message is printed, except if owl_run (from
* libowlps) is false, and NULL is returned.
*/
owl_result* owl_receive_position(int sockfd)
{
ssize_t nread ; // recvfrom return value
char csv[OWL_CSV_RESULT_STRLEN] ; // Read string
nread = recvfrom(sockfd, &csv, OWL_CSV_RESULT_STRLEN,
0, NULL, NULL) ;
if (nread <= 0)
{
if (owl_run)
perror("No request received from listener") ;
return NULL ;
}
return owl_fill_result(csv) ;
}
/*
* Splits the 'csv' string received from OwlPS Positioning and stores
* the fields in a new owl_result, and returns a pointer to it (or NULL
* in case of error).
*
* Note that the new owl_result is allocated with malloc() and must be
* deleted using free().
*
* Handled CSV format:
* Mobile_MAC;Request_type;Request_timestamp;Algorithm;X;Y;Z;Error;Area
* The Request_timestamp format is:
* seconds.nanoseconds
* The Area field can be empty.
*/
owl_result* owl_fill_result(char *csv)
{
char *csv_field = NULL ;
owl_result *result = NULL ;
result = malloc(sizeof(owl_result)) ;
memset(result, 0, sizeof(*result)) ;
/* Mobile MAC address */
csv_field = strsep(&csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the mobile's MAC address from the CSV"
" string (empty string?)!\n") ;
goto error ;
}
result->mobile_mac_addr =
strndup(csv_field, OWL_ETHER_ADDR_STRLEN) ;
/* Request type */
csv_field = strsep(&csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the request type from the CSV string!\n") ;
goto error ;
}
result->request_type = atoi(csv_field) ;
/* Timestamp */
// Seconds
csv_field = strsep(&csv, ".") ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the timestamp (seconds) from the CSV"
" string!\n") ;
goto error ;
}
result->mobile_timestamp.tv_sec = atol(csv_field) ;
// Nanoseconds
csv_field = strsep(&csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the timestamp (nanoseconds) from the CSV"
" string!\n") ;
goto error ;
}
result->mobile_timestamp.tv_nsec = atol(csv_field) ;
/* Algorithm results */
do
{
owl_algorithm_result *current_algo =
owl_fill_algorithm_result(&csv) ;
if (current_algo == NULL)
{
fprintf(stderr, "Error reading the algorithm #%d!\n",
result->nb_results + 1) ;
break ;
}
// Insert the current algorithm at the begining of the list
current_algo->next = result->results ;
result->results = current_algo ;
++result->nb_results ;
}
while (csv) ;
return result ; // Success
error:
owl_free_result(result) ;
return NULL ;
}
/*
* Splits the 'csv' string, stores the fields in a new
* owl_algorithm_result, and returns a pointer to it (or NULL
* in case of error).
*
* Note that the new owl_algorithm_result is allocated with malloc()
* and must be deleted using free().
*
* 'csv' must follow this CSV format:
* Algorithm;X;Y;Z;Error;Area
* The Area field can be empty.
*/
owl_algorithm_result* owl_fill_algorithm_result(char **csv)
{
owl_algorithm_result *algo ;
char *csv_field = NULL ;
algo = malloc(sizeof(owl_algorithm_result)) ;
memset(algo, 0, sizeof(*algo)) ;
// Algorithm name
csv_field = strsep(csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the algorithm name from the CSV string!\n") ;
goto error ;
}
algo->algorithm =
strndup(csv_field, OWL_ALGORITHM_STRLEN) ;
// X coordinate
csv_field = strsep(csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the X coordinate from the CSV string!\n") ;
goto error ;
}
algo->x = atof(csv_field) ;
// Y coordinate
csv_field = strsep(csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the Y coordinate from the CSV string!\n") ;
goto error ;
}
algo->y = atof(csv_field) ;
// Z coordinate
csv_field = strsep(csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the Z coordinate from the CSV string!\n") ;
goto error ;
}
algo->z = atof(csv_field) ;
// Distance error
csv_field = strsep(csv, CSV_DELIMITER) ;
if (! csv_field)
{
fprintf(stderr,
"Error reading the distance error from the CSV string!\n") ;
goto error ;
}
algo->error = atof(csv_field) ;
// Area name (optional)
csv_field = strsep(csv, CSV_DELIMITER) ;
if (csv_field)
algo->area = strndup(csv_field, OWL_AREA_STRLEN) ;
return algo ; // Success
error:
owl_free_algorithm_result(algo) ;
return NULL ;
}
/*
* Converts an owl_result back to a CSV string.
* 'dst' must be an allocated string of at least OWL_CSV_RESULT_STRLEN
* characters.
*
* CSV format:
* Mobile_MAC;Request_type;Request_timestamp;Nb_algo;Algo_1;;Algo_n
* Nb_algo is the number of algorithms in the result.
* The format of Algo_i is documented in owl_algorithm_result_to_csv().
*/
void owl_result_to_csv(char dst[OWL_CSV_RESULT_STRLEN],
const owl_result *const src)
{
size_t dst_len ;
char timestamp_str[OWL_TIMESTAMP_STRLEN] ;
assert(src) ;
owl_timestamp_to_string(timestamp_str, src->mobile_timestamp) ;
snprintf(dst, OWL_CSV_RESULT_REQUEST_STRLEN,
"%s;%"PRIu8";%s;%u",
src->mobile_mac_addr,
src->request_type,
timestamp_str,
src->nb_results) ;
dst_len = strlen(dst) ;
owl_algorithm_result *algo = src->results ;
while (algo)
{
char algo_str[OWL_CSV_ALGORITHM_RESULT_STRLEN] ;
owl_algorithm_result_to_csv(algo_str, algo) ;
dst[dst_len++] = ';' ;
strncpy(dst + dst_len, algo_str, OWL_CSV_ALGORITHM_RESULT_STRLEN) ;
dst_len += strlen(algo_str) ;
algo = algo->next ;
}
}
/*
* Converts an owl_algorithm_result back to a CSV string.
* 'dst' must be an allocated string of at least
* OWL_CSV_ALGORITHM_RESULT_STRLEN characters.
*
* CSV format:
* Algorithm_name;X;Y;Z;Error;Area_name
* Error is the distance from the true coordinates of the mobile, if
* known; if unknown, Error is set to -1.
* Area_name is the name of the area or room in which the mobile is (may
* be empty).
*/
void
owl_algorithm_result_to_csv(char dst[OWL_CSV_ALGORITHM_RESULT_STRLEN],
const owl_algorithm_result *const src)
{
assert(src) ;
snprintf(dst, OWL_CSV_ALGORITHM_RESULT_STRLEN,
"%s;%f;%f;%f;%f;%s",
src->algorithm,
src->x,
src->y,
src->z,
src->error,
src->area ? src->area : "") ;
}
/*
* Converts an owl_result back to a CSV string, in a simplified format.
* Only the *first* algorithm in the result's algorithm list will be
* included in the string.
* 'dst' must be an allocated string of at least
* OWL_CSV_RESULT_SIMPLE_STRLEN characters.
*
* CSV format:
* Mobile_MAC;First_algorithm
* First_algorithm is the first algorithm in src->results. Its format
* is documented in owl_algorithm_result_to_csv_simple().
*/
void owl_result_to_csv_simple(char dst[OWL_CSV_RESULT_SIMPLE_STRLEN],
const owl_result *const src)
{
size_t dst_len ;
char algo_str[OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN] ;
assert(src) ;
strncpy(dst, src->mobile_mac_addr, OWL_ETHER_ADDR_STRLEN) ;
dst[OWL_ETHER_ADDR_STRLEN - 1] = ';' ;
dst_len = OWL_ETHER_ADDR_STRLEN ;
if (! src->results)
return ;
owl_algorithm_result_to_csv_simple(algo_str, src->results) ;
strncpy(dst + dst_len, algo_str,
OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN) ;
}
/*
* Converts an owl_algorithm_result back to a CSV string, in a
* simplified format.
* 'dst' must be an allocated string of at least
* OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN characters.
*
* CSV format:
* X;Y;Z;Area_name
* Area_name is the name of the area or room in which the mobile is (may
* be empty).
*/
void owl_algorithm_result_to_csv_simple
(char dst[OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN],
const owl_algorithm_result *const src)
{
assert(src) ;
snprintf(dst, OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN,
"%f;%f;%f;%s",
src->x,
src->y,
src->z,
src->area ? src->area : "") ;
}
/*
* Prints an owl_result to the given stream.
*/
void owl_fprint_result(FILE *stream, const owl_result *const src)
{
char timestamp_str[OWL_TIMESTAMP_STRLEN] ;
assert(src) ;
owl_timestamp_to_string(timestamp_str, src->mobile_timestamp) ;
fprintf(stream,
"Mobile MAC: %s\n"
"Request type: %"PRIu8"\n"
"Mobile timestamp: %s\n"
"%u results:\n"
,
src->mobile_mac_addr,
src->request_type,
timestamp_str,
src->nb_results) ;
owl_algorithm_result *algo = src->results ;
while (algo)
{
owl_fprint_algorithm_result(stream, algo) ;
algo = algo->next ;
}
}
/*
* Prints an owl_algorithm_result to the given stream.
*/
void owl_fprint_algorithm_result(FILE *stream,
const owl_algorithm_result *const src)
{
assert(src) ;
fprintf(stream,
"* Algorithm: %s\n"
" X: %f\n"
" Y: %f\n"
" Z: %f\n"
" Error: %f\n"
" Area: %s\n"
,
src->algorithm,
src->x,
src->y,
src->z,
src->error,
src->area ? src->area : ""
) ;
}
/*
* Frees the memory allocated by an owl_result. The 'results' and
* 'mobile_mac_addr' fields *must* be defined, either to NULL or to a
* valid memory block allocated with malloc().
* Note that the pointer will not set to NULL.
*/
void owl_free_result(owl_result *result)
{
if (! result)
return ;
while (result->results)
{
owl_algorithm_result *algo = result->results ;
result->results = algo->next ;
owl_free_algorithm_result(algo) ;
}
free(result->mobile_mac_addr) ;
free(result) ;
}
/*
* Frees the memory allocated by a single owl_algorithm_result (*not*
* recursively). The 'algorithm' and 'area' fields *must* be defined,
* either to NULL or to a valid memory block allocated with malloc().
* Note that the pointer will not set to NULL.
*/
void owl_free_algorithm_result(owl_algorithm_result *algo)
{
if (! algo)
return ;
free(algo->algorithm) ;
free(algo->area) ;
free(algo) ;
}

View File

@ -0,0 +1,47 @@
/*
* This is a simple program to demonstrate the use of
* libowlps-resultreader-udp.
* It must be linked against libowlps and its dependencies
* (see the Makefile).
*/
#include "owlps-resultreader.h"
#include <signal.h>
#include <unistd.h>
int main(void)
{
struct sigaction action ; // Signal handler structure
owl_result *result ;
int sockfd ;
/* Set up signal handlers */
action.sa_flags = 0 ;
sigemptyset(&action.sa_mask) ;
action.sa_handler = owl_sigint_handler ;
sigaction(SIGINT, &action, NULL) ;
action.sa_handler = owl_sigterm_handler ;
sigaction(SIGTERM, &action, NULL) ;
/* Open the socket */
sockfd = owl_create_udp_listening_socket(OWL_DEFAULT_RESULT_PORT) ;
if (sockfd < 0)
return 1 ;
/* Read loop */
owl_run = owl_true ;
while (owl_run)
{
if (! (result = owl_receive_position(sockfd)))
return 1 ;
owl_print_result(result) ;
owl_free_result(result) ;
printf("--------------\n") ;
}
/* Cleaning */
close(sockfd) ;
return 0 ;
}

View File

@ -0,0 +1,105 @@
/*
* This library provides functions to read results sent on UDP by OwlPS
* Positioning.
* See the example program owlps-resultreader-udp.c.
*/
#ifndef _LIBOWLPS_RESULTREADER_CSV_
#define _LIBOWLPS_RESULTREADER_CSV_
#include <owlps.h>
#include <stdio.h>
#include <inttypes.h>
/* Maximum size of a result CSV string sent by OwlPS Positioning.
* Request's information:
* MAC, request type (2 chars), timestamp, ';'
* Plus, for each algorithm:
* Name, three coordinates, error (we assume the same size as the
* coordinates), area name, ';'
* Let's define OWL_NB_ALGORITHMS as the number of implemented
* algorithms (this is ugly).
*/
#define OWL_NB_ALGORITHMS 10
#define OWL_CSV_RESULT_REQUEST_STRLEN \
(OWL_ETHER_ADDR_STRLEN + OWL_TIMESTAMP_STRLEN + 3)
#define OWL_CSV_ALGORITHM_RESULT_STRLEN \
(OWL_ALGORITHM_STRLEN + 4 * OWL_COORDINATE_STRLEN + \
OWL_AREA_STRLEN + 1)
#define OWL_CSV_RESULT_STRLEN \
(OWL_CSV_RESULT_REQUEST_STRLEN + \
OWL_NB_ALGORITHMS * OWL_CSV_ALGORITHM_RESULT_STRLEN + 1)
/* Same thing, but for the simplified CSV strings created by
* *_to_csv_simple().
* Request's information is only the MAC address.
* For the algorithm:
* = 12 characters per coordinate + OWL_AREA_STRLEN
*/
#define OWL_CSV_RESULT_REQUEST_SIMPLE_STRLEN OWL_ETHER_ADDR_STRLEN
#define OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN \
(3 * OWL_COORDINATE_STRLEN + OWL_AREA_STRLEN + 1)
#define OWL_CSV_RESULT_SIMPLE_STRLEN \
(OWL_CSV_RESULT_REQUEST_SIMPLE_STRLEN + \
OWL_NB_ALGORITHMS * OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN + 1)
/* Linked list of algorithms' results.
* Each structure is the result of a single algorithm.
*/
typedef struct _owl_algorithm_result
{
char *algorithm ;
float x ;
float y ;
float z ;
float error ;
char *area ;
struct _owl_algorithm_result *next ;
} owl_algorithm_result ;
/* Results for a request. Includes the request's data, and the
* list of algorithms' results.
*/
typedef struct _owl_result
{
char *mobile_mac_addr ;
uint8_t request_type ;
owl_timestamp mobile_timestamp ;
unsigned int nb_results ;
owl_algorithm_result *results ;
} owl_result ;
owl_result* owl_receive_position(int sockfd) ;
owl_result* owl_fill_result(char *csv) ;
owl_algorithm_result* owl_fill_algorithm_result(char **csv) ;
void owl_result_to_csv(char dst[OWL_CSV_RESULT_STRLEN],
const owl_result *const src) ;
void
owl_algorithm_result_to_csv(char dst[OWL_CSV_ALGORITHM_RESULT_STRLEN],
const owl_algorithm_result *const src) ;
void owl_result_to_csv_simple(char dst[OWL_CSV_RESULT_SIMPLE_STRLEN],
const owl_result *const src) ;
void owl_algorithm_result_to_csv_simple
(char dst[OWL_CSV_ALGORITHM_RESULT_SIMPLE_STRLEN],
const owl_algorithm_result *const src) ;
void owl_fprint_result(FILE *stream, const owl_result *const src) ;
void owl_fprint_algorithm_result(FILE *stream,
const owl_algorithm_result *const src) ;
#define owl_print_result(SRC) \
(owl_fprint_result(stdout, (SRC)))
#define owl_print_algorithm_result(SRC) \
(owl_fprint_algorithm_result(stdout, (SRC)))
void owl_free_result(owl_result *result) ;
void owl_free_algorithm_result(owl_algorithm_result *algo) ;
#endif // _LIBOWLPS_RESULTREADER_CSV_

View File

@ -35,6 +35,7 @@ OBJS=$(LIB_CIBLE).o
# Flags
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O
#CFLAGS += -g -O0
#CFLAGS += -D NDEBUG
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)

View File

@ -38,6 +38,7 @@ OBJS=$(LIB_CIBLE).o
# Flags
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O
#CFLAGS += -g -O0
#CFLAGS += -D NDEBUG
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)

View File

@ -38,6 +38,7 @@ OBJS=$(LIB_CIBLE).o
# Flags
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O
#CFLAGS += -g -O0
#CFLAGS += -D NDEBUG
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)

View File

@ -19,7 +19,7 @@
owl_bool owl_run = TRUE ;
owl_bool owl_run = owl_true ;
@ -57,7 +57,7 @@ void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary,
/*
* Compares two MAC addresses.
* Returns TRUE if they are identical, FALSE otherwise.
* Returns owl_true if they are identical, owl_false otherwise.
*/
owl_bool owl_mac_equals(const uint8_t *const mac1,
const uint8_t *const mac2)
@ -65,8 +65,8 @@ owl_bool owl_mac_equals(const uint8_t *const mac1,
int i ;
for (i = 0 ; i < ETHER_ADDR_LEN ; ++i)
if(mac1[i] != mac2[i])
return FALSE ;
return TRUE ;
return owl_false ;
return owl_true ;
}
@ -132,6 +132,40 @@ uint_fast8_t owl_frequency_to_channel(const uint_fast16_t channel)
/* *** Time *** */
/*
* Sleeps for a given amount of milliseconds.
* 'time_ms' is an unsigned value, so please be careful: passing a
* negative value may not do what you think.
* In case of error, a message is displayed and a non-zero error code
* is returned (if positive, it is the number of non-sleeped seconds).
*/
int owl_msleep(uint32_t time_ms)
{
int ret ;
uint_fast32_t seconds, microseconds ;
if (! time_ms)
return 0 ;
seconds = time_ms / 1000 ;
microseconds = time_ms % 1000 * 1000 ;
if ((ret = sleep(seconds)))
{
perror("Cannot sleep()") ;
return ret ;
}
if ((ret = usleep(microseconds)))
{
perror("Cannot usleep()") ;
return ret ;
}
return 0 ;
}
/*
* Sets the owl_timestamp 'now' at the current time.
* Returns 0 in case of success non-zero otherwise.
@ -200,12 +234,12 @@ uint64_t owl_timestamp_to_ms(const owl_timestamp d)
/*
* Converts a owl_timestamp date value into a printable string.
* 'dst' must be an allocated array of at least owl_timestamp_STR_LEN
* 'dst' must be an allocated array of at least OWL_TIMESTAMP_STRLEN
* characters.
*/
void owl_timestamp_to_string(char *const dst, const owl_timestamp src)
{
snprintf(dst, OWL_TIMESTAMP_STR_LEN, "%"PRIu32".%"PRIu32,
snprintf(dst, OWL_TIMESTAMP_STRLEN, "%"PRIu32".%"PRIu32,
src.tv_sec, src.tv_nsec) ;
}
@ -297,6 +331,7 @@ float owl_swap_float(const float f)
* description will be saved.
* - client_description (in/out): the structure in which the client
* description will be saved.
* Returns a negative error code in case of error.
*/
int owl_create_udp_trx_socket(const char *const server_address,
const uint_fast16_t server_port,
@ -310,7 +345,7 @@ int owl_create_udp_trx_socket(const char *const server_address,
if (sockfd < 0)
{
perror("UDP socket creation failed") ;
return sockfd ;
return -OWL_ERR_SOCKET_CREATE ;
}
/* Initialise the client structure */
@ -334,6 +369,7 @@ int owl_create_udp_trx_socket(const char *const server_address,
* Creates a UDP reception socket and returns its descriptor.
* Parameters:
* - port: port on which the socket listens.
* Returns a negative error code in case of error.
*/
int owl_create_udp_listening_socket(const uint_fast16_t port)
{
@ -346,7 +382,7 @@ int owl_create_udp_listening_socket(const uint_fast16_t port)
if (sockfd < 0)
{
perror("UDP socket creation failed") ;
return sockfd ;
return -OWL_ERR_SOCKET_CREATE ;
}
/* Initialise the server structure */
@ -363,7 +399,7 @@ int owl_create_udp_listening_socket(const uint_fast16_t port)
{
perror("Cannot bind the UDP socket") ;
close(sockfd) ;
return ret ;
return -OWL_ERR_SOCKET_CREATE ;
}
return sockfd ;
@ -383,10 +419,10 @@ void owl_sigint_handler(const int num)
{
fprintf(stderr, "Error! The SIGINT handler was called but the"
" signal is not SIGINT.\n") ;
exit(ERR_BAD_SIGNAL) ;
exit(OWL_ERR_BAD_SIGNAL) ;
}
owl_run = FALSE ;
owl_run = owl_false ;
#ifndef NDEBUG
fprintf(stderr, "\nSignal received: end.\n");
@ -404,7 +440,7 @@ void owl_sigterm_handler(const int num)
{
fprintf(stderr, "Error! The SIGTERM handler was called but the"
" signal is not SIGTERM.\n") ;
exit(ERR_BAD_SIGNAL) ;
exit(OWL_ERR_BAD_SIGNAL) ;
}
owl_sigint_handler(SIGINT) ;

View File

@ -20,27 +20,27 @@ extern "C" {
// Port on which the positioning request is sent by the mobile:
#define LOC_REQUEST_DEFAULT_PORT 9900
#define OWL_DEFAULT_REQUEST_PORT 9900
// Port on which listeners and aggregator communicate:
#define AGGREGATE_DEFAULT_PORT 9901
#define OWL_DEFAULT_LISTENER_PORT 9901
// Port on which aggregator and positioning server communicate:
#define POSITIONER_DEFAULT_PORT 9902
#define OWL_DEFAULT_AGGREGATION_PORT 9902
// Port on which autocalibration requests are sent by the listeners:
#define DEFAULT_AUTOCALIBRATION_REQUEST_PORT 9903
#define OWL_DEFAULT_AUTOCALIBRATION_REQUEST_PORT 9903
// Port on which the aggregator listens for hello messages from the
// listeners, and the listeners listen for orders from the aggregator:
#define DEFAULT_AUTOCALIBRATION_PORT 9904
#define OWL_DEFAULT_AUTOCALIBRATION_PORT 9904
// Port on which the mobile listens for its position:
#define MOBILE_DEFAULT_PORT 9910
#define OWL_DEFAULT_RESULT_PORT 9910
/* Boolean type */
typedef enum {FALSE, TRUE} owl_bool ;
typedef enum {owl_false, owl_true} owl_bool ;
#define OWL_BOOL_TO_STRING(B) ((B) ? "true" : "false")
/* Direction type */
enum {NORTH = 1, EAST, SOUTH, WEST} ;
enum {owl_north = 1, owl_east, owl_south, owl_west} ;
#define OWL_DIRECTION_MIN 1
#define OWL_DIRECTION_MAX 4
typedef uint8_t owl_direction ;
@ -53,7 +53,7 @@ typedef struct _owl_timestamp
uint32_t tv_nsec ;
} owl_timestamp ;
// Length of a owl_timestamp when converted to string:
#define OWL_TIMESTAMP_STR_LEN 22 // 22 = 10 digits, '.', 10 digits, '\0'
#define OWL_TIMESTAMP_STRLEN 22 // 22 = 10 digits, '.', 10 digits, '\0'
/* Message sent by the listener to the aggregator */
@ -160,6 +160,12 @@ typedef struct _owl_autocalibration_order
/* Misc. */
// Length of a MAC address in string format (including '\0')
#define OWL_ETHER_ADDR_STRLEN 18
// Maximum length of an algorithm name (including '\0')
#define OWL_ALGORITHM_STRLEN 31
// Maximum length of an area name (including '\0')
#define OWL_AREA_STRLEN 31
// Maximum length of a coordinate X, Y or Z (including '\0')
#define OWL_COORDINATE_STRLEN 16
/* Global variables */
@ -167,8 +173,31 @@ typedef struct _owl_autocalibration_order
extern owl_bool owl_run ;
/* Function error codes */
#define ERR_BAD_SIGNAL 111
/* Error codes */
/* User interface */
// Wrong program invokation (command-line arguments):
#define OWL_ERR_BAD_USAGE 100
// Error when reading/parsing the configuration file:
#define OWL_ERR_CONFIG_FILE 101
/* System */
// Error when creating a thread:
#define OWL_ERR_THREAD_CREATE 110
// Wrong signal received:
#define OWL_ERR_BAD_SIGNAL 111
/* Network communication */
// Error when creating a socket:
#define OWL_ERR_SOCKET_CREATE 120
// Error when sending a message on a socket:
#define OWL_ERR_SOCKET_SEND 121
// Error when reading from a socket:
#define OWL_ERR_SOCKET_RECV 122
/* Network interface / capture */
// Error when opening the capture interface:
#define OWL_ERR_IFACE_PCAP_OPEN 130
// Error when reading the interface Wi-Fi mode:
#define OWL_ERR_IFACE_MODE_GET 131
// Error when setting the interface Wi-Fi mode:
#define OWL_ERR_IFACE_MODE_SET 132
/* Function headers */
@ -181,6 +210,7 @@ owl_bool owl_mac_equals(const uint8_t *const mac1,
uint_fast8_t owl_frequency_to_channel(const uint_fast16_t channel) ;
// Time
int owl_msleep(uint32_t time_ms) ;
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) ;
@ -226,16 +256,6 @@ void owl_close_fd(void *const fd) ;
void owl_close_file(void *const file) ;
/* Macros */
/*
* Test if a IEEE 802.11 frame is a retry.
* Input: IEEE 802.11 header flags.
* Returns 0 if the Retry bit is absent, a positive value if present.
*/
#define IS_RETRY(IEEE80211_FLAGS) ((IEEE80211_FLAGS) & 0x08)
#ifdef __cplusplus
}
#endif // __cplusplus

View File

@ -27,6 +27,7 @@ HEADER=owlps-aggregator.h
# Flags
LIBOWLPS_DIR = ../libowlps
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes -O -I$(LIBOWLPS_DIR)
#CFLAGS += -g -O0
DEPFLAGS=-MMD
XCFLAGS=$(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG=-fPIC

View File

@ -27,15 +27,6 @@
#define VERBOSE_REQUESTS cfg_getint(cfg, "verbose") >= 4
/* Error codes */
#define ERR_NO_MESSAGE_RECEIVED 1 // Error when reading the socket
#define ERR_CREATING_SOCKET 2 // Erreur when creating listening socket
#define ERR_BAD_USAGE 3 // Bad program call
#define ERR_PARSING_CONFIG_FILE 4 // Error reading the configuration file
#define ERR_SENDING_INFO 5 // Error sending a message on a socket
#define ERR_CREATING_THREAD 6 // Error creating a thread
/* Linked list storing data of each request */
typedef struct _request_info_list
{
@ -86,10 +77,10 @@ typedef struct _ap_list
/* Function headers */
void initialise_configuration(int argc, char **argv) ;
void parse_config_file(int argc, char **argv) ;
void parse_command_line(int argc, char **argv) ;
void check_configuration(void) ;
int initialise_configuration(int argc, char **argv) ;
int parse_config_file(int argc, char **argv) ;
int parse_command_line(int argc, char **argv) ;
int check_configuration(void) ;
int read_loop(int sockfd) ;
void got_request(owl_captured_request request) ;

View File

@ -42,10 +42,14 @@ int main(int argc, char **argv)
monitor_aps_thread, // APs monitoring thread
autocalibration_hello_thread ; // Hello messages reception thread
uint_fast16_t listening_port ;
int sockfd ; // UDP listening socket
int sockfd = -1 ; // UDP listening socket
owl_run = owl_true ;
program_name = argv[0] ;
initialise_configuration(argc, argv) ;
ret = initialise_configuration(argc, argv) ;
if (! owl_run)
goto exit ;
/* Set up signal handlers */
action.sa_flags = 0 ;
@ -66,7 +70,7 @@ int main(int argc, char **argv)
fprintf(stderr,
"Error! Cannot listen on port %"PRIuFAST16".\n",
listening_port) ;
ret = ERR_CREATING_SOCKET ;
ret = OWL_ERR_SOCKET_CREATE ;
goto exit ;
}
@ -75,7 +79,7 @@ int main(int argc, char **argv)
if (ret != 0)
{
perror("Cannot create monitor thread") ;
ret = ERR_CREATING_THREAD ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
if (cfg_getbool(cfg, "autocalibration"))
@ -85,7 +89,7 @@ int main(int argc, char **argv)
if (ret != 0)
{
perror("Cannot create autocalibration hello thread") ;
ret = ERR_CREATING_THREAD ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
ret = pthread_create(&monitor_aps_thread, NULL,
@ -93,12 +97,11 @@ int main(int argc, char **argv)
if (ret != 0)
{
perror("Cannot create monitor APs thread") ;
ret = ERR_CREATING_THREAD ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
}
owl_run = TRUE ;
ret = read_loop(sockfd) ;
/* Wait for the threads to terminate */
@ -140,7 +143,8 @@ int main(int argc, char **argv)
/* Last cleaning tasks */
exit:
close(sockfd) ; // Close socket
if (sockfd >= 0)
close(sockfd) ; // Close socket
free_request_list() ;
free_ap_list() ;
cfg_free(cfg) ; // Clean configuration
@ -154,11 +158,28 @@ int main(int argc, char **argv)
void initialise_configuration(int argc, char **argv)
/*
* Read the configuration from both the command line and the
* configuration file.
* Returns an error code, or 0 in case of success. If the program should
* stop (because of a special option or a configuration error), owl_run
* is set to false.
*/
int initialise_configuration(int argc, char **argv)
{
parse_config_file(argc, argv) ;
parse_command_line(argc, argv) ;
check_configuration() ;
int ret ;
ret = parse_config_file(argc, argv) ;
if (! owl_run)
return ret ;
ret = parse_command_line(argc, argv) ;
if (! owl_run)
return ret ;
ret = check_configuration() ;
if (! owl_run)
return ret ;
/* Configuration printing */
if (VERBOSE_INFO)
@ -166,10 +187,12 @@ void initialise_configuration(int argc, char **argv)
fprintf(stderr, "Configuration:\n") ;
cfg_print(cfg, stderr) ;
}
return 0 ;
}
void parse_config_file(int argc, char **argv)
int parse_config_file(int argc, char **argv)
{
// Config file options for confuse
cfg_opt_t opts[] =
@ -178,10 +201,10 @@ void parse_config_file(int argc, char **argv)
CFG_INT("verbose", 0, CFGF_NONE),
// Aggregation listening port
CFG_INT("listening_port", AGGREGATE_DEFAULT_PORT, CFGF_NONE),
CFG_INT("listening_port", OWL_DEFAULT_LISTENER_PORT, CFGF_NONE),
// Port and IP address of the localisation server:
CFG_INT("positioner_port", POSITIONER_DEFAULT_PORT, CFGF_NONE),
CFG_INT("positioner_port", OWL_DEFAULT_AGGREGATION_PORT, CFGF_NONE),
CFG_STR("positioner_ip", POSITIONER_DEFAULT_IP, CFGF_NONE),
CFG_STR("output_file", "", CFGF_NONE),
@ -196,7 +219,7 @@ void parse_config_file(int argc, char **argv)
// Autocalibration activated?
CFG_BOOL("autocalibration", cfg_false, CFGF_NONE),
// Port on which autocalibration data are exchanged:
CFG_INT("autocalibration_port", DEFAULT_AUTOCALIBRATION_PORT,
CFG_INT("autocalibration_port", OWL_DEFAULT_AUTOCALIBRATION_PORT,
CFGF_NONE),
// Time we keep APs in the list (in seconds):
CFG_INT("ap_keep_timeout", DEFAULT_AP_KEEP_TIMEOUT, CFGF_NONE),
@ -221,10 +244,12 @@ void parse_config_file(int argc, char **argv)
break ;
case 'h' :
print_usage() ;
exit(0) ;
owl_run = owl_false ;
return EXIT_SUCCESS ;
case 'V' :
print_version() ;
exit(0) ;
owl_run = owl_false ;
return EXIT_SUCCESS ;
}
}
@ -250,13 +275,16 @@ void parse_config_file(int argc, char **argv)
"Error! Parsing of configuration file « %s » failed!\n",
config_file) ;
free(config_file) ;
exit(ERR_PARSING_CONFIG_FILE) ;
owl_run = owl_false ;
return OWL_ERR_CONFIG_FILE ;
}
free(config_file) ;
return 0 ;
}
void parse_command_line(int argc, char **argv)
int parse_command_line(int argc, char **argv)
{
int opt ;
@ -281,9 +309,6 @@ void parse_command_line(int argc, char **argv)
break ;
case 'f' : // Config file
break ; // (already parsed)
case 'h' :
print_usage() ;
exit(0) ;
case 'i' :
cfg_setstr(cfg, "positioner_ip", optarg) ;
break ;
@ -316,20 +341,24 @@ void parse_command_line(int argc, char **argv)
break ;
default :
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
}
return 0 ;
}
void check_configuration()
int check_configuration()
{
// output_file //
if (cfg_getstr(cfg, "output_file")[0] == '\0')
{
fprintf(stderr, "Error! You must specify an output file.\n") ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
// listening_port //
@ -339,7 +368,7 @@ void check_configuration()
if (VERBOSE_WARNING)
fprintf(stderr, "Warning! Bad listening_port:"
" failing back to the default value.\n") ;
cfg_setint(cfg, "listening_port", AGGREGATE_DEFAULT_PORT) ;
cfg_setint(cfg, "listening_port", OWL_DEFAULT_LISTENER_PORT) ;
}
// positioner_port //
@ -349,7 +378,7 @@ void check_configuration()
if (VERBOSE_WARNING)
fprintf(stderr, "Warning! Bad positioner_port:"
" failing back to the default value.\n") ;
cfg_setint(cfg, "positioner_port", POSITIONER_DEFAULT_PORT) ;
cfg_setint(cfg, "positioner_port", OWL_DEFAULT_AGGREGATION_PORT) ;
}
// positioner_ip //
@ -358,7 +387,8 @@ void check_configuration()
fprintf(stderr, "Error! You must specify the IP address of the"
" localisation server.\n") ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
// aggregate_timeout //
@ -405,6 +435,8 @@ void check_configuration()
" failing back to the default value.\n") ;
cfg_setint(cfg, "ap_check_interval", DEFAULT_AP_CHECK_INTERVAL) ;
}
return 0 ;
}
@ -422,8 +454,8 @@ int read_loop(int sockfd)
char // Return values of
mobile_ip_str[INET_ADDRSTRLEN], // inet_ntop()
// and owl_timestamp_to_string():
request_time_str[OWL_TIMESTAMP_STR_LEN],
start_time_str[OWL_TIMESTAMP_STR_LEN] ;
request_time_str[OWL_TIMESTAMP_STRLEN],
start_time_str[OWL_TIMESTAMP_STRLEN] ;
while (owl_run)
{
@ -435,7 +467,7 @@ int read_loop(int sockfd)
if (owl_run)
{
perror("No request received from listener") ;
ret = ERR_NO_MESSAGE_RECEIVED ;
ret = OWL_ERR_SOCKET_RECV ;
}
break ;
}
@ -506,7 +538,7 @@ void* monitor_requests(void *NULL_value)
FILE *fd = NULL ;
char mac_str[OWL_ETHER_ADDR_STRLEN] ;
uint_fast32_t sub ; // owl_time_elapsed_ms() result
char request_time_str[OWL_TIMESTAMP_STR_LEN] ;
char request_time_str[OWL_TIMESTAMP_STRLEN] ;
uint_fast32_t aggregate_timeout =
cfg_getint(cfg, "aggregate_timeout") ;
@ -679,7 +711,7 @@ void* monitor_requests(void *NULL_value)
fflush(NULL) ;
// Wait to check again:
usleep(cfg_getint(cfg, "check_interval") * 1000) ;
owl_msleep(cfg_getint(cfg, "check_interval")) ;
}
/* Close output file & socket */
@ -872,7 +904,7 @@ void* listen_for_aps(void *NULL_value)
{
perror("Error! Cannot create UDP listening socket from the"
" listeners") ;
exit(ERR_CREATING_SOCKET) ;
exit(OWL_ERR_SOCKET_CREATE) ;
}
pthread_cleanup_push(&owl_close_fd, &listen_sockfd) ;
@ -1045,7 +1077,7 @@ void* monitor_aps(void *NULL_value)
}
sem_post(&lock_aps) ;
usleep(cfg_getint(cfg, "ap_check_interval") * 1000) ;
owl_msleep(cfg_getint(cfg, "ap_check_interval")) ;
}
pthread_exit(NULL_value) ;
@ -1146,7 +1178,7 @@ void order_send(ap_list *ap)
if (nsent != (ssize_t) sizeof(message))
{
perror("Error sending order to the listener") ;
exit(ERR_SENDING_INFO) ;
exit(OWL_ERR_SOCKET_SEND) ;
}
close(sockfd) ;
@ -1191,8 +1223,8 @@ void print_request_list()
request_info_list *info_ptr = NULL ;
char mobile_mac_str[OWL_ETHER_ADDR_STRLEN] ;
char
request_time_str[OWL_TIMESTAMP_STR_LEN],
start_time_str[OWL_TIMESTAMP_STR_LEN] ;
request_time_str[OWL_TIMESTAMP_STRLEN],
start_time_str[OWL_TIMESTAMP_STRLEN] ;
sem_wait(&lock_requests) ;
@ -1329,12 +1361,12 @@ void print_usage()
program_name,
DEFAULT_CONFIG_FILE,
POSITIONER_DEFAULT_IP,
POSITIONER_DEFAULT_PORT,
AGGREGATE_DEFAULT_PORT,
OWL_DEFAULT_AGGREGATION_PORT,
OWL_DEFAULT_LISTENER_PORT,
DEFAULT_AGGREGATE_TIMEOUT,
DEFAULT_KEEP_TIMEOUT,
DEFAULT_CHECK_INTERVAL,
DEFAULT_AUTOCALIBRATION_PORT,
OWL_DEFAULT_AUTOCALIBRATION_PORT,
DEFAULT_AP_KEEP_TIMEOUT,
DEFAULT_AP_CHECK_INTERVAL
) ;

View File

@ -54,7 +54,7 @@ struct {
float z ;
} options = {
"",
LOC_REQUEST_DEFAULT_PORT,
OWL_DEFAULT_REQUEST_PORT,
"",
-1,
0,
@ -64,9 +64,9 @@ struct {
char *program_name = NULL ;
// TRUE if the packet is a calibration request, FALSE if it is a simple
// True if the packet is a calibration request, false if it is a simple
// positioning request:
owl_bool is_calibration_request = FALSE ;
owl_bool is_calibration_request = owl_false ;
int socksendfd ; // Sending socket descriptor (send positioning packets)
int sockreceivefd ; // Receiving socket descriptor (Receive position)
@ -540,7 +540,7 @@ void parse_main_options(int argc, char **argv)
* is an option, we have -l without a port number */
if (argv[optind] == NULL || argv[optind][0] == '-')
// Take the default value:
options.listening_port = MOBILE_DEFAULT_PORT ;
options.listening_port = OWL_DEFAULT_RESULT_PORT ;
else
{
// Take the optind value:
@ -592,7 +592,7 @@ void parse_calibration_data(int argc, char **argv)
{
if (argc - optind == 4)
{
is_calibration_request = TRUE ;
is_calibration_request = owl_true ;
options.direction = strtoul(argv[optind++], NULL, 0) ;
options.x = strtod(argv[optind++], NULL) ;
options.y = strtod(argv[optind++], NULL) ;
@ -652,7 +652,7 @@ void check_configuration()
#ifdef DEBUG
fprintf(stderr, "Warning! Bad dest_port:"
" failing back to default value.\n") ;
options.dest_port = LOC_REQUEST_DEFAULT_PORT ;
options.dest_port = OWL_DEFAULT_REQUEST_PORT ;
#endif // DEBUG
}
if (options.listening_port > 65535)
@ -711,8 +711,8 @@ void print_configuration()
void create_socket()
{
socksendfd =
owlclient_create_trx_socket(options.dest_ip, options.dest_port,
&server, options.iface) ;
owl_create_trx_socket(options.dest_ip, options.dest_port,
&server, options.iface) ;
sockreceivefd =
owl_create_udp_listening_socket(options.listening_port) ;
}
@ -724,7 +724,7 @@ void make_packet()
{
uint_fast16_t offset ; // Index used to create the packet
owl_timestamp request_time ;
char request_time_str[OWL_TIMESTAMP_STR_LEN] ;
char request_time_str[OWL_TIMESTAMP_STRLEN] ;
// Get the current time and copy it as a string before to switch it to
// network endianess:
@ -776,8 +776,8 @@ void make_packet()
void send_request()
{
owlclient_send_request(socksendfd, &server, packet, packet_size,
options.nb_pkt, options.delay) ;
owl_send_request(socksendfd, &server, packet, packet_size,
options.nb_pkt, options.delay) ;
}
@ -816,7 +816,7 @@ void string2data(char* string_data)
int count_algo= 0 ;
int count_print = 0 ;
int onetime = 0 ;
owl_bool error_present = FALSE ;
owl_bool error_present = owl_false ;
while(onetime<1)
{
@ -867,7 +867,7 @@ void string2data(char* string_data)
break ;
strncpy(results[count_algo].algo, ptr, ALGO_STRLEN) ;
if(!strcmp(results[count_algo].algo,"Real"))
error_present = TRUE ;
error_present = owl_true ;
// X coordinate
ptr = strtok(NULL, delims) ;
@ -1030,12 +1030,12 @@ void print_usage()
,
program_name,
program_name,
LOC_REQUEST_DEFAULT_PORT,
OWL_DEFAULT_REQUEST_PORT,
DEFAULT_DELAY_NORMAL,
DEFAULT_DELAY_CALIB,
DEFAULT_NBPKT_NORMAL,
DEFAULT_NBPKT_CALIB,
MOBILE_DEFAULT_PORT
OWL_DEFAULT_RESULT_PORT
) ;
}

View File

@ -27,15 +27,19 @@ HEADER=
# Flags
LIBOWLPS_DIR = ../libowlps
LIBOWLPSCLIENT_DIR = ../libowlps-client
LIBOWLPSRESULTREADER_DIR = ../libowlps-resultreader
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR)
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR) \
-I$(LIBOWLPSRESULTREADER_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC
OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\"
OWLPSFLAGS += -D DEBUG
LIBS = -L$(LIBOWLPS_DIR) -lowlps \
-L$(LIBOWLPSCLIENT_DIR) -lowlps-client
-L$(LIBOWLPSCLIENT_DIR) -lowlps-client \
-L$(LIBOWLPSRESULTREADER_DIR) -lowlps-resultreader
OS := $(shell uname)
ifeq ("$(OS)", "Linux")
@ -93,6 +97,7 @@ purge : clean
help :
@echo "Bibliothèques nécessaires à la compilation :"
@echo " libowlps1.0 (fournie)"
@echo " libowlps-client1.0 (fournie)"
@echo
@echo "Cibles possibles :"
@echo " $(TARGET) (cible par défaut) : Compile le programme \

View File

@ -32,6 +32,7 @@ LIBOWLPS_DIR = ../libowlps
LIBOWLPSCLIENT_DIR = ../libowlps-client
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC

View File

@ -32,6 +32,7 @@ LIBOWLPS_DIR = ../libowlps
LIBOWLPSCLIENT_DIR = ../libowlps-client
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC

View File

@ -2,20 +2,19 @@
* This file is part of the rtap localisation project.
*/
#include "../libowlps-client/owlps-client.h"
#include <owlps-client.h>
#include <owlps-resultreader.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <string.h>
#include <signal.h>
#include <net/if.h>
/* Error codes */
#define ERR_BAD_USAGE 1 // Bad program call (bad number of arguments)
/* Number of packets to send */
#define DEFAULT_NBPKT_CALIB 20 // 20 packets when calibrating
#define DEFAULT_NBPKT_NORMAL 10 // 10 packets when requesting the position
@ -43,7 +42,7 @@ void print_configuration(void) ;
void create_socket(void) ;
void make_packet(void) ;
void send_request(void) ;
void receive_position(void) ;
int receive_position(void) ;
void print_usage(void) ;
void print_version(void) ;
@ -64,7 +63,7 @@ struct {
float z ;
} options = {
"",
LOC_REQUEST_DEFAULT_PORT,
OWL_DEFAULT_REQUEST_PORT,
"",
-1,
0,
@ -75,9 +74,9 @@ struct {
char *program_name = NULL ;
// TRUE if the packet is a calibration request, FALSE if it is a simple
// positioning request:
owl_bool is_calibration_request = FALSE ;
// owl_true if the packet is a calibration request, owl_false if it is
// a simple positioning request:
owl_bool is_calibration_request = owl_false ;
int sockfd ; // Sending socket descriptor
struct sockaddr_in server ; // Server info
@ -88,28 +87,36 @@ uint_fast16_t packet_size ; // Packet size
int main(int argc, char *argv[])
{
struct sigaction action ; // Signal handler structure
int ret = 0 ;
program_name = argv[0] ;
parse_command_line(argc, argv) ;
/* Set up signal handlers */
action.sa_flags = 0 ;
sigemptyset(&action.sa_mask) ;
action.sa_handler = owl_sigint_handler ;
sigaction(SIGINT, &action, NULL) ;
action.sa_handler = owl_sigterm_handler ;
sigaction(SIGTERM, &action, NULL) ;
create_socket() ;
request_transmission:
make_packet() ;
send_request() ;
free(packet) ;
if (options.flood_delay >= 0)
while (owl_run && options.flood_delay >= 0)
{
usleep(options.flood_delay * 1000) ;
goto request_transmission ;
owl_msleep(options.flood_delay) ;
if (owl_run) // owl_run can have been set to false during the sleep
send_request() ;
}
close(sockfd) ;
if (options.listening_port > 0)
receive_position() ;
ret = receive_position() ;
return 0 ;
return ret ;
}
@ -179,7 +186,7 @@ void parse_main_options(int argc, char **argv)
* is an option, we have -l without a port number */
if (argv[optind] == NULL || argv[optind][0] == '-')
// Take the default value:
options.listening_port = MOBILE_DEFAULT_PORT ;
options.listening_port = OWL_DEFAULT_RESULT_PORT ;
else
{
// Take the optind value:
@ -203,7 +210,7 @@ void parse_main_options(int argc, char **argv)
exit(0) ;
default :
print_usage() ;
exit(ERR_BAD_USAGE) ;
exit(OWL_ERR_BAD_USAGE) ;
}
}
}
@ -218,7 +225,7 @@ void check_destination_ip()
fprintf(stderr, "Error! You must specify a destination IP address"
" (-d).\n") ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
exit(OWL_ERR_BAD_USAGE) ;
}
}
@ -231,7 +238,7 @@ void parse_calibration_data(int argc, char **argv)
{
if (argc - optind == 4)
{
is_calibration_request = TRUE ;
is_calibration_request = owl_true ;
options.direction = strtoul(argv[optind++], NULL, 0) ;
options.x = strtod(argv[optind++], NULL) ;
options.y = strtod(argv[optind++], NULL) ;
@ -240,7 +247,7 @@ void parse_calibration_data(int argc, char **argv)
else // Bad number of arguments
{
print_usage() ;
exit(ERR_BAD_USAGE) ;
exit(OWL_ERR_BAD_USAGE) ;
}
}
}
@ -282,7 +289,7 @@ void check_configuration()
{
fprintf(stderr, "Error! « %"PRIu8" » is not a valid"
" direction.\n", options.direction) ;
exit(ERR_BAD_USAGE) ;
exit(OWL_ERR_BAD_USAGE) ;
}
// Check port numbers
@ -291,7 +298,7 @@ void check_configuration()
#ifdef DEBUG
fprintf(stderr, "Warning! Bad dest_port:"
" failing back to default value.\n") ;
options.dest_port = LOC_REQUEST_DEFAULT_PORT ;
options.dest_port = OWL_DEFAULT_REQUEST_PORT ;
#endif // DEBUG
}
if (options.listening_port > 65535)
@ -362,18 +369,33 @@ void print_configuration()
void create_socket()
{
sockfd =
owlclient_create_trx_socket(options.dest_ip, options.dest_port,
&server, options.iface) ;
owl_create_trx_socket(options.dest_ip, options.dest_port,
&server, options.iface) ;
}
/* Creates the packet to send. */
/*
* Prepares a new request and sends it.
*/
void send_request()
{
make_packet() ;
owl_send_request(sockfd, &server, packet, packet_size,
options.nb_pkt, options.delay) ;
free(packet) ;
}
/*
* Creates the packet to send.
*/
void make_packet()
{
uint_fast16_t offset ; // Index used to create the packet
owl_timestamp request_time ;
char request_time_str[OWL_TIMESTAMP_STR_LEN] ;
char request_time_str[OWL_TIMESTAMP_STRLEN] ;
// Get the current time and copy it as a string before to switch it to
// network endianess:
@ -399,14 +421,21 @@ void make_packet()
printf("Direction = %d, X = %f, Y = %f, Z = %f\n",
packet[offset - 1], options.x, options.y, options.z) ;
#endif // DEBUG
// Convert the coordinates to the network endianess
options.x = owl_htonf(options.x) ;
options.y = owl_htonf(options.y) ;
options.z = owl_htonf(options.z) ;
// Copy the coordinates to the packet
memcpy(&packet[offset], &options.x, sizeof(float)) ;
offset += sizeof(float) ;
memcpy(&packet[offset], &options.y, sizeof(float)) ;
offset += sizeof(float) ;
memcpy(&packet[offset], &options.z, sizeof(float)) ;
// Convert the coordinates back to the host endianess (mandatory
// in flood mode)
options.x = owl_ntohf(options.x) ;
options.y = owl_ntohf(options.y) ;
options.z = owl_ntohf(options.z) ;
}
else // Standard packet
@ -423,26 +452,31 @@ void make_packet()
void send_request()
/*
* Receives a position computed by the infrastructure.
* Note that it is currently not guaranteed that the received result
* correspond to the request sent.
* Returns 0, or a non-zero value in case of error.
*/
int receive_position()
{
owlclient_send_request(sockfd, &server, packet, packet_size,
options.nb_pkt, options.delay) ;
}
owl_result *result ;
void receive_position()
{
// Position of the mobile as computed by the infrastructure:
float x, y, z ;
printf("Waiting for the result from the infrastructure...\n") ;
sockfd = owl_create_udp_listening_socket(options.listening_port) ;
recvfrom(sockfd, &x, sizeof(float), 0, NULL, NULL) ;
recvfrom(sockfd, &y, sizeof(float), 0, NULL, NULL) ;
recvfrom(sockfd, &z, sizeof(float), 0, NULL, NULL) ;
close(sockfd) ;
if (sockfd < 0)
return OWL_ERR_SOCKET_CREATE ;
printf("Computed position: (%.4f;%.4f;%.4f)\n", x, y, z) ;
result = owl_receive_position(sockfd) ;
if (result == NULL)
return OWL_ERR_SOCKET_RECV ;
close(sockfd) ;
owl_print_result(result) ;
owl_free_result(result) ;
return 0 ;
}
@ -482,13 +516,13 @@ void print_usage()
,
program_name,
program_name,
LOC_REQUEST_DEFAULT_PORT,
OWL_DEFAULT_REQUEST_PORT,
DEFAULT_DELAY_NORMAL,
DEFAULT_DELAY_CALIB,
DEFAULT_NBPKT_NORMAL,
DEFAULT_NBPKT_CALIB,
DEFAULT_FLOOD_DELAY,
MOBILE_DEFAULT_PORT
OWL_DEFAULT_RESULT_PORT
) ;
}

View File

@ -29,6 +29,7 @@ LIBOWLPS_DIR = ../libowlps
LIBOWLPSCLIENT_DIR = ../libowlps-client
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC

View File

@ -32,6 +32,7 @@ LIBOWLPS_DIR = ../libowlps
LIBOWLPSCLIENT_DIR = ../libowlps-client
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC

View File

@ -32,6 +32,7 @@ LIBOWLPS_DIR = ../libowlps
LIBOWLPSCLIENT_DIR = ../libowlps-client
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSCLIENT_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC

View File

@ -94,6 +94,13 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
#define IS_FRAME_FROM_STA(FC2) \
(((FC2) & FRAME_FROM_STA_MASK) != FRAME_FROM_STA_MASK)
/*
* Test if a IEEE 802.11 frame is a retry.
* Input: IEEE 802.11 header flags.
* Returns 0 if the Retry bit is absent, a positive value if present.
*/
#define IS_RETRY(IEEE80211_FLAGS) ((IEEE80211_FLAGS) & 0x08)
/* Positions of the radiotap header fixed fields (in bytes) */
#define RTAP_P_HREVISION 0 // Header revision
@ -147,24 +154,15 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
//#define RTAP_EXT 31
/* Error codes */
#define ERR_OPENING_IFACE 2 // Error when opening capture interface
#define ERR_BAD_USAGE 3 // Bad program call
#define ERR_PARSING_CONFIG_FILE 4 // Error reading the configuration file
#define ERR_CREATING_THREAD 6 // Error creating a thread
#define ERR_SETTING_MODE 101
#define ERR_READING_MODE 104
/* Function headers */
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) ;
int initialise_configuration(int argc, char **argv) ;
int parse_config_file(int argc, char **argv) ;
int parse_command_line(int argc, char **argv) ;
int parse_main_options(int argc, char **argv) ;
#ifdef USE_PTHREAD
void parse_calibration_data(int argc, char **argv) ;
int parse_calibration_data(int argc, char **argv) ;
#endif // USE_PTHREAD
void check_configuration(void) ;
int check_configuration(void) ;
#ifdef DEBUG
void print_configuration(void) ;
#endif // DEBUG
@ -307,7 +305,7 @@ void print_version(void) ;
(options.aggregation_ip)
#ifdef USE_PTHREAD
#define SET_KEEP_MONITOR() \
(options.keep_monitor = TRUE)
(options.keep_monitor = owl_true)
#define GET_KEEP_MONITOR() \
(options.keep_monitor)
#endif // USE_PTHREAD
@ -330,7 +328,7 @@ void print_version(void) ;
#ifdef USE_PTHREAD
#define SET_AUTOCALIBRATION() \
(options.autocalibration = TRUE)
(options.autocalibration = owl_true)
#define GET_AUTOCALIBRATION() \
(options.autocalibration)
#define SET_AUTOCALIBRATION_IP(IP) \
@ -382,9 +380,9 @@ void print_version(void) ;
#define GET_VERBOSE() \
(options.verbose)
#define SET_DISPLAY_CAPTURED() \
(options.display_captured = TRUE)
(options.display_captured = owl_true)
#define UNSET_DISPLAY_CAPTURED() \
(options.display_captured = FALSE)
(options.display_captured = owl_false)
#define GET_DISPLAY_CAPTURED() \
(options.display_captured)
#endif // USE_CONFIG_FILE

View File

@ -45,12 +45,12 @@ 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 ;
// owl_true if the coordinates of the listener were provided by the user:
owl_bool coordinates_provided = owl_false ;
#endif // USE_PTHREAD
#ifdef USE_CONFIG_FILE
cfg_t *cfg ; // Configuration structure
cfg_t *cfg = NULL ; // Configuration structure
#else // USE_CONFIG_FILE
/* If we do not use libconfuse, we declare a structure to store getopt
@ -84,25 +84,25 @@ struct {
} options = { // Initalise default options:
MODE_ACTIVE,
"127.0.0.1",
AGGREGATE_DEFAULT_PORT,
LOC_REQUEST_DEFAULT_PORT,
OWL_DEFAULT_LISTENER_PORT,
OWL_DEFAULT_REQUEST_PORT,
#ifdef USE_PTHREAD
FALSE,
owl_false,
#endif // USE_PTHREAD
"",
"",
#ifdef USE_PTHREAD
FALSE,
owl_false,
"",
DEFAULT_AUTOCALIBRATION_REQUEST_PORT,
DEFAULT_AUTOCALIBRATION_PORT,
OWL_DEFAULT_AUTOCALIBRATION_REQUEST_PORT,
OWL_DEFAULT_AUTOCALIBRATION_PORT,
DEFAULT_AUTOCALIBRATION_HELLO_DELAY,
DEFAULT_AUTOCALIBRATION_DELAY,
DEFAULT_AUTOCALIBRATION_NBPKT,
0, 0, 0, 0,
#endif // USE_PTHREAD
0,
FALSE
owl_false
} ;
#endif // USE_CONFIG_FILE
@ -119,12 +119,15 @@ int main(int argc, char *argv[])
autocalibration_hello_thread ;
#endif // USE_PTHREAD
program_name = argv[0] ;
initialise_configuration(argc, argv) ;
owl_run = owl_true ;
owl_run = TRUE ;
program_name = argv[0] ;
ret = initialise_configuration(argc, argv) ;
if (! owl_run)
goto exit ;
/* Set up signal handlers */
action.sa_flags = 0 ;
sigemptyset(&action.sa_mask) ;
action.sa_handler = sigint_handler ;
sigaction(SIGINT, &action, NULL) ;
@ -149,7 +152,7 @@ int main(int argc, char *argv[])
if (ret != 0)
{
perror("Cannot create keep monitor thread") ;
ret = ERR_CREATING_THREAD ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
}
@ -161,7 +164,7 @@ int main(int argc, char *argv[])
if (ret != 0)
{
perror("Cannot create autocalibration thread") ;
ret = ERR_CREATING_THREAD ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
@ -170,7 +173,7 @@ int main(int argc, char *argv[])
if (ret != 0)
{
perror("Cannot create autocalibration hello thread") ;
ret = ERR_CREATING_THREAD ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
}
@ -244,19 +247,38 @@ int main(int argc, char *argv[])
void initialise_configuration(int argc, char **argv)
/*
* Read the configuration from both the command line and the
* configuration file.
* Returns an error code, or 0 in case of success. If the program should
* stop (because of a special option or a configuration error), owl_run
* is set to false.
*/
int initialise_configuration(int argc, char **argv)
{
parse_config_file(argc, argv) ;
parse_command_line(argc, argv) ;
check_configuration() ;
int ret ;
ret = parse_config_file(argc, argv) ;
if (! owl_run)
return ret ;
ret = parse_command_line(argc, argv) ;
if (! owl_run)
return ret ;
ret = check_configuration() ;
if (! owl_run)
return ret ;
if (VERBOSE_INFO)
print_configuration() ;
return 0 ;
}
void parse_config_file(int argc, char **argv)
int parse_config_file(int argc, char **argv)
{
#ifdef USE_CONFIG_FILE
// If we use libconfuse, we declare options:
@ -268,9 +290,9 @@ void parse_config_file(int argc, char **argv)
// IP address of the aggregator (default: loopback):
CFG_STR("aggregation_ip", "127.0.0.1", CFGF_NONE),
// Port on which the aggregator listens:
CFG_INT("aggregation_port", AGGREGATE_DEFAULT_PORT, CFGF_NONE),
CFG_INT("aggregation_port", OWL_DEFAULT_LISTENER_PORT, CFGF_NONE),
// Port on which mobiles send active requests:
CFG_INT("listening_port", LOC_REQUEST_DEFAULT_PORT, CFGF_NONE),
CFG_INT("listening_port", OWL_DEFAULT_REQUEST_PORT, CFGF_NONE),
#ifdef USE_PTHREAD
// Activate the active monitor mode keeping-up (read the code if
// you do not understand what I mean):
@ -289,9 +311,9 @@ void parse_config_file(int argc, char **argv)
CFG_STR("autocalibration_ip", "", CFGF_NONE),
// Port on which autocalibration requests are sent:
CFG_INT("autocalibration_request_port",
DEFAULT_AUTOCALIBRATION_REQUEST_PORT, CFGF_NONE),
OWL_DEFAULT_AUTOCALIBRATION_REQUEST_PORT, CFGF_NONE),
// Port on which autocalibration data are exchanged:
CFG_INT("autocalibration_port", DEFAULT_AUTOCALIBRATION_PORT,
CFG_INT("autocalibration_port", OWL_DEFAULT_AUTOCALIBRATION_PORT,
CFGF_NONE),
// Delay between two hello messages:
CFG_INT("autocalibration_hello_delay",
@ -342,10 +364,12 @@ void parse_config_file(int argc, char **argv)
break ;
case 'h' :
print_usage() ;
exit(0) ;
owl_run = owl_false ;
return EXIT_SUCCESS ;
case 'V' :
print_version() ;
exit(0) ;
owl_run = owl_false ;
return EXIT_SUCCESS ;
}
}
@ -372,25 +396,37 @@ void parse_config_file(int argc, char **argv)
"Error! Parsing of configuration file « %s » failed!\n",
config_file) ;
free(config_file) ;
exit(ERR_PARSING_CONFIG_FILE) ;
owl_run = owl_false ;
return OWL_ERR_CONFIG_FILE ;
}
free(config_file) ;
#endif // USE_CONFIG_FILE
return 0 ;
}
void parse_command_line(int argc, char **argv)
int parse_command_line(int argc, char **argv)
{
parse_main_options(argc, argv) ;
int ret ;
ret = parse_main_options(argc, argv) ;
if (! owl_run)
return ret ;
#ifdef USE_PTHREAD
parse_calibration_data(argc, argv) ;
ret = parse_calibration_data(argc, argv) ;
if (! owl_run)
return ret ;
#endif // USE_PTHREAD
return 0 ;
}
void parse_main_options(int argc, char **argv)
int parse_main_options(int argc, char **argv)
{
int opt ;
@ -429,8 +465,6 @@ void parse_main_options(int argc, char **argv)
break ;
case 'f' : // Config file
break ; // (already parsed)
case 'h' : // Usage
break ; // (already parsed)
case 'H' :
#ifdef USE_PTHREAD
SET_AUTOCALIBRATION_HELLO_DELAY(strtol(optarg, NULL, 0)) ;
@ -482,29 +516,30 @@ void parse_main_options(int argc, char **argv)
case 'v' :
INCREMENT_VERBOSE() ;
break ;
case 'V' : // Version
break ; // (already parsed)
case 'w' :
SET_WIFI_IFACE(optarg) ;
break ;
default :
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
}
return 0 ;
}
#ifdef USE_PTHREAD
void parse_calibration_data(int argc, char **argv)
int parse_calibration_data(int argc, char **argv)
{
/* Parse remaining arguments (possible calibration data) */
if (argc - optind != 0)
{
if (argc - optind == 4)
{
coordinates_provided = TRUE ;
coordinates_provided = owl_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)) ;
@ -513,15 +548,18 @@ void parse_calibration_data(int argc, char **argv)
else // Bad number of arguments
{
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
}
return 0 ;
}
#endif // USE_PTHREAD
void check_configuration()
int check_configuration()
{
switch (GET_MODE())
{
@ -532,7 +570,8 @@ void check_configuration()
default :
fprintf(stderr, "Error! Unknown mode « %c ».\n", (char) GET_MODE()) ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
if (GET_RTAP_IFACE()[0] == '\0')
@ -540,7 +579,8 @@ void check_configuration()
fprintf(stderr, "Error! You must specify a radiotap interface"
" for the capture.\n") ;
print_usage() ;
exit(ERR_BAD_USAGE) ;
owl_run = owl_false ;
return OWL_ERR_BAD_USAGE ;
}
if (GET_WIFI_IFACE()[0] == '\0')
@ -558,14 +598,14 @@ void check_configuration()
if (VERBOSE_WARNING)
fprintf(stderr, "Warning! Bad aggregation_port:"
" failing back to the default value.\n") ;
SET_AGGREGATION_PORT(AGGREGATE_DEFAULT_PORT) ;
SET_AGGREGATION_PORT(OWL_DEFAULT_LISTENER_PORT) ;
}
if (GET_LISTENING_PORT() < 1 || GET_LISTENING_PORT() > 65535)
{
if (VERBOSE_WARNING)
fprintf(stderr, "Warning! Bad listening_port:"
" failing back to the default value.\n") ;
SET_LISTENING_PORT(LOC_REQUEST_DEFAULT_PORT) ;
SET_LISTENING_PORT(OWL_DEFAULT_REQUEST_PORT) ;
}
// Autocalibration stuff //
@ -598,7 +638,7 @@ void check_configuration()
if (VERBOSE_WARNING)
fprintf(stderr, "Warning! Bad autocalibration_request_port:"
" failing back to the default value.\n") ;
SET_AUTOCALIBRATION_REQUEST_PORT(DEFAULT_AUTOCALIBRATION_REQUEST_PORT) ;
SET_AUTOCALIBRATION_REQUEST_PORT(OWL_DEFAULT_AUTOCALIBRATION_REQUEST_PORT) ;
}
if (GET_AUTOCALIBRATION_PORT() < 1 ||
GET_AUTOCALIBRATION_PORT() > 65535)
@ -606,10 +646,12 @@ void check_configuration()
if (VERBOSE_WARNING)
fprintf(stderr, "Warning! Bad autocalibration_port:"
" failing back to the default value.\n") ;
SET_AUTOCALIBRATION_PORT(DEFAULT_AUTOCALIBRATION_PORT) ;
SET_AUTOCALIBRATION_PORT(OWL_DEFAULT_AUTOCALIBRATION_PORT) ;
}
}
#endif // USE_PTHREAD
return 0 ;
}
@ -707,7 +749,7 @@ int iface_mode_monitor(const char *const iface)
if (ioctl(sockfd, SIOCGIWMODE, &wrq) == -1) // Get current mode
{
perror("Error reading interface mode") ;
return ERR_READING_MODE ;
return OWL_ERR_IFACE_MODE_GET ;
}
// If interface is not yet in Monitor mode
@ -717,7 +759,7 @@ int iface_mode_monitor(const char *const iface)
if (ioctl(sockfd, SIOCSIWMODE, &wrq) == -1) // Set up Monitor mode
{
perror("Error setting up Monitor mode") ;
return ERR_SETTING_MODE ;
return OWL_ERR_IFACE_MODE_SET ;
}
}
@ -743,14 +785,13 @@ int capture()
if (capture_handler == NULL) // Capture starting failed
{
fprintf(stderr, "Cannot open capture interface %s\n", errbuf) ;
return ERR_OPENING_IFACE ;
return OWL_ERR_IFACE_PCAP_OPEN ;
}
/* Open UDP socket to the aggregator */
aggregation_sockfd =
owlclient_create_trx_socket(GET_AGGREGATION_IP(),
GET_AGGREGATION_PORT(),
&aggregation_server, NULL) ;
owl_create_trx_socket(GET_AGGREGATION_IP(), GET_AGGREGATION_PORT(),
&aggregation_server, NULL) ;
while (owl_run)
// Capture one packet at time, and call read_packet() on it:
@ -784,9 +825,10 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
// Pointer to the (possible) UDP header of the packet:
struct udphdr *packet_udp_header = NULL ;
// Localisation request type (request, calibration, autocalibration):
owl_bool is_explicit_packet = TRUE ; // Is the packet an explicit request?
// Is the packet an explicit request?
owl_bool is_explicit_packet = owl_true ;
// Is the packet an autocalibration positioning request?
owl_bool uses_autocalibration_request_port = FALSE ;
owl_bool uses_autocalibration_request_port = owl_false ;
ssize_t nsent ; // sendto return value
// Blank the request:
@ -852,7 +894,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
#ifdef USE_PTHREAD
if (GET_AUTOCALIBRATION() && dest_port ==
(uint_fast16_t) GET_AUTOCALIBRATION_REQUEST_PORT())
uses_autocalibration_request_port = TRUE ;
uses_autocalibration_request_port = owl_true ;
else
#endif // USE_PTHREAD
if (dest_port != (uint_fast16_t) GET_LISTENING_PORT())
@ -864,7 +906,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
not_explicit_packet :
if (GET_MODE() == MODE_ACTIVE)
return ;
is_explicit_packet = FALSE ;
is_explicit_packet = owl_false ;
process_packet :
@ -884,8 +926,9 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
// Copy AP MAC :
memcpy(request.ap_mac_addr_bytes, my_mac_bytes, ETHER_ADDR_LEN) ;
// Capture time is in the pcap header (net-endian):
request.start_time = owl_timeval_to_timestamp(header->ts) ;
// Capture time is in the pcap header (host-endian):
request.start_time =
owl_hton_timestamp(owl_timeval_to_timestamp(header->ts)) ;
/* Active mode */
if (is_explicit_packet
@ -935,7 +978,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
printf("\nStrange explicit packet received\n") ;
fprintf(stderr,
"Error! Unknown request type (%d).\n", request.type) ;
is_explicit_packet = FALSE ;
is_explicit_packet = owl_false ;
}
if (! is_explicit_packet)
@ -977,8 +1020,8 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
if (GET_DISPLAY_CAPTURED())
{
char
request_time_str[OWL_TIMESTAMP_STR_LEN],
start_time_str[OWL_TIMESTAMP_STR_LEN] ;
request_time_str[OWL_TIMESTAMP_STRLEN],
start_time_str[OWL_TIMESTAMP_STRLEN] ;
owl_timestamp_to_string(request_time_str,
owl_ntoh_timestamp(request.request_time)) ;
owl_timestamp_to_string(start_time_str,
@ -1041,7 +1084,7 @@ void extract_calibration_data(const u_char *packet,
/*
* Fills 'request' with the required data extracted from the Radiotap
* header of 'packet'. The elements of 'rtap_fields' are set to TRUE
* header of 'packet'. The elements of 'rtap_fields' are set to owl_true
* when the corresponding Radiotap flag is found in the packet.
*/
void extract_radiotap_data(const u_char *packet,
@ -1059,7 +1102,7 @@ void extract_radiotap_data(const u_char *packet,
rtap_presentflags = le32toh(rtap_presentflags) ;
for (i = 0 ; i < 15 ; ++i) // Initialise present flags structure
rtap_fields[i] = FALSE ;
rtap_fields[i] = owl_false ;
rtap_position = 8 ; // Begining of the present flags determined fields
// Test the first 15 bits of the flag field in order to check their
@ -1071,15 +1114,15 @@ void extract_radiotap_data(const u_char *packet,
switch(i)
{
case RTAP_MACTS:
rtap_fields[RTAP_MACTS] = TRUE ;
rtap_fields[RTAP_MACTS] = owl_true ;
rtap_position += RTAP_L_MACTS ;
break ;
case RTAP_FLAGS:
rtap_fields[RTAP_FLAGS] = TRUE;
rtap_fields[RTAP_FLAGS] = owl_true;
rtap_position += RTAP_L_FLAGS ;
break ;
case RTAP_RATE:
rtap_fields[RTAP_RATE] = TRUE;
rtap_fields[RTAP_RATE] = owl_true;
rtap_position += RTAP_L_RATE ;
break ;
case RTAP_CHANNEL:
@ -1087,52 +1130,52 @@ void extract_radiotap_data(const u_char *packet,
rtap_position += RTAP_L_CHANNELTYPE ;
break ;
case RTAP_FHSS:
rtap_fields[RTAP_FHSS] = TRUE;
rtap_fields[RTAP_FHSS] = owl_true;
rtap_position += RTAP_L_FHSS ;
break ;
case RTAP_ANTENNASIGNALDBM:
memcpy(&request->antenna_signal_dbm,
&packet[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
rtap_fields[RTAP_ANTENNASIGNALDBM] = TRUE;
rtap_fields[RTAP_ANTENNASIGNALDBM] = owl_true;
if (VERBOSE_INFO)
printf("Antenna signal: %d dBm\n",
request->antenna_signal_dbm - 0x100);
rtap_position += RTAP_L_ANTENNASIGNALDBM ;
break ;
case RTAP_ANTENNANOISEDBM:
rtap_fields[RTAP_ANTENNANOISEDBM] = TRUE;
rtap_fields[RTAP_ANTENNANOISEDBM] = owl_true;
rtap_position += RTAP_L_ANTENNANOISEDBM ;
break ;
case RTAP_LOCKQUALITY:
rtap_fields[RTAP_LOCKQUALITY] = TRUE;
rtap_fields[RTAP_LOCKQUALITY] = owl_true;
rtap_position += RTAP_L_LOCKQUALITY ;
break ;
case RTAP_TXATTENUATION:
rtap_fields[RTAP_TXATTENUATION] = TRUE;
rtap_fields[RTAP_TXATTENUATION] = owl_true;
rtap_position += RTAP_L_TXATTENUATION ;
break ;
case RTAP_TXATTENUATIONDB:
rtap_fields[RTAP_TXATTENUATIONDB] = TRUE;
rtap_fields[RTAP_TXATTENUATIONDB] = owl_true;
rtap_position += RTAP_L_TXATTENUATIONDB ;
break ;
case RTAP_TXATTENUATIONDBM:
rtap_fields[RTAP_TXATTENUATIONDBM] = TRUE;
rtap_fields[RTAP_TXATTENUATIONDBM] = owl_true;
rtap_position += RTAP_L_TXATTENUATIONDBM ;
break ;
case RTAP_ANTENNA:
rtap_fields[RTAP_ANTENNA] = TRUE;
rtap_fields[RTAP_ANTENNA] = owl_true;
rtap_position += RTAP_L_ANTENNA ;
break ;
case RTAP_ANTENNASIGNALDB:
rtap_fields[RTAP_ANTENNASIGNALDB] = TRUE;
rtap_fields[RTAP_ANTENNASIGNALDB] = owl_true;
rtap_position += RTAP_L_ANTENNASIGNALDB ;
break ;
case RTAP_ANTENNANOISEDB:
rtap_fields[RTAP_ANTENNANOISEDB] = TRUE;
rtap_fields[RTAP_ANTENNANOISEDB] = owl_true;
rtap_position += RTAP_L_ANTENNANOISEDB ;
break ;
case RTAP_FCS:
rtap_fields[RTAP_FCS] = TRUE;
rtap_fields[RTAP_FCS] = owl_true;
rtap_position += RTAP_L_FCS ;
break ;
}
@ -1213,17 +1256,16 @@ void* autocalibrate_hello(void *NULL_value)
fprintf(stderr, "Autocalibration Hello thread launched.\n") ;
send_sockfd =
owlclient_create_trx_socket(GET_AGGREGATION_IP(),
GET_AUTOCALIBRATION_PORT(),
&serv, NULL) ;
owl_create_trx_socket(GET_AGGREGATION_IP(),
GET_AUTOCALIBRATION_PORT(), &serv, NULL) ;
pthread_cleanup_push(&owl_close_fd, &send_sockfd) ;
memcpy(&message.ap_mac_addr_bytes, my_mac_bytes, ETHER_ADDR_LEN) ;
while (owl_run)
{
owlclient_send_packet(send_sockfd, &serv,
&message, sizeof(message)) ;
owl_send_packet(send_sockfd, &serv,
&message, sizeof(message)) ;
sleep(GET_AUTOCALIBRATION_HELLO_DELAY()) ;
}
@ -1248,10 +1290,10 @@ void* autocalibrate(void *NULL_value)
// Socket to send autocalibration positioning requests
autocalibration_send_sockfd =
owlclient_create_trx_socket(GET_AUTOCALIBRATION_IP(),
GET_AUTOCALIBRATION_REQUEST_PORT(),
&autocalibration_send_server,
GET_WIFI_IFACE()) ;
owl_create_trx_socket(GET_AUTOCALIBRATION_IP(),
GET_AUTOCALIBRATION_REQUEST_PORT(),
&autocalibration_send_server,
GET_WIFI_IFACE()) ;
// Socket to receive orders from the aggregator
listen_sockfd =
@ -1260,7 +1302,7 @@ void* autocalibrate(void *NULL_value)
{
perror("Error! Cannot create UDP listening socket from the"
" aggregation server") ;
exit(ERR_CREATING_SOCKET) ;
exit(OWL_ERR_SOCKET_CREATE) ;
}
pthread_cleanup_push(&owl_close_fd, &listen_sockfd) ;
@ -1301,11 +1343,11 @@ void send_autocalibration_request()
uint8_t *packet ;
uint_fast16_t packet_size = make_packet(&packet) ;
owlclient_send_request(autocalibration_send_sockfd,
&autocalibration_send_server,
packet, packet_size,
GET_AUTOCALIBRATION_NBPKT(),
GET_AUTOCALIBRATION_DELAY()) ;
owl_send_request(autocalibration_send_sockfd,
&autocalibration_send_server,
packet, packet_size,
GET_AUTOCALIBRATION_NBPKT(),
GET_AUTOCALIBRATION_DELAY()) ;
free(packet) ;
}
@ -1332,7 +1374,7 @@ uint_fast16_t make_packet(uint8_t **packet)
if (VERBOSE_CHATTERBOX)
{
char request_time_str[OWL_TIMESTAMP_STR_LEN] ;
char request_time_str[OWL_TIMESTAMP_STRLEN] ;
owl_timestamp_to_string(request_time_str, request_time) ;
printf("Autocalibration time: %s\n", request_time_str) ;
}
@ -1457,10 +1499,10 @@ void print_usage()
program_name,
program_name,
DEFAULT_CONFIG_FILE,
LOC_REQUEST_DEFAULT_PORT,
AGGREGATE_DEFAULT_PORT,
DEFAULT_AUTOCALIBRATION_REQUEST_PORT,
DEFAULT_AUTOCALIBRATION_PORT,
OWL_DEFAULT_REQUEST_PORT,
OWL_DEFAULT_LISTENER_PORT,
OWL_DEFAULT_AUTOCALIBRATION_REQUEST_PORT,
OWL_DEFAULT_AUTOCALIBRATION_PORT,
DEFAULT_AUTOCALIBRATION_HELLO_DELAY,
DEFAULT_AUTOCALIBRATION_DELAY,
DEFAULT_AUTOCALIBRATION_NBPKT

View File

@ -33,9 +33,9 @@ endif
# Flags
LIBOWLPS_DIR = ../libowlps
#DEBUG = -g
TESTSGXXFLAGS = -I$(TESTS_DIR) -I$(SRC_DIR) -I.
GXXFLAGS = $(DEBUG) -O2 -Wall -Wextra -I$(LIBOWLPS_DIR)
GXXFLAGS = -O2 -Wall -Wextra -I$(LIBOWLPS_DIR)
#GXXFLAGS += -g -O0
LD = $(CXX)
LDFLAGS = -lstdc++ -lm -lboost_program_options \
-L$(LIBOWLPS_DIR) -lowlps

View File

@ -123,8 +123,9 @@ area_of_interest_number(const Point3D &position) const
*/
bool OutputTCPSocketEvAAL::send_data(const string &data) const
{
ssize_t nsent = send(sockfd, data.c_str(), data.size(), 0) ;
if (nsent != static_cast<ssize_t>(data.size()))
unsigned int data_len = data.size() + 1 ; // +1 for the '\0'
ssize_t nsent = send(sockfd, data.c_str(), data_len, 0) ;
if (nsent != static_cast<ssize_t>(data_len))
{
perror("Error sending result data through the TCPEvAAL socket") ;
return false ;

View File

@ -45,10 +45,11 @@ bool OutputUDPSocket::init_socket()
*/
bool OutputUDPSocket::send_data(const string &data) const
{
ssize_t nsent = sendto(sockfd, data.c_str(), data.size(), 0,
unsigned int data_len = data.size() + 1 ; // +1 for the '\0'
ssize_t nsent = sendto(sockfd, data.c_str(), data_len, 0,
(struct sockaddr *) &server_info,
sizeof(server_info)) ;
if (nsent != static_cast<ssize_t>(data.size()))
if (nsent != static_cast<ssize_t>(data_len))
{
perror("Error sending result data through the UDP socket") ;
return false ;

View File

@ -14,27 +14,31 @@ using namespace std ;
int main(int argc, char **argv)
{
owl_run = owl_true ;
/* Read options & configuration */
delete new UserInterface(argc, argv) ;
/* Read input data */
delete new InputDataReader() ;
if (owl_run)
{
/* Read input data */
delete new InputDataReader() ;
/* Set up signal handlers */
struct sigaction action ;
action.sa_flags = 0 ;
sigemptyset(&action.sa_mask) ;
action.sa_handler = owl_sigint_handler ;
sigaction(SIGINT, &action, NULL) ;
action.sa_handler = owl_sigterm_handler ;
sigaction(SIGTERM, &action, NULL) ;
/* Set up signal handlers */
struct sigaction action ;
action.sa_flags = 0 ;
sigemptyset(&action.sa_mask) ;
action.sa_handler = owl_sigint_handler ;
sigaction(SIGINT, &action, NULL) ;
action.sa_handler = owl_sigterm_handler ;
sigaction(SIGTERM, &action, NULL) ;
/* Run! */
owl_run = TRUE ;
Positioning positioning ;
/* Run! */
Positioning positioning ;
/* Clean */
Stock::clear() ;
/* Clean */
Stock::clear() ;
}
cerr << argv[0] << ": end." << endl ;
return 0 ;

View File

@ -678,7 +678,10 @@ closest_calibration_request(const Request &request)
// No non-AP reference point was found, we are forced to consider
// the AP reference points
if (i == calibration_requests.end())
ignore_aps = false ;
{
i = calibration_requests.begin() ;
ignore_aps = false ;
}
}
float distance = i->ss_square_distance(request) ;

View File

@ -149,7 +149,7 @@ void UserInterface::fill_input_options()
("input.csv-file,C", po::value<string>(),
"CSV file to use for input (when input.medium = CSV).")
("input.udp-port,p", po::value<int>()
->default_value(POSITIONER_DEFAULT_PORT),
->default_value(OWL_DEFAULT_AGGREGATION_PORT),
"Port on which the UDP socket listens (when input.medium = UDP).")
;
@ -263,7 +263,7 @@ void UserInterface::fill_output_options()
("output.udp-host", po::value<string>(),
"Host to which the UDP data is sent (when output.medium = UDP).")
("output.udp-port", po::value<int>()
->default_value(MOBILE_DEFAULT_PORT),
->default_value(OWL_DEFAULT_RESULT_PORT),
"Port on which the UDP data is sent (when output.medium = UDP).")
("output.tcpevaal-host", po::value<string>()
->default_value(DEFAULT_TCPEVAAL_HOST),
@ -293,7 +293,9 @@ void UserInterface::fill_misc_options()
void UserInterface::parse_options()
{
parse_command_line() ;
print_information_and_exit_if_requested() ;
print_information() ;
if (! owl_run)
return ;
parse_file() ;
@ -310,10 +312,12 @@ void UserInterface::parse_command_line() const
}
void UserInterface::print_information_and_exit_if_requested() const
/**
* If information is printed, owl_run is set to false, to indicate that
* the program should stop.
*/
void UserInterface::print_information() const
{
bool exit_program = false ;
// Print version if requested
if (Configuration::is_configured("version"))
{
@ -326,18 +330,15 @@ void UserInterface::print_information_and_exit_if_requested() const
"unknown version"
#endif // OWLPS_VERSION
<< ".\n" ;
exit_program = true ;
owl_run = owl_false ; // Tell main() to exit
}
// Print usage if requested
if (Configuration::is_configured("help"))
{
cout << *cli_options ;
exit_program = true ;
owl_run = owl_false ; // Tell main() to exit
}
if (exit_program)
exit(0) ;
}

View File

@ -37,7 +37,7 @@ protected:
void parse_file(void) const ;
/// Prints usage and/or version information if requested by the user
void print_information_and_exit_if_requested(void) const ;
void print_information(void) const ;
//@}
public:

110
owlps-udp-to-http/Makefile Normal file
View File

@ -0,0 +1,110 @@
# Source version
ifndef OWLPS_VERSION
OWLPS_VERSION := $(shell git describe 2>/dev/null || echo 'UNKNOWN_VERSION')
endif
# Répertoire d'installation
PREFIX=/usr/local
INSTALL_DIR= $(PREFIX)/bin
INSTALL_LIB= $(PREFIX)/lib
INSTALL_INC= $(PREFIX)/include
INSTALL_MAN= $(PREFIX)/share/man
# Compilateur
COLORGCC := $(shell which colorgcc >/dev/null 2>&1 ; echo $$?)
ifeq ($(COLORGCC), 0)
CC = colorgcc
endif
# Commandes d'installation et de désinstallation
RM = rm -f
CP = cp
# Cible
TARGET = owlps-udp-to-http
HEADER =
# Flags
LIBOWLPS_DIR = ../libowlps
LIBOWLPSRESULTREADER_DIR = ../libowlps-resultreader
CFLAGS = -O2 -Wall -Wextra -Wstrict-prototypes \
-I$(LIBOWLPS_DIR) -I$(LIBOWLPSRESULTREADER_DIR)
#CFLAGS += -g -O0
DEPFLAGS = -MMD
XCFLAGS = $(CFLAGS) $(DEPFLAGS) $(WARN) $(HEADERS)
PICFLAG = -fPIC
OWLPSFLAGS = -D OWLPS_VERSION=\"$(OWLPS_VERSION)\"
OWLPSFLAGS += -D DEBUG
LIBS = -pthread -L$(LIBOWLPS_DIR) -lowlps \
-L$(LIBOWLPSRESULTREADER_DIR) -lowlps-resultreader
OS := $(shell uname)
ifeq ("$(OS)", "Linux")
LIBS += -lrt
endif
STATIC_LIBS =
## Cibles de compilation standard ##
.PHONY : all dynamic static install uninstall clean purge help
dynamic : $(TARGET)
static : $(TARGET).static
all : dynamic static
# Cancel implicit make rule
%: %.c
%: %.o
$(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS)
%.static: %.o
$(CC) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ \
$(LDFLAGS) $(LIBS) $(STATIC_LIBS) -static
%.o: %.c $(HEADER)
$(CC) $(XCFLAGS) $(OWLPSFLAGS) -c $<
## Installation / désinstallation ##
install : $(TARGET)
@$(CP) $(TARGET) $(INSTALL_DIR)
@cd $(INSTALL_DIR) ; chown root:root $(TARGET) ; chmod 755 $(TARGET)
install-static : $(TARGET).static
@$(CP) $(TARGET).static $(INSTALL_DIR)
@cd $(INSTALL_DIR) ; chown root:root $(TARGET).static ; chmod 755 $(TARGET).static
uninstall :
@$(RM) $(INSTALL_DIR)/{$(TARGET),$(TARGET).static}
## Nettoyage ##
clean :
@$(RM) *~ *.o *.d
purge : clean
@$(RM) $(TARGET) $(TARGET).static
## Aide ##
help :
@echo "Bibliothèques nécessaires à la compilation :"
@echo " libowlps1.0 (fournie)"
@echo " libowlps-resultreader1.0 (fournie)"
@echo
@echo "Cibles possibles :"
@echo " $(TARGET) (cible par défaut) : Compile le programme \
$(TARGET)."
@echo " $(TARGET).static : Compile le programme $(TARGET).static \
(version sans lien dynamique)."
@echo " install : Installe le programme $(TARGET)."
@echo " uninstall : Désinstalle le programme $(TARGET)."
@echo " clean : Supprime les fichiers temporaires."
@echo " purge : Supprime le résultat de la compilation."
@echo
@echo "Note : l'installation se fait dans l'arborescence $(PREFIX). \
Modifiez la variable PREFIX du Makefile pour changer ce comportement."

View File

@ -0,0 +1,512 @@
/*
* This program listens for results sent by OwlPS Positioning on a UDP
* socket, and listens for a client on a TCP socket. The client is
* expected to send an HTTP GET request, with the request string as the
* first variable value (the variable name does not matter).
* For example, a correct request is detected if you load
* http://localhost:8080/?request=ReadSimpleResults
* (assuming the host running this program is localhost).
*
* The UDP listening port is the port on which OwlPS Positioning sends
* result by default.
* The TCP listening port is 8080.
*
* Only the last result read from the positioning server, for each
* mobile, is memorised and provided to the HTTP client.
*
* The HTTP requests currently implemented are listed bellow.
*
* ** Request "ReadResults" **
* Answer in case of error:
* Results;NOK;Explanation
* Normal answer:
* Results;OK;Nb_results;Result_1;;Result_n
* Nb_results is the number of results in the answer (number of mobiles).
* Result_i follows this format:
* Mobile_MAC;Request_type;Request_timestamp;Nb_algo;Algo_1;;Algo_n
* Nb_algo is the number of algorithms in the result.
* Algo_i follows this format:
* Algorithm_name;X;Y;Z;Error;Area_name
* Error is the distance from the true coordinates of the mobile, if
* known; if unknown, Error is set to -1.
* Area_name is the name of the area or room in which the mobile is (may
* be empty).
*
* ** Unknown request **
* If a unknown request is received, the answer format is:
* UnknownRequest;NOK
*
* ** Request "ReadSimpleResults" **
* Answer in case of error:
* SimpleResults;NOK;Explanation
* Normal answer:
* SimpleResults;OK;Nb_results;Result_1;;Result_n
* Nb_results is the number of results in the answer (number of mobiles).
* Result_i follows this format:
* Mobile_MAC;X;Y;Z;Area_name
* Area_name is the name of the area or room in which the mobile is (may
* be empty).
*/
#include "owlps-udp-to-http.h"
#include <signal.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <assert.h>
char *program_name = NULL ;
results_list *results = NULL ;
unsigned int nb_results = 0 ;
sem_t lock_results ;
int udp_sockfd = -1 ;
int tcp_sockfd = -1 ;
char *answer = NULL ; // Answer to send to the client
size_t answer_strlen = 0 ; // Total size of the answer string
size_t answer_buflen = 0 ; // Size of the answer allocated buffer
int main(int argc, char *argv[])
{
struct sigaction action ; // Signal handler structure
int ret = 0 ; // Program return value
pthread_t tcp_server_thread ;
program_name = argv[0] ;
owl_run = owl_true ;
if (argc > 1)
fprintf(stderr,
"Sorry, this program does not take any argument yet.\n") ;
/* Set up signal handlers */
action.sa_flags = 0 ;
sigemptyset(&action.sa_mask) ;
action.sa_handler = owl_sigint_handler ;
sigaction(SIGINT, &action, NULL) ;
action.sa_handler = owl_sigterm_handler ;
sigaction(SIGTERM, &action, NULL) ;
/* Set up the semaphore */
sem_init(&lock_results, 0, 1) ;
/* Prepare the TCP socket */
ret = init_tcp_socket() ;
if (ret)
goto exit ;
/* Launch the TCP thread */
ret = pthread_create(&tcp_server_thread, NULL,
&tcp_server, NULL) ;
if (ret)
{
perror("Cannot create the TCP server thread") ;
ret = OWL_ERR_THREAD_CREATE ;
goto exit ;
}
/* Main loop */
ret = receive_udp() ;
/* Stop the TCP thread */
// We must cancel the thread because it can be blocked on the
// recv() call:
if (pthread_cancel(tcp_server_thread))
perror("Cannot cancel the TCP server thread") ;
if (pthread_join(tcp_server_thread, NULL))
perror("Cannot join the TCP server thread") ;
exit:
/* Close sockets */
if (tcp_sockfd >= 0)
if (close(tcp_sockfd))
perror("Error closing the TCP socket") ;
if (udp_sockfd >= 0)
if (close(udp_sockfd))
perror("Error closing the UDP socket") ;
/* Last cleaning */
free(answer) ;
free_results_list() ;
sem_destroy(&lock_results) ;
printf("%s: end.\n", program_name) ;
return ret ;
}
/*
* Opens the UDP socket and reads from it the results sent by OwlPS
* Positioning.
* Returns a non-zero value in case of error.
*/
int receive_udp()
{
owl_result *result ;
/* Open the UDP socket */
udp_sockfd = owl_create_udp_listening_socket(OWL_DEFAULT_RESULT_PORT) ;
if (udp_sockfd < 0)
return OWL_ERR_SOCKET_CREATE ;
/* UDP read loop */
while (owl_run)
{
result = owl_receive_position(udp_sockfd) ;
if (result == NULL)
return OWL_ERR_SOCKET_RECV ;
owl_print_result(result) ;
store_result(result) ;
printf("--------------\n") ;
}
return 0 ;
}
/*
* Adds a new owl_result to the results' list.
*/
void store_result(owl_result *new_result)
{
sem_wait(&lock_results) ;
// The results' list does not exist yet
if (! results)
{
results = malloc(sizeof(results_list)) ;
++nb_results ;
results->result = new_result ;
results->next = NULL ;
}
// The results' list contains at least 1 element
else
{
// Search for an existing result with the same mobile's MAC
results_list *res = results ;
while (res != NULL)
{
char *mac = res->result->mobile_mac_addr ;
if (strncmp(mac, new_result->mobile_mac_addr,
OWL_ETHER_ADDR_STRLEN) == 0)
break ;
res = res->next ;
}
if (res == NULL) // Not found, adding an element
{
res = malloc(sizeof(results_list)) ;
++nb_results ;
res->next = results ;
results = res ;
}
else // Found, clearing it
owl_free_result(res->result) ;
res->result = new_result ;
}
sem_post(&lock_results) ;
}
/*
* Opens the TCP socket.
* Returns a non-zero value in case of error.
*/
int init_tcp_socket()
{
struct sockaddr_in server_addr ;
tcp_sockfd = socket(AF_INET, SOCK_STREAM, 0) ;
if (tcp_sockfd < 0)
{
perror("Error opening the TCP socket") ;
return OWL_ERR_SOCKET_CREATE ;
}
bzero((char *) &server_addr, sizeof(server_addr)) ;
server_addr.sin_family = AF_INET ;
server_addr.sin_addr.s_addr = INADDR_ANY ;
server_addr.sin_port = htons(TCP_PORT) ;
if (bind(tcp_sockfd, (struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0)
{
perror("Error binding the TCP socket") ;
return OWL_ERR_SOCKET_CREATE ;
}
return 0 ;
}
/*
* Waits for requests from HTTP clients.
*/
void* tcp_server(void *NULL_value)
{
int newsockfd ;
socklen_t client_len ;
struct sockaddr_in client_addr ;
ssize_t nbytes ; // recv/send return value
char client_message[CLIENT_MESSAGE_STRLEN] ;
char client_request[CLIENT_REQUEST_STRLEN] ;
int request_id ;
listen(tcp_sockfd, NB_CONNECTIONS) ;
client_len = sizeof(client_addr) ;
// Prepare the answer, assuming there is only 1 full result (an error
// message will also fit)
answer_buflen = ANSWER_HDR_STRLEN + OWL_CSV_RESULT_STRLEN ;
answer = malloc(answer_buflen) ;
strncpy(answer, ANSWER_HDR, ANSWER_HDR_STRLEN) ;
while (owl_run)
{
newsockfd = accept(tcp_sockfd,
(struct sockaddr*) &client_addr, &client_len) ;
if (newsockfd < 0)
{
perror("Error accepting a connection on the TCP socket") ;
continue ;
}
nbytes =
recv(newsockfd, client_message, CLIENT_MESSAGE_STRLEN, 0) ;
if (nbytes < 0)
{
perror("Error reading from the TCP socket") ;
close(newsockfd) ;
continue ;
}
client_message[nbytes] = '\0' ;
#ifdef DEBUG
printf("Got a message from the client:\n"
"\"%s\"\n", client_message) ;
#endif // DEBUG
request_id =
extract_request_from_message(client_request, client_message) ;
prepare_answer(request_id) ;
#ifdef DEBUG
printf("Answer to send:\n\"%s\"\n", answer) ;
#endif // DEBUG
/* Send the answer */
nbytes = send(newsockfd, answer, answer_strlen, 0) ;
if (nbytes < 0)
perror("Error sending answer to the TCP socket") ;
close(newsockfd) ;
}
pthread_exit(NULL_value) ;
}
/*
* Reads a message and search for a request in it.
* Returns the identifier of a request if found, or 0 if not found.
*/
int
extract_request_from_message(char client_request[CLIENT_REQUEST_STRLEN],
char *client_message)
{
char *token ;
token = strchr(client_message, '=') ;
if (! token)
return 0 ;
++token ;
token = strsep(&token, " ") ;
if (strncmp(SIMPLE_RESULTS_REQUEST, token,
strlen(SIMPLE_RESULTS_REQUEST)) == 0)
{
strncpy(client_request, SIMPLE_RESULTS_REQUEST,
CLIENT_REQUEST_STRLEN) ;
return SIMPLE_RESULTS_ID ;
}
if (strncmp(RESULTS_REQUEST, token,
strlen(RESULTS_REQUEST)) == 0)
{
strncpy(client_request, RESULTS_REQUEST,
CLIENT_REQUEST_STRLEN) ;
return RESULTS_ID ;
}
return 0 ; // No known request found
}
/*
* Prepare the answer string to send to the TCP client.
*/
void prepare_answer(int request_id)
{
// Reset the answer's length:
answer_strlen = ANSWER_HDR_STRLEN ;
switch (request_id)
{
case RESULTS_ID:
strncpy(answer + answer_strlen, RESULTS_ANSWER,
strlen(RESULTS_ANSWER)) ;
answer_strlen += strlen(RESULTS_ANSWER) ;
sem_wait(&lock_results) ;
if (! results)
{
char answer_end[] = ";NOK;NoResult" ;
strncpy(answer + answer_strlen, answer_end,
strlen(answer_end)) ;
answer_strlen += strlen(answer_end) ;
}
else
{
results_list *result ;
char answer_begin[10] ;
size_t answer_begin_len ;
snprintf(answer_begin, 10, ";OK;%u", nb_results) ;
answer_begin_len = strlen(answer_begin) ;
strncpy(answer + answer_strlen, answer_begin,
answer_begin_len) ;
answer_strlen += answer_begin_len ;
realloc_answer(answer_strlen +
nb_results * OWL_CSV_RESULT_STRLEN) ;
result = results ;
while (result != NULL)
{
char result_str[OWL_CSV_RESULT_STRLEN] ;
size_t result_len ;
owl_result_to_csv(result_str, result->result) ;
result_len = strlen(result_str) ;
answer[answer_strlen++] = ';' ;
assert(answer_strlen<answer_buflen) ;
strncpy(answer + answer_strlen, result_str,
result_len) ;
answer_strlen += result_len ;
result = result->next ;
}
}
sem_post(&lock_results) ;
break ;
case SIMPLE_RESULTS_ID:
strncpy(answer + answer_strlen, SIMPLE_RESULTS_ANSWER,
strlen(SIMPLE_RESULTS_ANSWER)) ;
answer_strlen += strlen(SIMPLE_RESULTS_ANSWER) ;
sem_wait(&lock_results) ;
if (! results)
{
char answer_end[] = ";NOK;NoResult" ;
strncpy(answer + answer_strlen, answer_end,
strlen(answer_end)) ;
answer_strlen += strlen(answer_end) ;
}
else
{
results_list *result ;
char answer_begin[10] ;
size_t answer_begin_len ;
snprintf(answer_begin, 10, ";OK;%u", nb_results) ;
answer_begin_len = strlen(answer_begin) ;
strncpy(answer + answer_strlen, answer_begin,
answer_begin_len) ;
answer_strlen += answer_begin_len ;
realloc_answer(answer_strlen +
nb_results * OWL_CSV_RESULT_SIMPLE_STRLEN) ;
result = results ;
while (result != NULL)
{
char result_str[OWL_CSV_RESULT_SIMPLE_STRLEN] ;
size_t result_len ;
owl_result_to_csv_simple(result_str, result->result) ;
result_len = strlen(result_str) ;
answer[answer_strlen++] = ';' ;
strncpy(answer + answer_strlen, result_str,
result_len) ;
answer_strlen += result_len ;
result = result->next ;
}
}
sem_post(&lock_results) ;
break ;
default:
{
char answer_end[] = "UnknownRequest;NOK" ;
strncpy(answer + ANSWER_HDR_STRLEN, answer_end,
strlen(answer_end)) ;
answer_strlen += strlen(answer_end) ;
}
}
answer[answer_strlen] = '\0' ;
}
/*
* Realloc the answer buffer to the if needed: grows it if new_size is
* greater than the current size, shrink it if the current size is
* greater than the double of new_size.
*/
void realloc_answer(size_t new_size)
{
if (new_size > answer_buflen)
answer_buflen = new_size ;
else if (answer_buflen / 2 >= new_size)
answer_buflen /= 2 ;
else
return ;
answer = realloc(answer, answer_buflen) ;
}
/*
* Frees the memory allocated for the results' list.
*/
void free_results_list()
{
results_list *tmp_res ;
while (results != NULL)
{
owl_free_result(results->result) ;
tmp_res = results ;
results = results->next ;
free(tmp_res) ;
}
nb_results = 0 ;
}

View File

@ -0,0 +1,52 @@
#ifndef _OWLPS_UDP_TO_HTTP_H_
#define _OWLPS_UDP_TO_HTTP_H_
#include <owlps-resultreader.h>
#define TCP_PORT 8080
#define NB_CONNECTIONS 1
#define CLIENT_MESSAGE_STRLEN 2500
#define CLIENT_REQUEST_STRLEN 21
#define SIMPLE_RESULTS_ID 1
#define SIMPLE_RESULTS_REQUEST "ReadSimpleResults"
#define SIMPLE_RESULTS_ANSWER "SimpleResults"
#define RESULTS_ID 2
#define RESULTS_REQUEST "ReadResults"
#define RESULTS_ANSWER "Results"
#ifndef OWLPS_VERSION
# define OWLPS_VERSION "unknown version"
#endif // OWLPS_VERSION
#define ANSWER_HDR \
"HTTP/1.1 200 OK\n" \
"Date: Sat, 01 Jan 0001 00:00:01 GMT\n" \
"Server: OwlPS UDP-to-HTTP ["OWLPS_VERSION"]\n" \
"Access-Control-Allow-Origin: *\n" \
"Connection: close\n" \
"Content-Type: text/html\n" \
"\n"
#define ANSWER_HDR_STRLEN strlen(ANSWER_HDR)
typedef struct _results_list
{
owl_result *result ;
struct _results_list *next ;
} results_list ;
int receive_udp(void) ;
void store_result(owl_result *result) ;
int init_tcp_socket(void) ;
void* tcp_server(void *NULL_value) ;
int
extract_request_from_message(char client_request[CLIENT_REQUEST_STRLEN],
char *client_message) ;
void prepare_answer(int request_id) ;
void realloc_answer(size_t new_size) ;
void free_results_list(void) ;
#endif // _OWLPS_UDP_TO_HTTP_H_