diff --git a/Machina.FFXIV/FFXIVNetworkMonitor.cs b/Machina.FFXIV/FFXIVNetworkMonitor.cs index 228c3c5..76ee5eb 100644 --- a/Machina.FFXIV/FFXIVNetworkMonitor.cs +++ b/Machina.FFXIV/FFXIVNetworkMonitor.cs @@ -60,7 +60,7 @@ public Boolean UseSocketFilter public delegate void MessageReceivedDelegate(string connection, long epoch, byte[] message); /// - /// Specifies the delegate that is called when data is received and successfully decoded/ + /// Specifies the delegate that is called when data is received and successfully decoded. /// public MessageReceivedDelegate MessageReceived = null; @@ -104,7 +104,7 @@ public void Start() _monitor.WindowName = "FINAL FANTASY XIV"; _monitor.MonitorType = MonitorType; _monitor.LocalIP = LocalIP; - _monitor.UseOneSocketPerRemoteIP = UseSocketFilter; + _monitor.UseSocketFilter = UseSocketFilter; _monitor.DataSent = (string connection, byte[] data) => ProcessSentMessage(connection, data); _monitor.DataReceived = (string connection, byte[] data) => ProcessReceivedMessage(connection, data); diff --git a/Machina.Tests/TCPNetworkMonitorTests.cs b/Machina.Tests/TCPNetworkMonitorTests.cs index 98a3483..95944db 100644 --- a/Machina.Tests/TCPNetworkMonitorTests.cs +++ b/Machina.Tests/TCPNetworkMonitorTests.cs @@ -23,7 +23,7 @@ public void TCPNetworkMonitor_RawSocket_SendAndReceiveData() monitor.MonitorType = TCPNetworkMonitor.NetworkMonitorType.RawSocket; monitor.DataReceived += (string connection, byte[] data) => DataReceived(connection, data); monitor.DataSent += (string connection, byte[] data) => DataSent(connection, data); - monitor.UseOneSocketPerRemoteIP = false; + monitor.UseSocketFilter = false; monitor.Start(); // start a dummy async download diff --git a/Machina/Properties/AssemblyInfo.cs b/Machina/Properties/AssemblyInfo.cs index afe37ce..0dbebfc 100644 --- a/Machina/Properties/AssemblyInfo.cs +++ b/Machina/Properties/AssemblyInfo.cs @@ -51,7 +51,7 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyVersion("2.1.0.0")] [assembly: AssemblyInformationalVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.1.0.0")] diff --git a/Machina/RawPCap.cs b/Machina/RawPCap.cs index b3fe0ea..826ffeb 100644 --- a/Machina/RawPCap.cs +++ b/Machina/RawPCap.cs @@ -243,7 +243,14 @@ public void Destroy() else break; - _thread.Abort(); + try + { + if (_thread.IsAlive) + _thread.Abort(); + } + catch (Exception) + { + } _thread = null; } @@ -377,6 +384,8 @@ private void StartCapture(Device device, uint remoteAddress) // Start thread _thread = new Thread(new ThreadStart(RunCaptureLoop)); + _thread.Name = "Machina.RawPCap.RunCaptureLoop"; + _thread.IsBackground = true; _thread.Start(); } catch (Exception ex) @@ -399,13 +408,15 @@ private void StartCapture(Device device, uint remoteAddress) private unsafe void RunCaptureLoop() { - try + bool bExceptionLogged = false; + + while (_cancelThread == false) { - while (_cancelThread == false) + try { if (_activeDevice == null) { - System.Threading.Thread.Sleep(100); + Thread.Sleep(100); continue; } @@ -416,26 +427,30 @@ private unsafe void RunCaptureLoop() // note: buffer returned by pcap_next_ex is static and owned by pcap library, does not need to be freed. int status = pcap_next_ex(_activeDevice.Handle, ref packetHeaderPtr, ref packetDataPtr); - if (status == 0)//500ms timeout + if (status == 0) // 500ms timeout continue; else if (status == -1) // error { - string error = "";// Marshal.PtrToStringAnsi(pcap_geterr(_activeDevice.Handle)); - Trace.Write("RawPCap: Error during pcap_loop. " + error); + string error = Marshal.PtrToStringAnsi(pcap_geterr(_activeDevice.Handle)); + if (!bExceptionLogged) + Trace.WriteLine("RawPCap: Error during pcap_loop. " + error); - System.Threading.Thread.Sleep(100); - continue; + bExceptionLogged = true; + + Thread.Sleep(100); } else if (status != 1) // anything else besides success { - Trace.Write("RawPCap: Unknown response code [" + status.ToString() + "] from pcap_next_ex.);"); - System.Threading.Thread.Sleep(100); - continue; + if (!bExceptionLogged) + Trace.WriteLine("RawPCap: Unknown response code [" + status.ToString() + "] from pcap_next_ex.);"); + + bExceptionLogged = true; + + Thread.Sleep(100); } else { pcap_pkthdr packetHeader = *(pcap_pkthdr*)packetHeaderPtr; - //pcap_pkthdr packetHeader = (pcap_pkthdr)Marshal.PtrToStructure(packetHeaderPtr, typeof(pcap_pkthdr)); if (packetHeader.caplen <= layer2Length) continue; @@ -444,7 +459,7 @@ private unsafe void RunCaptureLoop() // prepare data - skip the 14-byte ethernet header buffer.AllocatedSize = (int)packetHeader.caplen - layer2Length; if (buffer.AllocatedSize > buffer.Data.Length) - Trace.Write("RawPCap: packet length too large: " + buffer.AllocatedSize.ToString()); + Trace.WriteLine("RawPCap: packet length too large: " + buffer.AllocatedSize.ToString()); else { @@ -454,10 +469,21 @@ private unsafe void RunCaptureLoop() } } } - } - catch (Exception ex) - { - Trace.WriteLine("WinPCap: Exception during RunCaptureLoop. " + ex.ToString()); + catch (ThreadAbortException) + { + // do nothing, thread is aborting. + return; + } + catch (Exception ex) + { + if (!bExceptionLogged) + Trace.WriteLine("WinPCap: Exception during RunCaptureLoop. " + ex.ToString()); + + bExceptionLogged = true; + + // add sleep + Thread.Sleep(100); + } } } @@ -477,11 +503,11 @@ private unsafe void RunCaptureLoop() // else if (status == -1) // { // string error = Marshal.PtrToStringAnsi(pcap_geterr(_activeDevice.Handle)); - // Trace.Write("RawPCap: Error during pcap_loop. " + error); + // Trace.WriteLine("RawPCap: Error during pcap_loop. " + error); // } // else // { - // Trace.Write("RawPCap: Unknown status result from pcap_loop [" + status.ToString() + "]. exiting."); + // Trace.WriteLine("RawPCap: Unknown status result from pcap_loop [" + status.ToString() + "]. exiting."); // return; // } // } diff --git a/Machina/RawSocket.cs b/Machina/RawSocket.cs index 11ec8d6..d4ed68e 100644 --- a/Machina/RawSocket.cs +++ b/Machina/RawSocket.cs @@ -143,7 +143,7 @@ private static void OnReceive(IAsyncResult ar) } catch (Exception ex) { - Trace.Write("RawSocket: Error while receiving socket data. Network capture aborted, please restart application." + ex.ToString()); + Trace.WriteLine("RawSocket: Error while receiving socket data. Network capture aborted, please restart application." + ex.ToString()); } } } diff --git a/Machina/TCPNetworkMonitor.cs b/Machina/TCPNetworkMonitor.cs index e6595a0..359dc2e 100644 --- a/Machina/TCPNetworkMonitor.cs +++ b/Machina/TCPNetworkMonitor.cs @@ -18,7 +18,7 @@ namespace Machina /// supplied to distinguish between multiple connections from the same process. /// DataSent: Delegate that is called when data is sent and successfully decoded through IP and TCP decoders. Note that a connection identifier is /// supplied to distinguish between multiple connections from the same process. - /// UseOneSocketPerRemoteIP: boolean that specifies whether to start data capture as connections are detected within the target process (new behavior), or monitor + /// UseSocketFilter: boolean that specifies whether to start data capture as connections are detected within the target process (new behavior), or monitor /// the primary interface for the process and capture all data sent/received on that interface - and filter it. The new behavior may cause some data to be lost /// on connection startup, but significantly reduces the filtering overhead caused by other traffic on the network interface. /// @@ -59,7 +59,7 @@ public string LocalIP public string WindowName { get; set; } = ""; - public bool UseOneSocketPerRemoteIP + public bool UseSocketFilter { get; set; } = false; #region Data Delegates section @@ -122,9 +122,10 @@ public void Start() _processTCPInfo.ProcessID = ProcessID; _processTCPInfo.ProcessWindowName = WindowName; - _monitorThread = new Thread(new ThreadStart(Run)); - _monitorThread.Priority = ThreadPriority.Highest; - _monitorThread.Start(); + _monitorThread = new Thread(new ParameterizedThreadStart(Run)); + _monitorThread.Name = "Machina.TCPNetworkMonitor.Start"; + _monitorThread.IsBackground = true; + _monitorThread.Start(this); } /// @@ -135,19 +136,29 @@ public void Stop() Abort = true; if (_monitorThread != null) { - for (int i = 0; i < 50; i++) - if (_monitorThread.IsAlive) - System.Threading.Thread.Sleep(100); - else - break; if (_monitorThread.IsAlive) { - _monitorThread.Abort(); + for (int i = 0; i < 50; i++) + if (_monitorThread.IsAlive) + Thread.Sleep(10); + else + break; + } + + try + { + if (_monitorThread.IsAlive) + _monitorThread.Abort(); + } + catch (Exception) + { } + _monitorThread = null; } Cleanup(); + Abort = false; } private void Cleanup() @@ -164,11 +175,11 @@ private void Cleanup() _connections.Clear(); } - private void Run() + private void Run(object state) { - try + while (!(state as TCPNetworkMonitor).Abort) { - while (!Abort) + try { UpdateProcessConnections(); if (_connections.Count == 0) @@ -181,12 +192,19 @@ private void Run() ProcessNetworkData(); - Thread.Sleep(10); + + Thread.Sleep(30); + } + catch (ThreadAbortException) + { + // do nothing, thread is aborting. + return; + } + catch (Exception ex) + { + Trace.WriteLine("TCPNetworkMonitor Error: " + ex.ToString()); + return; } - } - catch (Exception ex) - { - Trace.WriteLine("TCPNetworkMonitor Error: " + ex.ToString()); } Cleanup(); @@ -229,20 +247,20 @@ private void UpdateSockets() bool found = false; for (int j = 0; j < _sockets.Count; j++) if (_connections[i].LocalIP == _sockets[j].LocalIP && - (!UseOneSocketPerRemoteIP || (_connections[i].RemoteIP == _sockets[j].RemoteIP))) + (!UseSocketFilter || (_connections[i].RemoteIP == _sockets[j].RemoteIP))) found = true; if (!found) { Trace.WriteLine("TCPNetworkMonitor: Starting " + MonitorType.ToString() + " listener on [" + new IPAddress(_connections[i].LocalIP).ToString() + "]" + - (UseOneSocketPerRemoteIP ? "=> [" + new IPAddress(_connections[i].RemoteIP).ToString() + "]." : "")); + (UseSocketFilter ? "=> [" + new IPAddress(_connections[i].RemoteIP).ToString() + "]." : "")); if (MonitorType == NetworkMonitorType.WinPCap) _sockets.Add(new RawPCap()); else _sockets.Add(new RawSocket()); - _sockets.Last().Create(_connections[i].LocalIP, UseOneSocketPerRemoteIP ? _connections[i].RemoteIP : 0); + _sockets.Last().Create(_connections[i].LocalIP, UseSocketFilter ? _connections[i].RemoteIP : 0); } } @@ -251,14 +269,14 @@ private void UpdateSockets() bool found = false; for (int j=0;j<_connections.Count;j++) if (_connections[j].LocalIP == _sockets[i].LocalIP && - (!UseOneSocketPerRemoteIP || (_connections[j].RemoteIP == _sockets[i].RemoteIP))) + (!UseSocketFilter || (_connections[j].RemoteIP == _sockets[i].RemoteIP))) found = true; if (!found) { Trace.WriteLine("TCPNetworkMonitor: Stopping " + MonitorType.ToString() + " listener on [" + new IPAddress(_sockets[i].LocalIP).ToString() + "]" + - (UseOneSocketPerRemoteIP ? "=> [" + new IPAddress(_sockets[i].RemoteIP).ToString() + "]." : "")); + (UseSocketFilter ? "=> [" + new IPAddress(_sockets[i].RemoteIP).ToString() + "]." : "")); _sockets[i].Destroy(); _sockets.RemoveAt(i); }