Menu

#10 An new event which provide lesser resource consumption

open
nobody
5
2012-09-14
2012-06-14
Anonymous
No

After reading the source code, I found that once I decided to use StartCapture() to capture packet by registering and handling the OnPacketArrival event, the method PacketHandler() will Marshal.Copy ALL the data to byte[] arrays. However, in my cases, I only interested in the data inside IP and TCP packets but not the rest payload of the TCP packets. It is obvious that there is no options to avoid copying payload data when using the event modal. The only option for now is to setup a loop and call the method GetNextPacketPointer(). However, I thought that would be neither efficient(too many P/Invoke will cause too much overheads and consumes too many cpu) nor elegant (compare to event modal).

Here is my proposal:
Create a new event named OnPacketArrivalEx which passes an event argument with type which names CaptureExEventArgs. The constructor of CaptureExEventArgs receives a LinkLayers, a header pointer, a data pointer, and a delegate which can create proper RawCapture object with a designated length of Data byte[] array. To do this, I refactory the project a little bit and add some members to, etc., RawCapture, to provide proper informations. Ok, it's too long a story to write here. Please read the code file which I've modified and attached here. (I changed the project's framework to .NET 4.0.) And I'm sorry that I didn't write little comment there since from the start I take it as an experiment. If you think that is not acceptable, I will try to complete the comment and submit again.

Here is the (maybe incomplete) file list which I modified:

RawCapture.cs:
A ActualCaptureLength is added, since from now on, Data.Length might not be the actual length of bytes traveling on net.

PcapDeviceCaptureLoop.cs:
A Thread.Sleep(10) is added in method Capture Thread() to fix the issue I submitted on previous request.

ICaptureDevice.cs:
An event named PacketArrived is added. (I proposed OnPacketArrivalEx here for the reason that it might have the same code style of the old ones. However, I am too uncomfortable that an event is named OnXXX because in Microsoft's suggestion, that would be the name for firing an event, not the event itself. So in my own implementation I changed to a more comfortable, for me at least, form of PacketArrived.)

PcapDevice.cs:
The signature of MarshalRawPacket is changed: a parameter linkType is add to decoupling between objects, a parameter maxDataLength is added to provide a way to specify how long the data I am interested in.
A _marshalRawPacketDelegate field is added to prevent the overhead of creating delegate every time a CaptureExEventArgs is created. (The CaptureExEventArgs need this delegate to work, because it don't know how to create that object. And the method between PcapDevice and AirPcapDevice is a bit different)
The method body of PacketHandler is changed to provide firing mechanism for the new event. Mainly, it was added for some codes.
A Property named NeedMarshalRawCapture is added for knowing whether MarshalRawCapture is needed.
The name of property IsOnCaptureArrivalNull is changed into HasNoneCaptureHandler. Since the original name is tightly related to the OnCaptureArrivalNull, the WinPcapDevice couldn't override and reuse this propert and it have to override the method StartCapture() and repeat the most of code inside same method of PcapDevice.
A PacketArrived event is added to implement the new same event in ICaptureDevice.

CaptureExEventArgs.cs:
A new event args is added. This class can get and cache RawCapture object with demanded data length. And for safe reason, access to the pointers exposed by it will be denied.

AirPcapDevice.cs:
The signature of MarshalPackets is changed: the out List<RawCapture> is canceled because it is no longer used.
And the body of MarshalPackets is changed because the old way don't use the PacketHandler to do things. This will prevent reusing the codes inside it. Now it calls PacketHandler inside it, but not returning a list of packets and do a dirty work in foreach loop. The old foreach loop calls SendPacketArrivalEvent directly, which makes a copy&paste of code to firing the new event. That is against the OOD principles.
A new MarshaRawPacket method is overrided to provide correct way to get the RawCapture object.

At last, I only tested the case of desiring 0 bytes of data by modifying codes in Example 3, and it works. The event handling codes like this:

    private static void device_PacketArrived(object sender, CaptureExEventArgs e)
    {
        var rawPacket = e.GetRawCapture(0);
        var time = rawPacket.Timeval.Date;
        var len = rawPacket.ActualCaptureLength;
        Console.WriteLine("{0}:{1}:{2},{3} Len={4}",
            time.Hour, time.Minute, time.Second, time.Millisecond, len);
        Console.WriteLine(rawPacket.ToString());
    }

By reading the codes in PacketDotNet, I highly doubt that a raw packets with incomplete protocol header data will cause raising some kind of exception. However, an raw packet with incomplete payload of the top most known protocol (i.e. TcpPacket) might be acceptable. I haven't test that case yet. And it would be tested in up coming days, maybe this afternoon (UTC+8).

Please don't hesitate to ask me do anything for SharpPcap. It's a greate project for every one.

Discussion

  • Chris Morgan

    Chris Morgan - 2012-06-14

    I think we would need to have a discussion about exactly what the code changes looked like as well as what the performance implications are.

    Consider that SharpPcap 4.x is already many times faster than 3.x, due to improvements in marshalling of data. Also consider that your raw capture data is only valid until the next packet that is captured. Often times this produces relatively undesirable restrictions that a user may not be aware of.

    Also, you'd want to make one of these changes at a time as well as perform adequate benchmarking. If the code changes were clean and easy to follow and the benchmarks showed a noticeable improvement then of course they would be integrated.

    This is probably best taken to email instead of here though, chmorgan@gmail.com

    Chris

     
  • Chris Morgan

    Chris Morgan - 2012-06-14

    Also, please submit git patches, it isn't easy for me to consume a rar file and I presume you sent a rar because you included the entire source files. With a git patch I'll be able to see only what you changed and it will be in plain text and easy to review and integrate.

    Chris

     
  • Anonymous

    Anonymous - 2012-06-15

    Yes, I believe that it would be better to git submit patches but I am not familiar with it. I will try it later. Also, I will talk to you in gmail later.

     

Anonymous
Anonymous

Add attachments
Cancel





Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.