nest-sanity-checks/notify.c

89 lines
2.9 KiB
C

#include <curl/curl.h>
#include "runtime-config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define NOTIFICATION_PREFIX "[h/nest-sanity-checks] "
/* No longer URL encoding payloads. TODO: remove later */
#pragma GCC poison urlencoded_report
/* #define NOTIFICATION_PREFIX_LEN sizeof(NOTIFICATION_PREFIX) */
/* notify_init() initializes curl.
If this fails, exiting is the only option, as curl must be usable,
or alerts will fail to send later on when things break.
This file is the only context that should utilize libcurl.
Therefore, the curl instance is static. */
static CURL *curl;
/* notify_init_early is the first thing that runs,
* and it makes sure that curl_global_init() does not
* run multiple times in parallel somehow.
*/
int notify_init_early() {
CURLcode curl_global_init_res;
curl_global_init_res = curl_global_init(CURL_GLOBAL_DEFAULT);
if(curl_global_init_res!=CURLE_OK) {
fprintf(stderr, "[E] curl_global_init failed.\n");
exit(1);
}
else {
return 0;
}
}
int notify_init() {
curl = curl_easy_init();
if(curl == NULL) {
fprintf(stderr, "[E] curl_easy_init failed.\n");
exit(1);
}
CURLcode url_set_result;
char *url;
url = config_get_url();
if(url==NULL) {
fprintf(stderr, "[E] notify url is null, exiting!\n");
exit(1);
}
url_set_result = curl_easy_setopt(curl, CURLOPT_URL, config_get_url());
if(url_set_result!=CURLE_OK) {
fprintf(stderr, "[E] Failed to set notify URL. Cannot deliver notifications, exiting.\n");
exit(1);
}
return 0;
}
const char *build_prefixed_report(const char *report) {
/* Adds a prefix to every message that goes to nest admins */
/* TODO: do this in a less weird way,
* maybe consider creating a C macro that
* adds prefixes and calls the report send function */
int report_len = strlen(report);
int notification_prefix_len = strlen(NOTIFICATION_PREFIX);
int post_payload_len = report_len + notification_prefix_len;
char *post_payload = malloc(post_payload_len+1);
for(int a=0;a<notification_prefix_len;a++) {
post_payload[a] = NOTIFICATION_PREFIX[a];
}
for(int a=0;a<report_len;a++) {
post_payload[notification_prefix_len+a] = report[a];
}
post_payload[post_payload_len]=0;
return post_payload;
}
int send_alarm(const char *report) {
assert(report!=NULL);
printf("[I] Sending report '%s'\n", report);
const char *prefixed_report;
prefixed_report = build_prefixed_report(report);
assert(prefixed_report!=NULL);
CURLcode post_field_set_result;
post_field_set_result = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, prefixed_report);
if(post_field_set_result != CURLE_OK) {
fprintf(stderr, "[E] Failed to send report, setting CURLOPT_POSTFIELDS to %s failed.\n", prefixed_report);
return -1;
}
CURLcode res;
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "[E] Failed to send report, curl_easy_perform failed: %s\n", curl_easy_strerror(res));
return -1;
}
return 0;
}