GB28181 TCP 模式 RTP wireshark 数据诊断分析

概述

关于RTP协议诊断,我们通常需要分析RTP头,扩展头,尤其是如SSRC, 时间戳,序号,mark标记从而进一步判定数据封包规范性,丢包及其网络抖动等问题,而wireshark 本是网络数据包分析利器,能根据SDP(RTSP/SIP交互)自动完成RTP协议解析,但针对TCP承载RTP只能自动解析RTSP隧道模式,针对GB28181使用的TCP承载RTP无法自动识别,

解决方式

有3种方式可以实现wireshark扩展支持该模式下的RTP协议自动解析(处理TCP粘包)

1. 基于LUA自实现wireshark插件

2. 基于c方式扩展wireshark插件

3. 通过wireshark+自定义工具组合方式解析


其中2方式难度较大,方式1可采用顶层插件解决TCP粘包识别,解析前2个字节长度,然后二次调用wireshark RTP解析器,需要有一定LUA脚本基础,方式3最为简单。

方式3: 可以通过wireshark跟踪原始tcp流以raw方式导出纯二进制文件,再简单文件处理即可导出纯RTP负载数据.

如GB28181中ps负载可导出mpg文件,vlc可以直接播放验证数据正确性,同时输出RTP相关字段值内容。

源码示例

#include <stdio.h>

#include <Winsock2.h>

#pragma comment(lib, "ws2_32.lib")

int main()
{
	unsigned char* buffer = new unsigned char[10240];

	FILE* readfile = fopen("gbdata", "rb");
	if (NULL == readfile)
	{
		printf("open read file failed, check gbdata file!\n");
		return -1;
	}

	FILE* logfile = fopen("RTP.log", "w");
	if (NULL == readfile)
	{
		printf("open rtp file error!\n");
		fclose(readfile);
		return -1;
	}

	FILE* writefile = fopen("gb.mpg", "wb");
	if (NULL == writefile)
	{
		printf("open video file error!\n");
		fclose(readfile);
		fclose(logfile);
		return -1;
	}

	int len = 0;
	int size = 0;
    int last = 0;
	while(!feof(readfile))
	{
		if (fread(&len, 2, 1, readfile) <= 0)
		{
			break;
		}
		size = ntohs(len);

		if (fread(buffer, size, 1, readfile) <= 0)
		{
			break;
		}

        bool padding = false;
        if (buffer[0] & 0x20)
            padding = true;

		unsigned int tm = 0;
		unsigned int seq = 0;
		unsigned int ssrc = 0;
        if (last == 0) {
            last = seq;
        }

        int mark = (buffer[1] & 0x80) >> 7;
		seq = buffer[2] << 8 | buffer[3];
		tm = buffer[4] << 24 | buffer[5] << 16 |  buffer[6] << 8 |  buffer[7];
		ssrc = buffer[8] << 24 | buffer[9] << 16 |  buffer[10] << 8 |  buffer[11];;
        unsigned char paddingLen = 0;
        if (padding) {
            paddingLen = buffer[size - 1];
        }

        if (paddingLen > 3) {
            printf("Error: padding > 3 bytes!\n");
            return 0;
        }

		char rtp[128] = {0};
		sprintf(rtp, "size:% 10d | seq:% 10u | time:% 10u | ssrc:% 10u | padding:%d paddinglen:%d | mark:%d | byte2:%x\n", size-12, seq, tm, ssrc, padding, paddingLen, mark, buffer[1]);

		fwrite(rtp, strlen(rtp), 1, logfile);

		printf("======== seq:%u--timestamp:%u--ssrc:%u\n", seq, tm, ssrc);

		fwrite(buffer+12, size-12 - paddingLen, 1, writefile);	
	}

	printf("Parse Done!\n");

	getchar();

	fclose(readfile);
	fclose(logfile);
	fclose(writefile);

	return 0;
}

 

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页