Browse Source

refactor named pipe IPC

tags/4.2.0.0
Student Main 4 years ago
parent
commit
5172267289
No known key found for this signature in database GPG Key ID: AA78519C208C8742
4 changed files with 100 additions and 85 deletions
  1. +88
    -0
      shadowsocks-csharp/Controller/Service/IPCService.cs
  2. +0
    -47
      shadowsocks-csharp/Controller/Service/NamedPipeServer.cs
  3. +11
    -37
      shadowsocks-csharp/Program.cs
  4. +1
    -1
      shadowsocks-csharp/shadowsocks-csharp.csproj

+ 88
- 0
shadowsocks-csharp/Controller/Service/IPCService.cs View File

@@ -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();
}
}
}

+ 0
- 47
shadowsocks-csharp/Controller/Service/NamedPipeServer.cs View File

@@ -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();
}
}
}
}
}

+ 11
- 37
shadowsocks-csharp/Program.cs View File

@@ -67,48 +67,21 @@ namespace Shadowsocks
} }
return; 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.") 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.")); I18N.GetString("Shadowsocks is already running."));
return;
} }
return;
} }
Utils.ReleaseMemory(true); Utils.ReleaseMemory(true);
@@ -136,9 +109,10 @@ namespace Shadowsocks
HotKeys.Init(MainController); HotKeys.Init(MainController);
MainController.Start(); 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)) if (!string.IsNullOrWhiteSpace(Options.OpenUrl))
{ {
MainController.AskAddServerBySSURL(Options.OpenUrl); MainController.AskAddServerBySSURL(Options.OpenUrl);


+ 1
- 1
shadowsocks-csharp/shadowsocks-csharp.csproj View File

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


Loading…
Cancel
Save