Source/Tx.Network/Pcap/PcapNgWriter.cs (54 lines of code) (raw):

namespace Tx.Network { using System; using System.IO; internal sealed class PcapNgWriter : IObserver<byte[]>, IDisposable { private static readonly byte[] BlockTypeBytes = { 3, 0, 0, 0 }; private readonly byte[] paddingBuffer = { 0, 0, 0, 0 }; private Stream stream; public PcapNgWriter(string filename) { if (filename == null) { throw new ArgumentNullException(nameof(filename)); } this.stream = File.Create(filename); // Write Section Header Block as per http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#section_spb // To have produced files to be compliant with PcapNg format } /// <summary> /// Provides the observer with new data. /// </summary> /// <param name="value">The current notification information.</param> public void OnNext(byte[] value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } var length = 12 + (value.Length / 4 + 1) * 4; var padSize = length - 12 - value.Length; this.stream.Write(BlockTypeBytes, 0, BlockTypeBytes.Length); var size = BitConverter.GetBytes(length); this.stream.Write(size, 0, 4); this.stream.Write(value, 0, value.Length); // do padding if (padSize > 0) { this.stream.Write(this.paddingBuffer, 0, padSize); } this.stream.Write(size, 0, 4); } /// <summary> /// Notifies the observer that the provider has finished sending push-based notifications. /// </summary> public void OnCompleted() { this.Dispose(); } /// <summary> /// Notifies the observer that the provider has experienced an error condition. /// </summary> /// <param name="error">An object that provides additional information about the error.</param> public void OnError(Exception error) { this.Dispose(); } public void Dispose() { if (this.stream != null) { this.stream.Flush(); this.stream.Close(); this.stream = null; } } } }