4 #include "sgwDynSpeed.h"
19 #define SPEED_UPLINK_NAME "upstream"
20 #define SPEED_DOWNLINK_NAME "downstream"
22 /** the maximal length of a line that is read from the file */
23 #define LINE_LENGTH 256
25 /** regular expression describing a comment */
26 static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
28 /** regular expression describing a key/value pair */
29 static const char * regexNameValueString =
30 "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*$";
32 /** the number of matches in regexNameValueString */
33 static const size_t regexNameValuematchCount = 3;
35 /** the compiled regular expression describing a comment */
36 static regex_t regexComment;
38 /** the compiled regular expression describing a key/value pair */
39 static regex_t regexNameValue;
41 /** true when the plugin has been started */
42 static bool started = false;
44 /** type to hold the cached stat result */
45 typedef struct _CachedStat {
46 time_t timeStamp; /* Time of last modification (second resolution) */
49 /** the cached stat result */
50 static CachedStat cachedStat;
53 Read an unsigned long number from a value string
58 the string to convert to a number
60 a pointer to the location where to store the number upon successful conversion
66 static bool readUL(const char * valueName, const char * value, unsigned long * valueNumber) {
68 unsigned long valueNew;
70 assert(valueName != NULL);
71 assert(value != NULL);
72 assert(valueNumber != NULL);
75 valueNew = strtoul(value, &endPtr, 10);
77 if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
78 /* invalid conversion */
79 sgwDynSpeedError(false, "Value of parameter %s (%s) could not be converted to a number", valueName, value);
83 *valueNumber = valueNew;
89 * Initialises the speedFile reader.
90 * @return true upon success, false otherwise
92 bool startSpeedFile(void) {
97 if (regcomp(®exComment, regexCommentString, REG_EXTENDED | REG_ICASE)) {
98 sgwDynSpeedError(false, "Could not compile regex \"%s\"", regexCommentString);
102 if (regcomp(®exNameValue, regexNameValueString, REG_EXTENDED | REG_ICASE)) {
103 sgwDynSpeedError(false, "Could not compile regex \"%s\"", regexNameValueString);
104 regfree(®exComment);
108 cachedStat.timeStamp = -1;
115 * Cleans up the speedFile reader.
117 void stopSpeedFile(void) {
119 regfree(®exNameValue);
120 regfree(®exComment);
126 * Performs a regex match
127 * @param regex the compiled regex to match against
128 * @param line the line to match
129 * @param nmatch the number of matches to produce
130 * @param pmatch the array with match information
131 * @return true upon success, false otherwise
133 static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t pmatch[]) {
134 int result = regexec(regex, line, nmatch, pmatch, 0);
139 if (result == REG_NOMATCH) {
145 regerror(result, regex, msgbuf, sizeof(msgbuf));
146 sgwDynSpeedError(false, "Regex match failed: %s", msgbuf);
152 /** the buffer in which to store a line read from the file */
153 static char line[LINE_LENGTH];
156 * Read the speed file
157 * @param fileName the filename
159 void readSpeedFile(char * fileName) {
162 unsigned int lineNumber = 0;
165 unsigned long uplink = DEF_UPLINK_SPEED;
166 unsigned long downlink = DEF_DOWNLINK_SPEED;
167 bool uplinkSet = false;
168 bool downlinkSet = false;
170 if (stat(fileName, &statBuf)) {
171 /* could not access the file */
175 if (!memcmp(&cachedStat.timeStamp, &statBuf.st_mtime, sizeof(cachedStat.timeStamp))) {
176 /* file did not change since last read */
180 fd = fopen(fileName, "r");
185 memcpy(&cachedStat.timeStamp, &statBuf.st_mtime, sizeof(cachedStat.timeStamp));
187 while (fgets(line, LINE_LENGTH, fd)) {
188 regmatch_t pmatch[regexNameValuematchCount];
192 if (regexMatch(®exComment, line, 0, NULL)) {
196 if (!regexMatch(®exNameValue, line, regexNameValuematchCount, pmatch)) {
197 sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses invalid syntax: %s", fileName, lineNumber,
202 /* determine name/value */
203 name = &line[pmatch[1].rm_so];
204 line[pmatch[1].rm_eo] = '\0';
205 value = &line[pmatch[2].rm_so];
206 line[pmatch[2].rm_eo] = '\0';
208 if (!strncasecmp(SPEED_UPLINK_NAME, name, sizeof(line))) {
209 if (!readUL(SPEED_UPLINK_NAME, value, &uplink)) {
213 } else if (!strncasecmp(SPEED_DOWNLINK_NAME, name, sizeof(line))) {
214 if (!readUL(SPEED_DOWNLINK_NAME, value, &downlink)) {
219 sgwDynSpeedError(false, "Gateway speed file \"%s\", line %d uses an invalid option \"%s\","
220 " valid options are [%s|%s]", fileName, lineNumber, name, SPEED_UPLINK_NAME, SPEED_DOWNLINK_NAME);
228 olsr_cnf->smart_gw_uplink = uplink;
231 olsr_cnf->smart_gw_downlink = downlink;
233 if (uplinkSet || downlinkSet) {
234 refresh_smartgw_netmask();