You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Server.cs 6.0 kB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Specialized;
  4. using System.Text;
  5. using System.Web;
  6. using Shadowsocks.Controller;
  7. namespace Shadowsocks.Model
  8. {
  9. [Serializable]
  10. public class Server
  11. {
  12. private const int DefaultServerTimeoutSec = 5;
  13. public const int MaxServerTimeoutSec = 20;
  14. public string server;
  15. public int server_port;
  16. public string password;
  17. public string method;
  18. public string plugin;
  19. public string plugin_opts;
  20. public string remarks;
  21. public int timeout;
  22. public override int GetHashCode()
  23. {
  24. return server.GetHashCode() ^ server_port;
  25. }
  26. public override bool Equals(object obj)
  27. {
  28. Server o2 = (Server)obj;
  29. return server == o2.server && server_port == o2.server_port;
  30. }
  31. public string FriendlyName()
  32. {
  33. if (server.IsNullOrEmpty())
  34. {
  35. return I18N.GetString("New server");
  36. }
  37. string serverStr;
  38. // CheckHostName() won't do a real DNS lookup
  39. var hostType = Uri.CheckHostName(server);
  40. switch (hostType)
  41. {
  42. case UriHostNameType.IPv6:
  43. serverStr = $"[{server}]:{server_port}";
  44. break;
  45. default:
  46. // IPv4 and domain name
  47. serverStr = $"{server}:{server_port}";
  48. break;
  49. }
  50. return remarks.IsNullOrEmpty()
  51. ? serverStr
  52. : $"{remarks} ({serverStr})";
  53. }
  54. public Server()
  55. {
  56. server = "";
  57. server_port = 8388;
  58. method = "aes-256-cfb";
  59. plugin = "";
  60. plugin_opts = "";
  61. password = "";
  62. remarks = "";
  63. timeout = DefaultServerTimeoutSec;
  64. }
  65. public static List<Server> GetServers(string ssURL)
  66. {
  67. var serverUrls = ssURL.Split('\r', '\n');
  68. List<Server> servers = new List<Server>();
  69. foreach (string serverUrl in serverUrls)
  70. {
  71. if (string.IsNullOrWhiteSpace(serverUrl))
  72. {
  73. continue;
  74. }
  75. Uri parsedUrl;
  76. try
  77. {
  78. parsedUrl = new Uri(serverUrl);
  79. }
  80. catch (UriFormatException)
  81. {
  82. continue;
  83. }
  84. Server tmp = new Server
  85. {
  86. remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)
  87. };
  88. string possiblyUnpaddedBase64 = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
  89. bool isOldFormatUrl = possiblyUnpaddedBase64.Length == 0;
  90. if (isOldFormatUrl)
  91. {
  92. int prefixLength = "ss://".Length;
  93. int indexOfHashOrSlash = serverUrl.LastIndexOfAny(
  94. new[] { '/', '#' },
  95. serverUrl.Length - 1,
  96. serverUrl.Length - prefixLength);
  97. int substringLength = serverUrl.Length - prefixLength;
  98. if (indexOfHashOrSlash >= 0)
  99. {
  100. substringLength = indexOfHashOrSlash - prefixLength;
  101. }
  102. possiblyUnpaddedBase64 = serverUrl.Substring(prefixLength, substringLength).TrimEnd('/');
  103. }
  104. else
  105. {
  106. // Web-safe base64 to normal base64
  107. possiblyUnpaddedBase64 = possiblyUnpaddedBase64.Replace('-', '+').Replace('_', '/');
  108. }
  109. string base64 = possiblyUnpaddedBase64.PadRight(
  110. possiblyUnpaddedBase64.Length + (4 - possiblyUnpaddedBase64.Length % 4) % 4,
  111. '=');
  112. string innerUserInfoOrUrl = Encoding.UTF8.GetString(Convert.FromBase64String(base64));
  113. string userInfo;
  114. if (isOldFormatUrl)
  115. {
  116. Uri innerUrl = new Uri("inner://" + innerUserInfoOrUrl);
  117. userInfo = innerUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped);
  118. tmp.server = innerUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped);
  119. tmp.server_port = innerUrl.Port;
  120. }
  121. else
  122. {
  123. userInfo = innerUserInfoOrUrl;
  124. tmp.server = parsedUrl.GetComponents(UriComponents.Host, UriFormat.Unescaped);
  125. tmp.server_port = parsedUrl.Port;
  126. }
  127. string[] userInfoParts = userInfo.Split(new[] { ':' }, 2);
  128. if (userInfoParts.Length != 2)
  129. {
  130. continue;
  131. }
  132. tmp.method = userInfoParts[0];
  133. tmp.password = userInfoParts[1];
  134. NameValueCollection queryParameters = HttpUtility.ParseQueryString(parsedUrl.Query);
  135. string[] pluginParts = HttpUtility.UrlDecode(queryParameters["plugin"] ?? "").Split(new[] { ';' }, 2);
  136. if (pluginParts.Length > 0)
  137. {
  138. tmp.plugin = pluginParts[0] ?? "";
  139. }
  140. if (pluginParts.Length > 1)
  141. {
  142. tmp.plugin_opts = pluginParts[1] ?? "";
  143. }
  144. servers.Add(tmp);
  145. }
  146. return servers;
  147. }
  148. public string Identifier()
  149. {
  150. return server + ':' + server_port;
  151. }
  152. }
  153. }