]> git.ipfire.org Git - pakfire.git/commitdiff
buildservice: Move API request handling code into xfer
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Nov 2023 09:57:45 +0000 (09:57 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Nov 2023 09:57:45 +0000 (09:57 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/buildservice.c
src/libpakfire/include/pakfire/xfer.h
src/libpakfire/xfer.c

index 1634e7a72afb126aea037511794a82f809e3f454..d3bed7e969252ab5410a20ba8c025cecb5ad076f 100644 (file)
@@ -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;
 }
index 09e6333578e61f5454b609eb7b64793cc10f6280..ca1e501d82b0c36bb431c873e38bb1fee4e8d4c0 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <curl/curl.h>
 
+#include <json.h>
+
 struct pakfire_xfer;
 
 #include <pakfire/ctx.h>
@@ -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 */
index e86618820846c568ee01e9e0e98c125ab6a97f3b..47aa3d2f39478bad1598837c1730d96568a4514b 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <curl/curl.h>
 
+#include <json.h>
+
 #include <openssl/err.h>
 #include <openssl/evp.h>
 
@@ -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;
+}