in src/source/Signaling/Signaling.c [7:189]
STATUS createSignalingSync(PSignalingClientInfoInternal pClientInfo, PChannelInfo pChannelInfo, PSignalingClientCallbacks pCallbacks,
PAwsCredentialProvider pCredentialProvider, PSignalingClient* ppSignalingClient)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
PSignalingClient pSignalingClient = NULL;
PCHAR userLogLevelStr = NULL;
UINT32 userLogLevel;
struct lws_context_creation_info creationInfo;
const lws_retry_bo_t retryPolicy = {
.secs_since_valid_ping = SIGNALING_SERVICE_WSS_PING_PONG_INTERVAL_IN_SECONDS,
};
PStateMachineState pStateMachineState;
BOOL cacheFound = FALSE;
PSignalingFileCacheEntry pFileCacheEntry = NULL;
CHK(pClientInfo != NULL && pChannelInfo != NULL && pCallbacks != NULL && pCredentialProvider != NULL && ppSignalingClient != NULL,
STATUS_NULL_ARG);
CHK(pChannelInfo->version <= CHANNEL_INFO_CURRENT_VERSION, STATUS_SIGNALING_INVALID_CHANNEL_INFO_VERSION);
CHK(NULL != (pFileCacheEntry = (PSignalingFileCacheEntry) MEMALLOC(SIZEOF(SignalingFileCacheEntry))), STATUS_NOT_ENOUGH_MEMORY);
// Allocate enough storage
CHK(NULL != (pSignalingClient = (PSignalingClient) MEMCALLOC(1, SIZEOF(SignalingClient))), STATUS_NOT_ENOUGH_MEMORY);
// Initialize the listener and restart thread trackers
CHK_STATUS(initializeThreadTracker(&pSignalingClient->listenerTracker));
CHK_STATUS(initializeThreadTracker(&pSignalingClient->reconnecterTracker));
// Validate and store the input
CHK_STATUS(createValidateChannelInfo(pChannelInfo, &pSignalingClient->pChannelInfo));
CHK_STATUS(validateSignalingCallbacks(pSignalingClient, pCallbacks));
CHK_STATUS(validateSignalingClientInfo(pSignalingClient, pClientInfo));
pSignalingClient->version = SIGNALING_CLIENT_CURRENT_VERSION;
// Set invalid call times
pSignalingClient->describeTime = INVALID_TIMESTAMP_VALUE;
pSignalingClient->createTime = INVALID_TIMESTAMP_VALUE;
pSignalingClient->getEndpointTime = INVALID_TIMESTAMP_VALUE;
pSignalingClient->getIceConfigTime = INVALID_TIMESTAMP_VALUE;
pSignalingClient->deleteTime = INVALID_TIMESTAMP_VALUE;
pSignalingClient->connectTime = INVALID_TIMESTAMP_VALUE;
if (pSignalingClient->pChannelInfo->cachingPolicy == SIGNALING_API_CALL_CACHE_TYPE_FILE) {
// Signaling channel name can be NULL in case of pre-created channels in which case we use ARN as the name
if (STATUS_FAILED(signalingCacheLoadFromFile(pChannelInfo->pChannelName != NULL ? pChannelInfo->pChannelName : pChannelInfo->pChannelArn,
pChannelInfo->pRegion, pChannelInfo->channelRoleType, pFileCacheEntry, &cacheFound,
pSignalingClient->clientInfo.cacheFilePath))) {
DLOGW("Failed to load signaling cache from file");
} else if (cacheFound) {
STRCPY(pSignalingClient->channelDescription.channelArn, pFileCacheEntry->channelArn);
STRCPY(pSignalingClient->channelEndpointHttps, pFileCacheEntry->httpsEndpoint);
STRCPY(pSignalingClient->channelEndpointWss, pFileCacheEntry->wssEndpoint);
pSignalingClient->describeTime = pFileCacheEntry->creationTsEpochSeconds * HUNDREDS_OF_NANOS_IN_A_SECOND;
pSignalingClient->getEndpointTime = pFileCacheEntry->creationTsEpochSeconds * HUNDREDS_OF_NANOS_IN_A_SECOND;
}
}
// Attempting to get the logging level from the env var and if it fails then set it from the client info
if ((userLogLevelStr = GETENV(DEBUG_LOG_LEVEL_ENV_VAR)) != NULL && STATUS_SUCCEEDED(STRTOUI32(userLogLevelStr, NULL, 10, &userLogLevel))) {
userLogLevel = userLogLevel > LOG_LEVEL_SILENT ? LOG_LEVEL_SILENT : userLogLevel < LOG_LEVEL_VERBOSE ? LOG_LEVEL_VERBOSE : userLogLevel;
} else {
userLogLevel = pClientInfo->signalingClientInfo.loggingLevel;
}
SET_LOGGER_LOG_LEVEL(userLogLevel);
// Store the credential provider
pSignalingClient->pCredentialProvider = pCredentialProvider;
CHK_STATUS(configureRetryStrategyForSignalingStateMachine(pSignalingClient));
// Create the state machine
CHK_STATUS(createStateMachine(SIGNALING_STATE_MACHINE_STATES, SIGNALING_STATE_MACHINE_STATE_COUNT,
CUSTOM_DATA_FROM_SIGNALING_CLIENT(pSignalingClient), signalingGetCurrentTime,
CUSTOM_DATA_FROM_SIGNALING_CLIENT(pSignalingClient), &pSignalingClient->pStateMachine));
// Prepare the signaling channel protocols array
pSignalingClient->signalingProtocols[PROTOCOL_INDEX_HTTPS].name = HTTPS_SCHEME_NAME;
pSignalingClient->signalingProtocols[PROTOCOL_INDEX_HTTPS].callback = lwsHttpCallbackRoutine;
pSignalingClient->signalingProtocols[PROTOCOL_INDEX_WSS].name = WSS_SCHEME_NAME;
pSignalingClient->signalingProtocols[PROTOCOL_INDEX_WSS].callback = lwsWssCallbackRoutine;
pSignalingClient->currentWsi[PROTOCOL_INDEX_HTTPS] = NULL;
pSignalingClient->currentWsi[PROTOCOL_INDEX_WSS] = NULL;
MEMSET(&creationInfo, 0x00, SIZEOF(struct lws_context_creation_info));
creationInfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
creationInfo.port = CONTEXT_PORT_NO_LISTEN;
creationInfo.protocols = pSignalingClient->signalingProtocols;
creationInfo.timeout_secs = SIGNALING_SERVICE_API_CALL_TIMEOUT_IN_SECONDS;
creationInfo.gid = -1;
creationInfo.uid = -1;
creationInfo.client_ssl_ca_filepath = pChannelInfo->pCertPath;
creationInfo.client_ssl_cipher_list = "HIGH:!PSK:!RSP:!eNULL:!aNULL:!RC4:!MD5:!DES:!3DES:!aDH:!kDH:!DSS";
creationInfo.ka_time = SIGNALING_SERVICE_TCP_KEEPALIVE_IN_SECONDS;
creationInfo.ka_probes = SIGNALING_SERVICE_TCP_KEEPALIVE_PROBE_COUNT;
creationInfo.ka_interval = SIGNALING_SERVICE_TCP_KEEPALIVE_PROBE_INTERVAL_IN_SECONDS;
creationInfo.retry_and_idle_policy = &retryPolicy;
ATOMIC_STORE_BOOL(&pSignalingClient->clientReady, FALSE);
ATOMIC_STORE_BOOL(&pSignalingClient->shutdown, FALSE);
ATOMIC_STORE_BOOL(&pSignalingClient->connected, FALSE);
ATOMIC_STORE_BOOL(&pSignalingClient->deleting, FALSE);
ATOMIC_STORE_BOOL(&pSignalingClient->deleted, FALSE);
ATOMIC_STORE_BOOL(&pSignalingClient->serviceLockContention, FALSE);
// Add to the signal handler
// signal(SIGINT, lwsSignalHandler);
// Create the sync primitives
pSignalingClient->connectedCvar = CVAR_CREATE();
CHK(IS_VALID_CVAR_VALUE(pSignalingClient->connectedCvar), STATUS_INVALID_OPERATION);
pSignalingClient->connectedLock = MUTEX_CREATE(FALSE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->connectedLock), STATUS_INVALID_OPERATION);
pSignalingClient->sendCvar = CVAR_CREATE();
CHK(IS_VALID_CVAR_VALUE(pSignalingClient->sendCvar), STATUS_INVALID_OPERATION);
pSignalingClient->sendLock = MUTEX_CREATE(FALSE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->sendLock), STATUS_INVALID_OPERATION);
pSignalingClient->receiveCvar = CVAR_CREATE();
CHK(IS_VALID_CVAR_VALUE(pSignalingClient->receiveCvar), STATUS_INVALID_OPERATION);
pSignalingClient->receiveLock = MUTEX_CREATE(FALSE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->receiveLock), STATUS_INVALID_OPERATION);
pSignalingClient->stateLock = MUTEX_CREATE(TRUE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->stateLock), STATUS_INVALID_OPERATION);
pSignalingClient->messageQueueLock = MUTEX_CREATE(TRUE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->messageQueueLock), STATUS_INVALID_OPERATION);
pSignalingClient->lwsServiceLock = MUTEX_CREATE(TRUE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->lwsServiceLock), STATUS_INVALID_OPERATION);
pSignalingClient->lwsSerializerLock = MUTEX_CREATE(TRUE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->lwsSerializerLock), STATUS_INVALID_OPERATION);
pSignalingClient->diagnosticsLock = MUTEX_CREATE(TRUE);
CHK(IS_VALID_MUTEX_VALUE(pSignalingClient->diagnosticsLock), STATUS_INVALID_OPERATION);
// Create the ongoing message list
CHK_STATUS(stackQueueCreate(&pSignalingClient->pMessageQueue));
pSignalingClient->pLwsContext = lws_create_context(&creationInfo);
CHK(pSignalingClient->pLwsContext != NULL, STATUS_SIGNALING_LWS_CREATE_CONTEXT_FAILED);
// Initializing the diagnostics mostly is taken care of by zero-mem in MEMCALLOC
pSignalingClient->diagnostics.createTime = SIGNALING_GET_CURRENT_TIME(pSignalingClient);
CHK_STATUS(hashTableCreateWithParams(SIGNALING_CLOCKSKEW_HASH_TABLE_BUCKET_COUNT,SIGNALING_CLOCKSKEW_HASH_TABLE_BUCKET_LENGTH,
&pSignalingClient->diagnostics.pEndpointToClockSkewHashMap));
// At this point we have constructed the main object and we can assign to the returned pointer
*ppSignalingClient = pSignalingClient;
// Notify of the state change initially as the state machinery is already in the NEW state
if (pSignalingClient->signalingClientCallbacks.stateChangeFn != NULL) {
CHK_STATUS(getStateMachineCurrentState(pSignalingClient->pStateMachine, &pStateMachineState));
CHK_STATUS(pSignalingClient->signalingClientCallbacks.stateChangeFn(pSignalingClient->signalingClientCallbacks.customData,
getSignalingStateFromStateMachineState(pStateMachineState->state)));
}
// Do not force ice config state
ATOMIC_STORE_BOOL(&pSignalingClient->refreshIceConfig, FALSE);
// We do not cache token in file system, so we will always have to retrieve one after creating the client.
CHK_STATUS(signalingStateMachineIterator(pSignalingClient, pSignalingClient->diagnostics.createTime + SIGNALING_CONNECT_STATE_TIMEOUT, SIGNALING_STATE_GET_TOKEN));
CleanUp:
if (pClientInfo != NULL && pSignalingClient != NULL) {
pClientInfo->signalingClientInfo.stateMachineRetryCountReadOnly = pSignalingClient->diagnostics.stateMachineRetryCount;
}
CHK_LOG_ERR(retStatus);
if (STATUS_FAILED(retStatus)) {
freeSignaling(&pSignalingClient);
}
if (ppSignalingClient != NULL) {
*ppSignalingClient = pSignalingClient;
}
SAFE_MEMFREE(pFileCacheEntry);
LEAVES();
return retStatus;
}