@@ -1005,6 +1005,8 @@ STATUS createPeerConnection(PRtcConfiguration pConfiguration, PRtcPeerConnection
1005
1005
pKvsPeerConnection -> twccLock = MUTEX_CREATE (TRUE);
1006
1006
pKvsPeerConnection -> pTwccManager = (PTwccManager ) MEMCALLOC (1 , SIZEOF (TwccManager ));
1007
1007
CHK (pKvsPeerConnection -> pTwccManager != NULL , STATUS_NOT_ENOUGH_MEMORY );
1008
+ CHK_STATUS (hashTableCreateWithParams (TWCC_HASH_TABLE_BUCKET_COUNT , TWCC_HASH_TABLE_BUCKET_LENGTH ,
1009
+ & pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable ));
1008
1010
}
1009
1011
1010
1012
* ppPeerConnection = (PRtcPeerConnection ) pKvsPeerConnection ;
@@ -1041,10 +1043,12 @@ STATUS freePeerConnection(PRtcPeerConnection* ppPeerConnection)
1041
1043
{
1042
1044
ENTERS ();
1043
1045
STATUS retStatus = STATUS_SUCCESS ;
1044
- PKvsPeerConnection pKvsPeerConnection ;
1046
+ PKvsPeerConnection pKvsPeerConnection = NULL ;
1045
1047
PDoubleListNode pCurNode = NULL ;
1046
1048
UINT64 item = 0 ;
1047
1049
UINT64 startTime ;
1050
+ UINT32 twccHashTableCount = 0 ;
1051
+ BOOL twccLocked = FALSE;
1048
1052
1049
1053
CHK (ppPeerConnection != NULL , STATUS_NULL_ARG );
1050
1054
@@ -1113,20 +1117,34 @@ STATUS freePeerConnection(PRtcPeerConnection* ppPeerConnection)
1113
1117
}
1114
1118
1115
1119
if (pKvsPeerConnection -> pTwccManager != NULL ) {
1116
- if (IS_VALID_MUTEX_VALUE (pKvsPeerConnection -> twccLock )) {
1117
- MUTEX_FREE (pKvsPeerConnection -> twccLock );
1120
+ MUTEX_LOCK (pKvsPeerConnection -> twccLock );
1121
+ twccLocked = TRUE;
1122
+
1123
+ if (STATUS_SUCCEEDED (hashTableGetCount (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable , & twccHashTableCount ))) {
1124
+ DLOGI ("Number of TWCC info packets in memory: %d" , twccHashTableCount );
1118
1125
}
1119
- // twccManager.twccPackets contains sequence numbers of packets (as opposed to pointers to actual packets)
1120
- // we should not deallocate items but we do need to clear the queue
1121
- CHK_LOG_ERR (stackQueueClear (& pKvsPeerConnection -> pTwccManager -> twccPackets , FALSE));
1126
+
1127
+ CHK_LOG_ERR (hashTableIterateEntries (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable , 0 , freeHashEntry ));
1128
+ CHK_LOG_ERR (hashTableFree (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable ));
1129
+
1122
1130
SAFE_MEMFREE (pKvsPeerConnection -> pTwccManager );
1123
1131
}
1124
1132
1125
1133
// Incase the `RemoteSessionDescription` has not already been freed.
1126
1134
SAFE_MEMFREE (pKvsPeerConnection -> pRemoteSessionDescription );
1127
1135
1136
+ if (IS_VALID_MUTEX_VALUE (pKvsPeerConnection -> twccLock )) {
1137
+ if (twccLocked ) {
1138
+ MUTEX_UNLOCK (pKvsPeerConnection -> twccLock );
1139
+ twccLocked = FALSE;
1140
+ }
1141
+ MUTEX_FREE (pKvsPeerConnection -> twccLock );
1142
+ pKvsPeerConnection -> twccLock = INVALID_MUTEX_VALUE ;
1143
+ }
1144
+
1128
1145
PROFILE_WITH_START_TIME_OBJ (startTime , pKvsPeerConnection -> peerConnectionDiagnostics .freePeerConnectionTime , "Free peer connection" );
1129
1146
SAFE_MEMFREE (* ppPeerConnection );
1147
+
1130
1148
CleanUp :
1131
1149
1132
1150
LEAVES ();
@@ -1826,47 +1844,93 @@ STATUS deinitKvsWebRtc(VOID)
1826
1844
return retStatus ;
1827
1845
}
1828
1846
1829
- STATUS twccManagerOnPacketSent (PKvsPeerConnection pc , PRtpPacket pRtpPacket )
1847
+ // Not thread safe. Ensure this function is invoked in a guarded section
1848
+ static STATUS twccRollingWindowDeletion (PKvsPeerConnection pKvsPeerConnection , PRtpPacket pRtpPacket , UINT16 endingSeqNum )
1849
+ {
1850
+ ENTERS ();
1851
+ STATUS retStatus = STATUS_SUCCESS ;
1852
+ UINT16 updatedSeqNum = 0 ;
1853
+ PTwccRtpPacketInfo tempTwccRtpPktInfo = NULL ;
1854
+ UINT64 ageOfOldest = 0 , firstRtpTime = 0 ;
1855
+ UINT64 twccPacketValue = 0 ;
1856
+ BOOL isCheckComplete = FALSE;
1857
+
1858
+ CHK (pKvsPeerConnection != NULL && pRtpPacket != NULL && pKvsPeerConnection -> pTwccManager != NULL , STATUS_NULL_ARG );
1859
+
1860
+ updatedSeqNum = pKvsPeerConnection -> pTwccManager -> firstSeqNumInRollingWindow ;
1861
+ do {
1862
+ // If the seqNum is not present in the hash table, it is ok. We move on to the next
1863
+ if (STATUS_SUCCEEDED (hashTableGet (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable , updatedSeqNum , & twccPacketValue ))) {
1864
+ tempTwccRtpPktInfo = (PTwccRtpPacketInfo ) twccPacketValue ;
1865
+ if (tempTwccRtpPktInfo != NULL ) {
1866
+ firstRtpTime = tempTwccRtpPktInfo -> localTimeKvs ;
1867
+ // Would be the case if the timestamps are not monotonically increasing.
1868
+ if (pRtpPacket -> sentTime >= firstRtpTime ) {
1869
+ ageOfOldest = pRtpPacket -> sentTime - firstRtpTime ;
1870
+ if (ageOfOldest > TWCC_ESTIMATOR_TIME_WINDOW ) {
1871
+ // If the seqNum is not present in the hash table, move on. However, this case should not happen
1872
+ // given this function is holding the lock and tempTwccRtpPktInfo is populated because it exists
1873
+ if (STATUS_SUCCEEDED (hashTableRemove (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable , updatedSeqNum ))) {
1874
+ SAFE_MEMFREE (tempTwccRtpPktInfo );
1875
+ }
1876
+ updatedSeqNum ++ ;
1877
+ } else {
1878
+ isCheckComplete = TRUE;
1879
+ }
1880
+ } else {
1881
+ // Move to the next seqNum to check if we can remove the next one atleast
1882
+ DLOGV ("Non-monotonic timestamp detected for RTP packet seqNum %d [ts: %" PRIu64 ". Current RTP packets' ts: %" PRIu64 ,
1883
+ updatedSeqNum , firstRtpTime , pRtpPacket -> sentTime );
1884
+ updatedSeqNum ++ ;
1885
+ }
1886
+ } else {
1887
+ CHK_STATUS (hashTableRemove (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable , updatedSeqNum ));
1888
+ updatedSeqNum ++ ;
1889
+ }
1890
+ } else {
1891
+ updatedSeqNum ++ ;
1892
+ }
1893
+ // reset before next iteration
1894
+ tempTwccRtpPktInfo = NULL ;
1895
+ } while (!isCheckComplete && updatedSeqNum != (endingSeqNum + 1 ));
1896
+
1897
+ // Update regardless. The loop checks until current RTP packets seq number irrespective of the failure
1898
+ pKvsPeerConnection -> pTwccManager -> firstSeqNumInRollingWindow = updatedSeqNum ;
1899
+ CleanUp :
1900
+ CHK_LOG_ERR (retStatus );
1901
+
1902
+ LEAVES ();
1903
+ return retStatus ;
1904
+ }
1905
+
1906
+ STATUS twccManagerOnPacketSent (PKvsPeerConnection pKvsPeerConnection , PRtpPacket pRtpPacket )
1830
1907
{
1831
1908
ENTERS ();
1832
1909
STATUS retStatus = STATUS_SUCCESS ;
1833
1910
BOOL locked = FALSE;
1834
- UINT64 sn = 0 ;
1835
- UINT16 seqNum ;
1836
- BOOL isEmpty = FALSE;
1837
- INT64 firstTimeKvs , lastLocalTimeKvs , ageOfOldest ;
1838
- CHK (pc != NULL && pRtpPacket != NULL , STATUS_NULL_ARG );
1839
- CHK (pc -> onSenderBandwidthEstimation != NULL && pc -> pTwccManager != NULL , STATUS_SUCCESS );
1911
+ UINT16 seqNum = 0 ;
1912
+ PTwccRtpPacketInfo pTwccRtpPktInfo = NULL ;
1913
+
1914
+ CHK (pKvsPeerConnection != NULL && pRtpPacket != NULL , STATUS_NULL_ARG );
1915
+ CHK (pKvsPeerConnection -> onSenderBandwidthEstimation != NULL && pKvsPeerConnection -> pTwccManager != NULL , STATUS_SUCCESS );
1840
1916
CHK (TWCC_EXT_PROFILE == pRtpPacket -> header .extensionProfile , STATUS_SUCCESS );
1841
1917
1842
- MUTEX_LOCK (pc -> twccLock );
1918
+ MUTEX_LOCK (pKvsPeerConnection -> twccLock );
1843
1919
locked = TRUE;
1844
1920
1921
+ CHK ((pTwccRtpPktInfo = MEMCALLOC (1 , SIZEOF (TwccRtpPacketInfo ))) != NULL , STATUS_NOT_ENOUGH_MEMORY );
1922
+
1923
+ pTwccRtpPktInfo -> packetSize = pRtpPacket -> payloadLength ;
1924
+ pTwccRtpPktInfo -> localTimeKvs = pRtpPacket -> sentTime ;
1925
+ pTwccRtpPktInfo -> remoteTimeKvs = TWCC_PACKET_LOST_TIME ;
1845
1926
seqNum = TWCC_SEQNUM (pRtpPacket -> header .extensionPayload );
1846
- CHK_STATUS (stackQueueEnqueue (& pc -> pTwccManager -> twccPackets , seqNum ));
1847
- pc -> pTwccManager -> twccPacketBySeqNum [seqNum ].seqNum = seqNum ;
1848
- pc -> pTwccManager -> twccPacketBySeqNum [seqNum ].packetSize = pRtpPacket -> payloadLength ;
1849
- pc -> pTwccManager -> twccPacketBySeqNum [seqNum ].localTimeKvs = pRtpPacket -> sentTime ;
1850
- pc -> pTwccManager -> twccPacketBySeqNum [seqNum ].remoteTimeKvs = TWCC_PACKET_LOST_TIME ;
1851
- pc -> pTwccManager -> lastLocalTimeKvs = pRtpPacket -> sentTime ;
1852
-
1853
- // cleanup queue until it contains up to 2 seconds of sent packets
1854
- do {
1855
- CHK_STATUS (stackQueuePeek (& pc -> pTwccManager -> twccPackets , & sn ));
1856
- firstTimeKvs = pc -> pTwccManager -> twccPacketBySeqNum [(UINT16 ) sn ].localTimeKvs ;
1857
- lastLocalTimeKvs = pRtpPacket -> sentTime ;
1858
- ageOfOldest = lastLocalTimeKvs - firstTimeKvs ;
1859
- if (ageOfOldest > TWCC_ESTIMATOR_TIME_WINDOW ) {
1860
- CHK_STATUS (stackQueueDequeue (& pc -> pTwccManager -> twccPackets , & sn ));
1861
- CHK_STATUS (stackQueueIsEmpty (& pc -> pTwccManager -> twccPackets , & isEmpty ));
1862
- } else {
1863
- break ;
1864
- }
1865
- } while (!isEmpty );
1927
+ CHK_STATUS (hashTableUpsert (pKvsPeerConnection -> pTwccManager -> pTwccRtpPktInfosHashTable , seqNum , (UINT64 ) pTwccRtpPktInfo ));
1866
1928
1929
+ // Ensure twccRollingWindowDeletion is run in a guarded section
1930
+ CHK_STATUS (twccRollingWindowDeletion (pKvsPeerConnection , pRtpPacket , seqNum ));
1867
1931
CleanUp :
1868
1932
if (locked ) {
1869
- MUTEX_UNLOCK (pc -> twccLock );
1933
+ MUTEX_UNLOCK (pKvsPeerConnection -> twccLock );
1870
1934
}
1871
1935
CHK_LOG_ERR (retStatus );
1872
1936
0 commit comments