Skip to content

Commit e38951f

Browse files
committed
check socket status before adding to select() list. When TurnConnection goes through failed state, go to cleanup state to cleanup the socket then back to failed state.
1 parent 1572667 commit e38951f

File tree

3 files changed

+111
-10
lines changed

3 files changed

+111
-10
lines changed

Diff for: src/source/Ice/ConnectionListener.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,7 @@ STATUS connectionListenerRemoveConnection(PConnectionListener pConnectionListene
136136
while (!hasConnection && pCurNode != NULL) {
137137
pCurrSocketConnection = (PSocketConnection) pCurNode->data;
138138
pCurNode = pCurNode->pNext;
139-
if (pCurrSocketConnection == pSocketConnection) {
140-
hasConnection = TRUE;
141-
}
139+
hasConnection = pCurrSocketConnection == pSocketConnection;
142140
}
143141

144142
/* If connection is not found then return early */
@@ -302,8 +300,12 @@ PVOID connectionListenerReceiveDataRoutine(PVOID arg)
302300

303301
for (i = 0; i < socketCount; ++i) {
304302
pSocketConnection = socketList[i];
305-
FD_SET(pSocketConnection->localSocket, &rfds);
306-
nfds = MAX(nfds, pSocketConnection->localSocket);
303+
if (socketConnectionIsClosed(pSocketConnection)) {
304+
updateSocketList = TRUE;
305+
} else {
306+
FD_SET(pSocketConnection->localSocket, &rfds);
307+
nfds = MAX(nfds, pSocketConnection->localSocket);
308+
}
307309
}
308310

309311
nfds++;

Diff for: src/source/Ice/TurnConnection.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ STATUS turnConnectionHandleStun(PTurnConnection pTurnConnection, PBYTE pBuffer,
218218

219219
switch (stunPacketType) {
220220
case STUN_PACKET_TYPE_ALLOCATE_SUCCESS_RESPONSE:
221-
/* If shutdown has been initiated, ignore the alloaction response */
221+
/* If shutdown has been initiated, ignore the allocation response */
222222
CHK(!ATOMIC_LOAD(&pTurnConnection->stopTurnConnection), retStatus);
223223
CHK_STATUS(deserializeStunPacket(pBuffer, bufferLen, pTurnConnection->longTermKey, KVS_MD5_DIGEST_LENGTH, &pStunPacket));
224224
CHK_STATUS(getStunAttribute(pStunPacket, STUN_ATTRIBUTE_TYPE_XOR_RELAYED_ADDRESS, &pStunAttr));
@@ -1058,7 +1058,7 @@ STATUS turnConnectionStepState(PTurnConnection pTurnConnection)
10581058

10591059
CHK_STATUS(turnConnectionFreePreAllocatedPackets(pTurnConnection));
10601060
CHK_STATUS(socketConnectionClosed(pTurnConnection->pControlChannel));
1061-
pTurnConnection->state = TURN_STATE_NEW;
1061+
pTurnConnection->state = STATUS_SUCCEEDED(pTurnConnection->errorStatus) ? TURN_STATE_NEW : TURN_STATE_FAILED;
10621062
ATOMIC_STORE_BOOL(&pTurnConnection->shutdownComplete, TRUE);
10631063
}
10641064

@@ -1068,6 +1068,11 @@ STATUS turnConnectionStepState(PTurnConnection pTurnConnection)
10681068
DLOGW("TurnConnection in TURN_STATE_FAILED due to 0x%08x. Aborting TurnConnection", pTurnConnection->errorStatus);
10691069
/* Since we are aborting, not gonna do cleanup */
10701070
ATOMIC_STORE_BOOL(&pTurnConnection->hasAllocation, FALSE);
1071+
/* If we haven't done cleanup, go to cleanup state which will do the cleanup then go to failed state again. */
1072+
if (!ATOMIC_LOAD_BOOL(&pTurnConnection->shutdownComplete)) {
1073+
pTurnConnection->state = TURN_STATE_CLEAN_UP;
1074+
pTurnConnection->stateTimeoutTime = currentTime + DEFAULT_TURN_CLEAN_UP_TIMEOUT;
1075+
}
10711076

10721077
break;
10731078

@@ -1289,7 +1294,7 @@ STATUS turnConnectionTimerCallback(UINT32 timerId, UINT64 currentTime, UINT64 cu
12891294
break;
12901295

12911296
case TURN_STATE_FAILED:
1292-
stopScheduling = TRUE;
1297+
stopScheduling = ATOMIC_LOAD_BOOL(&pTurnConnection->shutdownComplete);
12931298
break;
12941299

12951300
default:

Diff for: tst/TurnConnectionFunctionalityTest.cpp

+96-2
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ TEST_F(TurnConnectionFunctionalityTest, turnConnectionShutdownWithAllocationRemo
294294
BOOL doneAllocate = FALSE;
295295
UINT64 shutdownTimeout;
296296
UINT64 doneAllocateTimeout = GETTIME() + 10 * HUNDREDS_OF_NANOS_IN_A_SECOND;
297-
PSocketConnection pTurnSocketConnection = NULL;
297+
PSocketConnection pTurnSocketConnection = NULL, pCurrSocketConnection = NULL;
298+
PDoubleListNode pCurNode = NULL;
299+
BOOL connectionRemovedFromListener = TRUE;
298300

299301
initializeTestTurnConnection();
300302
pTurnSocketConnection = pTurnConnection->pControlChannel;
@@ -326,6 +328,20 @@ TEST_F(TurnConnectionFunctionalityTest, turnConnectionShutdownWithAllocationRemo
326328
EXPECT_TRUE(ATOMIC_LOAD_BOOL(&pTurnSocketConnection->connectionClosed));
327329
MUTEX_UNLOCK(pTurnConnection->lock);
328330

331+
THREAD_SLEEP(2 * HUNDREDS_OF_NANOS_IN_A_SECOND);
332+
333+
MUTEX_LOCK(pConnectionListener->lock);
334+
EXPECT_EQ(STATUS_SUCCESS, doubleListGetHeadNode(pConnectionListener->connectionList, &pCurNode));
335+
while (pCurNode != NULL && connectionRemovedFromListener) {
336+
pCurrSocketConnection = (PSocketConnection) pCurNode->data;
337+
pCurNode = pCurNode->pNext;
338+
connectionRemovedFromListener = pCurrSocketConnection != pTurnSocketConnection;
339+
}
340+
MUTEX_UNLOCK(pConnectionListener->lock);
341+
342+
/* make sure that pTurnSocketConnection has been removed from connection listener's list */
343+
EXPECT_TRUE(connectionRemovedFromListener == TRUE);
344+
329345
freeTestTurnConnection();
330346
}
331347

@@ -338,7 +354,9 @@ TEST_F(TurnConnectionFunctionalityTest, turnConnectionShutdownWithoutAllocationR
338354
BOOL atGetCredential = FALSE;
339355
UINT64 shutdownTimeout;
340356
UINT64 atGetCredentialTimeout = GETTIME() + 10 * HUNDREDS_OF_NANOS_IN_A_SECOND;
341-
PSocketConnection pTurnSocketConnection = NULL;
357+
PSocketConnection pTurnSocketConnection = NULL, pCurrSocketConnection = NULL;
358+
PDoubleListNode pCurNode = NULL;
359+
BOOL connectionRemovedFromListener = TRUE;
342360

343361
initializeTestTurnConnection();
344362
pTurnSocketConnection = pTurnConnection->pControlChannel;
@@ -369,6 +387,82 @@ TEST_F(TurnConnectionFunctionalityTest, turnConnectionShutdownWithoutAllocationR
369387
EXPECT_TRUE(ATOMIC_LOAD_BOOL(&pTurnSocketConnection->connectionClosed));
370388
MUTEX_UNLOCK(pTurnConnection->lock);
371389

390+
THREAD_SLEEP(2 * HUNDREDS_OF_NANOS_IN_A_SECOND);
391+
392+
MUTEX_LOCK(pConnectionListener->lock);
393+
EXPECT_EQ(STATUS_SUCCESS, doubleListGetHeadNode(pConnectionListener->connectionList, &pCurNode));
394+
while (pCurNode != NULL && connectionRemovedFromListener) {
395+
pCurrSocketConnection = (PSocketConnection) pCurNode->data;
396+
pCurNode = pCurNode->pNext;
397+
connectionRemovedFromListener = pCurrSocketConnection != pTurnSocketConnection;
398+
}
399+
MUTEX_UNLOCK(pConnectionListener->lock);
400+
401+
/* make sure that pTurnSocketConnection has been removed from connection listener's list */
402+
EXPECT_TRUE(connectionRemovedFromListener == TRUE);
403+
404+
freeTestTurnConnection();
405+
}
406+
407+
TEST_F(TurnConnectionFunctionalityTest, turnConnectionShutdownAfterFailure)
408+
{
409+
if (!mAccessKeyIdSet) {
410+
return;
411+
}
412+
413+
BOOL atGetCredential = FALSE;
414+
UINT64 shutdownTimeout;
415+
UINT64 atGetCredentialTimeout = GETTIME() + 10 * HUNDREDS_OF_NANOS_IN_A_SECOND;
416+
PSocketConnection pTurnSocketConnection = NULL, pCurrSocketConnection = NULL;
417+
PDoubleListNode pCurNode = NULL;
418+
BOOL connectionRemovedFromListener = TRUE;
419+
420+
initializeTestTurnConnection();
421+
pTurnSocketConnection = pTurnConnection->pControlChannel;
422+
423+
EXPECT_EQ(STATUS_SUCCESS, turnConnectionStart(pTurnConnection));
424+
425+
// wait until get credential state
426+
while (!atGetCredential && GETTIME() < atGetCredentialTimeout) {
427+
THREAD_SLEEP(10 * HUNDREDS_OF_NANOS_IN_A_MILLISECOND);
428+
MUTEX_LOCK(pTurnConnection->lock);
429+
if (pTurnConnection->state == TURN_STATE_GET_CREDENTIALS) {
430+
atGetCredential = TRUE;
431+
}
432+
MUTEX_UNLOCK(pTurnConnection->lock);
433+
}
434+
435+
MUTEX_LOCK(pTurnConnection->lock);
436+
pTurnConnection->state = TURN_STATE_FAILED;
437+
pTurnConnection->errorStatus = STATUS_INVALID_OPERATION;
438+
MUTEX_UNLOCK(pTurnConnection->lock);
439+
440+
shutdownTimeout = GETTIME() + 5 * HUNDREDS_OF_NANOS_IN_A_SECOND;
441+
while (!turnConnectionIsShutdownComplete(pTurnConnection) && GETTIME() < shutdownTimeout) {
442+
THREAD_SLEEP(HUNDREDS_OF_NANOS_IN_A_SECOND);
443+
}
444+
445+
EXPECT_TRUE(turnConnectionIsShutdownComplete(pTurnConnection));
446+
447+
MUTEX_LOCK(pTurnConnection->lock);
448+
EXPECT_TRUE(ATOMIC_LOAD_BOOL(&pTurnSocketConnection->connectionClosed));
449+
MUTEX_UNLOCK(pTurnConnection->lock);
450+
451+
/* select in connection timeout every 1s */
452+
THREAD_SLEEP(3 * HUNDREDS_OF_NANOS_IN_A_SECOND);
453+
454+
MUTEX_LOCK(pConnectionListener->lock);
455+
EXPECT_EQ(STATUS_SUCCESS, doubleListGetHeadNode(pConnectionListener->connectionList, &pCurNode));
456+
while (pCurNode != NULL && connectionRemovedFromListener) {
457+
pCurrSocketConnection = (PSocketConnection) pCurNode->data;
458+
pCurNode = pCurNode->pNext;
459+
connectionRemovedFromListener = pCurrSocketConnection != pTurnSocketConnection;
460+
}
461+
MUTEX_UNLOCK(pConnectionListener->lock);
462+
463+
/* make sure that pTurnSocketConnection has been removed from connection listener's list */
464+
EXPECT_TRUE(connectionRemovedFromListener == TRUE);
465+
372466
freeTestTurnConnection();
373467
}
374468

0 commit comments

Comments
 (0)