⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtcp.c

📁 h.248协议源码
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef __cplusplus
extern "C" {
#endif

/*

NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever without 
written prior approval by RADVision LTD.

RADVision LTD. reserves the right to revise this publication and make changes 
without obligation to notify any person of such revisions or changes.

*/ 

/****************************************************************************
  
  rtcp.c  --  RTCP implementation.

  This Comment:   16-Mar-1997
  Module Authors: Sasha Ruditsky, Oz Solomonovich

  Abstract:       The main RTCP module file.  

  Platforms:      All.
  
  Known Bugs:     Problems working on the GW.

****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "rvcore.h"
#include "rvmem.h"
#include "rvlist.h"
#include "rvtimer.h"
#include "rvdefalloc.h"
#include "rvtime.h"
#include "rvmutex.h"
#include "rvhost.h"
#include "rvinet.h"
#include "rvsocket.h"
#include "rvsocketaddr.h"
#include "rvsocketengine.h"
#include "buffer.h"
#include "bitfield.h"
#include "rtputil.h"
#include "rtcp.h"

#if defined(RV_OS_SOLARIS) || defined(RV_OS_REDHAT) || defined(RV_OS_TRU64) || defined(RV_OS_HPUX)
#define SOCKENGINE_TASK_PRIORITY 0
#endif
#if defined(RV_OS_WIN32)
#define SOCKENGINE_TASK_PRIORITY 60
#endif
#if defined(RV_OS_VXWORKS) || defined(RV_OS_NUCLEUS)
#define SOCKENGINE_TASK_PRIORITY 40
#endif
#if defined(RV_OS_PSOS)
#define SOCKENGINE_TASK_PRIORITY 170
#endif
#if defined(RV_OS_OSE)
#define SOCKENGINE_TASK_PRIORITY 16
#endif

#define MAXSDES                   255
#define MAXRTPSESSIONS            10
#define MAXRTPSESSIONMEMBERS      50
#define MAXRTCPPACKET             1470

#define MAX_DROPOUT               3000
#define MAX_MISORDER              100
#define MIN_SEQUENTIAL            2
#define RTP_SEQ_MOD               0x10000 

/* RTCP header bit locations - see the standard */
#define HEADER_V                  30      /* version                       */
#define HEADER_P                  29      /* padding                       */
#define HEADER_RC                 24      /* reception report count        */
#define HEADER_PT                 16      /* packet type                   */
#define HEADER_len                0       /* packet length in 32-bit words */

/* RTCP header bit field lengths - see the standard */
#define HDR_LEN_V                 2       /* version                       */
#define HDR_LEN_P                 1       /* padding                       */
#define HDR_LEN_RC                5       /* reception report count        */
#define HDR_LEN_PT                8       /* packet type                   */
#define HDR_LEN_len               16      /* packet length in 32-bit words */

/* used to overcome byte-allignment issues */
#define SIZEOF_RTCPHEADER         (sizeof(RvUint32) * 2)
#define SIZEOF_SR                 (sizeof(RvUint32) * 5)
#define SIZEOF_RR                 (sizeof(RvUint32) * 6)

#define SIZEOF_SDES(sdes)         (((sdes).length + 6) & 0xfc)

/* initial bit field value for RTCP headers: V=2,P=0,RC=0,PT=0,len=0 */
#define RTCP_HEADER_INIT          0x80000000

typedef enum {
   RTCP_SR   = 200,               /* sender report            */
   RTCP_RR   = 201,               /* receiver report          */
   RTCP_SDES = 202,               /* source description items */
   RTCP_BYE  = 203,               /* end of participation     */
   RTCP_APP  = 204                /* application specific     */
} rtcpType;

typedef enum {
   RTCP_SDES_END   = 0,
   RTCP_SDES_CNAME = 1,
   RTCP_SDES_NAME  = 2,
   RTCP_SDES_EMAIL = 3,
   RTCP_SDES_PHONE = 4,
   RTCP_SDES_LOC   = 5,
   RTCP_SDES_TOOL  = 6,
   RTCP_SDES_NOTE  = 7,
   RTCP_SDES_PRIV  = 8
} rtcpSDesType;

typedef struct 
{
   RvUint32  msdw;
   RvUint32  lsdw;
} RvUint64; 

typedef struct
{
   RvUint64  tNNTP;
   RvUint32  tRTP;       
   RvUint32  nPackets;
   RvUint32  nBytes;
} rtcpSR;

typedef struct
{
   RvUint32  ssrc;
   RvUint32  bfLost;      /* 8Bit fraction lost and 24 bit cumulative lost */
   RvUint32  nExtMaxSeq;
   RvUint32  nJitter;
   RvUint32  tLSR;
   RvUint32  tDLSR;
} rtcpRR;

typedef struct {
   RvUint16  max_seq;               /* highest seq. number seen */
   RvUint32  cycles;                /* shifted count of seq. number cycles */
   RvUint32  base_seq;              /* base seq number */
   RvUint32  bad_seq;               /* last 'bad' seq number + 1 */
   RvUint32  probation;             /* sequ. packets till source is valid */
   RvUint32  received;              /* packets received */
   RvUint32  expected_prior;        /* packet expected at last interval */
   RvUint32  received_prior;        /* packet received at last interval */
   RvUint32  transit;               /* relative trans time for prev pkt */
   RvUint32  jitter;                /* estimated jitter */
   /* ... */
} rtpSource;

typedef struct 
{
   RvUint8  type;
   RvUint8  length;
   char   value[MAXSDES + 1];     /* leave a place for an asciiz */
} rtcpSDES;

typedef struct
{
   int invalid;
   RvBool active;
   rtpSource src;
   RvUint32 ssrc; 
   RvUint32 tLSRmyTime; 
   rtcpSR eSR;
   rtcpRR eToRR;
   rtcpRR eFromRR;        
   rtcpSDES eCName;
} rtcpInfo;

RvBool rtcpInfoEqual(const rtcpInfo *a, const rtcpInfo *b)
{
	return a == b; /* TODO? */
}

#define rtcpInfoConstructCopy rvDefaultConstructCopy
#define rtcpInfoDestruct rvDefaultDestruct

typedef struct
{
   RvUint32  bits; 
   RvUint32  ssrc; 
} rtcpHeader;


typedef struct
{
   RvBool active;
   int collision;
   RvUint32 ssrc; 
   RvUint32 timestamp;
   rtcpSR eSR;
   rtcpSDES eCName;
} rtcpMyInfo;

rvDeclareList(rtcpInfo)
rvDefineList(rtcpInfo)

typedef struct 
{
   RvMutex mutex;
   RvBool isAllocated;	
   int socket;
   RvList(rtcpInfo) hList;             /* list of session members */
   rtcpMyInfo myInfo;
   RvUint32 ip;
   RvUint16 port;
   RvTimer tElem;
   RvSocketListener listener;
   RvUint32 rtt;
   int numOfRRs;
} rtcpSession;

#define RTCP_TIMEOUT 5000

static RvHost host;
static RvSocketEngine engine;

#define reduceNNTP(a) (((a).msdw<<16)+((a).lsdw>>16))
#define W32Len(l)  ((l + 3) / 4)  /* length in 32-bit words */

RVVXDAPI
RvInt32 VXDCALLCONV rtcpCreateRTCPPacket(
                IN      HRTCPSESSION  hRTCP,  
                IN OUT  RV_BUFFER *      buf);
RVVXDAPI
RvInt32 VXDCALLCONV rtcpProcessRTCPPacket(
        IN  rtcpSession *  s,
        IN  RvUint8 *         data,
        IN  RvInt32          dataLen,
        IN  rtcpType       type,
        IN  RvInt32          reportCount,
        IN  RvUint64         myTime);
RVVXDAPI
RvInt32 VXDCALLCONV rtcpProcessCompoundRTCPPacket(
        IN      HRTCPSESSION  hRTCP,
        IN OUT  RV_BUFFER *      buf,
        IN      RvUint64        myTime);

/* local functions */
static RvBool isMyIP(RvSocketAddr* addr)
{
    size_t i;

    for (i=0; i < rvHostGetNumOfAddrs(&host); i++)
    {
        if (rvIpv4AddrToUint32(rvSocketAddrGetIpv4Addr(addr)) == 
			rvIpv4AddrToUint32(rvHostGetIpv4Addr(&host, i)))
            return rvTrue;
    }

    return rvFalse;
}

static RvUint64 getNNTPTime(void)
{
	static RvTimespec startwalltime, startlineartime;
	static int firstcall = 0;
	RvTimespec currenttime, difftime, newtime;
	RvNtpTime newNTP;
	RvUint64 nntpTime;
    
    if (!firstcall) {
		rvTimeGetEpochTime(&startwalltime);
		rvTimeGetHires(&startlineartime);
		firstcall = 1;
    }

	rvTimeGetHires(&currenttime);
	rvTimeSubtract(&difftime, &currenttime, &startlineartime);
	rvTimeAdd(&newtime, &difftime, &startwalltime);
	rvTimeConvertNTP(&newtime, &newNTP, RV_NTP_TIME_ABSOLUTE);
    nntpTime.msdw = rvNtpTimeGetSecs(&newNTP);
	nntpTime.lsdw = rvNtpTimeGetFraction(&newNTP);

    return nntpTime;
}

static RvUint32 computeRoundTripTime(rtcpRR* rr) {
	RvUint32 rtt = reduceNNTP(getNNTPTime()) - rr->tDLSR - rr->tLSR;
	RvUint32 ms = ((rtt >> 16) * 1000) +
	  (((rtt & 0x0000FFFF) * 1000) / 0x10000);
	return ms;
}
  
static void setSDES(rtcpSDesType type, rtcpSDES* sdes, RvUint8 *data, int length)
{
    sdes->type   = (unsigned char)type;
    sdes->length = (unsigned char)length;
    memcpy(sdes->value,        data, length);
    memset(sdes->value+length, 0,    4-((length+2)%sizeof(RvUint32)));
}

static void init_seq(rtpSource *s, RvUint16 seq)
{
   s->base_seq       = seq;
   s->max_seq        = seq;
   s->bad_seq        = RTP_SEQ_MOD + 1;
   s->cycles         = 0;
   s->received       = 0;
   s->received_prior = 0;
   s->expected_prior = 0;
}


static int update_seq(rtpSource *s, RvUint16 seq, RvUint32 ts, RvUint32 arrival)
{
    RvUint16 udelta = (RvUint16)(seq - s->max_seq);

    if (s->probation) 
    { 
        if (seq == s->max_seq + 1) 
        {
            s->probation--;
            s->max_seq = seq;
            if (s->probation == 0) 
            {
                init_seq(s, seq);
                s->received++;
                return 1;
            }
        } 
        else 
        {
            s->probation = MIN_SEQUENTIAL - 1;
            s->max_seq = seq;
        }
        return 0;
    } 
    else if (udelta < MAX_DROPOUT) 
    {
        if (seq < s->max_seq) s->cycles += RTP_SEQ_MOD;
        s->max_seq = seq;
    } 
    else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) 
    {
        if (seq == s->bad_seq)
        {
            init_seq(s, seq);
        }
        else 
        {
            s->bad_seq = (seq + 1) & (RTP_SEQ_MOD-1);
            return 0;
        }
    } 
    else 
    {
   /* duplicate or reordered packet */
    }
    {
        RvInt32  transit = (RvInt32)(arrival - ts);
        RvInt32  d = (RvInt32)(transit - s->transit);
        s->transit = transit;
        if (d < 0) d = -d;
        s->jitter += d - ((s->jitter + 8) >> 4);
    }
    s->received++;
    return 1;
}


/*=========================================================================**
**  == makeHeader() ==                                                     **
**                                                                         **
**  Creates an RTCP packet header.                                         **
**                                                                         **
**  PARAMETERS:                                                            **
**      ssrc       A synchronization srouce value for the RTCP session.    **
**                                                                         **
**      count      A count of sender and receiver reports in the packet.   **
**                                                                         **
**      type       The RTCP packet type.                                   **
**                                                                         **
**      dataLen    The length of the data in the packet buffer, in         **
**                 octets, including the size of the header.               **
**                                                                         **
**  RETURNS:                                                               **
**      The function returns a header with the appropriate parameters.     **
**                                                                         **
**=========================================================================*/

static rtcpHeader makeHeader(RvUint32 ssrc, RvUint8 count, rtcpType type, 
                             RvUint16 dataLen)
{
    rtcpHeader header;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -