Skip to content

Commit 06bffce

Browse files
kateyanuragniyatim23hassanctech
authored
Incorporating PIC state machine level retry changes into webrtc signaling state machine (#1326)
* Incorporating PIC state machine level retry changes into webrtc signaling state machine * Signaling state machine rework (#1323) * replaced recursive calls to stepSignalingStateMachine with loops * removed recursive calls to stepSignalingStateMachine * replaced stepSignalingstatemachine with signalingStateMachineIterator * removed stepUntil, continueOnReady; removed status from iterator signature; set signalingclient version; added a lock in refreshIceConfiguration * changed the declaration for i from int to UINT32 * added signaling version; removed unnecessary comment * removed redeclaration; changed value in an existing macro * Fix issue with API call failures being treated as success (#1328) * return proper error, do not reset call result value * for non retriable failures, set the terminal exit status for state in… (#1320) * for non retriable failures, set the terminal exit status for state in state machine * address comments * adjust tests set retry max to 1 * Update LwsApiCalls.c trigger travis ci * Add retry strategy to client info to avoiud changing create signaling channel API signature * Incorporating PIC state machine level retry changes into webrtc signaling state machine * Add retry strategy to client info to avoiud changing create signaling channel API signature * Adding more debug logs in the code * fix merge conflicts * PR feedback Co-authored-by: Niyati Maheshwari <niyatim23@gmail.com> Co-authored-by: Hassan Sahibzada <hsahibza@amazon.com>
1 parent 46e9249 commit 06bffce

File tree

11 files changed

+372
-64
lines changed

11 files changed

+372
-64
lines changed

CMake/Dependencies/libkvsCommonLws-CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ include(ExternalProject)
66

77
ExternalProject_Add(libkvsCommonLws-download
88
GIT_REPOSITORY https://github.com/awslabs/amazon-kinesis-video-streams-producer-c.git
9-
GIT_TAG 99c1a8cd8cec88f99c9c4ce3944b53ae341d1491
9+
GIT_TAG 9a995a5793b4024f19912be9a319993b1e16005c
1010
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/build
1111
CMAKE_ARGS
1212
-DCMAKE_INSTALL_PREFIX=${OPEN_SRC_INSTALL_PREFIX}

samples/Common.c

+30
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,29 @@ STATUS lookForSslCert(PSampleConfiguration* ppSampleConfiguration)
697697
return retStatus;
698698
}
699699

700+
STATUS setupDefaultSignalingClientRetryStrategy(PSignalingClientInfo pSignalingClientInfo)
701+
{
702+
ENTERS();
703+
STATUS retStatus = STATUS_SUCCESS;
704+
PRetryStrategy pRetryStrategy = NULL;
705+
706+
CHK(pSignalingClientInfo != NULL, STATUS_NULL_ARG);
707+
708+
pSignalingClientInfo->signalingClientRetryStrategy.retryStrategyType = KVS_RETRY_STRATEGY_EXPONENTIAL_BACKOFF_WAIT;
709+
pSignalingClientInfo->signalingClientRetryStrategy.createRetryStrategyFn = exponentialBackoffRetryStrategyCreate;
710+
pSignalingClientInfo->signalingClientRetryStrategy.freeRetryStrategyFn = exponentialBackoffRetryStrategyFree;
711+
pSignalingClientInfo->signalingClientRetryStrategy.executeRetryStrategyFn = getExponentialBackoffRetryStrategyWaitTime;
712+
713+
CHK_STATUS(pSignalingClientInfo->signalingClientRetryStrategy.createRetryStrategyFn(NULL /* use default config */, &pRetryStrategy));
714+
pSignalingClientInfo->signalingClientRetryStrategy.pRetryStrategy = pRetryStrategy;
715+
716+
pSignalingClientInfo->signalingClientCreationMaxRetryCount = MAX_CREATE_SIGNALING_CLIENT_RETRIES;
717+
718+
CleanUp:
719+
LEAVES();
720+
return retStatus;
721+
}
722+
700723
STATUS createSampleConfiguration(PCHAR channelName, SIGNALING_CHANNEL_ROLE_TYPE roleType, BOOL trickleIce, BOOL useTurn,
701724
PSampleConfiguration* ppSampleConfiguration)
702725
{
@@ -782,6 +805,8 @@ STATUS createSampleConfiguration(PCHAR channelName, SIGNALING_CHANNEL_ROLE_TYPE
782805
pSampleConfiguration->clientInfo.version = SIGNALING_CLIENT_INFO_CURRENT_VERSION;
783806
pSampleConfiguration->clientInfo.loggingLevel = logLevel;
784807
pSampleConfiguration->clientInfo.cacheFilePath = NULL; // Use the default path
808+
CHK_STATUS(setupDefaultSignalingClientRetryStrategy(&pSampleConfiguration->clientInfo));
809+
785810
pSampleConfiguration->iceCandidatePairStatsTimerId = MAX_UINT32;
786811
pSampleConfiguration->pregenerateCertTimerId = MAX_UINT32;
787812

@@ -1063,6 +1088,11 @@ STATUS freeSampleConfiguration(PSampleConfiguration* ppSampleConfiguration)
10631088
SAFE_MEMFREE(pSampleConfiguration->pVideoFrameBuffer);
10641089
SAFE_MEMFREE(pSampleConfiguration->pAudioFrameBuffer);
10651090

1091+
if (pSampleConfiguration->clientInfo.signalingClientRetryStrategy.freeRetryStrategyFn != NULL) {
1092+
CHK_STATUS(pSampleConfiguration->clientInfo.signalingClientRetryStrategy.freeRetryStrategyFn(
1093+
&(pSampleConfiguration->clientInfo.signalingClientRetryStrategy.pRetryStrategy)));
1094+
}
1095+
10661096
if (IS_VALID_CVAR_VALUE(pSampleConfiguration->cvar) && IS_VALID_MUTEX_VALUE(pSampleConfiguration->sampleConfigurationObjLock)) {
10671097
CVAR_BROADCAST(pSampleConfiguration->cvar);
10681098
MUTEX_LOCK(pSampleConfiguration->sampleConfigurationObjLock);

samples/Samples.h

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939

4040
#define SAMPLE_HASH_TABLE_BUCKET_COUNT 50
4141
#define SAMPLE_HASH_TABLE_BUCKET_LENGTH 2
42+
#define MAX_CREATE_SIGNALING_CLIENT_RETRIES 3
4243

4344
#define IOT_CORE_CREDENTIAL_ENDPOINT ((PCHAR) "AWS_IOT_CORE_CREDENTIAL_ENDPOINT")
4445
#define IOT_CORE_CERT ((PCHAR) "AWS_IOT_CORE_CERT")

src/include/com/amazonaws/kinesis/video/webrtcclient/Include.h

+15-10
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,9 @@ extern "C" {
660660
typedef UINT64 SIGNALING_CLIENT_HANDLE;
661661
typedef SIGNALING_CLIENT_HANDLE* PSIGNALING_CLIENT_HANDLE;
662662

663+
typedef KvsRetryStrategy SignalingClientRetryStrategy;
664+
typedef PKvsRetryStrategy PSignalingClientRetryStrategy;
665+
663666
/**
664667
* @brief This is a sentinel indicating an invalid handle value
665668
*/
@@ -1177,16 +1180,18 @@ typedef struct {
11771180
* @brief Populate Signaling client with client ID and application log level
11781181
*/
11791182
typedef struct {
1180-
UINT32 version; //!< Version of the structure
1181-
CHAR clientId[MAX_SIGNALING_CLIENT_ID_LEN + 1]; //!< Client id to use. Defines if the client is a producer/consumer
1182-
UINT32 loggingLevel; //!< Verbosity level for the logging. One of LOG_LEVEL_XXX
1183-
//!< values or the default verbosity will be assumed. Currently,
1184-
//!< default value is LOG_LEVEL_WARNING
1185-
PCHAR cacheFilePath; //!< File cache path override. The default
1186-
//!< path is "./.SignalingCache_vN" which might not work for
1187-
//!< devices which have read only partition where the code is
1188-
//!< located. For default value or when file caching is not
1189-
//!< being used this value can be NULL or point to an EMPTY_STRING.
1183+
UINT32 version; //!< Version of the structure
1184+
CHAR clientId[MAX_SIGNALING_CLIENT_ID_LEN + 1]; //!< Client id to use. Defines if the client is a producer/consumer
1185+
UINT32 loggingLevel; //!< Verbosity level for the logging. One of LOG_LEVEL_XXX
1186+
//!< values or the default verbosity will be assumed. Currently,
1187+
//!< default value is LOG_LEVEL_WARNING
1188+
PCHAR cacheFilePath; //!< File cache path override. The default
1189+
//!< path is "./.SignalingCache_vN" which might not work for
1190+
//!< devices which have read only partition where the code is
1191+
//!< located. For default value or when file caching is not
1192+
//!< being used this value can be NULL or point to an EMPTY_STRING.
1193+
SignalingClientRetryStrategy signalingClientRetryStrategy; //!< Retry strategy used while creating signaling client
1194+
UINT32 signalingClientCreationMaxRetryCount; //!< Maximum attempts which createSignalingClientSync API will make on failures to create signaling client
11901195
} SignalingClientInfo, *PSignalingClientInfo;
11911196

11921197
/**

src/source/Signaling/Client.c

+46-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
#define LOG_CLASS "SignalingClient"
22
#include "../Include_i.h"
33

4+
STATUS validateSignalingClientRetryStrategy(PSignalingClientInfo pClientInfo) {
5+
ENTERS();
6+
STATUS retStatus = STATUS_SUCCESS;
7+
PSignalingClientRetryStrategy pSignalingClientRetryStrategy;
8+
9+
CHK(pClientInfo != NULL, STATUS_NULL_ARG);
10+
11+
pSignalingClientRetryStrategy = &(pClientInfo->signalingClientRetryStrategy);
12+
13+
CHK(pSignalingClientRetryStrategy->retryStrategyType > KVS_RETRY_STRATEGY_DISABLED &&
14+
pSignalingClientRetryStrategy->pRetryStrategy != NULL &&
15+
pSignalingClientRetryStrategy->executeRetryStrategyFn != NULL, STATUS_NULL_ARG);
16+
17+
CHK(pClientInfo->signalingClientCreationMaxRetryCount > 0, STATUS_NOT_IMPLEMENTED);
18+
19+
CleanUp:
20+
21+
LEAVES();
22+
return retStatus;
23+
}
24+
425
STATUS createSignalingClientSync(PSignalingClientInfo pClientInfo, PChannelInfo pChannelInfo, PSignalingClientCallbacks pCallbacks,
526
PAwsCredentialProvider pCredentialProvider, PSIGNALING_CLIENT_HANDLE pSignalingHandle)
627
{
728
ENTERS();
829
STATUS retStatus = STATUS_SUCCESS;
930
PSignalingClient pSignalingClient = NULL;
31+
PSignalingClientRetryStrategy pSignalingClientRetryStrategy = NULL;
1032
SignalingClientInfoInternal signalingClientInfoInternal;
33+
UINT32 signalingClientCreationMaxRetryCount;
34+
UINT64 signalingClientCreationWaitTime;
1135

1236
DLOGV("Creating Signaling Client Sync");
1337
CHK(pSignalingHandle != NULL && pClientInfo != NULL, STATUS_NULL_ARG);
@@ -16,7 +40,28 @@ STATUS createSignalingClientSync(PSignalingClientInfo pClientInfo, PChannelInfo
1640
MEMSET(&signalingClientInfoInternal, 0x00, SIZEOF(signalingClientInfoInternal));
1741
signalingClientInfoInternal.signalingClientInfo = *pClientInfo;
1842

19-
CHK_STATUS(createSignalingSync(&signalingClientInfoInternal, pChannelInfo, pCallbacks, pCredentialProvider, &pSignalingClient));
43+
CHK_STATUS(validateSignalingClientRetryStrategy(pClientInfo));
44+
45+
signalingClientCreationMaxRetryCount = pClientInfo->signalingClientCreationMaxRetryCount;
46+
pSignalingClientRetryStrategy = &(pClientInfo->signalingClientRetryStrategy);
47+
48+
while (signalingClientCreationMaxRetryCount > 0) {
49+
// Wait before cresting signaling client to ensure the first call from a large
50+
// client fleet will be spread across the wait time window.
51+
CHK_STATUS(pSignalingClientRetryStrategy->executeRetryStrategyFn(pSignalingClientRetryStrategy->pRetryStrategy, &signalingClientCreationWaitTime));
52+
DLOGV("Attempting to back off for [%lf] milliseconds before creating signaling client. Signaling client creation retry count [%d]",
53+
signalingClientCreationWaitTime/1000.0, signalingClientCreationMaxRetryCount);
54+
THREAD_SLEEP(signalingClientCreationWaitTime);
55+
56+
retStatus = createSignalingSync(&signalingClientInfoInternal, pChannelInfo, pCallbacks, pCredentialProvider, &pSignalingClient);
57+
if (retStatus == STATUS_SUCCESS) {
58+
break;
59+
}
60+
signalingClientCreationMaxRetryCount--;
61+
}
62+
63+
DLOGV("Create signaling client returned [%" PRId64 "].", retStatus);
64+
CHK_STATUS(retStatus);
2065

2166
*pSignalingHandle = TO_SIGNALING_CLIENT_HANDLE(pSignalingClient);
2267

src/source/Signaling/Signaling.c

+52-2
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ STATUS createSignalingSync(PSignalingClientInfoInternal pClientInfo, PChannelInf
3737
CHK_STATUS(validateSignalingCallbacks(pSignalingClient, pCallbacks));
3838
CHK_STATUS(validateSignalingClientInfo(pSignalingClient, pClientInfo));
3939

40-
pSignalingClient->version = SIGNALING_CLIENT_CURRENT_VERSION;
41-
4240
// Set invalid call times
41+
pSignalingClient->version = SIGNALING_CLIENT_CURRENT_VERSION;
4342
pSignalingClient->describeTime = INVALID_TIMESTAMP_VALUE;
4443
pSignalingClient->createTime = INVALID_TIMESTAMP_VALUE;
4544
pSignalingClient->getEndpointTime = INVALID_TIMESTAMP_VALUE;
@@ -74,6 +73,9 @@ STATUS createSignalingSync(PSignalingClientInfoInternal pClientInfo, PChannelInf
7473
// Store the credential provider
7574
pSignalingClient->pCredentialProvider = pCredentialProvider;
7675

76+
// Configure retry strategy for retries on error within signaling state machine
77+
CHK_STATUS(configureRetryStrategyForSignalingStateMachine(pSignalingClient));
78+
7779
// Create the state machine
7880
CHK_STATUS(createStateMachine(SIGNALING_STATE_MACHINE_STATES, SIGNALING_STATE_MACHINE_STATE_COUNT,
7981
CUSTOM_DATA_FROM_SIGNALING_CLIENT(pSignalingClient), signalingGetCurrentTime,
@@ -205,6 +207,8 @@ STATUS freeSignaling(PSignalingClient* ppSignalingClient)
205207
MUTEX_UNLOCK(pSignalingClient->lwsServiceLock);
206208
}
207209

210+
freeClientRetryStrategy(pSignalingClient);
211+
208212
freeStateMachine(pSignalingClient->pStateMachine);
209213

210214
freeChannelInfo(&pSignalingClient->pChannelInfo);
@@ -516,6 +520,52 @@ STATUS validateSignalingClientInfo(PSignalingClient pSignalingClient, PSignaling
516520
return retStatus;
517521
}
518522

523+
STATUS configureRetryStrategyForSignalingStateMachine(PSignalingClient pSignalingClient) {
524+
ENTERS();
525+
PRetryStrategy pRetryStrategy = NULL;
526+
STATUS retStatus = STATUS_SUCCESS;
527+
KVS_RETRY_STRATEGY_TYPE defaultKvsRetryStrategyType = KVS_RETRY_STRATEGY_EXPONENTIAL_BACKOFF_WAIT;
528+
529+
CHK(pSignalingClient != NULL, STATUS_NULL_ARG);
530+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.retryStrategyType = KVS_RETRY_STRATEGY_EXPONENTIAL_BACKOFF_WAIT;
531+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.createRetryStrategyFn = exponentialBackoffRetryStrategyCreate;
532+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.freeRetryStrategyFn = exponentialBackoffRetryStrategyFree;
533+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.executeRetryStrategyFn = getExponentialBackoffRetryStrategyWaitTime;
534+
535+
CHK_STATUS(pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.createRetryStrategyFn(
536+
NULL, &pRetryStrategy));
537+
538+
if (pRetryStrategy == NULL) {
539+
DLOGD("Unable to create exponential backoff retry strategy. This should not happen.");
540+
}
541+
542+
CHK(pRetryStrategy != NULL, STATUS_INTERNAL_ERROR);
543+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.pRetryStrategy = pRetryStrategy;
544+
545+
CleanUp:
546+
547+
LEAVES();
548+
return retStatus;
549+
}
550+
551+
STATUS freeClientRetryStrategy(PSignalingClient pSignalingClient) {
552+
ENTERS();
553+
STATUS retStatus = STATUS_SUCCESS;
554+
555+
CHK(pSignalingClient != NULL &&
556+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.freeRetryStrategyFn != NULL, STATUS_SUCCESS);
557+
558+
CHK_STATUS(pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.freeRetryStrategyFn(
559+
&(pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.pRetryStrategy)));
560+
561+
pSignalingClient->clientInfo.signalingStateMachineRetryStrategy.pRetryStrategy = NULL;
562+
563+
CleanUp:
564+
565+
LEAVES();
566+
return retStatus;
567+
}
568+
519569
STATUS validateIceConfiguration(PSignalingClient pSignalingClient)
520570
{
521571
ENTERS();

src/source/Signaling/Signaling.h

+15
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ typedef struct {
107107
SignalingApiCallHookFunc connectPostHookFn;
108108
SignalingApiCallHookFunc deletePreHookFn;
109109
SignalingApiCallHookFunc deletePostHookFn;
110+
111+
// Retry strategy for signaling state machine
112+
KvsRetryStrategy signalingStateMachineRetryStrategy;
110113
} SignalingClientInfoInternal, *PSignalingClientInfoInternal;
111114

112115
/**
@@ -281,6 +284,14 @@ typedef struct {
281284
UINT64 connectTime;
282285
} SignalingClient, *PSignalingClient;
283286

287+
static const ExponentialBackoffRetryStrategyConfig DEFAULT_SIGNALING_STATE_MACHINE_EXPONENTIAL_RETRY_CONFIG = {
288+
KVS_INFINITE_EXPONENTIAL_RETRIES, /* max retry count */
289+
10000, /* max retry wait time milliseconds */
290+
300, /* retry factor (base retry wait time milliseconds) */
291+
25000, /* minimum time in milliseconds to reset retry state */
292+
300 /* jitter factor milliseconds (jitter will be unused for FULL_JITTER variant of exponential backoff algorithm) */
293+
};
294+
284295
// Public handle to and from object converters
285296
#define TO_SIGNALING_CLIENT_HANDLE(p) ((SIGNALING_CLIENT_HANDLE) (p))
286297
#define FROM_SIGNALING_CLIENT_HANDLE(h) (IS_VALID_SIGNALING_CLIENT_HANDLE(h) ? (PSignalingClient) (h) : NULL)
@@ -299,6 +310,10 @@ STATUS validateSignalingCallbacks(PSignalingClient, PSignalingClientCallbacks);
299310
STATUS validateSignalingClientInfo(PSignalingClient, PSignalingClientInfoInternal);
300311
STATUS validateIceConfiguration(PSignalingClient);
301312

313+
STATUS configureRetryStrategyForSignalingStateMachine(PSignalingClient);
314+
STATUS setupDefaultKvsRetryStrategy(PSignalingClient);
315+
STATUS freeClientRetryStrategy(PSignalingClient);
316+
302317
STATUS signalingStoreOngoingMessage(PSignalingClient, PSignalingMessage);
303318
STATUS signalingRemoveOngoingMessage(PSignalingClient, PCHAR);
304319
STATUS signalingGetOngoingMessage(PSignalingClient, PCHAR, PCHAR, PSignalingMessage*);

0 commit comments

Comments
 (0)