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.

1208 lines
33 KiB

  1. /*----------------------------------------------------------------------------
  2. * File: RTCPRECV.C
  3. * Product: RTP/RTCP implementation
  4. * Description: Provides the RTCP receive network I/O.
  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. #define MIN(a, b) ((a < b) ? a : b)
  14. /*---------------------------------------------------------------------------
  15. / Global Variables
  16. /--------------------------------------------------------------------------*/
  17. /*---------------------------------------------------------------------------
  18. / External Variables
  19. /--------------------------------------------------------------------------*/
  20. extern PRTCP_CONTEXT pRTCPContext;
  21. extern PRTP_CONTEXT pRTPContext;
  22. extern RRCM_WS RRCMws;
  23. #ifdef ENABLE_ISDM2
  24. extern ISDM2 Isdm2;
  25. #endif
  26. #ifdef _DEBUG
  27. extern char debug_string[];
  28. #endif
  29. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  30. //INTEROP
  31. extern LPInteropLogger RTPLogger;
  32. #endif
  33. /*----------------------------------------------------------------------------
  34. * Function : RTCPrcvInit
  35. * Description: RTCP receive initialisation.
  36. *
  37. * Input : pRTCP : Pointer to the RTCP session information
  38. *
  39. * Return: TRUE/FALSE
  40. ---------------------------------------------------------------------------*/
  41. DWORD RTCPrcvInit (PSSRC_ENTRY pSSRC)
  42. {
  43. PRTCP_BFR_LIST pRcvStruct;
  44. PRTCP_SESSION pRTCP;
  45. int dwStatus;
  46. int dwError;
  47. int errorCnt = 0;
  48. int bfrErrorCnt = 0;
  49. DWORD idx;
  50. int wsockSuccess = FALSE;
  51. // save a pointer to the corresponding RTCP session
  52. pRTCP = pSSRC->pRTCPses;
  53. // Post receive buffers for WS-2. As these buffers are posted per receive
  54. // thread, few of them should be plenty enough for RTCP.
  55. for (idx = 0; idx < pRTPContext->registry.NumRTCPPostedBfr; idx++)
  56. {
  57. // get a free RTCP buffer for a receive operation
  58. pRcvStruct =
  59. (PRTCP_BFR_LIST)removePcktFromTail(&pRTCP->RTCPrcvBfrList,
  60. &pRTCP->critSect);
  61. // check buffer
  62. if (pRcvStruct == NULL)
  63. {
  64. RRCM_DBG_MSG ("RTCP: ERROR - Rcv Bfr Allocation Error", 0,
  65. __FILE__, __LINE__, DBG_ERROR);
  66. // make sure we have at least one buffer
  67. ASSERT (pRcvStruct);
  68. break;
  69. }
  70. // SSRC entry address of our own session
  71. pRcvStruct->pSSRC = pSSRC;
  72. // received address length reset by the receive routine
  73. pRcvStruct->addrLen = sizeof(SOCKADDR);
  74. // use hEvent to recover the buffer's address
  75. pRcvStruct->overlapped.hEvent = (WSAEVENT)pRcvStruct;
  76. // post the receive buffer for this thread
  77. dwStatus = RRCMws.recvFrom (pSSRC->RTCPsd,
  78. &pRcvStruct->bfr,
  79. pRcvStruct->dwBufferCount,
  80. &pRcvStruct->dwNumBytesXfr,
  81. &pRcvStruct->dwFlags,
  82. (PSOCKADDR)pRcvStruct->addr,
  83. &pRcvStruct->addrLen,
  84. (LPWSAOVERLAPPED)&pRcvStruct->overlapped,
  85. RTCPrcvCallback);
  86. // Check Winsock status
  87. if (dwStatus != 0)
  88. {
  89. // error, the receive request won't proceed
  90. dwError = GetLastError();
  91. if ((dwError != WSA_IO_PENDING) && (dwError != WSAEMSGSIZE))
  92. {
  93. RRCM_DBG_MSG ("RTCP: ERROR WSARecvFrom()", GetLastError(),
  94. __FILE__, __LINE__, DBG_ERROR);
  95. // notify application if interested
  96. RRCMnotification (RRCM_RTCP_WS_RCV_ERROR, pSSRC,
  97. pSSRC->SSRC, dwError);
  98. // Return the buffer to the free queue
  99. addToHeadOfList (&pRTCP->RTCPrcvBfrList,
  100. (PLINK_LIST)pRcvStruct,
  101. &pRTCP->critSect);
  102. }
  103. else
  104. {
  105. wsockSuccess = TRUE;
  106. // increment number of I/O pending
  107. InterlockedIncrement ((long *)&pRTCP->dwNumRcvIoPending);
  108. }
  109. }
  110. else
  111. {
  112. wsockSuccess = TRUE;
  113. // increment number of I/O pending
  114. InterlockedIncrement ((long *)&pRTCP->dwNumRcvIoPending);
  115. }
  116. }
  117. // make sure we posted at least some buffers
  118. if (wsockSuccess == FALSE)
  119. {
  120. // release all resources and kill the receive thread
  121. #ifdef _DEBUG
  122. wsprintf(debug_string,
  123. "RTCP: ERROR - Exit RCV init %s: Line:%d", __FILE__, __LINE__);
  124. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  125. #endif
  126. return(FALSE);
  127. }
  128. return (TRUE);
  129. }
  130. /*----------------------------------------------------------------------------
  131. * Function : RTCPrcvCallback
  132. * Description: Receive callback routine from Winsock2.
  133. *
  134. * Input : dwError: I/O completion status
  135. * cbTransferred: Number of bytes received
  136. * lpOverlapped: -> to overlapped structure
  137. * dwFlags: Flags
  138. *
  139. *
  140. * Return: None
  141. ---------------------------------------------------------------------------*/
  142. void CALLBACK RTCPrcvCallback (DWORD dwError,
  143. DWORD cbTransferred,
  144. LPWSAOVERLAPPED lpOverlapped,
  145. DWORD dwFlags)
  146. {
  147. PRTCP_BFR_LIST pRcvStruct;
  148. RTCP_T *pRTCPpckt;
  149. PRTCP_SESSION pRTCPses;
  150. PSSRC_ENTRY pSSRC;
  151. PAPP_RTCP_BFR pAppBfr;
  152. DWORD dwStatus = 0;
  153. DWORD i;
  154. DWORD pcktLen;
  155. DWORD dwSSRC;
  156. USHORT wHost;
  157. SOCKET RTCPsd;
  158. unsigned char *pEndPckt;
  159. unsigned char *pEndBlock;
  160. int tmpSize;
  161. #if IO_CHECK
  162. DWORD initTime = timeGetTime();
  163. #endif
  164. IN_OUT_STR ("RTCP: Enter RTCPrcvCallback\n");
  165. // hEvent in the WSAOVERLAPPED struct points to our buffer's information
  166. pRcvStruct = (PRTCP_BFR_LIST)lpOverlapped->hEvent;
  167. // SSRC entry pointer
  168. pSSRC = pRcvStruct->pSSRC;
  169. // check Winsock callback error status
  170. if (dwError)
  171. {
  172. // 65534 is probably a temporary bug in WS2
  173. if ((dwError == 65534) || (dwError == WSA_OPERATION_ABORTED))
  174. {
  175. RRCM_DBG_MSG ("RTCP: I/O Aborted", dwError,
  176. __FILE__, __LINE__, DBG_NOTIFY);
  177. }
  178. else
  179. {
  180. RRCM_DBG_MSG ("RTCP: ERROR - Rcv Callback", dwError,
  181. __FILE__, __LINE__, DBG_ERROR);
  182. }
  183. // invalid RTCP packet header, re-queue the buffer
  184. RTCPpostRecvBfr (pSSRC, pRcvStruct);
  185. IN_OUT_STR ("RTCP: Exit RTCPrcvCallback\n");
  186. return;
  187. }
  188. // read the RTCP packet
  189. pRTCPpckt = (RTCP_T *)pRcvStruct->bfr.buf;
  190. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  191. //INTEROP
  192. if (RTPLogger)
  193. {
  194. InteropOutput (RTPLogger,
  195. (BYTE FAR*)(pRcvStruct->bfr.buf),
  196. cbTransferred,
  197. RTPLOG_RECEIVED_PDU | RTCP_PDU);
  198. }
  199. #endif
  200. // get the RTCP session ptr
  201. pRTCPses = pSSRC->pRTCPses;
  202. // Check RTCP header validity of first packet in report.
  203. // Filter out junk. First thing in RTCP packet must be
  204. // either SR, RR or BYE
  205. if ((pRTCPpckt->common.type != RTP_TYPE) ||
  206. ((pRTCPpckt->common.pt != RTCP_SR) &&
  207. (pRTCPpckt->common.pt != RTCP_RR) &&
  208. (pRTCPpckt->common.pt != RTCP_BYE)))
  209. {
  210. #ifdef MONITOR_STATS
  211. pRTCPses->dwNumRTCPhdrErr++;
  212. #endif
  213. // invalid RTCP packet header, re-queue the buffer
  214. RTCPpostRecvBfr (pSSRC, pRcvStruct);
  215. #if 0 // we could have shutdown so this code can fault
  216. if (pRTCPpckt->common.pt == FLUSH_RTP_PAYLOAD_TYPE)
  217. {
  218. RRCM_DBG_MSG ("RTCP: Flushing RCV I/O", 0, NULL, 0, DBG_NOTIFY);
  219. }
  220. else
  221. {
  222. wsprintf(debug_string,
  223. "RTCP: ERROR - Pckt Header Error. Type:%d / Payload:%d",
  224. pRTCPpckt->common.type, pRTCPpckt->common.pt);
  225. RRCM_DBG_MSG (debug_string, 0, __FILE__, __LINE__, DBG_TRACE);
  226. }
  227. #endif
  228. IN_OUT_STR ("RTCP: Exit RTCPrcvCallback\n");
  229. return;
  230. }
  231. // get the socket descriptor
  232. RTCPsd = pSSRC->RTCPsd;
  233. // get the sender's SSRC
  234. RRCMws.ntohl (RTCPsd, pRTCPpckt->r.sr.ssrc, &dwSSRC);
  235. // skip our own loopback if we receive it
  236. if (ownLoopback (RTCPsd, dwSSRC, pRTCPses))
  237. {
  238. RTCPpostRecvBfr (pSSRC, pRcvStruct);
  239. return;
  240. }
  241. // at this point we think the RTCP packet's valid. Get the sender's
  242. // address, if not already known
  243. if (!(pRTCPses->dwSessionStatus & RTCP_DEST_LEARNED))
  244. {
  245. pRTCPses->dwSessionStatus |= RTCP_DEST_LEARNED;
  246. pRTCPses->toLen = pRcvStruct->addrLen;
  247. memcpy (&pRTCPses->toBfr, &pRcvStruct->addr, pRcvStruct->addrLen);
  248. #ifdef ENABLE_ISDM2
  249. // register our Xmt SSRC - Rcvd one will be found later
  250. if (Isdm2.hISDMdll)
  251. registerSessionToISDM (pSSRC, pRTCPses, &Isdm2);
  252. #endif
  253. }
  254. // Update our RTCP average packet size estimator
  255. EnterCriticalSection (&pRTCPses->critSect);
  256. tmpSize = (cbTransferred + NTWRK_HDR_SIZE) - pRTCPses->avgRTCPpktSizeRcvd;
  257. #ifdef ENABLE_FLOATING_POINT
  258. // As per RFC
  259. tmpSize = (int)(tmpSize * RTCP_SIZE_GAIN);
  260. #else
  261. // Need to remove floating point operation
  262. tmpSize = tmpSize / 16;
  263. #endif
  264. pRTCPses->avgRTCPpktSizeRcvd += tmpSize;
  265. LeaveCriticalSection (&pRTCPses->critSect);
  266. // check if the raw RTCP packet needs to be copied into an application
  267. // buffer - Mainly used by ActiveMovieRTP to propagate the reports up
  268. // the filter graph to the Receive Payload Handler
  269. pAppBfr = (PAPP_RTCP_BFR)removePcktFromHead (&(pRTCPses->appRtcpBfrList),
  270. &pRTCPses->critSect);
  271. if (pAppBfr && !(pAppBfr->dwBfrStatus & RTCP_SR_ONLY))
  272. {
  273. // copy the full RTCP packet
  274. memcpy (pAppBfr->bfr,
  275. pRTCPpckt,
  276. MIN(pAppBfr->dwBfrLen, cbTransferred));
  277. // number of bytes received
  278. pAppBfr->dwBytesRcvd = MIN(pAppBfr->dwBfrLen, cbTransferred);
  279. // set the event associated with this buffer
  280. SetEvent (pAppBfr->hBfrEvent);
  281. }
  282. // end of the received packet
  283. pEndPckt = (unsigned char *)pRTCPpckt + cbTransferred;
  284. while ((unsigned char *)pRTCPpckt < pEndPckt)
  285. {
  286. // get the length
  287. dwStatus = RRCMws.ntohs (RTCPsd, pRTCPpckt->common.length, &wHost);
  288. if (dwStatus)
  289. {
  290. RRCM_DBG_MSG ("RTCP: ERROR - WSANtohs()", GetLastError(),
  291. __FILE__, __LINE__, DBG_ERROR);
  292. }
  293. // get this report block length
  294. pcktLen = (wHost + 1) << 2;
  295. pEndBlock = (unsigned char *)pRTCPpckt + pcktLen;
  296. // sanity check
  297. if (pEndBlock > pEndPckt)
  298. {
  299. RRCM_DBG_MSG ("RTCP: ERROR - Rcv packet length error", 0,
  300. __FILE__, __LINE__, DBG_ERROR);
  301. #ifdef MONITOR_STATS
  302. pRTCPses->dwNumRTCPlenErr++;
  303. #endif
  304. break;
  305. }
  306. // make sure the version is correct for all packets
  307. if (pRTCPpckt->common.type != RTP_TYPE)
  308. {
  309. #ifdef MONITOR_STATS
  310. pRTCPses->dwNumRTCPhdrErr++;
  311. #endif
  312. // invalid RTCP packet header, packet will be re-queued
  313. break;
  314. }
  315. switch (pRTCPpckt->common.pt)
  316. {
  317. case RTCP_SR:
  318. // check if only the SR needs to be propagated up to the app
  319. if (pAppBfr && (pAppBfr->dwBfrStatus & RTCP_SR_ONLY))
  320. {
  321. // copy the RTCP SR
  322. memcpy (pAppBfr->bfr,
  323. pRTCPpckt,
  324. MIN(pAppBfr->dwBfrLen, 24));
  325. // number of bytes received
  326. pAppBfr->dwBytesRcvd = MIN(pAppBfr->dwBfrLen, 24);
  327. // set the event associated with this buffer
  328. SetEvent (pAppBfr->hBfrEvent);
  329. }
  330. // get the sender's SSRC
  331. RRCMws.ntohl (RTCPsd, pRTCPpckt->r.sr.ssrc, &dwSSRC);
  332. // parse the sender report
  333. parseRTCPsr (RTCPsd, pRTCPpckt, pRTCPses, pRcvStruct);
  334. // parse additional receiver reports if any
  335. for (i = 0; i < pRTCPpckt->common.count; i++)
  336. {
  337. parseRTCPrr (RTCPsd, &pRTCPpckt->r.sr.rr[i],
  338. pRTCPses, pRcvStruct,
  339. dwSSRC);
  340. }
  341. // notify application if interested
  342. RRCMnotification (RRCM_RECV_RTCP_SNDR_REPORT_EVENT, pSSRC,
  343. dwSSRC, 0);
  344. break;
  345. case RTCP_RR:
  346. // get the sender's SSRC
  347. RRCMws.ntohl (RTCPsd, pRTCPpckt->r.rr.ssrc, &dwSSRC);
  348. // parse receiver reports
  349. for (i = 0; i < pRTCPpckt->common.count; i++)
  350. {
  351. parseRTCPrr (RTCPsd, &pRTCPpckt->r.rr.rr[i],
  352. pRTCPses, pRcvStruct,
  353. dwSSRC);
  354. }
  355. // notify application if interested
  356. RRCMnotification (RRCM_RECV_RTCP_RECV_REPORT_EVENT, pSSRC,
  357. dwSSRC, 0);
  358. break;
  359. case RTCP_SDES:
  360. {
  361. PCHAR buf;
  362. buf = (PCHAR)&pRTCPpckt->r.sdes;
  363. for (i = 0; i < pRTCPpckt->common.count; i++)
  364. {
  365. buf = parseRTCPsdes (RTCPsd, buf, pRTCPses, pRcvStruct);
  366. if (buf == NULL)
  367. break;
  368. }
  369. }
  370. break;
  371. case RTCP_BYE:
  372. for (i = 0; i < pRTCPpckt->common.count; i++)
  373. parseRTCPbye (RTCPsd, pRTCPpckt->r.bye.src[i],
  374. pRTCPses, pRcvStruct);
  375. break;
  376. default:
  377. break;
  378. }
  379. // go to next report block
  380. pRTCPpckt = (RTCP_T *)(pEndBlock);
  381. }
  382. // post back the buffer to WS-2
  383. RTCPpostRecvBfr (pSSRC, pRcvStruct);
  384. #if IO_CHECK
  385. wsprintf(debug_string,
  386. "RTCP: Leaving Rcv Callback after: %ld msec\n",
  387. timeGetTime() - initTime);
  388. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  389. #endif
  390. IN_OUT_STR ("RTCP: Exit RTCPrcvCallback\n");
  391. }
  392. /*----------------------------------------------------------------------------
  393. * Function : parseRTCPsr
  394. * Description: Parse an RTCP sender reports and update the corresponding
  395. * statistics.
  396. *
  397. * Input : sd: RTCP Socket descriptor
  398. * pRTCPpckt: -> to the RTCP packet
  399. * pRTCPses: -> to the RTCP session information
  400. * pRcvStruct: -> to the receive structure information
  401. *
  402. * Return: OK: RRCM_NoError
  403. * !0: Error code (see RRCM.H)
  404. ---------------------------------------------------------------------------*/
  405. DWORD parseRTCPsr (SOCKET sd,
  406. RTCP_T *pRTCPpckt,
  407. PRTCP_SESSION pRTCPses,
  408. PRTCP_BFR_LIST pRcvStruct)
  409. {
  410. PSSRC_ENTRY pSSRC;
  411. DWORD dwSSRC;
  412. IN_OUT_STR ("RTCP: Enter parseRTCPsr\n");
  413. // get the sender's SSRC
  414. RRCMws.ntohl (sd, pRTCPpckt->r.sr.ssrc, &dwSSRC);
  415. #ifdef _DEBUG
  416. wsprintf(debug_string, "RTCP: Receive SR from SSRC:x%lX", dwSSRC);
  417. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  418. #endif
  419. // look for the SSRC entry in the list for this RTCP session
  420. pSSRC = searchforSSRCatTail((PSSRC_ENTRY)pRTCPses->RcvSSRCList.prev,
  421. dwSSRC);
  422. if (pSSRC == NULL)
  423. {
  424. // new SSRC, create an entry in this RTCP session
  425. pSSRC = createSSRCEntry(dwSSRC,
  426. pRTCPses,
  427. (PSOCKADDR)pRcvStruct->addr,
  428. (DWORD)pRcvStruct->addrLen,
  429. FALSE);
  430. if (pSSRC == NULL)
  431. {
  432. // cannot create a new entry, out of resources
  433. RRCM_DBG_MSG ("RTCP: ERROR - Resource allocation", 0,
  434. __FILE__, __LINE__, DBG_ERROR);
  435. IN_OUT_STR ("RTCP: Exit parseRTCPsr\n");
  436. return (RRCMError_RTCPResources);
  437. }
  438. // notify application if it desired so
  439. RRCMnotification (RRCM_NEW_SOURCE_EVENT, pSSRC, dwSSRC,
  440. UNKNOWN_PAYLOAD_TYPE);
  441. }
  442. // get the RTP timestamp
  443. RRCMws.ntohl (sd, pRTCPpckt->r.sr.rtp_ts, &pSSRC->xmtInfo.dwRTPts);
  444. // number of packets send
  445. RRCMws.ntohl (sd, pRTCPpckt->r.sr.psent, &pSSRC->xmtInfo.dwNumPcktSent);
  446. // number of bytes sent
  447. RRCMws.ntohl (sd, pRTCPpckt->r.sr.osent, &pSSRC->xmtInfo.dwNumBytesSent);
  448. // get the NTP most significant word
  449. RRCMws.ntohl (sd, pRTCPpckt->r.sr.ntp_sec, &pSSRC->xmtInfo.dwNTPmsw);
  450. // get the NTP least significant word
  451. RRCMws.ntohl (sd, pRTCPpckt->r.sr.ntp_frac, &pSSRC->xmtInfo.dwNTPlsw);
  452. // last SR timestamp (middle 32 bits of the NTP timestamp)
  453. pSSRC->xmtInfo.dwLastSR = ((pSSRC->xmtInfo.dwNTPmsw & 0x0000FFFF) << 16);
  454. pSSRC->xmtInfo.dwLastSR |= ((pSSRC->xmtInfo.dwNTPlsw & 0xFFFF0000) >> 16);
  455. // last time this SSRC's heard
  456. pSSRC->dwLastReportRcvdTime = pSSRC->xmtInfo.dwLastSRLocalTime =
  457. timeGetTime();
  458. // get the source address information
  459. if (!(pSSRC->dwSSRCStatus & NETWK_ADDR_UPDATED))
  460. {
  461. saveNetworkAddress(pSSRC,
  462. (PSOCKADDR)pRcvStruct->addr,
  463. pRcvStruct->addrLen);
  464. }
  465. // increment the number of report received from this SSRC
  466. InterlockedIncrement ((long *)&pSSRC->dwNumRptRcvd);
  467. #ifdef ENABLE_ISDM2
  468. // update ISDM
  469. if (Isdm2.hISDMdll && pRTCPses->hSessKey)
  470. {
  471. if (pSSRC->hISDM)
  472. updateISDMstat (pSSRC, &Isdm2, RECVR, FALSE);
  473. else
  474. registerSessionToISDM (pSSRC, pRTCPses, &Isdm2);
  475. }
  476. #endif
  477. IN_OUT_STR ("RTCP: Exit parseRTCPsr\n");
  478. return (RRCM_NoError);
  479. }
  480. /*----------------------------------------------------------------------------
  481. * Function : parseRTCPrr
  482. * Description: Parse an RTCP receiver reports and update the corresponding
  483. * statistics.
  484. *
  485. * Input : sd: RTCP socket descriptor
  486. * pRR: -> to receiver report buffer
  487. * pRTCPses: -> to the RTCP session information
  488. * pRcvStruct: -> to the receive structure information
  489. * senderSSRC: Sender's SSRC
  490. *
  491. * Return: OK: RRCM_NoError
  492. * !0: Error code (see RRCM.H)
  493. ---------------------------------------------------------------------------*/
  494. DWORD parseRTCPrr (SOCKET sd,
  495. RTCP_RR_T *pRR,
  496. PRTCP_SESSION pRTCPses,
  497. PRTCP_BFR_LIST pRcvStruct,
  498. DWORD senderSSRC)
  499. {
  500. PSSRC_ENTRY pSSRC;
  501. DWORD dwSSRC;
  502. DWORD dwGetFeedback = FALSE;
  503. IN_OUT_STR ("RTCP: Enter parseRTCPrr\n");
  504. #ifdef _DEBUG
  505. wsprintf(debug_string,
  506. "RTCP: Receive RR from sender SSRC:x%lX", senderSSRC);
  507. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  508. #endif
  509. // get the receiver report SSRC
  510. RRCMws.ntohl (sd, pRR->ssrc, &dwSSRC);
  511. #ifdef _DEBUG
  512. wsprintf(debug_string, "RTCP: RR for SSRC:x%lX", dwSSRC);
  513. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  514. #endif
  515. //
  516. // NOTE:
  517. // For now we just keep track of feedback information about ourselve. Later
  518. // the link list can be used to keep track about everybody feedback
  519. // information.
  520. //
  521. // Check to see if we're interested in this report, ie, does this SSRC report
  522. // information about one of our active sender.
  523. dwGetFeedback =
  524. searchforSSRCatTail((PSSRC_ENTRY)pRTCPses->XmtSSRCList.prev,
  525. dwSSRC) != NULL;
  526. // look for the sender SSRC entry in the list for this RTCP session
  527. pSSRC =
  528. searchforSSRCatTail((PSSRC_ENTRY)pRTCPses->RcvSSRCList.prev,
  529. senderSSRC);
  530. if (pSSRC == NULL)
  531. {
  532. // new SSRC, create an entry in this RTCP session
  533. pSSRC = createSSRCEntry(senderSSRC,
  534. pRTCPses,
  535. (PSOCKADDR)pRcvStruct->addr,
  536. (DWORD)pRcvStruct->addrLen,
  537. FALSE);
  538. if (pSSRC == NULL)
  539. {
  540. // cannot create a new entry, out of resources
  541. RRCM_DBG_MSG ("RTCP: ERROR - Resource allocation", 0,
  542. __FILE__, __LINE__, DBG_ERROR);
  543. IN_OUT_STR ("RTCP: Exit parseRTCPrr\n");
  544. return (RRCMError_RTCPResources);
  545. }
  546. // notify application if it desired so
  547. RRCMnotification (RRCM_NEW_SOURCE_EVENT, pSSRC, senderSSRC,
  548. UNKNOWN_PAYLOAD_TYPE);
  549. }
  550. // update RR feedback information
  551. if (dwGetFeedback)
  552. updateRRfeedback (sd, senderSSRC, dwSSRC, pRR, pSSRC);
  553. // last time this SSRC's heard
  554. pSSRC->dwLastReportRcvdTime = timeGetTime();
  555. // get the source address information
  556. if (!(pSSRC->dwSSRCStatus & NETWK_ADDR_UPDATED))
  557. {
  558. saveNetworkAddress(pSSRC,
  559. (PSOCKADDR)pRcvStruct->addr,
  560. pRcvStruct->addrLen);
  561. }
  562. // increment the number of report received from this SSRC
  563. InterlockedIncrement ((long *)&pSSRC->dwNumRptRcvd);
  564. #ifdef ENABLE_ISDM2
  565. // update ISDM
  566. if (Isdm2.hISDMdll && pRTCPses->hSessKey)
  567. {
  568. if (pSSRC->hISDM)
  569. updateISDMstat (pSSRC, &Isdm2, RECVR, TRUE);
  570. else
  571. registerSessionToISDM (pSSRC, pRTCPses, &Isdm2);
  572. }
  573. #endif
  574. IN_OUT_STR ("RTCP: Exit parseRTCPrr\n");
  575. return (RRCM_NoError);
  576. }
  577. /*----------------------------------------------------------------------------
  578. * Function : parseRTCPsdes
  579. * Description: Parse an RTCP SDES packet
  580. *
  581. * Input : sd: RTCP socket descriptor
  582. * bfr: -> to SDES buffer
  583. * pRTCPses: -> to the RTCP session information
  584. * pRcvStruct: -> to the receive structure information
  585. *
  586. * Return: OK: RRCM_NoError
  587. * !0: Error code (see RRCM.H)
  588. ---------------------------------------------------------------------------*/
  589. PCHAR parseRTCPsdes (SOCKET sd,
  590. PCHAR bfr,
  591. PRTCP_SESSION pRTCPses,
  592. PRTCP_BFR_LIST pRcvStruct)
  593. {
  594. DWORD dwHost;
  595. DWORD ssrc = *(DWORD *)bfr;
  596. RTCP_SDES_ITEM_T *pSdes;
  597. PSSRC_ENTRY pSSRC;
  598. IN_OUT_STR ("RTCP: Enter parseRTCPsdes\n");
  599. // get the SSRC
  600. RRCMws.ntohl (sd, ssrc, &dwHost);
  601. #ifdef _DEBUG
  602. wsprintf(debug_string, "RTCP: Receive SDES from SSRC: x%lX", dwHost);
  603. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  604. #endif
  605. // look for the SSRC entry in the list for this RTCP session
  606. pSSRC = searchforSSRCatTail ((PSSRC_ENTRY)pRTCPses->RcvSSRCList.prev,
  607. dwHost);
  608. if (pSSRC == NULL)
  609. {
  610. #ifdef _DEBUG
  611. wsprintf(debug_string,
  612. "RTCP: SDES and SSRC (x%lX) not found for session (Addr x%p)",
  613. dwHost, pRTCPses);
  614. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  615. #endif
  616. // new SSRC, create an entry in this RTCP session
  617. pSSRC = createSSRCEntry(dwHost,
  618. pRTCPses,
  619. (PSOCKADDR)pRcvStruct->addr,
  620. (DWORD)pRcvStruct->addrLen,
  621. FALSE);
  622. if (pSSRC == NULL)
  623. {
  624. // cannot create a new entry, out of resources
  625. RRCM_DBG_MSG ("RTCP: ERROR - Resource allocation", 0,
  626. __FILE__, __LINE__, DBG_ERROR);
  627. IN_OUT_STR ("RTCP: Exit parseRTCPsdes\n");
  628. return (NULL);
  629. }
  630. // notify application if it desired so
  631. RRCMnotification (RRCM_NEW_SOURCE_EVENT, pSSRC, dwHost,
  632. UNKNOWN_PAYLOAD_TYPE);
  633. }
  634. // read the SDES chunk
  635. pSdes = (RTCP_SDES_ITEM_T *)(bfr + sizeof(DWORD));
  636. // go through until a 'type = 0' is found
  637. for (; pSdes->dwSdesType;
  638. pSdes = (RTCP_SDES_ITEM_T *)((char *)pSdes + pSdes->dwSdesLength + 2))
  639. {
  640. switch (pSdes->dwSdesType)
  641. {
  642. case RTCP_SDES_CNAME:
  643. if (pSSRC->cnameInfo.dwSdesLength == 0)
  644. {
  645. pSSRC->cnameInfo.dwSdesLength = pSdes->dwSdesLength;
  646. // get the Cname
  647. memcpy (pSSRC->cnameInfo.sdesBfr, pSdes->sdesData,
  648. min (pSdes->dwSdesLength, MAX_SDES_LEN-1));
  649. }
  650. else
  651. {
  652. // check to see for a loop/collision of the SSRC
  653. if (memcmp (pSdes->sdesData, pSSRC->cnameInfo.sdesBfr,
  654. min (pSdes->dwSdesLength, MAX_SDES_LEN-1)) != 0)
  655. {
  656. // loop/collision of a third-party detected
  657. pSSRC->dwSSRCStatus |= THIRD_PARTY_COLLISION;
  658. // notify application if interested
  659. RRCMnotification (RRCM_REMOTE_COLLISION_EVENT, pSSRC,
  660. pSSRC->SSRC, 0);
  661. // RTP & RTCP packet from this SSRC will be rejected
  662. // until the senders resolve the collision
  663. IN_OUT_STR ("RTCP: Exit parseRTCPsdes\n");
  664. return NULL;
  665. }
  666. }
  667. break;
  668. case RTCP_SDES_NAME:
  669. // the name can change, not like the Cname, so update it
  670. // every time.
  671. pSSRC->nameInfo.dwSdesLength = pSdes->dwSdesLength;
  672. // get the name
  673. memcpy (pSSRC->nameInfo.sdesBfr, pSdes->sdesData,
  674. min (pSdes->dwSdesLength, MAX_SDES_LEN-1));
  675. break;
  676. default:
  677. break;
  678. }
  679. }
  680. // last time this SSRC's heard
  681. pSSRC->dwLastReportRcvdTime = timeGetTime();
  682. // get the source address information
  683. if (!(pSSRC->dwSSRCStatus & NETWK_ADDR_UPDATED))
  684. {
  685. saveNetworkAddress(pSSRC,
  686. (PSOCKADDR)pRcvStruct->addr,
  687. pRcvStruct->addrLen);
  688. }
  689. // adjust pointer
  690. bfr = (char *)pSdes;
  691. IN_OUT_STR ("RTCP: Exit parseRTCPsdes\n");
  692. // go the next 32 bits boundary
  693. return bfr + ((4 - ((LONG_PTR)bfr & 0x3)) & 0x3);
  694. }
  695. /*----------------------------------------------------------------------------
  696. * Function : parseRTCPbye
  697. * Description: Parse an RTCP BYE packet
  698. *
  699. * Input : sd: RTCP socket descriptor
  700. * ssrc: SSRC
  701. * pRTCPses: -> to the RTCP session information
  702. * pRcvStruct: -> to the receive structure
  703. *
  704. * Return: OK: RRCM_NoError
  705. * !0: Error code (see RRCM.H)
  706. ---------------------------------------------------------------------------*/
  707. DWORD parseRTCPbye (SOCKET sd,
  708. DWORD ssrc,
  709. PRTCP_SESSION pRTCPses,
  710. PRTCP_BFR_LIST pRcvStruct)
  711. {
  712. DWORD dwStatus;
  713. DWORD dwHost;
  714. PSSRC_ENTRY pSSRC;
  715. IN_OUT_STR ("RTCP: Enter parseRTCPbye\n");
  716. RRCMws.ntohl (sd, ssrc, &dwHost);
  717. #ifdef _DEBUG
  718. wsprintf(debug_string, "RTCP: BYE from SSRC: x%lX", dwHost);
  719. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  720. #endif
  721. // find the SSRC entry
  722. pSSRC = searchforSSRCatTail((PSSRC_ENTRY)pRTCPses->RcvSSRCList.prev,
  723. dwHost);
  724. if (pSSRC == NULL)
  725. {
  726. #ifdef _DEBUG
  727. wsprintf(debug_string,
  728. "RTCP: SSRC: x%lX not found in session: x%p",
  729. dwHost, pRTCPses);
  730. RRCM_DBG_MSG (debug_string, 0, __FILE__, __LINE__, DBG_TRACE);
  731. IN_OUT_STR ("RTCP: Exit parseRTCPbye\n");
  732. #endif
  733. return (RRCM_NoError);
  734. }
  735. // make sure the BYE is coming from the expected source and not intruder
  736. if ((pRcvStruct->addrLen != pSSRC->fromLen) ||
  737. #if 0
  738. // There is a bug NT's Winsock2 implememtation. The unused bytes of
  739. // SOCKADDR are not reset to 0 as they should be. Work fine on W95
  740. // Temporarily just check the first 8 bytes, i.e. address family, port
  741. // and IP address.
  742. (memcmp (&pRcvStruct->addr, &pSSRC->from, pSSRC->fromLen)))
  743. #else
  744. (memcmp (&pRcvStruct->addr, &pSSRC->from, 8)))
  745. #endif
  746. return (RRCM_NoError);
  747. // notify application if interested
  748. RRCMnotification (RRCM_BYE_EVENT, pSSRC, dwHost, 0);
  749. // delete this SSRC from the list
  750. dwStatus = deleteSSRCEntry (dwHost, pRTCPses);
  751. #ifdef _DEBUG
  752. if (dwStatus == FALSE)
  753. {
  754. wsprintf(debug_string,
  755. "RTCP: SSRC: x%lX not found in session: x%p",
  756. dwHost, pRTCPses);
  757. RRCM_DBG_MSG (debug_string, 0, __FILE__, __LINE__, DBG_TRACE);
  758. }
  759. #endif
  760. IN_OUT_STR ("RTCP: Exit parseRTCPbye\n");
  761. return (RRCM_NoError);
  762. }
  763. /*----------------------------------------------------------------------------
  764. * Function : ownLoopback
  765. * Description: Determine if we receive our own loopback. We don't want to
  766. * create an entry for ourselve, as we're already in the list.
  767. *
  768. * Input : sd: RTCP socket descriptor
  769. * ssrc: SSRC
  770. * pRTCPses: -> to the RTCP session's information
  771. *
  772. * Return: TRUE: Our loopback
  773. * FALSE: No loopback
  774. ---------------------------------------------------------------------------*/
  775. DWORD ownLoopback (SOCKET sd,
  776. DWORD ssrc,
  777. PRTCP_SESSION pRTCPses)
  778. {
  779. PSSRC_ENTRY pSSRC;
  780. IN_OUT_STR ("RTCP: Enter ownLoopback\n");
  781. // don't create an entry if received our own xmit back
  782. pSSRC = searchforSSRCatTail((PSSRC_ENTRY)pRTCPses->XmtSSRCList.prev,
  783. ssrc);
  784. IN_OUT_STR ("RTCP: Exit ownLoopback\n");
  785. if (pSSRC)
  786. return TRUE;
  787. else
  788. return FALSE;
  789. }
  790. /*----------------------------------------------------------------------------
  791. * Function : updateRRfeedback
  792. * Description: Update the Receiver Report feedback for an active source
  793. *
  794. * Input : sd: RTCP socket descriptor
  795. * dwSndSSRC: Sender's SSRC
  796. * pRR: -> to receiver report entry
  797. * pSSRC: -> to the SSRC entry
  798. *
  799. * Return: TRUE
  800. ---------------------------------------------------------------------------*/
  801. DWORD updateRRfeedback (SOCKET sd,
  802. DWORD dwSndSSRC,
  803. DWORD dwSSRCfedback,
  804. RTCP_RR_T *pRR,
  805. PSSRC_ENTRY pSSRC)
  806. {
  807. DWORD dwHost;
  808. IN_OUT_STR ("RTCP: Enter updateRRfeedback\n");
  809. // Note when we last heard from the receiver
  810. pSSRC->rrFeedback.dwLastRcvRpt = timeGetTime();
  811. // SSRC who's feedback is for (ourselve for now)
  812. pSSRC->rrFeedback.SSRC = dwSSRCfedback;
  813. // get delay since last SR
  814. RRCMws.ntohl (sd, pRR->dlsr, &pSSRC->rrFeedback.dwDelaySinceLastSR);
  815. // get last SR
  816. RRCMws.ntohl (sd, pRR->lsr, &pSSRC->rrFeedback.dwLastSR);
  817. // get the jitter
  818. RRCMws.ntohl (sd, pRR->jitter, &pSSRC->rrFeedback.dwInterJitter);
  819. // highest sequence number received
  820. RRCMws.ntohl (sd, pRR->expected,
  821. &pSSRC->rrFeedback.XtendedSeqNum.seq_union.dwXtndedHighSeqNumRcvd);
  822. // fraction lost
  823. pSSRC->rrFeedback.fractionLost = (pRR->received & 0xFF);
  824. // cumulative number of packet lost
  825. RRCMws.ntohl (sd, pRR->received, &dwHost);
  826. dwHost &= 0x00FFFFFF;
  827. pSSRC->rrFeedback.cumNumPcktLost = dwHost;
  828. IN_OUT_STR ("RTCP: Exit updateRRfeedback\n");
  829. return TRUE;
  830. }
  831. /*----------------------------------------------------------------------------
  832. * Function : RTCPpostRecvBfr
  833. * Description: RTCP post a receive buffer to Winsock-2
  834. *
  835. * Input : sd: RTCP socket descriptor
  836. * pSSRC: -> to the SSRC entry
  837. *
  838. * Return: TRUE
  839. ---------------------------------------------------------------------------*/
  840. void RTCPpostRecvBfr (PSSRC_ENTRY pSSRC,
  841. PRTCP_BFR_LIST pRcvStruct)
  842. {
  843. DWORD dwStatus;
  844. DWORD dwError;
  845. IN_OUT_STR ("RTCP: Enter RTCPpostRecvBfr\n");
  846. // decrement number of I/O pending
  847. InterlockedDecrement ((long *)&pSSRC->pRTCPses->dwNumRcvIoPending);
  848. // don't repost any buffer if within the shutdown procedure
  849. if ((pSSRC->pRTCPses->dwSessionStatus & SHUTDOWN_IN_PROGRESS) &&
  850. (pSSRC->pRTCPses->dwNumRcvIoPending == 0))
  851. {
  852. // shutdown done - set event
  853. if (SetEvent (pSSRC->pRTCPses->hShutdownDone) == FALSE)
  854. {
  855. RRCM_DBG_MSG ("RTCP: SetEvent() Error\n", GetLastError(),
  856. __FILE__, __LINE__, DBG_ERROR);
  857. }
  858. IN_OUT_STR ("RTCP: Exit RTCPpostRecvBfr\n");
  859. return;
  860. }
  861. else if (pSSRC->pRTCPses->dwSessionStatus & SHUTDOWN_IN_PROGRESS)
  862. {
  863. IN_OUT_STR ("RTCP: Exit RTCPpostRecvBfr\n");
  864. return;
  865. }
  866. // clear number of bytes transferred
  867. pRcvStruct->dwNumBytesXfr = 0;
  868. dwStatus = RRCMws.recvFrom (pSSRC->RTCPsd,
  869. &pRcvStruct->bfr,
  870. pRcvStruct->dwBufferCount,
  871. &pRcvStruct->dwNumBytesXfr,
  872. &pRcvStruct->dwFlags,
  873. (PSOCKADDR)pRcvStruct->addr,
  874. &pRcvStruct->addrLen,
  875. (LPWSAOVERLAPPED)&pRcvStruct->overlapped,
  876. RTCPrcvCallback);
  877. // Check Winsock status
  878. if (dwStatus != 0)
  879. {
  880. // error, the receive request won't proceed
  881. dwError = GetLastError();
  882. if ((dwError != WSA_IO_PENDING) && (dwError != WSAEMSGSIZE))
  883. {
  884. RRCM_DBG_MSG ("RTCP: ERROR - WSARecvFrom()", dwError,
  885. __FILE__, __LINE__, DBG_ERROR);
  886. // notify application if interested
  887. RRCMnotification (RRCM_RTCP_WS_RCV_ERROR, pSSRC,
  888. pSSRC->SSRC, dwError);
  889. // Return the buffer to the free queue
  890. addToHeadOfList (&pSSRC->pRTCPses->RTCPrcvBfrList,
  891. (PLINK_LIST)pRcvStruct,
  892. &pSSRC->pRTCPses->critSect);
  893. }
  894. else
  895. {
  896. // increment number of I/O pending
  897. InterlockedIncrement ((long *)&pSSRC->pRTCPses->dwNumRcvIoPending);
  898. }
  899. }
  900. else
  901. {
  902. // synchronous completion - callback has been scheduled
  903. // increment number of I/O pending
  904. InterlockedIncrement ((long *)&pSSRC->pRTCPses->dwNumRcvIoPending);
  905. }
  906. IN_OUT_STR ("RTCP: Exit RTCPpostRecvBfr\n");
  907. }
  908. /*----------------------------------------------------------------------------
  909. * Function : addApplicationRtcpBfr
  910. * Description: Add an application provided buffer for RTCP to copy the
  911. * raw received reports to be used by the application if it
  912. * desired so.
  913. *
  914. * Input : RTPsession: Handle to the RTP session
  915. * pAppBfr: -> an application buffer data structure
  916. *
  917. * Return: TRUE
  918. ---------------------------------------------------------------------------*/
  919. HRESULT WINAPI addApplicationRtcpBfr (DWORD_PTR RTPsession,
  920. PAPP_RTCP_BFR pAppBfr)
  921. {
  922. IN_OUT_STR ("RTCP : Enter addApplicationRtcpBfr()\n");
  923. PRTP_SESSION pSession = (PRTP_SESSION)RTPsession;
  924. PRTCP_SESSION pRTCPSess;
  925. if (pSession == NULL)
  926. {
  927. RRCM_DBG_MSG ("RTCP : ERROR - Invalid RTP session", 0,
  928. __FILE__, __LINE__, DBG_ERROR);
  929. IN_OUT_STR ("RTCP : Exit addApplicationRtcpBfr()\n");
  930. return (MAKE_RRCM_ERROR(RRCMError_RTPSessResources));
  931. }
  932. pRTCPSess = (PRTCP_SESSION)pSession->pRTCPSession;
  933. if (pRTCPSess == NULL)
  934. {
  935. RRCM_DBG_MSG ("RTCP : ERROR - Invalid RTCP session", 0,
  936. __FILE__, __LINE__, DBG_ERROR);
  937. IN_OUT_STR ("RTCP : Exit addApplicationRtcpBfr()\n");
  938. return (MAKE_RRCM_ERROR(RRCMError_RTCPInvalidSession));
  939. }
  940. // Let's add this buffer to our list
  941. addToTailOfList(&(pRTCPSess->appRtcpBfrList),
  942. (PLINK_LIST)pAppBfr,
  943. &pRTCPSess->critSect);
  944. IN_OUT_STR ("RTCP : Exit addApplicationRtcpBfr()\n");
  945. return NOERROR;
  946. }
  947. /*----------------------------------------------------------------------------
  948. * Function : removeApplicationRtcpBfr
  949. * Description: Remove an application provided buffer to this RTCP session.
  950. *
  951. * Input : RTPsession: RTP session handle
  952. *
  953. * Return: Application buffer address / NULL
  954. ---------------------------------------------------------------------------*/
  955. PAPP_RTCP_BFR WINAPI removeApplicationRtcpBfr (DWORD_PTR RTPsession)
  956. {
  957. PRTP_SESSION pSession = (PRTP_SESSION)RTPsession;
  958. PRTCP_SESSION pRTCPSess;
  959. PAPP_RTCP_BFR pAppBfr;
  960. IN_OUT_STR ("RTCP : Enter removeApplicationRtcpBfr()\n");
  961. if (pSession == NULL)
  962. {
  963. RRCM_DBG_MSG ("RTCP : ERROR - Invalid RTP session", 0,
  964. __FILE__, __LINE__, DBG_ERROR);
  965. IN_OUT_STR ("RTCP : Exit removeApplicationRtcpBfr()\n");
  966. return NULL;
  967. }
  968. pRTCPSess = (PRTCP_SESSION)pSession->pRTCPSession;
  969. if (pRTCPSess == NULL)
  970. {
  971. RRCM_DBG_MSG ("RTCP : ERROR - Invalid RTCP session", 0,
  972. __FILE__, __LINE__, DBG_ERROR);
  973. IN_OUT_STR ("RTCP : Exit removeApplicationRtcpBfr()\n");
  974. return NULL;
  975. }
  976. pAppBfr = (PAPP_RTCP_BFR)removePcktFromHead (&(pRTCPSess->appRtcpBfrList),
  977. &pRTCPSess->critSect);
  978. IN_OUT_STR ("RTCP : Exit removeApplicationRtcpBfr()\n");
  979. return pAppBfr;
  980. }
  981. // [EOF]
  982. 
  983.