in src/source/CurlApiCallbacks.c [10:180]
STATUS createCurlApiCallbacks(PCallbacksProvider pCallbacksProvider, PCHAR region, API_CALL_CACHE_TYPE cacheType, UINT64 endpointCachingPeriod,
PCHAR controlPlaneUrl, PCHAR certPath, PCHAR userAgentNamePostfix, PCHAR customUserAgent,
PCurlApiCallbacks* ppCurlApiCallbacks)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS, status;
PCurlApiCallbacks pCurlApiCallbacks = NULL;
CHK(pCallbacksProvider != NULL && ppCurlApiCallbacks != NULL, STATUS_NULL_ARG);
CHK(certPath == NULL || STRNLEN(certPath, MAX_PATH_LEN + 1) <= MAX_PATH_LEN, STATUS_INVALID_CERT_PATH_LENGTH);
CHK(customUserAgent == NULL || STRNLEN(customUserAgent, MAX_CUSTOM_USER_AGENT_LEN + 1) <= MAX_CUSTOM_USER_AGENT_LEN,
STATUS_MAX_CUSTOM_USER_AGENT_LEN_EXCEEDED);
CHK(userAgentNamePostfix == NULL ||
STRNLEN(userAgentNamePostfix, MAX_CUSTOM_USER_AGENT_NAME_POSTFIX_LEN + 1) <= MAX_CUSTOM_USER_AGENT_NAME_POSTFIX_LEN,
STATUS_MAX_USER_AGENT_NAME_POSTFIX_LEN_EXCEEDED);
CHK(endpointCachingPeriod <= MAX_ENDPOINT_CACHE_UPDATE_PERIOD, STATUS_INVALID_ENDPOINT_CACHING_PERIOD);
// Fix-up the endpoint TTL value
if (endpointCachingPeriod == ENDPOINT_UPDATE_PERIOD_SENTINEL_VALUE) {
endpointCachingPeriod = DEFAULT_ENDPOINT_CACHE_UPDATE_PERIOD;
}
// Allocate the entire structure
pCurlApiCallbacks = (PCurlApiCallbacks) MEMCALLOC(1, SIZEOF(CurlApiCallbacks));
CHK(pCurlApiCallbacks != NULL, STATUS_NOT_ENOUGH_MEMORY);
// Set the version, self
pCurlApiCallbacks->apiCallbacks.version = API_CALLBACKS_CURRENT_VERSION;
pCurlApiCallbacks->apiCallbacks.customData = (UINT64) pCurlApiCallbacks;
pCurlApiCallbacks->streamingRequestCount = 0;
// Endpoint period will be the same for all streams
pCurlApiCallbacks->cacheUpdatePeriod = endpointCachingPeriod;
// API call caching type
pCurlApiCallbacks->cacheType = cacheType;
// Set invalid guard locks
pCurlApiCallbacks->activeRequestsLock = INVALID_MUTEX_VALUE;
pCurlApiCallbacks->activeUploadsLock = INVALID_MUTEX_VALUE;
pCurlApiCallbacks->cachedEndpointsLock = INVALID_MUTEX_VALUE;
pCurlApiCallbacks->shutdownLock = INVALID_MUTEX_VALUE;
// Store the back pointer as we will be using the other callbacks
pCurlApiCallbacks->pCallbacksProvider = pCallbacksProvider;
// Set the callbacks
pCurlApiCallbacks->apiCallbacks.createStreamFn = createStreamCachingCurl;
pCurlApiCallbacks->apiCallbacks.describeStreamFn = describeStreamCachingCurl;
pCurlApiCallbacks->apiCallbacks.getStreamingEndpointFn = getStreamingEndpointCachingCurl;
pCurlApiCallbacks->apiCallbacks.tagResourceFn = tagResourceCachingCurl;
pCurlApiCallbacks->apiCallbacks.createDeviceFn = createDeviceCurl;
pCurlApiCallbacks->apiCallbacks.putStreamFn = putStreamCurl;
pCurlApiCallbacks->apiCallbacks.freeApiCallbacksFn = freeApiCallbacksCurl;
if (region == NULL || region[0] == '\0') {
STRCPY(pCurlApiCallbacks->region, DEFAULT_AWS_REGION);
} else {
STRNCPY(pCurlApiCallbacks->region, region, MAX_REGION_NAME_LEN);
pCurlApiCallbacks->region[MAX_REGION_NAME_LEN] = '\0';
}
status = getUserAgentString(userAgentNamePostfix, customUserAgent, MAX_USER_AGENT_LEN, pCurlApiCallbacks->userAgent);
pCurlApiCallbacks->userAgent[MAX_USER_AGENT_LEN] = '\0';
if (STATUS_FAILED(status)) {
DLOGW("Failed to generate user agent string with error 0x%08x.", status);
}
// Set the control plane URL
if (controlPlaneUrl == NULL || controlPlaneUrl[0] == '\0') {
// Create a fully qualified URI
SNPRINTF(pCurlApiCallbacks->controlPlaneUrl, MAX_URI_CHAR_LEN, "%s%s.%s%s", CONTROL_PLANE_URI_PREFIX, KINESIS_VIDEO_SERVICE_NAME,
pCurlApiCallbacks->region, CONTROL_PLANE_URI_POSTFIX);
} else {
STRNCPY(pCurlApiCallbacks->controlPlaneUrl, controlPlaneUrl, MAX_URI_CHAR_LEN);
}
// NULL terminate in case we overrun
pCurlApiCallbacks->controlPlaneUrl[MAX_URI_CHAR_LEN] = '\0';
if (certPath != NULL) {
STRNCPY(pCurlApiCallbacks->certPath, certPath, MAX_PATH_LEN);
} else {
// empty cert path
pCurlApiCallbacks->certPath[0] = '\0';
}
// Create the tracking ongoing requests
CHK_STATUS(hashTableCreateWithParams(STREAM_MAPPING_HASH_TABLE_BUCKET_COUNT, STREAM_MAPPING_HASH_TABLE_BUCKET_LENGTH,
&pCurlApiCallbacks->pActiveRequests));
CHK_STATUS(doubleListCreate(&pCurlApiCallbacks->pActiveUploads));
// Create the hash table for tracking endpoints
CHK_STATUS(hashTableCreateWithParams(STREAM_MAPPING_HASH_TABLE_BUCKET_COUNT, STREAM_MAPPING_HASH_TABLE_BUCKET_LENGTH,
&pCurlApiCallbacks->pCachedEndpoints));
CHK_STATUS(hashTableCreateWithParams(STREAM_MAPPING_HASH_TABLE_BUCKET_COUNT, STREAM_MAPPING_HASH_TABLE_BUCKET_LENGTH,
&pCurlApiCallbacks->pStreamsShuttingDown));
// Create the guard locks
pCurlApiCallbacks->activeUploadsLock = pCallbacksProvider->clientCallbacks.createMutexFn(pCallbacksProvider->clientCallbacks.customData, TRUE);
CHK(pCurlApiCallbacks->activeUploadsLock != INVALID_MUTEX_VALUE, STATUS_INVALID_OPERATION);
pCurlApiCallbacks->activeRequestsLock = pCallbacksProvider->clientCallbacks.createMutexFn(pCallbacksProvider->clientCallbacks.customData, TRUE);
CHK(pCurlApiCallbacks->activeRequestsLock != INVALID_MUTEX_VALUE, STATUS_INVALID_OPERATION);
pCurlApiCallbacks->cachedEndpointsLock = pCallbacksProvider->clientCallbacks.createMutexFn(pCallbacksProvider->clientCallbacks.customData, TRUE);
CHK(pCurlApiCallbacks->cachedEndpointsLock != INVALID_MUTEX_VALUE, STATUS_INVALID_OPERATION);
pCurlApiCallbacks->shutdownLock = pCallbacksProvider->clientCallbacks.createMutexFn(pCallbacksProvider->clientCallbacks.customData, TRUE);
CHK(pCurlApiCallbacks->shutdownLock != INVALID_MUTEX_VALUE, STATUS_INVALID_OPERATION);
#if !defined __WINDOWS_BUILD__
signal(SIGPIPE, SIG_IGN);
#endif
// Testability hooks initialization
pCurlApiCallbacks->hookCustomData = 0;
pCurlApiCallbacks->curlEasyPerformHookFn = NULL;
pCurlApiCallbacks->curlWriteCallbackHookFn = NULL;
pCurlApiCallbacks->curlReadCallbackHookFn = NULL;
// end testability hooks initialization
// Initialize the global ssl callbacks
CHK_STATUS(initializeSslCallbacks());
// CURL global initialization
CHK(0 == curl_global_init(CURL_GLOBAL_ALL), STATUS_CURL_LIBRARY_INIT_FAILED);
// Not in shutdown
ATOMIC_STORE_BOOL(&pCurlApiCallbacks->shutdown, FALSE);
// Prepare the Stream callbacks
pCurlApiCallbacks->streamCallbacks.version = STREAM_CALLBACKS_CURRENT_VERSION;
pCurlApiCallbacks->streamCallbacks.customData = (UINT64) pCurlApiCallbacks;
pCurlApiCallbacks->streamCallbacks.streamDataAvailableFn = dataAvailableCurl;
pCurlApiCallbacks->streamCallbacks.streamClosedFn = streamClosedCurl;
pCurlApiCallbacks->streamCallbacks.streamErrorReportFn = NULL;
pCurlApiCallbacks->streamCallbacks.fragmentAckReceivedFn = fragmentAckReceivedCurl;
pCurlApiCallbacks->streamCallbacks.streamShutdownFn = shutdownStreamCurl;
// Prepare the Producer callbacks
pCurlApiCallbacks->producerCallbacks.version = PRODUCER_CALLBACKS_CURRENT_VERSION;
pCurlApiCallbacks->producerCallbacks.customData = (UINT64) pCurlApiCallbacks;
pCurlApiCallbacks->producerCallbacks.clientShutdownFn = clientShutdownCurl;
// Append to the API callback chain
CHK_STATUS(addApiCallbacks((PClientCallbacks) pCallbacksProvider, (PApiCallbacks) pCurlApiCallbacks));
// Append the stream callbacks to the Stream callback chain
CHK_STATUS(addStreamCallbacks((PClientCallbacks) pCallbacksProvider, &pCurlApiCallbacks->streamCallbacks));
// Append the producer callbacks to the Producer callback chain
CHK_STATUS(addProducerCallbacks((PClientCallbacks) pCallbacksProvider, &pCurlApiCallbacks->producerCallbacks));
CleanUp:
CHK_LOG_ERR(retStatus);
if (STATUS_FAILED(retStatus)) {
freeCurlApiCallbacks(&pCurlApiCallbacks);
pCurlApiCallbacks = NULL;
}
// Set the return value if it's not NULL
if (ppCurlApiCallbacks != NULL) {
*ppCurlApiCallbacks = pCurlApiCallbacks;
}
LEAVES();
return retStatus;
}