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.

Util.cs 8.4 kB

10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.IO.Compression;
  6. using System.Linq;
  7. using System.Runtime.InteropServices;
  8. using System.Windows.Forms;
  9. using Microsoft.Win32;
  10. using Shadowsocks.Controller;
  11. namespace Shadowsocks.Util
  12. {
  13. public struct BandwidthScaleInfo
  14. {
  15. public float value;
  16. public string unit_name;
  17. public long unit;
  18. public BandwidthScaleInfo(float value, string unit_name, long unit)
  19. {
  20. this.value = value;
  21. this.unit_name = unit_name;
  22. this.unit = unit;
  23. }
  24. }
  25. public class Utils
  26. {
  27. private static bool? _portableMode;
  28. private static string TempPath = null;
  29. public static bool IsPortableMode()
  30. {
  31. if (!_portableMode.HasValue)
  32. {
  33. _portableMode = File.Exists(Path.Combine(Application.StartupPath, "shadowsocks_portable_mode.txt"));
  34. }
  35. return _portableMode.Value;
  36. }
  37. // return path to store temporary files
  38. public static string GetTempPath()
  39. {
  40. if (TempPath == null)
  41. {
  42. if (IsPortableMode())
  43. try
  44. {
  45. Directory.CreateDirectory(Path.Combine(Application.StartupPath, "temp"));
  46. }
  47. catch (Exception e)
  48. {
  49. TempPath = Path.GetTempPath();
  50. Logging.LogUsefulException(e);
  51. }
  52. finally
  53. {
  54. // don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log
  55. TempPath = Path.Combine(Application.StartupPath, "temp");
  56. }
  57. else
  58. TempPath = Path.GetTempPath();
  59. }
  60. return TempPath;
  61. }
  62. // return a full path with filename combined which pointed to the temporary directory
  63. public static string GetTempPath(string filename)
  64. {
  65. return Path.Combine(GetTempPath(), filename);
  66. }
  67. public static void ReleaseMemory(bool removePages)
  68. {
  69. // release any unused pages
  70. // making the numbers look good in task manager
  71. // this is totally nonsense in programming
  72. // but good for those users who care
  73. // making them happier with their everyday life
  74. // which is part of user experience
  75. GC.Collect(GC.MaxGeneration);
  76. GC.WaitForPendingFinalizers();
  77. if (removePages)
  78. {
  79. // as some users have pointed out
  80. // removing pages from working set will cause some IO
  81. // which lowered user experience for another group of users
  82. //
  83. // so we do 2 more things here to satisfy them:
  84. // 1. only remove pages once when configuration is changed
  85. // 2. add more comments here to tell users that calling
  86. // this function will not be more frequent than
  87. // IM apps writing chat logs, or web browsers writing cache files
  88. // if they're so concerned about their disk, they should
  89. // uninstall all IM apps and web browsers
  90. //
  91. // please open an issue if you're worried about anything else in your computer
  92. // no matter it's GPU performance, monitor contrast, audio fidelity
  93. // or anything else in the task manager
  94. // we'll do as much as we can to help you
  95. //
  96. // just kidding
  97. SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle,
  98. (UIntPtr)0xFFFFFFFF,
  99. (UIntPtr)0xFFFFFFFF);
  100. }
  101. }
  102. public static string UnGzip(byte[] buf)
  103. {
  104. byte[] buffer = new byte[1024];
  105. int n;
  106. using (MemoryStream sb = new MemoryStream())
  107. {
  108. using (GZipStream input = new GZipStream(new MemoryStream(buf),
  109. CompressionMode.Decompress,
  110. false))
  111. {
  112. while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
  113. {
  114. sb.Write(buffer, 0, n);
  115. }
  116. }
  117. return System.Text.Encoding.UTF8.GetString(sb.ToArray());
  118. }
  119. }
  120. public static string FormatBandwidth(long n)
  121. {
  122. var result = GetBandwidthScale(n);
  123. return $"{result.value:0.##}{result.unit_name}";
  124. }
  125. public static string FormatBytes(long bytes)
  126. {
  127. const long K = 1024L;
  128. const long M = K * 1024L;
  129. const long G = M * 1024L;
  130. const long T = G * 1024L;
  131. const long P = T * 1024L;
  132. const long E = P * 1024L;
  133. if (bytes >= P * 990)
  134. return (bytes / (double)E).ToString("F5") + "EiB";
  135. if (bytes >= T * 990)
  136. return (bytes / (double)P).ToString("F5") + "PiB";
  137. if (bytes >= G * 990)
  138. return (bytes / (double)T).ToString("F5") + "TiB";
  139. if (bytes >= M * 990)
  140. {
  141. return (bytes / (double)G).ToString("F4") + "GiB";
  142. }
  143. if (bytes >= M * 100)
  144. {
  145. return (bytes / (double)M).ToString("F1") + "MiB";
  146. }
  147. if (bytes >= M * 10)
  148. {
  149. return (bytes / (double)M).ToString("F2") + "MiB";
  150. }
  151. if (bytes >= K * 990)
  152. {
  153. return (bytes / (double)M).ToString("F3") + "MiB";
  154. }
  155. if (bytes > K * 2)
  156. {
  157. return (bytes / (double)K).ToString("F1") + "KiB";
  158. }
  159. return bytes.ToString() + "B";
  160. }
  161. /// <summary>
  162. /// Return scaled bandwidth
  163. /// </summary>
  164. /// <param name="n">Raw bandwidth</param>
  165. /// <returns>
  166. /// The BandwidthScaleInfo struct
  167. /// </returns>
  168. public static BandwidthScaleInfo GetBandwidthScale(long n)
  169. {
  170. long scale = 1;
  171. float f = n;
  172. string unit = "B";
  173. if (f > 1024)
  174. {
  175. f = f / 1024;
  176. scale <<= 10;
  177. unit = "KiB";
  178. }
  179. if (f > 1024)
  180. {
  181. f = f / 1024;
  182. scale <<= 10;
  183. unit = "MiB";
  184. }
  185. if (f > 1024)
  186. {
  187. f = f / 1024;
  188. scale <<= 10;
  189. unit = "GiB";
  190. }
  191. if (f > 1024)
  192. {
  193. f = f / 1024;
  194. scale <<= 10;
  195. unit = "TiB";
  196. }
  197. return new BandwidthScaleInfo(f, unit, scale);
  198. }
  199. public static RegistryKey OpenUserRegKey( string name, bool writable ) {
  200. // we are building x86 binary for both x86 and x64, which will
  201. // cause problem when opening registry key
  202. // detect operating system instead of CPU
  203. RegistryKey userKey = RegistryKey.OpenRemoteBaseKey( RegistryHive.CurrentUser, "",
  204. Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32 )
  205. .OpenSubKey( name, writable );
  206. return userKey;
  207. }
  208. public static bool IsWinVistaOrHigher() {
  209. return Environment.OSVersion.Version.Major > 5;
  210. }
  211. [DllImport("kernel32.dll")]
  212. [return: MarshalAs(UnmanagedType.Bool)]
  213. private static extern bool SetProcessWorkingSetSize(IntPtr process,
  214. UIntPtr minimumWorkingSetSize, UIntPtr maximumWorkingSetSize);
  215. }
  216. }