diff --git a/shadowsocks-csharp/Controller/Service/IPCService.cs b/shadowsocks-csharp/Controller/Service/IPCService.cs new file mode 100644 index 00000000..5e32f4aa --- /dev/null +++ b/shadowsocks-csharp/Controller/Service/IPCService.cs @@ -0,0 +1,88 @@ +using System; +using System.IO.Pipes; +using System.Net; +using System.Text; + +namespace Shadowsocks.Controller +{ + class RequestAddUrlEventArgs : EventArgs + { + public readonly string Url; + + public RequestAddUrlEventArgs(string url) + { + this.Url = url; + } + } + + internal class IPCService + { + private const int INT32_LEN = 4; + private const int OP_OPEN_URL = 1; + private static readonly string PIPE_PATH = $"Shadowsocks\\{Program.ExecutablePath.GetHashCode()}"; + + public event EventHandler OpenUrlRequested; + + public async void RunServer() + { + byte[] buf = new byte[4096]; + while (true) + { + using (NamedPipeServerStream stream = new NamedPipeServerStream(PIPE_PATH)) + { + await stream.WaitForConnectionAsync(); + await stream.ReadAsync(buf, 0, INT32_LEN); + int opcode = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 0)); + if (opcode == OP_OPEN_URL) + { + await stream.ReadAsync(buf, 0, INT32_LEN); + int strlen = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 0)); + + await stream.ReadAsync(buf, 0, strlen); + string url = Encoding.UTF8.GetString(buf, 0, strlen); + + OpenUrlRequested?.Invoke(this, new RequestAddUrlEventArgs(url)); + } + stream.Close(); + } + } + } + + private static (NamedPipeClientStream, bool) TryConnect() + { + NamedPipeClientStream pipe = new NamedPipeClientStream(PIPE_PATH); + bool exist; + try + { + pipe.Connect(10); + exist = true; + } + catch (TimeoutException) + { + exist = false; + } + return (pipe, exist); + } + + public static bool AnotherInstanceRunning() + { + (NamedPipeClientStream pipe, bool exist) = TryConnect(); + pipe.Dispose(); + return exist; + } + + public static void RequestOpenUrl(string url) + { + (NamedPipeClientStream pipe, bool exist) = TryConnect(); + if(!exist) return; + byte[] opAddUrl = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(OP_OPEN_URL)); + pipe.Write(opAddUrl, 0, INT32_LEN); // opcode addurl + byte[] b = Encoding.UTF8.GetBytes(url); + byte[] blen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(b.Length)); + pipe.Write(blen, 0, INT32_LEN); + pipe.Write(b, 0, b.Length); + pipe.Close(); + pipe.Dispose(); + } + } +} diff --git a/shadowsocks-csharp/Controller/Service/NamedPipeServer.cs b/shadowsocks-csharp/Controller/Service/NamedPipeServer.cs deleted file mode 100644 index 23689231..00000000 --- a/shadowsocks-csharp/Controller/Service/NamedPipeServer.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.IO; -using System.IO.Pipes; -using System.Net; -using System.Text; - -namespace Shadowsocks.Controller -{ - class RequestAddUrlEventArgs : EventArgs - { - public readonly string Url; - - public RequestAddUrlEventArgs(string url) - { - this.Url = url; - } - } - - internal class NamedPipeServer - { - public event EventHandler AddUrlRequested; - public async void Run(string path) - { - byte[] buf = new byte[4096]; - while (true) - { - using (NamedPipeServerStream stream = new NamedPipeServerStream(path)) - { - stream.WaitForConnection(); - await stream.ReadAsync(buf, 0, 4); - int opcode = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 0)); - if (opcode == 1) - { - await stream.ReadAsync(buf, 0, 4); - int strlen = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buf, 0)); - - await stream.ReadAsync(buf, 0, strlen); - string url = Encoding.UTF8.GetString(buf, 0, strlen); - - AddUrlRequested?.Invoke(this, new RequestAddUrlEventArgs(url)); - } - stream.Close(); - } - } - } - } -} diff --git a/shadowsocks-csharp/Program.cs b/shadowsocks-csharp/Program.cs index 2bee9850..c05bb9cc 100755 --- a/shadowsocks-csharp/Program.cs +++ b/shadowsocks-csharp/Program.cs @@ -67,48 +67,21 @@ namespace Shadowsocks } return; } - string pipename = $"Shadowsocks\\{ExecutablePath.GetHashCode()}"; - using (NamedPipeClientStream pipe = new NamedPipeClientStream(pipename)) + if (IPCService.AnotherInstanceRunning()) { - bool pipeExist = false; - try + if (!string.IsNullOrWhiteSpace(Options.OpenUrl)) { - pipe.Connect(10); - pipeExist = true; + IPCService.RequestOpenUrl(Options.OpenUrl); } - catch (TimeoutException) + else { - pipeExist = false; - } - - // --open-url exist, and no other instance, add it later - if (pipeExist && !string.IsNullOrWhiteSpace(Options.OpenUrl)) - { - byte[] b = Encoding.UTF8.GetBytes(Options.OpenUrl); - byte[] opAddUrl = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(1)); - byte[] blen = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(b.Length)); - pipe.Write(opAddUrl, 0, 4); // opcode addurl - pipe.Write(blen, 0, 4); - pipe.Write(b, 0, b.Length); - pipe.Close(); - return; - } - - // has another instance, and no need to communicate with it return - else if (pipeExist) - { - Process[] oldProcesses = Process.GetProcessesByName("Shadowsocks"); - if (oldProcesses.Length > 0) - { - Process oldProcess = oldProcesses[0]; - } MessageBox.Show(I18N.GetString("Find Shadowsocks icon in your notify tray.") - + Environment.NewLine - + I18N.GetString("If you want to start multiple Shadowsocks, make a copy in another directory."), + + Environment.NewLine + + I18N.GetString("If you want to start multiple Shadowsocks, make a copy in another directory."), I18N.GetString("Shadowsocks is already running.")); - return; } + return; } Utils.ReleaseMemory(true); @@ -136,9 +109,10 @@ namespace Shadowsocks HotKeys.Init(MainController); MainController.Start(); - NamedPipeServer namedPipeServer = new NamedPipeServer(); - Task.Run(() => namedPipeServer.Run(pipename)); - namedPipeServer.AddUrlRequested += (_1, e) => MainController.AskAddServerBySSURL(e.Url); + IPCService ipcService = new IPCService(); + Task.Run(() => ipcService.RunServer()); + ipcService.OpenUrlRequested += (_1, e) => MainController.AskAddServerBySSURL(e.Url); + if (!string.IsNullOrWhiteSpace(Options.OpenUrl)) { MainController.AskAddServerBySSURL(Options.OpenUrl); diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index c9f298df..a5229a78 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -170,7 +170,7 @@ - +