static size_t curl_write_func(void *ptr, size_t size, size_t nmemb, void *data) { Request *request = (Request *) data; int len = size * nmemb; request_headers_done(request); if (request->status != S3StatusOK) { return 0; } // On HTTP error, we expect to parse an HTTP error response if ((request->httpResponseCode < 200) || (request->httpResponseCode > 299)) { request->status = error_parser_add (&(request->errorParser), (char *) ptr, len); } // If there was a callback registered, make it else if (request->fromS3Callback) { request->status = (*(request->fromS3Callback)) (len, (char *) ptr, request->callbackData); } // Else, consider this an error - S3 has sent back data when it was not // expected else { request->status = S3StatusInternalError; } return ((request->status == S3StatusOK) ? len : 0); }
static size_t curl_read_func(void *ptr, size_t size, size_t nmemb, void *data) { Request *request = (Request *) data; int len = size * nmemb; request_headers_done(request); if (request->status != S3StatusOK) { return CURL_READFUNC_ABORT; } // If there is no data callback, or the data callback has already returned // contentLength bytes, return 0; if (!request->toS3Callback || !request->toS3CallbackBytesRemaining) { return 0; } // Don't tell the callback that we are willing to accept more data than we // really are if (len > request->toS3CallbackBytesRemaining) { len = request->toS3CallbackBytesRemaining; } // Otherwise, make the data callback int ret = (*(request->toS3Callback)) (len, (char *) ptr, request->callbackData); if (ret < 0) { request->status = S3StatusAbortedByCallback; return CURL_READFUNC_ABORT; } else { if (ret > request->toS3CallbackBytesRemaining) { ret = request->toS3CallbackBytesRemaining; } request->toS3CallbackBytesRemaining -= ret; return ret; } }
void request_finish(Request *request) { // If we haven't detected this already, we now know that the headers are // definitely done being read in request_headers_done(request); // If there was no error processing the request, then possibly there was // an S3 error parsed, which should be converted into the request status if (request->status == S3StatusOK) { error_parser_convert_status(&(request->errorParser), &(request->status)); // If there still was no error recorded, then it is possible that // there was in fact an error but that there was no error XML // detailing the error if ((request->status == S3StatusOK) && ((request->httpResponseCode < 200) || (request->httpResponseCode > 299))) { switch (request->httpResponseCode) { case 0: // This happens if the request never got any HTTP response // headers at all, we call this a ConnectionFailed error request->status = S3StatusConnectionFailed; break; case 100: // Some versions of libcurl erroneously set HTTP // status to this break; case 301: request->status = S3StatusErrorPermanentRedirect; break; case 307: request->status = S3StatusHttpErrorMovedTemporarily; break; case 400: request->status = S3StatusHttpErrorBadRequest; break; case 403: request->status = S3StatusHttpErrorForbidden; break; case 404: request->status = S3StatusHttpErrorNotFound; break; case 405: request->status = S3StatusErrorMethodNotAllowed; break; case 409: request->status = S3StatusHttpErrorConflict; break; case 411: request->status = S3StatusErrorMissingContentLength; break; case 412: request->status = S3StatusErrorPreconditionFailed; break; case 416: request->status = S3StatusErrorInvalidRange; break; case 500: request->status = S3StatusErrorInternalError; break; case 501: request->status = S3StatusErrorNotImplemented; break; case 503: request->status = S3StatusErrorSlowDown; break; default: request->status = S3StatusHttpErrorUnknown; break; } } } (*(request->completeCallback)) (request->status, &(request->errorParser.s3ErrorDetails), request->callbackData); request_release(request); }