]> git.ipfire.org Git - pakfire.git/commitdiff
xfer: Fail if the connection was unexpectedly closed
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 13 Aug 2024 18:54:15 +0000 (18:54 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 13 Aug 2024 18:54:15 +0000 (18:54 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/xfer.c

index ff88c52b51af014b2fdd16431c83c4fc8bf7d845..c4e7c30164abc40520a4ebaa180d5378cf18fedc 100644 (file)
@@ -717,6 +717,133 @@ int pakfire_xfer_auth(struct pakfire_xfer* xfer) {
        return 0;
 }
 
+/*
+       This function translates any cURL error codes into xfer codes
+*/
+static pakfire_xfer_error_code_t pakfire_xfer_code(CURLcode code, int http_status) {
+       switch (code) {
+               case CURLE_OK:
+                       return PAKFIRE_XFER_OK;
+
+               // Unsupported requests
+               case CURLE_UNSUPPORTED_PROTOCOL:
+               case CURLE_NOT_BUILT_IN:
+               case CURLE_RANGE_ERROR:
+                       return PAKFIRE_XFER_UNSUPPORTED;
+
+               // Invalid requests
+               case CURLE_URL_MALFORMAT:
+                       return PAKFIRE_XFER_INVALID_URL;
+
+               // Invalid responses
+               case CURLE_TOO_MANY_REDIRECTS:
+               case CURLE_GOT_NOTHING:
+               case CURLE_BAD_CONTENT_ENCODING:
+                       return PAKFIRE_XFER_INVALID_RESPONSE;
+
+               // DNS Errors
+               case CURLE_COULDNT_RESOLVE_PROXY:
+               case CURLE_COULDNT_RESOLVE_HOST:
+               case CURLE_FTP_CANT_GET_HOST:
+                       return PAKFIRE_XFER_DNS_ERROR;
+
+               // Authentication
+               case CURLE_AUTH_ERROR:
+                       return PAKFIRE_XFER_AUTH_ERROR;
+
+               // Transport Errors
+               case CURLE_PROXY:
+               case CURLE_SSL_CONNECT_ERROR:
+               case CURLE_SSL_CERTPROBLEM:
+               case CURLE_SSL_CIPHER:
+               case CURLE_PEER_FAILED_VERIFICATION:
+                       return PAKFIRE_XFER_TRANSPORT_ERROR;
+
+               // Access Denied
+               case CURLE_REMOTE_ACCESS_DENIED:
+                       return PAKFIRE_XFER_ACCESS_DENIED;
+
+               // Timeout
+               case CURLE_FTP_ACCEPT_TIMEOUT:
+               case CURLE_OPERATION_TIMEDOUT:
+                       return PAKFIRE_XFER_TIMEOUT;
+
+               // Write error
+               case CURLE_WRITE_ERROR:
+                       return PAKFIRE_XFER_WRITE_ERROR;
+
+               // Read error
+               case CURLE_READ_ERROR:
+               case CURLE_FILE_COULDNT_READ_FILE:
+                       return PAKFIRE_XFER_READ_ERROR;
+
+               // Aborted
+               case CURLE_ABORTED_BY_CALLBACK:
+                       return PAKFIRE_XFER_ABORTED;
+
+               // HTTP Errors
+               case CURLE_HTTP_RETURNED_ERROR:
+                       switch (http_status) {
+                               // Proxy Error
+                               case 502:
+                                       return PAKFIRE_XFER_TRANSPORT_ERROR;
+
+                               // Service Unavailable
+                               case 503:
+                                       return PAKFIRE_XFER_TRANSPORT_ERROR;
+
+                               default:
+                                       return PAKFIRE_XFER_FAILED;
+                       }
+                       break;
+
+               // Return "unknown error" for any other codes
+               default:
+                       return PAKFIRE_XFER_FAILED;
+       }
+}
+
+static int pakfire_xfer_fail(struct pakfire_xfer* xfer, int code) {
+       int r;
+
+       CTX_DEBUG(xfer->ctx, "Xfer failed\n");
+
+       // Throw away any downloaded data
+       if (xfer->fin) {
+               // Get file descriptor
+               int fd = fileno(xfer->fin);
+
+               // Truncate downloaded data
+               if (fd >= 0) {
+                       r = ftruncate(fd, 0);
+                       if (r)
+                               return r;
+               }
+
+               // Rewind
+               rewind(xfer->fin);
+       }
+
+       // Did we use a mirror?
+       if (xfer->mirror) {
+               pakfire_mirror_xfer_failed(xfer->mirror);
+
+               // Try again with another mirror
+               return -EAGAIN;
+       }
+
+       // Call the close callback for WebSockets
+       if (xfer->direction == PAKFIRE_XFER_SOCKET) {
+               if (xfer->callbacks.close) {
+                       r = xfer->callbacks.close(xfer, code, xfer->callbacks.data);
+                       if (r)
+                               return r;
+               }
+       }
+
+       return code;
+}
+
 static int pakfire_xfer_select_mirror(struct pakfire_xfer* xfer) {
        // Choose the next mirror
        if (xfer->mirror)
@@ -794,10 +921,18 @@ static int pakfire_xfer_socket_recv(struct pakfire_xfer* xfer) {
 
        // Read as many bytes as possible
        r = curl_ws_recv(xfer->handle, buffer, sizeof(buffer), &bytes_received, &meta);
-       if (r) {
-               CTX_ERROR(xfer->ctx, "Could not read from WebSocket: %s\n", curl_easy_strerror(r));
+       switch (r) {
+               case CURLE_OK:
+                       break;
 
-               return r;
+               // We seem to have lost the connection
+               case CURLE_GOT_NOTHING:
+                       return pakfire_xfer_fail(xfer, PAKFIRE_XFER_TRANSPORT_ERROR);
+
+               default:
+                       CTX_ERROR(xfer->ctx, "Could not read from WebSocket: %s\n", curl_easy_strerror(r));
+
+                       return r;
        }
 
        CTX_DEBUG(xfer->ctx, "Read %zu byte(s) from WebSocket\n", bytes_received);
@@ -943,133 +1078,6 @@ static int pakfire_xfer_save(struct pakfire_xfer* xfer) {
        return 0;
 }
 
-/*
-       This function translates any cURL error codes into xfer codes
-*/
-static pakfire_xfer_error_code_t pakfire_xfer_code(CURLcode code, int http_status) {
-       switch (code) {
-               case CURLE_OK:
-                       return PAKFIRE_XFER_OK;
-
-               // Unsupported requests
-               case CURLE_UNSUPPORTED_PROTOCOL:
-               case CURLE_NOT_BUILT_IN:
-               case CURLE_RANGE_ERROR:
-                       return PAKFIRE_XFER_UNSUPPORTED;
-
-               // Invalid requests
-               case CURLE_URL_MALFORMAT:
-                       return PAKFIRE_XFER_INVALID_URL;
-
-               // Invalid responses
-               case CURLE_TOO_MANY_REDIRECTS:
-               case CURLE_GOT_NOTHING:
-               case CURLE_BAD_CONTENT_ENCODING:
-                       return PAKFIRE_XFER_INVALID_RESPONSE;
-
-               // DNS Errors
-               case CURLE_COULDNT_RESOLVE_PROXY:
-               case CURLE_COULDNT_RESOLVE_HOST:
-               case CURLE_FTP_CANT_GET_HOST:
-                       return PAKFIRE_XFER_DNS_ERROR;
-
-               // Authentication
-               case CURLE_AUTH_ERROR:
-                       return PAKFIRE_XFER_AUTH_ERROR;
-
-               // Transport Errors
-               case CURLE_PROXY:
-               case CURLE_SSL_CONNECT_ERROR:
-               case CURLE_SSL_CERTPROBLEM:
-               case CURLE_SSL_CIPHER:
-               case CURLE_PEER_FAILED_VERIFICATION:
-                       return PAKFIRE_XFER_TRANSPORT_ERROR;
-
-               // Access Denied
-               case CURLE_REMOTE_ACCESS_DENIED:
-                       return PAKFIRE_XFER_ACCESS_DENIED;
-
-               // Timeout
-               case CURLE_FTP_ACCEPT_TIMEOUT:
-               case CURLE_OPERATION_TIMEDOUT:
-                       return PAKFIRE_XFER_TIMEOUT;
-
-               // Write error
-               case CURLE_WRITE_ERROR:
-                       return PAKFIRE_XFER_WRITE_ERROR;
-
-               // Read error
-               case CURLE_READ_ERROR:
-               case CURLE_FILE_COULDNT_READ_FILE:
-                       return PAKFIRE_XFER_READ_ERROR;
-
-               // Aborted
-               case CURLE_ABORTED_BY_CALLBACK:
-                       return PAKFIRE_XFER_ABORTED;
-
-               // HTTP Errors
-               case CURLE_HTTP_RETURNED_ERROR:
-                       switch (http_status) {
-                               // Proxy Error
-                               case 502:
-                                       return PAKFIRE_XFER_TRANSPORT_ERROR;
-
-                               // Service Unavailable
-                               case 503:
-                                       return PAKFIRE_XFER_TRANSPORT_ERROR;
-
-                               default:
-                                       return PAKFIRE_XFER_FAILED;
-                       }
-                       break;
-
-               // Return "unknown error" for any other codes
-               default:
-                       return PAKFIRE_XFER_FAILED;
-       }
-}
-
-static int pakfire_xfer_fail(struct pakfire_xfer* xfer, int code) {
-       int r;
-
-       CTX_DEBUG(xfer->ctx, "Xfer failed\n");
-
-       // Throw away any downloaded data
-       if (xfer->fin) {
-               // Get file descriptor
-               int fd = fileno(xfer->fin);
-
-               // Truncate downloaded data
-               if (fd >= 0) {
-                       r = ftruncate(fd, 0);
-                       if (r)
-                               return r;
-               }
-
-               // Rewind
-               rewind(xfer->fin);
-       }
-
-       // Did we use a mirror?
-       if (xfer->mirror) {
-               pakfire_mirror_xfer_failed(xfer->mirror);
-
-               // Try again with another mirror
-               return -EAGAIN;
-       }
-
-       // Call the close callback for WebSockets
-       if (xfer->direction == PAKFIRE_XFER_SOCKET) {
-               if (xfer->callbacks.close) {
-                       r = xfer->callbacks.close(xfer, code, xfer->callbacks.data);
-                       if (r)
-                               return r;
-               }
-       }
-
-       return code;
-}
-
 pakfire_xfer_error_code_t pakfire_xfer_done(struct pakfire_xfer* xfer, int code) {
        CURL* h = xfer->handle;
        int r;