@@ -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<RequestAddUrlEventArgs> 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(); | |||
} | |||
} | |||
} |
@@ -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<RequestAddUrlEventArgs> 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(); | |||
} | |||
} | |||
} | |||
} | |||
} |
@@ -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); | |||
@@ -170,7 +170,7 @@ | |||
<Compile Include="Controller\LoggerExtension.cs" /> | |||
<Compile Include="Controller\Service\GeositeUpdater.cs" /> | |||
<Compile Include="Controller\Service\PACDaemon.cs" /> | |||
<Compile Include="Controller\Service\NamedPipeServer.cs" /> | |||
<Compile Include="Controller\Service\IPCService.cs" /> | |||
<Compile Include="Controller\System\ProtocolHandler.cs" /> | |||
<Compile Include="Controller\System\Hotkeys\HotkeyCallbacks.cs" /> | |||
<Compile Include="Encryption\AEAD\AEADEncryptor.cs" /> | |||