From ce50c2ed4ddc784e783df605b956208182ad86da Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 5 Jun 2011 15:27:40 +0200 Subject: [PATCH] found bug (shitty overflow ;)) --- misc/controller/vzlogger/src/api.c | 78 +++++++++++++------------- misc/controller/vzlogger/src/api.h | 2 +- misc/controller/vzlogger/src/main.c | 57 ++++++++++++++----- misc/controller/vzlogger/src/main.h | 16 +++--- misc/controller/vzlogger/vzlogger.conf | 2 +- 5 files changed, 92 insertions(+), 63 deletions(-) diff --git a/misc/controller/vzlogger/src/api.c b/misc/controller/vzlogger/src/api.c index 1eb72c8..1420b3d 100644 --- a/misc/controller/vzlogger/src/api.c +++ b/misc/controller/vzlogger/src/api.c @@ -45,17 +45,17 @@ int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_ case CURLINFO_TEXT: case CURLINFO_END: if (end) *end = '\0'; /* terminate without \n */ - print(3, "%.*s", (channel_t *) ch, (int) size, data); + print(3, "CURL: %.*s", (channel_t *) ch, (int) size, data); break; case CURLINFO_SSL_DATA_IN: case CURLINFO_DATA_IN: - print(6, "Received %lu bytes", (channel_t *) ch, (unsigned long) size); + print(6, "CURL: Received %lu bytes", (channel_t *) ch, (unsigned long) size); break; case CURLINFO_SSL_DATA_OUT: case CURLINFO_DATA_OUT: - print(6, "Sent %lu bytes.. ", (channel_t *) ch, (unsigned long) size); + print(6, "CURL: Sent %lu bytes.. ", (channel_t *) ch, (unsigned long) size); break; case CURLINFO_HEADER_IN: @@ -78,10 +78,8 @@ size_t curl_custom_write_callback(void *ptr, size_t size, size_t nmemb, void *da memcpy(&(response->data[response->size]), ptr, realsize); response->size += realsize; - response->data[response->size] = 0; + //response->data[response->size] = 0; - print(1, "Addr: %lu", NULL, &(response->data)); - return realsize; } @@ -109,8 +107,15 @@ json_object * api_build_json(channel_t *ch) { CURL * api_curl_init(channel_t *ch) { CURL *curl; + struct curl_slist *header = NULL; + char url[255], agent[255]; - char buffer[255]; + sprintf(agent, "User-Agent: vzlogger/%s (%s)", VZ_VERSION, curl_version()); /* build user agent */ + sprintf(url, "%s/data/%s.json", ch->middleware, ch->uuid); /* build url */ + + header = curl_slist_append(header, "Content-type: application/json"); + header = curl_slist_append(header, "Accept: application/json"); + header = curl_slist_append(header, agent); curl = curl_easy_init(); if (!curl) { @@ -118,12 +123,8 @@ CURL * api_curl_init(channel_t *ch) { exit(EXIT_FAILURE); } - sprintf(buffer, "%s/data/%s.json", ch->middleware, ch->uuid); /* build url */ - curl_easy_setopt(curl, CURLOPT_URL, buffer); - - sprintf(buffer, "vzlogger/%s (%s)", VZ_VERSION, curl_version()); /* build user agent */ - curl_easy_setopt(curl, CURLOPT_USERAGENT, buffer); - + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header); curl_easy_setopt(curl, CURLOPT_VERBOSE, (int) opts.verbose); curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_custom_debug_callback); curl_easy_setopt(curl, CURLOPT_DEBUGDATA, (void *) ch); @@ -131,10 +132,9 @@ CURL * api_curl_init(channel_t *ch) { return curl; } -char * api_parse_exception(CURLresponse response) { +void api_parse_exception(CURLresponse response, char *err) { struct json_tokener * json_tok; struct json_object * json_obj; - char *errstr; json_tok = json_tokener_new(); json_obj = json_tokener_parse_ex(json_tok, response.data, response.size); @@ -142,19 +142,20 @@ char * api_parse_exception(CURLresponse response) { json_obj = json_object_object_get(json_obj, "exception"); if (json_obj) { - errstr = json_object_get_string(json_object_object_get(json_obj, "message")); + sprintf(err, "[%s] %s", + json_object_get_string(json_object_object_get(json_obj, "type")), + json_object_get_string(json_object_object_get(json_obj, "message")) + ); } else { - errstr = "missing exception"; + strcpy(err, "missing exception"); } } else { - errstr = json_tokener_errors[json_tok->err]; + strcpy(err, json_tokener_errors[json_tok->err]); } json_tokener_free(json_tok); - - return errstr; } @@ -173,36 +174,33 @@ void *api_thread(void *arg) { do { /* start thread mainloop */ CURLresponse response; - int curl_code, http_code; + int curl_code; + long int http_code; char *json_str; /* initialize response */ response.data = NULL; response.size = 0; - //pthread_mutex_lock(&ch->mutex); - //while (queue_is_empty(&ch->queue)) { /* detect spurious wakeups */ - // pthread_cond_wait(&ch->condition, &ch->mutex); /* sleep until new data has been read */ - //} - //pthread_mutex_unlock(&ch->mutex); + pthread_mutex_lock(&ch->mutex); + while (queue_is_empty(&ch->queue)) { /* detect spurious wakeups */ + pthread_cond_wait(&ch->condition, &ch->mutex); /* sleep until new data has been read */ + } + pthread_mutex_unlock(&ch->mutex); - //if (opts.verbose > 5) queue_print(&ch->queue); /* Debugging */ + pthread_mutex_lock(&ch->mutex); + json_str = json_object_to_json_string(api_build_json(ch)); + pthread_mutex_unlock(&ch->mutex); - //pthread_mutex_lock(&ch->mutex); - //json_str = json_object_to_json_string(api_build_json(ch)); - //pthread_mutex_unlock(&ch->mutex); + print(1, "JSON request body: %s", ch, json_str); - //print(1, "JSON body: %s", ch, json_str); - - //curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_str); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_custom_write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &response); curl_code = curl_easy_perform(curl); - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); - print(1, "Addr: %lu", ch, &(response.data)); - print(1, "Response: %s", ch, response.data); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); if (curl_code == CURLE_OK && http_code == 200) { /* everything is ok */ print(1, "Request succeeded with code: %i", ch, http_code); @@ -211,10 +209,12 @@ void *api_thread(void *arg) { } else { /* error */ if (curl_code != CURLE_OK) { - print(-1, "CURL failed: %s", ch, curl_easy_strerror(curl_code)); + print(-1, "CURL: %s", ch, curl_easy_strerror(curl_code)); } else if (http_code != 200) { - print(-1, "Invalid middlware response: %s", ch, api_parse_exception(response)); + char err[255]; + api_parse_exception(response, &err); + print(-1, "Invalid middlware response: %s", ch, err); } print(2, "Sleeping %i seconds due to previous failure", ch, RETRY_PAUSE); @@ -225,7 +225,7 @@ void *api_thread(void *arg) { free(json_str); // TODO free json objects - //if (response.data) free(response.data); + if (response.data) free(response.data); pthread_testcancel(); /* test for cancelation request */ } while (opts.daemon); diff --git a/misc/controller/vzlogger/src/api.h b/misc/controller/vzlogger/src/api.h index dfd2fba..dc156a9 100644 --- a/misc/controller/vzlogger/src/api.h +++ b/misc/controller/vzlogger/src/api.h @@ -43,6 +43,6 @@ int curl_custom_debug_callback(CURL *curl, curl_infotype type, char *data, size_ size_t curl_custom_write_callback(void *ptr, size_t size, size_t nmemb, void *data); json_object * api_build_json(channel_t *ch); -void *api_thread(void *arg); +void * api_thread(void *arg); #endif /* _API_H_ */ diff --git a/misc/controller/vzlogger/src/main.c b/misc/controller/vzlogger/src/main.c index f3a2bc3..a41a09f 100644 --- a/misc/controller/vzlogger/src/main.c +++ b/misc/controller/vzlogger/src/main.c @@ -212,13 +212,21 @@ int parse_channels(char * filename, channel_t * chans) { } char line[256]; - int j = 0; + int chan_num = 0, line_num = 1; - while (j < MAX_CHANNELS && fgets(line, sizeof line, file) != NULL) { /* read a line */ + while (chan_num < MAX_CHANNELS && fgets(line, sizeof line, file) != NULL) { /* read a line */ if (line[0] == ';' || line[0] == '\n') continue; /* skip comments */ - channel_t ch; - protocol_t *prot; + channel_t ch = { + chan_num, + NULL, + NULL, + NULL, + 0, + NULL, + protocols + }; + char *tok = strtok(line, " \t"); for (int i = 0; i < 7 && tok != NULL; i++) { @@ -226,21 +234,39 @@ int parse_channels(char * filename, channel_t * chans) { switch(i) { case 0: /* protocol */ - prot = protocols; /* reset pointer */ - while (prot->name && strcmp(prot->name, tok) != 0) prot++; /* linear search */ - ch.prot = prot; + while (ch.prot->name && strcmp(ch.prot->name, tok) != 0) ch.prot++; /* linear search */ + + if (ch.prot == NULL) { + print(-1, "Invalid protocol: %s in %s:%i", NULL, tok, filename, line_num); + exit(EXIT_FAILURE); + } break; case 1: /* interval */ - ch.interval = atoi(tok); + ch.interval = strtol(tok, (char **) NULL, 10); + + if (errno == EINVAL || errno == ERANGE) { + print(-1, "Invalid interval: %s in %s:%i", NULL, tok, filename, line_num); + exit(EXIT_FAILURE); + } break; case 2: /* uuid */ + if (len == 0) { // TODO add uuid validation + print(-1, "Missing uuid in %s:%i", NULL, filename, line_num); + exit(EXIT_FAILURE); + } + ch.uuid = (char *) malloc(len+1); /* including string termination */ strcpy(ch.uuid, tok); break; case 3: /* middleware */ + if (len == 0) { // TODO add uuid validation + print(-1, "Missing middleware in %s:%i", NULL, filename, line_num); + exit(EXIT_FAILURE); + } + ch.middleware = (char *) malloc(len+1); /* including string termination */ strcpy(ch.middleware, tok); break; @@ -248,22 +274,23 @@ int parse_channels(char * filename, channel_t * chans) { case 4: /* options */ ch.options = (char *) malloc(len); strncpy(ch.options, tok, len-1); - ch.options[len] = '\0'; /* replace \n by \0 */ + ch.options[len-1] = '\0'; /* replace \n by \0 */ break; } tok = strtok(NULL, " \t"); } - - ch.id = j; - print(1, "Parsed %s (on %s)", &ch, ch.uuid, ch.middleware); - chans[j++] = ch; + print(1, "Parsed ch#%i (protocol=%s interval=%i uuid=%s middleware=%s options=%s)", &ch, ch.id, ch.prot->name, ch.interval, ch.uuid, ch.middleware, ch.options); + chans[chan_num] = ch; + + chan_num++; + line_num++; } fclose(file); - return j; + return chan_num; } /** @@ -288,7 +315,7 @@ void *read_thread(void *arg) { pthread_mutex_unlock(&ch->mutex); print(1, "Value read: %.3f (next reading in %i secs)", ch, rd.value, ch->interval); - if (opts.verbose > 5) queue_print(&ch->queue); /* Debugging */ + //if (opts.verbose > 5) queue_print(&ch->queue); /* Debugging */ pthread_testcancel(); /* test for cancelation request */ sleep(ch->interval); /* else sleep and restart aquisition */ diff --git a/misc/controller/vzlogger/src/main.h b/misc/controller/vzlogger/src/main.h index 3bad60d..46b1156 100644 --- a/misc/controller/vzlogger/src/main.h +++ b/misc/controller/vzlogger/src/main.h @@ -28,6 +28,7 @@ #include #include +#include #include "protocol.h" #include "queue.h" @@ -50,16 +51,17 @@ * Datatype for every channel */ typedef struct { - char * middleware; - char * uuid; - unsigned int interval; - char * options; - int id; /* only for internal usage & debugging */ + + char *middleware; + char *uuid; + char *options; - queue_t queue; /* circular queue to buffer readings */ + unsigned int interval; + + void *handle; /* handle to store connection status */ protocol_t *prot; /* pointer to protocol */ - void * handle; /* handle to store connection status */ + queue_t queue; /* circular queue to buffer readings */ pthread_t reading_thread; /* pthread for asynchronus reading */ pthread_t logging_thread; /* pthread for asynchronus logging */ diff --git a/misc/controller/vzlogger/vzlogger.conf b/misc/controller/vzlogger/vzlogger.conf index b8a0403..614e829 100644 --- a/misc/controller/vzlogger/vzlogger.conf +++ b/misc/controller/vzlogger/vzlogger.conf @@ -5,4 +5,4 @@ ;prot intval uuid middleware options ;1wire 3 52960fe0-8882-11e0-b356-85eba28c1922 http://localhost/workspace/volkszaehler.org/htdocs/middleware /mnt/1wire/10.12E6D3000800/temperature ;obis 10 ef0e9adf-cd9e-4d9a-92c5-b4fb4c89ff98 http://volkszaehler.org/demo/middleware.php /dev/ttyS0 -obis 10 ef0e9adf-cd9e-4d9a-92c5-b4fb4c89ff98 http://volkszaehler.org/demo/middleware.php /dev/ttyS1 +obis 10 ef0e9adf-cd9e-4d9a-92c5-b4fb4c89ff98 http://volksxzaehler.org/demo/middleware.php /dev/ttyS1