]> git.ipfire.org Git - telemetry.git/commitdiff
request: Create scaffolding to create a HTTP request
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 10 Jul 2026 10:27:59 +0000 (10:27 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 10 Jul 2026 10:27:59 +0000 (10:27 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/daemon/client.c
src/daemon/request.c [new file with mode: 0644]
src/daemon/request.h [new file with mode: 0644]

index ddb96d17a73f644381a4ad755bf97a91c782da45..cc0b6e9bcd964e3582b863801089c93cb1667e1d 100644 (file)
@@ -188,6 +188,8 @@ dist_telemetryd_SOURCES = \
        src/daemon/proto.h \
        src/daemon/queue.c \
        src/daemon/queue.h \
+       src/daemon/request.c \
+       src/daemon/request.h \
        src/daemon/sensors.c \
        src/daemon/sensors.h \
        src/daemon/source.c \
index e2f3eb3f664ba9a6ac4943d1e449aaba27455d5c..ef6a893d4a687d6babc36c7a234f455dfc810aed 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "ctx.h"
 #include "client.h"
+#include "request.h"
 
 struct td_client {
        td_ctx* ctx;
@@ -45,7 +46,8 @@ struct td_client {
 };
 
 static int td_client_action(td_client* self) {
-       void* p = NULL;
+       td_request* request = NULL;
+       int r;
 
        CURLMsg* msg = NULL;
        int msgs_left = 0;
@@ -59,11 +61,10 @@ static int td_client_action(td_client* self) {
                switch (msg->msg) {
                        case CURLMSG_DONE:
                                // Update reference to transfer
-                               curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &p);
+                               curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &request);
 
-#if 0
                                // Call the done callback
-                               r = td_request_done(p, self->loop, msg->data.result);
+                               r = td_request_done(request, msg->data.result);
                                if (r < 0) {
                                        switch (-r) {
                                                case EAGAIN:
@@ -82,7 +83,6 @@ static int td_client_action(td_client* self) {
                                                        return r;
                                        }
                                }
-#endif
                                break;
 
                        default:
diff --git a/src/daemon/request.c b/src/daemon/request.c
new file mode 100644 (file)
index 0000000..218ae3b
--- /dev/null
@@ -0,0 +1,263 @@
+/*#############################################################################
+#                                                                             #
+# telemetryd - The IPFire Telemetry Collection Service                        #
+# Copyright (C) 2026 IPFire Development Team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <curl/curl.h>
+
+#include "buffer.h"
+#include "client.h"
+#include "ctx.h"
+#include "request.h"
+
+struct td_request {
+       td_ctx* ctx;
+       int nrefs;
+
+       // HTTP Client
+       td_client* client;
+
+       // cURL handle
+       CURL* handle;
+
+       // URL
+       CURLU* url;
+
+       // Output Buffer
+       td_buffer* buffer;
+};
+
+static int td_request_debug_callback(CURL *handle, curl_infotype type,
+               char* data, size_t size, void* p) {
+       td_request* self = p;
+
+       switch (type) {
+               case CURLINFO_TEXT:
+                       DEBUG(self->ctx, "cURL: %.*s", (int)size, data);
+                       break;
+
+               // Log headers
+               case CURLINFO_HEADER_IN:
+                       DEBUG(self->ctx, "cURL: < %.*s", (int)size, data);
+                       break;
+
+               case CURLINFO_HEADER_OUT:
+                       DEBUG(self->ctx, "cURL: > %.*s", (int)size, data);
+                       break;
+
+               // Ignore everything else
+               default:
+                       break;
+       }
+
+       return 0;
+}
+
+static size_t td_request_write(char* data, size_t size, size_t nmemb, void* p) {
+       td_request* self = p;
+
+       // Write everything to the buffer
+       return td_buffer_write(self->buffer, data, nmemb);
+}
+
+static int td_request_setup(td_request* self) {
+       int r;
+
+       // XXX Share Handle
+
+       // Be a good net citizen and set a user agent
+       r = curl_easy_setopt(self->handle, CURLOPT_USERAGENT, "Mozilla/5.0 (compatible; "
+                       PACKAGE_NAME "/" PACKAGE_VERSION "; +https://www.ipfire.org/)");
+       if (r)
+               goto ERROR;
+
+       // Enable logging/debugging
+       r = curl_easy_setopt(self->handle, CURLOPT_VERBOSE, 1L);
+       if (r)
+               goto ERROR;
+
+       r = curl_easy_setopt(self->handle, CURLOPT_DEBUGFUNCTION, td_request_debug_callback);
+       if (r)
+               goto ERROR;
+
+       r = curl_easy_setopt(self->handle, CURLOPT_DEBUGDATA, self);
+       if (r)
+               goto ERROR;
+
+       // Raise any HTTP errors
+       r = curl_easy_setopt(self->handle, CURLOPT_FAILONERROR, 1L);
+       if (r)
+               goto ERROR;
+
+       // Allow all support encodings
+       r = curl_easy_setopt(self->handle, CURLOPT_ACCEPT_ENCODING, "");
+       if (r)
+               goto ERROR;
+
+       // Reference back to this request
+       r = curl_easy_setopt(self->handle, CURLOPT_PRIVATE, self);
+       if (r)
+               goto ERROR;
+
+       // Follow any redirects
+       r = curl_easy_setopt(self->handle, CURLOPT_FOLLOWLOCATION, 1L);
+       if (r)
+               goto ERROR;
+
+       // Only follow up to 30 redirects
+       r = curl_easy_setopt(self->handle, CURLOPT_MAXREDIRS, 30L);
+       if (r)
+               goto ERROR;
+
+       // Write all data to the callback function
+       r = curl_easy_setopt(self->handle, CURLOPT_WRITEFUNCTION, td_request_write);
+       if (r)
+               goto ERROR;
+
+       r = curl_easy_setopt(self->handle, CURLOPT_WRITEDATA, self);
+       if (r)
+               goto ERROR;
+
+       // Configure the URL
+       r = curl_easy_setopt(self->handle, CURLOPT_CURLU, self->url);
+       if (r)
+               goto ERROR;
+
+ERROR:
+       return r;
+}
+
+static void td_request_free(td_request* self) {
+       if (self->handle)
+               curl_easy_cleanup(self->handle);
+       if (self->buffer)
+               td_buffer_unref(self->buffer);
+       if (self->client)
+               td_client_unref(self->client);
+       if (self->url)
+               curl_url_cleanup(self->url);
+       if (self->ctx)
+               td_ctx_unref(self->ctx);
+       free(self);
+}
+
+int td_request_create(td_request** request, td_ctx* ctx, td_client* client) {
+       td_request* self = NULL;
+       int r;
+
+       // Allocate some memory
+       self = calloc(1, sizeof(*self));
+       if (!self)
+               return -errno;
+
+       // Store a reference to the context
+       self->ctx = td_ctx_ref(ctx);
+
+       // Initialize the reference counter
+       self->nrefs = 1;
+
+       // Store a reference to the client
+       self->client = td_client_ref(client);
+
+       // Allocate a handle
+       self->handle = curl_easy_init();
+       if (!self->handle) {
+               r = -ENOMEM;
+               goto ERROR;
+       }
+
+       // Allocate the URL
+       self->url = curl_url();
+       if (!self->url) {
+               ERROR(self->ctx, "Failed to allocate the URL: %m\n");
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Allocate an output buffer
+       r = td_buffer_create(&self->buffer, self->ctx);
+       if (r < 0)
+               goto ERROR;
+
+       // Setup the request
+       r = td_request_setup(self);
+       if (r)
+               goto ERROR;
+
+       // Return the pointer
+       *request = self;
+       return 0;
+
+ERROR:
+       td_request_free(self);
+
+       return r;
+}
+
+td_request* td_request_ref(td_request* self) {
+       ++self->nrefs;
+       return self;
+}
+
+td_request* td_request_unref(td_request* self) {
+       if (--self->nrefs > 0)
+               return self;
+
+       td_request_free(self);
+       return NULL;
+}
+
+char* td_request_get_url(td_request* self) {
+       char* url = NULL;
+       int r;
+
+       // Format the URL
+       r = curl_url_get(self->url, CURLUPART_URL, &url, 0);
+       if (r < 0)
+               return NULL;
+
+       return url;
+}
+
+int td_request_set_url(td_request* self, const char* url) {
+       int r;
+
+       // Store the URL
+       r = curl_url_set(self->url, CURLUPART_URL, url, 0);
+       if (r < 0) {
+               ERROR(self->ctx, "Could not set the URL: %s\n", curl_easy_strerror(r));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+CURL* td_request_handle(td_request* self) {
+       return self->handle;
+}
+
+int td_request_launch(td_request* self) {
+       return td_client_launch_request(self->client, self);
+}
+
+int td_request_done(td_request* self, int code) {
+       return 0;
+}
diff --git a/src/daemon/request.h b/src/daemon/request.h
new file mode 100644 (file)
index 0000000..dcd8af8
--- /dev/null
@@ -0,0 +1,44 @@
+/*#############################################################################
+#                                                                             #
+# telemetryd - The IPFire Telemetry Collection Service                        #
+# Copyright (C) 2026 IPFire Development Team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef TELEMETRY_REQUEST_H
+#define TELEMETRY_REQUEST_H
+
+#include <curl/curl.h>
+
+typedef struct td_request td_request;
+
+#include "client.h"
+#include "ctx.h"
+
+int td_request_create(td_request** request, td_ctx* ctx, td_client* client);
+
+td_request* td_request_ref(td_request* self);
+td_request* td_request_unref(td_request* self);
+
+char* td_request_get_url(td_request* self);
+int td_request_set_url(td_request* self, const char* url);
+
+CURL* td_request_handle(td_request* self);
+
+int td_request_launch(td_request* self);
+int td_request_done(td_request* self, int code);
+
+#endif /* TELEMETRY_REQUEST_H */