[Olsr-dev] [PATCH RFC v1 2/4] smart gateway: hook up SmartGatewaySpeedFile{, Period} parameters
Hans-Christoph Steiner
(spam-protected)
Thu May 10 18:42:32 CEST 2012
This makes the core depend on regex.h which is not guaranteed on all platforms. Windows and Android (< 2.3) do not natively provide regex support.
.hc
On May 10, 2012, at 11:56 AM, Ferry Huberts wrote:
> From: Ferry Huberts <(spam-protected)>
>
> Signed-off-by: Ferry Huberts <(spam-protected)>
> ---
> make/Makefile.win32 | 2 +-
> src/gateway.c | 52 ++++++++++++-
> src/gatewaySpeedFile.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++
> src/gatewaySpeedFile.h | 13 +++
> 4 files changed, 266 insertions(+), 2 deletions(-)
> create mode 100644 src/gatewaySpeedFile.c
> create mode 100644 src/gatewaySpeedFile.h
>
> diff --git a/make/Makefile.win32 b/make/Makefile.win32
> index cf4a4a2..3693ef4 100644
> --- a/make/Makefile.win32
> +++ b/make/Makefile.win32
> @@ -9,7 +9,7 @@ SRCS += $(wildcard src/win32/*.c)
> HDRS += $(wildcard src/win32/*.h)
>
> CPPFLAGS += -DWIN32 -D_WIN32_WINNT=0x0600
> -LIBS += -mno-cygwin -lws2_32 -liphlpapi
> +LIBS += -mno-cygwin -lws2_32 -liphlpapi -lregex
> CPPFLAGS += -I$(TOPDIR)/src/win32
> CFLAGS += -mno-cygwin
>
> diff --git a/src/gateway.c b/src/gateway.c
> index 048a7cb..84d88b3 100644
> --- a/src/gateway.c
> +++ b/src/gateway.c
> @@ -19,6 +19,7 @@
> #include "log.h"
> #include "gateway_default_handler.h"
> #include "gateway.h"
> +#include "gatewaySpeedFile.h"
>
> #include <assert.h>
> #include <net/if.h>
> @@ -87,6 +88,14 @@ static void smartgw_tunnel_monitor (int if_index __attribute__ ((unused)),
> }
>
> /**
> + * Timer callback that reads the smart gateway speed file
> + */
> +static void smartgw_read_speed_file(void *context __attribute__ ((unused))) {
> + readGatewaySpeedFile(olsr_cnf->smart_gw_speed_file);
> + return;
> +}
> +
> +/**
> * Initialize gateway system
> */
> int
> @@ -107,6 +116,10 @@ olsr_init_gateways(void) {
> return 1;
> }
>
> + if (!startGatewaySpeedFile()) {
> + return 1;
> + }
> +
> olsr_add_ifchange_handler(smartgw_tunnel_monitor);
>
> /*
> @@ -140,10 +153,26 @@ void refresh_smartgw_netmask(void) {
> }
> }
>
> +/** The timer cookie, used to trace back the originator in debug */
> +static struct olsr_cookie_info *smartgw_speed_file_timer_cookie = NULL;
> +
> +/** The timer */
> +static struct timer_entry * smartgw_speed_file_timer = NULL;
> +
> /**
> * Cleanup gateway tunnel system
> */
> void olsr_cleanup_gateways(void) {
> + if (smartgw_speed_file_timer != NULL) {
> + olsr_stop_timer(smartgw_speed_file_timer);
> + smartgw_speed_file_timer = NULL;
> + }
> + if (smartgw_speed_file_timer_cookie != NULL) {
> + olsr_free_cookie(smartgw_speed_file_timer_cookie);
> + smartgw_speed_file_timer_cookie = NULL;
> + }
> + stopGatewaySpeedFile();
> +
> if (current_ipv4_gw) {
> olsr_os_del_ipip_tunnel(v4gw_tunnel);
> }
> @@ -161,7 +190,28 @@ void olsr_cleanup_gateways(void) {
> */
> void
> olsr_trigger_inetgw_startup(void) {
> - gw_handler->handle_startup();
> + if (olsr_cnf->smart_gw_speed_file) {
> + smartgw_read_speed_file(NULL);
> +
> + if (smartgw_speed_file_timer_cookie == NULL) {
> + smartgw_speed_file_timer_cookie = olsr_alloc_cookie("smartgw speed file", OLSR_COOKIE_TYPE_TIMER);
> + if (smartgw_speed_file_timer_cookie == NULL) {
> + olsr_syslog(OLSR_LOG_ERR,
> + "Could not allocate smart gateway speed file cookie, will not read the file.\n");
> + return;
> + }
> + }
> + if (smartgw_speed_file_timer == NULL) {
> + smartgw_speed_file_timer = olsr_start_timer(olsr_cnf->smart_gw_speed_file_period, 0, OLSR_TIMER_PERIODIC,
> + &smartgw_read_speed_file, NULL, smartgw_speed_file_timer_cookie);
> + if (smartgw_speed_file_timer == NULL) {
> + olsr_syslog(OLSR_LOG_ERR, "Could not start smart gateway speed file timer, will not read the file.\n");
> + return;
> + }
> + }
> + }
> +
> + gw_handler->handle_startup();
> }
>
> /**
> diff --git a/src/gatewaySpeedFile.c b/src/gatewaySpeedFile.c
> new file mode 100644
> index 0000000..72cfbf9
> --- /dev/null
> +++ b/src/gatewaySpeedFile.c
> @@ -0,0 +1,201 @@
> +#include "gatewaySpeedFile.h"
> +
> +#include "log.h"
> +#include <regex.h>
> +#include <sys/stat.h>
> +
> +#define LINE_LENGTH 256
> +
> +static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
> +static const char * regexNameValueString =
> + "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*$";
> +static const size_t regexNameValuematchCount = 3;
> +
> +static regex_t regexComment;
> +static regex_t regexNameValue;
> +static bool started = false;
> +
> +typedef struct _CachedStat {
> +#ifdef linux
> + struct timespec st_mtim; /* Time of last modification. */
> +#else
> + time_t st_mtime; /* Time of last modification. */
> +#endif
> +} CachedStat;
> +
> +static CachedStat cachedStat;
> +
> +/**
> + Read an unsigned long number from a value string
> +
> + @param valueName
> + the name of the value
> + @param value
> + the string to convert to a number
> + @param valueNumber
> + a pointer to the location where to store the number upon successful conversion
> +
> + @return
> + - true on success
> + - false otherwise
> + */
> +static bool readUL(const char * valueName, const char * value, unsigned long * valueNumber) {
> + char * endPtr = NULL;
> + unsigned long valueNew;
> +
> + errno = 0;
> + valueNew = strtoul(value, &endPtr, 10);
> +
> + if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
> + /* invalid conversion */
> + olsr_syslog(OLSR_LOG_ERR, "Configured %s (%s) could not be converted to a number: %s\n", valueName, value,
> + strerror(errno));
> + return false;
> + }
> +
> + *valueNumber = valueNew;
> +
> + return true;
> +}
> +
> +bool startGatewaySpeedFile(void) {
> + if (started) {
> + return true;
> + }
> +
> + if (regcomp(®exComment, regexCommentString, REG_EXTENDED)) {
> + olsr_printf(0, "Could not compile regex \"%s\"\n", regexCommentString);
> + return false;
> + }
> +
> + if (regcomp(®exNameValue, regexNameValueString, REG_EXTENDED)) {
> + olsr_printf(0, "Could not compile regex \"%s\"\n", regexNameValueString);
> + return false;
> + }
> +
> +#ifdef linux
> + cachedStat.st_mtim.tv_sec = -1;
> + cachedStat.st_mtim.tv_nsec = -1;
> +#else
> + cachedStat.st_mtime = -1;
> +#endif
> +
> + started = true;
> + return true;
> +}
> +
> +void stopGatewaySpeedFile(void) {
> + if (started) {
> + regfree(®exNameValue);
> + regfree(®exComment);
> + started = false;
> + }
> +}
> +
> +static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t pmatch[]) {
> + int result = regexec(regex, line, nmatch, pmatch, 0);
> + if (!result) {
> + return true;
> + }
> +
> + if (result == REG_NOMATCH) {
> + return false;
> + }
> +
> + {
> + char msgbuf[256];
> + regerror(result, regex, msgbuf, sizeof(msgbuf));
> + olsr_syslog(OLSR_LOG_ERR, "Regex match failed: %s\n", msgbuf);
> + }
> +
> + return false;
> +}
> +
> +static char line[LINE_LENGTH];
> +
> +void readGatewaySpeedFile(char * fileName) {
> + struct stat statBuf;
> + FILE * fd = NULL;
> + unsigned int lineNumber = 0;
> + char * name = NULL;
> + char * value = NULL;
> + unsigned long uplink = DEF_UPLINK_SPEED;
> + unsigned long downlink = DEF_DOWNLINK_SPEED;
> + bool uplinkSet = false;
> + bool downlinkSet = false;
> +
> + if (stat(fileName, &statBuf)) {
> + /* could not access the file */
> + goto out;
> + }
> +
> +#ifdef linux
> + if (!memcmp(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim))) {
> +#else
> + if (!memcmp(&cachedStat.st_mtime, &statBuf.st_mtime, sizeof(cachedStat.st_mtime))) {
> +#endif
> + /* file did not change since last read */
> + goto out;
> + }
> +
> + fd = fopen(fileName, "r");
> + if (!fd) {
> + goto out;
> + }
> +
> +#ifdef linux
> + memcpy(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim));
> +#else
> + memcpy(&cachedStat.st_mtime, &statBuf.st_mtime, sizeof(cachedStat.st_mtime));
> +#endif
> +
> + while (fgets(line, LINE_LENGTH, fd)) {
> + regmatch_t pmatch[regexNameValuematchCount];
> +
> + lineNumber++;
> +
> + if (regexMatch(®exComment, line, 0, NULL)) {
> + continue;
> + }
> +
> + if (!regexMatch(®exNameValue, line, regexNameValuematchCount, pmatch)) {
> + olsr_syslog(OLSR_LOG_ERR, "Gateway speed file \"%s\", line %d uses invalid syntax: %s\n", fileName, lineNumber,
> + line);
> + goto out;
> + }
> +
> + /* copy name/value */
> + name = &line[pmatch[1].rm_so];
> + line[pmatch[1].rm_eo] = '\0';
> + value = &line[pmatch[2].rm_so];
> + line[pmatch[2].rm_eo] = '\0';
> +
> + if (!strncasecmp(GATEWAY_SPEED_UPLINK, name, sizeof(line))) {
> + if (!readUL(GATEWAY_SPEED_UPLINK, value, &uplink)) {
> + goto out;
> + }
> + uplinkSet = true;
> + } else if (!strncasecmp(GATEWAY_SPEED_DOWNLINK, name, sizeof(line))) {
> + if (!readUL(GATEWAY_SPEED_DOWNLINK, value, &downlink)) {
> + goto out;
> + }
> + downlinkSet = true;
> + } else {
> + olsr_syslog(OLSR_LOG_ERR, "Gateway speed file \"%s\", line %d uses an invalid option \"%s\","
> + " valid options are [%s|%s]\n", fileName, lineNumber, name, GATEWAY_SPEED_UPLINK,
> + GATEWAY_SPEED_DOWNLINK);
> + goto out;
> + }
> + }
> +
> + fclose(fd);
> +
> + if (uplinkSet) {
> + olsr_cnf->smart_gw_uplink = uplink;
> + }
> + if (downlinkSet) {
> + olsr_cnf->smart_gw_downlink = downlink;
> + }
> +
> + out: return;
> +}
> diff --git a/src/gatewaySpeedFile.h b/src/gatewaySpeedFile.h
> new file mode 100644
> index 0000000..e50f607
> --- /dev/null
> +++ b/src/gatewaySpeedFile.h
> @@ -0,0 +1,13 @@
> +#ifndef GATEWAYSPEEDFILE_H
> +#define GATEWAYSPEEDFILE_H
> +
> +#include "olsr.h"
> +
> +#define GATEWAY_SPEED_UPLINK "upstream"
> +#define GATEWAY_SPEED_DOWNLINK "downstream"
> +
> +bool startGatewaySpeedFile(void);
> +void stopGatewaySpeedFile(void);
> +void readGatewaySpeedFile(char * fileName);
> +
> +#endif /* GATEWAYSPEEDFILE_H */
> --
> 1.7.7.6
>
>
> --
> Olsr-dev mailing list
> (spam-protected)
> https://lists.olsr.org/mailman/listinfo/olsr-dev
More information about the Olsr-dev
mailing list