}
static struct pakfire_httpclient_xfer* pakfire_httpclient_xfer_find(
- struct pakfire_httpclient* client, struct pakfire_xfer* xfer) {
+ struct pakfire_httpclient* self, struct pakfire_xfer* xfer) {
struct pakfire_httpclient_xfer* e = NULL;
- TAILQ_FOREACH(e, &client->xfers, nodes) {
+ TAILQ_FOREACH(e, &self->xfers, nodes) {
if (e->xfer == xfer)
return e;
}
return NULL;
}
-static int pakfire_httpclient_check(struct pakfire_httpclient* client) {
+static int pakfire_httpclient_check(struct pakfire_httpclient* self) {
struct pakfire_xfer* xfer = NULL;
int r;
for (;;) {
// Read the next message
- msg = curl_multi_info_read(client->curl, &msgs_left);
+ msg = curl_multi_info_read(self->curl, &msgs_left);
if (!msg)
break;
switch (-r) {
// If we are asked to try again we will re-queue the transfer
case EAGAIN:
- r = pakfire_httpclient_enqueue_xfer(client, xfer);
+ r = pakfire_httpclient_enqueue_xfer(self, xfer);
if (r)
return r;
break;
default:
- ERROR(client->ctx, "Received unhandled cURL message %u\n", msg->msg);
+ ERROR(self->ctx, "Received unhandled cURL message %u\n", msg->msg);
break;
}
}
// If we control the loop, terminate it if there are no more transfers left
- if (pakfire_httpclient_has_flag(client, PAKFIRE_HTTPCLIENT_OWN_LOOP)) {
- if (client->still_running <= 0)
- return sd_event_exit(client->loop, 0);
+ if (pakfire_httpclient_has_flag(self, PAKFIRE_HTTPCLIENT_OWN_LOOP)) {
+ if (self->still_running <= 0)
+ return sd_event_exit(self->loop, 0);
}
return 0;
}
static int __pakfire_httpclient_timer(sd_event_source* s, uint64_t usec, void* data) {
- struct pakfire_httpclient* client = data;
+ struct pakfire_httpclient* self = data;
int r;
- DEBUG(client->ctx, "cURL timer fired\n");
+ DEBUG(self->ctx, "cURL timer fired\n");
- r = curl_multi_socket_action(client->curl, CURL_SOCKET_TIMEOUT, 0, &client->still_running);
+ r = curl_multi_socket_action(self->curl, CURL_SOCKET_TIMEOUT, 0, &self->still_running);
if (r)
return r;
// Check for any messages
- r = pakfire_httpclient_check(client);
+ r = pakfire_httpclient_check(self);
if (r)
return r;
}
static int pakfire_httpclient_timer(CURLM* multi, long timeout_ms, void* data) {
- struct pakfire_httpclient* client = data;
+ struct pakfire_httpclient* self = data;
int r;
// A negative value indicates that we should remove the timer
if (timeout_ms < 0) {
- if (client->timer) {
- r = sd_event_source_set_enabled(client->timer, SD_EVENT_OFF);
+ if (self->timer) {
+ r = sd_event_source_set_enabled(self->timer, SD_EVENT_OFF);
if (r < 0)
- ERROR(client->ctx, "Could not disarm the timer: %s\n", strerror(-r));
+ ERROR(self->ctx, "Could not disarm the timer: %s\n", strerror(-r));
}
return 0;
}
// Set the timer
- r = sd_event_source_set_time_relative(client->timer, timeout_ms * 1000);
+ r = sd_event_source_set_time_relative(self->timer, timeout_ms * 1000);
if (r < 0) {
- ERROR(client->ctx, "Could not set timer: %s\n", strerror(-r));
+ ERROR(self->ctx, "Could not set timer: %s\n", strerror(-r));
return r;
}
// Have the timer fire once
- r = sd_event_source_set_enabled(client->timer, SD_EVENT_ONESHOT);
+ r = sd_event_source_set_enabled(self->timer, SD_EVENT_ONESHOT);
if (r < 0) {
- ERROR(client->ctx, "Could not enable the timer: %s\n", strerror(-r));
+ ERROR(self->ctx, "Could not enable the timer: %s\n", strerror(-r));
return r;
}
- DEBUG(client->ctx, "cURL set a timer for %ldms\n", timeout_ms);
+ DEBUG(self->ctx, "cURL set a timer for %ldms\n", timeout_ms);
return 0;
}
static int __pakfire_httpclient_socket(sd_event_source* s, int fd, uint32_t events, void* data) {
- struct pakfire_httpclient* client = data;
+ struct pakfire_httpclient* self = data;
int r;
int action = 0;
if (events & EPOLLOUT)
action |= CURL_CSELECT_OUT;
- //DEBUG(client->ctx, "cURL has activity on socket %d\n", fd);
+ //DEBUG(self->ctx, "cURL has activity on socket %d\n", fd);
// Inform cURL about some socket activity
- r = curl_multi_socket_action(client->curl, fd, action, &client->still_running);
+ r = curl_multi_socket_action(self->curl, fd, action, &self->still_running);
if (r)
return r;
// Check for any messages
- r = pakfire_httpclient_check(client);
+ r = pakfire_httpclient_check(self);
if (r)
return r;
// Disarm the timer
- if (client->still_running <= 0) {
- if (client->timer) {
- r = sd_event_source_set_enabled(client->timer, SD_EVENT_OFF);
+ if (self->still_running <= 0) {
+ if (self->timer) {
+ r = sd_event_source_set_enabled(self->timer, SD_EVENT_OFF);
if (r < 0) {
- ERROR(client->ctx, "Could not disarm the timer: %s\n", strerror(-r));
+ ERROR(self->ctx, "Could not disarm the timer: %s\n", strerror(-r));
return r;
}
}
static int pakfire_httpclient_socket(CURL* e, curl_socket_t fd, int what, void* data, void* data2) {
- struct pakfire_httpclient* client = data;
+ struct pakfire_httpclient* self = data;
sd_event_source* s = data2;
uint32_t events = 0;
int r;
// Disable the event
r = sd_event_source_set_enabled(s, SD_EVENT_OFF);
if (r < 0)
- ERROR(client->ctx, "Could not disable fd %d: %s\n", fd, strerror(-r));
+ ERROR(self->ctx, "Could not disable fd %d: %s\n", fd, strerror(-r));
- DEBUG(client->ctx, "cURL deregistered socket %d\n", fd);
+ DEBUG(self->ctx, "cURL deregistered socket %d\n", fd);
return r;
}
if (s) {
r = sd_event_source_set_io_events(s, events);
if (r < 0) {
- ERROR(client->ctx, "Could not change events for socket %d: %s\n",
+ ERROR(self->ctx, "Could not change events for socket %d: %s\n",
fd, strerror(-r));
return r;
}
- DEBUG(client->ctx, "cURL changed socket %d\n", fd);
+ DEBUG(self->ctx, "cURL changed socket %d\n", fd);
return 0;
}
// Add the socket to the event loop
- r = sd_event_add_io(client->loop, &s, fd, events, __pakfire_httpclient_socket, client);
+ r = sd_event_add_io(self->loop, &s, fd, events, __pakfire_httpclient_socket, self);
if (r < 0) {
- ERROR(client->ctx, "Could not register socket %d: %s\n", fd, strerror(-r));
+ ERROR(self->ctx, "Could not register socket %d: %s\n", fd, strerror(-r));
goto ERROR;
}
// Store the event source
- curl_multi_assign(client->curl, fd, sd_event_source_ref(s));
+ curl_multi_assign(self->curl, fd, sd_event_source_ref(s));
- DEBUG(client->ctx, "cURL registered socket %d\n", fd);
+ DEBUG(self->ctx, "cURL registered socket %d\n", fd);
ERROR:
if (s)
return r;
}
-static int pakfire_httpclient_setup_loop(struct pakfire_httpclient* client, sd_event* loop) {
+static int pakfire_httpclient_setup_loop(struct pakfire_httpclient* self, sd_event* loop) {
int r;
// Use the given loop
if (loop) {
- client->loop = sd_event_ref(loop);
+ self->loop = sd_event_ref(loop);
// Otherwise create a new loop
} else {
- r = sd_event_new(&client->loop);
+ r = sd_event_new(&self->loop);
if (r < 0) {
- ERROR(client->ctx, "Could not setup event loop: %s\n", strerror(-r));
+ ERROR(self->ctx, "Could not setup event loop: %s\n", strerror(-r));
return r;
}
// This is our very own loop
- client->flags |= PAKFIRE_HTTPCLIENT_OWN_LOOP;
+ self->flags |= PAKFIRE_HTTPCLIENT_OWN_LOOP;
}
// Create a new timer
- r = sd_event_add_time_relative(client->loop, &client->timer, CLOCK_MONOTONIC, 0, 0,
- __pakfire_httpclient_timer, client);
+ r = sd_event_add_time_relative(self->loop, &self->timer, CLOCK_MONOTONIC, 0, 0,
+ __pakfire_httpclient_timer, self);
if (r < 0) {
- ERROR(client->ctx, "Could not set timer: %s\n", strerror(-r));
+ ERROR(self->ctx, "Could not set timer: %s\n", strerror(-r));
return r;
}
return 0;
}
-static int pakfire_httpclient_setup_curl(struct pakfire_httpclient* client) {
+static int pakfire_httpclient_setup_curl(struct pakfire_httpclient* self) {
int r;
// Initialize cURL
r = curl_global_init(CURL_GLOBAL_DEFAULT);
if (r) {
- ERROR(client->ctx, "Could not initialize cURL: %d\n", r);
+ ERROR(self->ctx, "Could not initialize cURL: %d\n", r);
return r;
}
// Create a new multi handle
- client->curl = curl_multi_init();
- if (!client->curl) {
- ERROR(client->ctx, "Could not create cURL multi handle\n");
+ self->curl = curl_multi_init();
+ if (!self->curl) {
+ ERROR(self->ctx, "Could not create cURL multi handle\n");
return 1;
}
// Register with the event loop
- r = curl_multi_setopt(client->curl, CURLMOPT_TIMERFUNCTION, pakfire_httpclient_timer);
+ r = curl_multi_setopt(self->curl, CURLMOPT_TIMERFUNCTION, pakfire_httpclient_timer);
if (r) {
- ERROR(client->ctx, "Could not register the timer function: %s\n",
+ ERROR(self->ctx, "Could not register the timer function: %s\n",
curl_multi_strerror(r));
return r;
}
- r = curl_multi_setopt(client->curl, CURLMOPT_TIMERDATA, client);
+ r = curl_multi_setopt(self->curl, CURLMOPT_TIMERDATA, self);
if (r) {
- ERROR(client->ctx, "Could not register the timer data: %s\n",
+ ERROR(self->ctx, "Could not register the timer data: %s\n",
curl_multi_strerror(r));
return r;
}
- r = curl_multi_setopt(client->curl, CURLMOPT_SOCKETFUNCTION, pakfire_httpclient_socket);
+ r = curl_multi_setopt(self->curl, CURLMOPT_SOCKETFUNCTION, pakfire_httpclient_socket);
if (r) {
- ERROR(client->ctx, "Could not register the socket function: %s\n",
+ ERROR(self->ctx, "Could not register the socket function: %s\n",
curl_multi_strerror(r));
return r;
}
- r = curl_multi_setopt(client->curl, CURLMOPT_SOCKETDATA, client);
+ r = curl_multi_setopt(self->curl, CURLMOPT_SOCKETDATA, self);
if (r) {
- ERROR(client->ctx, "Could not register the socket data: %s\n",
+ ERROR(self->ctx, "Could not register the socket data: %s\n",
curl_multi_strerror(r));
return r;
}
// Limit parallel transfers
- r = curl_multi_setopt(client->curl, CURLMOPT_MAXCONNECTS, client->max_parallel);
+ r = curl_multi_setopt(self->curl, CURLMOPT_MAXCONNECTS, self->max_parallel);
if (r) {
- ERROR(client->ctx, "Could not set max parallel transfers: %s\n",
+ ERROR(self->ctx, "Could not set max parallel transfers: %s\n",
curl_multi_strerror(r));
return r;
return 0;
}
-static int pakfire_httpclient_setup_progress(struct pakfire_httpclient* client) {
+static int pakfire_httpclient_setup_progress(struct pakfire_httpclient* self) {
int r;
const int flags =
PAKFIRE_PROGRESS_SHOW_TRANSFER_SPEED;
// Create a new progress indicator
- r = pakfire_progress_create(&client->progress, client->ctx, flags, NULL);
+ r = pakfire_progress_create(&self->progress, self->ctx, flags, NULL);
if (r)
return r;
return 0;
}
-static void pakfire_httpclient_free(struct pakfire_httpclient* client) {
+static void pakfire_httpclient_free(struct pakfire_httpclient* self) {
struct pakfire_httpclient_xfer* e = NULL;
// Free any xfers that we still hold
- while (!TAILQ_EMPTY(&client->xfers)) {
- e = TAILQ_LAST(&client->xfers, xfers);
- TAILQ_REMOVE(&client->xfers, e, nodes);
+ while (!TAILQ_EMPTY(&self->xfers)) {
+ e = TAILQ_LAST(&self->xfers, xfers);
+ TAILQ_REMOVE(&self->xfers, e, nodes);
pakfire_httpclient_xfer_free(e);
}
- if (client->progress)
- pakfire_progress_unref(client->progress);
- if (client->curl)
- curl_multi_cleanup(client->curl);
- if (client->timer)
- sd_event_source_unref(client->timer);
- if (client->loop)
- sd_event_unref(client->loop);
- if (client->ctx)
- pakfire_ctx_unref(client->ctx);
- free(client);
+ if (self->progress)
+ pakfire_progress_unref(self->progress);
+ if (self->curl)
+ curl_multi_cleanup(self->curl);
+ if (self->timer)
+ sd_event_source_unref(self->timer);
+ if (self->loop)
+ sd_event_unref(self->loop);
+ if (self->ctx)
+ pakfire_ctx_unref(self->ctx);
+ free(self);
}
int pakfire_httpclient_create(struct pakfire_httpclient** client,
struct pakfire_ctx* ctx, sd_event* loop) {
- struct pakfire_httpclient* c = NULL;
+ struct pakfire_httpclient* self = NULL;
int r;
// Allocate a new object
- c = calloc(1, sizeof(*c));
- if (!c)
+ self = calloc(1, sizeof(*self));
+ if (!self)
return -errno;
// Store reference to the context
- c->ctx = pakfire_ctx_ref(ctx);
+ self->ctx = pakfire_ctx_ref(ctx);
// Initialize reference counting
- c->nrefs = 1;
+ self->nrefs = 1;
// Set parallelism
- c->max_parallel = DEFAULT_MAX_PARALLEL;
+ self->max_parallel = DEFAULT_MAX_PARALLEL;
// Init the xfer queue
- TAILQ_INIT(&c->xfers);
+ TAILQ_INIT(&self->xfers);
// Setup event loop
- r = pakfire_httpclient_setup_loop(c, loop);
+ r = pakfire_httpclient_setup_loop(self, loop);
if (r)
goto ERROR;
// Setup cURL
- r = pakfire_httpclient_setup_curl(c);
+ r = pakfire_httpclient_setup_curl(self);
if (r)
goto ERROR;
// Setup progress
- r = pakfire_httpclient_setup_progress(c);
+ r = pakfire_httpclient_setup_progress(self);
if (r)
goto ERROR;
// Return the pointer
- *client = pakfire_httpclient_ref(c);
+ *client = pakfire_httpclient_ref(self);
ERROR:
- if (c)
- pakfire_httpclient_unref(c);
+ if (self)
+ pakfire_httpclient_unref(self);
return r;
}
-struct pakfire_httpclient* pakfire_httpclient_ref(struct pakfire_httpclient* client) {
- ++client->nrefs;
+struct pakfire_httpclient* pakfire_httpclient_ref(struct pakfire_httpclient* self) {
+ ++self->nrefs;
- return client;
+ return self;
}
-struct pakfire_httpclient* pakfire_httpclient_unref(struct pakfire_httpclient* client) {
- if (--client->nrefs > 0)
- return client;
+struct pakfire_httpclient* pakfire_httpclient_unref(struct pakfire_httpclient* self) {
+ if (--self->nrefs > 0)
+ return self;
- pakfire_httpclient_free(client);
+ pakfire_httpclient_free(self);
return NULL;
}
-sd_event* pakfire_httpclient_loop(struct pakfire_httpclient* client) {
- return sd_event_ref(client->loop);
+sd_event* pakfire_httpclient_loop(struct pakfire_httpclient* self) {
+ return sd_event_ref(self->loop);
}
-int pakfire_httpclient_enqueue_xfer(struct pakfire_httpclient* client,
+int pakfire_httpclient_enqueue_xfer(struct pakfire_httpclient* self,
struct pakfire_xfer* xfer) {
struct pakfire_httpclient_xfer* e = NULL;
int r;
return r;
// Prepare the xfer
- r = pakfire_xfer_prepare(xfer, client->progress, 0);
+ r = pakfire_xfer_prepare(xfer, self->progress, 0);
if (r < 0)
goto ERROR;
// Increment the xfer counter
- client->total_xfers++;
+ self->total_xfers++;
// Update the total download size
- client->total_downloadsize += pakfire_xfer_get_size(xfer);
+ self->total_downloadsize += pakfire_xfer_get_size(xfer);
// Add the handle to cURL
- r = curl_multi_add_handle(client->curl, pakfire_xfer_handle(xfer));
+ r = curl_multi_add_handle(self->curl, pakfire_xfer_handle(xfer));
if (r) {
- ERROR(client->ctx, "Adding handle failed: %s\n", curl_multi_strerror(r));
+ ERROR(self->ctx, "Adding handle failed: %s\n", curl_multi_strerror(r));
goto ERROR;
}
// Keep a reference to the xfer
- TAILQ_INSERT_TAIL(&client->xfers, e, nodes);
+ TAILQ_INSERT_TAIL(&self->xfers, e, nodes);
// Transfer enqueued
- return pakfire_xfer_enqueued(xfer, client);
+ return pakfire_xfer_enqueued(xfer, self);
ERROR:
if (e)
return r;
}
-int pakfire_httpclient_dequeue_xfer(struct pakfire_httpclient* client,
+int pakfire_httpclient_dequeue_xfer(struct pakfire_httpclient* self,
struct pakfire_xfer* xfer) {
struct pakfire_httpclient_xfer* e = NULL;
// Find reference
- e = pakfire_httpclient_xfer_find(client, xfer);
+ e = pakfire_httpclient_xfer_find(self, xfer);
if (!e)
return 0;
// Decrement the xfers counter
- client->total_xfers--;
+ self->total_xfers--;
// Reduce the total download size
- client->total_downloadsize -= pakfire_xfer_get_size(xfer);
+ self->total_downloadsize -= pakfire_xfer_get_size(xfer);
- TAILQ_REMOVE(&client->xfers, e, nodes);
+ TAILQ_REMOVE(&self->xfers, e, nodes);
pakfire_httpclient_xfer_free(e);
return 0;
}
-int pakfire_httpclient_remove_xfer(struct pakfire_httpclient* client,
+int pakfire_httpclient_remove_xfer(struct pakfire_httpclient* self,
struct pakfire_xfer* xfer) {
int r;
// Remove the handle
- r = curl_multi_remove_handle(client->curl, pakfire_xfer_handle(xfer));
+ r = curl_multi_remove_handle(self->curl, pakfire_xfer_handle(xfer));
if (r) {
- ERROR(client->ctx, "Could not remove the handle: %s\n", curl_multi_strerror(r));
+ ERROR(self->ctx, "Could not remove the handle: %s\n", curl_multi_strerror(r));
return -ENOTSUP;
}
return 0;
}
-int pakfire_httpclient_run(struct pakfire_httpclient* client, const char* title) {
+int pakfire_httpclient_run(struct pakfire_httpclient* self, const char* title) {
int r = 0;
// Cannot run without any transfers
- if (!client->total_xfers) {
- DEBUG(client->ctx, "Skipping running HTTP client without any transfers\n");
+ if (!self->total_xfers) {
+ DEBUG(self->ctx, "Skipping running HTTP client without any transfers\n");
return 0;
}
// Set the title
- r = pakfire_progress_set_title(client->progress, "%s", title);
+ r = pakfire_progress_set_title(self->progress, "%s", title);
if (r)
goto ERROR;
// Start the progress
- r = pakfire_progress_start(client->progress, client->total_downloadsize);
+ r = pakfire_progress_start(self->progress, self->total_downloadsize);
if (r)
goto ERROR;
// Run the event loop
- r = sd_event_loop(client->loop);
+ r = sd_event_loop(self->loop);
if (r < 0) {
- ERROR(client->ctx, "Event loop failed: %s\n", strerror(-r));
+ ERROR(self->ctx, "Event loop failed: %s\n", strerror(-r));
goto ERROR;
}
ERROR:
// We are finished!
- pakfire_progress_finish(client->progress);
+ pakfire_progress_finish(self->progress);
return r;
}