/* 接收者/发送者计数是最后5位 */
#define RTCP_COUNT(octet) ((octet) & 0x1F)
#define RTCP_PT_MIN 192
/* Supplemental H.261 specific RTCP packet types according to Section C.3.5 */
#define RTCP_FIR 192
#define RTCP_NACK 193
#define RTCP_SMPTETC 194
#define RTCP_IJ 195
/* RTCP packet types according to Section A.11.1 */
/* And https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml */
#define RTCP_SR 200
#define RTCP_RR 201
#define RTCP_SDES 202
#define RTCP_BYE 203
#define RTCP_APP 204
#define RTCP_RTPFB 205
#define RTCP_PSFB 206
#define RTCP_XR 207
#define RTCP_AVB 208
#define RTCP_RSI 209
#define RTCP_TOKEN 210
#define RTCP_PT_MAX 210
static const char mon_names[12][4] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
/** data structure to hold time values with nanosecond resolution*/
typedef struct {
time_t secs;
int nsecs;
} nstime_t;
/*
* 1900-01-01 00:00:00 (proleptic?) UTC.
* Used by a number of time formats.
*/
#define EPOCH_DELTA_1900_01_01_00_00_00_UTC 2208988800U
/*
* NTP_BASETIME is in fact epoch - ntp_start_time; ntp_start_time
* is January 1, 2036, 00:00:00 UTC.
*/
#define NTP_BASETIME EPOCH_DELTA_1900_01_01_00_00_00_UTC
#define NTP_FLOAT_DENOM 4294967296.0
#define NTP_TS_SIZE 100
/* 解剖长度字段。附加到此字段的文字表示转换为的实际字节数 (即 (原始值 + 1) * 4) */
static int dissect_rtcp_length_field(u_char *rtcp_info, int offset)
{
uint16_t raw_length = ntohs(*(uint16_t*)(rtcp_info + offset));
printf("(%u bytes)\n", (raw_length+1)*4);
offset += 2;
return offset;
}
static int dissect_rtcp_rr(u_char *rtcp_info, int offset,int count, int packet_length )
{
int counter = 0;
uint8_t rr_flt = 0;
int rr_offset = offset;
counter = 1;
while ( counter <= count ) {
uint32_t lsr = 0, dlsr = 0;
/* Create a new subtree for a length of 24 bytes */
/* SSRC_n source identifier, 32 bits */
offset += 4;
/* Fraction lost, 8bits */
rr_flt = rtcp_info[offset];
offset++;
/* Cumulative number of packets lost, 24 bits */
offset += 3;
/* Sequence number cycles */
offset += 2;
/* highest sequence number received */
offset += 2;
/* Interarrival jitter */
offset += 4;
/* Last SR timestamp */
lsr = ntohl(*(uint32_t*)(rtcp_info + offset));
printf("Last SR timestamp: 0x%x\n",lsr);
offset += 4;
/* Delay since last SR timestamp */
dlsr = ntohl(*(uint32_t*)(rtcp_info + offset));
printf("(%d milliseconds)\n",(int)(((double)dlsr/(double)65536) * 1000.0));
offset += 4;
counter++;
}
return offset;
}
const char *tvb_ntp_fmt_ts_sec(u_char *rtcp_info, int offset)
{
uint32_t tempstmp = 0;
time_t temptime = 0;
struct tm *bd;
char *buff = NULL;
tempstmp = ntohl(*(uint32_t*)(rtcp_info + offset));
if (tempstmp == 0){
return "NULL";
}
/* We need a temporary variable here so the unsigned math
* works correctly (for years > 2036 according to RFC 2030
* chapter 3).
*/
temptime = (time_t)(tempstmp - NTP_BASETIME);
bd = gmtime(&temptime);
if (!bd){
return "Not representable";
}
buff = (char *)malloc(NTP_TS_SIZE);
snprintf(buff, NTP_TS_SIZE,
"%s %2d, %d %02d:%02d:%02d UTC",
mon_names[bd->tm_mon],
bd->tm_mday,
bd->tm_year + 1900,
bd->tm_hour,
bd->tm_min,
bd->tm_sec);
return buff;
}
static int dissect_rtcp_sr(u_char *rtcp_info, int offset,int count, int packet_length)
{
uint32_t ts_msw = 0, ts_lsw = 0;
int sr_offset = offset;
/* NTP timestamp */
ts_msw = ntohl(*(uint32_t*)(rtcp_info + offset));
printf("ts_msw: 0x%x\n",ts_msw);
ts_lsw = ntohl(*(uint32_t*)(rtcp_info + offset + 4));
printf("ts_lsw: 0x%x\n",ts_lsw);
//printf("offset: 0x%x 0x%x 0x%x 0x%x\n",rtcp_info[offset],rtcp_info[offset + 1],rtcp_info[offset + 2],rtcp_info[offset + 3]);
printf("MSW: %s\n",tvb_ntp_fmt_ts_sec(rtcp_info,offset));
offset += 8;
/* RTP timestamp, 32 bits */
offset += 4;
/* Sender's packet count, 32 bits */
offset += 4;
/* Sender's octet count, 32 bits */
offset += 4;
/* The rest of the packet is equal to the RR packet */
if ( count != 0 )
offset = dissect_rtcp_rr(rtcp_info, offset, count, packet_length-(offset-sr_offset));
else
{
/* If length remaining, assume profile-specific extension bytes */
if ((offset-sr_offset) < packet_length)
{
offset = sr_offset + packet_length;
}
}
return offset;
}
static int dissect_rtcp_sdes(u_char *rtcp_info, int offset, int count)
{
int chunk = 0;
int start_offset = 0;
int items_start_offset = 0;
uint32_t ssrc = 0;
unsigned int item_len = 0;
unsigned int sdes_type = 0;
unsigned int prefix_len = 0;
chunk = 1;
while ( chunk <= count )
{
/* Create a subtree for this chunk; we don't yet know
the length. */
start_offset = offset;
ssrc = ntohl(*(uint32_t*)(rtcp_info + offset));
printf("Chunk %u, SSRC/CSRC 0x%X\n", chunk, ssrc);
/* SSRC_n source identifier, 32 bits */
offset += 4;
/* Create a subtree for the SDES items; we don't yet know
the length */
/*
* Not every message is ended with "null" bytes, so check for
* end of frame as well.
*/
/* ID, 8 bits */
sdes_type = rtcp_info[offset];
printf("Type: %d\n",sdes_type);
if (sdes_type == 0)
break;
offset++;
/* Item length, 8 bits */
item_len = rtcp_info[offset];
printf("Length: %d\n",item_len);
offset++;
char *pszText = (char*)malloc(item_len);
if (pszText != 0)
{
memcpy(pszText, rtcp_info + offset,item_len);
pszText[item_len] = '\0';
printf("Text = %s\n",pszText);
}
chunk++;
}
return offset;
}
static void dissect_rtcp(u_char *rtcp_info,int packet_type, int offset,int PayloadLen)
{
unsigned int temp_byte = 0;
int elem_count = 0;
int packet_length = 0;
int total_packet_length = 0;
int loop = 2;
bool flag_rtcp = false;
/*检查是否为有效类型*/
if ( ( packet_type < RTCP_PT_MIN ) || ( packet_type > RTCP_PT_MAX ) )
exit(-1);
/*
* 获取完整的RTCP数据包的长度
*/
packet_length = (ntohs(*(uint16_t*)(rtcp_info + offset + 1)) + 1) * 4 ;
//printf("packet_length: %d\n",packet_length);
temp_byte = rtcp_info[offset-1];
elem_count = RTCP_COUNT( temp_byte );/* Source count, 5 bits */
printf("Reception report count: %d\n",elem_count);
switch ( packet_type )
{
case RTCP_SR:
case RTCP_RR:
/*
Real-time Transport Control Protocol (Receiver Report)
10.. .... = Version: RFC 1889 Version (2)
..0. .... = Padding: False
...0 0001 = Reception report count: 1
Packet type: Receiver Report (201)
Length: 7 (32 bytes)
Sender SSRC: 0xb584b03e (3045371966)
Source 1
*/
/* Packet type, 8 bits */
offset++;
/* Packet length in 32 bit words MINUS one, 16 bits */
offset = dissect_rtcp_length_field(rtcp_info, offset);
/* Sender Synchronization source, 32 bits */
offset += 4;
if ( packet_type == RTCP_SR )
{
offset = dissect_rtcp_sr(rtcp_info, offset, elem_count, packet_length-8 );
printf("dissect_rtcp_sr\n");
}
else
{
offset = dissect_rtcp_rr(rtcp_info, offset, elem_count, packet_length-8 );
}
//uint16_t second_packet_type = ntohs(*(uint16_t*)(rtcp_info + offset));
//printf("111offset: 0x%x 0x%x 0x%x 0x%x\n",rtcp_info[offset],rtcp_info[offset + 1],rtcp_info[offset + 2],rtcp_info[offset + 3]);
if (rtcp_info[offset + 1] == RTCP_SDES)
{
/* Source count, 5 bits */
offset++;
/* Packet type, 8 bits */
offset++;
/* Packet length in 32 bit words MINUS one, 16 bits */
offset = dissect_rtcp_length_field(rtcp_info, offset);
offset = dissect_rtcp_sdes(rtcp_info,offset,elem_count);
}
break;
default:
/*
* To prevent endless loops in case of an unknown message type
* increase offset. Some time the while will end :-)
*/
offset++;
break;
}
}
static bool dissect_rtcp_heur(u_char *rtcp_info,int PayloadLen)
{
unsigned int offset = 0;
unsigned int first_byte = 0;
unsigned int packet_type = 0;
/* 查看第一个字节 */
first_byte = rtcp_info[offset];
/* 版本位是否设置为2*/
//printf("version: %d\n",((first_byte & 0xC0) >> 6));
if (((first_byte & 0xC0) >> 6) != 2)
{
return false;
}
/* 看包类型 */
offset += 1;
packet_type = rtcp_info[offset];
//printf("packet_type: %d\n",packet_type);
/* 复合数据包中的第一个数据包应该是发送方或接收者报告 */
if (!((packet_type == RTCP_SR) || (packet_type == RTCP_RR) ||
(packet_type == RTCP_BYE) || (packet_type == RTCP_APP) ||
(packet_type == RTCP_PSFB)))
{
return false;
}
/*总长度必须是4个字节的倍数*/
//printf("PayloadLen: %d\n",PayloadLen);
if (PayloadLen % 4)
{
return false;
}
/* OK, dissect as RTCP */
dissect_rtcp(rtcp_info,packet_type,offset,PayloadLen);
return true;
}
static void confirm_rtcp_packet(struct ip *pIp)
{
int iIpTotalLen = ntohs(pIp->ip_len);
int offset = 0;
int nFragSeq = 0;
struct udphdr* pUdpHdr = (struct udphdr*)((char*)pIp + (pIp->ip_hl<<2));
if (pIp->ip_p == IPPROTO_UDP)
{
printf("\n");
int iPayloadLen = iIpTotalLen - (pIp->ip_hl<<2) - 8;
printf("UDP Payload Len %d\n", iPayloadLen);
u_char *pDnsHdr = (u_char*)(pUdpHdr+1);
dissect_rtcp_heur(pDnsHdr,iPayloadLen);
}
}
评论