Wireshark-protobuf编译小结

需要进行抓包分析,由于不支持自定义协议,因此需要做wireshark的protobuf插件开发。

wireshark 插件开发有两种,

一种是用lua开发,挂在wireshark上。

另一种是通过c插件编译出dll文件,将dll文件挂在wireshark上。

软件版本:

vs2008

python 2.7

protobuf 2.6.1

wireshark 1.8.6

主要参考帖子:

wireshark protobuf 插件

protobuf-wireshark编译小结 

Wireshark 插件开发整体解决方案

其中前两个是最主要的 ,第三个是前期环境配置的主要问题。

1、环境搭建。

1.1 安装vs2008(不需要拷贝vsc**.*等环境配置文件,用vs2008 commond promot运行nmake命令相当于配好了环境)

1.2 安装最新版本的cgwin,并配置:

  • Archive/unzip (not needed if using CMake)
  • Devel/bison (or install Win flex-bison - see Chocolatey below)
  • Devel/flex (or install Win flex-bison - see Chocolatey below)
  • Devel/git (recommended - see discussion about using Git below)
  • Interpreters/perl
  • Utils/patch (only if needed) (may be Devel/patch instead)
  • Web/wget (not needed if using CMake)
  • Text/asciidoc
  • Text/docbook-xml45
需要注意的是我安装的时候还需要额外安装utility里面的U2D(unixtodos)包。

1.3 下载wireshark源码。

http://www.Wireshark.org/download/src/all-versions/

我用的版本是wireshark 1.8.6

1.4 编译config.nmake文件

(1)WIRESHARK_LIBS:     设置编译wireshark所需要的库所在的目录。默认即可(因此不需要Wireshark 插件开发整体解决方案中的第5部.)

(2)PROGRAM_FILES:设置本机程序安装目录,默认即可。

(3)MSVC_VARIANT我使用的是VS2008,所以在这里把值为MSVC2008的那一行前面的#去掉,其余MSVC_VARIANT项保持不变。
(4)CYGWIN_PATH将其设置为Cygwin的bin目录,例如C:\Cygwin\bin.
(5)PYTHON及其后的PATH将其修改为本机python.exe和其安装目录的位置,例如:C:\Python27\Python.exe
(6)MSVCR_DLL如果VS不是安装在C盘,请在这里相应的地方用绝对路径表示,而不要去修改前面的PROGRAM_FILES。如果是在c盘,
则不能使用绝对路径。若是安装在c盘,此项不需要修改。
(7)MAKENSIS 如果你没有安装NSIS安装程序制作工具,用#注释掉此行
(8)HHC_DIR如果没有安装HTMLHelpWorkshop(chm帮助文件制作工具),注释掉此行

(9)注释掉HHC_EXE

1.5

在vs2008中cmd中cd到wireshark 源码的目录。

执行nmake -f makefile.nmake verify_tools,检查工具。全部成功如下图。


执行nmake -f makefile.nmake setup

执行nmake -f makefile.nmake distclean

执行nmake -f makefile.nmake all。


protobuf插件开发主要就是前两个链接。

1. 首先要先搭建好wireshark编译环境,参见前面参考。

2. 下载protobuf-wireshark代码,下载protobuf-wireshark-runtime-0.1.tar.gz文件点击打开链接

3. 解压protobuf-wireshark-runtime-0.1.tar.gz文件后,修改 wireshark.conf配置文件。设置wireshark的源代码和安装目录,本人配置如下

wireshark_src_dir     : /cygdrive/h/wireshark-1.8.6
wireshark_install_dir : /cygdrive/c/Program Files/Wireshark
wireshark_version     : 1.8.6

4. 启动cygwin终端,并切换到protobuf-wireshark-runtion-0.1的目录下面,本人地址为;/cygdrive/h/a/protobuf-wireshark-runtime-0.1

5. 执行$ ./make_wireshark_plugin.py wireshark.conf 

  注意:编译是通不过的,因为该工程是针对linux的,而我们要的是windows的版本。

  执行后,在wireshark\plusins目录下会创建protobuf目录,并且生成了moduleinfo.h、Makefile.am、packet-protobuf.c三个文件

 同时在protobuf-wireshark-runtime-0.1源代码目录下也会生成2个c++文件wireshark-glue-protobuf.h和wireshark-glue-protobuf.cc,把这2个文件拷贝到plugins\protobuf目录下面。

6. 切换到plugins\protobuf目录,并从其他插件目录拷贝 Makefile.common、moduleinfo.nmake、Makefile.nmake、plugin.rc.in 4个文件,对5和6中的文件做修改。

  wireshark的所有源代码都是基于c语言的,但是protobuf插件多了c++文件。

修改6中的三个文件内容。

makefile.common 文件内容:

# Makefile.common for protobuf plugin
#     Contains the stuff from Makefile.am and Makefile.nmake that is
#     a) common to both files and
#     b) portable between both files
#
# $Id: Makefile.common 27491 2009-02-21 16:33:48Z jake $
#
# Wireshark - Network traffic analyzer
# By Gerald Combs 
# Copyright 1998 Gerald Combs
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

# the name of the plugin
PLUGIN_NAME = protobuf

# the dissector sources (without any helpers)
DISSECTOR_SRC = \
	packet-protobuf.c
	
DISSECTOR_SRCC = \
	wireshark-glue-protobuf.cc
# corresponding headers
DISSECTOR_INCLUDES =	\
	wireshark-glue-protobuf.h\
	moduleinfo.h\
	

# Dissector helpers. They're included in the source files in this
# directory, but they're not dissectors themselves, i.e. they're not
# used to generate "plugin.c".
DISSECTOR_SUPPORT_SRC =

moduleinfo.nmake文件内容:

#  
# $Id: moduleinfo.nmake 20157 2006-12-19 22:23:22Z jake $  
#  
  
# The name  
PACKAGE=protobuf  
  
# The version  
MODULE_VERSION_MAJOR=0  
MODULE_VERSION_MINOR=0  
MODULE_VERSION_MICRO=1  
MODULE_VERSION_EXTRA=0  
  
#  
# The RC_VERSION should be comma-separated, not dot-separated,   
# as per Graham Bloice's message in  
#  
#   http://www.ethereal.com/lists/ethereal-dev/200303/msg00283.html  
#  
# "The RC_VERSION variable in config.nmake should be comma separated.   
# This allows the resources to be built correctly and the version  
# number to be correctly displayed in the explorer properties dialog  
# for the executables, and XP's tooltip, rather than 0.0.0.0."  
#  
  
MODULE_VERSION=$(MODULE_VERSION_MAJOR).$(MODULE_VERSION_MINOR).$(MODULE_VERSION_MICRO).$(MODULE_VERSION_EXTRA)  
RC_MODULE_VERSION=$(MODULE_VERSION_MAJOR),$(MODULE_VERSION_MINOR),$(MODULE_VERSION_MICRO),$(MODULE_VERSION_EXTRA) 

Makefile.nmake文件内容:

# Makefile.nmake  
# nmake file for Wireshark plugin  
#  
# $Id: Makefile.nmake 42971 2012-06-01 14:08:12Z wmeier $  
#  
PROTOBUF_DIR=F:\protobuf-2.6.1\src
PROTOBUF_LIB=F:\protobuf-2.6.1\vsprojects\Release\libprotobuf.lib
include ..\..\config.nmake  
include moduleinfo.nmake  
PLUGIN_NAME=protobuf  
DISSECTOR_SRC=packet-protobuf.c  
DISSECTOR_SRCC=wireshark-glue-protobuf.cc  
DISSECTOR_SUPPORT_SRC=  
DISSECTOR_INCLUDES=wireshark-glue-protobuf.h moduleinfo.h  
CFLAGS=$(WARNINGS_ARE_ERRORS) $(STANDARD_CFLAGS) /I../.. $(GLIB_CFLAGS) /I$(PROTOBUF_DIR)  	
.c.obj::  
	$(CC) $(CFLAGS) -Fd.\ -c $<  
.cc.obj::  
	$(CC) $(CFLAGS) -Fd.\ -c $<  
	  
LDFLAGS = $(PLUGIN_LDFLAGS)  
  
!IFDEF ENABLE_LIBWIRESHARK  
LINK_PLUGIN_WITH=..\..\epan\libwireshark.lib ..\..\wsutil\libwsutil.lib $(PROTOBUF_LIB)  
CFLAGS=/D_NEED_VAR_IMPORT_ $(CFLAGS)  
  
DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)  
DISSECTOR_OBJECTSS = $(DISSECTOR_SRCC:.cc=.obj)  
  
DISSECTOR_SUPPORT_OBJECTS = $(DISSECTOR_SUPPORT_SRC:.c=.obj)  
  
  
OBJECTS = $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS) $(DISSECTOR_OBJECTSS)  
  
RESOURCE=$(PLUGIN_NAME).res  
  
all: $(PLUGIN_NAME).dll  
  
$(PLUGIN_NAME).rc : moduleinfo.nmake  
	sed -e s/@PLUGIN_NAME@/$(PLUGIN_NAME)/ -e s/@RC_MODULE_VERSION@/$(RC_MODULE_VERSION)/ -e s/@RC_VERSION@/$(RC_VERSION)/ -e s/@MODULE_VERSION@/$(MODULE_VERSION)/ -e s/@PACKAGE@/$(PACKAGE)/ -e s/@VERSION@/$(VERSION)/ -e s/@MSVC_VARIANT@/$(MSVC_VARIANT)/ < plugin.rc.in > $@  
  
$(PLUGIN_NAME).dll $(PLUGIN_NAME).exp $(PLUGIN_NAME).lib : $(OBJECTS) $(LINK_PLUGIN_WITH) $(RESOURCE)  
	link -dll /out:$(PLUGIN_NAME).dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) $(GLIB_LIBS) $(RESOURCE)  
  
#  
# Build plugin.c, which contains the plugin version[] string, a  
# function plugin_register() that calls the register routines for all  
# protocols, and a function plugin_reg_handoff() that calls the handoff  
# registration routines for all protocols.  
#  
# We do this by scanning sources.  If that turns out to be too slow,  
# maybe we could just require every .o file to have an register routine  
# of a given name (packet-aarp.o -> proto_register_aarp, etc.).  
#  
# Formatting conventions:  The name of the proto_register_* routines an  
# proto_reg_handoff_* routines must start in column zero, or must be  
# preceded only by "void " starting in column zero, and must not be  
# inside #if.  
#  
# DISSECTOR_SRC is assumed to have all the files that need to be scanned.  
#  
# For some unknown reason, having a big "for" loop in the Makefile  
# to scan all the files doesn't work with some "make"s; they seem to  
# pass only the first few names in the list to the shell, for some  
# reason.  
#  
# Therefore, we have a script to generate the plugin.c file.  
# The shell script runs slowly, as multiple greps and seds are run  
# for each input file; this is especially slow on Windows.  Therefore,  
# if Python is present (as indicated by PYTHON being defined), we run  
# a faster Python script to do that work instead.  
#  
# The first argument is the directory in which the source files live.  
# The second argument is "plugin", to indicate that we should build  
# a plugin.c file for a plugin.  
# All subsequent arguments are the files to scan.  
#  
  
  
!ENDIF  
  
clean:  
	rm -f $(OBJECTS) $(RESOURCE) *.pdb *.sbr $(PLUGIN_NAME).dll $(PLUGIN_NAME).dll.manifest $(PLUGIN_NAME).lib $(PLUGIN_NAME).exp $(PLUGIN_NAME).rc  
  
distclean: clean  
  
maintainer-clean: distclean  
  
checkapi:  
# TODO: Fix api's :)  
#   $(PERL) ../../tools/checkAPIs.pl -g abort -g termoutput -build $(DISSECTOR_SRC) $(DISSECTOR_INCLUDES)  

8修改packet-protobuf.c,wireshark-glue-protobuf.cc

packet-protobuf.c内容:

#ifdef HAVE_CONFIG_H  
# include "config.h"  
#endif  
#include   
#include   
#include   
#include   
#include   
#include   
#include   
#include     
/* TCP数据包的固定头大小*/  
//#define FRAME_HEADER_LEN 4 

/*这个值在本程序中没有使用。本身他的作用是用来合并TCP包的时候,传入的包头固定大小,
由于自定义协议中前面有13字节固定长度,后面有两个字节固定长度,本程序中没有合并TCP包。
*/
#define FRAME_HEADER_LEN 11  
void proto_register_protobuf();  
void proto_reg_handoff_protobuf();  
static void dissect_protobuf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);  
static void dissect_protobuf_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);  
  
  
/* Define version if we are not building ethereal statically */  
#ifndef ENABLE_STATIC  
G_MODULE_EXPORT const gchar version[] = "0.0";  
#endif  
  
  
static int proto_protobuf = -1;  
static dissector_handle_t protobuf_handle;  
  
// Protocol field variables - START  
static int hf_protobuf = -1;  
// Protocol field variables - END  
  
int wireshark_pb_process_protobuf(void *tree_root, int srcport, int dstport, int item_id, void *tvb,  void *buf, int buf_size);  
void wireshark_pb_process_protobuf_register_proto( int proto, const char* dirname );  
void wireshark_pb_process_protobuf_register_ports();  
void wireshark_pb_process_protobuf_register_subtree( int proto, const char* name,  
												int *handle, int ** tree_handle );  
void wireshark_pb_process_protobuf_register_field( int proto, int type,  
												const char* name, const char * fullName,  
						int *handle );  
/* Register plugin - START */  
#ifndef ENABLE_STATIC  
G_MODULE_EXPORT void  
plugin_register(void) {   
	/* register the new protocol, protocol fields, and subtrees */  
	if (proto_protobuf == -1) { /* execute protocol initialization only once */  
		proto_register_protobuf();  
	}  
}  
G_MODULE_EXPORT void  
plugin_reg_handoff(void){  
	proto_reg_handoff_protobuf();  
}  
#endif  
void proto_register_protobuf(void) {  
  
	module_t *protobuf_module;  
	char* dirname;  
	if (proto_protobuf == -1) {  
		proto_protobuf = proto_register_protocol (  
				"protobuf ",/* name */  
				"protobuf",/* short name */  
				"protobuf"/* abbrev */  
			);  
		}  
	protobuf_module= prefs_register_protocol(proto_protobuf, proto_reg_handoff_protobuf);  
  
		/*char**/ dirname = get_persconffile_path("protobuf", FALSE, FALSE);  
		if( test_for_directory( dirname ) != EISDIR )   
	{  
			/* Although dir isn't a directory it may still use memory */  
			g_free( dirname );  
  
			dirname = get_datafile_path("protobuf");  
  
			if( test_for_directory( dirname ) != EISDIR )   
			{  
				g_free( dirname );  
				dirname = NULL;  
			}  
		}  
  
		wireshark_pb_process_protobuf_register_proto( proto_protobuf, dirname );  
}  
  
  
  
void proto_reg_handoff_protobuf (void) {  
	static int Initialized=FALSE;  
	unsigned int i = 0;  
  
	if (!Initialized) {  
		protobuf_handle = create_dissector_handle(dissect_protobuf, proto_protobuf);  
  
		wireshark_pb_process_protobuf_register_ports();     
	}  
}  
/* Register plugin - END */  
  
  
  
/* 解析一个TCP数据包*/  
static void dissect_protobuf_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)  
{  
	/*
		先进行数据包判断,如果数据长度小于7,则是继续向后偏移,直到取得大于7的长度,进入下一步。
		或者数据长度==0,或者偏移量达到最大偏移,则退出。
	*/
		proto_item * ti = NULL; 
		proto_item * pi =NULL;
		tvbuff_t * next_tvb=NULL;
	   gint maxOffset  = 0;
		gint msg_id =0;
		gint msglen=0;
		gint offect=0;  
			if (tree) { /* we are being asked for details */  
			  /* Always make sure that offset is LESS than maxOffset */   
			  gint data_len = tvb_get_letohs(tvb,2); 
			  if ( data_len==0)
					return ;
			 msglen= tvb_length(tvb);
			 offect=data_len+6;
			  while(data_len <7)
				{
				
					if(data_len==0 ||offect>=msglen)
						return ;
					tvb= tvb_new_subset_remaining(tvb,6+data_len);
					data_len = tvb_get_letohs(tvb,2); 
					offect+=data_len+6;
				}

			  /* TODO: implement your dissecting code */ 
			  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {  
				  col_set_str(pinfo->cinfo, COL_PROTOCOL, "protobuf-tcp");  
			  }  

			  /* Clear out stuff in the info column */  
			  if(check_col(pinfo->cinfo,COL_INFO)){  
				  col_clear(pinfo->cinfo,COL_INFO);  
			  }  

				/*
					ti 取得是数据长度,(eb 91 ** ** eb 91 之后的长度)。
					pi 取得是数据类型。从字节流开始偏移 9个字节。
				*/

			  //proto_item *pi=NULL;
			  //tvbuff_t * next_tvb = tvb_new_subset_remaining (tvb,4); 
			   next_tvb = tvb_new_subset_remaining(tvb,13); 			  
			  maxOffset = tvb_length(next_tvb);  
  			  msg_id = tvb_get_ntohs(tvb, 9);
			  //ti = proto_tree_add_item(tree,proto_protobuf,tvb,0,4,ENC_NA);  
			  ti = proto_tree_add_item(tree,proto_protobuf,tvb,2,2,ENC_NA); 
			  pi = proto_tree_add_item(tree,proto_protobuf,tvb,9,2,ENC_NA);
			  proto_item_append_text(ti, ", Length  %d",data_len);
			  proto_item_append_text(pi, ", Message type:%d",msg_id);			  
			 wireshark_pb_process_protobuf((void *) tree, pinfo->srcport, pinfo->destport, hf_protobuf,  msg_id, 
				(void *)next_tvb,  (void *)tvb_get_ptr(next_tvb,0,data_len-9), data_len-9);  

			}  
}  
  
/* TCP数据包的总长度,包含包头长度 */  
static guint get_protobuf_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)  
{  
	/* TODO: change this to your needs */  
	//return (guint)tvb_get_ntohl(tvb, offset)+4; /* e.g. length is at offset 4 */ 
	/*
	这个函数没有使用,但继续4的原因是,字节长度是包含最后两个校验位的长度,因此要减2,再加上报文头
	的长度,即+6,因此还是+4.
	*/
	return (guint)tvb_get_letohs(tvb,2)+4; /* e.g. length is at offset 10 */ 	
}  
  
/* Generate the main dissector function - START */  
  
static void dissect_protobuf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)  
{  
	if( pinfo->tcp_tree == NULL) //进入解析UDP数据包  
	{  
		dissect_protobuf_udp(tvb,pinfo,tree);  
  
	}else  
	{  
		 //进入解析TCP数据包。
		//没有经过并包处理,直接进行解析TCP数据。
		 dissect_protobuf_message(tvb, pinfo,tree);  		 
		//tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN,  
		//		 get_protobuf_message_len, dissect_protobuf_message);  
}  
}  



static void dissect_protobuf_udp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {  

  


if (check_col(pinfo->cinfo, COL_PROTOCOL)) {  
			col_set_str(pinfo->cinfo, COL_PROTOCOL, "protobuf-udp");  
		}  
  
		/* Clear out stuff in the info column */  
		if(check_col(pinfo->cinfo,COL_INFO)){  
			col_clear(pinfo->cinfo,COL_INFO);  
		}  
  
  
		if (tree) { /* we are being asked for details */  
  
		  /* Always make sure that offset is LESS than maxOffset */  
		  gint maxOffset = tvb_length(tvb);  
		
			  wireshark_pb_process_protobuf((void *) tree, pinfo->srcport, pinfo->destport, hf_protobuf,   
			(void *)tvb,  (void *)tvb_get_ptr(tvb,0,maxOffset), maxOffset);  
		}  



} //dissect_protobuf_udp  
/* Generate the main dissector function - END */  


/** Called from PB to add msg_str to tree_root */  
int wireshark_pb_add_protobuf(void* tree_root, void* tvb, int item_id, char* msg_str) {  
proto_tree_add_none_format ((proto_tree *) tree_root, item_id, (tvbuff_t*) tvb, 0, -1, msg_str);  
return 0;  
}  

void wireshark_pb_process_protobuf_register_subtree( int proto, const char* name,  
 int *handle, int ** p_tree_handle )  
{  
hf_register_info message_info =  
	{ handle,  
			{ (char*)name,  
			  (char*)name,  
					  FT_NONE,  
					  BASE_NONE,  
					  NULL, 0,  
					  "",  
					  HFILL  
			}  
	};  

hf_register_info *hf_info = malloc(sizeof( hf_register_info ) );    

*hf_info = message_info;  

proto_register_field_array( proto, hf_info, 1 );  

proto_register_subtree_array( p_tree_handle, 1 );  
}  

void wireshark_pb_process_protobuf_register_field( int proto, int type,  
											const char* name, const char * fullName,  
					int *handle )  
{  
int base = ( ( type == FT_UINT32 ) || ( type == FT_UINT64 ) ) ? BASE_HEX :   
		  ( ( type == FT_INT32 ) || ( type == FT_INT64 ) ) ? BASE_DEC :   
	  BASE_NONE;  

hf_register_info message_info =  
	{ handle,  
			{ (char*)fullName,  
			  (char*)name,  
					  type,  
					  base,  
					  NULL, 0,  
					  "",  
					  HFILL  
			}  
	};  

hf_register_info *hf_info = malloc(sizeof( hf_register_info ) );  

*hf_info = message_info;  

proto_register_field_array( proto, hf_info, 1 );  
}  

void wireshark_pb_process_protobuf_dissector_add( const char* name, int port )  
{  
dissector_add( name, port, protobuf_handle );  
}  

wireshark-glue-protobuf.cc文件内容:

#include "wireshark-glue-protobuf.h"  
  
#include   
#include   
#include   
#include 
#include 

#include   
#include   
#include   
#include   
#include   
#include   
#include   
  
using namespace std;  
using namespace google;  
using namespace protobuf;  
using namespace internal;  
  
extern "C" {  
  
static HandleMap* handleMap = NULL;  
static MessageConfigList messageConfigList;  
static google::protobuf::compiler::Importer* importer = NULL;  
static MaptoMesConfig  maptoMesconfig;
//static logger mylog;
static void * _tvb = NULL;  
static const char ARRAY_FORMAT[] = "%s[%d]";  
/*
添加Utf8ToString,将utf8数据转为string。希望解决中文显示问题,暂未成功。
*/

std::string Utf8ToString(const std::string &str)
{
	int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0); 
		
	wchar_t * pwBuf = new wchar_t[nwLen + 1];
	memset(pwBuf, 0, nwLen * 2 + 2); 

	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen); 

	int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL); 

	char * pBuf = new char[nLen + 1]; 
	memset(pBuf, 0, nLen + 1); 

	WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL); 

	std::string retStr = pBuf; 
	delete []pBuf; 
	delete []pwBuf; 

	pBuf = NULL; 
	pwBuf = NULL; 
	return retStr; 
}




/** 
  * @param buf The message contents 
  * @param buf_size The length of message contents in buf 
  * @param tree_root The WireShark tree to which this message is to be added. 
  * @param item_id Internal wireshark id to refer to this FT_NONE datatype. 
  */  
/*
当某一个port满足要求时,
修改了以前的做法,从第一个MessageConfigList对象开始反序列化,这会导致利用错误的protobuf_MessageConfig解析数据问题。
修改:增加MaptoMesConfig对象,这是一个map,key为数据类型,value 为protobuf_MessageConfig。通过字节流的数据类型,去
MaptoMesConfig中取相应的protobuf_MessageConfig进行解析。for循环应该是可以去掉的。
保留了for循环的考虑是尽量少减小代码修改。
*/
int wireshark_pb_process_protobuf(proto_tree* tree_root, int srcport, int dstport, int item_id, int msg_id ,tvbuff_t* tvb, void* buf, int buf_size)   
{  
  for( MessageConfigList::iterator it = messageConfigList.begin(); it != messageConfigList.end(); it++ )  
  {  
      if( (*it)->matchesSrcPort( srcport ) ||   (*it)->matchesDestPort( dstport ) )  
      {  
			//mylog.debug("DEBUG",msg_id);
		  MaptoMesConfig::iterator index=maptoMesconfig.find(msg_id);
		  if(index!=maptoMesconfig.end())
			  *it=maptoMesconfig[msg_id];
          return (*it)->dissect( tree_root, item_id, tvb, buf, buf_size ); 
      }   
  }  
  DBG_ERR("Failed to find match");  
    
  wireshark_pb_add_protobuf(tree_root,tvb,item_id,"Failed to find match");  
  return -1;  
}  
  
void wireshark_pb_process_protobuf_register_subtree_( int proto,   
                               const std::string& name,  
                               const std::string& full_name )  
{  
   Handles *handles = new Handles();  
   wireshark_pb_process_protobuf_register_subtree( proto,  
                            name.c_str(),  
                            &(handles->handle), &(handles->tree_handle) );  
   handleMap->insert( StringHandlePair( full_name, handles ) );  
}  
  
int wireshark_pb_process_protobuf_get_type( FieldDescriptor::CppType type )  
{  
  struct ftmap_t  
  {  
    FieldDescriptor::CppType cpp_type;  
    ftenum fttype;  
    int length;  
  };  
  
  static ftmap_t ftmap[] = {  
     { FieldDescriptor::CPPTYPE_UINT32, FT_UINT32 },  
     { FieldDescriptor::CPPTYPE_INT32, FT_INT32 },  
     { FieldDescriptor::CPPTYPE_UINT64, FT_UINT64 },  
     { FieldDescriptor::CPPTYPE_INT64, FT_INT64 },  
     { FieldDescriptor::CPPTYPE_DOUBLE, FT_DOUBLE },  
     { FieldDescriptor::CPPTYPE_FLOAT, FT_FLOAT },  
     { FieldDescriptor::CPPTYPE_BOOL, FT_BOOLEAN },  
     { FieldDescriptor::CPPTYPE_ENUM, FT_INT32 },   
     { FieldDescriptor::CPPTYPE_STRING, FT_STRING } };  
  
  for( int i =0; i < sizeof(ftmap)/sizeof(ftmap_t); i++ )  
  {  
     if( ftmap[i].cpp_type == type )   
     {  
       return ftmap[i].fttype;  
     }  
  }   
  
  DBG_ERR( "Couldnt find type for cpp type " << type );  
  return FT_NONE;  
}  
  
void wireshark_pb_process_protobuf_register_ports()  
{  
    for( MessageConfigList::iterator it = messageConfigList.begin(); it != messageConfigList.end(); it++ )  
    {  
        (*it)->register_ports();  
    }  
}  
  
void wireshark_pb_process_protobuf_register_proto( int proto, const char* dirname )  
{  
    if( dirname == NULL )  
    {  
        DBG_ERR( "couldnt get dirname ");   
        return;  
    }  
    DIR* dir = opendir( dirname );  
    if( dir == NULL )  
    {  
        DBG_ERR( "couldnt open " << dirname );  
        return;  
    }  
    dirent* dp;  
    std::string configFileExtension( ".conf" );  
    std::string protoFileExtension( ".proto" );  
  
    while( ( dp = readdir( dir ) ) != NULL )  
    {  
        std::string filename( dp->d_name );  
  
        size_t i = filename.rfind( configFileExtension );  
  
        if( ( i != std::string::npos ) && ( i == filename.length() - configFileExtension.length() ) )  
        {  
        protobuf_MessageConfig* messageConfig = new protobuf_MessageConfig( filename, dirname );  
  
        if( messageConfig->isValid() )  
        {  
            messageConfigList.push_back( messageConfig );  
            messageConfig->register_proto( proto );  
			//mylog.debug("add to maptomes",messageConfig->message_selfid);
			maptoMesconfig[messageConfig->message_selfid]=messageConfig;
			//mylog.debug("add to maptomes, size ",maptoMesconfig.size());
			//mylog.debug(" messageConfigList size ", messageConfigList.size());

        }  
        }  
  
        //const FileDescriptor* fileDesc = importer->Import( filename );  
        //  
        //for( int i = 0; i < fileDesc->message_type_count(); i++ )  
        //{  
        //    const Descriptor* desc = fileDesc->message_type( i );  
        //    std::string configFileName = desc->name() + ".config";   
        //  
        //    // check if desc->name() | .config exists TBD  
        //    messageConfigList.push_back( new protobuf_MessageConfig( configFileName, desc ) );  
        //}  
    }  
    closedir( dir );  
}  
  
protobuf_Dissector::protobuf_Dissector()  
  : _leaf( NULL ),  
    _len( -1 ),  
    _message( NULL ),  
    _offset( 0 ),  
    _prefix_len( -1 ),  
    _reflection( NULL )  
{  
}  
  
    
protobuf_Dissector::protobuf_Dissector( proto_tree* tree, int offset,  
                          const Message* message,   
                          const FieldDescriptor* field,  
                          int index )  
  : _leaf( NULL ),  
    _len( -1 ),  
    _message( message ),  
    _offset( offset ),  
    _prefix_len( 0 ),  
    _reflection( _message->GetReflection() )  
{  
    bool is_root = ( field == NULL );  
    const std::string& label = ( is_root ) ? _message->GetDescriptor()->name() : field->name();  
    const std::string& fullname = _message->GetDescriptor()->full_name();  
  
    int data_size = _message->ByteSize();    
    int total_size = data_size;  
        
    // if not root field then prefix_len needs to be computed  
    if( !is_root )  
    {  
      _prefix_len = WireFormat::TagSize( _message->GetDescriptor()->index(),   
                     FieldDescriptor::TYPE_MESSAGE );  
      _prefix_len+= io::CodedOutputStream::VarintSize32( data_size );  
      total_size+= _prefix_len;  
    }  
  
    _len = total_size;  
  
    // construct subtree here itself rather than in dissect method otherwise  
    // all repeated fields and messages are pushed to end of current tree  
    // regardless of their current position  
    HandleMap::iterator it = handleMap->find( fullname );  
  
    if( it == handleMap->end() )   
    {  
      DBG_ERR( "couldnt find handle for " << fullname );  
      return;  
    }  
  
    Handles *handles = it->second;  
  
    // add a subtree for current message  
    proto_item* item;  
    if( index == -1 )  
    {  
      item = proto_tree_add_none_format( tree, handles->handle, _tvb,   
                     _offset, _len,   
                     label.c_str() );  
    }  
    else  
    {  
      item = proto_tree_add_none_format( tree, handles->handle, _tvb,   
                     _offset, _len, ARRAY_FORMAT,   
                     label.c_str(), index );  
        
    }  
    _leaf = proto_item_add_subtree( item, *(handles->tree_handle) );  
}  
  
void protobuf_Dissector::dissect( DissectorList& dissectorList )  
{  
    //DBG( "Dissecting " << _message->GetDescriptor()->name()   
    //   << " of length " << _len  
    //   << " prefix len " << _prefix_len );  
  
    if( !_leaf )  
    {  
      DBG_ERR( "Couldnt find leaf node for current message" );  
      return;  
    }   
  
    _offset+= _prefix_len;  
  
    // now loop through all the field in current message  
  
    FieldDescriptorList fields ;  
  
    _reflection->ListFields( *_message, &fields );  
      
    for( FieldDescriptorList::iterator it = fields.begin(); it!=fields.end(); it++ )  
    {  
      const FieldDescriptor* field = *it;  
      bool is_message = ( field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ) ;  
  
      if( field->is_repeated() )  
      {  
    if( field->options().packed() )  
    {  
      int data_size = WireFormat::FieldDataOnlyByteSize( field, *_message );  
      if (data_size > 0)   
      {  
        _offset += WireFormat::TagSize( field->number(), FieldDescriptor::TYPE_STRING );  
        _offset += io::CodedOutputStream::VarintSize32( data_size );  
      }  
    }  
  
    int size = _reflection->FieldSize( *_message, field );  
    for( int i = 0; i < size; i++ )  
    {  
      if( is_message )  
      {  
        const Message& subMessage = _reflection->GetRepeatedMessage( *_message,   
                                     field, i );  
        protobuf_Dissector dissector( _leaf, _offset,  
                           &subMessage, field, i );  
        dissectorList.push_back( dissector );  
        _offset+= dissector.messageLength();  
      }  
      else  
      {  
        dissectRepeatedField( field, i );  
      }  
    }  
      }   
      else if( is_message )  
      {  
    const Message& subMessage = _reflection->GetMessage( *_message, field );  
    protobuf_Dissector dissector( _leaf, _offset,  
                       &subMessage, field );   
    dissectorList.push_back( dissector );  
    _offset+= dissector.messageLength();  
      }  
      else // plain simple field. process it immediately  
      {  
    dissectField( field );  
      }  
    }  
}  
  
void protobuf_Dissector::dissectField( const FieldDescriptor* field )  
{  
    int len = WireFormat::FieldByteSize( field, *_message );  
  
    //DBG( "Dissecting field " << field->name() << " " << len );  
  
    HandleMap::iterator it = handleMap->find( field->full_name() );  
  
    if( it == handleMap->end() )   
    {  
      DBG_ERR( "Couldnt find handle for " << field->full_name() );  
      return;  
    }  
  
    Handles *handles = it->second;  
  
    const EnumValueDescriptor* enumDesc = NULL;  
  	std::string Fromutf8tostring="";
    switch( field->cpp_type() )  
    {  
	
    case FieldDescriptor::CPPTYPE_UINT32:  
      proto_tree_add_uint( _leaf, handles->handle, _tvb, _offset, len,  
               _reflection->GetUInt32( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_INT32:  
      proto_tree_add_int( _leaf, handles->handle, _tvb, _offset, len,   
              _reflection->GetInt32( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_FLOAT:  
      proto_tree_add_float( _leaf, handles->handle, _tvb, _offset, len,   
                _reflection->GetFloat( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_UINT64:  
      proto_tree_add_uint64( _leaf, handles->handle, _tvb, _offset, len,   
                 _reflection->GetUInt64( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_INT64:  
      proto_tree_add_int64( _leaf, handles->handle, _tvb, _offset, len,   
                _reflection->GetInt64( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_DOUBLE:  
      proto_tree_add_double( _leaf, handles->handle, _tvb, _offset, len,   
                 _reflection->GetDouble( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_BOOL:  
      proto_tree_add_boolean( _leaf, handles->handle, _tvb, _offset, len,   
                  _reflection->GetBool( *_message, field ) );  
      break;  
    case FieldDescriptor::CPPTYPE_ENUM:  
      enumDesc = _reflection->GetEnum( *_message, field );  
      proto_tree_add_int_format_value( _leaf, handles->handle, _tvb, _offset, len,    //mawu
                       enumDesc->number(), "%d ( %s )", enumDesc->number(),  
                       enumDesc->name().c_str() ); 
	//Fromutf8tostring= Utf8ToString(enumDesc->name());
	//mylog.debug("Fromutf8tostring",Fromutf8tostring);
	//  proto_tree_add_int_format_value( _leaf, handles->handle, _tvb, _offset, len,   
	//	  enumDesc->number(), "%d ( %s )", enumDesc->number(),  
	//	 Fromutf8tostring.c_str());  
	//  Fromutf8tostring="";
      break;  
    case FieldDescriptor::CPPTYPE_STRING:  
      //proto_tree_add_string( _leaf, handles->handle, _tvb, _offset, len,     //mawu
      //           _reflection->GetString( *_message, field ).c_str() );  
	  //std::string ConvertString= Utf8ToString(_reflection->GetString( *_message, field ));
		//mylog.debug("befor convert ",_reflection->GetString( *_message, field ));
		//mylog.debug("befor convert size",_reflection->GetString( *_message, field ).size() );
		//mylog.debug("len is ",len);
		Fromutf8tostring = Utf8ToString(_reflection->GetString( *_message, field ));
		//mylog.debug("Fromutf8tostring1",Fromutf8tostring);
		//mylog.debug("Fromutf8tostring1.size",Fromutf8tostring.size());
		//mylog.debug("1temp.size:",temp.size());
		proto_tree_add_string( _leaf, handles->handle, _tvb, _offset, len,   
		          Fromutf8tostring.c_str());  
		Fromutf8tostring="";
      break;  
    default:  
      proto_tree_add_item( _leaf, handles->handle, _tvb, _offset, len, true );  
    };  
  
    _offset+=len;  
  
}  
  
void protobuf_Dissector::dissectRepeatedField( const FieldDescriptor* field, int index )  
{  
    int len = 0;  
    string scratch;  
  
    if( !field->options().packed() )  
    {  
      len+= WireFormat::TagSize( field->number(), field->type() );  
    }  
  
    //DBG( "Dissecting field " << field->name() << " " << len );  
  
    HandleMap::iterator it = handleMap->find( field->full_name() );  
  
    if( it == handleMap->end() )   
    {  
      DBG_ERR( "Couldnt find handle for " << field->full_name() );  
      return;  
    }  
  
    Handles *handles = it->second;  
  
    const EnumValueDescriptor* enumDesc = NULL;  
	std::string Fromutf8tostring="";
	/*
		下面所有用了Fromutf8tostring,都是将原utf-8转为string。本来是想解决中文显示问题,没有成功。
	*/
    switch( field->cpp_type() )  
    {  
    case FieldDescriptor::CPPTYPE_UINT32:  
      if( field->type() == FieldDescriptor::TYPE_FIXED32 )  
      {  
    len+= WireFormatLite::kFixed32Size;  
      }  
      else  
      {  
    len+= WireFormatLite::UInt32Size( _reflection->GetRepeatedUInt32( *_message, field, index )  );        
      }  
      proto_tree_add_uint( _leaf, handles->handle, _tvb, _offset, len,    
               _reflection->GetRepeatedUInt32( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_INT32:  
      if( field->type() == FieldDescriptor::TYPE_SFIXED32 )  
      {  
    len+= WireFormatLite::kSFixed32Size;  
      }  
      else if( field->type() == FieldDescriptor::TYPE_SINT32 )  
      {  
    len+= WireFormatLite::SInt32Size( _reflection->GetRepeatedInt32( *_message, field, index )  );     
      }  
      else  
      {  
    len+= WireFormatLite::Int32Size( _reflection->GetRepeatedInt32( *_message, field, index )  );      
      }  
      proto_tree_add_int( _leaf, handles->handle, _tvb, _offset, len,    
              _reflection->GetRepeatedInt32( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_FLOAT:  
      len+= WireFormatLite::kFloatSize;  
      proto_tree_add_float( _leaf, handles->handle, _tvb, _offset, len,    
                _reflection->GetRepeatedFloat( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_UINT64:  
      if( field->type() == FieldDescriptor::TYPE_FIXED64 )  
      {  
    len+= WireFormatLite::kFixed64Size;  
      }  
      else  
      {  
    len+= WireFormatLite::UInt64Size( _reflection->GetRepeatedUInt64( *_message, field, index )  );    
      }  
      proto_tree_add_uint64( _leaf, handles->handle, _tvb, _offset, len,    
                 _reflection->GetRepeatedUInt64( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_INT64:  
      if( field->type() == FieldDescriptor::TYPE_SFIXED64 )  
      {  
    len+= WireFormatLite::kSFixed64Size;  
      }  
      else if( field->type() == FieldDescriptor::TYPE_SINT64 )  
      {  
    len+= WireFormatLite::SInt64Size( _reflection->GetRepeatedInt64( *_message, field, index )  );     
      }  
      else  
      {  
    len+= WireFormatLite::Int64Size( _reflection->GetRepeatedInt64( *_message, field, index )  );      
      }  
      proto_tree_add_int64( _leaf, handles->handle, _tvb, _offset, len,    
                _reflection->GetRepeatedInt64( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_DOUBLE:  
      len+= WireFormatLite::kDoubleSize;  
      proto_tree_add_double( _leaf, handles->handle, _tvb, _offset, len,    
                 _reflection->GetRepeatedDouble( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_BOOL:  
      len+= WireFormatLite::kBoolSize;  
      proto_tree_add_boolean( _leaf, handles->handle, _tvb, _offset, len,  
                  _reflection->GetRepeatedBool( *_message, field, index ) );  
      break;  
    case FieldDescriptor::CPPTYPE_ENUM:  
      enumDesc = _reflection->GetRepeatedEnum( *_message, field, index );  
      len+= WireFormatLite::EnumSize( enumDesc->number() );  

      proto_tree_add_int_format_value( _leaf, handles->handle, _tvb, _offset, len,    ///mawu
                       enumDesc->number(), "%d ( %s )", enumDesc->number(),  
                       enumDesc->name().c_str() ); 
	 // Fromutf8tostring= Utf8ToString(enumDesc->name());
	 // 	mylog.debug("Fromutf8tostring",Fromutf8tostring);
	 // proto_tree_add_int_format_value( _leaf, handles->handle, _tvb, _offset, len,   
		//  enumDesc->number(), "%d ( %s )", enumDesc->number(),  
		//Fromutf8tostring.c_str() );  
	 // Fromutf8tostring="";
      break;  
    case FieldDescriptor::CPPTYPE_STRING:  
      len+= WireFormatLite::StringSize( _reflection->GetRepeatedStringReference( *_message, field, index, &scratch ) );  
      //proto_tree_add_string( _leaf, handles->handle, _tvb, _offset, len,    
      //           _reflection->GetRepeatedString( *_message, field, index ).c_str() );         ///mawu
	Fromutf8tostring=Utf8ToString (_reflection->GetRepeatedString( *_message, field, index ));
	//mylog.debug("Fromutf8tostring2",Fromutf8tostring);
	  proto_tree_add_string( _leaf, handles->handle, _tvb, _offset, len,    
		 Fromutf8tostring.c_str());  
	  Fromutf8tostring="";
      break;  
    default:  
      proto_tree_add_item( _leaf, handles->handle, _tvb, _offset, len, true );  
    };  
  
    _offset+=len;  
  
}  
  
class ErrorCollector   
      : public protobuf::compiler::MultiFileErrorCollector   
{   
    // Implementation of MultiFileErrorCollector interface.   
  
    void AddError(const string & filename, int line, int column, const string & message)  
    {  
        DBG( "Error in file " << filename << " at line/col:" << line << "/" << column   
        << message );  
    }  
};   
  
protobuf_MessageConfig::protobuf_MessageConfig()  
   : _desc( NULL )  
{  
}  
  
protobuf_MessageConfig::protobuf_MessageConfig( const std::string& filename, const std::string& dirname )  
   : _desc( NULL )  
{  
    parseConfigFile( filename, dirname );  
}  
  
int protobuf_MessageConfig::dissect(proto_tree* tree_root, int item_id, tvbuff_t* tvb, void* buf, int buf_size)  
{  
    DynamicMessageFactory factory;  
    Message* msg = factory.GetPrototype( _desc )->New();  
       
    if (!msg->ParseFromArray((char *) buf, buf_size)) {  
  
        wireshark_pb_add_protobuf(tree_root,tvb,item_id,"Failed parse message");  
       DBG_ERR( "Failed to parse message." );  
       /* 
       for (int i=0; i < buf_size; i++) { 
        printf("%2x ", ((char *)buf)[i]); 
    } 
    */  
    /* 
    printf("buf size=%d\n", buf_size); 
    printf("%s\n\n\n", buf); 
    */  
    return -1;  
  }  
  
  // store tvb for subsequent calls  
  _tvb = tvb;  
  
  int offset = 0;   
  
  DissectorList dissectorList;  
  
  // we process the message tree breadth wise  
  dissectorList.push_back( protobuf_Dissector( tree_root, offset, msg, NULL ) );  
    
  while ( !dissectorList.empty() )  
  {  
    protobuf_Dissector dissector = dissectorList.front();  
    dissectorList.pop_front();  
  
    // this can add further entries to message dissector list  
    dissector.dissect( dissectorList );  
  } // while( !dissectorList.empty() )  
  
  return 0;  
}  
  
void Tokenize(const std::string& str,  
          std::vector& tokens,  
          const std::string& delimiters = " ")  
{  
    // Skip delimiters at beginning.  
    std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);  
    // Find first "non-delimiter".  
    std::string::size_type pos     = str.find_first_of(delimiters, lastPos);  
  	//	mylog.debug("tokens content ",str);
    while (std::string::npos != pos || std::string::npos != lastPos)  
    {  
        // Found a token, add it to the vector.  
        tokens.push_back(str.substr(lastPos, pos - lastPos));

        // Skip delimiters.  Note the "not_of"  
        lastPos = str.find_first_not_of(delimiters, pos);  
        // Find next "non-delimiter"  
        pos = str.find_first_of(delimiters, lastPos);  
    }  
}  
 
int stringtoint(string s1)
{
	int sum=0;
	for (int i=0 ;i< s1.size();++i)
	{
		sum=sum*10+s1[i]-'0';
	}
	return sum;
}
bool protobuf_MessageConfig::isValid()  
{  
    return ( _desc != NULL );  
}  
  
bool protobuf_MessageConfig::matchesDestPort( int port )  
{  
    return matchesPort( _dstPorts, port );  
}  
  
bool protobuf_MessageConfig::matchesSrcPort( int port )  
{  
    return matchesPort( _srcPorts, port );  
}  
  
bool protobuf_MessageConfig::matchesPort( PortList& portList, int port )  
{  
    for( PortList::iterator it = portList.begin(); it != portList.end(); it++ )  
    {  
        if( *it == port ) return true;   
    }  
  
    return false;  
}  
  
void protobuf_MessageConfig::parseConfigFile( const std::string& filename, const std::string& dirname )  
{  
    std::ifstream infile;  
      
    infile.open( ( dirname + "/" + filename ).c_str() );  
    
    if( infile.fail() )  
    {  
        DBG_ERR( "Failed to open " << filename << "in dir " << dirname );  
    return;  
    }  
    std::string line;  
    std::string message_name;  
      
    while( !infile.eof() )  
    {  
    std::getline( infile, line );  
  
    // skip lines beginning with #  
    if( line[0] == '#' ) continue;  
      
    std::vector tokens;  
      
    Tokenize( line, tokens, " =" );  
  
        //DBG( "Found " << tokens.size() << " tokens" );  
  
    // skip lines which have less that 2 tokens  
        if( tokens.size() < 2 ) continue;  
      
        if( tokens[0] == "name" )  
        {  
        message_name = tokens[1];  
		//mylog.debug("message_name",message_name);
        continue;  
    }  
  
        if( tokens[0] == "proto_file" )  
        {  
            if( importer == NULL )  
            {  
            protobuf::compiler::DiskSourceTree *sourceTree = new protobuf::compiler::DiskSourceTree();  
			static ErrorCollector* errorCollector = new ErrorCollector();  
			sourceTree->MapPath( "", dirname );  
                importer = new protobuf::compiler::Importer( sourceTree, errorCollector );  
            }  
  
        DBG( "filename to import " << tokens[1] );  
            const FileDescriptor* fileDesc = importer->Import( tokens[1] );  
		//	mylog.debug("proto_file", tokens[1] );
            if( fileDesc == NULL )  
            {  
                DBG_ERR("Unable to parse " << tokens[1] );  
                continue;  
            }   
        DBG( "searching for message " << message_name );  
        //for( int i = 0; i < fileDesc->message_type_count(); i++ )  
        //{  
        //    DBG(" message " << fileDesc->message_type( i )->name() );  
        //}  
            _desc = fileDesc->FindMessageTypeByName( message_name );  
            continue;  
        } 
		if(tokens[0]=="message_id")
		{
				//mylog.debug("message_id", tokens[1] );
				message_selfid=stringtoint(tokens[1]);
				//mylog.debug("message_id_ind", message_selfid);
		}	
  
        bool src_port = false;  
        bool dst_port = false;  
        bool both_ports = false;  
      
    src_port = ( tokens[0] == "src_port" );  
    dst_port = ( tokens[0] == "dst_port" );  
    both_ports = ( tokens[0] == "port" );  
      
    for( int i = 1; i < tokens.size(); i++ )  
    {  

        int port = atoi( tokens[i].c_str() );  
	//	mylog.debug("port_id  ", port);
        if( src_port || both_ports )  
        {  
        _srcPorts.push_back( port );  
        }  
        if( dst_port || both_ports )  
        {  
        _dstPorts.push_back( port );  
        }  
    }      
    }  
  
    infile.close();  
  
    if( _desc == NULL )  
    {  
        DBG_ERR( "Couldnt get descriptor from " << filename );  
        _dstPorts.clear();  
        _srcPorts.clear();  
    }  
}  
void protobuf_MessageConfig::register_ports()  
{  
    register_ports( _srcPorts );  
    register_ports( _dstPorts );  
}  
  
void protobuf_MessageConfig::register_ports( PortList& portList )  
{  
    for( PortList::iterator it = portList.begin(); it != portList.end(); it++ )  
    {         
        wireshark_pb_process_protobuf_dissector_add( "tcp.port", *it ); // 注册TCP端口,本人添加  
        wireshark_pb_process_protobuf_dissector_add( "udp.port", *it ); // 注册UDP端口  
    }  
}  
  
void protobuf_MessageConfig::register_proto( int proto )  
{  
  if( handleMap == NULL )  
  {  
    handleMap = new HandleMap();  
  }  
  
  DescriptorList messageDescriptorList;  
  FieldDescriptorList fieldDescriptorList;  
  
  // we process the message definition depth first  
  messageDescriptorList.push_back( _desc );  
    
  while( !messageDescriptorList.empty() )  
  {  
    const Descriptor* messageDescriptor = messageDescriptorList.back();  
    messageDescriptorList.pop_back();      
      
    DBG( "Register message ( " << messageDescriptor->name() << " )" );  
      
    wireshark_pb_process_protobuf_register_subtree_( proto,   
                              messageDescriptor->name(),   
                              messageDescriptor->full_name() );  
      
    for( int i = 0; i < messageDescriptor->field_count(); i++ )  
    {  
      const FieldDescriptor* fieldDescriptor = messageDescriptor->field( i );  
        
      if( fieldDescriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE )  
      {  
		messageDescriptorList.push_back( fieldDescriptor->message_type() );  
      }  
      else  
      {  
    fieldDescriptorList.push_back( fieldDescriptor );  
      }  
    }  
  }  
    
  // process all field descriptors at very end  
  while( !fieldDescriptorList.empty() )  
  {  
    const FieldDescriptor* fieldDescriptor = fieldDescriptorList.back();  
    fieldDescriptorList.pop_back();  
  
    Handles *handles = new Handles();  
    DBG( "Register field ( " << fieldDescriptor->name() << " : " << fieldDescriptor->full_name() << " )" );  
    wireshark_pb_process_protobuf_register_field( proto,   
                               wireshark_pb_process_protobuf_get_type( fieldDescriptor->cpp_type() ),  
                               fieldDescriptor->name().c_str(),  
                               fieldDescriptor->name().c_str(),  
                               &(handles->handle) );  
    handleMap->insert( StringHandlePair( fieldDescriptor->full_name(), handles ) );  
  }  
  
}  
  
}


9.修改plugins目录下的Makefile.nmake,增加protobuf工程的编译。重新编译wireshark。

提示:需要下载dirent-1.13.zip,解压后把dirent.h放到VC\Include目录下面,这是一个模拟linux dir相关接口的源代码。

10.把 plugins\protobuf\protobuf.dll 拷贝到wireshark安装目录下plugins\版本号\ 目录下。

11. 在wireshark 安装目录下创建protobuf目录,用于放置protobuf的配置文件和消息定义文件。

12.启动你的wireshark,可以开始抓包分析google protobuf消息了

你可能感兴趣的:(Wireshark-protobuf编译小结)