@@ -1,9 +1,9 @@ | |||||
using Shadowsocks.Util; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System; | |||||
using System.IO; | using System.IO; | ||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using System.Text; | |||||
using System.Net; | |||||
using Shadowsocks.Util; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -15,8 +15,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
string temppath = Utils.GetTempPath(); | |||||
LogFile = Path.Combine(temppath, "shadowsocks.log"); | |||||
LogFile = Utils.GetTempPath("shadowsocks.log"); | |||||
FileStream fs = new FileStream(LogFile, FileMode.Append); | FileStream fs = new FileStream(LogFile, FileMode.Append); | ||||
StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs); | StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs); | ||||
sw.AutoFlush = true; | sw.AutoFlush = true; | ||||
@@ -34,7 +33,7 @@ namespace Shadowsocks.Controller | |||||
public static void Error(object o) | public static void Error(object o) | ||||
{ | { | ||||
Console.WriteLine("[E] "+ o); | |||||
Console.WriteLine("[E] " + o); | |||||
} | } | ||||
public static void Info(object o) | public static void Info(object o) | ||||
@@ -49,6 +48,25 @@ namespace Shadowsocks.Controller | |||||
#endif | #endif | ||||
} | } | ||||
#if DEBUG | |||||
public static void Debug(EndPoint local, EndPoint remote, int len, string header = null, string tailer = null) | |||||
{ | |||||
if (header == null && tailer == null) | |||||
Debug($"{local} => {remote} (size={len})"); | |||||
else if (header == null && tailer != null) | |||||
Debug($"{local} => {remote} (size={len}), {tailer}"); | |||||
else if (header != null && tailer == null) | |||||
Debug($"{header}: {local} => {remote} (size={len})"); | |||||
else | |||||
Debug($"{header}: {local} => {remote} (size={len}), {tailer}"); | |||||
} | |||||
public static void Debug(Socket sock, int len, string header = null, string tailer = null) | |||||
{ | |||||
Debug(sock.LocalEndPoint, sock.RemoteEndPoint, len, header, tailer); | |||||
} | |||||
#endif | |||||
public static void LogUsefulException(Exception e) | public static void LogUsefulException(Exception e) | ||||
{ | { | ||||
// just log useful exceptions, not all of them | // just log useful exceptions, not all of them | ||||
@@ -9,6 +9,7 @@ using System.Net.NetworkInformation; | |||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using Shadowsocks.Model; | using Shadowsocks.Model; | ||||
using Shadowsocks.Util; | using Shadowsocks.Util; | ||||
@@ -30,8 +31,8 @@ namespace Shadowsocks.Controller | |||||
public Statistics FilteredStatistics { get; private set; } | public Statistics FilteredStatistics { get; private set; } | ||||
public static readonly DateTime UnknownDateTime = new DateTime(1970, 1, 1); | public static readonly DateTime UnknownDateTime = new DateTime(1970, 1, 1); | ||||
private int Repeat => _config.RepeatTimesNum; | private int Repeat => _config.RepeatTimesNum; | ||||
private const int RetryInterval = 2*60*1000; //retry 2 minutes after failed | |||||
private int Interval => (int) TimeSpan.FromMinutes(_config.DataCollectionMinutes).TotalMilliseconds; | |||||
private const int RetryInterval = 2 * 60 * 1000; //retry 2 minutes after failed | |||||
private int Interval => (int)TimeSpan.FromMinutes(_config.DataCollectionMinutes).TotalMilliseconds; | |||||
private Timer _timer; | private Timer _timer; | ||||
private State _state; | private State _state; | ||||
private List<Server> _servers; | private List<Server> _servers; | ||||
@@ -42,8 +43,7 @@ namespace Shadowsocks.Controller | |||||
//static constructor to initialize every public static fields before refereced | //static constructor to initialize every public static fields before refereced | ||||
static AvailabilityStatistics() | static AvailabilityStatistics() | ||||
{ | { | ||||
var temppath = Utils.GetTempPath(); | |||||
AvailabilityStatisticsFile = Path.Combine(temppath, StatisticsFilesName); | |||||
AvailabilityStatisticsFile = Utils.GetTempPath(StatisticsFilesName); | |||||
} | } | ||||
public AvailabilityStatistics(Configuration config, StatisticsStrategyConfiguration statisticsConfig) | public AvailabilityStatistics(Configuration config, StatisticsStrategyConfiguration statisticsConfig) | ||||
@@ -181,11 +181,11 @@ namespace Shadowsocks.Controller | |||||
if (!File.Exists(AvailabilityStatisticsFile)) | if (!File.Exists(AvailabilityStatisticsFile)) | ||||
{ | { | ||||
var headerLine = string.Join(Delimiter, data.Select(kv => kv.Key).ToArray()); | var headerLine = string.Join(Delimiter, data.Select(kv => kv.Key).ToArray()); | ||||
lines = new[] {headerLine, dataLine}; | |||||
lines = new[] { headerLine, dataLine }; | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
lines = new[] {dataLine}; | |||||
lines = new[] { dataLine }; | |||||
} | } | ||||
try | try | ||||
{ | { | ||||
@@ -248,30 +248,29 @@ namespace Shadowsocks.Controller | |||||
Logging.Debug($"loading statistics from {path}"); | Logging.Debug($"loading statistics from {path}"); | ||||
if (!File.Exists(path)) | if (!File.Exists(path)) | ||||
{ | { | ||||
Console.WriteLine($"statistics file does not exist, try to reload {RetryInterval/60/1000} minutes later"); | |||||
Console.WriteLine($"statistics file does not exist, try to reload {RetryInterval / 60 / 1000} minutes later"); | |||||
_timer.Change(RetryInterval, Interval); | _timer.Change(RetryInterval, Interval); | ||||
return; | return; | ||||
} | } | ||||
RawStatistics = (from l in File.ReadAllLines(path) | |||||
.Skip(1) | |||||
let strings = l.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries) | |||||
let rawData = new RawStatisticsData | |||||
{ | |||||
Timestamp = ParseExactOrUnknown(strings[0]), | |||||
ServerName = strings[1], | |||||
ICMPStatus = strings[2], | |||||
RoundtripTime = int.Parse(strings[3]), | |||||
Geolocation = 5 > strings.Length ? | |||||
null | |||||
: strings[4], | |||||
ISP = 6 > strings.Length ? null : strings[5] | |||||
} | |||||
group rawData by rawData.ServerName into server | |||||
select new | |||||
{ | |||||
ServerName = server.Key, | |||||
data = server.ToList() | |||||
}).ToDictionary(server => server.ServerName, server=> server.data); | |||||
RawStatistics = (from l in File.ReadAllLines(path).Skip(1) | |||||
let strings = l.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries) | |||||
let rawData = new RawStatisticsData | |||||
{ | |||||
Timestamp = ParseExactOrUnknown(strings[0]), | |||||
ServerName = strings[1], | |||||
ICMPStatus = strings[2], | |||||
RoundtripTime = int.Parse(strings[3]), | |||||
Geolocation = 5 > strings.Length ? | |||||
null | |||||
: strings[4], | |||||
ISP = 6 > strings.Length ? null : strings[5] | |||||
} | |||||
group rawData by rawData.ServerName into server | |||||
select new | |||||
{ | |||||
ServerName = server.Key, | |||||
data = server.ToList() | |||||
}).ToDictionary(server => server.ServerName, server => server.data); | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
@@ -300,7 +299,7 @@ namespace Shadowsocks.Controller | |||||
public string ICMPStatus; | public string ICMPStatus; | ||||
public int RoundtripTime; | public int RoundtripTime; | ||||
public string Geolocation; | public string Geolocation; | ||||
public string ISP ; | |||||
public string ISP; | |||||
} | } | ||||
public class StatisticsData | public class StatisticsData | ||||
@@ -310,6 +309,5 @@ namespace Shadowsocks.Controller | |||||
public int MinResponse; | public int MinResponse; | ||||
public int MaxResponse; | public int MaxResponse; | ||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,12 +1,12 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | |||||
using System.Net; | |||||
using System.IO; | using System.IO; | ||||
using System.Net; | |||||
using System.Text; | |||||
using Shadowsocks.Model; | |||||
using Shadowsocks.Properties; | using Shadowsocks.Properties; | ||||
using SimpleJson; | |||||
using Shadowsocks.Util; | using Shadowsocks.Util; | ||||
using Shadowsocks.Model; | |||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
@@ -38,13 +38,13 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
File.WriteAllText(Utils.GetTempPath() + "\\gfwlist.txt", e.Result, Encoding.UTF8); | |||||
File.WriteAllText(Utils.GetTempPath("gfwlist.txt"), e.Result, Encoding.UTF8); | |||||
List<string> lines = ParseResult(e.Result); | List<string> lines = ParseResult(e.Result); | ||||
if (File.Exists(USER_RULE_FILE)) | if (File.Exists(USER_RULE_FILE)) | ||||
{ | { | ||||
string local = File.ReadAllText(USER_RULE_FILE, Encoding.UTF8); | string local = File.ReadAllText(USER_RULE_FILE, Encoding.UTF8); | ||||
string[] rules = local.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); | string[] rules = local.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); | ||||
foreach(string rule in rules) | |||||
foreach (string rule in rules) | |||||
{ | { | ||||
if (rule.StartsWith("!") || rule.StartsWith("[")) | if (rule.StartsWith("!") || rule.StartsWith("[")) | ||||
continue; | continue; | ||||
@@ -146,8 +146,8 @@ Content-Type: application/x-ns-proxy-autoconfig | |||||
Content-Length: {0} | Content-Length: {0} | ||||
Connection: Close | Connection: Close | ||||
", System.Text.Encoding.UTF8.GetBytes(pac).Length) + pac; | |||||
byte[] response = System.Text.Encoding.UTF8.GetBytes(text); | |||||
", Encoding.UTF8.GetBytes(pac).Length) + pac; | |||||
byte[] response = Encoding.UTF8.GetBytes(text); | |||||
socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket); | socket.BeginSend(response, 0, response.Length, 0, new AsyncCallback(SendCallback), socket); | ||||
Util.Utils.ReleaseMemory(true); | Util.Utils.ReleaseMemory(true); | ||||
} | } | ||||
@@ -1,14 +1,14 @@ | |||||
using Shadowsocks.Model; | |||||
using Shadowsocks.Properties; | |||||
using System; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.IO; | using System.IO; | ||||
using System.IO.Compression; | |||||
using System.Text; | |||||
using System.Net.NetworkInformation; | |||||
using System.Net; | using System.Net; | ||||
using System.Net.NetworkInformation; | |||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Text; | |||||
using Shadowsocks.Model; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | using Shadowsocks.Util; | ||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
@@ -16,16 +16,14 @@ namespace Shadowsocks.Controller | |||||
class PolipoRunner | class PolipoRunner | ||||
{ | { | ||||
private Process _process; | private Process _process; | ||||
private static string temppath; | |||||
private int _runningPort; | private int _runningPort; | ||||
static PolipoRunner() | static PolipoRunner() | ||||
{ | { | ||||
temppath = Utils.GetTempPath(); | |||||
try | try | ||||
{ | { | ||||
FileManager.UncompressFile(temppath + "/ss_privoxy.exe", Resources.privoxy_exe); | |||||
FileManager.UncompressFile(temppath + "/mgwz.dll", Resources.mgwz_dll); | |||||
FileManager.UncompressFile(Utils.GetTempPath("ss_privoxy.exe"), Resources.privoxy_exe); | |||||
FileManager.UncompressFile(Utils.GetTempPath("mgwz.dll"), Resources.mgwz_dll); | |||||
} | } | ||||
catch (IOException e) | catch (IOException e) | ||||
{ | { | ||||
@@ -64,20 +62,16 @@ namespace Shadowsocks.Controller | |||||
polipoConfig = polipoConfig.Replace("__SOCKS_PORT__", configuration.localPort.ToString()); | polipoConfig = polipoConfig.Replace("__SOCKS_PORT__", configuration.localPort.ToString()); | ||||
polipoConfig = polipoConfig.Replace("__POLIPO_BIND_PORT__", _runningPort.ToString()); | polipoConfig = polipoConfig.Replace("__POLIPO_BIND_PORT__", _runningPort.ToString()); | ||||
polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); | polipoConfig = polipoConfig.Replace("__POLIPO_BIND_IP__", configuration.shareOverLan ? "0.0.0.0" : "127.0.0.1"); | ||||
FileManager.ByteArrayToFile(temppath + "/privoxy.conf", System.Text.Encoding.UTF8.GetBytes(polipoConfig)); | |||||
FileManager.ByteArrayToFile(Utils.GetTempPath("privoxy.conf"), Encoding.UTF8.GetBytes(polipoConfig)); | |||||
if (!(temppath.EndsWith("\\") || temppath.EndsWith("/"))) { | |||||
temppath = temppath + "\\"; | |||||
} | |||||
_process = new Process(); | _process = new Process(); | ||||
// Configure the process using the StartInfo properties. | // Configure the process using the StartInfo properties. | ||||
_process.StartInfo.FileName = temppath + "ss_privoxy.exe"; | |||||
_process.StartInfo.Arguments = " \"" + temppath + "privoxy.conf\""; | |||||
_process.StartInfo.FileName = "ss_privoxy.exe"; | |||||
_process.StartInfo.Arguments = "privoxy.conf"; | |||||
_process.StartInfo.WorkingDirectory = Utils.GetTempPath(); | |||||
_process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; | _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; | ||||
_process.StartInfo.UseShellExecute = true; | _process.StartInfo.UseShellExecute = true; | ||||
_process.StartInfo.CreateNoWindow = true; | _process.StartInfo.CreateNoWindow = true; | ||||
//_process.StartInfo.RedirectStandardOutput = true; | |||||
//_process.StartInfo.RedirectStandardError = true; | |||||
_process.Start(); | _process.Start(); | ||||
} | } | ||||
RefreshTrayArea(); | RefreshTrayArea(); | ||||
@@ -1,11 +1,8 @@ | |||||
using System; | using System; | ||||
using System.Collections; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Net; | using System.Net; | ||||
using System.Reflection; | |||||
using System.Text; | |||||
using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||
using System.IO; | |||||
using SimpleJson; | using SimpleJson; | ||||
using Shadowsocks.Model; | using Shadowsocks.Model; | ||||
@@ -129,8 +126,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
string temppath = Utils.GetTempPath(); | |||||
LatestVersionLocalName = Path.Combine(temppath, LatestVersionName); | |||||
LatestVersionLocalName = Utils.GetTempPath(LatestVersionName); | |||||
WebClient http = CreateWebClient(); | WebClient http = CreateWebClient(); | ||||
http.DownloadFileCompleted += Http_DownloadFileCompleted; | http.DownloadFileCompleted += Http_DownloadFileCompleted; | ||||
http.DownloadFileAsync(new Uri(LatestVersionURL), LatestVersionLocalName); | http.DownloadFileAsync(new Uri(LatestVersionURL), LatestVersionLocalName); | ||||
@@ -145,7 +141,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
if(e.Error != null) | |||||
if (e.Error != null) | |||||
{ | { | ||||
Logging.LogUsefulException(e.Error); | Logging.LogUsefulException(e.Error); | ||||
return; | return; | ||||
@@ -241,6 +237,5 @@ namespace Shadowsocks.Controller | |||||
return Asset.CompareVersion(x.version, y.version); | return Asset.CompareVersion(x.version, y.version); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } |
@@ -443,12 +443,12 @@ namespace Shadowsocks.Controller | |||||
private void pacServer_UserRuleFileChanged(object sender, EventArgs e) | private void pacServer_UserRuleFileChanged(object sender, EventArgs e) | ||||
{ | { | ||||
// TODO: this is a dirty hack. (from code GListUpdater.http_DownloadStringCompleted()) | // TODO: this is a dirty hack. (from code GListUpdater.http_DownloadStringCompleted()) | ||||
if (!File.Exists(Utils.GetTempPath() + "\\gfwlist.txt")) | |||||
if (!File.Exists(Utils.GetTempPath("gfwlist.txt"))) | |||||
{ | { | ||||
UpdatePACFromGFWList(); | UpdatePACFromGFWList(); | ||||
return; | return; | ||||
} | } | ||||
List<string> lines = GFWListUpdater.ParseResult(File.ReadAllText(Utils.GetTempPath() + "\\gfwlist.txt")); | |||||
List<string> lines = GFWListUpdater.ParseResult(File.ReadAllText(Utils.GetTempPath("gfwlist.txt"))); | |||||
if (File.Exists(PACServer.USER_RULE_FILE)) | if (File.Exists(PACServer.USER_RULE_FILE)) | ||||
{ | { | ||||
string local = File.ReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8); | string local = File.ReadAllText(PACServer.USER_RULE_FILE, Encoding.UTF8); | ||||
@@ -1,11 +1,10 @@ | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System; | |||||
using System.IO; | using System.IO; | ||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Text; | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
namespace Shadowsocks.Encryption | namespace Shadowsocks.Encryption | ||||
{ | { | ||||
@@ -15,8 +14,7 @@ namespace Shadowsocks.Encryption | |||||
static MbedTLS() | static MbedTLS() | ||||
{ | { | ||||
string tempPath = Utils.GetTempPath(); | |||||
string dllPath = tempPath + "/libsscrypto.dll"; | |||||
string dllPath = Utils.GetTempPath("libsscrypto.dll"); | |||||
try | try | ||||
{ | { | ||||
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); | FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); | ||||
@@ -59,10 +57,9 @@ namespace Shadowsocks.Encryption | |||||
public extern static void md5_starts(IntPtr ctx); | public extern static void md5_starts(IntPtr ctx); | ||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | ||||
public extern static void md5_update(IntPtr ctx, byte[] input, uint ilen ); | |||||
public extern static void md5_update(IntPtr ctx, byte[] input, uint ilen); | |||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | ||||
public extern static void md5_finish(IntPtr ctx, byte[] output); | public extern static void md5_finish(IntPtr ctx, byte[] output); | ||||
} | } | ||||
} | } |
@@ -1,11 +1,10 @@ | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System; | |||||
using System.IO; | using System.IO; | ||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Text; | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
namespace Shadowsocks.Encryption | namespace Shadowsocks.Encryption | ||||
{ | { | ||||
@@ -19,8 +18,7 @@ namespace Shadowsocks.Encryption | |||||
static PolarSSL() | static PolarSSL() | ||||
{ | { | ||||
string tempPath = Utils.GetTempPath(); | |||||
string dllPath = tempPath + "/libsscrypto.dll"; | |||||
string dllPath = Utils.GetTempPath("libsscrypto.dll"); | |||||
try | try | ||||
{ | { | ||||
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); | FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); | ||||
@@ -63,6 +61,5 @@ namespace Shadowsocks.Encryption | |||||
[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] | ||||
public extern static int arc4_crypt(IntPtr ctx, int length, byte[] input, byte[] output); | public extern static int arc4_crypt(IntPtr ctx, int length, byte[] input, byte[] output); | ||||
} | } | ||||
} | } |
@@ -1,11 +1,10 @@ | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System; | |||||
using System.IO; | using System.IO; | ||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Text; | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.Util; | |||||
namespace Shadowsocks.Encryption | namespace Shadowsocks.Encryption | ||||
{ | { | ||||
@@ -15,8 +14,7 @@ namespace Shadowsocks.Encryption | |||||
static Sodium() | static Sodium() | ||||
{ | { | ||||
string tempPath = Utils.GetTempPath(); | |||||
string dllPath = tempPath + "/libsscrypto.dll"; | |||||
string dllPath = Utils.GetTempPath("libsscrypto.dll"); | |||||
try | try | ||||
{ | { | ||||
FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); | FileManager.UncompressFile(dllPath, Resources.libsscrypto_dll); | ||||
@@ -47,7 +45,6 @@ namespace Shadowsocks.Encryption | |||||
public extern static void ss_sha1_hmac_ex(byte[] key, uint keylen, | public extern static void ss_sha1_hmac_ex(byte[] key, uint keylen, | ||||
byte[] input, int ioff, uint ilen, | byte[] input, int ioff, uint ilen, | ||||
byte[] output); | byte[] output); | ||||
} | } | ||||
} | } | ||||
@@ -1,13 +1,13 @@ | |||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Properties; | |||||
using Shadowsocks.View; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System; | |||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.IO; | using System.IO; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Windows.Forms; | using System.Windows.Forms; | ||||
using Shadowsocks.Controller; | |||||
using Shadowsocks.Util; | |||||
using Shadowsocks.View; | |||||
namespace Shadowsocks | namespace Shadowsocks | ||||
{ | { | ||||
static class Program | static class Program | ||||
@@ -18,7 +18,7 @@ namespace Shadowsocks | |||||
[STAThread] | [STAThread] | ||||
static void Main() | static void Main() | ||||
{ | { | ||||
Util.Utils.ReleaseMemory(true); | |||||
Utils.ReleaseMemory(true); | |||||
using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode())) | using (Mutex mutex = new Mutex(false, "Global\\Shadowsocks_" + Application.StartupPath.GetHashCode())) | ||||
{ | { | ||||
Application.EnableVisualStyles(); | Application.EnableVisualStyles(); | ||||
@@ -37,15 +37,19 @@ namespace Shadowsocks | |||||
return; | return; | ||||
} | } | ||||
Directory.SetCurrentDirectory(Application.StartupPath); | Directory.SetCurrentDirectory(Application.StartupPath); | ||||
#if DEBUG | |||||
Logging.OpenLogFile(); | Logging.OpenLogFile(); | ||||
// truncate privoxy log file while debugging | |||||
string privoxyLogFilename = Utils.GetTempPath("privoxy.log"); | |||||
if (File.Exists(privoxyLogFilename)) | |||||
using (new FileStream(privoxyLogFilename, FileMode.Truncate)) { } | |||||
#else | |||||
Logging.OpenLogFile(); | |||||
#endif | |||||
ShadowsocksController controller = new ShadowsocksController(); | ShadowsocksController controller = new ShadowsocksController(); | ||||
MenuViewController viewController = new MenuViewController(controller); | MenuViewController viewController = new MenuViewController(controller); | ||||
controller.Start(); | controller.Start(); | ||||
Application.Run(); | Application.Run(); | ||||
} | } | ||||
} | } | ||||
@@ -11,23 +11,38 @@ namespace Shadowsocks.Util | |||||
{ | { | ||||
public class Utils | public class Utils | ||||
{ | { | ||||
private static string TempPath = null; | |||||
// return path to store temporary files | // return path to store temporary files | ||||
public static string GetTempPath() | public static string GetTempPath() | ||||
{ | { | ||||
if (File.Exists(Application.StartupPath + "\\shadowsocks_portable_mode.txt")) | |||||
if (TempPath == null) | |||||
{ | { | ||||
try | |||||
{ | |||||
Directory.CreateDirectory(Application.StartupPath + "\\temp"); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Logging.LogUsefulException(e); | |||||
} | |||||
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log | |||||
return Application.StartupPath + "\\temp"; | |||||
if (File.Exists(Path.Combine(Application.StartupPath, "shadowsocks_portable_mode.txt"))) | |||||
try | |||||
{ | |||||
Directory.CreateDirectory(Path.Combine(Application.StartupPath, "temp")); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
TempPath = Path.GetTempPath(); | |||||
Logging.LogUsefulException(e); | |||||
} | |||||
finally | |||||
{ | |||||
// don't use "/", it will fail when we call explorer /select xxx/temp\xxx.log | |||||
TempPath = Path.Combine(Application.StartupPath, "temp"); | |||||
} | |||||
else | |||||
TempPath = Path.GetTempPath(); | |||||
} | } | ||||
return Path.GetTempPath(); | |||||
return TempPath; | |||||
} | |||||
// return a full path with filename combined which pointed to the temporary directory | |||||
public static string GetTempPath(string filename) | |||||
{ | |||||
return Path.Combine(GetTempPath(), filename); | |||||
} | } | ||||
public static void ReleaseMemory(bool removePages) | public static void ReleaseMemory(bool removePages) | ||||