Leaked source code of windows server 2003
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.

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