📄 rtcp.c
字号:
#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(¤ttime);
rvTimeSubtract(&difftime, ¤ttime, &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 + -