rtcp.c
上传用户:biaoge6808
上传日期:2007-08-15
资源大小:42k
文件大小:60k
源码类别:

多媒体

开发平台:

C/C++

  1. #ifdef __cplusplus
  2. extern "C" {
  3. #endif
  4. /*
  5. NOTICE:
  6. This document contains information that is proprietary to RADVISION LTD.
  7. No part of this publication may be reproduced in any form whatsoever without
  8. written prior approval by RADVISION LTD.
  9. RADVISION LTD. reserves the right to revise this publication and make changes
  10. without obligation to notify any person of such revisions or changes.
  11. */
  12. /****************************************************************************
  13.   rtcp.c  --  RTCP implementation.
  14.   Abstract:       The main RTCP module file.
  15.   Platforms:      All.
  16. ****************************************************************************/
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <rvcommon.h>
  20. #include <rlist.h>
  21. #include "buffer.h"
  22. #include "bitfield.h"
  23. #include <mti.h>
  24. #include <ti.h>
  25. #include <li.h>
  26. #include <time.h>
  27. #include <mei.h>
  28. #include "rtcp.h"
  29. #define MAXSDES                   255
  30. #define MAXRTPSESSIONS            10
  31. #define MAXRTPSESSIONMEMBERS      50
  32. #define MAXRTCPPACKET             1470
  33. #define MAXIPS                    20
  34. #define MAX_DROPOUT               3000
  35. #define MAX_MISORDER              100
  36. #define MIN_SEQUENTIAL            2
  37. #define RTP_SEQ_MOD               0x10000
  38. #define ALIGNMENT                 0x10
  39. /* RTCP header bit locations - see the standard */
  40. #define HEADER_V                  30      /* version                       */
  41. #define HEADER_P                  29      /* padding                       */
  42. #define HEADER_RC                 24      /* reception report count        */
  43. #define HEADER_PT                 16      /* packet type                   */
  44. #define HEADER_len                0       /* packet length in 32-bit words */
  45. /* RTCP header bit field lengths - see the standard */
  46. #define HDR_LEN_V                 2       /* version                       */
  47. #define HDR_LEN_P                 1       /* padding                       */
  48. #define HDR_LEN_RC                5       /* reception report count        */
  49. #define HDR_LEN_PT                8       /* packet type                   */
  50. #define HDR_LEN_len               16      /* packet length in 32-bit words */
  51. /* used to overcome byte-allignment issues */
  52. #define SIZEOF_RTCPHEADER         (sizeof(UINT32) * 2)
  53. #define SIZEOF_SR                 (sizeof(UINT32) * 5)
  54. #define SIZEOF_RR                 (sizeof(UINT32) * 6)
  55. #define SIZEOF_SDES(sdes)         (((sdes).length + 6) & 0xfc)
  56. /* initial bit field value for RTCP headers: V=2,P=0,RC=0,PT=0,len=0 */
  57. #define RTCP_HEADER_INIT          0x80000000
  58. typedef enum {
  59.    RTCP_SR   = 200,               /* sender report            */
  60.    RTCP_RR   = 201,               /* receiver report          */
  61.    RTCP_SDES = 202,               /* source description items */
  62.    RTCP_BYE  = 203,               /* end of participation     */
  63.    RTCP_APP  = 204                /* application specific     */
  64. } rtcpType;
  65. typedef enum {
  66.    RTCP_SDES_END   = 0,
  67.    RTCP_SDES_CNAME = 1,
  68.    RTCP_SDES_NAME  = 2,
  69.    RTCP_SDES_EMAIL = 3,
  70.    RTCP_SDES_PHONE = 4,
  71.    RTCP_SDES_LOC   = 5,
  72.    RTCP_SDES_TOOL  = 6,
  73.    RTCP_SDES_NOTE  = 7,
  74.    RTCP_SDES_PRIV  = 8
  75. } rtcpSDesType;
  76. typedef struct
  77. {
  78.    UINT32  msdw;
  79.    UINT32  lsdw;
  80. } RV_UINT64;
  81. typedef struct
  82. {
  83.    RV_UINT64  tNNTP;
  84.    UINT32  tRTP;
  85.    UINT32  nPackets;
  86.    UINT32  nBytes;
  87. } rtcpSR;
  88. typedef struct
  89. {
  90.    UINT32  ssrc;
  91.    UINT32  bfLost;      /* 8Bit fraction lost and 24 bit cumulative lost */
  92.    UINT32  nExtMaxSeq;
  93.    UINT32  nJitter;
  94.    UINT32  tLSR;
  95.    UINT32  tDLSR;
  96. } rtcpRR;
  97. typedef struct {
  98.    UINT16  max_seq;               /* highest seq. number seen */
  99.    UINT32  cycles;                /* shifted count of seq. number cycles */
  100.    UINT32  base_seq;              /* base seq number */
  101.    UINT32  bad_seq;               /* last 'bad' seq number + 1 */
  102.    UINT32  probation;             /* sequ. packets till source is valid */
  103.    UINT32  received;              /* packets received */
  104.    UINT32  expected_prior;        /* packet expected at last interval */
  105.    UINT32  received_prior;        /* packet received at last interval */
  106.    UINT32  transit;               /* relative trans time for prev pkt */
  107.    UINT32  jitter;                /* estimated jitter */
  108.    /* ... */
  109. } rtpSource;
  110. typedef struct
  111. {
  112.    UINT8  type;
  113.    UINT8  length;
  114.    char   value[MAXSDES + 1];     /* leave a place for an asciiz */
  115. } rtcpSDES;
  116. typedef struct
  117. {
  118.    int        invalid;
  119.    BOOL       active;
  120.    rtpSource  src;
  121.    UINT32     ssrc;
  122.    UINT32     tLSRmyTime;
  123.    rtcpSR     eSR;
  124.    rtcpRR     eToRR;
  125.    rtcpRR     eFromRR;
  126.    rtcpSDES   eCName;
  127. } rtcpInfo;
  128. typedef struct
  129. {
  130.    UINT32  bits;
  131.    UINT32  ssrc;
  132. } rtcpHeader;
  133. typedef struct
  134. {
  135.    BOOL      active;
  136.    int       collision;
  137.    UINT32    ssrc;
  138.    UINT32    timestamp;
  139.    rtcpSR    eSR;
  140.    rtcpSDES  eCName;
  141. } rtcpMyInfo;
  142. typedef struct
  143. {
  144.    BOOL        isAllocated;
  145.    int         socket;
  146.    rtcpMyInfo  myInfo;
  147.    UINT32      ip;
  148.    UINT16      port;
  149.    HTI         tElem;
  150.    HMEI        hMutex;            /* Mutex handle*/
  151.    rtcpInfo    *participantsArray;
  152.    int         sessionMembers;
  153.    int         maxSessionMembers;
  154. /*h.e 30.04.01*/
  155.    LPRTCPEVENTHANDLER rtcpRecvCallback;
  156.    void*                haRtcp;
  157. /*==*/
  158. } rtcpSession;
  159. static UINT32 rtcpInitialized = 0;
  160. static UINT32 localIP;
  161. static UINT32 myIPs[MAXIPS];
  162. #ifndef RV_USE_R0
  163. static HSTIMER hst;
  164. #endif
  165. #define reduceNNTP(a) (((a).msdw<<16)+((a).lsdw>>16))
  166. #define W32Len(l)  ((l + 3) / 4)  /* length in 32-bit words */
  167. /* local functions */
  168. static RV_UINT64 getNNTPTime(void);
  169. static void   RVCALLCONV rtcpTimerCallback(void* key);
  170. static void   rtcpLiCallback   (int socket, liEvents event, int error, void *context);
  171. static UINT32 ipBindTo=LI_ADDR_ANY;
  172. static BOOL   isMyIP(UINT32 ip);
  173. static void   setSDES(rtcpSDesType type, rtcpSDES* sdes, BYTE *data,
  174.                       int length);
  175. static void   init_seq  (rtpSource *s, UINT16 seq);
  176. static int    update_seq(rtpSource *s, UINT16 seq, UINT32 ts, UINT32 arrival);
  177. static UINT32 getLost    (rtpSource *s);
  178. static UINT32 getJitter  (rtpSource *s);
  179. static UINT32 getSequence(rtpSource *s);
  180. /*h.e 30.05.01*/
  181. static UINT32 getSSRCfrom(BYTE *);
  182. /*===*/
  183. static rtcpHeader makeHeader(UINT32 ssrc, UINT8 count, rtcpType type,
  184.                              UINT16 dataLen);
  185. static rtcpInfo * findSSrc(rtcpSession *,UINT32);
  186. static rtcpInfo *insertNewSSRC(rtcpSession *s, UINT32 ssrc);
  187. int align(int addr, int alignVal)
  188. {
  189.   return  ((addr / alignVal) * alignVal + alignVal);
  190. }
  191. RVAPI
  192. INT32 RVCALLCONV rtcpGetEnumFirst(
  193.                 IN  HRTCPSESSION  hRTCP,
  194.                 IN  INT32 *       ssrc);
  195. RVAPI
  196. INT32 RVCALLCONV rtcpGetEnumNext(
  197.                 IN  HRTCPSESSION  hRTCP,
  198.                 IN  INT32         prev,
  199.                 IN  INT32 *       ssrc);
  200. RVAPI
  201. INT32 RVCALLCONV rtcpProcessCompoundRTCPPacket(
  202.         IN      HRTCPSESSION  hRTCP,
  203.         IN OUT  BUFFER *      buf,
  204.         IN      RV_UINT64        myTime);
  205. RVAPI
  206. INT32 RVCALLCONV rtcpProcessRTCPPacket(
  207.         IN  rtcpSession *  s,
  208.         IN  BYTE *         data,
  209.         IN  INT32          dataLen,
  210.         IN  rtcpType       type,
  211.         IN  INT32          reportCount,
  212.         IN  RV_UINT64         myTime);
  213.                       /* == Basic RTCP Functions == */
  214. /*=========================================================================**
  215. **  == rtcpInit() ==                                                       **
  216. **                                                                         **
  217. **  Initializes the RTCP module.                                           **
  218. **                                                                         **
  219. **  RETURNS:                                                               **
  220. **      A non-negative value upon success, or a negative integer error     **
  221. **      code.                                                              **
  222. **                                                                         **
  223. **=========================================================================*/
  224. RVAPI
  225. INT32 RVCALLCONV rtcpInit(void)
  226. {
  227.     int i,err;
  228.     UINT32 **ips;
  229. #ifdef RV_USE_R0
  230.     HSTIMER hst;
  231. #else
  232.     if (hst) return ERR_RTCP_GENERALERROR;
  233. #endif
  234.     if ((err = liInit()) < 0)
  235.         return ERR_RTCP_GENERALERROR;
  236.     if (rtcpInitialized == 0)
  237.     {
  238.         if ((hst = mtimerInit(1024,(HAPPTIMER)myIPs)) == NULL)
  239.         {
  240.             liEnd();
  241.             return ERR_RTCP_GENERALERROR;
  242.         }
  243.         ips = liGetHostAddrs();
  244.         if (!ips)
  245.         {
  246.             liEnd();
  247.             mtimerEnd(hst);
  248.             hst = NULL;
  249.             return ERR_RTCP_GENERALERROR;
  250.         }
  251.         localIP = liConvertIp((char*)"127.0.0.1");
  252.         for (i=0; ips[i]; i++)
  253.             myIPs[i] = *(ips[i]);
  254.     }
  255.     liThreadAttach(NULL);
  256.     rtcpInitialized++;
  257.     return 0;
  258. }
  259. /*=========================================================================**
  260. **  == rtcpInitEx() ==                                                     **
  261. **                                                                         **
  262. **  Initializes the RTCP module.                                           **
  263. **  Parameter: ip - ip address to 'bind' RTCP session                      **
  264. **                                                                         **
  265. **  RETURNS:                                                               **
  266. **      A non-negative value upon success, or a negative integer error     **
  267. **      code.                                                              **
  268. **                                                                         **
  269. **=========================================================================*/
  270. RVAPI
  271. INT32 RVCALLCONV rtcpInitEx(UINT32 ip)
  272. {
  273.     INT32 rc;
  274.     if ((rc=rtcpInit()) != ERR_RTCP_GENERALERROR)
  275.       ipBindTo=ip;
  276.     return rc;
  277. }
  278. /*=========================================================================**
  279. **  == rtcpEnd() ==                                                        **
  280. **                                                                         **
  281. **  Shuts down the RTCP module.                                            **
  282. **                                                                         **
  283. **  RETURNS:                                                               **
  284. **      A non-negative value upon success, or a negative integer error     **
  285. **      code.                                                              **
  286. **                                                                         **
  287. **=========================================================================*/
  288. RVAPI
  289. INT32 RVCALLCONV rtcpEnd(void)
  290. {
  291.     int err = 0;
  292.     liThreadDetach(NULL);
  293.     err = liEnd();
  294. #ifdef RV_USE_R0
  295.     mtimerEndByHandle((HAPPTIMER)myIPs);
  296. #else
  297.     mtimerEnd(hst);
  298.     hst = NULL;
  299. #endif
  300.     rtcpInitialized--;
  301.     return err;
  302. }
  303. /*h.e 30.04.01*/
  304. RVAPI
  305. INT32 RVCALLCONV rtcpSetRTCPRecvEventHandler(
  306.     IN HRTCPSESSION         hRTCP,
  307.     IN LPRTCPEVENTHANDLER   rtcpCallback,
  308.     IN void *               context)
  309. {
  310.     rtcpSession *s = (rtcpSession *)hRTCP;
  311.   s->rtcpRecvCallback=rtcpCallback;
  312.   s->haRtcp=context;                     /*context is Event to inform Ring3 about RTCP arrival*/
  313.   return 0;
  314. }
  315. /*===*/
  316. /*=========================================================================**
  317. **  == rtcpGetAllocationSize()                                             **
  318. **                                                                         **
  319. **  Calculates an allocation size for RTCP session             **
  320. **                                                                         **
  321. **  PARAMETERS:                                                            **
  322. **      sessionMembers  Maximum number of participants in the session      **
  323. **                                                                         **
  324. **                                                                         **
  325. **  RETURNS:                                                               **
  326. **      If no error occurs, the function returns an allocation size for    **
  327. **      RTCP session.  Otherwise it returns NULL.                          **
  328. **                                                                         **
  329. **=========================================================================*/
  330. RVAPI
  331. int RVCALLCONV rtcpGetAllocationSize(
  332.     IN  int sessionMembers)
  333. {
  334.     return sizeof(rtcpSession) + ALIGNMENT
  335.         +  sizeof(rtcpInfo) * sessionMembers + ALIGNMENT
  336.         +  mutexGetAllocationSize();
  337. }
  338. /************************************************************************************
  339.  * rtcpSetLocalAddress
  340.  * description: Set the local address to use for calls to rtcpOpenXXX functions.
  341.  *              This parameter overrides the value given in rtcpInitEx() for all
  342.  *              subsequent calls.
  343.  * input: ip    - Local IP address to use
  344.  * output: none.
  345.  * return value: Non-negative value on success
  346.  *               Negative value on failure
  347.  ***********************************************************************************/
  348. RVAPI
  349. int RVCALLCONV rtcpSetLocalAddress(IN UINT32 ip)
  350. {
  351.     ipBindTo = ip;
  352.     return 0;
  353. }
  354. /*=========================================================================**
  355. **  == rtcpOpenFrom() ==                                                   **
  356. **                                                                         **
  357. **  Opens a new RTCP session in provided buffer.                           **
  358. **                                                                         **
  359. **  PARAMETERS:                                                            **
  360. **      ssrc     The synchronization source value for the RTCP session.    **
  361. **                                                                         **
  362. **      port     The UDP port number to be used for the RTCP session.      **
  363. **                                                                         **
  364. **      cname    A unique name representing the source of the RTP data.    **
  365. **               Must not be NULL.                                         **
  366. **      maxSessionMembers   Maximum number of participants in the session  **
  367. **                                                                         **
  368. **  buffer   pointer to at least rtcpGetAllocationSize byte of memory      **
  369. **                                                                         **
  370. **  bufferSize size of the buffer                                          **
  371. **                                                                         **
  372. **  RETURNS:                                                               **
  373. **      If no error occurs, the function returns a handle for the new      **
  374. **      RTCP session.  Otherwise it returns NULL.                          **
  375. **                                                                         **
  376. **  COMMENTS:                                                              **
  377. **              -----------------------------------------------            **
  378. **     buffer  | rtcpSession |X| participantsArray |X| "mutex" |           **
  379. **              -----------------------------------------------            **
  380. **                            X - alignment area                           **
  381. **=========================================================================*/
  382. RVAPI
  383. HRTCPSESSION RVCALLCONV rtcpOpenFrom(
  384.         IN  UINT32  ssrc,
  385.         IN  UINT16  port,
  386.         IN  char *  cname,
  387.         IN  int     maxSessionMembers,
  388.         IN  void *  buffer,
  389.         IN  int     bufferSize)
  390. {
  391.     rtcpSession* s=(rtcpSession*)buffer;
  392.     int allocSize=rtcpGetAllocationSize(maxSessionMembers);
  393.     int participantsArrayOfs;
  394.     int mutexSectionOfs;
  395.     if (!cname  ||  strlen(cname) > MAXSDES || allocSize > bufferSize)
  396.     {
  397.         return NULL;
  398.     }
  399.     memset(buffer, 0, allocSize);
  400.     s->sessionMembers = 0;
  401.     s->maxSessionMembers = maxSessionMembers;
  402.     s->rtcpRecvCallback = NULL;
  403.     s->isAllocated=FALSE;
  404.     participantsArrayOfs = align (sizeof(rtcpSession), ALIGNMENT);
  405.     s->participantsArray = (rtcpInfo *) ((char *)s + participantsArrayOfs);
  406.     s->participantsArray[0].ssrc = s->myInfo.ssrc = ssrc;
  407.     s->socket = liOpen(ipBindTo,port,LI_UDP);
  408.     if (s->socket==RVERROR)
  409.     {
  410.         return NULL;
  411.     }
  412.     s->tElem = (HTI)RVERROR;
  413.     /* initialize "mutex" in supplied buffer*/
  414.     mutexSectionOfs = participantsArrayOfs + align(sizeof(rtcpInfo)*maxSessionMembers, ALIGNMENT);
  415.     s->hMutex = mutexInitFrom( (void *) ((char *)s + mutexSectionOfs) );
  416. #ifndef UNDER_CE
  417.     if (!s->hMutex)
  418.     {
  419.         return NULL;
  420.     }
  421. #endif
  422.     liCallOn(s->socket,liEvRead,rtcpLiCallback,s);
  423.     setSDES(RTCP_SDES_CNAME, &(s->myInfo.eCName), (BYTE*)cname, (int)strlen(cname));
  424.     return (HRTCPSESSION)s;
  425. }
  426. /*=========================================================================**
  427. **  == rtcpOpen() ==                                                       **
  428. **                                                                         **
  429. **  Opens a new RTCP session.                                              **
  430. **                                                                         **
  431. **  PARAMETERS:                                                            **
  432. **      ssrc     The synchronization source value for the RTCP session.    **
  433. **                                                                         **
  434. **      port     The UDP port number to be used for the RTCP session.      **
  435. **                                                                         **
  436. **      cname    A unique name representing the source of the RTP data.    **
  437. **               Must not be NULL.                                         **
  438. **                                                                         **
  439. **  RETURNS:                                                               **
  440. **      If no error occurs, the function returns a handle for the new      **
  441. **      RTCP session.  Otherwise it returns NULL.                          **
  442. **                                                                         **
  443. **=========================================================================*/
  444. RVAPI
  445. HRTCPSESSION RVCALLCONV rtcpOpen(
  446.         IN  UINT32  ssrc,
  447.         IN  UINT16  port,
  448.         IN  char *  cname)
  449. {
  450.     rtcpSession* s;
  451.     int allocSize=rtcpGetAllocationSize(MAXRTPSESSIONMEMBERS);
  452.     s = (rtcpSession*)calloc(allocSize,1);
  453.     if (s==NULL)
  454.         return NULL;
  455.     if((rtcpSession*)rtcpOpenFrom(ssrc, port, cname, MAXRTPSESSIONMEMBERS, (void*)s, allocSize)==NULL)
  456.     {
  457.         free(s);
  458.         return NULL;
  459.     }
  460.     s->isAllocated=TRUE;
  461.     return (HRTCPSESSION)s;
  462. }
  463. /*=========================================================================**
  464. **  == rtcpClose() ==                                                      **
  465. **                                                                         **
  466. **  Closes an RTCP session.                                                **
  467. **                                                                         **
  468. **  PARAMETERS:                                                            **
  469. **      hRTCP      The handle of the RTCP session.                         **
  470. **                                                                         **
  471. **  RETURNS:                                                               **
  472. **      A non-negative value upon success, or a negative integer error     **
  473. **      code.                                                              **
  474. **                                                                         **
  475. **=========================================================================*/
  476. RVAPI
  477. INT32 RVCALLCONV rtcpClose(
  478.                 IN  HRTCPSESSION  hRTCP)
  479. {
  480.     rtcpSession *s = (rtcpSession *)hRTCP;
  481.     if (s->tElem!=(HTI)RVERROR)
  482.       {
  483. #ifdef RV_USE_R0
  484.         mtimerResetByHandle((HAPPTIMER)myIPs, s->tElem);
  485. #else
  486.         mtimerReset(hst,s->tElem);
  487. #endif
  488.         s->tElem=(HTI)RVERROR;
  489.       }
  490.     liClose(s->socket);
  491.     mutexEnd(s->hMutex);
  492.     /* free memory allocated for rtcpSession */
  493.     if (s->isAllocated)
  494.     free(s);
  495.     return 0;
  496. }
  497. /*=========================================================================**
  498. **  == rtcpSetRemoteAddress() ==                                           **
  499. **                                                                         **
  500. **  Defines the address of the remote peer or of the multicast groop.      **
  501. **                                                                         **
  502. **  PARAMETERS:                                                            **
  503. **      hRTCP    The handle of the RTCP session.                           **
  504. **                                                                         **
  505. **      ip       The IP address to which the RTCP packets will be sent.    **
  506. **                                                                         **
  507. **      port     The UDP port to which the RTCP packets should be sent.    **
  508. **                                                                         **
  509. **  RETURNS:                                                               **
  510. **      A non-negative value upon success, or a negative integer error     **
  511. **      code.                                                              **
  512. **                                                                         **
  513. **=========================================================================*/
  514. RVAPI
  515. void RVCALLCONV rtcpSetRemoteAddress(
  516.                 IN  HRTCPSESSION  hRTCP,     /* RTCP Session Opaque Handle */
  517.                 IN  UINT32        ip,        /* target ip address */
  518.                 IN  UINT16        port)      /* target UDP port */
  519. {
  520.     rtcpSession *s = (rtcpSession *)hRTCP;
  521.     s->ip   = ip;
  522.     s->port = port;
  523.     if (ip&&port)
  524.     {
  525.         if (s->tElem==(HTI)RVERROR)
  526. #ifdef RV_USE_R0
  527.             s->tElem =mtimerSetByHandle((HAPPTIMER)myIPs, rtcpTimerCallback, s, 5000/* should be calculated*/);
  528. #else
  529.             s->tElem =mtimerSet(hst, rtcpTimerCallback, s, 5000/* should be calculated*/);
  530. #endif
  531.     }
  532.     else
  533.     {
  534.         rtcpStop(hRTCP);
  535.     }
  536. }
  537. /*=========================================================================**
  538. **  == rtcpStop() ==                                                       **
  539. **                                                                         **
  540. **  Stop RTCP transmisions .                                               **
  541. **                                                                         **
  542. **  PARAMETERS:                                                            **
  543. **      hRTCP    The handle of the RTCP session.                           **
  544. **                                                                         **
  545. **  RETURNS:                                                               **
  546. **      A non-negative value upon success, or a negative integer error     **
  547. **      code.                                                              **
  548. **                                                                         **
  549. **=========================================================================*/
  550. RVAPI
  551. INT32 RVCALLCONV rtcpStop(
  552.                 IN  HRTCPSESSION  hRTCP)     /* RTCP Session Opaque Handle */
  553. {
  554.     rtcpSession *s = (rtcpSession *)hRTCP;
  555.     s->ip   = 0;
  556.     s->port = 0;
  557.     /* Clear the list*/
  558.     memset(s->participantsArray,0,(sizeof(rtcpInfo))*(s->sessionMembers));
  559.     s->myInfo.collision = 0;
  560.     s->myInfo.active = 0;
  561.     s->myInfo.timestamp = 0;
  562.     memset(&(s->myInfo.eSR),0,sizeof(s->myInfo.eSR));
  563.     if (s->tElem!=(HTI)RVERROR)
  564.     {
  565. #ifdef RV_USE_R0
  566.         mtimerResetByHandle((HAPPTIMER)myIPs,s->tElem);
  567. #else
  568.         mtimerReset(hst,s->tElem);
  569. #endif
  570.         s->tElem=(HTI)RVERROR;
  571.     }
  572.     return 0;
  573. }
  574. /*=========================================================================**
  575. **  == rtcpRTPPacketRecv() ==                                              **
  576. **                                                                         **
  577. **  Informs the RTCP session that a packet was received in the             **
  578. **  corresponding RTP session.                                             **
  579. **                                                                         **
  580. **  PARAMETERS:                                                            **
  581. **      hRTCP      The handle of the RTCP session.                         **
  582. **                                                                         **
  583. **      localTimestamp  The local timestamp for the received packet.       **
  584. **                                                                         **
  585. **      timestamp  The RTP timestamp from the received packet.             **
  586. **                                                                         **
  587. **      sequence   The packet sequence number.                             **
  588. **                                                                         **
  589. **  RETURNS:                                                               **
  590. **      A non-negative value upon success, or a negative integer error     **
  591. **      code.                                                              **
  592. **                                                                         **
  593. **=========================================================================*/
  594. RVAPI
  595. INT32 RVCALLCONV rtcpRTPPacketRecv(
  596.                 IN  HRTCPSESSION  hRTCP,
  597.                 IN  UINT32        ssrc,
  598.                 IN  UINT32        localTimestamp,
  599.                 IN  UINT32        myTimestamp,
  600.                 IN  UINT16        sequence)
  601. {
  602.     rtcpSession *s = (rtcpSession *)hRTCP;
  603.     rtcpInfo info, *fInfo;
  604.     if (ssrc == s->myInfo.ssrc)
  605.     {
  606.       s->myInfo.collision = 1;
  607.       return ERR_RTCP_SSRCCOLLISION;
  608.     }
  609.     info.ssrc = ssrc;
  610.     /* See if we can find this source or not */
  611.     fInfo = findSSrc(s,ssrc);
  612. #ifdef RTP_NOLOCKS
  613.     if (!fInfo) /* New source */
  614.     {
  615.         rtcpHeader head;
  616.         /* create an invalid record */
  617.         head = makeHeader(ssrc, 0, RTCP_RR, SIZEOF_RTCPHEADER);
  618.         /* we'll send it to ourselves to make sure we can handle the change
  619.            in the RTCP's database in multi-threaded environments without locking it. */
  620.         liUdpSend(s->socket, (UINT8 *)&head, (int)SIZEOF_RTCPHEADER, localIP,
  621.                   liGetSockPort(s->socket));
  622.     }
  623. #else  /* RTP_NOLOCKS */
  624.     /* The new way of doing things: If we didn't find this SSRC, we lock the
  625.        RTCP database and search for the SSRC again. If we don't find it again - we
  626.        insert it to the list, and finally we unlock... */
  627.     if (!fInfo)  /* New source */
  628.     {
  629.       /* this section is working with threads.*/
  630.       /* Lock the rtcp session.*/
  631.       mutexLock(s->hMutex);
  632.       /* check if the ssrc is exist*/
  633.       fInfo = findSSrc(s,ssrc);
  634.       if (!fInfo)
  635.       {
  636.           /* Still no SSRC - we should add it to the list ourselves */
  637.           fInfo = insertNewSSRC(s, ssrc);
  638.       }
  639.       /* unlock the rtcp session.*/
  640.       mutexUnlock(s->hMutex);
  641.     }
  642. #endif  /* RTP_NOLOCKS */
  643.     if (fInfo)
  644.     {
  645.         if (!fInfo->invalid)
  646.         {
  647.             fInfo->active = TRUE;
  648.             update_seq(&(fInfo->src), sequence, localTimestamp, myTimestamp);
  649.         }
  650.     }
  651.     return 0;
  652. }
  653. /*=========================================================================**
  654. **  == rtcpRTPPacketSent() ==                                              **
  655. **                                                                         **
  656. **  Informs the RTCP session that a packet was sent in the corresponding   **
  657. **  RTP session.                                                           **
  658. **                                                                         **
  659. **  PARAMETERS:                                                            **
  660. **      hRTCP      The handle of the RTCP session.                         **
  661. **                                                                         **
  662. **      bytes      The number of bytes in the sent packet.                 **
  663. **                                                                         **
  664. **      timestamp  The RTP timestamp from the received packet.             **
  665. **                                                                         **
  666. **  RETURNS:                                                               **
  667. **      A non-negative value upon success, or a negative integer error     **
  668. **      code.                                                              **
  669. **                                                                         **
  670. **=========================================================================*/
  671. RVAPI
  672. INT32 RVCALLCONV rtcpRTPPacketSent(
  673.                 IN  HRTCPSESSION  hRTCP,
  674.                 IN  INT32         bytes,
  675.                 IN  UINT32        timestamp)
  676. {
  677.     rtcpSession *s = (rtcpSession *)hRTCP;
  678.     s->myInfo.active = TRUE;
  679.     s->myInfo.eSR.nPackets++;
  680.     s->myInfo.eSR.nBytes += bytes;
  681.     s->myInfo.eSR.tNNTP = getNNTPTime();
  682.     s->myInfo.eSR.tRTP = timestamp;
  683.     if (s->myInfo.collision)
  684.       return ERR_RTCP_SSRCCOLLISION;
  685.     return 0;
  686. }
  687. /*=========================================================================**
  688. **  == rtcpGetPort() ==                                                    **
  689. **                                                                         **
  690. **  Gets the UDP port of an RTCP session.                                  **
  691. **                                                                         **
  692. **  PARAMETERS:                                                            **
  693. **      hRTCP      The handle of the RTCP session.                         **
  694. **                                                                         **
  695. **  RETURNS:                                                               **
  696. **      A non-negative value upon success, or a negative integer error     **
  697. **      code.                                                              **
  698. **                                                                         **
  699. **=========================================================================*/
  700. RVAPI
  701. UINT16 RVCALLCONV rtcpGetPort(
  702.                 IN  HRTCPSESSION  hRTCP)
  703. {
  704.     rtcpSession *s = (rtcpSession *)hRTCP;
  705.     UINT16 sockPort;
  706.     sockPort=liGetSockPort(s->socket);
  707.     return sockPort;
  708. }
  709.                    /* == ENDS: Basic RTCP Functions == */
  710.                     /* == Accessory RTCP Functions == */
  711. /*=========================================================================**
  712. **  == rtcpCheckSSRCCollision() ==                                         **
  713. **                                                                         **
  714. **  Checks for SSRC collisions in the RTCP session and the corresponding   **
  715. **  RTP session.                                                           **
  716. **                                                                         **
  717. **  PARAMETERS:                                                            **
  718. **      hRTCP      The handle of the RTCP session.                         **
  719. **                                                                         **
  720. **  RETURNS:                                                               **
  721. **      TRUE is returned if a collision was detected, otherwise FALSE.     **
  722. **                                                                         **
  723. **=========================================================================*/
  724. RVAPI
  725. BOOL RVCALLCONV rtcpCheckSSRCCollision(
  726.                 IN  HRTCPSESSION  hRTCP)
  727. {
  728.     rtcpSession *s = (rtcpSession *)hRTCP;
  729.     return (s->myInfo.collision != 0);
  730. }
  731. /*=========================================================================**
  732. **  == rtcpEnumParticipants() ==                                           **
  733. **                                                                         **
  734. **  Provides information about in the RTCP session and the corresponding   **
  735. **  RTP session.                                                           **
  736. **                                                                         **
  737. **  PARAMETERS:                                                            **
  738. **      hRTCP      The handle of the RTCP session.                         **
  739. **                                                                         **
  740. **      enumerator A pointer to the function that will be called once per  **
  741. **                 SSRC in the session.                                    **
  742. **                                                                         **
  743. **  RETURNS:                                                               **
  744. **      If the enumeration process was stopped by the enumerator, the      **
  745. **      function returns FALSE, otherwise TRUE.                            **
  746. **                                                                         **
  747. **  The prototype of the SSRC enumerator is as follows:                    **
  748. **                                                                         **
  749. **      BOOL                                                               **
  750. **      SSRCENUM(                                                          **
  751. **        IN  HRTPSESSION  hTRCP,                                          **
  752. **        IN  UINT32       ssrc                                            **
  753. **      );                                                                 **
  754. **                                                                         **
  755. **  The parameters passed to the enumerator are as follows:                **
  756. **      hRTCP      The handle of the RTCP session.                         **
  757. **                                                                         **
  758. **      ssrc       A synchronization source that participates in the       **
  759. **                 session.                                                **
  760. **                                                                         **
  761. **  The enumerator should return FALSE if it wants the enumeration process **
  762. **  to continue.  Returning TRUE will cause rtcpEnumParticipant() to       **
  763. **  return immediately.                                                    **
  764. **                                                                         **
  765. **=========================================================================*/
  766. RVAPI
  767. BOOL RVCALLCONV rtcpEnumParticipants(
  768.                 IN HRTCPSESSION hRTCP,
  769.                 IN LPSSRCENUM   enumerator)
  770. {
  771.     int elem, ssrc=0;
  772.     elem = rtcpGetEnumFirst(hRTCP, &ssrc);
  773.     while (elem >= 0)
  774.     {
  775.         if (enumerator(hRTCP, ssrc))
  776.         {
  777.             return FALSE;
  778.         }
  779.         elem = rtcpGetEnumNext(hRTCP, elem, &ssrc);
  780.     }
  781.     return TRUE;
  782. }
  783. /*=========================================================================**
  784. **  == rtcpGetSourceInfo() ==                                              **
  785. **                                                                         **
  786. **  Provides information about a particular synchronization source.        **
  787. **                                                                         **
  788. **  TBD                                                                    **
  789. **                                                                         **
  790. **=========================================================================*/
  791. RVAPI
  792. INT32 RVCALLCONV rtcpGetSourceInfo(
  793.                 IN   HRTCPSESSION  hRTCP,
  794.                 IN   UINT32        ssrc,
  795.                 OUT  RTCPINFO *    info)
  796. {
  797.     rtcpSession *s = (rtcpSession *)hRTCP;
  798.     rtcpInfo *fInfo, intInfo;
  799.     if (ssrc == s->myInfo.ssrc)
  800.     {
  801.         info->selfNode         = TRUE;
  802.         info->sr.valid         = s->myInfo.active;
  803.         info->sr.mNTPtimestamp = s->myInfo.eSR.tNNTP.msdw;
  804.         info->sr.lNTPtimestamp = s->myInfo.eSR.tNNTP.lsdw;
  805.         info->sr.timestamp     = s->myInfo.eSR.tRTP;
  806.         info->sr.packets       = s->myInfo.eSR.nPackets;
  807.         info->sr.octets        = s->myInfo.eSR.nBytes;
  808.         strncpy(info->cname, s->myInfo.eCName.value, sizeof(info->cname));
  809.         return 0;
  810.     }
  811.     intInfo.ssrc = ssrc;
  812.     fInfo = findSSrc(s,ssrc);
  813.     if (fInfo)
  814.     {
  815.         info->selfNode              = FALSE;
  816.         info->sr.valid              = !fInfo->invalid;
  817.         info->sr.mNTPtimestamp      = fInfo->eSR.tNNTP.msdw;
  818.         info->sr.lNTPtimestamp      = fInfo->eSR.tNNTP.lsdw;
  819.         info->sr.timestamp          = fInfo->eSR.tRTP;
  820.         info->sr.packets            = fInfo->eSR.nPackets;
  821.         info->sr.octets             = fInfo->eSR.nBytes;
  822.         info->rrFrom.valid          = TRUE;
  823.         info->rrFrom.fractionLost   = (fInfo->eFromRR.bfLost >> 24);
  824.         info->rrFrom.cumulativeLost = (fInfo->eFromRR.bfLost & 0xffffff);
  825.         info->rrFrom.sequenceNumber = fInfo->eFromRR.nExtMaxSeq;
  826.         info->rrFrom.jitter         = fInfo->eFromRR.nJitter;
  827.         info->rrFrom.lSR            = fInfo->eFromRR.tLSR;
  828.         info->rrFrom.dlSR           = fInfo->eFromRR.tDLSR;
  829.         info->rrTo.valid            = TRUE;
  830.         info->rrTo.fractionLost     = (fInfo->eToRR.bfLost >> 24);
  831.         info->rrTo.cumulativeLost   = (fInfo->eToRR.bfLost & 0xffffff);
  832.         info->rrTo.sequenceNumber   = fInfo->eToRR.nExtMaxSeq;
  833.         info->rrTo.jitter           = fInfo->eToRR.nJitter;
  834.         info->rrTo.lSR              = fInfo->eToRR.tLSR;
  835.         info->rrTo.dlSR             = fInfo->eToRR.tDLSR;
  836.         strncpy(info->cname, fInfo->eCName.value, sizeof(info->cname));
  837.     }
  838.     return (!fInfo) ? ERR_RTCP_ILLEGALSSRC : 0;
  839. }
  840. /*=========================================================================**
  841. **  == rtcpSetGroupAddress() ==                                            **
  842. **                                                                         **
  843. **  Specifies a multicast IP for an RTCP session.                          **
  844. **                                                                         **
  845. **  PARAMETERS:                                                            **
  846. **      hRTCP      The handle of the RTCP session.                         **
  847. **                                                                         **
  848. **      ip         The multicast IP address for the RTCP session.          **
  849. **                 SSRC in the session.                                    **
  850. **                                                                         **
  851. **  RETURNS:                                                               **
  852. **      If the enumeration process was stopped by the enumerator, the      **
  853. **      function returns FALSE, otherwise TRUE.                            **
  854. **                                                                         **
  855. **=========================================================================*/
  856. RVAPI
  857. INT32 RVCALLCONV rtcpSetGroupAddress(
  858.                 IN  HRTCPSESSION  hRTCP,
  859.                 IN  UINT32        ip)
  860. {
  861.     rtcpSession *s = (rtcpSession *)hRTCP;
  862.     liJoinMulticastGroup(s->socket, ip, LI_ADDR_ANY);
  863.     return 0;
  864. }
  865. /*=========================================================================**
  866. **  == rtcpGetSSRC() ==                                                    **
  867. **                                                                         **
  868. **  Returns the synchronization source value for an RTCP session.          **
  869. **                                                                         **
  870. **  PARAMETERS:                                                            **
  871. **      hRTCP      The handle of the RTCP session.                         **
  872. **                                                                         **
  873. **  RETURNS:                                                               **
  874. **      The synchronization source value for the specified RTCP session.   **
  875. **                                                                         **
  876. **=========================================================================*/
  877. RVAPI
  878. INT32 RVCALLCONV rtcpGetSSRC(
  879.                 IN  HRTCPSESSION  hRTCP)
  880. {
  881.     rtcpSession *s = (rtcpSession *)hRTCP;
  882.     return s->myInfo.ssrc;
  883. }
  884. /*=========================================================================**
  885. **  == rtcpSetSSRC() ==                                                    **
  886. **                                                                         **
  887. **  Changes the synchronization source value for an RTCP session.          **
  888. **                                                                         **
  889. **  PARAMETERS:                                                            **
  890. **      hRTCP      The handle of the RTCP session.                         **
  891. **                                                                         **
  892. **      ssrc       A synchronization srouce value for the RTCP session.    **
  893. **                                                                         **
  894. **  RETURNS:                                                               **
  895. **      If the enumeration process was stopped by the enumerator, the      **
  896. **      function returns FALSE, otherwise TRUE.                            **
  897. **                                                                         **
  898. **=========================================================================*/
  899. RVAPI
  900. INT32 RVCALLCONV rtcpSetSSRC(
  901.                 IN  HRTCPSESSION  hRTCP,
  902.                 IN  UINT32        ssrc)
  903. {
  904.     rtcpSession *s = (rtcpSession *)hRTCP;
  905.     s->myInfo.ssrc      = ssrc;
  906.     s->myInfo.collision = 0;
  907.     return 0;
  908. }
  909.                  /* == ENDS: Accessory RTCP Functions == */
  910.                      /* == Internal RTCP Functions == */
  911. RVAPI
  912. INT32 RVCALLCONV rtcpGetEnumFirst(
  913.                 IN  HRTCPSESSION  hRTCP,
  914.                 IN  INT32 *       ssrc)
  915. {
  916.     return rtcpGetEnumNext(hRTCP, -1, ssrc);
  917. }
  918. RVAPI
  919. INT32 RVCALLCONV rtcpGetEnumNext(
  920.                 IN  HRTCPSESSION  hRTCP,
  921.                 IN  INT32         prev,
  922.                 IN  INT32 *       ssrc)
  923. {
  924.     rtcpSession *s = (rtcpSession *)hRTCP;
  925.     rtcpInfo* info;
  926.     INT32 index, doAgain = 1;
  927.     if (prev < 0)
  928.         index = 0;
  929.     else
  930.         index = prev+1;
  931.     while ((doAgain == 1)&&(index < s->sessionMembers))
  932.     {
  933.         info = &s->participantsArray[index];
  934.         if (!info->invalid)
  935.         {
  936.             doAgain = 0;
  937.             *ssrc = info->ssrc;
  938.         }
  939.         else
  940.         {
  941.             index++;
  942.         }
  943.     }
  944.     if (index < s->sessionMembers)
  945.         return index;
  946.     else
  947.         return -1;
  948. }
  949. RVAPI
  950. INT32 RVCALLCONV rtcpCreateRTCPPacket(
  951.                 IN      HRTCPSESSION  hRTCP,
  952.                 IN OUT  BUFFER *      buf)
  953. {
  954.     rtcpSession *s = (rtcpSession *)hRTCP;
  955.     rtcpHeader head;
  956.     UINT32 allocated = 0;
  957.     BUFFER bufC;
  958.     rtcpType type = RTCP_SR;
  959.     int            index;
  960.     if (buffValid(buf, SIZEOF_RTCPHEADER + SIZEOF_SR))
  961.     {
  962.         RV_UINT64 myTime = s->myInfo.eSR.tNNTP;
  963.         UINT8 cc = 0;
  964.         rtcpInfo *info;
  965.         allocated = SIZEOF_RTCPHEADER;
  966.         if (s->myInfo.active)
  967.         {
  968.             s->myInfo.active = FALSE;
  969.             bufC = buffCreate(&(s->myInfo.eSR), SIZEOF_SR);
  970.             buffAddToBuffer(buf, &bufC, allocated);
  971.             liConvertHeader2l(buf->buffer + allocated, 0, (int)W32Len(bufC.length));
  972.             allocated += SIZEOF_SR;
  973.         }
  974.         else
  975.         {
  976.             type = RTCP_RR;
  977.         }
  978.         index = 0;
  979.         while( index < s->sessionMembers)
  980.         {
  981.             info = &s->participantsArray[index];
  982.             if (info->active)
  983.             {
  984.                 info->eToRR.bfLost     = getLost    (&(info->src));
  985.                 info->eToRR.nJitter    = getJitter  (&(info->src));
  986.                 info->eToRR.nExtMaxSeq = getSequence(&(info->src));
  987.                 info->eToRR.tDLSR      =
  988.                     (info->tLSRmyTime) ?
  989.                     (reduceNNTP(myTime)-info->tLSRmyTime) :
  990.                     0;
  991.                 bufC = buffCreate(&(info->eToRR), SIZEOF_RR);
  992.                 if (buffAddToBuffer(buf, &bufC, allocated))
  993.                 {
  994.                     cc++;
  995.                     if (cc == 32)
  996.                         break;
  997.                     liConvertHeader2l(buf->buffer + allocated, 0,
  998.                                       (int)W32Len(bufC.length));
  999.                     allocated += SIZEOF_RR;
  1000.                 }
  1001.                 info->active = FALSE;
  1002.             }
  1003.            index++;
  1004.         }
  1005.         head = makeHeader(s->myInfo.ssrc, cc, type, (UINT16)allocated);
  1006.         bufC = buffCreate(&head, SIZEOF_RTCPHEADER);
  1007.         buffAddToBuffer(buf, &bufC, 0);
  1008.         /* add an CNAME SDES packet to the compound packet */
  1009.         if (buffValid(buf,
  1010.             allocated + SIZEOF_RTCPHEADER + SIZEOF_SDES(s->myInfo.eCName)))
  1011.         {
  1012.             BUFFER sdes_buf;
  1013.             /* 'sdes_buf' is inside the compound buffer 'buf' */
  1014.             sdes_buf = buffCreate(buf->buffer + allocated,
  1015.                 (SIZEOF_RTCPHEADER + SIZEOF_SDES(s->myInfo.eCName)));
  1016.             head = makeHeader(s->myInfo.ssrc, 1, RTCP_SDES,
  1017.               (UINT16)sdes_buf.length);
  1018.             memcpy(sdes_buf.buffer, (char *)&head, SIZEOF_RTCPHEADER);
  1019.             memcpy(sdes_buf.buffer + SIZEOF_RTCPHEADER, &(s->myInfo.eCName),
  1020.                    SIZEOF_SDES(s->myInfo.eCName));
  1021.             allocated += sdes_buf.length;
  1022.         }
  1023.         if (s->myInfo.collision == 1  &&
  1024.             buffValid(buf, allocated + SIZEOF_RTCPHEADER))
  1025.         {
  1026.             head = makeHeader(s->myInfo.ssrc, 1, RTCP_BYE,
  1027.                               SIZEOF_RTCPHEADER);
  1028.             bufC = buffCreate(&head, SIZEOF_RTCPHEADER);
  1029.             buffAddToBuffer(buf, &bufC, allocated);
  1030.             s->myInfo.collision = 2;
  1031.             allocated += SIZEOF_RTCPHEADER;
  1032.         }
  1033.     }
  1034.     buf->length = allocated;
  1035.     return 0;
  1036. }
  1037. RVAPI
  1038. INT32 RVCALLCONV rtcpProcessCompoundRTCPPacket(
  1039.         IN      HRTCPSESSION  hRTCP,
  1040.         IN OUT  BUFFER *      buf,
  1041.         IN      RV_UINT64        myTime)
  1042. {
  1043.     rtcpSession *s = (rtcpSession *)hRTCP;
  1044.     rtcpHeader *head;
  1045.     BYTE *currPtr = buf->buffer, *dataPtr, *compoundEnd;
  1046.     int hdr_count, hdr_len;
  1047.     rtcpType hdr_type;
  1048.     compoundEnd = buf->buffer + buf->length;
  1049.     while (currPtr < compoundEnd)
  1050.     {
  1051.         if ((compoundEnd + 1 - currPtr) < 1)
  1052.         {
  1053.             return ERR_RTCP_ILLEGALPACKET;
  1054.         }
  1055.         head = (rtcpHeader*)(currPtr);
  1056.         liConvertHeader2l(currPtr, 0, 1);
  1057.         hdr_count = bitfieldGet(head->bits, HEADER_RC, HDR_LEN_RC);
  1058.         hdr_type  = (rtcpType)bitfieldGet(head->bits, HEADER_PT, HDR_LEN_PT);
  1059.         hdr_len   = sizeof(UINT32) *
  1060.                     (bitfieldGet(head->bits, HEADER_len, HDR_LEN_len));
  1061.         if ((compoundEnd - currPtr) < hdr_len)
  1062.         {
  1063.             return ERR_RTCP_ILLEGALPACKET;
  1064.         }
  1065.         dataPtr = (BYTE *)head + sizeof(UINT32);
  1066.         rtcpProcessRTCPPacket(s, dataPtr, hdr_len, hdr_type, hdr_count,
  1067.                               myTime);
  1068.         currPtr += hdr_len + sizeof(UINT32);
  1069.     }
  1070.     return 0;
  1071. }
  1072. RVAPI
  1073. INT32 RVCALLCONV rtcpProcessRTCPPacket(
  1074.         IN  rtcpSession *  s,
  1075.         IN  BYTE *         data,
  1076.         IN  INT32          dataLen,
  1077.         IN  rtcpType       type,
  1078.         IN  INT32          reportCount,
  1079.         IN  RV_UINT64      myTime)
  1080. {
  1081.     unsigned scanned = 0;
  1082.     rtcpInfo info, *fInfo=NULL;
  1083.     if (dataLen == 0)
  1084.         return 0;
  1085.     switch(type)
  1086.     {
  1087.         case RTCP_SR:
  1088.         case RTCP_RR:
  1089.         {
  1090.             liConvertHeader2l(data, 0, 1);
  1091.             info.ssrc = *(UINT32 *)(data);
  1092.             scanned = sizeof(UINT32);
  1093.             if (info.ssrc == s->myInfo.ssrc)
  1094.             {
  1095.                 s->myInfo.collision = 1;
  1096.                 return ERR_RTCP_SSRCCOLLISION;
  1097.             }
  1098.             fInfo = findSSrc(s,info.ssrc);
  1099.             if (!fInfo) /* New source */
  1100.             {
  1101.                 /* insert the new source */
  1102. #ifndef RTP_NOLOCKS
  1103.                 mutexLock(s->hMutex);
  1104. #endif
  1105.                 fInfo = insertNewSSRC(s, *(UINT32 *)data);
  1106. #ifndef RTP_NOLOCKS
  1107.                 mutexUnlock(s->hMutex);
  1108. #endif
  1109.             }
  1110.             break;
  1111.         }
  1112.         default:
  1113.             break;
  1114.     }
  1115.     /* process the information */
  1116.     switch(type)
  1117.     {
  1118.         case RTCP_SR:
  1119.         {
  1120.             liConvertHeader2l(data + scanned, 0, W32Len(sizeof(rtcpSR)));
  1121.             if (fInfo)
  1122.             {
  1123.                 fInfo->eSR        = *(rtcpSR *)(data + scanned);
  1124.                 fInfo->eToRR.tLSR = reduceNNTP(fInfo->eSR.tNNTP);
  1125.                 fInfo->tLSRmyTime = reduceNNTP(myTime);
  1126.             }
  1127.             scanned += SIZEOF_SR;
  1128.         }
  1129.         /* fall into RR */
  1130.         case RTCP_RR:
  1131.         {
  1132.             if (fInfo)
  1133.             {
  1134.                 int i;
  1135.                 rtcpRR* rr = (rtcpRR*)(data + scanned);
  1136.                 liConvertHeader2l(data + scanned, 0,
  1137.                                   reportCount * W32Len(sizeof(rtcpRR)));
  1138.                 for (i=0; i < reportCount; i++)
  1139.                 {
  1140.                     if (rr[i].ssrc == s->myInfo.ssrc)
  1141.                     {
  1142.                         fInfo->eFromRR = rr[i];
  1143.                         break;
  1144.                     }
  1145.                 }
  1146.             }
  1147.             break;
  1148.         }
  1149.         case RTCP_SDES:
  1150.         {
  1151.             int i;
  1152.             rtcpSDES *sdes;
  1153.             for (i = 0; i < reportCount; i++)
  1154.             {
  1155.                 liConvertHeader2l(data + scanned, 0, 1);
  1156.                 info.ssrc = *(UINT32 *)(data + scanned);
  1157.                 sdes = (rtcpSDES *)(data + scanned + sizeof(info.ssrc));
  1158.                 fInfo = findSSrc(s,info.ssrc);
  1159.                 if (fInfo)
  1160.                 {
  1161.                     switch(sdes->type)
  1162.                     {
  1163.                         case RTCP_SDES_CNAME:
  1164.                             memcpy(&(fInfo->eCName), sdes,
  1165.                                    SIZEOF_SDES(*sdes));
  1166.                             fInfo->eCName.value[sdes->length] = 0;
  1167.                             break;
  1168. /* known SDES types that are not handled:
  1169.                         case RTCP_SDES_END:
  1170.                         case RTCP_SDES_NAME:
  1171.                         case RTCP_SDES_EMAIL:
  1172.                         case RTCP_SDES_PHONE:
  1173.                         case RTCP_SDES_LOC:
  1174.                         case RTCP_SDES_TOOL:
  1175.                         case RTCP_SDES_NOTE:
  1176.                         case RTCP_SDES_PRIV:
  1177.                             break;
  1178. */
  1179.                         }
  1180.                     }
  1181.                     scanned += SIZEOF_SDES(*sdes) + sizeof(UINT32);
  1182.                 }
  1183.             break;
  1184.         }
  1185.         case RTCP_BYE:
  1186.         {
  1187.             int i;
  1188.             for (i = 0; i < reportCount; i++)
  1189.             {
  1190.                 liConvertHeader2l(data + scanned, 0, 1);
  1191.                 info.ssrc = *(UINT32 *)(data + scanned);
  1192.                 scanned += sizeof(info.ssrc);
  1193.                 fInfo = findSSrc(s,info.ssrc);
  1194.                 if (fInfo)
  1195.                 {
  1196.                     /* We don't really delete this SSRC, we just mark it as invalid */
  1197.                     fInfo->invalid = TRUE;
  1198.                     fInfo->ssrc    = 0;
  1199.                 }
  1200.             }
  1201.             break;
  1202.         }
  1203.         case RTCP_APP:
  1204.             break;
  1205.     }
  1206.     return 0;
  1207. }
  1208. static void RVCALLCONV rtcpTimerCallback(void* key)
  1209. {
  1210.     rtcpSession* s = (rtcpSession*)key;
  1211.     UINT32 buffer[MAXRTCPPACKET/sizeof(UINT32)+1];
  1212.     BUFFER buf;
  1213.     buf = buffCreate(buffer,MAXRTCPPACKET);
  1214.     /* s->tElem =mtimerSet(hst,rtcpTimerCallback,s,5000  should be calculated); */
  1215.     rtcpCreateRTCPPacket((HRTCPSESSION)s, &buf);
  1216.     liUdpSend(s->socket, buf.buffer, (int)buf.length, s->ip, s->port);
  1217. }
  1218. static void rtcpLiCallback(int socket, liEvents event, int error,
  1219.                            void *context)
  1220. {
  1221.     rtcpSession* s = (rtcpSession*)context;
  1222.     UINT32 ip;
  1223.     UINT16 port;
  1224.     UINT32 buffer[MAXRTCPPACKET/sizeof(UINT32)+1];
  1225.     BUFFER buf;
  1226.     if(socket || event || error);
  1227.     if (s == NULL)
  1228.         return;
  1229.     buf = buffCreate(buffer, MAXRTCPPACKET);
  1230.     buf.length = liUdpRecv(s->socket, buf.buffer, (int)buf.length, &ip, &port);
  1231.     if (port != liGetSockPort(s->socket) || !isMyIP(ip))
  1232.     {
  1233.         INT32 res=rtcpProcessCompoundRTCPPacket((HRTCPSESSION)s, &buf, getNNTPTime());
  1234.         if ((res==0) && (s->rtcpRecvCallback != NULL))
  1235.         {
  1236.            UINT32 ssrc=getSSRCfrom(buf.buffer);
  1237.            s->rtcpRecvCallback((HRTCPSESSION)s, s->haRtcp, ssrc);
  1238.         }
  1239.     }
  1240. }
  1241. static RV_UINT64 getNNTPTime(void)
  1242. {
  1243.     const  UINT32 from1900Till1970 = (UINT32)2208988800ul;
  1244.     static UINT32 startTime = 0;
  1245.     static UINT32 startMilliTime = 0;
  1246.     RV_UINT64 nntpTime;
  1247.     if (!startTime)
  1248.     {
  1249.         startTime = (UINT32)time(NULL) + from1900Till1970;
  1250.         startMilliTime = timerGetTimeInMilliseconds();
  1251.     }
  1252.     nntpTime.msdw = startTime;
  1253.     nntpTime.lsdw = timerGetTimeInMilliseconds() - startMilliTime;
  1254.     nntpTime.msdw += nntpTime.lsdw/1000;
  1255.     nntpTime.lsdw %= 1000;
  1256.     nntpTime.lsdw *= 4294967;
  1257.     return nntpTime;
  1258. }
  1259. static BOOL isMyIP(UINT32 ip)
  1260. {
  1261.     int i;
  1262.     for (i=0; myIPs[i]; i++)
  1263.     {
  1264.         if (ip == myIPs[i])
  1265.         {
  1266.             return TRUE;
  1267.         }
  1268.     }
  1269.     return FALSE;
  1270. }
  1271. static void setSDES(rtcpSDesType type, rtcpSDES* sdes, BYTE *data, int length)
  1272. {
  1273.     sdes->type   = (unsigned char)type;
  1274.     sdes->length = (unsigned char)length;
  1275.     memcpy(sdes->value,        data, length);
  1276.     memset(sdes->value+length, 0,    4-((length+2)%sizeof(UINT32)));
  1277. }
  1278. static void init_seq(rtpSource *s, UINT16 seq)
  1279. {
  1280.    s->base_seq       = seq;
  1281.    s->max_seq        = seq;
  1282.    s->bad_seq        = RTP_SEQ_MOD + 1;
  1283.    s->cycles         = 0;
  1284.    s->received       = 0;
  1285.    s->received_prior = 0;
  1286.    s->expected_prior = 0;
  1287. }
  1288. static int update_seq(rtpSource *s, UINT16 seq, UINT32 ts, UINT32 arrival)
  1289. {
  1290.     UINT16 udelta = (UINT16)(seq - s->max_seq);
  1291.     if (s->probation)
  1292.     {
  1293.         if (seq == s->max_seq + 1)
  1294.         {
  1295.             s->probation--;
  1296.             s->max_seq = seq;
  1297.             if (s->probation == 0)
  1298.             {
  1299.                 init_seq(s, seq);
  1300.                 s->received++;
  1301.                 return 1;
  1302.             }
  1303.         }
  1304.         else
  1305.         {
  1306.             s->probation = MIN_SEQUENTIAL - 1;
  1307.             s->max_seq = seq;
  1308.         }
  1309.         return 0;
  1310.     }
  1311.     else if (udelta < MAX_DROPOUT)
  1312.     {
  1313.         if (seq < s->max_seq) s->cycles += RTP_SEQ_MOD;
  1314.         s->max_seq = seq;
  1315.     }
  1316.     else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER)
  1317.     {
  1318.         if (seq == s->bad_seq)
  1319.         {
  1320.             init_seq(s, seq);
  1321.         }
  1322.         else
  1323.         {
  1324.             s->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
  1325.             return 0;
  1326.         }
  1327.     }
  1328.     else
  1329.     {
  1330.    /* duplicate or reordered packet */
  1331.     }
  1332.     {
  1333.         INT32  transit = (INT32)(arrival - ts);
  1334.         INT32  d = (INT32)(transit - s->transit);
  1335.         s->transit = transit;
  1336.         if (d < 0) d = -d;
  1337.         s->jitter += d - ((s->jitter + 8) >> 4);
  1338.     }
  1339.     s->received++;
  1340.     return 1;
  1341. }
  1342. /*=========================================================================**
  1343. **  == makeHeader() ==                                                     **
  1344. **                                                                         **
  1345. **  Creates an RTCP packet header.                                         **
  1346. **                                                                         **
  1347. **  PARAMETERS:                                                            **
  1348. **      ssrc       A synchronization source value for the RTCP session.    **
  1349. **                                                                         **
  1350. **      count      A count of sender and receiver reports in the packet.   **
  1351. **                                                                         **
  1352. **      type       The RTCP packet type.                                   **
  1353. **                                                                         **
  1354. **      dataLen    The length of the data in the packet buffer, in         **
  1355. **                 octets, including the size of the header.               **
  1356. **                                                                         **
  1357. **  RETURNS:                                                               **
  1358. **      The function returns a header with the appropriate parameters.     **
  1359. **                                                                         **
  1360. **=========================================================================*/
  1361. static rtcpHeader makeHeader(UINT32 ssrc, UINT8 count, rtcpType type,
  1362.                              UINT16 dataLen)
  1363. {
  1364.     rtcpHeader header;
  1365.     header.ssrc = ssrc;
  1366.     header.bits = RTCP_HEADER_INIT;
  1367.     header.bits = bitfieldSet(header.bits, count, HEADER_RC, HDR_LEN_RC);
  1368.     header.bits = bitfieldSet(header.bits, type,  HEADER_PT, HDR_LEN_PT);
  1369.     header.bits = bitfieldSet(header.bits, W32Len(dataLen) - 1,
  1370.                               HEADER_len, HDR_LEN_len);
  1371.     liConvertHeader2h((UINT8 *)&header, 0, W32Len(SIZEOF_RTCPHEADER));
  1372.     return header;
  1373. }
  1374. static UINT32 getLost(rtpSource *s)
  1375. {
  1376.     UINT32 extended_max;
  1377.     UINT32 expected;
  1378.     INT32  received_interval;
  1379.     INT32  expected_interval;
  1380.     INT32  lost;
  1381.     INT32  lost_interval;
  1382.     UINT8  fraction;
  1383.     extended_max = s->cycles + s->max_seq;
  1384.     expected = extended_max - s->base_seq + 1;
  1385.     lost = expected - s->received;
  1386.     expected_interval = expected - s->expected_prior;
  1387.     s->expected_prior = expected;
  1388.     received_interval = s->received - s->received_prior;
  1389.     s->received_prior = s->received;
  1390.     lost_interval = expected_interval - received_interval;
  1391.     if (expected_interval == 0  ||  lost_interval <= 0)
  1392.         fraction = 0;
  1393.     else
  1394.         fraction = (UINT8)((lost_interval << 8) / expected_interval);
  1395.     return (fraction << 24) + lost;
  1396. }
  1397. static UINT32 getJitter(rtpSource *s)
  1398. {
  1399.     return s->jitter >> 4;
  1400. }
  1401. static UINT32 getSequence(rtpSource *s)
  1402. {
  1403.     return s->max_seq + s->cycles;
  1404. }
  1405. static UINT32 getSSRCfrom(BYTE *head)
  1406. {
  1407.    BYTE *ssrcPtr = (BYTE *)head + sizeof(UINT32);
  1408.    return *(UINT32 *)(ssrcPtr);
  1409. }
  1410. static rtcpInfo *findSSrc(rtcpSession *s, UINT32 ssrc)
  1411. {
  1412.     int     index = 0;
  1413.     BOOL    doAgain = TRUE;
  1414.     rtcpInfo *pInfo;
  1415.     if (s == NULL)
  1416.         return NULL;
  1417.     /* Look for the given SSRC */
  1418.     while ((doAgain) && (index < s->sessionMembers))
  1419.     {
  1420.        if (s->participantsArray[index].ssrc == ssrc)
  1421.             doAgain = FALSE;
  1422.        else
  1423.            index ++;
  1424.     }
  1425.     if (index < s->sessionMembers )
  1426.         pInfo = &s->participantsArray[index];
  1427.     else
  1428.         pInfo = NULL;
  1429.     return pInfo;
  1430. }
  1431. static rtcpInfo *insertNewSSRC(rtcpSession *s, UINT32 ssrc)
  1432. {
  1433.     rtcpInfo* pInfo = NULL;
  1434.     int index;
  1435.     if (s->sessionMembers >= s->maxSessionMembers)
  1436.     {
  1437.         /* We've got too many - see if we can remove some old ones */
  1438.         index = 0;
  1439.         while ((index < s->sessionMembers) &&
  1440.                (s->participantsArray[index].invalid && s->participantsArray[index].ssrc == 0))
  1441.             index++;
  1442.     }
  1443.     else
  1444.     {
  1445.         /* Add it as a new one to the list */
  1446.         index = s->sessionMembers;
  1447.         s->sessionMembers++;
  1448.     }
  1449.     if (index < s->sessionMembers)
  1450.     {
  1451.         /* Got a place for it ! */
  1452.         pInfo = &s->participantsArray[index];
  1453.         memset(pInfo, 0, sizeof(rtcpInfo));
  1454.         pInfo->ssrc             = ssrc;
  1455.         pInfo->eToRR.ssrc       = ssrc;
  1456.         pInfo->active           = FALSE;
  1457.         pInfo->src.probation    = MIN_SEQUENTIAL - 1;
  1458.     }
  1459.     return pInfo;
  1460. }
  1461.                   /* == ENDS: Internal RTCP Functions == */
  1462. #ifdef __cplusplus
  1463. }
  1464. #endif