如何通过OPN定义新的解析器? [英] How to define a new parser by OPN?

查看:79
本文介绍了如何通过OPN定义新的解析器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用网络监视器和自定义解析器很长一段时间,但是,我想切换到Message Analyer,因为它有更多的支持。我发现没有用于将.npl文件转换为.opn文件的转换工具,因此我决定我必须自己完成
。我读了编程手册以获取编程解析器的说明在.opn之下,但我发现我很难处理这个任务,因为我从未接触过OPN。我现在正在寻求帮助来完成我的解析器转换。


我的目标非常简单。我收到了一些由UDP传输的消息,存储为.pcap文件。我想编写一个解析器来解码它们,这样当我打开Message Analyzer时,我可以直接读取消息。以下是一个图表显示我正在使用的
协议。 (对不起,我发现我无法上传图表)...


提取UDP标头后,我收到的每个数据包都应该有一个标头和一系列消息。


以下是我的解析器的逻辑:


之后我收到了一个UDP数据包,我应该提取有效负载。然后我应该提取标题,之后,我应该有一个循环来逐个提取所有的消息。最后,我需要打印到
消息分析器内的屏幕。


这是我试图执行我想要做的一些.opn代码:


由于这些代码无效,我在这里寻求帮助。

协议L1Proto_D与
BinaryEncodingDefaults {Endian = Endian.Little},
文档
{
ProtocolName =" L1 Protocol",
ShortName =" L1Proto_D",
Description =""
},
OPNAuthoring
{
Copyright =" No",
References =
[
new reference {Name =" L1Proto_D 1234"},
],
RevisionSummary =
[
new Revision {Class = RevisionClass.Major,Version =" 1.0.0",Date =" 22-03 -2015"}
]
};

使用UDP;


模式Port = short;
pattern Address = binary其中value.Count == 4;

//保持L1Proto_D
注释的值ushort数据报#PorterPort;
annotation ushort Datagram#SourcePort;
annotation binary Datagram#SourceAddress;
annotation binary Datagram#DestinationAddress;

端点L1Proto_D_通过UDP.Connect接受L1Proto_D_Msg_Header;

autostart actor L1Proto_D_OverUDP(UDP.Host host)
{
进程主机接受d:UDP.Datagram
{
DecodeAndDispatchPacket(d,host);
}
}

消息L1Proto_D_Msg_Header
{
// Header
ushort PktSize with BinaryEncoding {Width = 2};带有BinaryEncoding的
字节MsgCount {Width = 1};带有BinaryEncoding的
字节Filler1 {宽度= 1};
uint SeqNum with BinaryEncoding {Width = 4};
ulong SendTime with BinaryEncoding {Width = 8};

覆盖字符串ToString()
{
string summary = null;
summary =" PktSize:" +(PktSize.ToString())
+",MsgCount:" +(MsgCount.ToString())
+",Filler1:" +(Filler1.ToString())
+",SeqNum:" +(SeqNum.ToString())
+",SendTime:" +(SendTime.ToString());

返回摘要;
}
}
类型L1ProtoBookUpdate
{
uint带有BinaryEncoding的OrderBookID {宽度= 4};
string具有BinaryEncoding的填充程序{Length = 3,TextEncoding = TextEncoding.ASCII};
字节NoEntries with BinaryEncoding {Width = 1};
}
类型BookDetails
{
ulong AggregateQuantity with BinaryEncoding {Width = 8};
int BinaryEncoding的价格{宽度= 4};带有BinaryEncoding的
uint NumberOfOrders {Width = 4};
byte Side with BinaryEncoding {Width = 1};
字符串Filler1 with BinaryEncoding {Length = 1,TextEncoding = TextEncoding.ASCII};
byte PriceLevel with BinaryEncoding {Width = 1};带有BinaryEncoding的
字节UpdateAction {宽度= 1};
字符串Filler2 with BinaryEncoding {Length = 4,TextEncoding = TextEncoding.ASCII};
}
void DecodeAndDispatchPacket(UDP.Datagram d,UDP.Host host)
{
stream m = d.Payload;
可选L1Proto_D_Msg_Header msg = BinaryDecoder< L1Proto_D_Msg_Header>(m);
L1Proto_D_Msg_Header Header = new L1Proto_D_Msg_Header {};
if(msg!= nothing)
{
Header = msg as L1Proto_D_Msg_Header;
int frameLength = d.Length - 8;

while(m.BytePosition< d.Length)
{
ushort MsgType = BinaryDecoder< ushort>(m)as ushort;

if(MsgType == 100)
{
//做某事......
}
否则if(MsgType == 11)
{
//做某事......
}
否则if(MsgType == 353)
{
L1ProtoBookUpdate Msg353 = BinaryDecoder< L1ProtoBookUpdate>(m)作为L1ProtoBookUpdate;
while(m.BytePosition< d.Length)
{
BookDetails Msg353Ext = BinaryDecoder< BookDetails>(m)as BookDetails;
}
}
}
}
}



解决方案

我会帮忙,但我现在正试图找出你看到的错误。我能够编译你的OPN,所以它对我有用。事实上,基于OPN,我认为你取得了一些进展,然后被困在这里。 但是让我们检查一下我们是否在同一个
页面。


目前我看到它解析了任何UDP,因为你没有where子句将它限制为单个端口&NBSP;也许这是有目的的,对我来说意味着所有UDP流量都试图使用这个解析路径。 对于这些情况,我看到
异常:


Parsing \tActor:OpnGenerated.L1Proto_D_actor_L1Proto_D_OverUDP + L1Proto_D_OverUDP

例外:无法将可选的System.UInt16强制转换为System.UInt16因为值为'nothing'。

哈希码:49df24adb4b5a028d721c68a75b6c576
$
通话栈:

  在Microsoft.Opn.Runtime.Values.OptionalValue`1.get_Value()

  在OpnGenerated.L1Proto_D.DecodeAndDispatchPacket(数据报d,主机主持人)

  在OpnGenerated.L1Proto_D_actor_L1Proto_D_OverUDP.L1Proto_D_OverUDP .__ OnAcceptsDatagram(MessageEventArgs __args)

  在Microsoft.Opn.Runtime.Actors.MessageEvent.Execute(MessageEventHandler handler,MessageEventArgs args)


这是你指的问题吗? 


也许还有帮助,我已经制作了一个适合我的DecodeAndDispatchPacket的简单版本(最后)。 我的猜测是你想使用MsgType来确定如何进一步解析。  DHCP.OPN有一个你可以参考的例子,
寻找"类型OptionType",看看它如何使用OptionsChoice来创建动态定义。

 void DecodeAndDispatchPacket(UDP.Datagram d,UDP.Host host)
{
var msg = BinaryDecoder< L1Proto_D_Msg_Header>(d.Payload)as L1Proto_D_Msg_Header;
if(msg!= null)
{
dispatch(端点L1Proto_D_Connection over host)接受(msg as L1Proto_D_Msg_Header);
}
}


Paul


I have been using Network Monitor with a self defined parser for a long time, however, I would like to switch to Message Analyer since it has more support. I found that there has no conversion tool for converting from .npl file to .opn file, so I decided that I have to do it by myself. I read the programming manual for instructions to program my parser under .opn, but I found that it is difficult for me to handle this task since I have never touch OPN. I am now looking for help to complete my parser conversion.

My goal is very simple. I received some messages that are transmitted by UDP stored as .pcap files. I would like to write a parser to decode them so that when I turn on the Message Analyzer, I can read the message directly. Following is a graph shows what protocol I am using. (Sorry, I find that I cannot upload a graph)...

After extracting the UDP header, I should have one header and a sequence of messages in every packet I received.

Here is the logic of my parser:

After I received a UDP packet, I should extract the payload. Then I should extract the header, after that, I should have a loop to extract all the message one by one. Finally, I need to print out to the screen inside the Message Analyzer.

Here is some .opn code that I am trying to perform what I want to do:

Since these code are not working, I am here asking for help.

protocol L1Proto_D with
BinaryEncodingDefaults{Endian = Endian.Little},
Documentation
{
    ProtocolName = "L1 Protocol",
    ShortName = "L1Proto_D",
    Description = ""
},
OPNAuthoring
{
    Copyright = "No",
    References =
        [
            new Reference{Name = "L1Proto_D 1234"},
        ],
    RevisionSummary =
        [
            new Revision{Class = RevisionClass.Major, Version = "1.0.0", Date = "22-03-2015"}
        ]
};

using UDP;


pattern Port = short;
pattern Address = binary where value.Count == 4; 

// Keep the values for L1Proto_D
annotation ushort Datagram#DestinationPort;
annotation ushort Datagram#SourcePort;
annotation binary Datagram#SourceAddress;
annotation binary Datagram#DestinationAddress;

endpoint L1Proto_D_Connection over UDP.Host accepts L1Proto_D_Msg_Header;

autostart actor L1Proto_D_OverUDP(UDP.Host host)
{
	process host accepts d:UDP.Datagram
	{
		DecodeAndDispatchPacket(d, host);
	}
}

message L1Proto_D_Msg_Header
{
	// Header
	ushort PktSize with BinaryEncoding{Width = 2};
	byte MsgCount with BinaryEncoding{Width = 1};
	byte Filler1 with BinaryEncoding{Width = 1};
	uint SeqNum with BinaryEncoding{Width = 4};
	ulong SendTime with BinaryEncoding{Width = 8};
	
    override string ToString()
    {
		string summary = null;
		summary = "PktSize: " + (PktSize.ToString())
                  + ", MsgCount: " + (MsgCount.ToString()) 
                  + ", Filler1: " + (Filler1.ToString())
                  + ", SeqNum: " + (SeqNum.ToString())
				  + ", SendTime: " + (SendTime.ToString());
				  
		return summary;
	}
}
type L1ProtoBookUpdate
{
	uint OrderBookID with BinaryEncoding{Width = 4};
	string Filler with BinaryEncoding{Length = 3, TextEncoding = TextEncoding.ASCII};
	byte NoEntries with BinaryEncoding{Width = 1};
}
type BookDetails
{
	ulong AggregateQuantity with BinaryEncoding{Width = 8};
	int Price with BinaryEncoding{Width = 4};
	uint NumberOfOrders with BinaryEncoding{Width = 4};
	byte Side with BinaryEncoding{Width = 1};
	string Filler1 with BinaryEncoding{Length = 1, TextEncoding = TextEncoding.ASCII};
	byte PriceLevel with BinaryEncoding{Width = 1};
	byte UpdateAction with BinaryEncoding{Width = 1};
	string Filler2 with BinaryEncoding{Length = 4, TextEncoding = TextEncoding.ASCII};
}
void DecodeAndDispatchPacket(UDP.Datagram d, UDP.Host host)
{
	stream m = d.Payload;
	optional L1Proto_D_Msg_Header msg = BinaryDecoder<L1Proto_D_Msg_Header>(m);
	L1Proto_D_Msg_Header Header = new L1Proto_D_Msg_Header{};
    if (msg != nothing)
    {
		Header = msg as L1Proto_D_Msg_Header;
		int frameLength = d.Length - 8;

		while(m.BytePosition < d.Length)
		{
			ushort MsgType = BinaryDecoder<ushort>(m) as ushort;
			
			if(MsgType == 100)
			{
				// do something ...
			}
			else if(MsgType == 11)
			{
				// do something ...
			}
			else if(MsgType == 353)
			{
				L1ProtoBookUpdate Msg353 = BinaryDecoder<L1ProtoBookUpdate>(m) as L1ProtoBookUpdate;
				while(m.BytePosition < d.Length)
				{
					BookDetails Msg353Ext = BinaryDecoder<BookDetails>(m) as BookDetails;
				}
			}
		}
	}
}


解决方案

I will help, but I'm currently trying to figure out the error you see. I'm able to compile your OPN, so it works for me. In fact, based on the OPN, I'm thinking you made some progress, and then got stuck here.  But let's check if we are on the same page.

Currently I see that it parses anything UDP, since you don't have a where clause limiting it to a single port.  Maybe this was on purpose, be what that means for me is that all UDP traffic attempts to use this parsing path.  For these cases I see an exception:

Parsing\tActor: OpnGenerated.L1Proto_D_actor_L1Proto_D_OverUDP+L1Proto_D_OverUDP
Exception: Cannot cast optional System.UInt16 to System.UInt16 because the value is 'nothing'.
Hash Code: 49df24adb4b5a028d721c68a75b6c576
Call Stack:
   at Microsoft.Opn.Runtime.Values.OptionalValue`1.get_Value()
   at OpnGenerated.L1Proto_D.DecodeAndDispatchPacket(Datagram d, Host host)
   at OpnGenerated.L1Proto_D_actor_L1Proto_D_OverUDP.L1Proto_D_OverUDP.__OnAcceptsDatagram(MessageEventArgs __args)
   at Microsoft.Opn.Runtime.Actors.MessageEvent.Execute(MessageEventHandler handler, MessageEventArgs args)

Is this the problem you are referring to? 

Also to perhaps help further, I've made a simple version of DecodeAndDispatchPacket that works for me (at the end).  My guess is that you wanted to use the MsgType to determine how to parse further.  DHCP.OPN has an example you could reference, look for "type OptionType", and see how it use the OptionsChoice to create a dynamic definition.

void DecodeAndDispatchPacket(UDP.Datagram d, UDP.Host host)
{
    var msg = BinaryDecoder<L1Proto_D_Msg_Header>(d.Payload) as L1Proto_D_Msg_Header;
    if(msg != null)
    {
        dispatch (endpoint L1Proto_D_Connection over host) accepts (msg as L1Proto_D_Msg_Header);
    }
}

Paul


这篇关于如何通过OPN定义新的解析器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆