2008-02-14 08:54:51 +01:00
|
|
|
/*
|
2013-05-29 18:43:35 +02:00
|
|
|
* This file is part of the Owl Positioning System (OwlPS) project.
|
|
|
|
* It is subject to the copyright notice and license terms in the
|
|
|
|
* COPYRIGHT.t2t file found in the top-level directory of this
|
|
|
|
* distribution and at
|
|
|
|
* http://code.lm7.fr/p/owlps/source/tree/master/COPYRIGHT.t2t
|
|
|
|
* No part of the OwlPS Project, including this file, may be copied,
|
|
|
|
* modified, propagated, or distributed except according to the terms
|
|
|
|
* contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
|
|
|
|
* distributed along with this file, either separately or by replacing
|
|
|
|
* this notice by the COPYRIGHT.t2t file's contents.
|
2012-11-03 14:52:33 +01:00
|
|
|
*
|
|
|
|
***********************************************************************
|
|
|
|
*
|
2012-02-06 16:44:09 +01:00
|
|
|
* This is the main source file of libowlps.
|
2008-02-14 08:54:51 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2008-10-06 17:27:33 +02:00
|
|
|
#include "owlps.h"
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2011-03-29 18:30:00 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2012-02-02 20:27:48 +01:00
|
|
|
#include <sys/time.h>
|
2011-03-29 18:30:00 +02:00
|
|
|
#include <signal.h>
|
|
|
|
|
2011-06-23 13:16:58 +02:00
|
|
|
#include <arpa/inet.h>
|
2013-09-20 23:07:46 +02:00
|
|
|
#include <netdb.h>
|
2011-06-23 13:16:58 +02:00
|
|
|
|
2011-04-07 14:31:31 +02:00
|
|
|
#include <assert.h>
|
|
|
|
|
2008-03-14 11:31:04 +01:00
|
|
|
|
|
|
|
|
2013-05-15 21:46:13 +02:00
|
|
|
bool owl_run = true ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2011-04-07 12:08:41 +02:00
|
|
|
/* *** Miscellaneous functions *** */
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts a MAC address from bytes to character string.
|
2011-03-25 10:16:41 +01:00
|
|
|
* The string is allocated in a static buffer, and will be overwritten
|
|
|
|
* each time this function is called.
|
2014-02-18 16:22:35 +01:00
|
|
|
* **This function is not thread-safe!** Please use the reentrant version
|
|
|
|
* owl_mac_bytes_to_string_r() if concurrent calls are possible.
|
2013-06-04 02:28:13 +02:00
|
|
|
*
|
|
|
|
* @returns A pointer to the static buffer containing the character
|
|
|
|
* string. This pointer must *not* be freed manually by the caller.
|
2008-02-14 08:54:51 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2011-03-25 10:16:41 +01:00
|
|
|
static char mac_str[OWL_ETHER_ADDR_STRLEN] ;
|
|
|
|
owl_mac_bytes_to_string_r(mac_binary, mac_str) ;
|
|
|
|
return mac_str ;
|
|
|
|
}
|
|
|
|
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts a MAC address from bytes to character string.
|
|
|
|
* The `mac_str` buffer must be allocated by the caller and its length
|
|
|
|
* must be of at least `OWL_ETHER_ADDR_STRLEN`.
|
2011-03-25 10:16:41 +01:00
|
|
|
* This function is thread-safe.
|
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary,
|
2011-03-25 10:16:41 +01:00
|
|
|
char mac_str[OWL_ETHER_ADDR_STRLEN])
|
|
|
|
{
|
2011-06-23 17:38:08 +02:00
|
|
|
snprintf(mac_str, OWL_ETHER_ADDR_STRLEN,
|
|
|
|
"%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
mac_binary[0], mac_binary[1], mac_binary[2],
|
|
|
|
mac_binary[3], mac_binary[4], mac_binary[5]) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
2011-04-05 13:42:10 +02:00
|
|
|
* Compares two MAC addresses.
|
2013-06-04 02:28:13 +02:00
|
|
|
*
|
|
|
|
* @returns `true` if the two addresses are identical, `false` otherwise.
|
2011-04-05 13:42:10 +02:00
|
|
|
*/
|
2013-05-15 21:46:13 +02:00
|
|
|
bool owl_mac_equals(const uint8_t *const mac1,
|
|
|
|
const uint8_t *const mac2)
|
2011-04-05 13:42:10 +02:00
|
|
|
{
|
|
|
|
int i ;
|
2012-05-25 12:23:06 +02:00
|
|
|
for (i = ETHER_ADDR_LEN - 1 ; i >= 0 ; --i)
|
2011-04-05 13:42:10 +02:00
|
|
|
if(mac1[i] != mac2[i])
|
2013-05-15 21:46:13 +02:00
|
|
|
return false ;
|
|
|
|
return true ;
|
2011-04-05 13:42:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts a IEEE 802.11 frequency (in MHz) into a channel number.
|
|
|
|
*
|
|
|
|
* @returns The channel number corresponding to `frequency`.
|
|
|
|
* @returns 0 if the frequency does not correspond to an official
|
|
|
|
* channel.
|
2011-03-09 17:42:58 +01:00
|
|
|
*/
|
2013-06-03 20:32:37 +02:00
|
|
|
uint_fast8_t owl_frequency_to_channel(const uint_fast16_t frequency)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2013-06-03 20:32:37 +02:00
|
|
|
switch (frequency)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_1 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 1 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_2 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 2 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_3 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 3 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_4 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 4 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_5 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 5 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_6 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 6 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_7 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 7 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_8 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 8 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_9 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 9 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_10 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 10 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_11 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 11 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_12 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 12 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_13 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 13 ;
|
2011-05-09 14:14:50 +02:00
|
|
|
case OWL_80211_MHZ_CHANNEL_14 :
|
2013-06-03 20:32:37 +02:00
|
|
|
return 14 ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
2013-06-03 20:32:37 +02:00
|
|
|
return 0 ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-04-07 12:08:41 +02:00
|
|
|
/* *** Time *** */
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
2011-08-24 15:31:10 +02:00
|
|
|
* Sleeps for a given amount of milliseconds.
|
2013-06-04 02:28:13 +02:00
|
|
|
* `time_ms` is an unsigned value, so please be careful: passing a
|
2011-08-24 15:31:10 +02:00
|
|
|
* negative value may not do what you think.
|
2013-06-04 02:28:13 +02:00
|
|
|
* In case of error, a message is displayed on the standard error.
|
|
|
|
*
|
|
|
|
* @returns 0 if everything went well.
|
|
|
|
* @returns A non-zero error code in case of error; if positive, it is
|
|
|
|
* the number of non-slept seconds.
|
2011-08-24 15:31:10 +02:00
|
|
|
*/
|
|
|
|
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 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Sets the `owl_timestamp` `now` to the current time.
|
|
|
|
*
|
|
|
|
* @returns 0 in case of success, non-zero otherwise.
|
2011-03-10 15:04:12 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
int owl_timestamp_now(owl_timestamp *const now)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2011-03-10 19:38:27 +01:00
|
|
|
int ret ;
|
2012-02-02 20:27:48 +01:00
|
|
|
|
|
|
|
#if _POSIX_TIMERS > 0
|
2011-03-14 11:31:38 +01:00
|
|
|
struct timespec now_ts ;
|
2012-02-02 20:27:48 +01:00
|
|
|
ret = clock_gettime(CLOCK_REALTIME, &now_ts) ;
|
|
|
|
#else // _POSIX_TIMERS
|
|
|
|
struct timeval now_ts ;
|
|
|
|
ret = gettimeofday(&now_ts, NULL) ;
|
|
|
|
#endif // _POSIX_TIMERS
|
|
|
|
|
|
|
|
if (ret)
|
2011-03-10 15:51:42 +01:00
|
|
|
{
|
|
|
|
perror("Cannot get the current time") ;
|
2011-03-10 19:38:27 +01:00
|
|
|
return ret ;
|
2011-03-10 15:51:42 +01:00
|
|
|
}
|
2011-03-14 11:31:38 +01:00
|
|
|
|
2012-02-02 20:27:48 +01:00
|
|
|
#if _POSIX_TIMERS > 0
|
2012-01-07 00:43:21 +01:00
|
|
|
owl_timespec_to_timestamp(&now_ts, now) ;
|
2012-02-02 20:27:48 +01:00
|
|
|
#else // _POSIX_TIMERS
|
|
|
|
owl_timeval_to_timestamp(&now_ts, now) ;
|
|
|
|
#endif // _POSIX_TIMERS
|
2011-03-14 11:31:38 +01:00
|
|
|
|
2011-03-10 19:38:27 +01:00
|
|
|
return 0 ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts the `struct timespec` `src` into the `owl_timestamp` `dst`.
|
|
|
|
* `src` and `dst` must not be `NULL`.
|
2011-03-14 11:31:38 +01:00
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
void owl_timespec_to_timestamp(const struct timespec *const src,
|
|
|
|
owl_timestamp *const dst)
|
2011-03-14 11:31:38 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(src) ;
|
|
|
|
assert(dst) ;
|
|
|
|
dst->tv_sec = src->tv_sec ;
|
|
|
|
dst->tv_nsec = src->tv_nsec ;
|
2011-03-14 11:31:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts the `struct timeval` `src` into the `owl_timestamp` `dst`.
|
|
|
|
* `src` and `dst` must not be `NULL`.
|
2011-03-10 15:51:42 +01:00
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
void owl_timeval_to_timestamp(const struct timeval *const src,
|
|
|
|
owl_timestamp *const dst)
|
2011-03-10 15:51:42 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(src) ;
|
|
|
|
assert(dst) ;
|
|
|
|
dst->tv_sec = src->tv_sec ;
|
|
|
|
dst->tv_nsec = src->tv_usec * 1000u ;
|
2011-03-10 15:51:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Compares two `owl_timestamp` and returns `true` if they are equal,
|
|
|
|
* `false` otherwise.
|
|
|
|
* `d1` and `d2` must not be `NULL`.
|
|
|
|
*/
|
2013-05-15 21:46:13 +02:00
|
|
|
bool owl_timestamp_equals(const owl_timestamp *const d1,
|
|
|
|
const owl_timestamp *const d2)
|
2011-03-25 10:37:06 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(d1) ;
|
|
|
|
assert(d2) ;
|
|
|
|
return d1->tv_sec == d2->tv_sec && d1->tv_nsec == d2->tv_nsec ;
|
2011-03-25 10:37:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts the `owl_timestamp` date value `d` into milliseconds.
|
|
|
|
* `d` must not be `NULL`.
|
|
|
|
*
|
|
|
|
* @returns The millisecond value of `d`.
|
2011-03-10 15:51:42 +01:00
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
uint64_t owl_timestamp_to_ms(const owl_timestamp *const d)
|
2010-01-11 19:40:45 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(d) ;
|
|
|
|
return
|
|
|
|
(uint64_t) d->tv_sec * 1000u + (uint64_t) d->tv_nsec / 1000000lu ;
|
2010-01-11 19:40:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts the `owl_timestamp` date value `src` into a printable string.
|
|
|
|
* `src` must not be `NULL`.
|
|
|
|
* `dst` must be an allocated array of at least `OWL_TIMESTAMP_STRLEN`
|
2011-03-15 13:50:00 +01:00
|
|
|
* characters.
|
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
void owl_timestamp_to_string(const owl_timestamp *const src,
|
|
|
|
char *const dst)
|
2011-03-15 13:50:00 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(src) ;
|
|
|
|
assert(dst) ;
|
2012-07-13 16:35:00 +02:00
|
|
|
snprintf(dst, OWL_TIMESTAMP_STRLEN, "%"PRIu32".%09"PRIu32,
|
2012-01-07 00:43:21 +01:00
|
|
|
src->tv_sec, src->tv_nsec) ;
|
2011-03-15 13:50:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Returns the time (in milliseconds) elapsed between two `owl_timestamp`
|
|
|
|
* `d1` and `d2`. `d1` can either be lower (before) or greater (after)
|
|
|
|
* `d2`, the returned value will always be the delay between the older
|
|
|
|
* and the newer time.
|
|
|
|
* `d1` and `d2` must not be NULL.
|
2011-03-09 17:42:58 +01:00
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
uint_fast32_t owl_time_elapsed_ms(const owl_timestamp *const d1,
|
|
|
|
const owl_timestamp *const d2)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2012-01-06 13:45:47 +01:00
|
|
|
owl_timestamp elapsed ;
|
2012-01-07 00:43:21 +01:00
|
|
|
owl_time_elapsed(d1, d2, &elapsed) ;
|
|
|
|
return owl_timestamp_to_ms(&elapsed) ;
|
2011-03-15 13:58:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Computes the time difference between two `owl_timestamp` `d1` and
|
|
|
|
* `d2`. The result is stored in the `elapsed` parameter.
|
2012-01-06 13:45:47 +01:00
|
|
|
* Note that it is a delay, not a simple substraction, therefore the
|
2013-06-04 02:28:13 +02:00
|
|
|
* result is always positive.
|
|
|
|
* NULL parameters are not accepted.
|
2011-03-15 13:58:39 +01:00
|
|
|
*/
|
2012-01-06 13:45:47 +01:00
|
|
|
void owl_time_elapsed(const owl_timestamp *const d1,
|
|
|
|
const owl_timestamp *const d2,
|
|
|
|
owl_timestamp *const elapsed)
|
2011-03-15 13:58:39 +01:00
|
|
|
{
|
2012-01-06 13:45:47 +01:00
|
|
|
int_fast32_t sec, nsec ;
|
|
|
|
|
|
|
|
assert(d1) ;
|
|
|
|
assert(d2) ;
|
|
|
|
assert(elapsed) ;
|
|
|
|
|
|
|
|
sec = (int_fast64_t) d1->tv_sec - d2->tv_sec ;
|
|
|
|
nsec = (int_fast64_t) d1->tv_nsec - d2->tv_nsec ;
|
|
|
|
|
|
|
|
if (sec == 0)
|
|
|
|
{
|
|
|
|
elapsed->tv_sec = 0 ;
|
|
|
|
elapsed->tv_nsec = abs(nsec) ;
|
|
|
|
}
|
|
|
|
else if (sec > 0)
|
|
|
|
{
|
|
|
|
if (nsec >= 0)
|
|
|
|
{
|
|
|
|
elapsed->tv_sec = sec ;
|
|
|
|
elapsed->tv_nsec = nsec ;
|
|
|
|
}
|
|
|
|
else // nsec < 0
|
|
|
|
{
|
|
|
|
elapsed->tv_sec = sec - 1 ;
|
|
|
|
elapsed->tv_nsec = nsec + 1000000000ul ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // sec < 0
|
|
|
|
{
|
|
|
|
if (nsec > 0)
|
|
|
|
{
|
|
|
|
elapsed->tv_sec = abs(sec) - 1 ;
|
|
|
|
elapsed->tv_nsec = 1000000000ul - nsec ;
|
|
|
|
}
|
|
|
|
else // nsec <= 0
|
|
|
|
{
|
|
|
|
elapsed->tv_sec = abs(sec) ;
|
|
|
|
elapsed->tv_nsec = abs(nsec) ;
|
|
|
|
}
|
|
|
|
}
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-07 14:31:31 +02:00
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/* *** Endianness *** */
|
2011-04-07 14:31:31 +02:00
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts an `owl_timestamp` from host endianness to network
|
|
|
|
* endianness.
|
|
|
|
* The conversion is done in-place. `d` must not be `NULL`.
|
2011-03-14 11:20:57 +01:00
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
void owl_hton_timestamp(owl_timestamp *const d)
|
2011-03-14 11:20:57 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(d) ;
|
|
|
|
d->tv_sec = htonl(d->tv_sec) ;
|
|
|
|
d->tv_nsec = htonl(d->tv_nsec) ;
|
2011-03-14 11:20:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Converts an `owl_timestamp` from network endianness to host
|
|
|
|
* endianness.
|
|
|
|
* The conversion is done in-place. `d` must not be `NULL`.
|
2011-03-14 11:20:57 +01:00
|
|
|
*/
|
2012-01-07 00:43:21 +01:00
|
|
|
void owl_ntoh_timestamp(owl_timestamp *const d)
|
2011-03-14 11:20:57 +01:00
|
|
|
{
|
2012-01-07 00:43:21 +01:00
|
|
|
assert(d) ;
|
|
|
|
d->tv_sec = ntohl(d->tv_sec) ;
|
|
|
|
d->tv_nsec = ntohl(d->tv_nsec) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* This function swaps the bytes composing a `float`, i.e. it changes
|
|
|
|
* their order.
|
2013-09-11 23:32:56 +02:00
|
|
|
* You probably want to use the owl_htonf() and owl_ntohf() macros
|
2011-04-07 14:31:31 +02:00
|
|
|
* instead of this function.
|
2013-06-04 02:28:13 +02:00
|
|
|
*
|
|
|
|
* @returns The swapped `float`.
|
2011-04-07 14:31:31 +02:00
|
|
|
*/
|
|
|
|
float owl_swap_float(const float f)
|
|
|
|
{
|
|
|
|
float ret ;
|
|
|
|
char
|
|
|
|
*f_bytes = (char*) &f,
|
|
|
|
*ret_bytes = (char*) &ret ;
|
|
|
|
|
|
|
|
assert(sizeof(float) == 4) ;
|
|
|
|
|
|
|
|
ret_bytes[0] = f_bytes[3] ;
|
|
|
|
ret_bytes[1] = f_bytes[2] ;
|
|
|
|
ret_bytes[2] = f_bytes[1] ;
|
|
|
|
ret_bytes[3] = f_bytes[0] ;
|
|
|
|
|
|
|
|
return ret ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2011-04-07 12:08:41 +02:00
|
|
|
/* *** Network *** */
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Opens a UDP transmission socket and returns its descriptor.
|
|
|
|
*
|
|
|
|
* @param[in] server_address The server's IP address.
|
|
|
|
* @param[in] server_port The listening port on the server.
|
|
|
|
* @param[out] server_description The structure in which the server
|
|
|
|
* description will be saved.
|
|
|
|
*
|
|
|
|
* @returns A file descriptor to the opened socket in case of success,
|
|
|
|
* or a negative error code.
|
2008-02-14 08:54:51 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
int owl_create_udp_trx_socket(const char *const server_address,
|
|
|
|
const uint_fast16_t server_port,
|
2013-09-20 23:07:46 +02:00
|
|
|
struct sockaddr *const server_description)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2013-09-20 23:07:46 +02:00
|
|
|
char server_port_str[6] ;
|
|
|
|
struct addrinfo
|
|
|
|
gai_hints,
|
|
|
|
*gai_results = NULL,
|
|
|
|
*gai_res = NULL ;
|
|
|
|
int gai_ret ; // Return value of getaddrinfo()
|
|
|
|
int sockfd = -1 ; // Socket descriptor
|
|
|
|
|
|
|
|
/* Get the server information */
|
|
|
|
sprintf(server_port_str, "%"PRIuFAST16, server_port) ;
|
|
|
|
memset(&gai_hints, 0, sizeof(struct addrinfo)) ;
|
|
|
|
gai_hints.ai_family = AF_INET ; // IPv4 only
|
|
|
|
gai_hints.ai_socktype = SOCK_DGRAM ;
|
|
|
|
gai_ret = getaddrinfo(server_address, server_port_str,
|
|
|
|
&gai_hints, &gai_results) ;
|
|
|
|
if (gai_ret)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2013-09-20 23:07:46 +02:00
|
|
|
fprintf(stderr, "UDP socket creation failed: getaddrinfo(): %s\n",
|
|
|
|
gai_strerror(gai_ret)) ;
|
2011-08-26 11:29:44 +02:00
|
|
|
return -OWL_ERR_SOCKET_CREATE ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2013-09-20 23:07:46 +02:00
|
|
|
/* Create the UDP socket: loop until socket() succeeds */
|
|
|
|
for (gai_res = gai_results ; gai_res != NULL ;
|
|
|
|
gai_res = gai_res->ai_next)
|
|
|
|
{
|
|
|
|
sockfd = socket(gai_res->ai_family, gai_res->ai_socktype,
|
|
|
|
gai_res->ai_protocol) ;
|
|
|
|
if (sockfd != -1)
|
|
|
|
break ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gai_res == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"UDP socket creation failed: socket().\n") ;
|
|
|
|
return -OWL_ERR_SOCKET_CREATE ;
|
|
|
|
}
|
2011-03-09 17:42:58 +01:00
|
|
|
|
2013-09-20 23:07:46 +02:00
|
|
|
/* Copy the server description */
|
|
|
|
memcpy(server_description, gai_res->ai_addr, gai_res->ai_addrlen) ;
|
2011-03-09 17:42:58 +01:00
|
|
|
|
2013-09-20 23:07:46 +02:00
|
|
|
freeaddrinfo(gai_results) ;
|
2011-03-09 17:42:58 +01:00
|
|
|
return sockfd ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Opens a UDP reception socket and returns its descriptor.
|
|
|
|
* `port` is the port on which the socket will listen.
|
|
|
|
*
|
|
|
|
* @returns A file descriptor to the opened socket in case of success,
|
|
|
|
* or a negative error code.
|
2008-02-14 08:54:51 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
int owl_create_udp_listening_socket(const uint_fast16_t port)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2013-09-20 23:30:04 +02:00
|
|
|
char port_str[6] ;
|
|
|
|
struct addrinfo
|
|
|
|
gai_hints,
|
|
|
|
*gai_results = NULL,
|
|
|
|
*gai_res = NULL ;
|
|
|
|
int gai_ret ; // Return value of getaddrinfo()
|
2011-03-09 17:42:58 +01:00
|
|
|
int sockfd ; // Socket descriptor
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2013-09-20 23:30:04 +02:00
|
|
|
/* Get the server information */
|
|
|
|
sprintf(port_str, "%"PRIuFAST16, port) ;
|
|
|
|
memset(&gai_hints, 0, sizeof(struct addrinfo)) ;
|
|
|
|
gai_hints.ai_family = AF_INET ; // IPv4 only
|
|
|
|
gai_hints.ai_socktype = SOCK_DGRAM ;
|
|
|
|
gai_hints.ai_flags = AI_PASSIVE ;
|
|
|
|
gai_ret = getaddrinfo(NULL, port_str, &gai_hints, &gai_results) ;
|
|
|
|
if (gai_ret)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2013-09-20 23:30:04 +02:00
|
|
|
fprintf(stderr, "UDP socket creation failed: getaddrinfo(): %s\n",
|
|
|
|
gai_strerror(gai_ret)) ;
|
2011-08-26 11:29:44 +02:00
|
|
|
return -OWL_ERR_SOCKET_CREATE ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2013-09-20 23:30:04 +02:00
|
|
|
/* Create the UDP socket:
|
|
|
|
* loop until both socket() and bind() succeed */
|
|
|
|
for (gai_res = gai_results ; gai_res != NULL ;
|
|
|
|
gai_res = gai_res->ai_next)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
2013-09-20 23:30:04 +02:00
|
|
|
sockfd = socket(gai_res->ai_family, gai_res->ai_socktype,
|
|
|
|
gai_res->ai_protocol) ;
|
|
|
|
if (sockfd == -1)
|
|
|
|
continue ;
|
|
|
|
|
|
|
|
if (! bind(sockfd, gai_res->ai_addr, gai_res->ai_addrlen))
|
|
|
|
break ; // Success!
|
|
|
|
|
2011-03-24 08:43:43 +01:00
|
|
|
close(sockfd) ;
|
2013-09-20 23:30:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gai_res == NULL)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"UDP socket creation failed: socket() or bind().\n") ;
|
2011-08-26 11:29:44 +02:00
|
|
|
return -OWL_ERR_SOCKET_CREATE ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2011-03-09 17:42:58 +01:00
|
|
|
return sockfd ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-26 16:51:49 +01:00
|
|
|
|
2011-04-07 12:08:41 +02:00
|
|
|
/* *** Signals *** */
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
2011-03-09 17:42:58 +01:00
|
|
|
* Generic signal handler for SIGINT.
|
2013-06-04 02:28:13 +02:00
|
|
|
*
|
|
|
|
* @param num The catched signal. This function will exit with
|
|
|
|
* `OWL_ERR_BAD_SIGNAL` if `num != SIGINT`.
|
2011-03-09 17:42:58 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
void owl_sigint_handler(const int num)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
if (num != SIGINT)
|
|
|
|
{
|
2011-03-09 17:42:58 +01:00
|
|
|
fprintf(stderr, "Error! The SIGINT handler was called but the"
|
|
|
|
" signal is not SIGINT.\n") ;
|
2011-08-20 19:28:31 +02:00
|
|
|
exit(OWL_ERR_BAD_SIGNAL) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2013-05-15 21:46:13 +02:00
|
|
|
owl_run = false ;
|
2008-02-14 08:54:51 +01:00
|
|
|
|
2011-07-24 18:58:21 +02:00
|
|
|
#ifndef NDEBUG
|
2011-03-24 09:00:57 +01:00
|
|
|
fprintf(stderr, "\nSignal received: end.\n");
|
2011-07-24 18:58:21 +02:00
|
|
|
#endif // NDEBUG
|
2008-02-14 08:54:51 +01:00
|
|
|
fflush(NULL) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
2011-04-07 12:08:41 +02:00
|
|
|
* Generic signal handler for SIGTERM.
|
2013-06-04 02:28:13 +02:00
|
|
|
*
|
|
|
|
* @param num The catched signal. This function will exit with
|
|
|
|
* `OWL_ERR_BAD_SIGNAL` if `num != SIGTERM`.
|
2011-04-07 12:08:41 +02:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
void owl_sigterm_handler(const int num)
|
2008-02-14 08:54:51 +01:00
|
|
|
{
|
|
|
|
if (num != SIGTERM)
|
|
|
|
{
|
2011-03-09 17:42:58 +01:00
|
|
|
fprintf(stderr, "Error! The SIGTERM handler was called but the"
|
|
|
|
" signal is not SIGTERM.\n") ;
|
2011-08-20 19:28:31 +02:00
|
|
|
exit(OWL_ERR_BAD_SIGNAL) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
|
|
|
|
2011-03-11 11:19:44 +01:00
|
|
|
owl_sigint_handler(SIGINT) ;
|
2008-02-14 08:54:51 +01:00
|
|
|
}
|
2011-03-24 10:16:02 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2011-04-07 12:08:41 +02:00
|
|
|
/* *** Thread-related functions *** */
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Closes the file descriptor `fd`.
|
|
|
|
* `fd` must be passed as an int pointer (`int*`). If `fd` is `NULL`,
|
|
|
|
* nothing will be done. Uppon error, a message is displayed on the
|
|
|
|
* standard error.
|
2011-03-24 10:16:02 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
void owl_close_fd(void *const fd)
|
2011-03-24 10:16:02 +01:00
|
|
|
{
|
|
|
|
if (fd == NULL)
|
|
|
|
return ;
|
|
|
|
|
2011-04-05 13:42:10 +02:00
|
|
|
const int *const file_desc = fd ;
|
2011-03-24 10:16:02 +01:00
|
|
|
if (close(*file_desc) != 0)
|
|
|
|
perror("Error closing file descriptor") ;
|
2011-07-24 18:58:21 +02:00
|
|
|
#ifndef NDEBUG
|
2011-03-24 10:16:02 +01:00
|
|
|
else
|
|
|
|
fprintf(stderr, "File descriptor %d closed successfully.\n",
|
|
|
|
*file_desc) ;
|
2011-07-24 18:58:21 +02:00
|
|
|
#endif // NDEBUG
|
2011-03-24 10:16:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-04 02:28:13 +02:00
|
|
|
/**
|
|
|
|
* Closes the stream `file`.
|
|
|
|
* `file` must be passed as a pointer on a pointer of FILE (FILE**).
|
|
|
|
* If `*file` is either `stdout`, `stderr` or `stdin`, it will not be
|
|
|
|
* closed.
|
2011-03-24 10:16:02 +01:00
|
|
|
*/
|
2011-04-05 13:42:10 +02:00
|
|
|
void owl_close_file(void *const file)
|
2011-03-24 10:16:02 +01:00
|
|
|
{
|
|
|
|
if (file == NULL)
|
|
|
|
return ;
|
|
|
|
|
|
|
|
FILE **stream = file ;
|
|
|
|
if (*stream == stdout || *stream == stderr || *stream == stdin)
|
|
|
|
return ;
|
|
|
|
|
|
|
|
if (fclose(*stream) != 0)
|
|
|
|
perror("Error closing stream") ;
|
2011-07-24 18:58:21 +02:00
|
|
|
#ifndef NDEBUG
|
2011-03-24 10:16:02 +01:00
|
|
|
else
|
|
|
|
fprintf(stderr, "Stream closed successfully.\n") ;
|
2011-07-24 18:58:21 +02:00
|
|
|
#endif // NDEBUG
|
2011-03-24 10:16:02 +01:00
|
|
|
}
|