/* 接收者/发送者计数是最后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); } }
评论