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:
commit
7b7766ab5b
82
Makefile
82
Makefile
|
@ -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
49
TODO
|
@ -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().
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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."
|
|
@ -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) ;
|
||||
}
|
|
@ -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 ;
|
||||
}
|
|
@ -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_
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) ;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) ;
|
||||
|
|
|
@ -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
|
||||
) ;
|
||||
|
|
|
@ -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
|
||||
) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -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) ;
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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."
|
|
@ -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 ;
|
||||
}
|
|
@ -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_
|
Loading…
Reference in New Issue