Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle situation where callback is invoked before hostname is populated #1829

Merged
merged 1 commit into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ extern "C" {
#define STATUS_PEERCONNECTION_CREATE_ANSWER_WITHOUT_REMOTE_DESCRIPTION STATUS_PEERCONNECTION_BASE + 0x00000001
#define STATUS_PEERCONNECTION_CODEC_INVALID STATUS_PEERCONNECTION_BASE + 0x00000002
#define STATUS_PEERCONNECTION_CODEC_MAX_EXCEEDED STATUS_PEERCONNECTION_BASE + 0x00000003
#define STATUS_PEERCONNECTION_UNSUPPORTED_HOSTNAME STATUS_PEERCONNECTION_BASE + 0x00000004
#define STATUS_PEERCONNECTION_EARLY_DNS_RESOLUTION_FAILED STATUS_PEERCONNECTION_BASE + 0x00000004
/*!@} */

/////////////////////////////////////////////////////
Expand Down
3 changes: 2 additions & 1 deletion src/source/Ice/IceUtils.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ STATUS parseIceServer(PIceServer pIceServer, PCHAR url, PCHAR username, PCHAR cr

// Adding a NULL_ARG check specifically to cover for the case where early STUN
// resolution might not be enabled
if (retStatus == STATUS_NULL_ARG || pIceServer->setIpFn == NULL) {
// Also cover the case where hostname is not resolved because the request was made too soon
if (retStatus == STATUS_NULL_ARG || retStatus == STATUS_PEERCONNECTION_EARLY_DNS_RESOLUTION_FAILED || pIceServer->setIpFn == NULL) {
// Reset the retStatus to ensure the appropriate status code is returned from
// getIpWithHostName
retStatus = STATUS_SUCCESS;
Expand Down
72 changes: 41 additions & 31 deletions src/source/PeerConnection/PeerConnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,19 +787,26 @@ STATUS onSetStunServerIp(UINT64 customData, PCHAR url, PKvsIpAddress pIpAddr)
MUTEX_LOCK(pWebRtcClientContext->stunCtxlock);
locked = TRUE;

CHK(STRCMP(url, pWebRtcClientContext->pStunIpAddrCtx->hostname) == 0, STATUS_PEERCONNECTION_UNSUPPORTED_HOSTNAME);

if (pWebRtcClientContext->pStunIpAddrCtx->isIpInitialized) {
DLOGI("Initialized successfully");
if (currentTime > (pWebRtcClientContext->pStunIpAddrCtx->startTime + pWebRtcClientContext->pStunIpAddrCtx->expirationDuration)) {
DLOGI("Expired...need to refresh STUN address");
// Reset start time
pWebRtcClientContext->pStunIpAddrCtx->startTime = 0;
CHK_ERR(getStunAddr(pWebRtcClientContext->pStunIpAddrCtx) == STATUS_SUCCESS, retStatus, "Failed to resolve after cache expiry");
}
MEMCPY(pIpAddr, &pWebRtcClientContext->pStunIpAddrCtx->kvsIpAddr, SIZEOF(pWebRtcClientContext->pStunIpAddrCtx->kvsIpAddr));
// This covers a situation where say we receive a URL that is not the default STUN or the hostname is not populated
// pWebRtcClientContext->pStunIpAddrCtx->status needs to be set to ensure we do not go ahead with resolution on thread
// in case we receive the request early on
if (STRCMP(url, pWebRtcClientContext->pStunIpAddrCtx->hostname) != 0) {
retStatus = STATUS_PEERCONNECTION_EARLY_DNS_RESOLUTION_FAILED;
// This is to ensure we do not go ahead with STUN resolution if this call is already made
pWebRtcClientContext->pStunIpAddrCtx->status = STATUS_PEERCONNECTION_EARLY_DNS_RESOLUTION_FAILED;
} else {
DLOGE("Initialization failed");
if (pWebRtcClientContext->pStunIpAddrCtx->isIpInitialized) {
DLOGI("Initialized successfully");
if (currentTime > (pWebRtcClientContext->pStunIpAddrCtx->startTime + pWebRtcClientContext->pStunIpAddrCtx->expirationDuration)) {
DLOGI("Expired...need to refresh STUN address");
// Reset start time
pWebRtcClientContext->pStunIpAddrCtx->startTime = 0;
CHK_ERR(getStunAddr(pWebRtcClientContext->pStunIpAddrCtx) == STATUS_SUCCESS, retStatus, "Failed to resolve after cache expiry");
}
MEMCPY(pIpAddr, &pWebRtcClientContext->pStunIpAddrCtx->kvsIpAddr, SIZEOF(pWebRtcClientContext->pStunIpAddrCtx->kvsIpAddr));
} else {
DLOGE("Initialization failed");
}
}
CleanUp:
if (locked) {
Expand All @@ -822,30 +829,33 @@ PVOID resolveStunIceServerIp(PVOID args)
if (ATOMIC_LOAD_BOOL(&pWebRtcClientContext->isContextInitialized)) {
MUTEX_LOCK(pWebRtcClientContext->stunCtxlock);
locked = TRUE;

if (pWebRtcClientContext->pStunIpAddrCtx == NULL) {
DLOGE("Failed to resolve STUN IP address because webrtc client instance was not created");
} else {
if ((pRegion = GETENV(DEFAULT_REGION_ENV_VAR)) == NULL) {
pRegion = DEFAULT_AWS_REGION;
}

pHostnamePostfix = KINESIS_VIDEO_STUN_URL_POSTFIX;
// If region is in CN, add CN region uri postfix
if (STRSTR(pRegion, "cn-")) {
pHostnamePostfix = KINESIS_VIDEO_STUN_URL_POSTFIX_CN;
}

SNPRINTF(pWebRtcClientContext->pStunIpAddrCtx->hostname, SIZEOF(pWebRtcClientContext->pStunIpAddrCtx->hostname),
KINESIS_VIDEO_STUN_URL_WITHOUT_PORT, pRegion, pHostnamePostfix);
if (getStunAddr(pWebRtcClientContext->pStunIpAddrCtx) == STATUS_SUCCESS) {
getIpAddrStr(&pWebRtcClientContext->pStunIpAddrCtx->kvsIpAddr, addressResolved, ARRAY_SIZE(addressResolved));
DLOGI("ICE Server address for %s with getaddrinfo: %s", pWebRtcClientContext->pStunIpAddrCtx->hostname, addressResolved);
pWebRtcClientContext->pStunIpAddrCtx->isIpInitialized = TRUE;
if (pWebRtcClientContext->pStunIpAddrCtx->status != STATUS_PEERCONNECTION_EARLY_DNS_RESOLUTION_FAILED) {
if ((pRegion = GETENV(DEFAULT_REGION_ENV_VAR)) == NULL) {
pRegion = DEFAULT_AWS_REGION;
}

pHostnamePostfix = KINESIS_VIDEO_STUN_URL_POSTFIX;
// If region is in CN, add CN region uri postfix
if (STRSTR(pRegion, "cn-")) {
pHostnamePostfix = KINESIS_VIDEO_STUN_URL_POSTFIX_CN;
}

SNPRINTF(pWebRtcClientContext->pStunIpAddrCtx->hostname, SIZEOF(pWebRtcClientContext->pStunIpAddrCtx->hostname),
KINESIS_VIDEO_STUN_URL_WITHOUT_PORT, pRegion, pHostnamePostfix);
if (getStunAddr(pWebRtcClientContext->pStunIpAddrCtx) == STATUS_SUCCESS) {
getIpAddrStr(&pWebRtcClientContext->pStunIpAddrCtx->kvsIpAddr, addressResolved, ARRAY_SIZE(addressResolved));
DLOGI("ICE Server address for %s with getaddrinfo: %s", pWebRtcClientContext->pStunIpAddrCtx->hostname, addressResolved);
pWebRtcClientContext->pStunIpAddrCtx->isIpInitialized = TRUE;
} else {
DLOGE("Failed to resolve %s", pWebRtcClientContext->pStunIpAddrCtx->hostname);
}
pWebRtcClientContext->pStunIpAddrCtx->startTime = GETTIME();
} else {
DLOGE("Failed to resolve %s", pWebRtcClientContext->pStunIpAddrCtx->hostname);
DLOGW("Request already received to get the URL before resolution could even start...allowing higher layers to handle resolution");
}
pWebRtcClientContext->pStunIpAddrCtx->startTime = GETTIME();
}
if (locked) {
MUTEX_UNLOCK(pWebRtcClientContext->stunCtxlock);
Expand Down
11 changes: 8 additions & 3 deletions tst/MetricsApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ TEST_F(MetricsApiTest, webRtcGetMetrics)

MEMSET(&configuration, 0x00, SIZEOF(RtcConfiguration));

EXPECT_EQ(STATUS_SUCCESS, createPeerConnection(&configuration, &pRtcPeerConnection));
ASSERT_EQ(STATUS_SUCCESS, createPeerConnection(&configuration, &pRtcPeerConnection));

EXPECT_EQ(STATUS_NULL_ARG, rtcPeerConnectionGetMetrics(pRtcPeerConnection, NULL, NULL));

Expand Down Expand Up @@ -57,7 +57,7 @@ TEST_F(MetricsApiTest, webRtcIceServerGetMetrics)
STRNCPY(configuration.iceServers[1].credential, (PCHAR) "username", MAX_ICE_CONFIG_CREDENTIAL_LEN);
STRNCPY(configuration.iceServers[1].username, (PCHAR) "password", MAX_ICE_CONFIG_USER_NAME_LEN);

EXPECT_EQ(STATUS_SUCCESS, createPeerConnection(&configuration, &pRtcPeerConnection));
ASSERT_EQ(STATUS_SUCCESS, createPeerConnection(&configuration, &pRtcPeerConnection));

EXPECT_EQ(STATUS_ICE_SERVER_INDEX_INVALID, rtcPeerConnectionGetMetrics(pRtcPeerConnection, NULL, &rtcIceMetrics));

Expand Down Expand Up @@ -90,10 +90,15 @@ TEST_F(MetricsApiTest, webRtcIceCandidateGetMetrics)
STRNCPY(configuration.iceServers[0].credential, (PCHAR) "", MAX_ICE_CONFIG_CREDENTIAL_LEN);
STRNCPY(configuration.iceServers[0].username, (PCHAR) "", MAX_ICE_CONFIG_USER_NAME_LEN);

EXPECT_EQ(STATUS_SUCCESS, createPeerConnection(&configuration, &pRtcPeerConnection));
ASSERT_EQ(STATUS_SUCCESS, createPeerConnection(&configuration, &pRtcPeerConnection));

pIceAgent = ((PKvsPeerConnection) pRtcPeerConnection)->pIceAgent;

if(pIceAgent == NULL) {
DLOGI("ICE Agent null");
} else {
DLOGI("ICE agent not null");
}
IceCandidate localCandidate;
IceCandidate remoteCandidate;
IceCandidatePair iceCandidatePair;
Expand Down