diff --git a/server/core/load_utils.c b/server/core/load_utils.c index d8a735ecd..264f25d84 100644 --- a/server/core/load_utils.c +++ b/server/core/load_utils.c @@ -65,6 +65,7 @@ static void register_module(const char *module, MODULE_INFO *info); static void unregister_module(const char *module); int module_create_feedback_report(GWBUF **buffer, MODULES *modules, FEEDBACK_CONF *cfg); +int do_http_post(GWBUF *buffer, void *cfg); struct MemoryStruct { char *data; @@ -568,13 +569,13 @@ module_feedback_send(void* data) { GWBUF *buffer = NULL; void *data_ptr=NULL; long http_code = 0; - struct MemoryStruct chunk; int last_action = _NOTIFICATION_SEND_PENDING; time_t now; struct tm *now_tm; int hour; int n_mod=0; char hex_setup_info[2 * SHA_DIGEST_LENGTH + 1]=""; + int http_send = 0; now = time(NULL); now_tm = localtime(&now); @@ -634,11 +635,6 @@ module_feedback_send(void* data) { "module_feedback_send(): task now runs: hour is [%d], last_action [%d]", hour, feedback_config->feedback_last_action))); - - /* allocate first memory chunck for httpd servr reply */ - chunk.data = malloc(1); /* will be grown as needed by the realloc above */ - chunk.size = 0; /* no data at this point */ - if (!module_create_feedback_report(&buffer, modules_list, feedback_config)) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, @@ -649,118 +645,27 @@ module_feedback_send(void* data) { return; } + /* try sending data via http/https post */ + http_send = do_http_post(buffer, feedback_config); - /* Initializing curl library for data send via HTTP */ - curl_global_init(CURL_GLOBAL_DEFAULT); - - curl = curl_easy_init(); - - if (curl) { - char error_message[CURL_ERROR_SIZE]=""; - - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_message); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, feedback_config->feedback_connect_timeout); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, feedback_config->feedback_timeout); - - /* curl API call for data send via HTTP POST using a "file" type input */ - curl_formadd(&formpost, - &lastptr, - CURLFORM_COPYNAME, "data", - CURLFORM_BUFFER, "report.txt", - CURLFORM_BUFFERPTR, (char *)GWBUF_DATA(buffer), - CURLFORM_BUFFERLENGTH, strlen((char *)GWBUF_DATA(buffer)), - CURLFORM_CONTENTTYPE, "text/plain", - CURLFORM_END); - - curl_easy_setopt(curl, CURLOPT_HEADER, 1); - - /* some servers don't like requests that are made without a user-agent field, so we provide one */ - curl_easy_setopt(curl, CURLOPT_USERAGENT, "MaxScale-agent/http-1.0"); - /* Force HTTP/1.0 */ - curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); - - curl_easy_setopt(curl, CURLOPT_URL, feedback_config->feedback_url); - curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); - -#ifdef SKIP_PEER_VERIFICATION - /* - * This makes the connection A LOT LESS SECURE. - */ - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); -#endif - -#ifdef SKIP_HOSTNAME_VERIFICATION - /* - * this will make the connection less secure. - */ - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); -#endif - - /* send all data to this function */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); - - /* we pass our 'chunk' struct to the callback function */ - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); - - /* Perform the request, res will get the return code */ - res = curl_easy_perform(curl); - - /* Check for errors */ - if(res != CURLE_OK) { - last_action = _NOTIFICATION_SEND_ERROR; - - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error: module_feedback_send(), curl call for [%s] failed due: %s, %s", - feedback_config->feedback_url, - curl_easy_strerror(res), - error_message))); - } else { - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); - } - - if (http_code == 302) { - char *from = strstr(chunk.data, "

ok

"); - if (from) { - last_action = _NOTIFICATION_SEND_OK; - } else { - last_action = _NOTIFICATION_SEND_ERROR; - } - } else { - last_action = _NOTIFICATION_SEND_ERROR; - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error in module_feedback_send(), Bad HTTP Code from remote server: %lu", - http_code))); - } + if (http_send == 0) { + feedback_config->feedback_last_action = _NOTIFICATION_SEND_OK; } else { - LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error in module_feedback_send(), curl object not initialized"))); - last_action = _NOTIFICATION_SEND_ERROR; - } + feedback_config->feedback_last_action = _NOTIFICATION_SEND_ERROR; - /* update last action in the config struct */ - feedback_config->feedback_last_action = last_action; + LOGIF(LT, (skygw_log_write_flush( + LOGFILE_TRACE, + "Error in module_create_feedback_report(): do_http_post ret_code is %d", http_send))); + } LOGIF(LT, (skygw_log_write_flush( LOGFILE_TRACE, - "module_feedback_send(): task run result: hour is [%d], last_action [%d], HTTP code [%d]", - hour, feedback_config->feedback_last_action, http_code))); + "module_feedback_send(): task completed: hour is [%d], last_action [%d]", + hour, + feedback_config->feedback_last_action))); - if (chunk.data) - free(chunk.data); + gwbuf_free(buffer); - if (buffer) - gwbuf_free(buffer); - - if (curl) { - curl_easy_cleanup(curl); - curl_formfree(formpost); - } - - curl_global_cleanup(); } /** @@ -865,3 +770,121 @@ module_create_feedback_report(GWBUF **buffer, MODULES *modules, FEEDBACK_CONF *c return 1; } +/** + * Send data to notification service via http/https + * + * @param buffer The GWBUF with data to send + * @param cfg The configuration details of notification service + * @return 0 on success, != 0 on failure + */ +int +do_http_post(GWBUF *buffer, void *cfg) { + CURL *curl = NULL; + CURLcode res; + struct curl_httppost *formpost=NULL; + struct curl_httppost *lastptr=NULL; + long http_code = 0; + struct MemoryStruct chunk; + int ret_code = 1; + + FEEDBACK_CONF *feedback_config = (FEEDBACK_CONF *) cfg; + + /* allocate first memory chunck for httpd servr reply */ + chunk.data = malloc(1); /* will be grown as needed by the realloc above */ + chunk.size = 0; /* no data at this point */ + + /* Initializing curl library for data send via HTTP */ + curl_global_init(CURL_GLOBAL_DEFAULT); + + curl = curl_easy_init(); + + if (curl) { + char error_message[CURL_ERROR_SIZE]=""; + + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_message); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, feedback_config->feedback_connect_timeout); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, feedback_config->feedback_timeout); + + /* curl API call for data send via HTTP POST using a "file" type input */ + curl_formadd(&formpost, + &lastptr, + CURLFORM_COPYNAME, "data", + CURLFORM_BUFFER, "report.txt", + CURLFORM_BUFFERPTR, (char *)GWBUF_DATA(buffer), + CURLFORM_BUFFERLENGTH, strlen((char *)GWBUF_DATA(buffer)), + CURLFORM_CONTENTTYPE, "text/plain", + CURLFORM_END); + + curl_easy_setopt(curl, CURLOPT_HEADER, 1); + + /* some servers don't like requests that are made without a user-agent field, so we provide one */ + curl_easy_setopt(curl, CURLOPT_USERAGENT, "MaxScale-agent/http-1.0"); + /* Force HTTP/1.0 */ + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + + curl_easy_setopt(curl, CURLOPT_URL, feedback_config->feedback_url); + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + + /* send all data to this function */ + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + + /* we pass our 'chunk' struct to the callback function */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); + + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + + /* Check for errors */ + if(res != CURLE_OK) { + ret_code = 2; + + LOGIF(LE, (skygw_log_write_flush( + LOGFILE_ERROR, + "Error: do_http_post(), curl call for [%s] failed due: %s, %s", + feedback_config->feedback_url, + curl_easy_strerror(res), + error_message))); + } else { + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); + } + + if (http_code == 302) { + char *from = strstr(chunk.data, "

ok

"); + if (from) { + ret_code = 0; + } else { + ret_code = 3; + } + } else { + LOGIF(LE, (skygw_log_write_flush( + LOGFILE_ERROR, + "Error: do_http_post(), Bad HTTP Code from remote server: %lu", + http_code))); + ret_code = 4; + } + } else { + LOGIF(LE, (skygw_log_write_flush( + LOGFILE_ERROR, + "Error: do_http_post(), curl object not initialized"))); + ret_code = 1; + } + + LOGIF(LT, (skygw_log_write_flush( + LOGFILE_TRACE, + "do_http_post() ret_code [%d], HTTP code [%d]", + ret_code, http_code))); + + if (chunk.data) + free(chunk.data); + + if (curl) { + curl_easy_cleanup(curl); + curl_formfree(formpost); + } + + curl_global_cleanup(); + + return ret_code; +} +