📄 rtcp.c
字号:
/***********************************************************************
Copyright (c) 2002 RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Ltd.. No part of this document may be reproduced in any
form whatsoever without written prior approval by RADVISION Ltd..
RADVISION Ltd. reserve the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
***********************************************************************/
#include "rvstdio.h"
#include "rvlock.h"
#include "rvselect.h"
#include "rvsocket.h"
#include "rvmemory.h"
#include "rvclock.h"
#include "rvntptime.h"
#include "rvtime.h"
#include "rvtimer.h"
#include "rvhost.h"
#include "rvrtpbuffer.h"
#include "bitfield.h"
#include "rtputil.h"
#include "rvrtcp.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAXSDES 255
#define MAXRTPSESSIONS 10
#define MAXRTPSESSIONMEMBERS 50
#define MAXRTCPPACKET 1470
#define MAXIPS 20
#define MAX_DROPOUT 3000
#define MAX_MISORDER 100
#define MIN_SEQUENTIAL 2
#define RTP_SEQ_MOD 0x10000
#define ALIGNMENT 0x10
/* 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
{
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;
typedef struct
{
RvUint32 bits;
RvUint32 ssrc;
} rtcpHeader;
typedef struct
{
RvBool active;
int collision;
RvUint32 ssrc;
RvUint32 timestamp;
rtcpSR eSR;
rtcpSDES eCName;
} rtcpMyInfo;
typedef struct
{
RvBool isAllocated;
RvSocket socket;
RvSelectFd selectFd;
rtcpMyInfo myInfo;
RvAddress remoteAddress;
RvBool remoteAddressSet;
RvTimer timer; /* Timer of this RTCP session */
RvBool isTimerSet; /* RV_TRUE if we started a timer for this session */
rtcpInfo* participantsArray;
int sessionMembers;
int maxSessionMembers;
LPRTCPEVENTHANDLER rtcpRecvCallback;
void* haRtcp;
RvLock lock; /* Lock of this session. Used to protect the session members */
} rtcpSession;
#define RV_RTCP_MAXIPS RvUint32Const(20)
/* Internal RTCP instance used. There a single such object */
typedef struct
{
RvSelectEngine* selectEngine; /* select engine used for RTP/RTCP messages */
RvUint32 localIp; /* IP to bind to */
RvUint32 hostIPs[RV_RTCP_MAXIPS]; /* Local host IPs */
RvUint32 timesInitialized; /* Times the RTP was initialized */
RvTimerQueue* timersQueue; /* Timers queue to use */
} RvRtcpInstance;
/* RTCP instance to use */
static RvRtcpInstance rvRtcpInstance;
#define reduceNNTP(a) (RvUint32)((a >> 16) && 0xffffffff)
#define W32Len(l) ((l + 3) / 4) /* length in 32-bit words */
/* local functions */
static RvUint64 getNNTPTime(void);
static RvBool rtcpTimerCallback(IN void* key);
static RvBool isMyIP(RvUint32 ip);
static void setSDES(rtcpSDesType type, rtcpSDES* sdes, RvUint8 *data,
int length);
static void init_seq (rtpSource *s, RvUint16 seq);
static int update_seq(rtpSource *s, RvUint16 seq, RvUint32 ts, RvUint32 arrival);
static RvUint32 getLost (rtpSource *s);
static RvUint32 getJitter (rtpSource *s);
static RvUint32 getSequence(rtpSource *s);
/*h.e 30.05.01*/
static RvUint32 getSSRCfrom(RvUint8 *);
/*===*/
static rtcpHeader makeHeader(RvUint32 ssrc, RvUint8 count, rtcpType type,
RvUint16 dataLen);
static rtcpInfo * findSSrc(rtcpSession *,RvUint32);
static rtcpInfo *insertNewSSRC(rtcpSession *s, RvUint32 ssrc);
static void rtcpEventCallback(
IN RvSelectEngine* selectEngine,
IN RvSelectFd* fd,
IN RvSelectEvents selectEvent,
IN RvBool error);
RVAPI
RvInt32 RVCALLCONV rtcpProcessCompoundRTCPPacket(
IN HRTCPSESSION hRTCP,
IN OUT RvRtpBuffer* buf,
IN RvUint64 myTime);
RVAPI
RvInt32 RVCALLCONV rtcpProcessRTCPPacket(
IN rtcpSession * s,
IN RvUint8 * data,
IN RvInt32 dataLen,
IN rtcpType type,
IN RvInt32 reportCount,
IN RvUint64 myTime);
/* == Basic RTCP Functions == */
/*=========================================================================**
** == rtcpInit() == **
** **
** Initializes the RTCP module. **
** **
** RETURNS: **
** A non-negative value upon success, or a negative integer error **
** code. **
** **
**=========================================================================*/
RVAPI
RvInt32 RVCALLCONV rtcpInit(void)
{
RvStatus status;
status = RvCBaseInit();
if (status != RV_OK)
return status;
status = RvRtpInitSelectEngine(&rvRtcpInstance.selectEngine);
if (status != RV_OK)
{
RvCBaseEnd();
return ERR_RTCP_GENERALERROR;
}
/* Construct a pool of timers to use */
status = RvRtpInitTimerQueue(&rvRtcpInstance.timersQueue);
if (status != RV_OK)
{
RvRtpEndSelectEngine();
RvCBaseEnd();
return ERR_RTCP_GENERALERROR;
}
if (rvRtcpInstance.timesInitialized == 0)
{
RvAddress addresses[RV_RTCP_MAXIPS];
RvUint32 numAddrs = RV_RTCP_MAXIPS;
RvUint32 i;
rvRtcpInstance.localIp = 0;
/* Find the list of host addresses we have */
status = RvHostLocalGetAddress(&numAddrs, addresses);
if (status != RV_OK)
{
RvRtpEndTimerQueue();
RvRtpEndSelectEngine();
RvCBaseEnd();
return ERR_RTCP_GENERALERROR;
}
for (i = 0; i < numAddrs; i++)
rvRtcpInstance.hostIPs[i] = RvAddressIpv4GetIp(RvAddressGetIpv4(addresses + i));
}
rvRtcpInstance.timesInitialized++;
return RV_OK;
}
/*=========================================================================**
** == rtcpInitEx() == **
** **
** Initializes the RTCP module. **
** Parameter: ip - ip address to 'bind' RTCP session **
** **
** RETURNS: **
** A non-negative value upon success, or a negative integer error **
** code. **
** **
**=========================================================================*/
RVAPI
RvInt32 RVCALLCONV rtcpInitEx(RvUint32 ip)
{
RvInt32 rc;
if ((rc=rtcpInit()) >= 0)
{
rvRtcpInstance.localIp = ip;
}
return rc;
}
/*=========================================================================**
** == rtcpEnd() == **
** **
** Shuts down the RTCP module. **
** **
** RETURNS: **
** A non-negative value upon success, or a negative integer error **
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -