@@ -0,0 +1,39 @@ | |||||
--- | |||||
name: Bug report (English) | |||||
about: Create a report to help us improve | |||||
title: '' | |||||
labels: '' | |||||
assignees: '' | |||||
--- | |||||
<!-- | |||||
- Shadowsocks is a non-profit open source project. If you bought the service from a provider, please contact them. | |||||
- If you have questions rather than Shadowsocks Windows client, please go to https://github.com/shadowsocks | |||||
- Please read Wiki carefully, especially https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting | |||||
- And search from Issue Board https://github.com/shadowsocks/shadowsocks-windows/issues?utf8=%E2%9C%93&q=is%3Aissue | |||||
- Please include the following information. Questions lacking details will be closed. | |||||
--> | |||||
### Describe the bug | |||||
### Environment | |||||
- Shadowsocks client version: | |||||
- OS version: | |||||
- .NET version: | |||||
### Steps you have tried | |||||
### What did you expect to see? | |||||
### What did you see instead? | |||||
### Config and error log in detail (with all sensitive info masked) | |||||
``` | |||||
PASTE LOG HERE | |||||
``` |
@@ -0,0 +1,39 @@ | |||||
--- | |||||
name: Bug报告 (中文) | |||||
about: 反馈Bug | |||||
title: '' | |||||
labels: bug report | |||||
assignees: '' | |||||
--- | |||||
<!-- | |||||
- 影梭(Shadowsocks)是一个开源非盈利项目,不提供任何托管服务。如果你是从服务提供商购买的服务,请联系他们。 | |||||
- 如果你有非影梭Windows客户端相关的问题,请去 https://github.com/shadowsocks | |||||
- 提问前请先阅读wiki https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting. | |||||
- 并在Issue Board中搜索 https://github.com/shadowsocks/shadowsocks-windows/issues?utf8=%E2%9C%93&q=is%3Aissue | |||||
- 请按照以下格式描述你的问题,描述不清的问题将会被关闭。 | |||||
--> | |||||
### 简要描述问题 | |||||
### 环境 | |||||
- Shadowsocks客户端版本: | |||||
- 操作系统版本: | |||||
- .NET版本: | |||||
### 操作步骤 | |||||
### 期望的结果 | |||||
### 实际结果 | |||||
### 配置文件和日志文件(请隐去敏感信息) | |||||
``` | |||||
在此粘贴日志 | |||||
``` |
@@ -0,0 +1,20 @@ | |||||
--- | |||||
name: Feature request | |||||
about: Suggest an idea for this project | |||||
title: '' | |||||
labels: '' | |||||
assignees: '' | |||||
--- | |||||
**Is your feature request related to a problem? Please describe.** | |||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] | |||||
**Describe the solution you'd like** | |||||
A clear and concise description of what you want to happen. | |||||
**Describe alternatives you've considered** | |||||
A clear and concise description of any alternative solutions or features you've considered. | |||||
**Additional context** | |||||
Add any other context or screenshots about the feature request here. |
@@ -1,29 +0,0 @@ | |||||
<!-- | |||||
- Shadowsocks is a non-profit open source project. If you bought the service from a provider, please contact them. | |||||
影梭(Shadowsocks)是一个开源非盈利项目,不提供任何托管服务。如果你是从服务提供商购买的服务,请联系他们。 | |||||
- If you have questions rather than Shadowsocks Windows client, please go to https://github.com/shadowsocks | |||||
如果你有非影梭Windows客户端相关的问题,请去 https://github.com/shadowsocks | |||||
- Please read Wiki carefully, especially https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting | |||||
提问前请先阅读wiki https://github.com/shadowsocks/shadowsocks-windows/wiki/Troubleshooting. | |||||
- And search from Issue Board https://github.com/shadowsocks/shadowsocks-windows/issues?utf8=%E2%9C%93&q=is%3Aissue | |||||
并在Issue Board中搜索 https://github.com/shadowsocks/shadowsocks-windows/issues?utf8=%E2%9C%93&q=is%3Aissue | |||||
- Please include the following information. Questions lacking details will be closed. | |||||
请按照以下格式描述你的问题,描述不清的问题将会被关闭。 | |||||
--> | |||||
### Shadowsocks version / 影梭版本 | |||||
### Environment (Operating system, .NET Framework, etc) / 使用环境(操作系统,.NET Framework等) | |||||
### Steps you have tried / 操作步骤 | |||||
### What did you expect to see? / 期望的结果 | |||||
### What did you see instead? / 实际结果 | |||||
### Config and error log in detail (with all sensitive info masked) / 配置文件和日志文件(请隐去敏感信息) |
@@ -1,10 +1,12 @@ | |||||
using NLog; | |||||
using System; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Linq; | using System.Linq; | ||||
using System.Net; | using System.Net; | ||||
using System.Net.Sockets; | using System.Net.Sockets; | ||||
using System.Timers; | using System.Timers; | ||||
using NLog; | |||||
using Shadowsocks.Controller.Strategy; | using Shadowsocks.Controller.Strategy; | ||||
using Shadowsocks.Encryption; | using Shadowsocks.Encryption; | ||||
using Shadowsocks.Encryption.AEAD; | using Shadowsocks.Encryption.AEAD; | ||||
@@ -12,16 +14,22 @@ using Shadowsocks.Encryption.Exception; | |||||
using Shadowsocks.Model; | using Shadowsocks.Model; | ||||
using Shadowsocks.Proxy; | using Shadowsocks.Proxy; | ||||
using Shadowsocks.Util.Sockets; | using Shadowsocks.Util.Sockets; | ||||
using static Shadowsocks.Encryption.EncryptorBase; | using static Shadowsocks.Encryption.EncryptorBase; | ||||
namespace Shadowsocks.Controller | namespace Shadowsocks.Controller | ||||
{ | { | ||||
class TCPRelay : Listener.Service | |||||
internal class TCPRelay : Listener.Service | |||||
{ | { | ||||
private static Logger logger = LogManager.GetCurrentClassLogger(); | |||||
private ShadowsocksController _controller; | |||||
public event EventHandler<SSTCPConnectedEventArgs> OnConnected; | |||||
public event EventHandler<SSTransmitEventArgs> OnInbound; | |||||
public event EventHandler<SSTransmitEventArgs> OnOutbound; | |||||
public event EventHandler<SSRelayEventArgs> OnFailed; | |||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger(); | |||||
private readonly ShadowsocksController _controller; | |||||
private DateTime _lastSweepTime; | private DateTime _lastSweepTime; | ||||
private Configuration _config; | |||||
private readonly Configuration _config; | |||||
public ISet<TCPHandler> Handlers { get; set; } | public ISet<TCPHandler> Handlers { get; set; } | ||||
@@ -37,9 +45,24 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
if (socket.ProtocolType != ProtocolType.Tcp | if (socket.ProtocolType != ProtocolType.Tcp | ||||
|| (length < 2 || firstPacket[0] != 5)) | || (length < 2 || firstPacket[0] != 5)) | ||||
{ | |||||
return false; | return false; | ||||
} | |||||
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | ||||
TCPHandler handler = new TCPHandler(_controller, _config, this, socket); | |||||
TCPHandler handler = new TCPHandler(_controller, _config, socket); | |||||
handler.OnConnected += OnConnected; | |||||
handler.OnInbound += OnInbound; | |||||
handler.OnOutbound += OnOutbound; | |||||
handler.OnFailed += OnFailed; | |||||
handler.OnClosed += (h, arg) => | |||||
{ | |||||
lock (Handlers) | |||||
{ | |||||
Handlers.Remove(handler); | |||||
} | |||||
}; | |||||
IList<TCPHandler> handlersToClose = new List<TCPHandler>(); | IList<TCPHandler> handlersToClose = new List<TCPHandler>(); | ||||
lock (Handlers) | lock (Handlers) | ||||
@@ -50,8 +73,12 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
_lastSweepTime = now; | _lastSweepTime = now; | ||||
foreach (TCPHandler handler1 in Handlers) | foreach (TCPHandler handler1 in Handlers) | ||||
{ | |||||
if (now - handler1.lastActivity > TimeSpan.FromSeconds(900)) | if (now - handler1.lastActivity > TimeSpan.FromSeconds(900)) | ||||
{ | |||||
handlersToClose.Add(handler1); | handlersToClose.Add(handler1); | ||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
foreach (TCPHandler handler1 in handlersToClose) | foreach (TCPHandler handler1 in handlersToClose) | ||||
@@ -80,26 +107,46 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
handlersToClose.ForEach(h => h.Close()); | handlersToClose.ForEach(h => h.Close()); | ||||
} | } | ||||
} | |||||
public void UpdateInboundCounter(Server server, long n) | |||||
public class SSRelayEventArgs : EventArgs | |||||
{ | |||||
public readonly Server server; | |||||
public SSRelayEventArgs(Server server) | |||||
{ | { | ||||
_controller.UpdateInboundCounter(server, n); | |||||
this.server = server; | |||||
} | } | ||||
} | |||||
public void UpdateOutboundCounter(Server server, long n) | |||||
public class SSTransmitEventArgs : SSRelayEventArgs | |||||
{ | |||||
public readonly long length; | |||||
public SSTransmitEventArgs(Server server, long length) : base(server) | |||||
{ | { | ||||
_controller.UpdateOutboundCounter(server, n); | |||||
this.length = length; | |||||
} | } | ||||
} | |||||
public class SSTCPConnectedEventArgs : SSRelayEventArgs | |||||
{ | |||||
public readonly TimeSpan latency; | |||||
public void UpdateLatency(Server server, TimeSpan latency) | |||||
public SSTCPConnectedEventArgs(Server server, TimeSpan latency) : base(server) | |||||
{ | { | ||||
_controller.UpdateLatency(server, latency); | |||||
this.latency = latency; | |||||
} | } | ||||
} | } | ||||
internal class TCPHandler | internal class TCPHandler | ||||
{ | { | ||||
class AsyncSession | |||||
public event EventHandler<SSTCPConnectedEventArgs> OnConnected; | |||||
public event EventHandler<SSTransmitEventArgs> OnInbound; | |||||
public event EventHandler<SSTransmitEventArgs> OnOutbound; | |||||
public event EventHandler<SSRelayEventArgs> OnClosed; | |||||
public event EventHandler<SSRelayEventArgs> OnFailed; | |||||
private class AsyncSession | |||||
{ | { | ||||
public IProxy Remote { get; } | public IProxy Remote { get; } | ||||
@@ -109,7 +156,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
class AsyncSession<T> : AsyncSession | |||||
private class AsyncSession<T> : AsyncSession | |||||
{ | { | ||||
public T State { get; set; } | public T State { get; set; } | ||||
@@ -124,7 +171,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
} | } | ||||
private static Logger Logger = LogManager.GetCurrentClassLogger(); | |||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); | |||||
private readonly int _serverTimeout; | private readonly int _serverTimeout; | ||||
private readonly int _proxyTimeout; | private readonly int _proxyTimeout; | ||||
@@ -143,10 +190,9 @@ namespace Shadowsocks.Controller | |||||
public DateTime lastActivity; | public DateTime lastActivity; | ||||
private ShadowsocksController _controller; | |||||
private Configuration _config; | |||||
private TCPRelay _tcprelay; | |||||
private Socket _connection; | |||||
private readonly ShadowsocksController _controller; | |||||
private readonly ProxyConfig _config; | |||||
private readonly Socket _connection; | |||||
private IEncryptor _encryptor; | private IEncryptor _encryptor; | ||||
private Server _server; | private Server _server; | ||||
@@ -170,16 +216,16 @@ namespace Shadowsocks.Controller | |||||
private int _totalWrite = 0; | private int _totalWrite = 0; | ||||
// remote -> local proxy (ciphertext, before decrypt) | // remote -> local proxy (ciphertext, before decrypt) | ||||
private byte[] _remoteRecvBuffer = new byte[BufferSize]; | |||||
private readonly byte[] _remoteRecvBuffer = new byte[BufferSize]; | |||||
// client -> local proxy (plaintext, before encrypt) | // client -> local proxy (plaintext, before encrypt) | ||||
private byte[] _connetionRecvBuffer = new byte[BufferSize]; | |||||
private readonly byte[] _connetionRecvBuffer = new byte[BufferSize]; | |||||
// local proxy -> remote (plaintext, after decrypt) | // local proxy -> remote (plaintext, after decrypt) | ||||
private byte[] _remoteSendBuffer = new byte[BufferSize]; | |||||
private readonly byte[] _remoteSendBuffer = new byte[BufferSize]; | |||||
// local proxy -> client (ciphertext, before decrypt) | // local proxy -> client (ciphertext, before decrypt) | ||||
private byte[] _connetionSendBuffer = new byte[BufferSize]; | |||||
private readonly byte[] _connetionSendBuffer = new byte[BufferSize]; | |||||
private bool _connectionShutdown = false; | private bool _connectionShutdown = false; | ||||
private bool _remoteShutdown = false; | private bool _remoteShutdown = false; | ||||
@@ -197,11 +243,11 @@ namespace Shadowsocks.Controller | |||||
private EndPoint _destEndPoint = null; | private EndPoint _destEndPoint = null; | ||||
public TCPHandler(ShadowsocksController controller, Configuration config, TCPRelay tcprelay, Socket socket) | |||||
// TODO: decouple controller | |||||
public TCPHandler(ShadowsocksController controller, Configuration config, Socket socket) | |||||
{ | { | ||||
_controller = controller; | _controller = controller; | ||||
_config = config; | |||||
_tcprelay = tcprelay; | |||||
_config = config.proxy; | |||||
_connection = socket; | _connection = socket; | ||||
_proxyTimeout = config.proxy.proxyTimeout * 1000; | _proxyTimeout = config.proxy.proxyTimeout * 1000; | ||||
_serverTimeout = config.GetCurrentServer().timeout * 1000; | _serverTimeout = config.GetCurrentServer().timeout * 1000; | ||||
@@ -214,11 +260,13 @@ namespace Shadowsocks.Controller | |||||
Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint, | Server server = _controller.GetAServer(IStrategyCallerType.TCP, (IPEndPoint)_connection.RemoteEndPoint, | ||||
_destEndPoint); | _destEndPoint); | ||||
if (server == null || server.server == "") | if (server == null || server.server == "") | ||||
{ | |||||
throw new ArgumentException("No server configured"); | throw new ArgumentException("No server configured"); | ||||
} | |||||
_encryptor = EncryptorFactory.GetEncryptor(server.method, server.password); | _encryptor = EncryptorFactory.GetEncryptor(server.method, server.password); | ||||
this._server = server; | |||||
_server = server; | |||||
/* prepare address buffer length for AEAD */ | /* prepare address buffer length for AEAD */ | ||||
Logger.Trace($"_addrBufLength={_addrBufLength}"); | Logger.Trace($"_addrBufLength={_addrBufLength}"); | ||||
@@ -235,20 +283,31 @@ namespace Shadowsocks.Controller | |||||
private void CheckClose() | private void CheckClose() | ||||
{ | { | ||||
if (_connectionShutdown && _remoteShutdown) | if (_connectionShutdown && _remoteShutdown) | ||||
{ | |||||
Close(); | Close(); | ||||
} | |||||
} | |||||
private void ErrorClose(Exception e) | |||||
{ | |||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
} | } | ||||
public void Close() | public void Close() | ||||
{ | { | ||||
lock (_closeConnLock) | lock (_closeConnLock) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
_closed = true; | _closed = true; | ||||
} | } | ||||
lock (_tcprelay.Handlers) | |||||
{ | |||||
_tcprelay.Handlers.Remove(this); | |||||
} | |||||
OnClosed?.Invoke(this, new SSRelayEventArgs(_server)); | |||||
try | try | ||||
{ | { | ||||
_connection.Shutdown(SocketShutdown.Both); | _connection.Shutdown(SocketShutdown.Both); | ||||
@@ -263,7 +322,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var remote = _currentRemoteSession.Remote; | |||||
IProxy remote = _currentRemoteSession.Remote; | |||||
remote.Shutdown(SocketShutdown.Both); | remote.Shutdown(SocketShutdown.Both); | ||||
remote.Close(); | remote.Close(); | ||||
} | } | ||||
@@ -284,7 +343,11 @@ namespace Shadowsocks.Controller | |||||
private void HandshakeReceive() | private void HandshakeReceive() | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
int bytesRead = _firstPacketLength; | int bytesRead = _firstPacketLength; | ||||
@@ -301,18 +364,23 @@ namespace Shadowsocks.Controller | |||||
HandshakeSendCallback, null); | HandshakeSendCallback, null); | ||||
} | } | ||||
else | else | ||||
{ | |||||
Close(); | Close(); | ||||
} | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void HandshakeSendCallback(IAsyncResult ar) | private void HandshakeSendCallback(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
_connection.EndSend(ar); | _connection.EndSend(ar); | ||||
@@ -324,27 +392,30 @@ namespace Shadowsocks.Controller | |||||
// +-----+-----+-------+------+----------+----------+ | // +-----+-----+-------+------+----------+----------+ | ||||
// Skip first 3 bytes, and read 2 more bytes to analysis the address. | // Skip first 3 bytes, and read 2 more bytes to analysis the address. | ||||
// 2 more bytes is designed if address is domain then we don't need to read once more to get the addr length. | // 2 more bytes is designed if address is domain then we don't need to read once more to get the addr length. | ||||
// TODO validate | |||||
// validate is unnecessary, we did it in first packet, but we can do it in future version | |||||
_connection.BeginReceive(_connetionRecvBuffer, 0, 3 + ADDR_ATYP_LEN + 1, SocketFlags.None, | _connection.BeginReceive(_connetionRecvBuffer, 0, 3 + ADDR_ATYP_LEN + 1, SocketFlags.None, | ||||
HandshakeReceive2Callback, null); | |||||
AddressReceiveCallback, null); | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void HandshakeReceive2Callback(IAsyncResult ar) | |||||
private void AddressReceiveCallback(IAsyncResult ar) | |||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
int bytesRead = _connection.EndReceive(ar); | int bytesRead = _connection.EndReceive(ar); | ||||
if (bytesRead >= 5) | if (bytesRead >= 5) | ||||
{ | { | ||||
_command = _connetionRecvBuffer[1]; | _command = _connetionRecvBuffer[1]; | ||||
switch(_command) | |||||
switch (_command) | |||||
{ | { | ||||
case CMD_CONNECT: | case CMD_CONNECT: | ||||
@@ -355,7 +426,7 @@ namespace Shadowsocks.Controller | |||||
// +----+-----+-------+------+----------+----------+ | // +----+-----+-------+------+----------+----------+ | ||||
byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; | byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; | ||||
_connection.BeginSend(response, 0, response.Length, SocketFlags.None, | _connection.BeginSend(response, 0, response.Length, SocketFlags.None, | ||||
ResponseCallback, null); | |||||
ConnectResponseCallback, null); | |||||
break; | break; | ||||
case CMD_UDP_ASSOC: | case CMD_UDP_ASSOC: | ||||
ReadAddress(HandleUDPAssociate); | ReadAddress(HandleUDPAssociate); | ||||
@@ -376,12 +447,11 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void ResponseCallback(IAsyncResult ar) | |||||
private void ConnectResponseCallback(IAsyncResult ar) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
@@ -391,8 +461,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
@@ -431,15 +500,19 @@ namespace Shadowsocks.Controller | |||||
private void OnAddressFullyRead(IAsyncResult ar) | private void OnAddressFullyRead(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
int bytesRead = _connection.EndReceive(ar); | int bytesRead = _connection.EndReceive(ar); | ||||
var states = (object[])ar.AsyncState; | |||||
object[] states = (object[])ar.AsyncState; | |||||
int bytesRemain = (int)states[0]; | int bytesRemain = (int)states[0]; | ||||
var onSuccess = (Action)states[1]; | |||||
Action onSuccess = (Action)states[1]; | |||||
if (bytesRead >= bytesRemain) | if (bytesRead >= bytesRemain) | ||||
{ | { | ||||
@@ -472,7 +545,7 @@ namespace Shadowsocks.Controller | |||||
break; | break; | ||||
} | } | ||||
Logger.Debug($"connect to {dstAddr}:{dstPort}"); | |||||
Logger.Debug($"connect to {dstAddr}:{dstPort}"); | |||||
_destEndPoint = SocketUtil.GetEndPoint(dstAddr, dstPort); | _destEndPoint = SocketUtil.GetEndPoint(dstAddr, dstPort); | ||||
@@ -486,8 +559,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
@@ -515,7 +587,11 @@ namespace Shadowsocks.Controller | |||||
private void ReadAll(IAsyncResult ar) | private void ReadAll(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
if (ar.AsyncState != null) | if (ar.AsyncState != null) | ||||
@@ -533,13 +609,14 @@ namespace Shadowsocks.Controller | |||||
ReadAll, null); | ReadAll, null); | ||||
} | } | ||||
else | else | ||||
{ | |||||
Close(); | Close(); | ||||
} | |||||
} | } | ||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
@@ -584,9 +661,9 @@ namespace Shadowsocks.Controller | |||||
serverEP = pluginEP; | serverEP = pluginEP; | ||||
remote = new DirectConnect(); | remote = new DirectConnect(); | ||||
} | } | ||||
else if (_config.proxy.useProxy) | |||||
else if (_config.useProxy) | |||||
{ | { | ||||
switch (_config.proxy.proxyType) | |||||
switch (_config.proxyType) | |||||
{ | { | ||||
case ProxyConfig.PROXY_SOCKS5: | case ProxyConfig.PROXY_SOCKS5: | ||||
remote = new Socks5Proxy(); | remote = new Socks5Proxy(); | ||||
@@ -597,14 +674,14 @@ namespace Shadowsocks.Controller | |||||
default: | default: | ||||
throw new NotSupportedException("Unknown forward proxy."); | throw new NotSupportedException("Unknown forward proxy."); | ||||
} | } | ||||
proxyEP = SocketUtil.GetEndPoint(_config.proxy.proxyServer, _config.proxy.proxyPort); | |||||
proxyEP = SocketUtil.GetEndPoint(_config.proxyServer, _config.proxyPort); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
remote = new DirectConnect(); | remote = new DirectConnect(); | ||||
} | } | ||||
var session = new AsyncSession(remote); | |||||
AsyncSession session = new AsyncSession(remote); | |||||
lock (_closeConnLock) | lock (_closeConnLock) | ||||
{ | { | ||||
if (_closed) | if (_closed) | ||||
@@ -632,14 +709,13 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void ProxyConnectTimer_Elapsed(object sender, ElapsedEventArgs e) | private void ProxyConnectTimer_Elapsed(object sender, ElapsedEventArgs e) | ||||
{ | { | ||||
var timer = (ProxyTimer)sender; | |||||
ProxyTimer timer = (ProxyTimer)sender; | |||||
timer.Elapsed -= ProxyConnectTimer_Elapsed; | timer.Elapsed -= ProxyConnectTimer_Elapsed; | ||||
timer.Enabled = false; | timer.Enabled = false; | ||||
timer.Dispose(); | timer.Dispose(); | ||||
@@ -649,7 +725,7 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
return; | return; | ||||
} | } | ||||
var proxy = timer.Session.Remote; | |||||
IProxy proxy = timer.Session.Remote; | |||||
Logger.Info($"Proxy {proxy.ProxyEndPoint} timed out"); | Logger.Info($"Proxy {proxy.ProxyEndPoint} timed out"); | ||||
proxy.Close(); | proxy.Close(); | ||||
@@ -664,15 +740,15 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
try | try | ||||
{ | { | ||||
var session = (AsyncSession<ProxyTimer>)ar.AsyncState; | |||||
AsyncSession<ProxyTimer> session = (AsyncSession<ProxyTimer>)ar.AsyncState; | |||||
ProxyTimer timer = session.State; | ProxyTimer timer = session.State; | ||||
var destEndPoint = timer.DestEndPoint; | |||||
var server = timer.Server; | |||||
EndPoint destEndPoint = timer.DestEndPoint; | |||||
Server server = timer.Server; | |||||
timer.Elapsed -= ProxyConnectTimer_Elapsed; | timer.Elapsed -= ProxyConnectTimer_Elapsed; | ||||
timer.Enabled = false; | timer.Enabled = false; | ||||
timer.Dispose(); | timer.Dispose(); | ||||
var remote = session.Remote; | |||||
IProxy remote = session.Remote; | |||||
// Complete the connection. | // Complete the connection. | ||||
remote.EndConnectProxy(ar); | remote.EndConnectProxy(ar); | ||||
@@ -694,9 +770,9 @@ namespace Shadowsocks.Controller | |||||
_destConnected = false; | _destConnected = false; | ||||
NetworkCredential auth = null; | NetworkCredential auth = null; | ||||
if (_config.proxy.useAuth) | |||||
if (_config.useAuth) | |||||
{ | { | ||||
auth = new NetworkCredential(_config.proxy.authUser, _config.proxy.authPwd); | |||||
auth = new NetworkCredential(_config.authUser, _config.authPwd); | |||||
} | } | ||||
// Connect to the remote endpoint. | // Connect to the remote endpoint. | ||||
@@ -708,14 +784,13 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void DestConnectTimer_Elapsed(object sender, ElapsedEventArgs e) | private void DestConnectTimer_Elapsed(object sender, ElapsedEventArgs e) | ||||
{ | { | ||||
var timer = (ServerTimer)sender; | |||||
ServerTimer timer = (ServerTimer)sender; | |||||
timer.Elapsed -= DestConnectTimer_Elapsed; | timer.Elapsed -= DestConnectTimer_Elapsed; | ||||
timer.Enabled = false; | timer.Enabled = false; | ||||
timer.Dispose(); | timer.Dispose(); | ||||
@@ -725,10 +800,9 @@ namespace Shadowsocks.Controller | |||||
return; | return; | ||||
} | } | ||||
var session = timer.Session; | |||||
AsyncSession session = timer.Session; | |||||
Server server = timer.Server; | Server server = timer.Server; | ||||
IStrategy strategy = _controller.GetCurrentStrategy(); | |||||
strategy?.SetFailure(server); | |||||
OnFailed?.Invoke(this, new SSRelayEventArgs(_server)); | |||||
Logger.Info($"{server.FriendlyName()} timed out"); | Logger.Info($"{server.FriendlyName()} timed out"); | ||||
session.Remote.Close(); | session.Remote.Close(); | ||||
Close(); | Close(); | ||||
@@ -736,17 +810,21 @@ namespace Shadowsocks.Controller | |||||
private void ConnectCallback(IAsyncResult ar) | private void ConnectCallback(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
var session = (AsyncSession<ServerTimer>)ar.AsyncState; | |||||
AsyncSession<ServerTimer> session = (AsyncSession<ServerTimer>)ar.AsyncState; | |||||
ServerTimer timer = session.State; | ServerTimer timer = session.State; | ||||
_server = timer.Server; | _server = timer.Server; | ||||
timer.Elapsed -= DestConnectTimer_Elapsed; | timer.Elapsed -= DestConnectTimer_Elapsed; | ||||
timer.Enabled = false; | timer.Enabled = false; | ||||
timer.Dispose(); | timer.Dispose(); | ||||
var remote = session.Remote; | |||||
IProxy remote = session.Remote; | |||||
// Complete the connection. | // Complete the connection. | ||||
remote.EndConnectDest(ar); | remote.EndConnectDest(ar); | ||||
@@ -754,10 +832,9 @@ namespace Shadowsocks.Controller | |||||
Logger.Debug($"Socket connected to ss server: {_server.FriendlyName()}"); | Logger.Debug($"Socket connected to ss server: {_server.FriendlyName()}"); | ||||
var latency = DateTime.Now - _startConnectTime; | |||||
IStrategy strategy = _controller.GetCurrentStrategy(); | |||||
strategy?.UpdateLatency(_server, latency); | |||||
_tcprelay.UpdateLatency(_server, latency); | |||||
TimeSpan latency = DateTime.Now - _startConnectTime; | |||||
OnConnected?.Invoke(this, new SSTCPConnectedEventArgs(_server, latency)); | |||||
StartPipe(session); | StartPipe(session); | ||||
} | } | ||||
@@ -768,11 +845,9 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
if (_server != null) | if (_server != null) | ||||
{ | { | ||||
IStrategy strategy = _controller.GetCurrentStrategy(); | |||||
strategy?.SetFailure(_server); | |||||
OnFailed?.Invoke(this, new SSRelayEventArgs(_server)); | |||||
} | } | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
@@ -781,7 +856,7 @@ namespace Shadowsocks.Controller | |||||
int available = Math.Min(_connection.Available, RecvSize - _firstPacketLength); | int available = Math.Min(_connection.Available, RecvSize - _firstPacketLength); | ||||
if (available > 0) | if (available > 0) | ||||
{ | { | ||||
var size = _connection.Receive(_connetionRecvBuffer, _firstPacketLength, available, | |||||
int size = _connection.Receive(_connetionRecvBuffer, _firstPacketLength, available, | |||||
SocketFlags.None); | SocketFlags.None); | ||||
_firstPacketLength += size; | _firstPacketLength += size; | ||||
@@ -790,7 +865,11 @@ namespace Shadowsocks.Controller | |||||
private void StartPipe(AsyncSession session) | private void StartPipe(AsyncSession session) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
_startReceivingTime = DateTime.Now; | _startReceivingTime = DateTime.Now; | ||||
@@ -803,20 +882,24 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void PipeRemoteReceiveCallback(IAsyncResult ar) | private void PipeRemoteReceiveCallback(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
var session = (AsyncSession)ar.AsyncState; | |||||
AsyncSession session = (AsyncSession)ar.AsyncState; | |||||
int bytesRead = session.Remote.EndReceive(ar); | int bytesRead = session.Remote.EndReceive(ar); | ||||
_totalRead += bytesRead; | _totalRead += bytesRead; | ||||
_tcprelay.UpdateInboundCounter(_server, bytesRead); | |||||
OnInbound?.Invoke(this, new SSTransmitEventArgs(_server, bytesRead)); | |||||
if (bytesRead > 0) | if (bytesRead > 0) | ||||
{ | { | ||||
lastActivity = DateTime.Now; | lastActivity = DateTime.Now; | ||||
@@ -845,8 +928,6 @@ namespace Shadowsocks.Controller | |||||
Logger.Trace($"start sending {bytesToSend}"); | Logger.Trace($"start sending {bytesToSend}"); | ||||
_connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, | _connection.BeginSend(_remoteSendBuffer, 0, bytesToSend, SocketFlags.None, | ||||
PipeConnectionSendCallback, new object[] { session, bytesToSend }); | PipeConnectionSendCallback, new object[] { session, bytesToSend }); | ||||
IStrategy strategy = _controller.GetCurrentStrategy(); | |||||
strategy?.UpdateLastRead(_server); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
@@ -857,20 +938,23 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
private void PipeConnectionReceiveCallback(IAsyncResult ar) | private void PipeConnectionReceiveCallback(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
int bytesRead = _connection.EndReceive(ar); | int bytesRead = _connection.EndReceive(ar); | ||||
var session = (AsyncSession)ar.AsyncState; | |||||
var remote = session.Remote; | |||||
AsyncSession session = (AsyncSession)ar.AsyncState; | |||||
IProxy remote = session.Remote; | |||||
if (bytesRead > 0) | if (bytesRead > 0) | ||||
{ | { | ||||
@@ -885,8 +969,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
@@ -907,22 +990,25 @@ namespace Shadowsocks.Controller | |||||
return; | return; | ||||
} | } | ||||
} | } | ||||
_tcprelay.UpdateOutboundCounter(_server, bytesToSend); | |||||
OnOutbound?.Invoke(this, new SSTransmitEventArgs(_server, bytesToSend)); | |||||
_startSendingTime = DateTime.Now; | _startSendingTime = DateTime.Now; | ||||
session.Remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, | session.Remote.BeginSend(_connetionSendBuffer, 0, bytesToSend, SocketFlags.None, | ||||
PipeRemoteSendCallback, new object[] { session, bytesToSend }); | PipeRemoteSendCallback, new object[] { session, bytesToSend }); | ||||
IStrategy strategy = _controller.GetCurrentStrategy(); | |||||
strategy?.UpdateLastWrite(_server); | |||||
} | } | ||||
private void PipeRemoteSendCallback(IAsyncResult ar) | private void PipeRemoteSendCallback(IAsyncResult ar) | ||||
{ | { | ||||
if (_closed) return; | |||||
if (_closed) | |||||
{ | |||||
return; | |||||
} | |||||
try | try | ||||
{ | { | ||||
var container = (object[])ar.AsyncState; | |||||
var session = (AsyncSession)container[0]; | |||||
var bytesShouldSend = (int)container[1]; | |||||
object[] container = (object[])ar.AsyncState; | |||||
AsyncSession session = (AsyncSession)container[0]; | |||||
int bytesShouldSend = (int)container[1]; | |||||
int bytesSent = session.Remote.EndSend(ar); | int bytesSent = session.Remote.EndSend(ar); | ||||
if (bytesSent > 0) | if (bytesSent > 0) | ||||
@@ -944,8 +1030,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
@@ -954,11 +1039,11 @@ namespace Shadowsocks.Controller | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var container = (object[])ar.AsyncState; | |||||
var session = (AsyncSession)container[0]; | |||||
var bytesShouldSend = (int)container[1]; | |||||
var bytesSent = _connection.EndSend(ar); | |||||
var bytesRemaining = bytesShouldSend - bytesSent; | |||||
object[] container = (object[])ar.AsyncState; | |||||
AsyncSession session = (AsyncSession)container[0]; | |||||
int bytesShouldSend = (int)container[1]; | |||||
int bytesSent = _connection.EndSend(ar); | |||||
int bytesRemaining = bytesShouldSend - bytesSent; | |||||
if (bytesRemaining > 0) | if (bytesRemaining > 0) | ||||
{ | { | ||||
Logger.Info("reconstruct _remoteSendBuffer to re-send"); | Logger.Info("reconstruct _remoteSendBuffer to re-send"); | ||||
@@ -972,8 +1057,7 @@ namespace Shadowsocks.Controller | |||||
} | } | ||||
catch (Exception e) | catch (Exception e) | ||||
{ | { | ||||
Logger.LogUsefulException(e); | |||||
Close(); | |||||
ErrorClose(e); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -217,25 +217,25 @@ namespace Shadowsocks.Controller | |||||
StatisticsStrategyConfiguration.Save(configuration); | StatisticsStrategyConfiguration.Save(configuration); | ||||
} | } | ||||
public bool AskAddServerBySSURL(string ssURL) | |||||
{ | |||||
var dr = MessageBox.Show(I18N.GetString("Import from URL: {0} ?", ssURL), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo); | |||||
if (dr == DialogResult.Yes) | |||||
{ | |||||
public bool AskAddServerBySSURL(string ssURL) | |||||
{ | |||||
var dr = MessageBox.Show(I18N.GetString("Import from URL: {0} ?", ssURL), I18N.GetString("Shadowsocks"), MessageBoxButtons.YesNo); | |||||
if (dr == DialogResult.Yes) | |||||
{ | |||||
if (AddServerBySSURL(ssURL)) | if (AddServerBySSURL(ssURL)) | ||||
{ | { | ||||
MessageBox.Show(I18N.GetString("Successfully imported from {0}", ssURL)); | MessageBox.Show(I18N.GetString("Successfully imported from {0}", ssURL)); | ||||
return true; | return true; | ||||
} | |||||
} | |||||
else | else | ||||
{ | { | ||||
MessageBox.Show(I18N.GetString("Failed to import. Please check if the link is valid.")); | MessageBox.Show(I18N.GetString("Failed to import. Please check if the link is valid.")); | ||||
} | |||||
} | |||||
return false; | |||||
} | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
public bool AddServerBySSURL(string ssURL) | public bool AddServerBySSURL(string ssURL) | ||||
{ | { | ||||
try | try | ||||
@@ -486,29 +486,32 @@ namespace Shadowsocks.Controller | |||||
ConfigChanged?.Invoke(this, new EventArgs()); | ConfigChanged?.Invoke(this, new EventArgs()); | ||||
} | } | ||||
public void UpdateLatency(Server server, TimeSpan latency) | |||||
public void UpdateLatency(object sender, SSTCPConnectedEventArgs args) | |||||
{ | { | ||||
GetCurrentStrategy()?.UpdateLatency(args.server, args.latency); | |||||
if (_config.availabilityStatistics) | if (_config.availabilityStatistics) | ||||
{ | { | ||||
availabilityStatistics.UpdateLatency(server, (int)latency.TotalMilliseconds); | |||||
availabilityStatistics.UpdateLatency(args.server, (int)args.latency.TotalMilliseconds); | |||||
} | } | ||||
} | } | ||||
public void UpdateInboundCounter(Server server, long n) | |||||
public void UpdateInboundCounter(object sender, SSTransmitEventArgs args) | |||||
{ | { | ||||
Interlocked.Add(ref _inboundCounter, n); | |||||
GetCurrentStrategy()?.UpdateLastRead(args.server); | |||||
Interlocked.Add(ref _inboundCounter, args.length); | |||||
if (_config.availabilityStatistics) | if (_config.availabilityStatistics) | ||||
{ | { | ||||
availabilityStatistics.UpdateInboundCounter(server, n); | |||||
availabilityStatistics.UpdateInboundCounter(args.server, args.length); | |||||
} | } | ||||
} | } | ||||
public void UpdateOutboundCounter(Server server, long n) | |||||
public void UpdateOutboundCounter(object sender, SSTransmitEventArgs args) | |||||
{ | { | ||||
Interlocked.Add(ref _outboundCounter, n); | |||||
GetCurrentStrategy()?.UpdateLastWrite(args.server); | |||||
Interlocked.Add(ref _outboundCounter, args.length); | |||||
if (_config.availabilityStatistics) | if (_config.availabilityStatistics) | ||||
{ | { | ||||
availabilityStatistics.UpdateOutboundCounter(server, n); | |||||
availabilityStatistics.UpdateOutboundCounter(args.server, args.length); | |||||
} | } | ||||
} | } | ||||
@@ -552,6 +555,11 @@ namespace Shadowsocks.Controller | |||||
privoxyRunner.Start(_config); | privoxyRunner.Start(_config); | ||||
TCPRelay tcpRelay = new TCPRelay(this, _config); | TCPRelay tcpRelay = new TCPRelay(this, _config); | ||||
tcpRelay.OnConnected += UpdateLatency; | |||||
tcpRelay.OnInbound += UpdateInboundCounter; | |||||
tcpRelay.OnOutbound += UpdateOutboundCounter; | |||||
tcpRelay.OnFailed += (o, e) => GetCurrentStrategy()?.SetFailure(e.server); | |||||
UDPRelay udpRelay = new UDPRelay(this); | UDPRelay udpRelay = new UDPRelay(this); | ||||
List<Listener.IService> services = new List<Listener.IService> | List<Listener.IService> services = new List<Listener.IService> | ||||
{ | { | ||||
@@ -12,22 +12,22 @@ Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowsocks,Shadowso | |||||
,,,,,, | ,,,,,, | ||||
System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,Proxy système | System Proxy,Системный прокси-сервер,系统代理,系統代理,システムプロキシ,시스템 프록시,Proxy système | ||||
Disable,Отключен,禁用,禁用,無効,비활성화,Désactiver | Disable,Отключен,禁用,禁用,無効,비활성화,Désactiver | ||||
PAC,Сценарий настройки (PAC),PAC 模式,PAC 模式,PAC,PAC,PAC | |||||
PAC,Сценарий настройки (PAC),PAC 模式,PAC 模式,PAC,프록시 자동 구성 (PAC),PAC | |||||
Global,Для всей системы,全局模式,全局模式,全般,전역,Global | Global,Для всей системы,全局模式,全局模式,全般,전역,Global | ||||
Servers,Серверы,服务器,伺服器,サーバー,서버,Serveurs | Servers,Серверы,服务器,伺服器,サーバー,서버,Serveurs | ||||
Edit Servers...,Редактировать серверы…,编辑服务器...,編輯伺服器...,サーバーの編集...,서버 수정…,Éditer serveurs… | Edit Servers...,Редактировать серверы…,编辑服务器...,編輯伺服器...,サーバーの編集...,서버 수정…,Éditer serveurs… | ||||
Statistics Config...,Настройки статистики…,统计配置...,統計設定檔...,統計情報の設定...,통계 설정,Configuration des statistiques… | Statistics Config...,Настройки статистики…,统计配置...,統計設定檔...,統計情報の設定...,통계 설정,Configuration des statistiques… | ||||
Start on Boot,Автозагрузка,开机启动,開機啟動,システムと同時に起動,시스템 시작 시에 시작하기,Démarrage automatique | Start on Boot,Автозагрузка,开机启动,開機啟動,システムと同時に起動,시스템 시작 시에 시작하기,Démarrage automatique | ||||
Associate ss:// Links,Ассоциированный ss:// Ссылки,关联 ss:// 链接,關聯 ss:// 鏈接,,, | |||||
Associate ss:// Links,Ассоциированный ss:// Ссылки,关联 ss:// 链接,關聯 ss:// 鏈接,,ss:// 링크 연결, | |||||
Forward Proxy...,Прямой прокси…,正向代理设置...,正向 Proxy 設定...,フォワードプロキシの設定...,포워드 프록시,Forward-proxy… | Forward Proxy...,Прямой прокси…,正向代理设置...,正向 Proxy 設定...,フォワードプロキシの設定...,포워드 프록시,Forward-proxy… | ||||
Allow other Devices to connect,Общий доступ к подключению,允许其他设备连入,允許其他裝置連入,他のデバイスからの接続を許可する,다른 기기에서 연결 허용,Autoriser d'autres appareils à se connecter | Allow other Devices to connect,Общий доступ к подключению,允许其他设备连入,允許其他裝置連入,他のデバイスからの接続を許可する,다른 기기에서 연결 허용,Autoriser d'autres appareils à se connecter | ||||
Local PAC,Локальный PAC,使用本地 PAC,使用本機 PAC,ローカル PAC,로컬 PAC,PAC local | |||||
Online PAC,Удаленный PAC,使用在线 PAC,使用線上 PAC,オンライン PAC,온라인 PAC,PAC en ligne | |||||
Edit Local PAC File...,Редактировать локальный PAC…,编辑本地 PAC 文件...,編輯本機 PAC 檔案...,ローカル PAC ファイルの編集...,로컬 PAC 파일 수정,Modifier le fichier PAC local ... | |||||
Update Local PAC from Geosite,Обновить локальный PAC из Geosite,从 Geosite 更新本地 PAC,從 Geosite 更新本機 PAC,Geosite からローカル PAC を更新,Geosite에서 로컬 PAC 파일 업데이트,Mettre à jour le PAC local à partir de Geosite | |||||
Local PAC,Локальный PAC,使用本地 PAC,使用本機 PAC,ローカル PAC,로컬 프록시 자동 구성,PAC local | |||||
Online PAC,Удаленный PAC,使用在线 PAC,使用線上 PAC,オンライン PAC,온라인 프록시 자동 구성,PAC en ligne | |||||
Edit Local PAC File...,Редактировать локальный PAC…,编辑本地 PAC 文件...,編輯本機 PAC 檔案...,ローカル PAC ファイルの編集...,로컬 프록시 자동 구성 파일 수정,Modifier le fichier PAC local ... | |||||
Update Local PAC from Geosite,Обновить локальный PAC из Geosite,从 Geosite 更新本地 PAC,從 Geosite 更新本機 PAC,Geosite からローカル PAC を更新,Geosite에서 로컬 프록시 자동 구성 파일 업데이트,Mettre à jour le PAC local à partir de Geosite | |||||
Edit User Rule for Geosite...,Редактировать свои правила для Geosite,编辑 Geosite 的用户规则...,編輯 Geosite 的使用者規則...,ユーザールールの編集...,Geosite 사용자 수정,Modifier la règle utilisateur pour Geosite ... | Edit User Rule for Geosite...,Редактировать свои правила для Geosite,编辑 Geosite 的用户规则...,編輯 Geosite 的使用者規則...,ユーザールールの編集...,Geosite 사용자 수정,Modifier la règle utilisateur pour Geosite ... | ||||
Secure Local PAC,Безопасный URL локального PAC,保护本地 PAC,安全本機 PAC,ローカル PAC を保護,로컬 PAC 암호화,Sécuriser PAC local | |||||
Copy Local PAC URL,Копировать URL локального PAC,复制本地 PAC 网址,複製本機 PAC 網址,ローカル PAC URL をコピー,로컬 PAC 파일 URL 복사,Copier l'URL du PAC local | |||||
Secure Local PAC,Безопасный URL локального PAC,保护本地 PAC,安全本機 PAC,ローカル PAC を保護,로컬 프록시 자동 구성 파일 암호화,Sécuriser PAC local | |||||
Copy Local PAC URL,Копировать URL локального PAC,复制本地 PAC 网址,複製本機 PAC 網址,ローカル PAC URL をコピー,로컬 프록시 자동 구성 파일 URL 복사,Copier l'URL du PAC local | |||||
Share Server Config...,Поделиться конфигурацией сервера…,分享服务器配置...,分享伺服器設定檔...,サーバーの設定を共有...,서버 설정 공유,Partager la configuration du serveur ... | Share Server Config...,Поделиться конфигурацией сервера…,分享服务器配置...,分享伺服器設定檔...,サーバーの設定を共有...,서버 설정 공유,Partager la configuration du serveur ... | ||||
Scan QRCode from Screen...,Сканировать QRCode с экрана…,扫描屏幕上的二维码...,掃描螢幕上的 QR 碼...,画面から QR コードをスキャン...,화면에서 QR코드 스캔,Scanner le QRCode à partir de l'écran ... | Scan QRCode from Screen...,Сканировать QRCode с экрана…,扫描屏幕上的二维码...,掃描螢幕上的 QR 碼...,画面から QR コードをスキャン...,화면에서 QR코드 스캔,Scanner le QRCode à partir de l'écran ... | ||||
Import URL from Clipboard...,Импорт адреса из буфера обмена…,从剪贴板导入URL...,從剪貼簿匯入 URL...,クリップボードから URL をインポート...,클립보드에서 URL 가져오기…,Importer l'URL du presse-papiers ... | Import URL from Clipboard...,Импорт адреса из буфера обмена…,从剪贴板导入URL...,從剪貼簿匯入 URL...,クリップボードから URL をインポート...,클립보드에서 URL 가져오기…,Importer l'URL du presse-papiers ... | ||||
@@ -66,17 +66,17 @@ Plugin Options,Опции плагина,插件选项,外掛程式選項,プラ | |||||
Need Plugin Argument,Требуются аргументы,需要命令行参数,,,플러그인 인자가 필요함,Besoin d'un argument de plugin | Need Plugin Argument,Требуются аргументы,需要命令行参数,,,플러그인 인자가 필요함,Besoin d'un argument de plugin | ||||
Plugin Arguments,Аргументы,插件参数,外掛程式參數,プラグインの引数,플러그인 인자,Arguments du plugin | Plugin Arguments,Аргументы,插件参数,外掛程式參數,プラグインの引数,플러그인 인자,Arguments du plugin | ||||
Proxy Port,Порт прокси,代理端口,Proxy 連接埠,プロキシポート,프록시 포트,Port proxy | Proxy Port,Порт прокси,代理端口,Proxy 連接埠,プロキシポート,프록시 포트,Port proxy | ||||
Portable Mode,Переносимый режим,便携模式,便攜模式,ポータブルモード,포터블(Portable) 모드,Mode portable | |||||
Restart required,Требуется перезапуск программы,需要重新启动SS,需要重新啟動SS,再起動SSが必要,재시작 필요함,Redémarrage nécessaire | |||||
Portable Mode,Переносимый режим,便携模式,便攜模式,ポータブルモード,포터블 모드,Mode portable | |||||
Restart required,Требуется перезапуск программы,需要重新启动SS,需要重新啟動SS,再起動SSが必要,재시작이 필요합니다,Redémarrage nécessaire | |||||
Remarks,Примечания,备注,註解,付記,알림,Remarques | Remarks,Примечания,备注,註解,付記,알림,Remarques | ||||
Timeout(Sec),Таймаут(сек),超时(秒),逾時 (秒),タイムアウト (秒),시간초과(Timeout) (초),Délai d'attente(sec) | |||||
Timeout(Sec),Таймаут(сек),超时(秒),逾時 (秒),タイムアウト (秒),시간 초과 (초),Délai d'attente(sec) | |||||
OK,ОК,确定,確定,OK,확인,OK | OK,ОК,确定,確定,OK,확인,OK | ||||
Cancel,Отмена,取消,取消,キャンセル,취소,Annuler | Cancel,Отмена,取消,取消,キャンセル,취소,Annuler | ||||
Apply,Применить,应用,應用,適用,적용,Appliquer | Apply,Применить,应用,應用,適用,적용,Appliquer | ||||
New server,Новый сервер,未配置的服务器,新伺服器,新規サーバー,새 서버,Nouveau serveur | New server,Новый сервер,未配置的服务器,新伺服器,新規サーバー,새 서버,Nouveau serveur | ||||
Move &Up,Выше,上移(&U),上移 (&U),上に移動 (&U),위로 (&U),Monter | Move &Up,Выше,上移(&U),上移 (&U),上に移動 (&U),위로 (&U),Monter | ||||
Move D&own,Ниже,下移(&O),下移 (&O),下に移動 (&O),아래로 (&O),Descendre | Move D&own,Ниже,下移(&O),下移 (&O),下に移動 (&O),아래로 (&O),Descendre | ||||
deprecated,Устаревшее,不推荐,不推薦,非推奨,폐기됨(deprecated),Obsolète | |||||
deprecated,Устаревшее,不推荐,不推薦,非推奨,더 이상 사용되지 않음,Obsolète | |||||
"Encryption method {0} not exist, will replace with {1}",,加密方法{0}不存在,将使用{1}代替,,,{0} 암호화 방식이 존재하지 않으므로 {1}로 대체될 것입니다.,"Méthode de chiffrement {0} n'existe pas, sera remplacée par {1}" | "Encryption method {0} not exist, will replace with {1}",,加密方法{0}不存在,将使用{1}代替,,,{0} 암호화 방식이 존재하지 않으므로 {1}로 대체될 것입니다.,"Méthode de chiffrement {0} n'existe pas, sera remplacée par {1}" | ||||
,,,,,, | ,,,,,, | ||||
#Statistics Config,,,,,, | #Statistics Config,,,,,, | ||||
@@ -116,8 +116,8 @@ Use Proxy,Использовать прокси,使用代理,使用 Proxy,プロ | |||||
Proxy Type,Тип прокси,代理类型,Proxy 類型,プロキシの種類,프록시 종류,Type de proxy | Proxy Type,Тип прокси,代理类型,Proxy 類型,プロキシの種類,프록시 종류,Type de proxy | ||||
Proxy Addr,Адрес прокси,代理地址,Proxy 位址,プロキシアドレス,프록시 주소,Adresse de proxy | Proxy Addr,Адрес прокси,代理地址,Proxy 位址,プロキシアドレス,프록시 주소,Adresse de proxy | ||||
Proxy Port,Порт прокси,代理端口,Proxy 連接埠,プロキシポート,프록시 포트,Port de proxy | Proxy Port,Порт прокси,代理端口,Proxy 連接埠,プロキシポート,프록시 포트,Port de proxy | ||||
"If server has a plugin, proxy will not be used","Если сервер использует плагины, прокси НЕ будет использоваться",若服务器含有插件,代理将不被使用,若伺服器含有外掛程式,Proxy 將不被使用,サーバーにプラグインがある場合、プロキシは利用されません,"만약 서버가 플러그인이 있다면, 프록시는용되지 않을 것입니다.","Si le serveur a un plugin, le proxy ne sera pas utilisé" | |||||
Use Auth,Требуется авторизация,使用认证,使用認證,認証を利用する,서버 증명(Auth) 사용,Utiliser l'authentification | |||||
"If server has a plugin, proxy will not be used","Если сервер использует плагины, прокси НЕ будет использоваться",若服务器含有插件,代理将不被使用,若伺服器含有外掛程式,Proxy 將不被使用,サーバーにプラグインがある場合、プロキシは利用されません,서버에 플러그인이 설치 되어 있는 경우 프록시를 사용할 수 없습니다.,"Si le serveur a un plugin, le proxy ne sera pas utilisé" | |||||
Use Auth,Требуется авторизация,使用认证,使用認證,認証を利用する,서버 인증 사용,Utiliser l'authentification | |||||
User Name,Пользователь,用户名,認證用戶,認証ユーザ,사용자 이름,Nom d'utilisateur | User Name,Пользователь,用户名,認證用戶,認証ユーザ,사용자 이름,Nom d'utilisateur | ||||
Auth Pwd,Пароль,认证密码,認證口令,認証パスワード,비밀번호,Mot de passe d'authentification | Auth Pwd,Пароль,认证密码,認證口令,認証パスワード,비밀번호,Mot de passe d'authentification | ||||
,,,,,, | ,,,,,, | ||||
@@ -142,9 +142,9 @@ QRCode and URL,QRCode и URL,二维码与 URL,QR 碼與 URL,QR コードと URL, | |||||
,,,,,, | ,,,,,, | ||||
# PAC Url Form,,,,,, | # PAC Url Form,,,,,, | ||||
,,,,,, | ,,,,,, | ||||
Edit Online PAC URL,Изменение URL удаленного PAC,编辑在线 PAC 网址,編輯線上 PAC 網址,オンライン PAC URL の編集,온라인 PAC URL 수정,Modifier l'URL du PAC en ligne | |||||
Edit Online PAC URL...,Редактировать URL удаленного PAC…,编辑在线 PAC 网址...,編輯線上 PAC 網址...,オンライン PAC URL の編集...,온라인 PAC URL 수정…,Modifier l'URL du PAC en ligne ... | |||||
Please input PAC Url,Введите URL адрес для PAC-файла,请输入 PAC 网址,請輸入 PAC 網址,PAC URLを入力して下さい,PAC URL을 입력하세요,Veuillez saisir l'URL PAC | |||||
Edit Online PAC URL,Изменение URL удаленного PAC,编辑在线 PAC 网址,編輯線上 PAC 網址,オンライン PAC URL の編集,온라인 프록시 자동 구성 URL 수정,Modifier l'URL du PAC en ligne | |||||
Edit Online PAC URL...,Редактировать URL удаленного PAC…,编辑在线 PAC 网址...,編輯線上 PAC 網址...,オンライン PAC URL の編集...,온라인 프록시 자동 구성 URL 수정…,Modifier l'URL du PAC en ligne ... | |||||
Please input PAC Url,Введите URL адрес для PAC-файла,请输入 PAC 网址,請輸入 PAC 網址,PAC URLを入力して下さい,프록시 자동 구성 URL을 입력하세요,Veuillez saisir l'URL PAC | |||||
,,,,,, | ,,,,,, | ||||
# HotkeySettings Form,,,,,, | # HotkeySettings Form,,,,,, | ||||
,,,,,, | ,,,,,, | ||||
@@ -164,7 +164,7 @@ Port {0} already in use,Порт {0} уже используется,端口 {0} | |||||
Port {0} is reserved by system,Порт {0} зарезервирован системой,端口 {0} 是系统保留端口,連接埠號碼 {0} 由系統保留, ポート番号 {0} はシステムによって予約されています,{0}번 포트는 시스템에서 사용 중입니다.,Port {0} réservé par le système | Port {0} is reserved by system,Порт {0} зарезервирован системой,端口 {0} 是系统保留端口,連接埠號碼 {0} 由系統保留, ポート番号 {0} はシステムによって予約されています,{0}번 포트는 시스템에서 사용 중입니다.,Port {0} réservé par le système | ||||
Invalid server address,Неверный адрес сервера,非法服务器地址,無效伺服器位址,サーバーアドレスが無効です。,올바르지 않은 서버 주소입니다.,Adresse de serveur non valide | Invalid server address,Неверный адрес сервера,非法服务器地址,無效伺服器位址,サーバーアドレスが無効です。,올바르지 않은 서버 주소입니다.,Adresse de serveur non valide | ||||
Illegal port number format,Неверный числовой формат порта,非法端口格式,無效連接埠號碼格式,ポート番号のフォーマットが無効です。,올바르지 않은 포트 번호 형식입니다.,Format de numéro de port illégal | Illegal port number format,Неверный числовой формат порта,非法端口格式,無效連接埠號碼格式,ポート番号のフォーマットが無効です。,올바르지 않은 포트 번호 형식입니다.,Format de numéro de port illégal | ||||
Illegal timeout format,Неверный формат таймаута,非法超时格式,無效逾時格式,タイムアウト値のフォーマットが無効です。,올바르지 않은 시간초과(Timeout) 형식입니다.,Format de délai d'attente illégal | |||||
Illegal timeout format,Неверный формат таймаута,非法超时格式,無效逾時格式,タイムアウト値のフォーマットが無効です。,올바르지 않은 시간 초과 형식입니다.,Format de délai d'attente illégal | |||||
Server IP can not be blank,IP-адрес сервера не может быть пустым,服务器 IP 不能为空,伺服器 IP 不能為空,サーバー IP が指定されていません。,서버 IP는 비어있으면 안됩니다.,L'adresse IP du serveur ne peut pas être vide | Server IP can not be blank,IP-адрес сервера не может быть пустым,服务器 IP 不能为空,伺服器 IP 不能為空,サーバー IP が指定されていません。,서버 IP는 비어있으면 안됩니다.,L'adresse IP du serveur ne peut pas être vide | ||||
Password can not be blank,Пароль не может быть пустым,密码不能为空,密碼不能為空,パスワードが指定されていません。,비밀번호는 비어있으면 안됩니다.,Le mot de passe ne peut pas être vide | Password can not be blank,Пароль не может быть пустым,密码不能为空,密碼不能為空,パスワードが指定されていません。,비밀번호는 비어있으면 안됩니다.,Le mot de passe ne peut pas être vide | ||||
Port out of range,Порт выходит за допустимый диапазон,端口超出范围,連接埠號碼超出範圍,ポート番号は範囲外です。,올바른 포트 범위가 아닙니다.,Port hors de portée | Port out of range,Порт выходит за допустимый диапазон,端口超出范围,連接埠號碼超出範圍,ポート番号は範囲外です。,올바른 포트 범위가 아닙니다.,Port hors de portée | ||||
@@ -176,8 +176,8 @@ Shadowsocks is here,Shadowsocks находится здесь,Shadowsocks 在这 | |||||
You can turn on/off Shadowsocks in the context menu,Вы можете управлять Shadowsocks из контекстного меню,可以在右键菜单中开关 Shadowsocks,可以在右鍵選項單中開關 Shadowsocks,コンテキストメニューを使って、Shadowsocks を有効または無効にすることができます。,프로그램 메뉴에서 Shadowsocks를 끄고 켤 수 있습니다.,Vous pouvez activer / désactiver Shadowsocks dans le menu contextuel | You can turn on/off Shadowsocks in the context menu,Вы можете управлять Shadowsocks из контекстного меню,可以在右键菜单中开关 Shadowsocks,可以在右鍵選項單中開關 Shadowsocks,コンテキストメニューを使って、Shadowsocks を有効または無効にすることができます。,프로그램 메뉴에서 Shadowsocks를 끄고 켤 수 있습니다.,Vous pouvez activer / désactiver Shadowsocks dans le menu contextuel | ||||
System Proxy Enabled,Системный прокси включен,系统代理已启用,系統 Proxy 已啟用,システム プロキシが有効です。,시스템 프록시가 활성화되었습니다.,Proxy système activé | System Proxy Enabled,Системный прокси включен,系统代理已启用,系統 Proxy 已啟用,システム プロキシが有効です。,시스템 프록시가 활성화되었습니다.,Proxy système activé | ||||
System Proxy Disabled,Системный прокси отключен,系统代理未启用,系統 Proxy 未啟用,システム プロキシが無効です。,시스템 프록시가 비활성화되었습니다.,Proxy système désactivé | System Proxy Disabled,Системный прокси отключен,系统代理未启用,系統 Proxy 未啟用,システム プロキシが無効です。,시스템 프록시가 비활성화되었습니다.,Proxy système désactivé | ||||
Failed to update PAC file ,Не удалось обновить PAC файл,更新 PAC 文件失败,更新 PAC 檔案失敗,PAC の更新に失敗しました。,PAC 파일을 업데이트하는데 실패했습니다.,Impossible de mettre à jour le fichier PAC | |||||
PAC updated,PAC файл обновлен,更新 PAC 成功,更新 PAC 成功,PAC を更新しました。,PAC 파일이 업데이트되었습니다.,PAC mis à jour | |||||
Failed to update PAC file ,Не удалось обновить PAC файл,更新 PAC 文件失败,更新 PAC 檔案失敗,PAC の更新に失敗しました。,프록시 자동 구성 파일을 업데이트하는데 실패했습니다.,Impossible de mettre à jour le fichier PAC | |||||
PAC updated,PAC файл обновлен,更新 PAC 成功,更新 PAC 成功,PAC を更新しました。,프록시 자동 구성 파일이 업데이트되었습니다.,PAC mis à jour | |||||
No updates found. Please report to Geosite if you have problems with it.,Обновлений не найдено. Сообщите авторам Geosite если у вас возникли проблемы.,未发现更新。如有问题请提交给 Geosite。,未發現更新。如有問題請報告至 Geosite。,お使いのバージョンは最新です。問題がある場合は、Geosite に報告して下さい。,사용 가능한 업데이트를 찾지 못했습니다. 문제가 있다면 Geosite로 전송해주세요.,Aucune mise à jour trouvée. Veuillez signaler à Geosite si vous avez des problèmes concernant. | No updates found. Please report to Geosite if you have problems with it.,Обновлений не найдено. Сообщите авторам Geosite если у вас возникли проблемы.,未发现更新。如有问题请提交给 Geosite。,未發現更新。如有問題請報告至 Geosite。,お使いのバージョンは最新です。問題がある場合は、Geosite に報告して下さい。,사용 가능한 업데이트를 찾지 못했습니다. 문제가 있다면 Geosite로 전송해주세요.,Aucune mise à jour trouvée. Veuillez signaler à Geosite si vous avez des problèmes concernant. | ||||
No QRCode found. Try to zoom in or move it to the center of the screen.,QRCode не обнаружен. Попробуйте увеличить изображение или переместить его в центр экрана.,未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置,未發現 QR 碼,嘗試把它放大或移動到靠近熒幕中間的位置,QR コードが見つかりませんでした。コードを大きくするか、画面の中央に移動して下さい。,QR코드를 찾을 수 없습니다. 가운데로 화면을 이동시키거나 확대해보세요.,Aucun QRCode trouvé. Essayez de zoomer ou de le déplacer vers le centre de l'écran. | No QRCode found. Try to zoom in or move it to the center of the screen.,QRCode не обнаружен. Попробуйте увеличить изображение или переместить его в центр экрана.,未发现二维码,尝试把它放大或移动到靠近屏幕中间的位置,未發現 QR 碼,嘗試把它放大或移動到靠近熒幕中間的位置,QR コードが見つかりませんでした。コードを大きくするか、画面の中央に移動して下さい。,QR코드를 찾을 수 없습니다. 가운데로 화면을 이동시키거나 확대해보세요.,Aucun QRCode trouvé. Essayez de zoomer ou de le déplacer vers le centre de l'écran. | ||||
Shadowsocks is already running.,Shadowsocks уже запущен.,Shadowsocks 已经在运行。,Shadowsocks 已經在執行。,Shadowsocks 実行中,Shadowsocks가 이미 실행 중입니다.,Shadowsocks est déjà en cours d'exécution. | Shadowsocks is already running.,Shadowsocks уже запущен.,Shadowsocks 已经在运行。,Shadowsocks 已經在執行。,Shadowsocks 実行中,Shadowsocks가 이미 실행 중입니다.,Shadowsocks est déjà en cours d'exécution. | ||||
@@ -190,25 +190,25 @@ Successfully imported from {0},Успешно импортировано из {0 | |||||
Failed to import. Please check if the link is valid.,,导入失败,请检查链接是否有效。,導入失敗,請檢查鏈接是否有效。,,, | Failed to import. Please check if the link is valid.,,导入失败,请检查链接是否有效。,導入失敗,請檢查鏈接是否有效。,,, | ||||
System Proxy On: ,Системный прокси:,系统代理已启用:,系統 Proxy 已啟用:,システム プロキシが有効:,시스템 프록시 활성화됨: ,Proxy système activé: | System Proxy On: ,Системный прокси:,系统代理已启用:,系統 Proxy 已啟用:,システム プロキシが有効:,시스템 프록시 활성화됨: ,Proxy système activé: | ||||
Running: Port {0},Запущен на порту {0},正在运行:端口 {0},正在執行:連接埠號碼 {0},実行中:ポート {0},실행 중: 포트 {0}번,En cours d'exécution: port {0} | Running: Port {0},Запущен на порту {0},正在运行:端口 {0},正在執行:連接埠號碼 {0},実行中:ポート {0},실행 중: 포트 {0}번,En cours d'exécution: port {0} | ||||
"Unexpected error, shadowsocks will exit. Please report to","Непредвиденная ошибка, пожалуйста сообщите на",非预期错误,Shadowsocks将退出。请提交此错误到,非預期錯誤,Shadowsocks 將結束。請報告此錯誤至,予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:,알 수 없는 오류로 Shadowsocks가 종료될 것입니다. 오류를 제보해주세요:,Shadowsocks va quitter en présence d/érreur inattendue. Veuillez signaler à | |||||
"Unsupported operating system, use Windows Vista at least.","Операционная система не поддерживается, минимальные системные требования: Windows Vista или выше.",不支持的操作系统版本,最低需求为Windows Vista。,不支援的作業系統版本,最低需求為 Windows Vista。,お使いの OS はサポートされていません。Windows Vista 以降の OS で実行して下さい。,"지원하지 않는 운영체제입니다, 최소한 Windows Vista가 필요합니다.","Système d'exploitation incompatible, veuillez utiliser Windows Vista ou ultérieure." | |||||
"Unsupported .NET Framework, please update to {0} or later.","Версия .NET Framework не поддерживается, минимальные системные требования: {0} или выше.",当前 .NET Framework 版本过低,请升级至{0}或更新版本。,目前 .NET Framework 版本過低,最低需求為{0}。,お使いの .NET Framework はサポートされていません。{0} 以降のバンジョーをインストールして下さい。,"지원하지 않는 .NET 프레임워크입니다, {0} 또는 상위 버전으로 업데이트해주세요.",".NET Framework incompatible, veuillez mettre à jour vers {0} ou ultérieure." | |||||
"Unexpected error, shadowsocks will exit. Please report to","Непредвиденная ошибка, пожалуйста сообщите на",非预期错误,Shadowsocks将退出。请提交此错误到,非預期錯誤,Shadowsocks 將結束。請報告此錯誤至,予想外のエラーが発生したため、Shadowsocks を終了します。詳しくは下記までお問い合わせ下さい:,알 수 없는 오류로 Shadowsocks가 종료될 것입니다. 오류를 여기로 제보해주세요:,Shadowsocks va quitter en présence d/érreur inattendue. Veuillez signaler à | |||||
"Unsupported operating system, use Windows Vista at least.","Операционная система не поддерживается, минимальные системные требования: Windows Vista или выше.",不支持的操作系统版本,最低需求为Windows Vista。,不支援的作業系統版本,最低需求為 Windows Vista。,お使いの OS はサポートされていません。Windows Vista 以降の OS で実行して下さい。,지원하지 않는 운영체제입니다. 최소 Windows Vista가 필요합니다.,"Système d'exploitation incompatible, veuillez utiliser Windows Vista ou ultérieure." | |||||
"Unsupported .NET Framework, please update to {0} or later.","Версия .NET Framework не поддерживается, минимальные системные требования: {0} или выше.",当前 .NET Framework 版本过低,请升级至{0}或更新版本。,目前 .NET Framework 版本過低,最低需求為{0}。,お使いの .NET Framework はサポートされていません。{0} 以降のバンジョーをインストールして下さい。,지원하지 않는 .NET 프레임워크입니다. {0} 또는 상위 버전으로 업데이트해주세요.,".NET Framework incompatible, veuillez mettre à jour vers {0} ou ultérieure." | |||||
Proxy request failed,Не удалось выполнить запрос,代理请求失败,Proxy 要求失敗,プロキシ要求が失敗しました。,프록시 요청에 실패했습니다.,Échec de la demande de proxy | Proxy request failed,Не удалось выполнить запрос,代理请求失败,Proxy 要求失敗,プロキシ要求が失敗しました。,프록시 요청에 실패했습니다.,Échec de la demande de proxy | ||||
Proxy handshake failed,Не удалось выполнить хэндшейк,代理握手失败,Proxy 交握失敗,プロキシ ハンドシェイクに失敗しました。,프록시 핸드쉐이크에 실패했습니다.,Échec de la prise de contact par proxy | Proxy handshake failed,Не удалось выполнить хэндшейк,代理握手失败,Proxy 交握失敗,プロキシ ハンドシェイクに失敗しました。,프록시 핸드쉐이크에 실패했습니다.,Échec de la prise de contact par proxy | ||||
Register hotkey failed,Не удалось применить настройки горячих клавиш,注册快捷键失败,註冊快速鍵失敗,ホットキーの登錄に失敗しました。,단축키 등록에 실패했습니다.,Échec de l'enregistrement du raccourci clavier | Register hotkey failed,Не удалось применить настройки горячих клавиш,注册快捷键失败,註冊快速鍵失敗,ホットキーの登錄に失敗しました。,단축키 등록에 실패했습니다.,Échec de l'enregistrement du raccourci clavier | ||||
Cannot parse hotkey: {0},Не удалось распознать следующие горячие клавиши: {0},解析快捷键失败: {0},剖析快速鍵失敗: {0},ホットキーを解析できません: {0},단축키를 해석할 수 없습니다: {0},Impossible d'analyser le raccourci clavier: {0} | Cannot parse hotkey: {0},Не удалось распознать следующие горячие клавиши: {0},解析快捷键失败: {0},剖析快速鍵失敗: {0},ホットキーを解析できません: {0},단축키를 해석할 수 없습니다: {0},Impossible d'analyser le raccourci clavier: {0} | ||||
"Timeout is invalid, it should not exceed {0}",Таймаут не может превышать значение {0},超时无效,不应超过 {0},逾時無效,不應超過 {0},タイムアウト値が無効です。{0} 以下の値を指定して下さい。,"올바르지 않은 시간초과(Timeout) 설정입니다, {0}을 초과하지 않아야 합니다.","Le délai d'attente invalide, il ne doit pas dépasser {0}" | |||||
"Timeout is invalid, it should not exceed {0}",Таймаут не может превышать значение {0},超时无效,不应超过 {0},逾時無效,不應超過 {0},タイムアウト値が無効です。{0} 以下の値を指定して下さい。,올바르지 않은 시간 초과 설정입니다. {0}을 초과하지 않아야 합니다.,"Le délai d'attente invalide, il ne doit pas dépasser {0}" | |||||
Cannot find the plugin program file,Файл плагина не найден,找不到插件程序文件,找不到外掛程式文件,,플러그인 프로그램 파일을 찾을 수 없습니다.,Impossible de trouver le fichier du programme du plugin | Cannot find the plugin program file,Файл плагина не найден,找不到插件程序文件,找不到外掛程式文件,,플러그인 프로그램 파일을 찾을 수 없습니다.,Impossible de trouver le fichier du programme du plugin | ||||
,,,,,, | ,,,,,, | ||||
Operation failure,Операция завершилась неудачей,操作失败,,,작업에 실패했습니다.,Operation failure | Operation failure,Операция завершилась неудачей,操作失败,,,작업에 실패했습니다.,Operation failure | ||||
Auto save failed,Автоматическое сохранение не удалось,自动保存失败,,,자동 저장에 실패했습니다.,Échec de l'enregistrement automatique | Auto save failed,Автоматическое сохранение не удалось,自动保存失败,,,자동 저장에 실패했습니다.,Échec de l'enregistrement automatique | ||||
Whether to discard unconfigured servers,Внесенные изменения будут утеряны,是否丢弃未配置的服务器,,,완전하지 않은 서버 설정 변경 사항을 폐기하시겠습니까?,Eliminer les serveurs non configurés ou non | |||||
"Invalid server address, Cannot automatically save or discard changes",Неверный адрес сервера. Невозможно сохранить или отменить изменения,非法服务器地址,无法自动保存,是否丢弃修改,,,"서버 주소가 올바르지 않아 자동저장할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Adresse de serveur invalide, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
"Illegal port number format, Cannot automatically save or discard changes",Неверный числовой адрес порта. Невозможно сохранить или отменить изменения,非法端口格式,无法自动保存,是否丢弃修改,,,"포트 번호가 올바르지 않아 자동저장할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Format de numéro de port illégal, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
"Password can not be blank, Cannot automatically save or discard changes",Пароль не может быть пустым. Невозможно сохранить или отменить изменения,密码不能为空,无法自动保存,是否丢弃修改,,,"비밀번호가 비어있어 자동저장할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Le mot de passe ne peut pas être vide, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
"Illegal timeout format, Cannot automatically save or discard changes",Неверный формат таймаута. Невозможно сохранить или отменить изменения,非法超时格式,无法自动保存,是否丢弃修改,,,"시간초과(Timeout) 형식이 올바르지 않아 자동저장할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Format de délai d'attente illégal, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
Whether to discard unconfigured servers,Внесенные изменения будут утеряны,是否丢弃未配置的服务器,,,구성되지 않은 서버 설정 변경 사항을 폐기하시겠습니까?,Eliminer les serveurs non configurés ou non | |||||
"Invalid server address, Cannot automatically save or discard changes",Неверный адрес сервера. Невозможно сохранить или отменить изменения,非法服务器地址,无法自动保存,是否丢弃修改,,,"서버 주소가 올바르지 않아 자동 저장 할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Adresse de serveur invalide, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
"Illegal port number format, Cannot automatically save or discard changes",Неверный числовой адрес порта. Невозможно сохранить или отменить изменения,非法端口格式,无法自动保存,是否丢弃修改,,,"포트 번호가 올바르지 않아 자동 저장 할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Format de numéro de port illégal, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
"Password can not be blank, Cannot automatically save or discard changes",Пароль не может быть пустым. Невозможно сохранить или отменить изменения,密码不能为空,无法自动保存,是否丢弃修改,,,"비밀번호를 입력하지 않아 자동 저장 할 수 없습니다, 변경 사항을 폐기하시겠습니까?","Le mot de passe ne peut pas être vide, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
"Illegal timeout format, Cannot automatically save or discard changes",Неверный формат таймаута. Невозможно сохранить или отменить изменения,非法超时格式,无法自动保存,是否丢弃修改,,,시간 초과 형식이 올바르지 않아 자동 저장 할 수 없습니다. 변경 사항을 폐기하시겠습니까?,"Format de délai d'attente illégal, impossible d'enregistrer ou d'annuler automatiquement les modifications" | |||||
,,,,,, | ,,,,,, | ||||
"Error occured when process proxy setting, do you want reset current setting and retry?",Произошла ошибка при обработке настроек. Хотите сбросить текущие настройки и попробовать снова?,处理代理设置时发生错误,是否重置当前代理设置并重试?,,,프록시 설정을 처리하는데에 오류가 발생했습니다. 현재 설정을 폐기하고 다시시도하시겠습니까?,Une erreur s'est produite lors du processus de configuration du proxy. Voulez-vous réinitialiser le paramètre actuel et réessayer? | |||||
"Error occured when process proxy setting, do you want reset current setting and retry?",Произошла ошибка при обработке настроек. Хотите сбросить текущие настройки и попробовать снова?,处理代理设置时发生错误,是否重置当前代理设置并重试?,,,프록시 설정을 처리하는데에 오류가 발생했습니다. 현재 설정을 폐기하고 다시 시도하시겠습니까?,Une erreur s'est produite lors du processus de configuration du proxy. Voulez-vous réinitialiser le paramètre actuel et réessayer? | |||||
"Unrecoverable proxy setting error occured, see log for detail","Произошла серьезная ошибка, подробности можно узнать в журналах",发生不可恢复的代理设置错误,查看日志以取得详情,,,복구 불가능한 프록시 설정 오류가 발생했습니다. 자세한 정보는 로그를 참조하세요.,"Une erreur de paramètre de proxy irrécupérable s'est produite, consultez le journal pour plus de détails" | "Unrecoverable proxy setting error occured, see log for detail","Произошла серьезная ошибка, подробности можно узнать в журналах",发生不可恢复的代理设置错误,查看日志以取得详情,,,복구 불가능한 프록시 설정 오류가 발생했습니다. 자세한 정보는 로그를 참조하세요.,"Une erreur de paramètre de proxy irrécupérable s'est produite, consultez le journal pour plus de détails" | ||||
Auth user can not be blank,Пользователь не может быть пустым,认证用户不能为空,認證用戶不能為空,認証ユーザが指定されていません。,증명 정보의 사용자 이름은 비어있을 수 없습니다.,L'utilisateur d'authentification ne peut pas être vide | |||||
Auth pwd can not be blank,Пароль не может быть пустым,认证密码不能为空,認證口令不能為空,認証パスワードが指定されていません。,증명 정보의 비밀번호는 비어있을 수 없습니다.,Le mot de passe d'authentification ne peut pas être vide | |||||
Auth user can not be blank,Пользователь не может быть пустым,认证用户不能为空,認證用戶不能為空,認証ユーザが指定されていません。,인증 정보의 사용자 이름은 비어있을 수 없습니다.,L'utilisateur d'authentification ne peut pas être vide | |||||
Auth pwd can not be blank,Пароль не может быть пустым,认证密码不能为空,認證口令不能為空,認証パスワードが指定されていません。,인증 정보의 비밀번호는 비어있을 수 없습니다.,Le mot de passe d'authentification ne peut pas être vide |