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.

1106 lines
41 KiB

  1. /*----------------------------------------------------------------------------
  2. * File: RTCPIO.C
  3. * Product: RTP/RTCP implementation
  4. * Description: Provides the RTCP 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. /*---------------------------------------------------------------------------
  14. / Global Variables
  15. /--------------------------------------------------------------------------*/
  16. #define DBG_CUM_FRACT_LOSS 0
  17. #define FRACTION_ENTRIES 10
  18. #define FRACTION_SHIFT_MAX 32
  19. long microSecondFrac [FRACTION_ENTRIES] = {500000,
  20. 250000,
  21. 125000,
  22. 62500,
  23. 31250,
  24. 15625,
  25. 7812, // some precision lost
  26. 3906, // some precision lost
  27. 1953, // some precision lost
  28. 976}; // ~ 1 milli second
  29. /*---------------------------------------------------------------------------
  30. / External Variables
  31. /--------------------------------------------------------------------------*/
  32. extern PRTCP_CONTEXT pRTCPContext;
  33. extern RRCM_WS RRCMws;
  34. #ifdef ENABLE_ISDM2
  35. extern ISDM2 Isdm2;
  36. #endif
  37. #ifdef _DEBUG
  38. extern char debug_string[];
  39. #endif
  40. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  41. //INTEROP
  42. extern LPInteropLogger RTPLogger;
  43. #endif
  44. /*----------------------------------------------------------------------------
  45. * Function : xmtRTCPreport
  46. * Description: RTCP report generator
  47. *
  48. * Input : pSSRC : -> to the SSRC entry
  49. *
  50. * Return: None.
  51. ---------------------------------------------------------------------------*/
  52. BOOL FormatRTCPReport (PRTCP_SESSION pRTCP,
  53. PSSRC_ENTRY pSSRC,
  54. DWORD curTime)
  55. {
  56. PLINK_LIST pTmp;
  57. RTCP_COMMON_T *pRTCPhdr;
  58. RTCP_RR_T *pRTCPrr;
  59. RECEIVER_RPT *pRTCPrecvr;
  60. SENDER_RPT *pRTCPsr;
  61. DWORD numRcvRpt;
  62. DWORD numSrc;
  63. SOCKET sd;
  64. DWORD dwTotalRtpBW = 0;
  65. PDWORD pLastWord;
  66. SDES_DATA sdesBfr[MAX_NUM_SDES];
  67. PCHAR pData;
  68. unsigned short pcktLen;
  69. int weSent = FALSE;
  70. #ifdef _DEBUG
  71. DWORD timeDiff;
  72. #endif
  73. #ifdef ENABLE_ISDM2
  74. // update ISDM
  75. if (Isdm2.hISDMdll && pSSRC->hISDM)
  76. updateISDMstat (pSSRC, &Isdm2, XMITR, TRUE);
  77. #endif
  78. ASSERT (!pSSRC->dwNumXmtIoPending); // should only have one pending send
  79. if (pSSRC->dwNumXmtIoPending)
  80. return FALSE;
  81. memset (sdesBfr, 0x00, sizeof(SDES_DATA) * MAX_NUM_SDES);
  82. // lock out access to the SSRC entry
  83. EnterCriticalSection (&pSSRC->critSect);
  84. // socket descriptor
  85. sd = pSSRC->RTCPsd;
  86. // RTCP common header
  87. pRTCPhdr = (RTCP_COMMON_T *)pRTCP->XmtBfr.buf;
  88. // RTP protocol version
  89. pRTCPhdr->type = RTP_TYPE;
  90. // reset the flag
  91. weSent = 0;
  92. // SR or RR ? Check our Xmt list entry to know if we've sent data
  93. if (pSSRC->xmtInfo.dwCurXmtSeqNum != pSSRC->xmtInfo.dwPrvXmtSeqNum)
  94. {
  95. // set flag for Bw calculation
  96. weSent = TRUE;
  97. // update packet count
  98. pSSRC->xmtInfo.dwPrvXmtSeqNum = pSSRC->xmtInfo.dwCurXmtSeqNum;
  99. // build SR
  100. RTCPbuildSenderRpt (pSSRC, pRTCPhdr, &pRTCPsr, sd);
  101. // set the receiver report pointer
  102. pData = (PCHAR)(pRTCPsr + 1);
  103. // adjust for the additional structure defined in the SENDER_RPT
  104. pData -= sizeof (RTCP_RR_T);
  105. pRTCPrr = (RTCP_RR_T *)pData;
  106. #ifdef DYNAMIC_RTCP_BW
  107. // calculate the RTP bandwidth used by this transmitter
  108. dwTotalRtpBW = updateRtpXmtBW (pSSRC);
  109. #endif
  110. }
  111. else
  112. {
  113. // payload type, RR
  114. pRTCPhdr->pt = RTCP_RR;
  115. // set the receiver report pointer
  116. pRTCPrecvr = (RECEIVER_RPT *)(pRTCPhdr + 1);
  117. // set our SSRC as the originator of this report
  118. RRCMws.htonl (sd, pSSRC->SSRC, &pRTCPrecvr->ssrc);
  119. pRTCPrr = pRTCPrecvr->rr;
  120. }
  121. // build receiver report list
  122. numRcvRpt = 0;
  123. numSrc = 0;
  124. // go through the received SSRCs list
  125. pTmp = pRTCP->RcvSSRCList.prev;
  126. while (pTmp)
  127. {
  128. // increment the number of sources for later time-out calculation
  129. numSrc++;
  130. // check to see if this entry is an active sender
  131. if (((PSSRC_ENTRY)pTmp)->rcvInfo.dwNumPcktRcvd ==
  132. ((PSSRC_ENTRY)pTmp)->rcvInfo.dwPrvNumPcktRcvd)
  133. {
  134. // not an active source, don't include it in the RR
  135. pTmp = pTmp->next;
  136. // next entry in SSRC list
  137. continue;
  138. }
  139. // build RR
  140. RTCPbuildReceiverRpt ((PSSRC_ENTRY)pTmp, pRTCPrr, sd);
  141. #ifdef DYNAMIC_RTCP_BW
  142. // calculate the RTP bandwidth used by this remote stream
  143. dwTotalRtpBW += updateRtpRcvBW ((PSSRC_ENTRY)pTmp);
  144. #endif
  145. // next entry in receiver report
  146. pRTCPrr++;
  147. // next entry in SSRC list
  148. pTmp = pTmp->next;
  149. if (++numRcvRpt >= MAX_RR_ENTRIES)
  150. // !!! TODO !!!
  151. // When over 31 sources, generate a second packet or go round robin
  152. break;
  153. }
  154. // check to see if any Receiver Report. If not, still send an empty RR,
  155. // that will be followed by an SDES CNAME, for case like initialization
  156. // time, or when no stream received yet
  157. if ((numRcvRpt == 0) && (weSent == TRUE))
  158. {
  159. // adjust to the right place
  160. pRTCPrr = (RTCP_RR_T *)pData;
  161. }
  162. // report count
  163. pRTCPhdr->count = (WORD)numRcvRpt;
  164. // packet length for the previous SR/RR
  165. pcktLen = (unsigned short)((char *)pRTCPrr - pRTCP->XmtBfr.buf);
  166. RRCMws.htons (sd, (WORD)((pcktLen >> 2) - 1), &pRTCPhdr->length);
  167. // check which SDES needs to be send
  168. RTCPcheckSDEStoXmit (pSSRC, sdesBfr);
  169. // build the SDES information
  170. pLastWord = RTCPbuildSDES ((RTCP_COMMON_T *)pRTCPrr, pSSRC, sd,
  171. pRTCP->XmtBfr.buf, sdesBfr);
  172. // calculate total RTCP packet length to xmit
  173. pRTCP->XmtBfr.len = (u_long)((char *)pLastWord - pRTCP->XmtBfr.buf);
  174. if ( ! (pSSRC->dwSSRCStatus & RTCP_XMT_USER_CTRL))
  175. {
  176. #ifdef DYNAMIC_RTCP_BW
  177. // get 5% of the total RTP bandwidth
  178. dwTotalRtpBW = (dwTotalRtpBW * 5) / 100;
  179. // calculate the next interval based upon RTCP parameters
  180. if (dwTotalRtpBW < pSSRC->xmtInfo.dwRtcpStreamMinBW)
  181. {
  182. dwTotalRtpBW = pSSRC->xmtInfo.dwRtcpStreamMinBW;
  183. }
  184. #ifdef _DEBUG
  185. wsprintf(debug_string, "RTCP: RTCP BW (Bytes/sec) = %ld", dwTotalRtpBW);
  186. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  187. #endif
  188. #else
  189. dwTotalRtpBW = pSSRC->xmtInfo.dwRtcpStreamMinBW;
  190. #endif
  191. pSSRC->dwNextReportSendTime = curTime + RTCPxmitInterval (numSrc + 1,
  192. numRcvRpt,
  193. dwTotalRtpBW,
  194. weSent,
  195. (int)(pRTCP->XmtBfr.len + NTWRK_HDR_SIZE),
  196. &pRTCP->avgRTCPpktSizeRcvd,
  197. 0);
  198. }
  199. else
  200. {
  201. // user's control of the RTCP timeout interval
  202. if (pSSRC->dwUserXmtTimeoutCtrl != RTCP_XMT_OFF)
  203. {
  204. pSSRC->dwNextReportSendTime =
  205. timeGetTime() + pSSRC->dwUserXmtTimeoutCtrl;
  206. }
  207. else
  208. {
  209. pSSRC->dwNextReportSendTime = RTCP_XMT_OFF;
  210. }
  211. }
  212. #ifdef _DEBUG
  213. timeDiff = curTime - pSSRC->dwPrvTime;
  214. pSSRC->dwPrvTime = curTime;
  215. wsprintf(debug_string,
  216. "RTCP: Sent report #%ld for SSRC x%lX after %5ld msec - (%s) w/ %d RR",
  217. pSSRC->dwNumRptSent,
  218. pSSRC->SSRC,
  219. timeDiff,
  220. (weSent==TRUE) ? "SR": "RR",
  221. numRcvRpt);
  222. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  223. #endif
  224. // unlock pointer access
  225. LeaveCriticalSection (&pSSRC->critSect);
  226. return TRUE;
  227. }
  228. /*----------------------------------------------------------------------------
  229. * Function : getSSRCpcktLoss
  230. * Description: Calculate the packet loss fraction and cumulative number.
  231. *
  232. * Input : pSSRC: -> to SSRC entry
  233. * update: Flag. Update the number received, or just calculate the
  234. * number of packet lost w/o updating the counters.
  235. *
  236. *
  237. * Return: Fraction Lost: Number of packet lost (8:24)
  238. ---------------------------------------------------------------------------*/
  239. DWORD getSSRCpcktLoss (PSSRC_ENTRY pSSRC,
  240. DWORD update)
  241. {
  242. DWORD expected;
  243. DWORD expectedInterval;
  244. DWORD rcvdInterval;
  245. int lostInterval;
  246. DWORD fraction;
  247. DWORD cumLost;
  248. DWORD dwTmp;
  249. IN_OUT_STR ("RTCP: Enter getSSRCpcktLoss()\n");
  250. // if nothing has been received, there is no loss
  251. if (pSSRC->rcvInfo.dwNumPcktRcvd == 0)
  252. {
  253. IN_OUT_STR ("RTCP: Exit getSSRCpcktLoss()\n");
  254. return 0;
  255. }
  256. // as per the RFC, but always one packet off when doing it ???
  257. expected = pSSRC->rcvInfo.XtendedSeqNum.seq_union.dwXtndedHighSeqNumRcvd -
  258. pSSRC->rcvInfo.dwBaseRcvSeqNum + 1;
  259. cumLost = expected - pSSRC->rcvInfo.dwNumPcktRcvd;
  260. // 24 bits value
  261. cumLost &= 0x00FFFFFF;
  262. #if DBG_CUM_FRACT_LOSS
  263. wsprintf(debug_string, "RTCP : High Seq. #: %ld - Base: %ld",
  264. pSSRC->rcvInfo.XtendedSeqNum.seq_union.dwXtndedHighSeqNumRcvd,
  265. pSSRC->rcvInfo.dwBaseRcvSeqNum + 1);
  266. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  267. wsprintf(debug_string, "RTCP : Expected: %ld - CumLost: %ld",
  268. expected,
  269. cumLost);
  270. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  271. #endif
  272. // Network byte order the lost number (will be or'ed with the fraction)
  273. RRCMws.htonl (pSSRC->RTPsd, cumLost, &dwTmp);
  274. cumLost = dwTmp;
  275. // fraction lost (per RFC)
  276. expectedInterval = expected - pSSRC->rcvInfo.dwExpectedPrior;
  277. rcvdInterval =
  278. pSSRC->rcvInfo.dwNumPcktRcvd - pSSRC->rcvInfo.dwPrvNumPcktRcvd;
  279. #if DBG_CUM_FRACT_LOSS
  280. wsprintf(debug_string, "RTCP : Exp. interval: %ld - Rcv interval: %ld",
  281. expectedInterval,
  282. rcvdInterval);
  283. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  284. #endif
  285. // check if need to update the data, or just calculate the loss
  286. if (update)
  287. {
  288. pSSRC->rcvInfo.dwExpectedPrior = expected;
  289. pSSRC->rcvInfo.dwPrvNumPcktRcvd = pSSRC->rcvInfo.dwNumPcktRcvd;
  290. }
  291. lostInterval = expectedInterval - rcvdInterval;
  292. if (expectedInterval == 0 || lostInterval <= 0)
  293. fraction = 0;
  294. else
  295. {
  296. fraction = (lostInterval << 8) / expectedInterval;
  297. // 8 bits value
  298. if (fraction > 0x000000FF)
  299. // 100 % loss
  300. fraction = 0x000000FF;
  301. fraction &= 0x000000FF;
  302. }
  303. #if DBG_CUM_FRACT_LOSS
  304. wsprintf(debug_string, "RTCP : Lost interval: %ld - Fraction: %ld",
  305. lostInterval,
  306. fraction);
  307. RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
  308. #endif
  309. // get the 32 bits fraction/number
  310. cumLost |= fraction;
  311. IN_OUT_STR ("RTCP: Exit getSSRCpcktLoss()\n");
  312. return cumLost;
  313. }
  314. /*----------------------------------------------------------------------------
  315. * Function : RTCPcheckSDEStoXmit
  316. * Description: Check which SDES needs to be transmitted with this report.
  317. * SDES frequency varies for each type and is defined by the
  318. * application.
  319. *
  320. * Input : pSSRC: -> to the SSRC entry
  321. * pSdes: -> to SDES buffer to initialize
  322. *
  323. * Return: None
  324. ---------------------------------------------------------------------------*/
  325. void RTCPcheckSDEStoXmit (PSSRC_ENTRY pSSRC,
  326. PSDES_DATA pSdes)
  327. {
  328. PSDES_DATA pTmpSdes = pSdes;
  329. IN_OUT_STR ("RTCP: Enter RTCPcheckSDEStoXmit()\n");
  330. if (pSSRC->cnameInfo.dwSdesFrequency)
  331. {
  332. if ((pSSRC->dwNumRptSent % pSSRC->cnameInfo.dwSdesFrequency) == 0)
  333. {
  334. // CNAME
  335. pTmpSdes->dwSdesType = RTCP_SDES_CNAME;
  336. pTmpSdes->dwSdesLength = pSSRC->cnameInfo.dwSdesLength;
  337. memcpy (pTmpSdes->sdesBfr, pSSRC->cnameInfo.sdesBfr,
  338. pSSRC->cnameInfo.dwSdesLength);
  339. }
  340. }
  341. pTmpSdes++;
  342. if (pSSRC->nameInfo.dwSdesFrequency)
  343. {
  344. if ((pSSRC->dwNumRptSent % pSSRC->nameInfo.dwSdesFrequency) == 0)
  345. {
  346. // NAME
  347. pTmpSdes->dwSdesType = RTCP_SDES_NAME;
  348. pTmpSdes->dwSdesLength = pSSRC->nameInfo.dwSdesLength;
  349. memcpy (pTmpSdes->sdesBfr, pSSRC->nameInfo.sdesBfr,
  350. pSSRC->nameInfo.dwSdesLength);
  351. }
  352. }
  353. pTmpSdes++;
  354. if (pSSRC->emailInfo.dwSdesFrequency)
  355. {
  356. if ((pSSRC->dwNumRptSent % pSSRC->emailInfo.dwSdesFrequency) == 0)
  357. {
  358. // EMAIL
  359. pTmpSdes->dwSdesType = RTCP_SDES_EMAIL;
  360. pTmpSdes->dwSdesLength = pSSRC->emailInfo.dwSdesLength;
  361. memcpy (pTmpSdes->sdesBfr, pSSRC->emailInfo.sdesBfr,
  362. pSSRC->emailInfo.dwSdesLength);
  363. }
  364. }
  365. pTmpSdes++;
  366. if (pSSRC->phoneInfo.dwSdesFrequency)
  367. {
  368. if ((pSSRC->dwNumRptSent % pSSRC->phoneInfo.dwSdesFrequency) == 0)
  369. {
  370. // PHONE
  371. pTmpSdes->dwSdesType = RTCP_SDES_PHONE;
  372. pTmpSdes->dwSdesLength = pSSRC->phoneInfo.dwSdesLength;
  373. memcpy (pTmpSdes->sdesBfr, pSSRC->phoneInfo.sdesBfr,
  374. pSSRC->phoneInfo.dwSdesLength);
  375. }
  376. }
  377. pTmpSdes++;
  378. if (pSSRC->locInfo.dwSdesFrequency)
  379. {
  380. if ((pSSRC->dwNumRptSent % pSSRC->locInfo.dwSdesFrequency) == 0)
  381. {
  382. // LOCATION
  383. pTmpSdes->dwSdesType = RTCP_SDES_LOC;
  384. pTmpSdes->dwSdesLength = pSSRC->locInfo.dwSdesLength;
  385. memcpy (pTmpSdes->sdesBfr, pSSRC->locInfo.sdesBfr,
  386. pSSRC->locInfo.dwSdesLength);
  387. }
  388. }
  389. pTmpSdes++;
  390. if (pSSRC->toolInfo.dwSdesFrequency)
  391. {
  392. if ((pSSRC->dwNumRptSent % pSSRC->toolInfo.dwSdesFrequency) == 0)
  393. {
  394. // TOOL
  395. pTmpSdes->dwSdesType = RTCP_SDES_TOOL;
  396. pTmpSdes->dwSdesLength = pSSRC->toolInfo.dwSdesLength;
  397. memcpy (pTmpSdes->sdesBfr, pSSRC->toolInfo.sdesBfr,
  398. pSSRC->toolInfo.dwSdesLength);
  399. }
  400. }
  401. pTmpSdes++;
  402. if (pSSRC->txtInfo.dwSdesFrequency)
  403. {
  404. if ((pSSRC->dwNumRptSent % pSSRC->txtInfo.dwSdesFrequency) == 0)
  405. {
  406. // TEXT
  407. pTmpSdes->dwSdesType = RTCP_SDES_TXT;
  408. pTmpSdes->dwSdesLength = pSSRC->txtInfo.dwSdesLength;
  409. memcpy (pTmpSdes->sdesBfr, pSSRC->txtInfo.sdesBfr,
  410. pSSRC->txtInfo.dwSdesLength);
  411. }
  412. }
  413. pTmpSdes++;
  414. if (pSSRC->privInfo.dwSdesFrequency)
  415. {
  416. if ((pSSRC->dwNumRptSent % pSSRC->privInfo.dwSdesFrequency) == 0)
  417. {
  418. // PRIVATE
  419. pTmpSdes->dwSdesType = RTCP_SDES_PRIV;
  420. pTmpSdes->dwSdesLength = pSSRC->privInfo.dwSdesLength;
  421. memcpy (pTmpSdes->sdesBfr, pSSRC->privInfo.sdesBfr,
  422. pSSRC->privInfo.dwSdesLength);
  423. }
  424. }
  425. pTmpSdes++;
  426. pTmpSdes->dwSdesLength = 0;
  427. IN_OUT_STR ("RTCP: Exit RTCPcheckSDEStoXmit()\n");
  428. }
  429. /*----------------------------------------------------------------------------
  430. * Function : RTCPbuildSDES
  431. * Description: Build the SDES report
  432. *
  433. * Input : pRTCPhdr: -> to the RTCP packet header
  434. * pSSRC: -> to the SSRC entry
  435. * sd: Socket descriptor
  436. * startAddr: -> to the packet start address
  437. * pSdes: -> to the SDES information to build
  438. *
  439. * Return: pLastWord: Address of the packet last Dword
  440. ---------------------------------------------------------------------------*/
  441. PDWORD RTCPbuildSDES (RTCP_COMMON_T *pRTCPhdr,
  442. PSSRC_ENTRY pSSRC,
  443. SOCKET sd,
  444. PCHAR startAddr,
  445. PSDES_DATA pSdes)
  446. {
  447. RTCP_SDES_T *pRTCPsdes;
  448. RTCP_SDES_ITEM_T *pRTCPitem;
  449. int pad = 0;
  450. PCHAR ptr;
  451. unsigned short pcktLen;
  452. IN_OUT_STR ("RTCP: Enter RTCPbuildSDES()\n");
  453. // setup header
  454. pRTCPhdr->type = RTP_TYPE;
  455. pRTCPhdr->pt = RTCP_SDES;
  456. pRTCPhdr->p = 0;
  457. pRTCPhdr->count = 1;
  458. // SDES specific header
  459. pRTCPsdes = (RTCP_SDES_T *)(pRTCPhdr + 1);
  460. // Get the SSRC
  461. RRCMws.htonl (sd, pSSRC->SSRC, &pRTCPsdes->src);
  462. // SDES item
  463. pRTCPitem = (RTCP_SDES_ITEM_T *)pRTCPsdes->item;
  464. while (pSdes->dwSdesLength)
  465. {
  466. // set SDES item characteristics
  467. pRTCPitem->dwSdesType = (char)pSdes->dwSdesType;
  468. // make sure we don't go too far
  469. if (pSdes->dwSdesLength > MAX_SDES_LEN)
  470. pSdes->dwSdesLength = MAX_SDES_LEN;
  471. pRTCPitem->dwSdesLength = (unsigned char)(pSdes->dwSdesLength);
  472. memcpy (pRTCPitem->sdesData, pSdes->sdesBfr, pSdes->dwSdesLength);
  473. // packet length
  474. pcktLen =
  475. (unsigned short)((char *)(pRTCPitem->sdesData + pRTCPitem->dwSdesLength) - (char *)pRTCPsdes);
  476. pRTCPitem = (RTCP_SDES_ITEM_T *)((unsigned char *)pRTCPsdes + pcktLen);
  477. pSdes->dwSdesLength = 0; // setting this to zero will clear this entry
  478. // next SDES
  479. pSdes++;
  480. }
  481. // total SDES packet length
  482. pcktLen = (unsigned short)((char *)pRTCPitem - (char *)pRTCPhdr);
  483. // Zero the last word of the SDES item chunk, and padd to the
  484. // 32 bits boundary. If we landed exactly on the boundary then
  485. // have a whole null word to terminate the sdes, as is needed.
  486. pad = 4 - (pcktLen & 3);
  487. pcktLen += (unsigned short)pad;
  488. ptr = (PCHAR)pRTCPitem;
  489. while (pad--)
  490. *ptr++ = 0x00;
  491. // update packet length in header field
  492. RRCMws.htons (sd, (WORD)((pcktLen >> 2) - 1), &pRTCPhdr->length);
  493. IN_OUT_STR ("RTCP: Exit RTCPbuildSDES()\n");
  494. return ((PDWORD)ptr);
  495. }
  496. /*----------------------------------------------------------------------------
  497. * Function : RTCPbuildSenderRpt
  498. * Description: Build the RTCP Sender Report
  499. *
  500. * Input : pSSRC: -> to the SSRC entry
  501. * pRTCPhdr: -> to the RTCP packet header
  502. * pRTCPsr: -> to the Sender Report header
  503. * sd: Socket descriptor
  504. *
  505. * Return: None
  506. ---------------------------------------------------------------------------*/
  507. void RTCPbuildSenderRpt (PSSRC_ENTRY pSSRC,
  508. RTCP_COMMON_T *pRTCPhdr,
  509. SENDER_RPT **pRTCPsr,
  510. SOCKET sd)
  511. {
  512. DWORD dwTmp;
  513. DWORD NTPtime;
  514. DWORD RTPtime;
  515. DWORD RTPtimeStamp = 0;
  516. IN_OUT_STR ("RTCP: Enter RTCPbuildSenderRpt()\n");
  517. // payload type, SR
  518. pRTCPhdr->pt = RTCP_SR;
  519. // padding
  520. pRTCPhdr->p = 0;
  521. // sender report header
  522. *pRTCPsr = (SENDER_RPT *)(pRTCPhdr + 1);
  523. // fill in sender report packet
  524. RRCMws.htonl (sd, pSSRC->SSRC, &((*pRTCPsr)->ssrc));
  525. RRCMws.htonl (sd, pSSRC->xmtInfo.dwNumPcktSent, &((*pRTCPsr)->psent));
  526. RRCMws.htonl (sd, pSSRC->xmtInfo.dwNumBytesSent, &((*pRTCPsr)->osent));
  527. // NTP timestamp
  528. NTPtime = RTPtime = timeGetTime ();
  529. // get the number of seconds (integer calculation)
  530. dwTmp = NTPtime/1000;
  531. // NTP Msw
  532. RRCMws.htonl (sd, (NTPtime/1000), &((*pRTCPsr)->ntp_sec));
  533. // convert back dwTmp from second to millisecond
  534. dwTmp *= 1000;
  535. // get the remaining number of millisecond for the LSW
  536. NTPtime -= dwTmp;
  537. // NTP Lsw
  538. RRCMws.htonl (sd, usec2ntpFrac ((long)NTPtime*1000),
  539. &((*pRTCPsr)->ntp_frac));
  540. // calculate the RTP timestamp offset which correspond to this NTP
  541. // time and convert it to stream samples
  542. if (pSSRC->dwStreamClock)
  543. {
  544. RTPtimeStamp =
  545. pSSRC->xmtInfo.dwLastSendRTPTimeStamp +
  546. ((RTPtime - pSSRC->xmtInfo.dwLastSendRTPSystemTime) *
  547. (pSSRC->dwStreamClock / 1000));
  548. }
  549. RRCMws.htonl (sd, RTPtimeStamp, &((*pRTCPsr)->rtp_ts));
  550. IN_OUT_STR ("RTCP: Exit RTCPbuildSenderRpt()\n");
  551. }
  552. /*----------------------------------------------------------------------------
  553. * Function : usec2ntp
  554. * Description: Convert microsecond to fraction of second for NTP
  555. * As per VIC.
  556. * Convert micro-second to fraction of second * 2^32. This
  557. * routine uses the factorization:
  558. * 2^32/10^6 = 4096 + 256 - 1825/32
  559. * which results in a max conversion error of 3*10^-7 and an
  560. * average error of half that
  561. *
  562. * Input : usec: Micro second
  563. *
  564. * Return: Fraction of second in NTP format
  565. ---------------------------------------------------------------------------*/
  566. DWORD usec2ntp (DWORD usec)
  567. {
  568. DWORD tmp = (usec * 1825) >>5;
  569. return ((usec << 12) + (usec << 8) - tmp);
  570. }
  571. /*----------------------------------------------------------------------------
  572. * Function : usec2ntpFrac
  573. * Description: Convert microsecond to fraction of second for NTP.
  574. * Just uses an array of microsecond and set the corresponding
  575. * bit.
  576. *
  577. * Input : usec: Micro second
  578. *
  579. * Return: Fraction of second
  580. ---------------------------------------------------------------------------*/
  581. DWORD usec2ntpFrac (long usec)
  582. {
  583. DWORD idx;
  584. DWORD fraction = 0;
  585. DWORD tmpFraction = 0;
  586. long tmpVal;
  587. DWORD shift;
  588. for (idx=0, shift=FRACTION_SHIFT_MAX-1;
  589. idx < FRACTION_ENTRIES;
  590. idx++, shift--)
  591. {
  592. tmpVal = usec;
  593. if ((tmpVal - microSecondFrac[idx]) > 0)
  594. {
  595. usec -= microSecondFrac[idx];
  596. tmpFraction = (1 << shift);
  597. fraction |= tmpFraction;
  598. }
  599. else if ((tmpVal - microSecondFrac[idx]) == 0)
  600. {
  601. tmpFraction = (1 << shift);
  602. fraction |= tmpFraction;
  603. break;
  604. }
  605. }
  606. return fraction;
  607. }
  608. /*----------------------------------------------------------------------------
  609. * Function : RTCPbuildReceiverRpt
  610. * Description: Build the RTCP Receiver Report
  611. *
  612. * Input : pSSRC: -> to the SSRC entry
  613. * pRTCPsr: -> to the Receiver Report header
  614. * sd: Socket descriptor
  615. *
  616. * Return: None
  617. ---------------------------------------------------------------------------*/
  618. void RTCPbuildReceiverRpt (PSSRC_ENTRY pSSRC,
  619. RTCP_RR_T *pRTCPrr,
  620. SOCKET sd)
  621. {
  622. DWORD dwDlsr;
  623. IN_OUT_STR ("RTCP: Enter RTCPbuildReceiverRpt()\n");
  624. // get the SSRC
  625. RRCMws.htonl (sd, pSSRC->SSRC, &pRTCPrr->ssrc);
  626. // get fraction and cumulative number of packet lost (per RFC)
  627. pRTCPrr->received = getSSRCpcktLoss (pSSRC, TRUE);
  628. // extended highest sequence number received
  629. RRCMws.htonl (sd,
  630. pSSRC->rcvInfo.XtendedSeqNum.seq_union.dwXtndedHighSeqNumRcvd,
  631. &pRTCPrr->expected);
  632. // interrarival jitter
  633. #ifdef ENABLE_FLOATING_POINT
  634. RRCMws.htonl (sd, pSSRC->rcvInfo.interJitter, &pRTCPrr->jitter);
  635. #else
  636. // Check RFC for details of the round off
  637. RRCMws.htonl (sd, (pSSRC->rcvInfo.interJitter >> 4), &pRTCPrr->jitter);
  638. #endif
  639. // last SR
  640. RRCMws.htonl (sd, pSSRC->xmtInfo.dwLastSR, &pRTCPrr->lsr);
  641. // delay since last SR (only if an SR has been received from
  642. // this source, otherwise 0)
  643. if (pRTCPrr->lsr)
  644. {
  645. // get the DLSR
  646. dwDlsr = getDLSR (pSSRC);
  647. RRCMws.htonl (sd, dwDlsr, &pRTCPrr->dlsr);
  648. }
  649. else
  650. pRTCPrr->dlsr = 0;
  651. IN_OUT_STR ("RTCP: Exit RTCPbuildReceiverRpt()\n");
  652. }
  653. /*----------------------------------------------------------------------------
  654. * Function : getDLSR
  655. * Description: Get a DLSR packet
  656. *
  657. * Input : pSSRC: -> to the SSRC entry
  658. *
  659. * Return: DLSR in seconds:fraction format
  660. ---------------------------------------------------------------------------*/
  661. DWORD getDLSR (PSSRC_ENTRY pSSRC)
  662. {
  663. DWORD dwDlsr;
  664. DWORD dwTime;
  665. DWORD dwTmp;
  666. // DLSR in millisecond
  667. dwTime = timeGetTime() - pSSRC->xmtInfo.dwLastSRLocalTime;
  668. // get the number of seconds (integer calculation)
  669. dwTmp = dwTime/1000;
  670. // set the DLSR upper 16 bits (seconds)
  671. dwDlsr = dwTmp << 16;
  672. // convert back dwTmp from second to millisecond
  673. dwTmp *= 1000;
  674. // get the remaining number of millisecond for the LSW
  675. dwTime -= dwTmp;
  676. // convert microseconds to fraction of seconds
  677. dwTmp = usec2ntpFrac ((long)dwTime*1000);
  678. // get only the upper 16 bits
  679. dwTmp >>= 16;
  680. dwTmp &= 0x0000FFFF;
  681. // set the DLSR lower 16 bits (fraction of seconds)
  682. dwDlsr |= dwTmp;
  683. return dwDlsr;
  684. }
  685. /*----------------------------------------------------------------------------
  686. * Function : RTCPsendBYE
  687. * Description: Send an RTCP BYE packet
  688. *
  689. * Input : pRTCP: -> to the RTCP session
  690. * pSSRC: -> to the SSRC entry
  691. * byeReason: -> to the Bye reason, eg, "camera malfunction"...
  692. *
  693. * Return: None
  694. ---------------------------------------------------------------------------*/
  695. void RTCPsendBYE (PSSRC_ENTRY pSSRC,
  696. PCHAR pByeReason)
  697. {
  698. #define MAX_RTCP_BYE_SIZE 500 // ample
  699. PRTCP_SESSION pRTCP;
  700. WSABUF wsaBuf;
  701. char buf[MAX_RTCP_BYE_SIZE];
  702. RTCP_COMMON_T *pRTCPhdr;
  703. RTCP_RR_T *pRTCPrr;
  704. RECEIVER_RPT *pRTCPrecvr;
  705. BYE_PCKT *pBye;
  706. DWORD *pLastWord;
  707. DWORD dwStatus;
  708. DWORD dwNumBytesXfr;
  709. DWORD offset;
  710. DWORD byeLen;
  711. unsigned short pcktLen;
  712. PCHAR pBfr;
  713. IN_OUT_STR ("RTCP: Enter RTCPsendBYE()\n");
  714. // get the RTCP session
  715. pRTCP = pSSRC->pRTCPses;
  716. // check to see if under H.323 conference control. Don't send BYE in
  717. // this case
  718. if (pRTCP->dwSessionStatus & H323_CONFERENCE)
  719. return;
  720. // make sure the destination address is known
  721. if (!(pRTCP->dwSessionStatus & RTCP_DEST_LEARNED))
  722. {
  723. IN_OUT_STR ("RTCP: Exit RTCPsendBYE()\n");
  724. return;
  725. }
  726. // RTCP common header
  727. pRTCPhdr = (RTCP_COMMON_T *)buf;
  728. // RTP protocol version
  729. pRTCPhdr->type = RTP_TYPE;
  730. // empty RR
  731. pRTCPhdr->pt = RTCP_RR;
  732. // padding
  733. pRTCPhdr->p = 0;
  734. // report count
  735. pRTCPhdr->count = 0;
  736. // set the receiver report pointer
  737. pRTCPrecvr = (RECEIVER_RPT *)(pRTCPhdr + 1);
  738. // get our SSRC
  739. RRCMws.htonl (pSSRC->RTCPsd, pSSRC->SSRC, &pRTCPrecvr->ssrc);
  740. // build receiver report list
  741. pRTCPrr = pRTCPrecvr->rr;
  742. // just adjust the size, sending 0 or garbagge doesn't matter, the
  743. // report count will tell the receiver what's valid
  744. pRTCPrr++;
  745. // packet length for the previous RR
  746. pcktLen = (unsigned short)((char *)pRTCPrr - buf);
  747. RRCMws.htons (pSSRC->RTCPsd, (WORD)((pcktLen >> 2) - 1), &pRTCPhdr->length);
  748. // BYE packet
  749. pRTCPhdr = (RTCP_COMMON_T *)pRTCPrr;
  750. pRTCPhdr->type = RTP_TYPE;
  751. pRTCPhdr->pt = RTCP_BYE;
  752. pRTCPhdr->count = 1;
  753. pBye = (BYE_PCKT *)pRTCPhdr + 1;
  754. RRCMws.htonl (pSSRC->RTCPsd, pSSRC->SSRC, pBye->src);
  755. pBye++;
  756. // send the reason
  757. pBfr = (PCHAR)pBye;
  758. if (pByeReason)
  759. byeLen = min (strlen(pByeReason), MAX_SDES_LEN);
  760. else
  761. byeLen = strlen ("Session Terminated");
  762. // Pre-zero the last word of the SDES item chunk, and padd to the
  763. // 32 bits boundary. Need to do this before the memcpy, If we
  764. // landed exactly on the boundary then this will give us a whole
  765. // null word to terminate the sdes, as is needed.
  766. offset = (DWORD)((pBfr - buf) + byeLen);
  767. pLastWord = (unsigned long *)(buf + (offset & ~3));
  768. *pLastWord++ = 0;
  769. if (pByeReason)
  770. memcpy (pBfr+1, pByeReason, byeLen);
  771. else
  772. strcpy (pBfr+1, "Session Terminated");
  773. *pBfr = (unsigned char)byeLen;
  774. pcktLen = (unsigned short)((char *)pLastWord - (char *)pRTCPhdr);
  775. RRCMws.htons (pSSRC->RTCPsd, (WORD)((pcktLen >> 2) - 1), &pRTCPhdr->length);
  776. // calculate total RTCP packet length to xmit
  777. wsaBuf.len = (u_long)((char *)pLastWord - buf);
  778. #if (defined(_DEBUG) || defined(PCS_COMPLIANCE))
  779. if (RTPLogger)
  780. {
  781. //INTEROP
  782. InteropOutput (RTPLogger,
  783. (BYTE FAR*)(buf),
  784. (int)wsaBuf.len,
  785. RTPLOG_SENT_PDU | RTCP_PDU);
  786. }
  787. #endif
  788. // send the packet
  789. dwStatus = RRCMws.sendTo (pSSRC->RTCPsd,
  790. &wsaBuf,
  791. 1,
  792. &dwNumBytesXfr,
  793. 0,
  794. (PSOCKADDR)pRTCP->toBfr,
  795. pRTCP->toLen,
  796. NULL,
  797. NULL);
  798. IN_OUT_STR ("RTCP: Exit RTCPsendBYE()\n");
  799. }
  800. /*----------------------------------------------------------------------------
  801. * Function : updateRtpXmtBW
  802. * Description: Calculate a sending stream bandwidth during the last report
  803. * interval.
  804. *
  805. * Input : pSSRC: -> to the SSRC entry
  806. *
  807. * Return: Bandwith used by transmitter in bytes/sec
  808. ---------------------------------------------------------------------------*/
  809. #ifdef DYNAMIC_RTCP_BW
  810. DWORD updateRtpXmtBW (PSSRC_ENTRY pSSRC)
  811. {
  812. DWORD dwBW = 0;
  813. DWORD dwTimeInterval;
  814. DWORD dwByteInterval;
  815. DWORD dwTimeNow = timeGetTime();
  816. IN_OUT_STR ("RTCP: Enter updateRtpXmtBW()\n");
  817. if (pSSRC->xmtInfo.dwLastTimeBwCalculated == 0)
  818. {
  819. pSSRC->xmtInfo.dwLastTimeBwCalculated = dwTimeNow;
  820. pSSRC->xmtInfo.dwLastTimeNumBytesSent = pSSRC->xmtInfo.dwNumBytesSent;
  821. pSSRC->xmtInfo.dwLastTimeNumPcktSent = pSSRC->xmtInfo.dwNumPcktSent;
  822. }
  823. else
  824. {
  825. dwTimeInterval = dwTimeNow - pSSRC->xmtInfo.dwLastTimeBwCalculated;
  826. pSSRC->xmtInfo.dwLastTimeBwCalculated = dwTimeNow;
  827. // get the interval in second (we loose the fractional part)
  828. dwTimeInterval = dwTimeInterval / 1000;
  829. dwByteInterval =
  830. pSSRC->xmtInfo.dwNumBytesSent - pSSRC->xmtInfo.dwLastTimeNumBytesSent;
  831. dwBW = dwByteInterval / dwTimeInterval;
  832. pSSRC->xmtInfo.dwLastTimeNumBytesSent = pSSRC->xmtInfo.dwNumBytesSent;
  833. pSSRC->xmtInfo.dwLastTimeNumPcktSent = pSSRC->xmtInfo.dwNumPcktSent;
  834. }
  835. IN_OUT_STR ("RTCP: Exit updateRtpXmtBW()\n");
  836. return dwBW;
  837. }
  838. #endif // #ifdef DYNAMIC_RTCP_BW
  839. /*----------------------------------------------------------------------------
  840. * Function : updateRtpRcvBW
  841. * Description: Calculate a remote stream RTP bandwidth during the last
  842. * report interval.
  843. *
  844. * Input : pSSRC: -> to the SSRC entry
  845. *
  846. * Return: Bandwith used by the remote stream in bytes/sec
  847. ---------------------------------------------------------------------------*/
  848. #ifdef DYNAMIC_RTCP_BW
  849. DWORD updateRtpRcvBW (PSSRC_ENTRY pSSRC)
  850. {
  851. DWORD dwBW = 0;
  852. DWORD dwTimeInterval;
  853. DWORD dwByteInterval;
  854. DWORD dwTimeNow = timeGetTime();
  855. IN_OUT_STR ("RTCP: Enter updateRtpRcvBW()\n");
  856. if (pSSRC->rcvInfo.dwLastTimeBwCalculated == 0)
  857. {
  858. pSSRC->rcvInfo.dwLastTimeBwCalculated = dwTimeNow;
  859. pSSRC->rcvInfo.dwLastTimeNumBytesRcvd = pSSRC->rcvInfo.dwNumPcktRcvd;
  860. pSSRC->rcvInfo.dwLastTimeNumPcktRcvd = pSSRC->rcvInfo.dwNumBytesRcvd;
  861. }
  862. else
  863. {
  864. dwTimeInterval = dwTimeNow - pSSRC->rcvInfo.dwLastTimeBwCalculated;
  865. pSSRC->rcvInfo.dwLastTimeBwCalculated = dwTimeNow;
  866. // get the interval in second (we loose the fractional part)
  867. dwTimeInterval = dwTimeInterval / 1000;
  868. dwByteInterval =
  869. pSSRC->rcvInfo.dwNumBytesRcvd - pSSRC->rcvInfo.dwLastTimeNumBytesRcvd;
  870. dwBW = dwByteInterval / dwTimeInterval;
  871. pSSRC->rcvInfo.dwLastTimeNumBytesRcvd = pSSRC->rcvInfo.dwNumPcktRcvd;
  872. pSSRC->rcvInfo.dwLastTimeNumPcktRcvd = pSSRC->rcvInfo.dwNumBytesRcvd;
  873. }
  874. IN_OUT_STR ("RTCP: Exit updateRtpXmtBW()\n");
  875. return dwBW;
  876. }
  877. #endif // #ifdef DYNAMIC_RTCP_BW
  878. // [EOF]