STSStatus request_perform(RequestParams* params, int* httpResponseCode, char* response) { Request* request = 0; STSStatus status; if (STSStatusOK != (status = request_get(params, &request))) { fprintf(stderr, "Request Get ERR\n"); return status; } request->getResultCallback = responseCallback; request->callbackData = response; request->status = STSStatusWaiting; CURLcode code = curl_easy_perform(request->curl); if (CURLE_OK != code) { request->httpResponseCode = 0; *httpResponseCode = request->httpResponseCode; request->status = request_curl_code_to_status(code); return request->status; } else { *httpResponseCode = request->httpResponseCode; request_finish(request); return request->status; } }
S3Status S3_finish_request_context(S3RequestContext *requestContext) { CURLMsg *msg; int junk; while ((msg = curl_multi_info_read(requestContext->curlm, &junk))) { if (msg->msg != CURLMSG_DONE) { return S3StatusInternalError; } Request *request; if (curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char **) (char *) &request) != CURLE_OK) { return S3StatusInternalError; } // Remove the request from the list of requests if (request->prev == request->next) { // It was the only one on the list requestContext->requests = 0; } else { // It doesn't matter what the order of them are, so just in // case request was at the head of the list, put the one after // request to the head of the list requestContext->requests = request->next; request->prev->next = request->next; request->next->prev = request->prev; } if ((msg->data.result != CURLE_OK) && (request->status == S3StatusOK)) { request->status = request_curl_code_to_status (msg->data.result); if (! request->errorParser.s3ErrorDetails.message) { request->errorParser.s3ErrorDetails.message = curl_easy_strerror(msg->data.result); } } if (curl_multi_remove_handle(requestContext->curlm, msg->easy_handle) != CURLM_OK) { return S3StatusInternalError; } // Finish the request, ensuring that all callbacks have been made, // and also releases the request request_finish(request); // Now, since a callback was made, there may be new requests // queued up to be performed immediately, so do so } return S3StatusOK; }
void request_perform(const RequestParams *params, S3RequestContext *context) { Request *request; S3Status status; #define return_status(status) \ (*(params->completeCallback))(status, 0, params->callbackData); \ return // These will hold the computed values RequestComputedValues computed; // Validate the bucket name if (params->bucketContext.bucketName && ((status = S3_validate_bucket_name (params->bucketContext.bucketName, params->bucketContext.uriStyle)) != S3StatusOK)) { return_status(status); } // Compose the amz headers if ((status = compose_amz_headers(params, &computed)) != S3StatusOK) { return_status(status); } // Compose standard headers if ((status = compose_standard_headers (params, &computed)) != S3StatusOK) { return_status(status); } // URL encode the key if ((status = encode_key(params, &computed)) != S3StatusOK) { return_status(status); } // Compute the canonicalized amz headers canonicalize_amz_headers(&computed); // Compute the canonicalized resource canonicalize_resource(params->bucketContext.bucketName, params->subResource, computed.urlEncodedKey, computed.canonicalizedResource); // Compose Authorization header if ((status = compose_auth_header(params, &computed)) != S3StatusOK) { return_status(status); } // Get an initialized Request structure now if ((status = request_get(params, &computed, &request)) != S3StatusOK) { return_status(status); } // If a RequestContext was provided, add the request to the curl multi if (context) { CURLMcode code = curl_multi_add_handle(context->curlm, request->curl); if (code == CURLM_OK) { if (context->requests) { request->prev = context->requests->prev; request->next = context->requests; context->requests->prev->next = request; context->requests->prev = request; } else { context->requests = request->next = request->prev = request; } } else { if (request->status == S3StatusOK) { request->status = (code == CURLM_OUT_OF_MEMORY) ? S3StatusOutOfMemory : S3StatusInternalError; } request_finish(request); } } // Else, perform the request immediately else { CURLcode code = curl_easy_perform(request->curl); if ((code != CURLE_OK) && (request->status == S3StatusOK)) { request->status = request_curl_code_to_status(code); } // Finish the request, ensuring that all callbacks have been made, and // also releases the request request_finish(request); } }
S3Status S3_runonce_request_context(S3RequestContext *requestContext, int *requestsRemainingReturn) { CURLMcode status; do { status = curl_multi_perform(requestContext->curlm, requestsRemainingReturn); switch (status) { case CURLM_OK: case CURLM_CALL_MULTI_PERFORM: break; case CURLM_OUT_OF_MEMORY: return S3StatusOutOfMemory; default: return S3StatusInternalError; } CURLMsg *msg; int junk; while ((msg = curl_multi_info_read(requestContext->curlm, &junk))) { if (msg->msg != CURLMSG_DONE) { return S3StatusInternalError; } Request *request; if (curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char **) (char *) &request) != CURLE_OK) { return S3StatusInternalError; } // Remove the request from the list of requests if (request->prev == request->next) { // It was the only one on the list requestContext->requests = 0; } else { // It doesn't matter what the order of them are, so just in // case request was at the head of the list, put the one after // request to the head of the list requestContext->requests = request->next; request->prev->next = request->next; request->next->prev = request->prev; } if ((msg->data.result != CURLE_OK) && (request->status == S3StatusOK)) { request->status = request_curl_code_to_status (msg->data.result); } if (curl_multi_remove_handle(requestContext->curlm, msg->easy_handle) != CURLM_OK) { return S3StatusInternalError; } // Finish the request, ensuring that all callbacks have been made, // and also releases the request request_finish(request); // Now, since a callback was made, there may be new requests // queued up to be performed immediately, so do so status = CURLM_CALL_MULTI_PERFORM; } } while (status == CURLM_CALL_MULTI_PERFORM); return S3StatusOK; }