SIP002 and SIP003 support
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
@@ -14,6 +15,7 @@ using Shadowsocks.Model;
|
||||
using Shadowsocks.Properties;
|
||||
using Shadowsocks.Util;
|
||||
using System.Linq;
|
||||
using Shadowsocks.Proxy;
|
||||
|
||||
namespace Shadowsocks.Controller
|
||||
{
|
||||
@@ -33,6 +35,8 @@ namespace Shadowsocks.Controller
|
||||
private StrategyManager _strategyManager;
|
||||
private PrivoxyRunner privoxyRunner;
|
||||
private GFWListUpdater gfwListUpdater;
|
||||
private readonly ConcurrentDictionary<Server, Sip003Plugin> _pluginsByServer;
|
||||
|
||||
public AvailabilityStatistics availabilityStatistics = AvailabilityStatistics.Instance;
|
||||
public StatisticsStrategyConfiguration StatisticsConfiguration { get; private set; }
|
||||
|
||||
@@ -79,6 +83,7 @@ namespace Shadowsocks.Controller
|
||||
_config = Configuration.Load();
|
||||
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
|
||||
_strategyManager = new StrategyManager(this);
|
||||
_pluginsByServer = new ConcurrentDictionary<Server, Sip003Plugin>();
|
||||
StartReleasingMemory();
|
||||
StartTrafficStatistics(61);
|
||||
}
|
||||
@@ -144,6 +149,23 @@ namespace Shadowsocks.Controller
|
||||
return GetCurrentServer();
|
||||
}
|
||||
|
||||
public EndPoint GetPluginLocalEndPointIfConfigured(Server server)
|
||||
{
|
||||
var plugin = _pluginsByServer.GetOrAdd(server, Sip003Plugin.CreateIfConfigured);
|
||||
if (plugin == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (plugin.StartIfNeeded())
|
||||
{
|
||||
Logging.Info(
|
||||
$"Started SIP003 plugin for {server.Identifier()} on {plugin.LocalEndPoint} - PID: {plugin.ProcessId}");
|
||||
}
|
||||
|
||||
return plugin.LocalEndPoint;
|
||||
}
|
||||
|
||||
public void SaveServers(List<Server> servers, int localPort)
|
||||
{
|
||||
_config.configs = servers;
|
||||
@@ -259,6 +281,7 @@ namespace Shadowsocks.Controller
|
||||
{
|
||||
_listener.Stop();
|
||||
}
|
||||
StopPlugins();
|
||||
if (privoxyRunner != null)
|
||||
{
|
||||
privoxyRunner.Stop();
|
||||
@@ -270,6 +293,15 @@ namespace Shadowsocks.Controller
|
||||
Encryption.RNG.Close();
|
||||
}
|
||||
|
||||
private void StopPlugins()
|
||||
{
|
||||
foreach (var serverAndPlugin in _pluginsByServer)
|
||||
{
|
||||
serverAndPlugin.Value?.Dispose();
|
||||
}
|
||||
_pluginsByServer.Clear();
|
||||
}
|
||||
|
||||
public void TouchPACFile()
|
||||
{
|
||||
string pacFilename = _pacServer.TouchPACFile();
|
||||
@@ -297,13 +329,41 @@ namespace Shadowsocks.Controller
|
||||
public static string GetQRCode(Server server)
|
||||
{
|
||||
string tag = string.Empty;
|
||||
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
if(!server.remarks.IsNullOrEmpty())
|
||||
string url = string.Empty;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(server.plugin))
|
||||
{
|
||||
// For backwards compatiblity, if no plugin, use old url format
|
||||
string parts = $"{server.method}:{server.password}@{server.server}:{server.server_port}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
url = base64;
|
||||
}
|
||||
else
|
||||
{
|
||||
// SIP002
|
||||
string parts = $"{server.method}:{server.password}";
|
||||
string base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(parts));
|
||||
string websafeBase64 = base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
|
||||
|
||||
string pluginPart = server.plugin;
|
||||
if (!string.IsNullOrWhiteSpace(server.plugin_opts))
|
||||
{
|
||||
pluginPart += ";" + server.plugin_opts;
|
||||
}
|
||||
|
||||
url = string.Format(
|
||||
"{0}@{1}:{2}/?plugin={3}",
|
||||
websafeBase64,
|
||||
HttpUtility.UrlEncode(server.server, Encoding.UTF8),
|
||||
server.server_port,
|
||||
HttpUtility.UrlEncode(pluginPart, Encoding.UTF8));
|
||||
}
|
||||
|
||||
if (!server.remarks.IsNullOrEmpty())
|
||||
{
|
||||
tag = $"#{HttpUtility.UrlEncode(server.remarks, Encoding.UTF8)}";
|
||||
}
|
||||
return $"ss://{base64}{tag}";
|
||||
return $"ss://{url}{tag}";
|
||||
}
|
||||
|
||||
public void UpdatePACFromGFWList()
|
||||
@@ -421,6 +481,8 @@ namespace Shadowsocks.Controller
|
||||
|
||||
protected void Reload()
|
||||
{
|
||||
StopPlugins();
|
||||
|
||||
Encryption.RNG.Reload();
|
||||
// some logic in configuration updated the config when saving, we need to read it again
|
||||
_config = Configuration.Load();
|
||||
|
||||
Reference in New Issue
Block a user