/// <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); }
private static TunnelInfo FindTunnelInfo(NgrokTunnels ngrokTunnels, int forwardingPort) { TunnelInfo result = null; if (ngrokTunnels != null && ngrokTunnels.Tunnels != null) { foreach (var item in ngrokTunnels.Tunnels) { if (item.Protocol == "https" && item.PublicUrl != null && item.PublicUrl.StartsWith("https://") && item.ForwardingInfo != null && item.ForwardingInfo.Port == forwardingPort) { result = item; break; } } } return(result); }
/// <summary> /// Find Ngrok tunnels. /// </summary> /// <param name="ngrokApiPort">Port for Ngrok api.</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>Ngrok tunnels.</returns> public static async Task <NgrokTunnels> FindNgrokTunnels(int ngrokApiPort, CancellationToken cancellationToken) { NgrokTunnels result = null; try { using var http = new HttpClient(new SocketsHttpHandler { AllowAutoRedirect = false, ConnectTimeout = AppSettings.HTTP_CONNECTION_TIMEOUT, }); http.Timeout = AppSettings.HTTP_CLIENT_TIMEOUT; http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); using var response = await http.GetAsync(String.Format(NGROK_TUNNELS_API, ngrokApiPort), cancellationToken); if (response.IsSuccessStatusCode) { using var content = response.Content; string text = await content.ReadAsStringAsync(cancellationToken); if (Log.IsDebugEnabled) { Log.Debug("Ngrok Tunnels: {TunnelsInfo}", text); } result = JsonSerializer.Deserialize <NgrokTunnels>(text); } } catch (Exception ex) { Log.Error(ex, "Failed to find Ngrok tunnelings."); } cancellationToken.ThrowIfCancellationRequested(); return(result); }