diff --git a/shadowsocks-csharp/Data/mgwz.dll.gz b/shadowsocks-csharp/Data/mgwz.dll.gz
new file mode 100644
index 00000000..139725f3
Binary files /dev/null and b/shadowsocks-csharp/Data/mgwz.dll.gz differ
diff --git a/shadowsocks-csharp/Data/polipo.exe.gz b/shadowsocks-csharp/Data/polipo.exe.gz
deleted file mode 100755
index c7038e12..00000000
Binary files a/shadowsocks-csharp/Data/polipo.exe.gz and /dev/null differ
diff --git a/shadowsocks-csharp/Data/polipo_config.txt b/shadowsocks-csharp/Data/polipo_config.txt
deleted file mode 100755
index fabeab66..00000000
--- a/shadowsocks-csharp/Data/polipo_config.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-proxyAddress = "__POLIPO_BIND_IP__"
-proxyPort = 8123
-
-socksParentProxy = "127.0.0.1:__SOCKS_PORT__"
-socksProxyType = socks5
-diskCacheRoot = ""
-localDocumentRoot = ""
-
-allowedPorts = 1-65535
-tunnelAllowedPorts = 1-65535
\ No newline at end of file
diff --git a/shadowsocks-csharp/Data/privoxy.exe.gz b/shadowsocks-csharp/Data/privoxy.exe.gz
new file mode 100644
index 00000000..36f7d360
Binary files /dev/null and b/shadowsocks-csharp/Data/privoxy.exe.gz differ
diff --git a/shadowsocks-csharp/Data/privoxy_conf.txt b/shadowsocks-csharp/Data/privoxy_conf.txt
new file mode 100644
index 00000000..8a821739
--- /dev/null
+++ b/shadowsocks-csharp/Data/privoxy_conf.txt
@@ -0,0 +1,5 @@
+listen-address __POLIPO_BIND_IP__:__POLIPO_BIND_PORT__
+show-on-task-bar 0
+activity-animation 0
+forward-socks5 / 127.0.0.1:__SOCKS_PORT__ .
+hide-console
diff --git a/shadowsocks-csharp/View/ServerLogForm.Designer.cs b/shadowsocks-csharp/View/ServerLogForm.Designer.cs
new file mode 100644
index 00000000..cb6f9729
--- /dev/null
+++ b/shadowsocks-csharp/View/ServerLogForm.Designer.cs
@@ -0,0 +1,282 @@
+namespace Shadowsocks.View
+{
+ partial class ServerLogForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.ServerDataGrid = new System.Windows.Forms.DataGridView();
+ this.timer = new System.Windows.Forms.Timer(this.components);
+ this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
+ this.ID = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Server = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Enable = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.TotalConnect = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Connecting = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.AvgLatency = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.AvgSpeed = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.MaxSpeed = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Upload = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Download = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ErrorPercent = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ConnectError = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ConnectTimeout = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.ConnectNoData = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this.Continuous = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ ((System.ComponentModel.ISupportInitialize)(this.ServerDataGrid)).BeginInit();
+ this.tableLayoutPanel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // ServerDataGrid
+ //
+ this.ServerDataGrid.AllowUserToAddRows = false;
+ this.ServerDataGrid.AllowUserToDeleteRows = false;
+ this.ServerDataGrid.AllowUserToResizeRows = false;
+ this.ServerDataGrid.BorderStyle = System.Windows.Forms.BorderStyle.None;
+ this.ServerDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this.ServerDataGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+ this.ID,
+ this.Server,
+ this.Enable,
+ this.TotalConnect,
+ this.Connecting,
+ this.AvgLatency,
+ this.AvgSpeed,
+ this.MaxSpeed,
+ this.Upload,
+ this.Download,
+ this.ErrorPercent,
+ this.ConnectError,
+ this.ConnectTimeout,
+ this.ConnectNoData,
+ this.Continuous});
+ this.ServerDataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.ServerDataGrid.Location = new System.Drawing.Point(0, 0);
+ this.ServerDataGrid.Margin = new System.Windows.Forms.Padding(0);
+ this.ServerDataGrid.MinimumSize = new System.Drawing.Size(1, 1);
+ this.ServerDataGrid.MultiSelect = false;
+ this.ServerDataGrid.Name = "ServerDataGrid";
+ this.ServerDataGrid.ReadOnly = true;
+ this.ServerDataGrid.RowHeadersVisible = false;
+ this.ServerDataGrid.RowTemplate.Height = 23;
+ this.ServerDataGrid.Size = new System.Drawing.Size(117, 48);
+ this.ServerDataGrid.TabIndex = 0;
+ this.ServerDataGrid.CellClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.ServerDataGrid_CellClick);
+ this.ServerDataGrid.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.ServerDataGrid_CellDoubleClick);
+ this.ServerDataGrid.SortCompare += new System.Windows.Forms.DataGridViewSortCompareEventHandler(this.ServerDataGrid_SortCompare);
+ this.ServerDataGrid.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ServerDataGrid_MouseUp);
+ //
+ // timer
+ //
+ this.timer.Enabled = true;
+ this.timer.Interval = 250;
+ this.timer.Tick += new System.EventHandler(this.timer_Tick);
+ //
+ // tableLayoutPanel1
+ //
+ this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.tableLayoutPanel1.ColumnCount = 1;
+ this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ this.tableLayoutPanel1.Controls.Add(this.ServerDataGrid, 0, 0);
+ this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel1.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
+ this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
+ this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
+ this.tableLayoutPanel1.Name = "tableLayoutPanel1";
+ this.tableLayoutPanel1.RowCount = 1;
+ this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel1.Size = new System.Drawing.Size(116, 48);
+ this.tableLayoutPanel1.TabIndex = 1;
+ //
+ // ID
+ //
+ this.ID.HeaderText = "ID";
+ this.ID.MinimumWidth = 2;
+ this.ID.Name = "ID";
+ this.ID.ReadOnly = true;
+ this.ID.Width = 28;
+ //
+ // Server
+ //
+ this.Server.HeaderText = "Server";
+ this.Server.MinimumWidth = 2;
+ this.Server.Name = "Server";
+ this.Server.ReadOnly = true;
+ this.Server.Width = 200;
+ //
+ // Enable
+ //
+ this.Enable.HeaderText = "Enable";
+ this.Enable.MinimumWidth = 2;
+ this.Enable.Name = "Enable";
+ this.Enable.ReadOnly = true;
+ this.Enable.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.Enable.Width = 28;
+ //
+ // TotalConnect
+ //
+ this.TotalConnect.HeaderText = "Total Connect";
+ this.TotalConnect.MinimumWidth = 2;
+ this.TotalConnect.Name = "TotalConnect";
+ this.TotalConnect.ReadOnly = true;
+ this.TotalConnect.Visible = false;
+ this.TotalConnect.Width = 48;
+ //
+ // Connecting
+ //
+ this.Connecting.HeaderText = "Connecting";
+ this.Connecting.MinimumWidth = 2;
+ this.Connecting.Name = "Connecting";
+ this.Connecting.ReadOnly = true;
+ this.Connecting.Width = 28;
+ //
+ // AvgLatency
+ //
+ this.AvgLatency.HeaderText = "Latency";
+ this.AvgLatency.MinimumWidth = 2;
+ this.AvgLatency.Name = "AvgLatency";
+ this.AvgLatency.ReadOnly = true;
+ this.AvgLatency.Width = 48;
+ //
+ // AvgSpeed
+ //
+ this.AvgSpeed.HeaderText = "Avg Speed";
+ this.AvgSpeed.MinimumWidth = 2;
+ this.AvgSpeed.Name = "AvgSpeed";
+ this.AvgSpeed.ReadOnly = true;
+ this.AvgSpeed.Width = 72;
+ //
+ // MaxSpeed
+ //
+ this.MaxSpeed.HeaderText = "Max Speed";
+ this.MaxSpeed.MinimumWidth = 2;
+ this.MaxSpeed.Name = "MaxSpeed";
+ this.MaxSpeed.ReadOnly = true;
+ this.MaxSpeed.Width = 72;
+ //
+ // Upload
+ //
+ this.Upload.HeaderText = "Upload";
+ this.Upload.MinimumWidth = 2;
+ this.Upload.Name = "Upload";
+ this.Upload.ReadOnly = true;
+ this.Upload.Width = 72;
+ //
+ // Download
+ //
+ this.Download.HeaderText = "Download";
+ this.Download.MinimumWidth = 2;
+ this.Download.Name = "Download";
+ this.Download.ReadOnly = true;
+ this.Download.Width = 72;
+ //
+ // ErrorPercent
+ //
+ this.ErrorPercent.HeaderText = "Error Percent";
+ this.ErrorPercent.MinimumWidth = 2;
+ this.ErrorPercent.Name = "ErrorPercent";
+ this.ErrorPercent.ReadOnly = true;
+ this.ErrorPercent.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.ErrorPercent.Width = 60;
+ //
+ // ConnectError
+ //
+ this.ConnectError.HeaderText = "Error";
+ this.ConnectError.MinimumWidth = 2;
+ this.ConnectError.Name = "ConnectError";
+ this.ConnectError.ReadOnly = true;
+ this.ConnectError.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.ConnectError.Visible = false;
+ this.ConnectError.Width = 28;
+ //
+ // ConnectTimeout
+ //
+ this.ConnectTimeout.HeaderText = "Timeout";
+ this.ConnectTimeout.MinimumWidth = 2;
+ this.ConnectTimeout.Name = "ConnectTimeout";
+ this.ConnectTimeout.ReadOnly = true;
+ this.ConnectTimeout.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.ConnectTimeout.Visible = false;
+ this.ConnectTimeout.Width = 28;
+ //
+ // ConnectNoData
+ //
+ this.ConnectNoData.HeaderText = "NoData";
+ this.ConnectNoData.MinimumWidth = 2;
+ this.ConnectNoData.Name = "ConnectNoData";
+ this.ConnectNoData.ReadOnly = true;
+ this.ConnectNoData.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
+ this.ConnectNoData.Visible = false;
+ this.ConnectNoData.Width = 28;
+ //
+ // Continuous
+ //
+ this.Continuous.HeaderText = "Continuous";
+ this.Continuous.Name = "Continuous";
+ this.Continuous.ReadOnly = true;
+ this.Continuous.Width = 28;
+ //
+ // ServerLogForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(116, 48);
+ this.Controls.Add(this.tableLayoutPanel1);
+ this.Font = new System.Drawing.Font("NSimSun", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2);
+ this.Name = "ServerLogForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "ServerLog";
+ this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ServerLogForm_FormClosed);
+ ((System.ComponentModel.ISupportInitialize)(this.ServerDataGrid)).EndInit();
+ this.tableLayoutPanel1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.DataGridView ServerDataGrid;
+ private System.Windows.Forms.Timer timer;
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ID;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Server;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Enable;
+ private System.Windows.Forms.DataGridViewTextBoxColumn TotalConnect;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Connecting;
+ private System.Windows.Forms.DataGridViewTextBoxColumn AvgLatency;
+ private System.Windows.Forms.DataGridViewTextBoxColumn AvgSpeed;
+ private System.Windows.Forms.DataGridViewTextBoxColumn MaxSpeed;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Upload;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Download;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ErrorPercent;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ConnectError;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ConnectTimeout;
+ private System.Windows.Forms.DataGridViewTextBoxColumn ConnectNoData;
+ private System.Windows.Forms.DataGridViewTextBoxColumn Continuous;
+ }
+}
\ No newline at end of file
diff --git a/shadowsocks-csharp/View/ServerLogForm.cs b/shadowsocks-csharp/View/ServerLogForm.cs
new file mode 100644
index 00000000..b99f42d4
--- /dev/null
+++ b/shadowsocks-csharp/View/ServerLogForm.cs
@@ -0,0 +1,616 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using Shadowsocks.Controller;
+using Shadowsocks.Model;
+using Shadowsocks.Properties;
+using System.Threading;
+
+namespace Shadowsocks.View
+{
+ public partial class ServerLogForm : Form
+ {
+ private ShadowsocksController controller;
+ private ContextMenu contextMenu1;
+ private MenuItem clearItem;
+ private List listOrder = new List();
+ private int lastRefreshIndex = 0;
+ private bool rowChange = false;
+ private ServerSpeedLogShow[] ServerSpeedLogList;
+ private Thread workerThread;
+
+ public ServerLogForm(ShadowsocksController controller)
+ {
+ this.controller = controller;
+ this.Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
+ InitializeComponent();
+ this.Width = 760;
+
+ Configuration config = controller.GetCurrentConfiguration();
+ if (config.configs.Count < 8)
+ {
+ this.Height = 300;
+ }
+ else if (config.configs.Count < 20)
+ {
+ this.Height = 300 + (config.configs.Count - 8) * 16;
+ }
+ else
+ {
+ this.Height = 500;
+ }
+ UpdateTexts();
+ UpdateLog();
+
+ this.contextMenu1 = new ContextMenu(new MenuItem[] {
+ this.clearItem = CreateMenuItem("&Clear", new EventHandler(this.ClearItem_Click)),
+ });
+ ServerDataGrid.ContextMenu = contextMenu1;
+ controller.ConfigChanged += controller_ConfigChanged;
+ }
+
+ private MenuItem CreateMenuItem(string text, EventHandler click)
+ {
+ return new MenuItem(I18N.GetString(text), click);
+ }
+
+ private void UpdateTitle()
+ {
+ this.Text = I18N.GetString("ServerLog") + "("
+ + (controller.GetCurrentConfiguration().shareOverLan ? "any" : "local") + ":" + controller.GetCurrentConfiguration().localPort.ToString()
+ + I18N.GetString(" Version") + UpdateChecker.Version
+ + ")";
+ }
+ private void UpdateTexts()
+ {
+ UpdateTitle();
+ for (int i = 0; i < ServerDataGrid.Columns.Count; ++i)
+ {
+ ServerDataGrid.Columns[i].HeaderText = I18N.GetString(ServerDataGrid.Columns[i].HeaderText);
+ }
+ }
+
+ private void controller_ConfigChanged(object sender, EventArgs e)
+ {
+ UpdateTitle();
+ }
+
+ private string FormatBytes(long bytes)
+ {
+ const long K = 1024L;
+ const long M = K * 1024L;
+ const long G = M * 1024L;
+ const long T = G * 1024L;
+ const long P = T * 1024L;
+ const long E = P * 1024L;
+
+ if (bytes >= E * 2)
+ return (bytes / (double)E).ToString("F5") + "E";
+ if (bytes >= P * 2)
+ return (bytes / (double)P).ToString("F5") + "P";
+ if (bytes >= T * 2)
+ return (bytes / (double)T).ToString("F5") + "T";
+ if (bytes >= G * 2)
+ {
+ return (bytes / (double)G).ToString("F4") + "G";
+ }
+ if (bytes >= K * 990)
+ {
+ return (bytes / (double)M).ToString("F4") + "M";
+ }
+ if (bytes > K * 2)
+ {
+ return (bytes / (double)K).ToString("F3") + "K";
+ }
+ return bytes.ToString();
+ }
+
+ public bool SetBackColor(DataGridViewCell cell, Color newColor)
+ {
+ if (cell.Style.BackColor != newColor)
+ {
+ cell.Style.BackColor = newColor;
+ rowChange = true;
+ return true;
+ }
+ return false;
+ }
+ public bool SetCellText(DataGridViewCell cell, string newString)
+ {
+ if ((string)cell.Value != newString)
+ {
+ cell.Value = newString;
+ rowChange = true;
+ return true;
+ }
+ return false;
+ }
+ public bool SetCellText(DataGridViewCell cell, long newInteger)
+ {
+ if ((string)cell.Value != newInteger.ToString())
+ {
+ cell.Value = newInteger.ToString();
+ rowChange = true;
+ return true;
+ }
+ return false;
+ }
+ byte ColorMix(byte a, byte b, double alpha)
+ {
+ return (byte)(b * alpha + a * (1 - alpha));
+ }
+ Color ColorMix(Color a, Color b, double alpha)
+ {
+ return Color.FromArgb(ColorMix(a.R, b.R, alpha),
+ ColorMix(a.G, b.G, alpha),
+ ColorMix(a.B, b.B, alpha));
+ }
+ public void UpdateLogThread()
+ {
+ while (workerThread != null)
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ ServerSpeedLogShow[] _ServerSpeedLogList = new ServerSpeedLogShow[config.configs.Count];
+ for (int i = 0; i < config.configs.Count; ++i)
+ {
+ _ServerSpeedLogList[i] = config.configs[i].ServerSpeedLog().Translate();
+ }
+ ServerSpeedLogList = _ServerSpeedLogList;
+
+ workerThread.Suspend();
+ }
+ }
+ public void UpdateLog()
+ {
+ if (workerThread == null)
+ {
+ workerThread = new Thread(this.UpdateLogThread);
+ workerThread.Start();
+ }
+ else
+ {
+ try
+ {
+ workerThread.Resume();
+ }
+ catch
+ {
+
+ }
+ }
+ }
+ public void RefreshLog()
+ {
+ if (ServerSpeedLogList == null)
+ return;
+
+ Configuration config = controller.GetCurrentConfiguration();
+ if (listOrder.Count > config.configs.Count)
+ {
+ listOrder.RemoveRange(config.configs.Count, listOrder.Count - config.configs.Count);
+ }
+ while (listOrder.Count < config.configs.Count)
+ {
+ listOrder.Add(0);
+ }
+ while (ServerDataGrid.Rows.Count < config.configs.Count)
+ {
+ ServerDataGrid.Rows.Add();
+ int id = ServerDataGrid.Rows.Count - 1;
+ ServerDataGrid[0, id].Value = id;
+ }
+ if (ServerDataGrid.Rows.Count > config.configs.Count)
+ {
+ for (int list_index = 0; list_index < ServerDataGrid.Rows.Count; ++list_index)
+ {
+ DataGridViewCell id_cell = ServerDataGrid[0, list_index];
+ int id = (int)id_cell.Value;
+ if (id >= config.configs.Count)
+ {
+ ServerDataGrid.Rows.RemoveAt(list_index);
+ --list_index;
+ }
+ }
+ }
+ //int index = 0;
+ //foreach (Server server in config.configs)
+ //for ( int id = 0; id < config.configs.Count; ++id)
+ try
+ {
+ for (int list_index = (lastRefreshIndex >= ServerDataGrid.Rows.Count) ? 0 : lastRefreshIndex, rowChangeCnt = 0;
+ list_index < ServerDataGrid.Rows.Count && rowChangeCnt <= 200;
+ ++list_index, ++rowChangeCnt)
+ {
+ lastRefreshIndex = list_index + 1;
+ DataGridViewCell id_cell = ServerDataGrid[0, list_index];
+ int id = (int)id_cell.Value;
+ Server server = config.configs[id];
+ ServerSpeedLogShow serverSpeedLog = ServerSpeedLogList[id];
+ const byte colAdd = 2;
+ listOrder[id] = list_index;
+ rowChange = false;
+ for (int curcol = 0; curcol < ServerDataGrid.Columns.Count; ++curcol)
+ {
+ DataGridViewCell cell = ServerDataGrid[curcol, list_index];
+ string columnName = ServerDataGrid.Columns[curcol].Name;
+ // Server
+ if (columnName == "Server")
+ {
+ if (config.index == id)
+ SetBackColor(cell, Color.Cyan);
+ else
+ SetBackColor(cell, Color.White);
+ SetCellText(cell, server.FriendlyName());
+ }
+ // Enable
+ if (columnName == "Enable")
+ {
+ if (server.isEnable())
+ SetBackColor(cell, Color.White);
+ else
+ SetBackColor(cell, Color.Red);
+ }
+ // TotalConnectTimes
+ else if (columnName == "TotalConnect")
+ {
+ SetCellText(cell, serverSpeedLog.totalConnectTimes);
+ }
+ // TotalConnecting
+ else if (columnName == "Connecting")
+ {
+ SetCellText(cell, server.GetConnections().Count);
+ //SetCellText(cell, serverSpeedLog.totalConnectTimes - serverSpeedLog.totalDisconnectTimes);
+ }
+ // AvgConnectTime
+ else if (columnName == "AvgLatency")
+ {
+ if (serverSpeedLog.avgConnectTime >= 0)
+ SetCellText(cell, serverSpeedLog.avgConnectTime);
+ else
+ SetCellText(cell, "-");
+ }
+ // AvgSpeed
+ else if (columnName == "AvgSpeed")
+ {
+ long avgBytes = serverSpeedLog.avgDownloadBytes;
+ string valStr = FormatBytes(avgBytes);
+ Color[] colList = new Color[6] { Color.White, Color.LightGreen, Color.Yellow, Color.Pink, Color.Red, Color.Red };
+ long[] bytesList = new long[6] { 0, 1024 * 64, 1024 * 512, 1024 * 1024 * 4, 1024 * 1024 * 16, 1024 * 1024 * 1024 };
+ for (int i = 1; i < colList.Length; ++i)
+ {
+ if (avgBytes < bytesList[i])
+ {
+ SetBackColor(cell,
+ ColorMix(colList[i - 1],
+ colList[i],
+ (double)(avgBytes - bytesList[i - 1]) / (bytesList[i] - bytesList[i - 1])
+ )
+ );
+ break;
+ }
+ }
+ SetCellText(cell, valStr);
+ }
+ // MaxSpeed
+ else if (columnName == "MaxSpeed")
+ {
+ long maxBytes = serverSpeedLog.maxDownloadBytes;
+ string valStr = FormatBytes(maxBytes);
+ Color[] colList = new Color[6] { Color.White, Color.LightGreen, Color.Yellow, Color.Pink, Color.Red, Color.Red };
+ long[] bytesList = new long[6] { 0, 1024 * 64, 1024 * 512, 1024 * 1024 * 4, 1024 * 1024 * 16, 1024 * 1024 * 1024 };
+ for (int i = 1; i < colList.Length; ++i)
+ {
+ if (maxBytes < bytesList[i])
+ {
+ SetBackColor(cell,
+ ColorMix(colList[i - 1],
+ colList[i],
+ (double)(maxBytes - bytesList[i - 1]) / (bytesList[i] - bytesList[i - 1])
+ )
+ );
+ break;
+ }
+ }
+ SetCellText(cell, valStr);
+ }
+ // TotalUploadBytes
+ else if (columnName == "Upload")
+ {
+ string valStr = FormatBytes(serverSpeedLog.totalUploadBytes);
+ if ((string)cell.Value != valStr)
+ {
+ if (valStr == "0")
+ SetBackColor(cell, Color.White);
+ else
+ {
+ SetBackColor(cell, Color.LightGreen);
+ cell.Tag = 8;
+ }
+ }
+ else if (cell.Tag != null)
+ {
+ cell.Tag = (int)cell.Tag - 1;
+ if ((int)cell.Tag == 0) SetBackColor(cell, Color.White);
+ //Color col = cell.Style.BackColor;
+ //SetBackColor(cell, Color.FromArgb(Math.Min(255, col.R + colAdd), Math.Min(255, col.G + colAdd), Math.Min(255, col.B + colAdd)));
+ }
+ SetCellText(cell, valStr);
+ }
+ // TotalDownloadBytes
+ else if (columnName == "Download")
+ {
+ string valStr = FormatBytes(serverSpeedLog.totalDownloadBytes);
+ if ((string)cell.Value != valStr)
+ {
+ if (valStr == "0")
+ SetBackColor(cell, Color.White);
+ else
+ {
+ SetBackColor(cell, Color.LightGreen);
+ cell.Tag = 8;
+ }
+ }
+ else if (cell.Tag != null)
+ {
+ cell.Tag = (int)cell.Tag - 1;
+ if ((int)cell.Tag == 0) SetBackColor(cell, Color.White);
+ //Color col = cell.Style.BackColor;
+ //SetBackColor(cell, Color.FromArgb(Math.Min(255, col.R + colAdd), Math.Min(255, col.G + colAdd), Math.Min(255, col.B + colAdd)));
+ }
+ SetCellText(cell, valStr);
+ }
+ // ErrorConnectTimes
+ else if (columnName == "ConnectError")
+ {
+ SetCellText(cell, serverSpeedLog.errorConnectTimes);
+ }
+ // ErrorTimeoutTimes
+ else if (columnName == "ConnectTimeout")
+ {
+ SetCellText(cell, serverSpeedLog.errorTimeoutTimes);
+ }
+ // ErrorTimeoutTimes
+ else if (columnName == "ConnectNoData")
+ {
+ long val = serverSpeedLog.errorNoDataTimes;
+ Color col = Color.FromArgb(255, (byte)Math.Max(0, 255 - val * 8), (byte)Math.Max(0, 255 - val * 8));
+ SetBackColor(cell, col);
+ SetCellText(cell, val);
+ }
+ // ErrorTimeoutTimes
+ else if (columnName == "Continuous")
+ {
+ long val = serverSpeedLog.errorContinurousTimes;
+ Color col = Color.FromArgb(255, (byte)Math.Max(0, 255 - val * 8), (byte)Math.Max(0, 255 - val * 8));
+ SetBackColor(cell, col);
+ SetCellText(cell, val);
+ }
+ // ErrorPersent
+ else if (columnName == "ErrorPercent")
+ {
+ if (serverSpeedLog.totalConnectTimes > 0)
+ {
+ double percent = (serverSpeedLog.errorConnectTimes
+ + serverSpeedLog.errorTimeoutTimes
+ + serverSpeedLog.errorNoDataTimes)
+ * 100.00 / serverSpeedLog.totalConnectTimes;
+ SetBackColor(cell, Color.FromArgb(255, (byte)(255 - percent * 2), (byte)(255 - percent * 2)));
+ if (percent < 1e-4)
+ SetCellText(cell, percent.ToString("F0") + "%");
+ else
+ SetCellText(cell, percent.ToString("F2") + "%");
+ }
+ else
+ {
+ SetBackColor(cell, Color.White);
+ SetCellText(cell, "-");
+ }
+ }
+ if (columnName == "Server")
+ {
+ if (cell.Style.Alignment != DataGridViewContentAlignment.MiddleLeft)
+ cell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft;
+ }
+ else
+ {
+ if (cell.Style.Alignment != DataGridViewContentAlignment.MiddleRight)
+ cell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
+ }
+ }
+ if (rowChange)
+ rowChangeCnt++;
+ }
+ }
+ catch
+ {
+
+ }
+ if (ServerDataGrid.SortedColumn != null)
+ {
+ ServerDataGrid.Sort(ServerDataGrid.SortedColumn, (ListSortDirection)((int)ServerDataGrid.SortOrder - 1));
+ }
+ }
+
+ private void ClearItem_Click(object sender, EventArgs e)
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ foreach (Server server in config.configs)
+ {
+ server.ServerSpeedLog().Clear();
+ }
+ }
+
+ private void timer_Tick(object sender, EventArgs e)
+ {
+ RefreshLog();
+ UpdateLog();
+ }
+
+ private void ServerDataGrid_MouseUp(object sender, MouseEventArgs e)
+ {
+ if (e.Button == MouseButtons.Right)
+ {
+ contextMenu1.Show(ServerDataGrid, new Point(e.X, e.Y));
+ }
+ }
+
+ private void ServerDataGrid_CellClick(object sender, DataGridViewCellEventArgs e)
+ {
+ if (e.RowIndex >= 0)
+ {
+ int id = (int)ServerDataGrid[0, e.RowIndex].Value;
+ if (ServerDataGrid.Columns[e.ColumnIndex].Name == "Server")
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ controller.SelectServerIndex(id);
+ }
+ if (ServerDataGrid.Columns[e.ColumnIndex].Name == "Enable")
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ Server server = config.configs[id];
+ server.setEnable(!server.isEnable());
+ }
+ ServerDataGrid[0, e.RowIndex].Selected = true;
+ }
+ }
+
+ private void ServerDataGrid_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
+ {
+ if (e.RowIndex >= 0)
+ {
+ int id = (int)ServerDataGrid[0, e.RowIndex].Value;
+ if (ServerDataGrid.Columns[e.ColumnIndex].Name == "Server")
+ {
+ controller.ShowConfigForm();
+ }
+ if (ServerDataGrid.Columns[e.ColumnIndex].Name == "Connecting")
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ Server server = config.configs[id];
+ server.GetConnections().CloseAll();
+ }
+ if (ServerDataGrid.Columns[e.ColumnIndex].Name == "ErrorPercent")
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ config.configs[id].ServerSpeedLog().Clear();
+ config.configs[id].setEnable(true);
+ }
+ if (ServerDataGrid.Columns[e.ColumnIndex].Name == "ConnectError"
+ || ServerDataGrid.Columns[e.ColumnIndex].Name == "ConnectTimeout"
+ || ServerDataGrid.Columns[e.ColumnIndex].Name == "ConnectNoData"
+ || ServerDataGrid.Columns[e.ColumnIndex].Name == "Continuous"
+ )
+ {
+ Configuration config = controller.GetCurrentConfiguration();
+ config.configs[id].ServerSpeedLog().ClearError();
+ config.configs[id].setEnable(true);
+ }
+ ServerDataGrid[0, e.RowIndex].Selected = true;
+ }
+ }
+
+ private void ServerLogForm_FormClosed(object sender, FormClosedEventArgs e)
+ {
+ controller.ConfigChanged -= controller_ConfigChanged;
+ Thread thread = workerThread;
+ workerThread = null;
+ thread.Resume();
+ }
+
+ private long Str2Long(String str)
+ {
+ if (str == "-") return -1;
+ if (str.LastIndexOf('K') > 0)
+ {
+ Double ret = Convert.ToDouble(str.Substring(0, str.LastIndexOf('K')));
+ return (long)(ret * 1024);
+ }
+ if (str.LastIndexOf('M') > 0)
+ {
+ Double ret = Convert.ToDouble(str.Substring(0, str.LastIndexOf('M')));
+ return (long)(ret * 1024 * 1024);
+ }
+ if (str.LastIndexOf('G') > 0)
+ {
+ Double ret = Convert.ToDouble(str.Substring(0, str.LastIndexOf('G')));
+ return (long)(ret * 1024 * 1024 * 1024);
+ }
+ if (str.LastIndexOf('T') > 0)
+ {
+ Double ret = Convert.ToDouble(str.Substring(0, str.LastIndexOf('T')));
+ return (long)(ret * 1024 * 1024 * 1024 * 1024);
+ }
+ try
+ {
+ Double ret = Convert.ToDouble(str);
+ return (long)ret;
+ }
+ catch
+ {
+ return -1;
+ }
+ }
+
+ private void ServerDataGrid_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
+ {
+ //e.SortResult = 0;
+ if (e.Column.Name == "Server")
+ {
+ e.SortResult = System.String.Compare(Convert.ToString(e.CellValue1), Convert.ToString(e.CellValue2));
+ e.Handled = true;
+ }
+ else if (e.Column.Name == "ID"
+ || e.Column.Name == "TotalConnect"
+ || e.Column.Name == "Connecting"
+ || e.Column.Name == "ConnectError"
+ || e.Column.Name == "ConnectTimeout"
+ || e.Column.Name == "ConnectNoData"
+ || e.Column.Name == "Continuous"
+ )
+ {
+ Int32 v1 = Convert.ToInt32(e.CellValue1);
+ Int32 v2 = Convert.ToInt32(e.CellValue2);
+ e.SortResult = (v1 == v2 ? 0 : (v1 < v2 ? -1 : 1));
+ }
+ else if (e.Column.Name == "ErrorPercent")
+ {
+ String s1 = Convert.ToString(e.CellValue1);
+ String s2 = Convert.ToString(e.CellValue2);
+ Int32 v1 = s1.Length <= 1 ? 0 : Convert.ToInt32(Convert.ToDouble(s1.Substring(0, s1.Length - 1)) * 100);
+ Int32 v2 = s2.Length <= 1 ? 0 : Convert.ToInt32(Convert.ToDouble(s2.Substring(0, s2.Length - 1)) * 100);
+ e.SortResult = v1 == v2 ? 0 : v1 < v2 ? -1 : 1;
+ }
+ else if (e.Column.Name == "AvgLatency"
+ || e.Column.Name == "AvgSpeed"
+ || e.Column.Name == "MaxSpeed"
+ || e.Column.Name == "Upload"
+ || e.Column.Name == "Download"
+ )
+ {
+ String s1 = Convert.ToString(e.CellValue1);
+ String s2 = Convert.ToString(e.CellValue2);
+ long v1 = Str2Long(s1);
+ long v2 = Str2Long(s2);
+ e.SortResult = (v1 == v2 ? 0 : (v1 < v2 ? -1 : 1));
+ }
+ if (e.SortResult == 0)
+ {
+ int v1 = listOrder[Convert.ToInt32(ServerDataGrid[0, e.RowIndex1].Value)];
+ int v2 = listOrder[Convert.ToInt32(ServerDataGrid[0, e.RowIndex2].Value)];
+ e.SortResult = (v1 == v2 ? 0 : (v1 < v2 ? -1 : 1));
+ if (e.SortResult != 0 && ServerDataGrid.SortOrder == SortOrder.Descending)
+ {
+ e.SortResult = -e.SortResult;
+ }
+ }
+ if (e.SortResult != 0)
+ {
+ e.Handled = true;
+ }
+ }
+ }
+}
diff --git a/shadowsocks-csharp/View/ServerLogForm.resx b/shadowsocks-csharp/View/ServerLogForm.resx
new file mode 100644
index 00000000..8f313209
--- /dev/null
+++ b/shadowsocks-csharp/View/ServerLogForm.resx
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/shadowsocks-csharp/shadowsocks-csharp4.0.csproj b/shadowsocks-csharp/shadowsocks-csharp4.0.csproj
new file mode 100644
index 00000000..7b35413e
--- /dev/null
+++ b/shadowsocks-csharp/shadowsocks-csharp4.0.csproj
@@ -0,0 +1,257 @@
+
+
+
+ Debug
+ AnyCPU
+ 9.0.21022
+ 2.0
+ {0F2A0C8A-6C06-485B-AA13-AEEC19CA9637}
+ WinExe
+ Properties
+ Shadowsocks
+ ShadowsocksR
+ v4.0
+ 512
+
+
+ shadowsocks.ico
+ false
+
+
+
+
+ 3.5
+
+
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 1
+ 1.0.0.%2a
+ false
+ true
+
+
+ true
+ bin\Net4.0x86\Debug\
+ TRACE;DEBUG
+ full
+ x86
+ prompt
+ ManagedMinimumRules.ruleset
+ false
+
+
+ bin\Net4.0x86\Release\
+ TRACE
+ true
+ pdbonly
+ x86
+ prompt
+ ManagedMinimumRules.ruleset
+ false
+ true
+
+
+ app.manifest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+ Form
+
+
+ ConfigForm.cs
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ QRCodeForm.cs
+
+
+ Form
+
+
+ Form
+
+
+ ServerLogForm.cs
+
+
+ ConfigForm.cs
+ Designer
+
+
+ ResXFileCodeGenerator
+ Designer
+ Resources.Designer.cs
+
+
+ QRCodeForm.cs
+
+
+ ServerLogForm.cs
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ .NET Framework 3.5 SP1 Client Profile
+ false
+
+
+ False
+ .NET Framework 2.0 %28x86%29
+ false
+
+
+ False
+ .NET Framework 3.0 %28x86%29
+ false
+
+
+ False
+ .NET Framework 3.5
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+ False
+ Windows Installer 3.1
+ true
+
+
+
+
+
\ No newline at end of file