Skip to content

Commit d764c46

Browse files
committed
Viewer peer can have either IPv4-only or Dual-Stack (using Ipv6) STUN servers to make successful connection not that C master does both v4 & v6
1 parent da2b12b commit d764c46

File tree

13 files changed

+153
-76
lines changed

13 files changed

+153
-76
lines changed

CMake/Dependencies/libwebsockets-CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ ExternalProject_Add(project_libwebsockets
6464
-DLWS_EXT_PTHREAD_LIBRARIES=${LWS_EXT_PTHREAD_LIBRARIES}
6565
-DLWS_OPENSSL_INCLUDE_DIRS=${LWS_OPENSSL_INCLUDE_DIRS}
6666
-DLWS_OPENSSL_LIBRARIES=${LWS_OPENSSL_LIBRARIES}
67+
-DLWS_IPV6=1
6768
BUILD_ALWAYS TRUE
6869
TEST_COMMAND ""
6970
)

samples/Common.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,10 @@ STATUS initializePeerConnection(PSampleConfiguration pSampleConfiguration, PRtcP
375375
if (STRSTR(pSampleConfiguration->channelInfo.pRegion, "cn-")) {
376376
pKinesisVideoStunUrlPostFix = KINESIS_VIDEO_STUN_URL_POSTFIX_CN;
377377
}
378-
SNPRINTF(configuration.iceServers[0].urls, MAX_ICE_CONFIG_URI_LEN, KINESIS_VIDEO_STUN_URL, pSampleConfiguration->channelInfo.pRegion,
379-
pKinesisVideoStunUrlPostFix);
378+
// SNPRINTF(configuration.iceServers[0].urls, MAX_ICE_CONFIG_URI_LEN, KINESIS_VIDEO_STUN_URL, pSampleConfiguration->channelInfo.pRegion,
379+
// pKinesisVideoStunUrlPostFix);
380+
SNPRINTF(configuration.iceServers[0].urls, MAX_ICE_CONFIG_URI_LEN, "stun:stun.l.google.com:19302");
381+
DLOGI("STUN server URL: %s", configuration.iceServers[0].urls);
380382

381383
if (pSampleConfiguration->useTurn) {
382384
// Set the URIs from the configuration
@@ -507,7 +509,7 @@ STATUS createSampleStreamingSession(PSampleConfiguration pSampleConfiguration, P
507509

508510
// Flag to enable/disable SDK calculations of selected ice server, local, remote and candidate pair stats.
509511
// Note: enableIceStats only has an effect if compiler flag ENABLE_STATS_CALCULATION_CONTROL is defined.
510-
pSampleConfiguration->enableIceStats = FALSE;
512+
pSampleConfiguration->enableIceStats = TRUE;
511513

512514
CHK_STATUS(initializePeerConnection(pSampleConfiguration, &pSampleStreamingSession->pPeerConnection));
513515
CHK_STATUS(peerConnectionOnIceCandidate(pSampleStreamingSession->pPeerConnection, (UINT64) pSampleStreamingSession, onIceCandidateHandler));
@@ -887,7 +889,7 @@ STATUS createSampleConfiguration(PCHAR channelName, SIGNALING_CHANNEL_ROLE_TYPE
887889
pSampleConfiguration->channelInfo.pTags = NULL;
888890
pSampleConfiguration->channelInfo.channelType = SIGNALING_CHANNEL_TYPE_SINGLE_MASTER;
889891
pSampleConfiguration->channelInfo.channelRoleType = roleType;
890-
pSampleConfiguration->channelInfo.cachingPolicy = SIGNALING_API_CALL_CACHE_TYPE_FILE;
892+
pSampleConfiguration->channelInfo.cachingPolicy = SIGNALING_API_CALL_CACHE_TYPE_NONE;
891893
pSampleConfiguration->channelInfo.cachingPeriod = SIGNALING_API_CALL_CACHE_TTL_SENTINEL_VALUE;
892894
pSampleConfiguration->channelInfo.asyncIceServerConfig = TRUE; // has no effect
893895
pSampleConfiguration->channelInfo.retry = TRUE;

src/source/Ice/IceAgent.c

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ STATUS createIceAgent(PCHAR username, PCHAR password, PIceAgentCallbacks pIceAge
116116
if (doStatCalcs) {
117117
CHK(NULL != (pIceAgent->pRtcIceServerDiagnostics[i] = (PRtcIceServerDiagnostics) MEMCALLOC(1, SIZEOF(RtcIceServerDiagnostics))),
118118
STATUS_NOT_ENOUGH_MEMORY);
119-
pIceAgent->pRtcIceServerDiagnostics[i]->port = (INT32) getInt16(pIceAgent->iceServers[i].ipAddress.port);
119+
pIceAgent->pRtcIceServerDiagnostics[i]->port = (INT32) getInt16(pIceAgent->iceServers[i].ipAddresses.ipv4Address.port);
120120
switch (pIceAgent->iceServers[pIceAgent->iceServersCount].transport) {
121121
case KVS_SOCKET_PROTOCOL_UDP:
122122
STRCPY(pIceAgent->pRtcIceServerDiagnostics[i]->protocol, ICE_TRANSPORT_TYPE_UDP);
@@ -639,8 +639,9 @@ STATUS iceAgentStartGathering(PIceAgent pIceAgent)
639639
"Srflx candidates setup time");
640640
}
641641

642-
PROFILE_CALL_WITH_T_OBJ(CHK_STATUS(iceAgentInitRelayCandidates(pIceAgent)), pIceAgent->iceAgentProfileDiagnostics.relayCandidateSetUpTime,
643-
"Relay candidates setup time");
642+
// Disable relay candidate gathering for STUN testing.
643+
// PROFILE_CALL_WITH_T_OBJ(CHK_STATUS(iceAgentInitRelayCandidates(pIceAgent)), pIceAgent->iceAgentProfileDiagnostics.relayCandidateSetUpTime,
644+
// "Relay candidates setup time");
644645

645646
// start listening for incoming data
646647
CHK_STATUS(connectionListenerStart(pIceAgent->pConnectionListener));
@@ -1105,6 +1106,11 @@ STATUS createIceCandidatePairs(PIceAgent pIceAgent, PIceCandidate pIceCandidate,
11051106
pCurrentIceCandidate = (PIceCandidate) data;
11061107
pCurNode = pCurNode->pNext;
11071108

1109+
// Skip forming pairs with local host candidates for STUN testing.
1110+
if (isRemoteCandidate && pCurrentIceCandidate->iceCandidateType == ICE_CANDIDATE_TYPE_HOST) {
1111+
continue;
1112+
}
1113+
11081114
// https://tools.ietf.org/html/rfc8445#section-6.1.2.2
11091115
// pair local and remote candidates with the same family
11101116
if (pCurrentIceCandidate->state == ICE_CANDIDATE_STATE_VALID && pCurrentIceCandidate->ipAddress.family == pIceCandidate->ipAddress.family) {
@@ -1458,14 +1464,32 @@ STATUS iceAgentSendSrflxCandidateRequest(PIceAgent pIceAgent)
14581464
switch (pCandidate->iceCandidateType) {
14591465
case ICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
14601466
pIceServer = &(pIceAgent->iceServers[pCandidate->iceServerIndex]);
1461-
if (pIceServer->ipAddress.family == pCandidate->ipAddress.family) {
1467+
if (pIceServer->ipAddresses.ipv4Address.family == pCandidate->ipAddress.family) {
14621468
// update transactionId
14631469
CHK_STATUS(
14641470
iceUtilsGenerateTransactionId(pBindingRequest->header.transactionId, ARRAY_SIZE(pBindingRequest->header.transactionId)));
14651471

14661472
transactionIdStoreInsert(pIceAgent->pStunBindingRequestTransactionIdStore, pBindingRequest->header.transactionId);
14671473
checkSum = COMPUTE_CRC32(pBindingRequest->header.transactionId, ARRAY_SIZE(pBindingRequest->header.transactionId));
1468-
CHK_STATUS(iceAgentSendStunPacket(pBindingRequest, NULL, 0, pIceAgent, pCandidate, &pIceServer->ipAddress));
1474+
1475+
DLOGD("[TEST] Sending STUN binding request to IPv4 STUN server: %u:%u", pIceServer->ipAddresses.ipv4Address.address, pIceServer->ipAddresses.ipv4Address.port);
1476+
1477+
CHK_STATUS(iceAgentSendStunPacket(pBindingRequest, NULL, 0, pIceAgent, pCandidate, &pIceServer->ipAddresses.ipv4Address));
1478+
if (pIceAgent->pRtcIceServerDiagnostics[pCandidate->iceServerIndex] != NULL) {
1479+
pIceAgent->pRtcIceServerDiagnostics[pCandidate->iceServerIndex]->totalRequestsSent++;
1480+
CHK_STATUS(hashTableUpsert(pIceAgent->requestTimestampDiagnostics, checkSum, GETTIME()));
1481+
}
1482+
} else if (pIceServer->ipAddresses.ipv6Address.family == pCandidate->ipAddress.family) {
1483+
// update transactionId
1484+
CHK_STATUS(
1485+
iceUtilsGenerateTransactionId(pBindingRequest->header.transactionId, ARRAY_SIZE(pBindingRequest->header.transactionId)));
1486+
1487+
transactionIdStoreInsert(pIceAgent->pStunBindingRequestTransactionIdStore, pBindingRequest->header.transactionId);
1488+
checkSum = COMPUTE_CRC32(pBindingRequest->header.transactionId, ARRAY_SIZE(pBindingRequest->header.transactionId));
1489+
1490+
DLOGD("[TEST] Sending STUN binding request to IPv6 STUN server: %u:%u", pIceServer->ipAddresses.ipv6Address.address, pIceServer->ipAddresses.ipv6Address.port);
1491+
1492+
CHK_STATUS(iceAgentSendStunPacket(pBindingRequest, NULL, 0, pIceAgent, pCandidate, &pIceServer->ipAddresses.ipv6Address));
14691493
if (pIceAgent->pRtcIceServerDiagnostics[pCandidate->iceServerIndex] != NULL) {
14701494
pIceAgent->pRtcIceServerDiagnostics[pCandidate->iceServerIndex]->totalRequestsSent++;
14711495
CHK_STATUS(hashTableUpsert(pIceAgent->requestTimestampDiagnostics, checkSum, GETTIME()));
@@ -1762,7 +1786,7 @@ STATUS iceAgentInitSrflxCandidate(PIceAgent pIceAgent)
17621786
if (pCandidate->iceCandidateType == ICE_CANDIDATE_TYPE_HOST) {
17631787
for (j = 0; j < pIceAgent->iceServersCount; j++) {
17641788
pIceServer = &pIceAgent->iceServers[j];
1765-
if (!pIceServer->isTurn && pIceServer->ipAddress.family == pCandidate->ipAddress.family) {
1789+
if (!pIceServer->isTurn && (pIceServer->ipAddresses.ipv4Address.family == pCandidate->ipAddress.family || pIceServer->ipAddresses.ipv6Address.family == pCandidate->ipAddress.family)) {
17661790
CHK((pNewCandidate = (PIceCandidate) MEMCALLOC(1, SIZEOF(IceCandidate))) != NULL, STATUS_NOT_ENOUGH_MEMORY);
17671791
generateJSONSafeString(pNewCandidate->id, ARRAY_SIZE(pNewCandidate->id));
17681792
pNewCandidate->isRemote = FALSE;
@@ -1794,18 +1818,19 @@ STATUS iceAgentInitSrflxCandidate(PIceAgent pIceAgent)
17941818
pCandidate = srflxCandidates[j];
17951819
// TODO: IPv6 STUN is not supported at the moment. Remove this check if the support is added in the future
17961820
if (IS_IPV4_ADDR(&(pCandidate->ipAddress))) {
1797-
// open up a new socket at host candidate's ip address for server reflex candidate.
1798-
// the new port will be stored in pNewCandidate->ipAddress.port. And the Ip address will later be updated
1799-
// with the correct ip address once the STUN response is received.
1800-
CHK_STATUS(createSocketConnection(pCandidate->ipAddress.family, KVS_SOCKET_PROTOCOL_UDP, &pCandidate->ipAddress, NULL, (UINT64) pIceAgent,
1801-
incomingDataHandler, pIceAgent->kvsRtcConfiguration.sendBufSize, &pCandidate->pSocketConnection));
1802-
ATOMIC_STORE_BOOL(&pCandidate->pSocketConnection->receiveData, TRUE);
1803-
// connectionListener will free the pSocketConnection at the end.
1804-
CHK_STATUS(connectionListenerAddConnection(pIceAgent->pConnectionListener, pCandidate->pSocketConnection));
1805-
1821+
DLOGW("[TEST] IPv4 STUN candidate detected ....");
18061822
} else {
1807-
DLOGW("IPv6 candidate detected, ignoring....");
1823+
DLOGW("[TEST] IPv6 STUN candidate detected ....");
18081824
}
1825+
1826+
// open up a new socket at host candidate's ip address for server reflex candidate.
1827+
// the new port will be stored in pNewCandidate->ipAddress.port. And the Ip address will later be updated
1828+
// with the correct ip address once the STUN response is received.
1829+
CHK_STATUS(createSocketConnection(pCandidate->ipAddress.family, KVS_SOCKET_PROTOCOL_UDP, &pCandidate->ipAddress, NULL, (UINT64) pIceAgent,
1830+
incomingDataHandler, pIceAgent->kvsRtcConfiguration.sendBufSize, &pCandidate->pSocketConnection));
1831+
ATOMIC_STORE_BOOL(&pCandidate->pSocketConnection->receiveData, TRUE);
1832+
// connectionListener will free the pSocketConnection at the end.
1833+
CHK_STATUS(connectionListenerAddConnection(pIceAgent->pConnectionListener, pCandidate->pSocketConnection));
18091834
}
18101835

18111836
CleanUp:
@@ -1898,7 +1923,7 @@ STATUS iceAgentInitRelayCandidate(PIceAgent pIceAgent, UINT32 iceServerIndex, KV
18981923
// open up a new socket without binding to any host address. The candidate Ip address will later be updated
18991924
// with the correct relay ip address once the Allocation success response is received. Relay candidate's socket is managed
19001925
// by TurnConnection struct.
1901-
CHK_STATUS(createSocketConnection(KVS_IP_FAMILY_TYPE_IPV4, protocol, NULL, &pIceAgent->iceServers[iceServerIndex].ipAddress,
1926+
CHK_STATUS(createSocketConnection(KVS_IP_FAMILY_TYPE_IPV4, protocol, NULL, &pIceAgent->iceServers[iceServerIndex].ipAddresses.ipv4Address,
19021927
(UINT64) pNewCandidate, incomingRelayedDataHandler, pIceAgent->kvsRtcConfiguration.sendBufSize,
19031928
&pNewCandidate->pSocketConnection));
19041929
// connectionListener will free the pSocketConnection at the end.

src/source/Ice/IceUtils.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,25 @@ STATUS iceUtilsSendStunPacket(PStunPacket pStunPacket, PBYTE password, UINT32 pa
168168
UINT32 stunPacketSize = STUN_PACKET_ALLOCATION_SIZE;
169169
BYTE stunPacketBuffer[STUN_PACKET_ALLOCATION_SIZE];
170170

171+
CHAR ipAddrStr[KVS_IP_ADDRESS_STRING_BUFFER_LEN];
172+
173+
getIpAddrStr(pDest, ipAddrStr, ARRAY_SIZE(ipAddrStr));
174+
171175
CHK_STATUS(iceUtilsPackageStunPacket(pStunPacket, password, passwordLen, stunPacketBuffer, &stunPacketSize));
172176
CHK(pDest != NULL, STATUS_NULL_ARG);
173177
switch (pStunPacket->header.stunMessageType) {
174178
case STUN_PACKET_TYPE_BINDING_REQUEST:
175-
DLOGD("Sending BINDING_REQUEST to ip:%u.%u.%u.%u, port:%u", pDest->address[0], pDest->address[1], pDest->address[2], pDest->address[3],
176-
(UINT16) getInt16(pDest->port));
179+
// Need to format properly for IPv6.
180+
// DLOGD("Sending BINDING_REQUEST to ip:%u.%u.%u.%u, port:%u", pDest->address[0], pDest->address[1], pDest->address[2], pDest->address[3],
181+
// (UINT16) getInt16(pDest->port));
182+
DLOGD("Sending BINDING_REQUEST to ip:%s, port:%u",ipAddrStr,(UINT16) getInt16(pDest->port));
183+
177184
break;
178185
case STUN_PACKET_TYPE_BINDING_RESPONSE_SUCCESS:
179-
DLOGD("Sending BINDING_RESPONSE_SUCCESS to ip:%u.%u.%u.%u, port:%u", pDest->address[0], pDest->address[1], pDest->address[2],
180-
pDest->address[3], (UINT16) getInt16(pDest->port));
186+
// DLOGD("Sending BINDING_RESPONSE_SUCCESS to ip:%u.%u.%u.%u, port:%u", pDest->address[0], pDest->address[1], pDest->address[2],
187+
// pDest->address[3], (UINT16) getInt16(pDest->port));
188+
DLOGD("Sending BINDING_RESPONSE_SUCCESS to ip:%s, port:%u",ipAddrStr,(UINT16) getInt16(pDest->port));
189+
181190
break;
182191
default:
183192
break;
@@ -222,6 +231,7 @@ STATUS parseIceServer(PIceServer pIceServer, PCHAR url, PCHAR username, PCHAR cr
222231
PCHAR separator = NULL, urlNoPrefix = NULL, paramStart = NULL;
223232
UINT32 port = ICE_STUN_DEFAULT_PORT;
224233
CHAR addressResolved[KVS_IP_ADDRESS_STRING_BUFFER_LEN + 1] = {'\0'};
234+
CHAR addressResolved2[KVS_IP_ADDRESS_STRING_BUFFER_LEN + 1] = {'\0'};
225235

226236
// username and credential is only mandatory for turn server
227237
CHK(url != NULL && pIceServer != NULL, STATUS_NULL_ARG);
@@ -264,7 +274,7 @@ STATUS parseIceServer(PIceServer pIceServer, PCHAR url, PCHAR username, PCHAR cr
264274
}
265275

266276
if (pIceServer->setIpFn != NULL) {
267-
retStatus = pIceServer->setIpFn(0, pIceServer->url, &pIceServer->ipAddress);
277+
retStatus = pIceServer->setIpFn(0, pIceServer->url, &pIceServer->ipAddresses);
268278
}
269279

270280
// Adding a NULL_ARG check specifically to cover for the case where early STUN
@@ -274,12 +284,18 @@ STATUS parseIceServer(PIceServer pIceServer, PCHAR url, PCHAR username, PCHAR cr
274284
// Reset the retStatus to ensure the appropriate status code is returned from
275285
// getIpWithHostName
276286
retStatus = STATUS_SUCCESS;
277-
CHK_STATUS(getIpWithHostName(pIceServer->url, &pIceServer->ipAddress));
287+
CHK_STATUS(getIpWithHostName(pIceServer->url, &pIceServer->ipAddresses));
278288
}
279289

280-
pIceServer->ipAddress.port = (UINT16) getInt16((INT16) port);
281-
getIpAddrStr(&pIceServer->ipAddress, addressResolved, ARRAY_SIZE(addressResolved));
282-
DLOGP("ICE Server address for %s: %s", pIceServer->url, addressResolved);
290+
DLOGD("Setting port to %u", port);
291+
pIceServer->ipAddresses.ipv4Address.port = (UINT16) getInt16((INT16) port);
292+
getIpAddrStr(&pIceServer->ipAddresses.ipv4Address, addressResolved, ARRAY_SIZE(addressResolved));
293+
DLOGP("ICE Server IPv4 address for %s: %s", pIceServer->url, addressResolved);
294+
295+
pIceServer->ipAddresses.ipv6Address.port = (UINT16) getInt16((INT16) port);
296+
getIpAddrStr(&pIceServer->ipAddresses.ipv6Address, addressResolved2, ARRAY_SIZE(addressResolved));
297+
DLOGP("ICE Server IPv6 address for %s: %s", pIceServer->url, addressResolved2);
298+
283299

284300
CleanUp:
285301

src/source/Ice/IceUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ typedef struct {
5454
BOOL isTurn;
5555
BOOL isSecure;
5656
CHAR url[MAX_ICE_CONFIG_URI_LEN + 1];
57-
KvsIpAddress ipAddress;
57+
DualKvsIpAddresses ipAddresses;
5858
CHAR username[MAX_ICE_CONFIG_USER_NAME_LEN + 1];
5959
CHAR credential[MAX_ICE_CONFIG_CREDENTIAL_LEN + 1];
6060
KVS_SOCKET_PROTOCOL transport;

0 commit comments

Comments
 (0)