/// <summary> /// Find Ngrok tunnel info. /// </summary> /// <param name="ngrokApiPort">Port for Ngrok api.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>Ngrok tunnel info.</returns> public async Task <TunnelInfo> FindTunnel(int forwardingPort, string ngrokRegion, CancellationToken cancellationToken) { TunnelInfo result = null; try { NgrokTunnels tunnels = null; tunnels = await FindNgrokTunnels(this.ngrokApiPort, cancellationToken); result = FindTunnelInfo(tunnels, forwardingPort); if (tunnels != null && result == null) { if (this.ngrokProcess != null) { if (this.ngrokProcess.Close()) { tunnels = null; } this.ngrokProcess.Dispose(); } } if (tunnels == null) { this.ngrokProcess = NgrokProcess.StartProcess(forwardingPort, ngrokRegion); int delay = RETRY_INITIAL_DELAY; for (int i = 0; i < RETRY_MAX; i++) { // delay will be 500, 1000, 2000, 4000 ms, so about 7500 ms in max. await Task.Delay(delay, cancellationToken); tunnels = await FindNgrokTunnels(this.ngrokApiPort, cancellationToken); result = FindTunnelInfo(tunnels, forwardingPort); if (result != null) { break; } delay *= 2; } } } catch (Exception ex) { Log.Error(ex, "Failed to find Ngrok tunneling info."); } cancellationToken.ThrowIfCancellationRequested(); return(result); }
protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { this.ngrokProcess?.Close(); this.ngrokProcess?.Dispose(); this.ngrokProcess = null; } // TODO: free unmanaged resources (unmanaged objects) and override finalizer // TODO: set large fields to null disposedValue = true; } }