/// <summary> /// Starts the packet diversion with the given number of threads. /// </summary> /// <param name="numThreads"> /// The number of threads to use for diversion. If equal to or less than zero, will default /// to Environment.ProcessorCount. /// </param> /// <remarks> /// The number of threads ought not to exceed Environment.ProcessorCount but this is not /// enforced with a bounds check. /// </remarks> public void Start(int numThreads) { lock (m_startStopLock) { if (m_running) { return; } if (numThreads <= 0) { numThreads = Environment.ProcessorCount; } m_diversionThreads = new List <Thread>(); #if ENGINE_NO_BLOCK_TOR string mainFilterString = "outbound and tcp and ((ip and ip.SrcAddr != 127.0.0.1) or (ipv6 and ipv6.SrcAddr != ::1))"; #else string mainFilterString = "outbound and tcp"; #endif string QUICFilterString = "udp and (udp.DstPort == 80 || udp.DstPort == 443)"; m_diversionHandle = WinDivertMethods.WinDivertOpen(mainFilterString, WINDIVERT_LAYER.WINDIVERT_LAYER_NETWORK, -1000, 0); if (m_diversionHandle == new IntPtr(-1) || m_diversionHandle == IntPtr.Zero) { // Invalid handle value. throw new Exception(string.Format("Failed to open main diversion handle. Got Win32 error code {0}.", Marshal.GetLastWin32Error())); } m_QUICDropHandle = WinDivertMethods.WinDivertOpen(QUICFilterString, WINDIVERT_LAYER.WINDIVERT_LAYER_NETWORK, -999, WinDivertConstants.WINDIVERT_FLAG_DROP); if (m_QUICDropHandle == new IntPtr(-1) || m_QUICDropHandle == IntPtr.Zero) { // Invalid handle value. throw new Exception(string.Format("Failed to open QUIC diversion handle. Got Win32 error code {0}.", Marshal.GetLastWin32Error())); } WinDivertMethods.WinDivertSetParam(m_diversionHandle, WINDIVERT_PARAM.WINDIVERT_PARAM_QUEUE_LEN, 8192); WinDivertMethods.WinDivertSetParam(m_diversionHandle, WINDIVERT_PARAM.WINDIVERT_PARAM_QUEUE_TIME, 2048); m_running = true; for (int i = 0; i < numThreads; ++i) { m_diversionThreads.Add(new Thread(() => { RunDiversion(); })); m_diversionThreads.Last().Start(); } } }