public static async Task PcapToPdmp( string pcapFile, string[] keyFiles, string outputFile, ITShark tshark, CancellationToken cancellation, Action <string> reportStatus, LJTraceSource trace ) { var tsharkArgs = new StringBuilder(); tsharkArgs.Append($"-r \"{pcapFile}\""); tsharkArgs.Append($" -T pdml -2"); var keyFile = keyFiles.FirstOrDefault(); // todo: support many files if (!string.IsNullOrEmpty(keyFile) && File.Exists(keyFile)) { tsharkArgs.Append($" -o \"ssl.desegment_ssl_records: TRUE\" -o \"ssl.desegment_ssl_application_data: TRUE\" -o \"ssl.keylog_file:{keyFile}\""); } using (var process = tshark.Start(tsharkArgs.ToString())) using (var cancellationSub = cancellation.Register(() => process.Kill())) using (var xmlReader = XmlReader.Create(process.StandardOutput)) using (var writer = new StreamWriter(outputFile, false, new UTF8Encoding(false))) { var packetsRead = 0; var processTask = process.GetExitCodeAsync(Timeout.InfiniteTimeSpan); using (var statusReportTimer = new Timer( _ => reportStatus($"converting to text: {packetsRead} packets"), null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(1))) { await Task.WhenAll( processTask, Convert(xmlReader, writer, cancellation, val => packetsRead = val, trace) ); } if (processTask.Result != 0) { trace.Error("tshark failed: {0}", process.StandardError.ReadToEnd()); throw new Exception($"tshark failed with code {processTask.Result}"); } } }