PcapDotNet and Datalink type - c#

I'm trying to manipulate some network captures (pcap format) using Pcap.net.
I'm opening the pcap file and creating the dumper with:
OfflinePacketDevice selectedDevice = new OfflinePacketDevice(pcapInFile);
using (PacketCommunicator PcapReader = selectedDevice.Open(655360, PacketDeviceOpenAttributes.Promiscuous, 1000))
{
PacketDumpFile PcapWriter = PcapReader.OpenDump(pcapOutFile);
PcapReader.ReceivePackets(count, PacketDispatcher);
}
And the PacketDispatcher would be something like:
private void PacketDispatcher(Packet packet)
{
// Manipulate the packet
PcapWriter.Dump(packet);
}
Everything is ok as far as the pcapInFile Datalink is ethernet type. But i have several captures without ethernet layer (rawip) and i have to build a new ethernet layer. In this kind of caps the datalink type is the same as the pcapInFile (raw ip) and i want to change it to ethernet...
If i store all the manipulated packets in a ienumerable and dump them with:
PacketDumpFile.Dump(pcapOutFile, new PcapDataLink(1), Packets.Count(), Packets);
It works fine... But, this is not very useful if you are dealing with files of several gigas...
Any idea?
Thanks!

Assuming the concern is about having all packets in RAM, you can create an IEnumerable that doesn't contain everything in RAM using yield.
This way as Dumper dumps packets it will call your method to populate the next item using yield.

Well, despite this is not an answer but a workaround, and since nobody wrote a better solution this is how a fixed it:
Use SharPcap instead of PcapDotNet, then you can declare a reader and a writer this way:
public CaptureFileReaderDevice PcapReader;
public CaptureFileWriterDevice PcapWriter;
PcapReader = new CaptureFileReaderDevice(fileIn);
PcapReader.OnPacketArrival += packetDispatcher;
PcapReader.Capture();
In the packetDispatcher function:
RawCapture raw = new RawCapture(LinkLayers.Ethernet, e.Packet.Timeval,RebuildNullLinkLayer(e, offset));
CaptureHandler.PcapWriter.Write(raw);
And in the RebuildNullLinkLayer function you can add the ethernet layer, modify whatever you want, etc...
Note that when you call the RawCapture Constructor you can choose the Link Layer (mi original issue with Pcap.Net...), so if you are parsing a RawIp capture, you can convert the packets to Ethernet.

Related

How do I change PCap.Net packet data?

I have a (production) WireShark capture file that I need to 'replay' over my (debug) network. I can read and interpret the packets, but I need to tweak a few details before the packets can be sent, like source IP addresses and ports.
The problem, however, is that all data in the PcapDotNet.Packets.Packet is read-only. It just has setters.
So like setting for instance the Ethernet.IpV4.Source will not work.
IpV4Address.TryParse("192.168.1.10", out var newAddress); // for demo sake.
packet.Ethernet.IpV4.Source = newAddress; // Won't work
Is there a simple way to avoid building a new packet from scratch, or is that the only way to create a slightly different packet?
Instead of changing the packet inplace, you should just create a new one based on the old one.
You can use ExtractLayer() on each layer you want to keep from the old packet, and then change the layer properties if necessary.
In this case, you can do:
IpV4Layer ipV4Layer = packet.Ethernet.IpV4.ExtractLayer();
ipV4Layer.Source = newAddress;
Packet newPacket = PacketBuild.Build(DateTime.Now, packet.Ethernet.ExtractLayer(), ipV4Layer, packet.Ethernet.IpV4.Payload.ExtractLayer());
You probably also want to reset the IPv4 checksum, so you should do:
ipV4Layer.HeaderChecksum = null;
And you might need to something similar to the UDP or TCP layers on top of the IPv4 layer, in case you have them.

Dynamically send n audio sources (concurrently ) to specifc channel on ASIO device

So i have been having some fun exploring the NAudio lib.
However, I'm not sure whether I am missing something using the ASIO class. Basically my requirements are the following:
Dynamically output (mono) sources to an ASIO device, each source to a dedicated channel (later on I will probably be working with 64 channels)
Be free to 'stream' the n audio sources to the device at any time during the session (multiple sources simultaneously)
Have the control over each channel
So in Code I'd have something like:
...
WaveFileReader source1 = new WaveFileReader( pathToMyFile1 );
WaveFileReader source2 = new WaveFileReader( pathToMyFile2 );
WaveFileReader source3 = new WaveFileReader( pathToMyFile3 );
...
WaveFileReader sourceN = new WaveFileReader( pathToMyFileN );
AsioOut out = new AsioOut();
...
/*Now init out...*/
...
out.Play();
...
/* now react on events, possibly within a multi-threaded enviroment*/
/* and concurrently send each of these sources to a dedicated channel*/
/* as required, (as stated, possibly even many at the same time) */
...
So my Question basically is:
Can I, using one of the existing classes, achieve something like this? Or will I have to engineer my own implentation of one of the interfaces (ISampleProvider, IWaveProvider etc, pretty sure it will somehow work going down an abstraction level)?
Thanks for any Input on this!
The MultiplexingWaveProvider can do something close to what you want. Read about it here. For 64 channel work you might find you need to write your own fine-tuned code as performance could become an issue.

Windows named pipe in node js (preferred shared memory)

I am using named pipe to share some data between 2 processes in windows. One is a node process and other is a C# process. Here is a sample of code I use in my node process:
var net = require('net');
var PIPE_NAME = "mypipe";
var PIPE_PATH = "\\\\.\\pipe\\" + PIPE_NAME;
var L = console.log;
var server = net.createServer(function(stream) {
L('Server: on connection')
stream.on('data', function(c) {
L('Server: on data:', c.toString());
});
stream.on('end', function() {
L('Server: on end')
server.close();
});
stream.write('Take it easy!');
});
server.on('close',function(){
L('Server: on close');
})
server.listen(PIPE_PATH,function(){
L('Server: on listening');
})
I use a NamedPipeClientStream in c# to read the data. I do this in a loop on both the sides, such as my node process is a producer and C# process is a consumer.
This works fine.
But sometimes the C# loop hangs and at that point in my node process I want to overwrite the new data over the old data. I was wondering if I can specify some max size in my pipe (the one I create in nodejs) or a timeout for the data but couldn't find such things in standard documentation.
If it cannot be solved this way, there is a shared memory route to solve the problem but I couldn't find any stable shared memory library for nodejs which works nicely on windows (and I don't have much time to write one right now). I need some pointers to move in the right direction.
Any advice is appreciated. Thanks.
EDIT: I would really want to implement the above stuff using shared memory since I need to share large amount of data at a fast rate and I need to tweak for performance. Any pointers on how to implement it?
I figured out a way to use the drain event in writable stream of nodejs as per my requirement.

WCF - do not serialize (emit) empty collections

We are implementing an Client / Server application. Data are sent throughout the LAN. Where LAN means company network with several sites / locations.
We are using WCF and NetTcpBinding (EDIT: VS2010 .net 4.0).
I know that [DataMember(EmitDefaultValue = false)] is not recommended by Microsoft. But as mentionend above, data might be sent from one site to another. Therefore: size really matters!
Not sending the default value works most of the time fine. I have just an issue with collections of any kind. I do not want to transfer empty collections!
So I usually end up with to members of the same type (one for work, one work network) and I need to implement the methods OnSerializing and OnDeserialized.
[DataMember(EmitDefaultValue = false)]
private List<someType> data = new List<someType>();
[NonSerialized]
private List<someType> network = new List<someType>();
[OnDeserialized]
private void OnDeserialized(StreamingContext c)
{
if (network == null)
data = new List<someType>();
else
data = network;
}
[OnSerializing]
private void OnSerializing(StreamingContext c)
{
if (data.Count > 0)
network = data;
else
network = null;
}
Is there any elegant way to do that?
Or maybe even a completely different approach?
Remark: for simplicity I did not care about possible multi-threading issues.
But as mentionend above, data might be sent from one site to another.
Therfore: size really matters!
Do you really think that a few Bytes will make a big difference using NetTcpBinding in a LAN ? Did you made a load test to show that.
I know that [DataMember(EmitDefaultValue = false)] is not recommended
by Microsoft
It's not recommanded because it's not interoperable. This recomandation does not apply to your case as you have only WCF Clients/Server on a NetTcpBinding. The config already does not support interop (through java or php).
The WCF binary encoder (uned in NetTcpBinding) supports Gzip/Deflate compression since .net 4.5. You will gain more Bytes with this feature than removing empty collections.
Read more here.

protobuf-csharp-port

I'm using Jon Skeet's (excellent) port of Google's Protocol Buffers to C#/.Net.
For practice, I have written a dummy Instant Messenger app that sends some messages down a socket. I have a message definition as follows:-
message InstantMessage {<br/>
required string Message = 1;<br/>
required int64 TimeStampTicks = 2; <br/>
}
When the sender serialises the message, it sends it really elegantly:-
...
InstantMessage.Builder imBuild = new InstantMessage.Builder();
imBuild.Message = txtEnterText.Text;
imBuild.TimeStampTicks = DateTime.Now.Ticks;
InstantMessage im = imBuild.BuildPartial();
im.WriteTo(networkStream);
...
This works great. But at the other end, I'm having trouble getting the ParseFrom to work.
I want to use:-
InstantMessage im = InstantMessage.ParseFrom(networkStream);
But instead I have had to read it to bytes and then parse it from here. This is obviously not ideal for a number of reasons. Current code is:-
while (true)
{
Byte[] byteArray = new Byte[10000000];
int intMsgLength;
int runningMsgLength = 0;
DateTime start = DateTime.Now;
while (true)
{
runningMsgLength += networkStream.Read(byteArray, runningMsgLength, 10000000 - runningMsgLength);
if (!networkStream.DataAvailable)
break;
}
InstantMessage im = InstantMessage.ParseFrom(byteArray.Take(runningMsgLength).ToArray());
When I try to use ParseFrom, control does not return to the calling method even when I know a valid GB message is on the wire.
Any advice would be gratefully received,
PW
Sorry for taking a while to answer this. As Marc says, protocol buffers don't have a terminator, and they aren't length prefixed unless they're nested. However, you can put on the length prefix yourself. If you look at MessageStreamIterator and MessageStreamWriter, you'll see how I do this - basically I pretend that I'm in the middle of a message, writing a nested message as field 1. Unfortunately when reading the message, I have to use internal details (BuildImpl).
There's now another API to do this: IMessage.WriteDelimitedTo and IBuilder.MergeDelimitedFrom. This is probably what you want at the moment, but I seem to remember there's a slight issue with it in terms of detecting the end of the stream (i.e. when there isn't another message to read). I can't remember whether there's a fix for it at the moment - I have a feeling it's changed in the Java version and I may not have ported the change yet. Anyway, that's definitely the area to look at.
Protobuf has no terminator - so either close the stream, or use your own length prefix etc. Protobuf-net exposes this easily via SerializeWithLenghtPrefix / DeserializeWithLengthPrefix.
Simply: without this, it can't know where each message ends, so keeps trying to read to the end of the stream.

Categories