Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

854 lines
24 KiB

  1. /*----------------------------------------------------------------------------
  2. * File: RTCPSSRC.C
  3. * Product: RTP/RTCP implementation
  4. * Description: Provides SSRC related function.
  5. *
  6. * INTEL Corporation Proprietary Information
  7. * This listing is supplied under the terms of a license agreement with
  8. * Intel Corporation and may not be copied nor disclosed except in
  9. * accordance with the terms of that agreement.
  10. * Copyright (c) 1995 Intel Corporation.
  11. *--------------------------------------------------------------------------*/
  12. #include "rrcm.h"
  13. #include "md5.h"
  14. /*---------------------------------------------------------------------------
  15. / Global Variables
  16. /--------------------------------------------------------------------------*/
  17. /*---------------------------------------------------------------------------
  18. / External Variables
  19. /--------------------------------------------------------------------------*/
  20. extern PRTCP_CONTEXT pRTCPContext;
  21. #ifdef ENABLE_ISDM2
  22. extern KEY_HANDLE hRRCMRootKey;
  23. extern ISDM2 Isdm2;
  24. #endif
  25. #ifdef _DEBUG
  26. extern char debug_string[];
  27. #endif
  28. /*----------------------------------------------------------------------------
  29. * Function : getOneSSRCentry
  30. * Description: Get an SSRC entry from the free list of entries.
  31. *
  32. * Input : pList : -> to the list to get the entry from
  33. * hHeap : Handle to the heap where the data resides
  34. * *pNum : -> to the number of initial free entry in the list
  35. * *pCritSect : -> to the critical section
  36. *
  37. * Return: OK: -> to SSRC entry
  38. * Error: NULL
  39. ---------------------------------------------------------------------------*/
  40. PSSRC_ENTRY getOneSSRCentry (PLINK_LIST pList,
  41. HANDLE hHeap,
  42. DWORD *pNum,
  43. CRITICAL_SECTION *pCritSect)
  44. {
  45. PSSRC_ENTRY pSSRC = NULL;
  46. IN_OUT_STR ("RTCP: Enter getOneSSRCentry()\n");
  47. // get an entry from the free list
  48. pSSRC = (PSSRC_ENTRY)removePcktFromHead (pList, pCritSect);
  49. if (pSSRC == NULL)
  50. {
  51. // try to reallocate some free cells
  52. if (allocateLinkedList (pList, hHeap, pNum,
  53. sizeof(SSRC_ENTRY),
  54. pCritSect) == RRCM_NoError)
  55. {
  56. // get a free cell if some have been reallocated
  57. pSSRC = (PSSRC_ENTRY)removePcktFromHead (pList, pCritSect);
  58. }
  59. }
  60. if (pSSRC)
  61. {
  62. clearSSRCEntry (pSSRC);
  63. // initialize the critical section
  64. InitializeCriticalSection(&pSSRC->critSect);
  65. }
  66. IN_OUT_STR ("RTCP: Exit getOneSSRCentry()\n");
  67. return (pSSRC);
  68. }
  69. /*----------------------------------------------------------------------------
  70. * Function : getSSRC
  71. * Description: Get a unique 32 bits SSRC
  72. *
  73. * Input : RcvSSRCList: Session's receive SSRC list address
  74. * XmtSSRCList: Session's transmit SSRC list address
  75. *
  76. * Return: Unique 32 bits SSRC
  77. ---------------------------------------------------------------------------*/
  78. DWORD getSSRC (LINK_LIST RcvSSRCList,
  79. LINK_LIST XmtSSRCList)
  80. {
  81. DWORD SSRCnum = 0;
  82. DWORD dwStatus;
  83. PSSRC_ENTRY pSSRC;
  84. MD5_CTX context;
  85. DWORD i;
  86. union {
  87. unsigned char c[16];
  88. DWORD x[4];
  89. }digest;
  90. struct {
  91. DWORD pid;
  92. DWORD time;
  93. FILETIME createTime;
  94. FILETIME exitTime;
  95. FILETIME kernelTime;
  96. FILETIME userTime;
  97. } md5Input;
  98. IN_OUT_STR ("RTCP: Enter getSSRC()\n");
  99. // go through all SSRCs of this RTP/RTCP session
  100. while (SSRCnum == 0)
  101. {
  102. // get MD5 inputs
  103. md5Input.pid = GetCurrentThreadId();
  104. md5Input.time = timeGetTime();
  105. dwStatus = GetProcessTimes (GetCurrentProcess(),
  106. &md5Input.createTime,
  107. &md5Input.exitTime,
  108. &md5Input.kernelTime,
  109. &md5Input.userTime);
  110. if (dwStatus == FALSE)
  111. {
  112. RRCM_DBG_MSG ("RTCP: GetProcessTimes() failed", GetLastError(),
  113. __FILE__, __LINE__, DBG_NOTIFY);
  114. }
  115. // Implementation suggested by draft 08, Appendix 6
  116. MD5Init (&context);
  117. MD5Update (&context, (unsigned char *)&md5Input, sizeof (md5Input));
  118. MD5Final ((unsigned char *)&digest, &context);
  119. SSRCnum = 0;
  120. for (i=0; i < 3; i++)
  121. SSRCnum ^= digest.x[i];
  122. // look through all transmitter for this session
  123. pSSRC = (PSSRC_ENTRY)XmtSSRCList.prev;
  124. if (isSSRCunique (pSSRC, &SSRCnum) == TRUE)
  125. {
  126. // look through all received SSRC for this session
  127. pSSRC = (PSSRC_ENTRY)RcvSSRCList.prev;
  128. isSSRCunique (pSSRC, &SSRCnum);
  129. }
  130. }
  131. IN_OUT_STR ("RTCP: Exit getSSRC()\n");
  132. return (SSRCnum);
  133. }
  134. /*----------------------------------------------------------------------------
  135. * Function : getAnSSRC
  136. * Description: Build an SSRC according to the RFC, but does not check for
  137. * collision. Mainly used by H.323 to get a 32 bits number.
  138. *
  139. * Input : None
  140. *
  141. * Return: 32 bits SSRC
  142. ---------------------------------------------------------------------------*/
  143. DWORD WINAPI getAnSSRC (void)
  144. {
  145. DWORD SSRCnum = 0;
  146. DWORD dwStatus;
  147. MD5_CTX context;
  148. DWORD i;
  149. union {
  150. unsigned char c[16];
  151. DWORD x[4];
  152. }digest;
  153. struct {
  154. DWORD pid;
  155. DWORD time;
  156. FILETIME createTime;
  157. FILETIME exitTime;
  158. FILETIME kernelTime;
  159. FILETIME userTime;
  160. } md5Input;
  161. IN_OUT_STR ("RTCP: Enter getAnSSRC()\n");
  162. // get MD5 inputs
  163. md5Input.pid = GetCurrentThreadId();
  164. md5Input.time = timeGetTime();
  165. dwStatus = GetProcessTimes (GetCurrentProcess(),
  166. &md5Input.createTime,
  167. &md5Input.exitTime,
  168. &md5Input.kernelTime,
  169. &md5Input.userTime);
  170. if (dwStatus == FALSE)
  171. {
  172. RRCM_DBG_MSG ("RTCP: GetProcessTimes() failed", GetLastError(),
  173. __FILE__, __LINE__, DBG_NOTIFY);
  174. }
  175. // Implementation suggested by draft 08, Appendix 6
  176. MD5Init (&context);
  177. MD5Update (&context, (unsigned char *)&md5Input, sizeof (md5Input));
  178. MD5Final ((unsigned char *)&digest, &context);
  179. SSRCnum = 0;
  180. for (i=0; i < 3; i++)
  181. SSRCnum ^= digest.x[i];
  182. IN_OUT_STR ("RTCP: Exit getAnSSRC()\n");
  183. return (SSRCnum);
  184. }
  185. /*----------------------------------------------------------------------------
  186. * Function : isSSRCunique
  187. * Description: Check to see the SSRC already exist
  188. *
  189. * Input : pSSRC : -> to an SSRC list
  190. * *SSRCnum : -> to the SSRC to check
  191. *
  192. * Return: 0: SSRC already exist
  193. * 1: SSRC is unique
  194. ---------------------------------------------------------------------------*/
  195. DWORD isSSRCunique (PSSRC_ENTRY pSSRC,
  196. DWORD *SSRCnum)
  197. {
  198. IN_OUT_STR ("RTCP: Enter isSSRCunique()\n");
  199. // make sure SSRC is unique for this session
  200. while (pSSRC)
  201. {
  202. if (pSSRC->SSRC == *SSRCnum)
  203. {
  204. // SSRC already in use, get a new one
  205. *SSRCnum = 0;
  206. return FALSE;
  207. }
  208. // get next RTCP session
  209. pSSRC = (PSSRC_ENTRY)pSSRC->SSRCList.next;
  210. }
  211. IN_OUT_STR ("RTCP: Exit isSSRCunique()\n");
  212. return TRUE;
  213. }
  214. /*----------------------------------------------------------------------------
  215. * Function : createSSRCEntry
  216. * Description: Create an SSRC entry, for a particular RTP/RTCP session
  217. *
  218. * Input : SSRCnum : SSRC number
  219. * pRTCP : -> to the RTCP session
  220. * fromAddr : From address
  221. * fromLen : From length
  222. * headOfList : Put the new entry at the head of the list
  223. *
  224. * Return: Address of the SSRC entry data structure.
  225. ---------------------------------------------------------------------------*/
  226. PSSRC_ENTRY createSSRCEntry (DWORD SSRCnum,
  227. PRTCP_SESSION pRTCP,
  228. PSOCKADDR fromAddr,
  229. DWORD fromLen,
  230. DWORD headOfList)
  231. {
  232. PSSRC_ENTRY pSSRCentry;
  233. PSSRC_ENTRY pSSRCtmp;
  234. PLINK_LIST pTmp;
  235. BOOL entryAdded = FALSE;
  236. IN_OUT_STR ("RTCP: Enter createSSRCEntry()\n");
  237. // get an SSRC cell from the free list
  238. pSSRCentry = getOneSSRCentry (&pRTCPContext->RRCMFreeStat,
  239. pRTCPContext->hHeapRRCMStat,
  240. &pRTCPContext->dwInitNumFreeRRCMStat,
  241. &pRTCPContext->critSect);
  242. if (pSSRCentry == NULL)
  243. return NULL;
  244. // save the remote source address
  245. if (saveNetworkAddress(pSSRCentry,
  246. fromAddr,
  247. fromLen) != RRCM_NoError)
  248. {
  249. addToHeadOfList (&pRTCPContext->RRCMFreeStat,
  250. (PLINK_LIST)pSSRCentry,
  251. &pRTCPContext->critSect);
  252. return (NULL);
  253. }
  254. pSSRCentry->SSRC = SSRCnum;
  255. pSSRCentry->rcvInfo.dwProbation = MIN_SEQUENTIAL;
  256. // set this SSRC entry's RTCP session
  257. pSSRCentry->pRTCPses = pRTCP;
  258. // initialize the socket descriptor
  259. pSSRCentry->RTPsd = ((PSSRC_ENTRY)pRTCP->XmtSSRCList.prev)->RTPsd;
  260. pSSRCentry->RTCPsd = ((PSSRC_ENTRY)pRTCP->XmtSSRCList.prev)->RTCPsd;
  261. // initialize 'dwLastReportRcvdTime' to now
  262. pSSRCentry->dwLastReportRcvdTime = timeGetTime();
  263. #ifdef _DEBUG
  264. wsprintf (debug_string,
  265. "RTCP: Create SSRC entry (Addr:x%lX, SSRC=x%lX) for session: (Addr:x%lX)",
  266. pSSRCentry, pSSRCentry->SSRC, pRTCP);
  267. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  268. #endif
  269. #ifdef ENABLE_ISDM2
  270. // register to ISDM
  271. if (Isdm2.hISDMdll && (pRTCP->dwSessionStatus & RTCP_DEST_LEARNED))
  272. registerSessionToISDM (pSSRCentry, pRTCP, &Isdm2);
  273. #endif
  274. // check to see if it's our entry that needs to be put at the head of
  275. // the SSRC list. If it's not our entry, will find a place for it in the
  276. // ordered list
  277. if (headOfList)
  278. {
  279. // Attach the SSRC to the RTCP session list entry head
  280. addToHeadOfList (&pRTCP->XmtSSRCList,
  281. (PLINK_LIST)pSSRCentry,
  282. &pRTCP->critSect);
  283. // number of SSRC entry for the RTCP session
  284. InterlockedIncrement ((long *)&pRTCP->dwCurNumSSRCperSes);
  285. #ifdef MONITOR_STATS
  286. // high number of SSRC entry for the RTCP session
  287. InterlockedIncrement ((long *)&pRTCP->dwHiNumSSRCperSes)
  288. #endif
  289. return (pSSRCentry);
  290. }
  291. // put it on the receive list of SSRCs
  292. pTmp = (PLINK_LIST)pRTCP->RcvSSRCList.prev;
  293. // check if it's the first one
  294. if (pTmp == NULL)
  295. {
  296. // Attach the SSRC to the RTCP session list entry head
  297. addToHeadOfList (&pRTCP->RcvSSRCList,
  298. (PLINK_LIST)pSSRCentry,
  299. &pRTCP->critSect);
  300. // number of SSRC entry for the RTCP session
  301. InterlockedIncrement ((long *)&pRTCP->dwCurNumSSRCperSes);
  302. #ifdef MONITOR_STATS
  303. // high number of SSRC entry for the RTCP session
  304. InterlockedIncrement ((long *)&pRTCP->dwHiNumSSRCperSes)
  305. #endif
  306. return (pSSRCentry);
  307. }
  308. while (!entryAdded)
  309. {
  310. if (pTmp != NULL)
  311. {
  312. pSSRCtmp = (PSSRC_ENTRY)pTmp;
  313. if (pSSRCtmp->SSRC < SSRCnum)
  314. pTmp = pTmp->next;
  315. else
  316. {
  317. // lock at the RTCP session level, for head/tail ptrs access
  318. EnterCriticalSection (&pRTCP->critSect);
  319. if ((pTmp->next == NULL) && (pSSRCtmp->SSRC < SSRCnum))
  320. {
  321. // attach the SSRC to the RTCP session list entry head
  322. // This SSRC is bigger than all other ones
  323. addToHeadOfList (&pRTCP->RcvSSRCList,
  324. (PLINK_LIST)pSSRCentry,
  325. &pRTCP->critSect);
  326. }
  327. else if (pTmp->prev == NULL)
  328. {
  329. // attach the SSRC to the RTCP session list entry tail
  330. // This SSRC is smaller than all other ones
  331. addToTailOfList (&pRTCP->RcvSSRCList,
  332. (PLINK_LIST)pSSRCentry,
  333. &pRTCP->critSect);
  334. }
  335. else
  336. {
  337. // this SSRC is in between other SSRCs
  338. EnterCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
  339. (pTmp->prev)->next = (PLINK_LIST)pSSRCentry;
  340. LeaveCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
  341. // don't need to lock out pSSRCentry pointers
  342. pSSRCentry->SSRCList.next = pTmp;
  343. pSSRCentry->SSRCList.prev = pTmp->prev;
  344. pTmp->prev = (PLINK_LIST)pSSRCentry;
  345. }
  346. // unlock RTCP session access
  347. LeaveCriticalSection (&pRTCP->critSect);
  348. // set loop flag
  349. entryAdded = TRUE;
  350. }
  351. }
  352. else
  353. {
  354. // attach the SSRC to the RTCP session list entry head
  355. addToHeadOfList (&pRTCP->RcvSSRCList,
  356. (PLINK_LIST)pSSRCentry,
  357. &pRTCP->critSect);
  358. // set loop flag
  359. entryAdded = TRUE;
  360. }
  361. }
  362. // number of SSRC entry for the RTCP session
  363. InterlockedIncrement ((long *)&pRTCP->dwCurNumSSRCperSes);
  364. #ifdef MONITOR_STATS
  365. // high number of SSRC entry for the RTCP session
  366. InterlockedIncrement ((long *)&pRTCP->dwHiNumSSRCperSes)
  367. #endif
  368. IN_OUT_STR ("RTCP: Exit createSSRCEntry()\n");
  369. return (pSSRCentry);
  370. }
  371. /*----------------------------------------------------------------------------
  372. * Function : deleteSSRCEntry
  373. * Description: Delete an SSRC entry (for a particular RTP/RTCP session).
  374. *
  375. * Input : SSRCnum : SSRC number to delete from the list
  376. * pRTCP : -> to the RTCP session
  377. *
  378. * Return: TRUE: Deleted
  379. * FALSE: Entry not found
  380. ---------------------------------------------------------------------------*/
  381. DWORD deleteSSRCEntry (DWORD SSRCnum,
  382. PRTCP_SESSION pRTCP)
  383. {
  384. PSSRC_ENTRY pSSRCtmp = NULL;
  385. PLINK_LIST pTmp;
  386. DWORD dwStatus = FALSE;
  387. IN_OUT_STR ("RTCP: Enter deleteSSRCEntry()\n");
  388. // walk through the list from the tail
  389. pTmp = (PLINK_LIST)pRTCP->RcvSSRCList.prev;
  390. while (pTmp)
  391. {
  392. // lock access to this entry
  393. EnterCriticalSection (&((PSSRC_ENTRY)pTmp)->critSect);
  394. if (((PSSRC_ENTRY)pTmp)->SSRC == SSRCnum)
  395. {
  396. #ifdef _DEBUG
  397. wsprintf (debug_string,
  398. "RTCP: Delete SSRC=x%lX from session: (Addr:x%lX)",
  399. SSRCnum, pRTCP);
  400. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  401. #endif
  402. #ifdef ENABLE_ISDM2
  403. // unregister ISDM session
  404. if (Isdm2.hISDMdll && ((PSSRC_ENTRY)pTmp)->hISDM)
  405. Isdm2.ISDMEntry.ISD_DeleteValue(hRRCMRootKey,
  406. ((PSSRC_ENTRY)pTmp)->hISDM, NULL);
  407. #endif
  408. // remove the entry from the list
  409. if (pTmp->next == NULL)
  410. {
  411. removePcktFromHead (&pRTCP->RcvSSRCList,
  412. &pRTCP->critSect);
  413. }
  414. else if (pTmp->prev == NULL)
  415. {
  416. removePcktFromTail (&pRTCP->RcvSSRCList,
  417. &pRTCP->critSect);
  418. }
  419. else
  420. {
  421. // in between, relink around
  422. EnterCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
  423. (pTmp->prev)->next = pTmp->next;
  424. LeaveCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
  425. EnterCriticalSection (&((PSSRC_ENTRY)pTmp->next)->critSect);
  426. (pTmp->next)->prev = pTmp->prev;
  427. LeaveCriticalSection (&((PSSRC_ENTRY)pTmp->next)->critSect);
  428. }
  429. // number of SSRC entry for the RTCP session
  430. InterlockedDecrement ((long *)&pRTCP->dwCurNumSSRCperSes);
  431. // return entry to the free list
  432. addToHeadOfList (&pRTCPContext->RRCMFreeStat,
  433. pTmp,
  434. &pRTCPContext->critSect);
  435. // unlock access to this entry
  436. LeaveCriticalSection (&((PSSRC_ENTRY)pTmp)->critSect);
  437. dwStatus = TRUE;
  438. break;
  439. }
  440. // unlock access to this entry
  441. LeaveCriticalSection (&((PSSRC_ENTRY)pTmp)->critSect);
  442. pTmp = pTmp->next;
  443. }
  444. IN_OUT_STR ("RTCP: Exit deleteSSRCEntry()\n");
  445. return (dwStatus);
  446. }
  447. /*----------------------------------------------------------------------------
  448. * Function : deleteSSRClist
  449. * Description: Delete the SSRC list of an RTP/RTCP session.
  450. *
  451. * Input : pRTCP : -> to RTCP session
  452. * pFreeList : -> to the free list of SSRCs
  453. * pOwner : -> to the free list owner
  454. *
  455. * Return: None
  456. ---------------------------------------------------------------------------*/
  457. void deleteSSRClist (PRTCP_SESSION pRTCP,
  458. PLINK_LIST pFreeList,
  459. PRTCP_CONTEXT pOwner)
  460. {
  461. PLINK_LIST pSSRC;
  462. IN_OUT_STR ("RTCP: Enter deleteSSRClist()\n");
  463. ASSERT (pFreeList);
  464. ASSERT (pRTCP);
  465. // lock access to the full RTCP session
  466. EnterCriticalSection (&pRTCP->critSect);
  467. // go through the list of transmit SSRCs for this RTCP session
  468. while (pRTCP->XmtSSRCList.next != NULL)
  469. {
  470. // get packet from the list tail
  471. pSSRC = removePcktFromTail ((PLINK_LIST)&pRTCP->XmtSSRCList,
  472. &pRTCP->critSect);
  473. if (pSSRC != NULL)
  474. {
  475. #ifdef _DEBUG
  476. wsprintf(debug_string,
  477. "RTCP: Delete SSRC entry (x%lX) from session (x%lX)",
  478. ((PSSRC_ENTRY)pSSRC)->SSRC, pRTCP);
  479. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  480. #endif
  481. #ifdef ENABLE_ISDM2
  482. // unregister ISDM session
  483. if (Isdm2.hISDMdll && ((PSSRC_ENTRY)pSSRC)->hISDM)
  484. Isdm2.ISDMEntry.ISD_DeleteValue (hRRCMRootKey,
  485. ((PSSRC_ENTRY)pSSRC)->hISDM, NULL);
  486. #endif
  487. // put it back to the free list
  488. addToHeadOfList (pFreeList, pSSRC, &pOwner->critSect);
  489. // release the critical section
  490. DeleteCriticalSection (&((PSSRC_ENTRY)pSSRC)->critSect);
  491. }
  492. }
  493. // go through the list of SSRCs for this RTP/RTCP session
  494. while (pRTCP->RcvSSRCList.next != NULL)
  495. {
  496. // get packet from the list tail
  497. pSSRC = removePcktFromTail ((PLINK_LIST)&pRTCP->RcvSSRCList,
  498. &pRTCP->critSect);
  499. if (pSSRC != NULL)
  500. {
  501. #ifdef _DEBUG
  502. wsprintf(debug_string,
  503. "RTCP: Delete SSRC entry (x%lX) from session (x%lX)",
  504. ((PSSRC_ENTRY)pSSRC)->SSRC, pRTCP);
  505. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  506. #endif
  507. #ifdef ENABLE_ISDM2
  508. // unregister ISDM session
  509. if (Isdm2.hISDMdll && ((PSSRC_ENTRY)pSSRC)->hISDM)
  510. Isdm2.ISDMEntry.ISD_DeleteValue (hRRCMRootKey,
  511. ((PSSRC_ENTRY)pSSRC)->hISDM, NULL);
  512. #endif
  513. // put it back to the free list
  514. addToHeadOfList (pFreeList, pSSRC, &pOwner->critSect);
  515. // release the critical section
  516. DeleteCriticalSection (&((PSSRC_ENTRY)pSSRC)->critSect);
  517. }
  518. }
  519. // unlock access to the full RTCP session
  520. LeaveCriticalSection (&pRTCP->critSect);
  521. IN_OUT_STR ("RTCP: Exit deleteSSRClist()\n");
  522. }
  523. /*----------------------------------------------------------------------------
  524. * Function : SSRCTimeoutCheck
  525. * Description: Check if an rcv SSRC needs to be timed out
  526. * Since there may be multiple RCV SSRCs, repeat calling
  527. * this function until it returns NULL
  528. *
  529. * Input : pRTCC : -> to the RTCP session
  530. * curTime : Current time
  531. *
  532. * Return: NULL : No action needed
  533. * PSSRC : -> to the SSRC entry that should be deleted
  534. ---------------------------------------------------------------------------*/
  535. PSSRC_ENTRY SSRCTimeoutCheck (PRTCP_SESSION pRTCP, DWORD curTime)
  536. {
  537. PSSRC_ENTRY pSSRC;
  538. DWORD tmpTime;
  539. // check the colliding entries table and clear it if needed
  540. RRCMTimeOutCollisionTable (pRTCP);
  541. // get the right session to close
  542. pSSRC = (PSSRC_ENTRY)pRTCP->RcvSSRCList.prev;
  543. while (pSSRC)
  544. {
  545. // check if this SSRC timed-out
  546. tmpTime = curTime - pSSRC->dwLastReportRcvdTime;
  547. // get the time in minutes
  548. tmpTime /= (1000*60);
  549. if (tmpTime > RTCP_TIME_OUT_MINUTES)
  550. {
  551. break;
  552. }
  553. pSSRC = (PSSRC_ENTRY)pSSRC->SSRCList.next;
  554. }
  555. return pSSRC;
  556. }
  557. /*---------------------------------------------------------------------------
  558. * Function : RRCMChkCollisionTable
  559. * Description: Check the collision table to try to find a match
  560. *
  561. * Input : pFrom : -> recv from address
  562. * fromlen : -> recv from address length
  563. * pSSRC : -> to the SSRC entry
  564. *
  565. * Return: TRUE: Match found
  566. * FALSE: No match found
  567. --------------------------------------------------------------------------*/
  568. DWORD RRCMChkCollisionTable (PSOCKADDR pFrom,
  569. UINT fromlen,
  570. PSSRC_ENTRY pSSRC)
  571. {
  572. DWORD idx;
  573. DWORD dwStatus = FALSE;
  574. PRTCP_SESSION pRTCP = pSSRC->pRTCPses;
  575. IN_OUT_STR ("RRCM: Enter RRCMChkCollisionTable()\n");
  576. // entry w/ time == 0 are empty
  577. for (idx = 0; idx < NUM_COLLISION_ENTRIES; idx++)
  578. {
  579. if (pRTCP->collInfo[idx].dwCollideTime != 0)
  580. {
  581. if (memcmp (&pRTCP->collInfo[idx].collideAddr,
  582. pFrom,
  583. fromlen) == 0)
  584. {
  585. // update the time of last collision received
  586. pRTCP->collInfo[idx].dwCollideTime = timeGetTime();
  587. dwStatus = TRUE;
  588. break;
  589. }
  590. }
  591. }
  592. IN_OUT_STR ("RRCM: Exit RRCMChkCollisionTable()\n");
  593. return dwStatus;
  594. }
  595. /*---------------------------------------------------------------------------
  596. * Function : RRCMAddEntryToCollisionTable
  597. * Description: Add an entry into the collision table.
  598. *
  599. * Input : pFrom : -> recv from address
  600. * fromlen : -> recv from address length
  601. * pSSRC : -> to the SSRC entry
  602. *
  603. * Return: TRUE: Entry added
  604. * FALSE: Table full
  605. --------------------------------------------------------------------------*/
  606. DWORD RRCMAddEntryToCollisionTable (PSOCKADDR pFrom,
  607. UINT fromlen,
  608. PSSRC_ENTRY pSSRC)
  609. {
  610. DWORD idx;
  611. DWORD dwStatus = FALSE;
  612. PRTCP_SESSION pRTCP = pSSRC->pRTCPses;
  613. IN_OUT_STR ("RRCM: Enter RRCMAddEntryToCollisionTable()\n");
  614. // entry w/ time == 0 are empty
  615. for (idx = 0; idx < NUM_COLLISION_ENTRIES; idx++)
  616. {
  617. if (pRTCP->collInfo[idx].dwCollideTime == 0)
  618. {
  619. memcpy (&pRTCP->collInfo[idx].collideAddr,
  620. pFrom,
  621. fromlen);
  622. pRTCP->collInfo[idx].addrLen = fromlen;
  623. pRTCP->collInfo[idx].dwCollideTime = timeGetTime();
  624. pRTCP->collInfo[idx].dwCurRecvRTCPrptNumber = pSSRC->dwNumRptRcvd;
  625. pRTCP->collInfo[idx].SSRC = pSSRC->SSRC;
  626. dwStatus = TRUE;
  627. break;
  628. }
  629. }
  630. IN_OUT_STR ("RRCM: Exit RRCMAddEntryToCollisionTable()\n");
  631. return dwStatus;
  632. }
  633. /*---------------------------------------------------------------------------
  634. * Function : RRCMTimeOutInCollisionTable
  635. * Description: Check if an entry in the collision table must be timed-out
  636. *
  637. * Input : pRTCP : -> to the RTCP session
  638. *
  639. * Return: None
  640. --------------------------------------------------------------------------*/
  641. void RRCMTimeOutCollisionTable (PRTCP_SESSION pRTCP)
  642. {
  643. DWORD idx;
  644. DWORD currTime = timeGetTime();
  645. DWORD diffTime;
  646. IN_OUT_STR ("RTCP: Enter RRCMTimeOutCollisionTable()\n");
  647. // entry w/ time == 0 are empty
  648. for (idx = 0; idx < NUM_COLLISION_ENTRIES; idx++)
  649. {
  650. // valid entries have the time set
  651. if (pRTCP->collInfo[idx].dwCollideTime)
  652. {
  653. // remove the entry from this table if 10 RTCP report intervals
  654. // have occured without a collision
  655. // clear the entry if over 5'
  656. // !!! TODO !!!
  657. // !!! using the right interval !!!
  658. diffTime = currTime - pRTCP->collInfo[idx].dwCollideTime;
  659. diffTime /= 1000;
  660. if (diffTime > 300)
  661. {
  662. pRTCP->collInfo[idx].dwCollideTime = 0;
  663. // the SSRC entry in the receive list will be deleted by
  664. // the timeout thread
  665. }
  666. }
  667. }
  668. IN_OUT_STR ("RTCP: Exit RRCMTimeOutCollisionTable()\n");
  669. }
  670. /*----------------------------------------------------------------------------
  671. * Function : clearSSRCEntry
  672. * Description: Clears what needs to be cleared in an SSRC entry
  673. *
  674. * Input : pSSRC : -> to the SSRC entry
  675. *
  676. * Return: None
  677. ---------------------------------------------------------------------------*/
  678. void clearSSRCEntry (PSSRC_ENTRY pSSRC)
  679. {
  680. IN_OUT_STR ("RTCP: Enter clearSSRCEntry()\n");
  681. memset (&pSSRC->xmtInfo, 0x00, sizeof(XMIT_INFO));
  682. memset (&pSSRC->rcvInfo, 0x00, sizeof(RECV_INFO));
  683. memset (&pSSRC->rrFeedback, 0x00, sizeof (RTCP_FEEDBACK));
  684. memset (&pSSRC->cnameInfo, 0x00, sizeof(SDES_DATA));
  685. memset (&pSSRC->nameInfo, 0x00, sizeof(SDES_DATA));
  686. memset (&pSSRC->from, 0x00, sizeof(SOCKADDR));
  687. pSSRC->SSRC = 0;
  688. pSSRC->dwSSRCStatus = 0;
  689. pSSRC->dwStreamClock = 0;
  690. pSSRC->fromLen = 0;
  691. pSSRC->dwLastReportRcvdTime = 0;
  692. pSSRC->dwUserXmtTimeoutCtrl = 0;
  693. pSSRC->RTPsd = 0;
  694. pSSRC->RTCPsd = 0;
  695. pSSRC->pRTCPses = NULL;
  696. pSSRC->dwNumRptSent = 0;
  697. pSSRC->dwNumRptRcvd = 0;
  698. #ifdef ENABLE_ISDM2
  699. pSSRC->hISDM = 0;
  700. #endif
  701. #ifdef _DEBUG
  702. pSSRC->dwPrvTime = 0;
  703. #endif
  704. IN_OUT_STR ("RTCP: Exit clearSSRCEntry()\n");
  705. }
  706. // [EOF]