in src/source/Response.c [125:235]
STATUS initializeCurlSession(PRequestInfo pRequestInfo, PCallInfo pCallInfo, CURL** ppCurl, PVOID data, CurlCallbackFunc writeHeaderFn,
CurlCallbackFunc readFn, CurlCallbackFunc writeFn, CurlCallbackFunc responseWriteFn)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
BOOL secureConnection;
CURL* pCurl = NULL;
UINT32 length;
STAT_STRUCT entryStat;
CHK(pRequestInfo != NULL && pCallInfo != NULL && ppCurl != NULL, STATUS_NULL_ARG);
pCallInfo->pRequestInfo = pRequestInfo;
pCallInfo->httpStatus = HTTP_STATUS_CODE_NOT_SET;
pCallInfo->callResult = SERVICE_CALL_RESULT_NOT_SET;
// Initialize curl and set options
pCurl = curl_easy_init();
CHK(pCurl != NULL, STATUS_CURL_INIT_FAILED);
// set up the friendly error message buffer
pCallInfo->errorBuffer[0] = '\0';
curl_easy_setopt(pCurl, CURLOPT_ERRORBUFFER, pCallInfo->errorBuffer);
curl_easy_setopt(pCurl, CURLOPT_URL, pRequestInfo->url);
curl_easy_setopt(pCurl, CURLOPT_NOSIGNAL, 1);
// Setting up limits for curl timeout
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_TIME, DEFAULT_LOW_SPEED_TIME_LIMIT / HUNDREDS_OF_NANOS_IN_A_SECOND);
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_LIMIT, DEFAULT_LOW_SPEED_LIMIT);
// set verification for SSL connections
CHK_STATUS(requestRequiresSecureConnection(pRequestInfo->url, &secureConnection));
if (secureConnection) {
// Use the default cert store at /etc/ssl in most common platforms
if (pRequestInfo->certPath[0] != '\0') {
CHK(0 == FSTAT(pRequestInfo->certPath, &entryStat), STATUS_DIRECTORY_ENTRY_STAT_ERROR);
if (S_ISDIR(entryStat.st_mode)) {
// Assume it's the path as we have a directory
curl_easy_setopt(pCurl, CURLOPT_CAPATH, pRequestInfo->certPath);
} else {
// We should check for the extension being PEM
length = (UINT32) STRNLEN(pRequestInfo->certPath, MAX_PATH_LEN);
CHK(length > ARRAY_SIZE(CA_CERT_FILE_SUFFIX), STATUS_INVALID_ARG_LEN);
CHK(0 == STRCMPI(CA_CERT_FILE_SUFFIX, &pRequestInfo->certPath[length - ARRAY_SIZE(CA_CERT_FILE_SUFFIX) + 1]),
STATUS_INVALID_CA_CERT_PATH);
curl_easy_setopt(pCurl, CURLOPT_CAINFO, pRequestInfo->certPath);
}
}
// Enforce the public cert verification - even though this is the default
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1L);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 2L);
curl_easy_setopt(pCurl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
}
// set request completion timeout in milliseconds
if (pRequestInfo->completionTimeout != SERVICE_CALL_INFINITE_TIMEOUT) {
curl_easy_setopt(pCurl, CURLOPT_TIMEOUT_MS, pRequestInfo->completionTimeout / HUNDREDS_OF_NANOS_IN_A_MILLISECOND);
}
curl_easy_setopt(pCurl, CURLOPT_CONNECTTIMEOUT_MS, pRequestInfo->connectionTimeout / HUNDREDS_OF_NANOS_IN_A_MILLISECOND);
curl_easy_setopt(pCurl, CURLOPT_TCP_NODELAY, 1);
// set header callback
curl_easy_setopt(pCurl, CURLOPT_HEADERFUNCTION, writeHeaderFn);
curl_easy_setopt(pCurl, CURLOPT_HEADERDATA, data);
switch (pRequestInfo->verb) {
case HTTP_REQUEST_VERB_GET:
curl_easy_setopt(pCurl, CURLOPT_HTTPGET, 1L);
break;
case HTTP_REQUEST_VERB_PUT:
curl_easy_setopt(pCurl, CURLOPT_PUT, 1L);
break;
case HTTP_REQUEST_VERB_POST:
curl_easy_setopt(pCurl, CURLOPT_POST, 1L);
if (pRequestInfo->body == NULL) {
// Set the read callback from the request
curl_easy_setopt(pCurl, CURLOPT_READFUNCTION, readFn);
curl_easy_setopt(pCurl, CURLOPT_READDATA, data);
// Set the write callback from the request
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, writeFn);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, data);
} else {
// Set the read data and it's size
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE, pRequestInfo->bodySize);
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, pRequestInfo->body);
// Set response callback
curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, responseWriteFn);
curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, data);
}
break;
}
// Create the response headers list
CHK_STATUS(stackQueueCreate(&pCallInfo->pResponseHeaders));
*ppCurl = pCurl;
CleanUp:
LEAVES();
return retStatus;
}