From: Michael Tremer Date: Wed, 1 Nov 2023 09:57:45 +0000 (+0000) Subject: buildservice: Move API request handling code into xfer X-Git-Tag: 0.9.30~1360 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3fcf86a041edd3019731eb9a65a285887f2ecc4a;p=pakfire.git buildservice: Move API request handling code into xfer Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/buildservice.c b/src/libpakfire/buildservice.c index 1634e7a72..d3bed7e96 100644 --- a/src/libpakfire/buildservice.c +++ b/src/libpakfire/buildservice.c @@ -217,103 +217,11 @@ ERROR: return r; } -static int pakfire_buildservice_handle_error(struct pakfire_buildservice* service, - struct pakfire_xfer* xfer, const struct json_object* error) { - struct json_object* message = NULL; - struct json_object* code = NULL; - const char* m = NULL; - unsigned int c = 0; - - // Fetch the URL - const char* url = pakfire_xfer_get_effective_url(xfer); - - // Fetch the code - if (!json_object_object_get_ex(error, "code", &code)) - return -EBADMSG; - - // Check if the code is an integer - if (!json_object_is_type(code, json_type_int)) - return -EBADMSG; - - // Fetch the message - if (!json_object_object_get_ex(error, "message", &message)) - return -EBADMSG; - - // Check if the message is a string - if (!json_object_is_type(message, json_type_string)) - return -EBADMSG; - - c = json_object_get_uint64(code); - m = json_object_get_string(message); - - // Log the error - CTX_ERROR(service->ctx, "%s responded with error %u (%s):\n %s\n", - url, c, strerror(c), m); - - return -c; -} - -/* - This function parses an API response -*/ -static int pakfire_buildservice_parse_response(struct pakfire_buildservice* service, - struct pakfire_xfer* xfer, const char* buffer, const size_t length, - struct json_object** object) { - struct json_object* error = NULL; - struct json_object* o = NULL; - int r; - - // Check if we received any data - if (!length) { - CTX_ERROR(service->ctx, "Received an empty response\n"); - r = -EBADMSG; - goto ERROR; - } - - // XXX Maybe fetch the parser's error message here?! - - // Parse the buffer - o = pakfire_json_parse(service->ctx, buffer, length); - if (!o) { - CTX_ERROR(service->ctx, "Could not parse the response\n"); - r = -EBADMSG; - goto ERROR; - } - - // Check if the response is a dictionary - if (!json_object_is_type(o, json_type_object)) { - CTX_ERROR(service->ctx, "The received object is not a JSON dict\n"); - r = -EBADMSG; - goto ERROR; - } - - // Fetch error - r = json_object_object_get_ex(o, "error", &error); - if (r) { - r = pakfire_buildservice_handle_error(service, xfer, error); - goto ERROR; - } - - // Return the object - *object = o; - - return 0; - -ERROR: - if (o) - json_object_put(o); - - return r; -} - // Build int pakfire_buildservice_build(struct pakfire_buildservice* service, const char* upload, const char* repo, const char** arches, int flags) { struct pakfire_xfer* xfer = NULL; - struct json_object* response = NULL; - char* buffer = NULL; - size_t length = 0; int r; // Create a new xfer @@ -352,30 +260,14 @@ int pakfire_buildservice_build(struct pakfire_buildservice* service, const char* goto ERROR; } - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + // Send the request + r = pakfire_xfer_run_api_request(xfer, NULL); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - ERROR: if (xfer) pakfire_xfer_unref(xfer); - if (response) - json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -390,8 +282,6 @@ static int pakfire_buildservice_create_upload(struct pakfire_buildservice* servi struct json_object* id = NULL; const char* __id = NULL; char* hexdigest = NULL; - char* buffer = NULL; - size_t length = 0; struct stat stat; int r; @@ -447,23 +337,11 @@ static int pakfire_buildservice_create_upload(struct pakfire_buildservice* servi if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + // Send the request + r = pakfire_xfer_run_api_request(xfer, &response); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - // Fetch the ID r = json_object_object_get_ex(response, "id", &id); if (r == 0) { @@ -497,8 +375,6 @@ ERROR: json_object_put(response); if (hexdigest) free(hexdigest); - if (buffer) - free(buffer); return r; } @@ -506,9 +382,6 @@ ERROR: static int pakfire_buildservice_upload_payload(struct pakfire_buildservice* service, const char* filename, const char* uuid, FILE* f) { struct pakfire_xfer* xfer = NULL; - struct json_object* response = NULL; - char* buffer = NULL; - size_t length = 0; char url[PATH_MAX]; int r; @@ -532,28 +405,14 @@ static int pakfire_buildservice_upload_payload(struct pakfire_buildservice* serv if (r) goto ERROR; - // Set the output buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, 0); + // Send the request + r = pakfire_xfer_run_api_request(xfer, NULL); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - ERROR: if (xfer) pakfire_xfer_unref(xfer); - if (response) - json_object_put(response); return r; } @@ -610,8 +469,6 @@ PAKFIRE_EXPORT int pakfire_buildservice_list_uploads( struct pakfire_xfer* xfer = NULL; struct json_object* response = NULL; struct json_object* uploads = NULL; - char* buffer = NULL; - size_t length = 0; int r; // Create a new xfer @@ -624,23 +481,11 @@ PAKFIRE_EXPORT int pakfire_buildservice_list_uploads( if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); + // Send the request + r = pakfire_xfer_run_api_request(xfer, &response); if (r) goto ERROR; - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); - if (r) - goto ERROR; - - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - // Fetch the uploads uploads = json_object_object_get(response, "uploads"); if (!uploads) { @@ -657,8 +502,6 @@ ERROR: pakfire_xfer_unref(xfer); if (response) json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -667,8 +510,6 @@ PAKFIRE_EXPORT int pakfire_buildservice_delete_upload( struct pakfire_buildservice* service, const char* uuid) { struct pakfire_xfer* xfer = NULL; struct json_object* response = NULL; - char* buffer = NULL; - size_t length = 0; char url[PATH_MAX]; int r; @@ -692,30 +533,16 @@ PAKFIRE_EXPORT int pakfire_buildservice_delete_upload( if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); + // Send the request + r = pakfire_xfer_run_api_request(xfer, &response); if (r) goto ERROR; - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); - if (r) - goto ERROR; - - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - ERROR: if (xfer) pakfire_xfer_unref(xfer); if (response) json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -728,8 +555,6 @@ PAKFIRE_EXPORT int pakfire_buildservice_list_repos(struct pakfire_buildservice* struct json_object* response = NULL; struct json_object* repos = NULL; char url[PATH_MAX]; - char* buffer = NULL; - size_t length = 0; int r; // Check inputs @@ -751,23 +576,11 @@ PAKFIRE_EXPORT int pakfire_buildservice_list_repos(struct pakfire_buildservice* if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + // Send the request + r = pakfire_xfer_run_api_request(xfer, &response); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - // Fetch the repos if (!json_object_object_get_ex(response, "repos", &repos)) { CTX_ERROR(service->ctx, "Malformed response\n"); @@ -783,8 +596,6 @@ ERROR: pakfire_xfer_unref(xfer); if (response) json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -794,8 +605,6 @@ PAKFIRE_EXPORT int pakfire_buildservice_get_repo(struct pakfire_buildservice* se struct pakfire_xfer* xfer = NULL; struct json_object* response = NULL; char url[PATH_MAX]; - char* buffer = NULL; - size_t length = 0; int r; // Check inputs @@ -817,23 +626,11 @@ PAKFIRE_EXPORT int pakfire_buildservice_get_repo(struct pakfire_buildservice* se if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); + // Send the request + r = pakfire_xfer_run_api_request(xfer, &response); if (r) goto ERROR; - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); - if (r) - goto ERROR; - - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - // Return the pointer *p = json_object_get(response); @@ -842,8 +639,6 @@ ERROR: pakfire_xfer_unref(xfer); if (response) json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -853,8 +648,6 @@ PAKFIRE_EXPORT int pakfire_buildservice_create_repo(struct pakfire_buildservice* struct pakfire_xfer* xfer = NULL; struct json_object* response = NULL; char url[PATH_MAX]; - char* buffer = NULL; - size_t length = 0; int r; // Check inputs @@ -888,23 +681,11 @@ PAKFIRE_EXPORT int pakfire_buildservice_create_repo(struct pakfire_buildservice* goto ERROR; } - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + // Send the request + r = pakfire_xfer_run_api_request(xfer, &response); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - // Return the pointer if (p) *p = json_object_get(response); @@ -914,8 +695,6 @@ ERROR: pakfire_xfer_unref(xfer); if (response) json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -923,9 +702,6 @@ ERROR: PAKFIRE_EXPORT int pakfire_buildservice_delete_repo(struct pakfire_buildservice* service, const char* distro, const char* name) { struct pakfire_xfer* xfer = NULL; - struct json_object* response = NULL; - char* buffer = NULL; - size_t length = 0; char url[PATH_MAX]; int r; @@ -949,30 +725,14 @@ PAKFIRE_EXPORT int pakfire_buildservice_delete_repo(struct pakfire_buildservice* if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + // Send the request + r = pakfire_xfer_run_api_request(xfer, NULL); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - ERROR: if (xfer) pakfire_xfer_unref(xfer); - if (response) - json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -986,9 +746,6 @@ PAKFIRE_EXPORT int pakfire_buildservice_submit_stats(struct pakfire_buildservice int r; struct pakfire_xfer* xfer = NULL; - json_object* response = NULL; - char* buffer = NULL; - size_t length = 0; // Fetch the distro const struct pakfire_distro* distro = pakfire_ctx_get_distro(service->ctx); @@ -1189,30 +946,14 @@ PAKFIRE_EXPORT int pakfire_buildservice_submit_stats(struct pakfire_buildservice if (r) goto ERROR; - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); + // Send the request + r = pakfire_xfer_run_api_request(xfer, NULL); if (r) goto ERROR; - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); - if (r) - goto ERROR; - - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - ERROR: if (xfer) pakfire_xfer_unref(xfer); - if (response) - json_object_put(response); - if (buffer) - free(buffer); return r; } @@ -1221,12 +962,8 @@ PAKFIRE_EXPORT int pakfire_buildservice_job_finished(struct pakfire_buildservice const char* uuid, int success, const char* logfile, const char** packages) { struct pakfire_xfer* xfer = NULL; char url[PATH_MAX]; - char* buffer = NULL; - size_t length = 0; int r; - struct json_object* response = NULL; - unsigned int num_packages = 0; // Count packages @@ -1267,30 +1004,14 @@ PAKFIRE_EXPORT int pakfire_buildservice_job_finished(struct pakfire_buildservice goto ERROR; } - // Write the response to the buffer - r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); - if (r) - goto ERROR; - - // Run the xfer - r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + // Send the request + r = pakfire_xfer_run_api_request(xfer, NULL); if (r) goto ERROR; - // Parse the response - r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response); - if (r) { - CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r)); - goto ERROR; - } - ERROR: if (xfer) pakfire_xfer_unref(xfer); - if (response) - json_object_put(response); - if (buffer) - free(buffer); return r; } diff --git a/src/libpakfire/include/pakfire/xfer.h b/src/libpakfire/include/pakfire/xfer.h index 09e633357..ca1e501d8 100644 --- a/src/libpakfire/include/pakfire/xfer.h +++ b/src/libpakfire/include/pakfire/xfer.h @@ -25,6 +25,8 @@ #include +#include + struct pakfire_xfer; #include @@ -88,6 +90,7 @@ int pakfire_xfer_done(struct pakfire_xfer* xfer, int code); int pakfire_xfer_fail(struct pakfire_xfer* xfer, int code); int pakfire_xfer_run(struct pakfire_xfer* xfer, int flags); +int pakfire_xfer_run_api_request(struct pakfire_xfer* xfer, struct json_object** response); #endif /* PAKFIRE_PRIVATE */ #endif /* PAKFIRE_XFER_H */ diff --git a/src/libpakfire/xfer.c b/src/libpakfire/xfer.c index e86618820..47aa3d2f3 100644 --- a/src/libpakfire/xfer.c +++ b/src/libpakfire/xfer.c @@ -25,6 +25,8 @@ #include +#include + #include #include @@ -532,7 +534,17 @@ ERROR: return r; } +static void pakfire_xfer_reset_output(struct pakfire_xfer* xfer) { + if (xfer->fin) { + fclose(xfer->fin); + xfer->fin = NULL; + } +} + int pakfire_xfer_set_output(struct pakfire_xfer* xfer, FILE* f) { + pakfire_xfer_reset_output(xfer); + + // Store the new stream xfer->fin = f; return 0; @@ -1181,3 +1193,143 @@ AGAIN: return r; } + +static int pakfire_xfer_handle_api_error( + struct pakfire_xfer* xfer, const struct json_object* error) { + struct json_object* message = NULL; + struct json_object* code = NULL; + const char* m = NULL; + unsigned int c = 0; + + // Fetch the URL + const char* url = pakfire_xfer_get_effective_url(xfer); + + // Fetch the code + if (!json_object_object_get_ex(error, "code", &code)) + return -EBADMSG; + + // Check if the code is an integer + if (!json_object_is_type(code, json_type_int)) + return -EBADMSG; + + // Fetch the message + if (!json_object_object_get_ex(error, "message", &message)) + return -EBADMSG; + + // Check if the message is a string + if (!json_object_is_type(message, json_type_string)) + return -EBADMSG; + + c = json_object_get_uint64(code); + m = json_object_get_string(message); + + // Log the error + CTX_ERROR(xfer->ctx, "%s responded with error %u (%s):\n %s\n", + url, c, strerror(c), m); + + return -c; +} + +/* + This function parses an API response +*/ +static int pakfire_xfer_parse_api_response(struct pakfire_xfer* xfer, + const char* buffer, const size_t length, struct json_object** object) { + struct json_object* error = NULL; + struct json_object* o = NULL; + int r; + + // Check if we received any data + if (!length) { + CTX_ERROR(xfer->ctx, "Received an empty response\n"); + r = -EBADMSG; + goto ERROR; + } + + // XXX Maybe fetch the parser's error message here?! + + // Parse the buffer + o = pakfire_json_parse(xfer->ctx, buffer, length); + if (!o) { + CTX_ERROR(xfer->ctx, "Could not parse the response\n"); + r = -EBADMSG; + goto ERROR; + } + + // Check if the response is a dictionary + if (!json_object_is_type(o, json_type_object)) { + CTX_ERROR(xfer->ctx, "The received object is not a JSON dict\n"); + r = -EBADMSG; + goto ERROR; + } + + // Fetch error + r = json_object_object_get_ex(o, "error", &error); + if (r) { + r = pakfire_xfer_handle_api_error(xfer, error); + goto ERROR; + } + + // Return the object + if (object) + *object = json_object_get(o); + +ERROR: + if (o) + json_object_put(o); + + return r; +} + +static int pakfire_xfer_run_api_request_once(struct pakfire_xfer* xfer, struct json_object** response) { + char* buffer = NULL; + size_t length = 0; + int r; + + // Write the response to the buffer + r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length); + if (r) + goto ERROR; + + // Run the xfer + r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS); + if (r) + goto ERROR; + + // Parse the response + r = pakfire_xfer_parse_api_response(xfer, buffer, length, response); + if (r) { + CTX_ERROR(xfer->ctx, "Could not parse the API response: %s\n", strerror(-r)); + goto ERROR; + } + +ERROR: + // Reset the output stream + pakfire_xfer_reset_output(xfer); + + if (buffer) + free(buffer); + + return r; +} + +/* + This function sends a request and automatically parses the response. + The response might optionally be returned if response is not NULL. +*/ +int pakfire_xfer_run_api_request(struct pakfire_xfer* xfer, struct json_object** response) { + int r; + + // Loop indefinitely... + for (;;) { + r = pakfire_xfer_run_api_request_once(xfer, response); + switch (r) { + // XXX need to catch errors and act accordingly + + default: + return r; + } + } + + return 0; +}