private void PingTunnels(object _tunnels) { List <CnCNetTunnel> Tunnels = (List <CnCNetTunnel>)_tunnels; for (int tnlId = 0; tnlId < Tunnels.Count; tnlId++) { CnCNetTunnel tunnel = Tunnels[tnlId]; if (!tunnel.Official) { int pingInMs = -1; Ping p = new Ping(); try { PingReply reply = p.Send(IPAddress.Parse(tunnel.Address), 500); if (reply.Status == IPStatus.Success) { if (reply.RoundtripTime > 0) { pingInMs = Convert.ToInt32(reply.RoundtripTime); } } } catch { } if (pingInMs > -1) { tunnel.PingInMs = pingInMs; } DoTunnelPinged(tnlId, pingInMs); } } }
/// <summary> /// Parses a formatted string that contains the tunnel server's /// information into a CnCNetTunnel instance. /// </summary> /// <param name="str">The string that contains the tunnel server's information.</param> /// <returns>A CnCNetTunnel instance parsed from the given string.</returns> public static CnCNetTunnel Parse(string str) { // For the format, check http://cncnet.org/master-list try { var tunnel = new CnCNetTunnel(); string[] parts = str.Split(';'); string address = parts[0]; string[] detailedAddress = address.Split(new char[] { ':' }); tunnel.Address = detailedAddress[0]; tunnel.Port = int.Parse(detailedAddress[1]); tunnel.Country = parts[1]; tunnel.CountryCode = parts[2]; tunnel.Name = parts[3]; tunnel.RequiresPassword = parts[4] != "0"; tunnel.Clients = int.Parse(parts[5]); tunnel.MaxClients = int.Parse(parts[6]); int status = int.Parse(parts[7]); tunnel.Official = status == 2; if (!tunnel.Official) { tunnel.Recommended = status == 1; } CultureInfo cultureInfo = CultureInfo.InvariantCulture; tunnel.Latitude = double.Parse(parts[8], cultureInfo); tunnel.Longitude = double.Parse(parts[9], cultureInfo); tunnel.Version = int.Parse(parts[10]); tunnel.Distance = double.Parse(parts[11], cultureInfo); return(tunnel); } catch (Exception ex) { if (ex is FormatException || ex is OverflowException || ex is IndexOutOfRangeException) { Logger.Log("Parsing tunnel information failed: " + ex.Message + Environment.NewLine + "Parsed string: " + str); return(null); } throw ex; } }
private void HandleRefreshedTunnels(List <CnCNetTunnel> tunnels) { if (tunnels.Count > 0) { Tunnels = tunnels; } TunnelsRefreshed?.Invoke(this, EventArgs.Empty); Task[] pingTasks = new Task[Tunnels.Count]; for (int i = 0; i < Tunnels.Count; i++) { if (UserINISettings.Instance.PingUnofficialCnCNetTunnels || Tunnels[i].Official || Tunnels[i].Recommended) { pingTasks[i] = PingListTunnelAsync(i); } } if (CurrentTunnel != null) { var updatedTunnel = Tunnels.Find(t => t.Address == CurrentTunnel.Address && t.Port == CurrentTunnel.Port); if (updatedTunnel != null) { // don't re-ping if the tunnel still exists in list, just update the tunnel instance and // fire the event handler (the tunnel was already pinged when traversing the tunnel list) CurrentTunnel = updatedTunnel; DoCurrentTunnelPinged(); } else { // tunnel is not in the list anymore so it's not updated with a list instance and pinged PingCurrentTunnelAsync(); } } }
/// <summary> /// Downloads and parses the list of CnCNet tunnels. /// </summary> /// <returns>A list of tunnel servers.</returns> private List <CnCNetTunnel> RefreshTunnels() { string tunnelCacheFile = ProgramConstants.GamePath + "Client\\tunnel_cache"; List <CnCNetTunnel> returnValue = new List <CnCNetTunnel>(); WebClient client = new WebClient(); byte[] data; Logger.Log("Fetching tunnel server info."); try { data = client.DownloadData(MainClientConstants.CNCNET_TUNNEL_LIST_URL); } catch (Exception ex) { Logger.Log("Error when downloading tunnel server info: " + ex.Message); Logger.Log("Retrying."); try { data = client.DownloadData(MainClientConstants.CNCNET_TUNNEL_LIST_URL); } catch { if (!File.Exists(tunnelCacheFile)) { Logger.Log("Tunnel cache file doesn't exist!"); return(returnValue); } else { Logger.Log("Fetching tunnel server list failed. Using cached tunnel data."); data = File.ReadAllBytes(tunnelCacheFile); } } } string convertedData = Encoding.Default.GetString(data); string[] serverList = convertedData.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string serverInfo in serverList) { try { CnCNetTunnel tunnel = CnCNetTunnel.Parse(serverInfo); if (tunnel == null) { continue; } if (tunnel.RequiresPassword) { continue; } if (tunnel.Version != SUPPORTED_TUNNEL_VERSION) { continue; } if (tunnel.Official || tunnel.Recommended) { Ping p = new Ping(); try { PingReply reply = p.Send(IPAddress.Parse(tunnel.Address), 500); if (reply.Status == IPStatus.Success) { if (reply.RoundtripTime > 0) { tunnel.PingInMs = Convert.ToInt32(reply.RoundtripTime); } } } catch { } } returnValue.Add(tunnel); } catch { } } if (returnValue.Count > 0) { try { if (File.Exists(tunnelCacheFile)) { File.Delete(tunnelCacheFile); } if (!Directory.Exists(ProgramConstants.GamePath + "Client")) { Directory.CreateDirectory(ProgramConstants.GamePath + "Client"); } File.WriteAllBytes(tunnelCacheFile, data); } catch (Exception ex) { Logger.Log("Refreshing tunnel cache file failed! Returned error: " + ex.Message); } } return(returnValue); }
/// <summary> /// Downloads and parses the list of CnCNet tunnels. /// </summary> /// <returns>A list of tunnel servers.</returns> private List <CnCNetTunnel> RefreshTunnels() { string tunnelCacheFile = ProgramConstants.GamePath + "Client\\tunnel_cache"; List <CnCNetTunnel> returnValue = new List <CnCNetTunnel>(); WebClient client = new WebClient(); byte[] data; Logger.Log("Fetching tunnel server info."); try { data = client.DownloadData("http://cncnet.org/master-list"); } catch (Exception ex) { Logger.Log("Error when downloading tunnel server info: " + ex.Message); Logger.Log("Retrying."); try { data = client.DownloadData("http://cncnet.org/master-list"); } catch { if (!File.Exists(tunnelCacheFile)) { Logger.Log("Tunnel cache file doesn't exist!"); return(returnValue); } else { Logger.Log("Fetching tunnel server list failed. Using cached tunnel data."); data = File.ReadAllBytes(tunnelCacheFile); } } } string convertedData = Encoding.Default.GetString(data); string[] serverList = convertedData.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string serverinfo in serverList) { string[] serverInfo = serverinfo.Split(new char[] { ';' }); CnCNetTunnel tunnel = new CnCNetTunnel(); try { string address = serverInfo[0]; string[] detailedAddress = address.Split(new char[] { ':' }); tunnel.Address = detailedAddress[0]; tunnel.Port = Convert.ToInt32(detailedAddress[1]); tunnel.Country = serverInfo[1]; tunnel.CountryCode = serverInfo[2]; tunnel.Name = serverInfo[3]; tunnel.RequiresPassword = Conversions.BooleanFromString(serverInfo[4], true); tunnel.Clients = Convert.ToInt32(serverInfo[5]); tunnel.MaxClients = Convert.ToInt32(serverInfo[6]); tunnel.Official = (Convert.ToInt32(serverInfo[7]) == 2); if (!tunnel.Official) { tunnel.Recommended = (Convert.ToInt32(serverInfo[7]) == 1); } CultureInfo cultureInfo = CultureInfo.GetCultureInfo("en-US"); tunnel.Latitude = Convert.ToDouble(serverInfo[8], cultureInfo); tunnel.Longitude = Convert.ToDouble(serverInfo[9], cultureInfo); tunnel.Version = Convert.ToInt32(serverInfo[10]); tunnel.Distance = Convert.ToDouble(serverInfo[11], cultureInfo); tunnel.PingInMs = -1; if (tunnel.RequiresPassword) { continue; } if (tunnel.Version != 2) { continue; } if (tunnel.Official || tunnel.Recommended) { Ping p = new Ping(); try { PingReply reply = p.Send(IPAddress.Parse(detailedAddress[0]), 500); if (reply.Status == IPStatus.Success) { if (reply.RoundtripTime > 0) { tunnel.PingInMs = Convert.ToInt32(reply.RoundtripTime); } } } catch { } } returnValue.Add(tunnel); } catch { } } if (returnValue.Count > 0) { try { if (File.Exists(tunnelCacheFile)) { File.Delete(tunnelCacheFile); } if (!Directory.Exists(ProgramConstants.GamePath + "Client")) { Directory.CreateDirectory(ProgramConstants.GamePath + "Client"); } File.WriteAllBytes(tunnelCacheFile, data); } catch (Exception ex) { Logger.Log("Refreshing tunnel cache file failed! Returned error: " + ex.Message); } } return(returnValue); }