@@ -1,10 +1,10 @@ | |||
using Shadowsocks.Model; | |||
using System; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Net.NetworkInformation; | |||
using System.Net.Sockets; | |||
using System.Text; | |||
using Shadowsocks.Model; | |||
namespace Shadowsocks.Controller | |||
{ | |||
@@ -79,9 +79,7 @@ namespace Shadowsocks.Controller | |||
// Start an asynchronous socket to listen for connections. | |||
Logging.Info("Shadowsocks started"); | |||
_tcpSocket.BeginAccept( | |||
new AsyncCallback(AcceptCallback), | |||
_tcpSocket); | |||
_tcpSocket.BeginAccept(new AsyncCallback(AcceptCallback), _tcpSocket); | |||
UDPState udpState = new UDPState(); | |||
_udpSocket.BeginReceiveFrom(udpState.buffer, 0, udpState.buffer.Length, 0, ref udpState.remoteEndPoint, new AsyncCallback(RecvFromCallback), udpState); | |||
} | |||
@@ -1,8 +1,6 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Text; | |||
namespace Shadowsocks.Controller | |||
{ | |||
@@ -1,31 +1,30 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Net.Sockets; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Timers; | |||
using Shadowsocks.Controller.Strategy; | |||
using Shadowsocks.Encryption; | |||
using Shadowsocks.Model; | |||
using Shadowsocks.Controller.Strategy; | |||
using System.Timers; | |||
namespace Shadowsocks.Controller | |||
{ | |||
class TCPRelay : Listener.Service | |||
{ | |||
private ShadowsocksController _controller; | |||
private DateTime _lastSweepTime; | |||
public ISet<Handler> Handlers | |||
public ISet<TCPHandler> Handlers | |||
{ | |||
get; set; | |||
} | |||
public TCPRelay(ShadowsocksController controller) | |||
{ | |||
this._controller = controller; | |||
this.Handlers = new HashSet<Handler>(); | |||
this._lastSweepTime = DateTime.Now; | |||
_controller = controller; | |||
Handlers = new HashSet<TCPHandler>(); | |||
_lastSweepTime = DateTime.Now; | |||
} | |||
public bool Handle(byte[] firstPacket, int length, Socket socket, object state) | |||
@@ -39,22 +38,21 @@ namespace Shadowsocks.Controller | |||
return false; | |||
} | |||
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); | |||
Handler handler = new Handler(); | |||
TCPHandler handler = new TCPHandler(this); | |||
handler.connection = socket; | |||
handler.controller = _controller; | |||
handler.relay = this; | |||
handler.Start(firstPacket, length); | |||
IList<Handler> handlersToClose = new List<Handler>(); | |||
lock (this.Handlers) | |||
IList<TCPHandler> handlersToClose = new List<TCPHandler>(); | |||
lock (Handlers) | |||
{ | |||
this.Handlers.Add(handler); | |||
Logging.Debug($"TCP connections: {Handlers.Count}"); | |||
Handlers.Add(handler); | |||
DateTime now = DateTime.Now; | |||
if (now - _lastSweepTime > TimeSpan.FromSeconds(1)) | |||
{ | |||
_lastSweepTime = now; | |||
foreach (Handler handler1 in this.Handlers) | |||
foreach (TCPHandler handler1 in Handlers) | |||
{ | |||
if (now - handler1.lastActivity > TimeSpan.FromSeconds(900)) | |||
{ | |||
@@ -63,18 +61,28 @@ namespace Shadowsocks.Controller | |||
} | |||
} | |||
} | |||
foreach (Handler handler1 in handlersToClose) | |||
foreach (TCPHandler handler1 in handlersToClose) | |||
{ | |||
Logging.Debug("Closing timed out TCP connection."); | |||
handler1.Close(); | |||
} | |||
return true; | |||
} | |||
public void UpdateInboundCounter(long n) | |||
{ | |||
_controller.UpdateInboundCounter(n); | |||
} | |||
public void UpdateOutboundCounter(long n) | |||
{ | |||
_controller.UpdateOutboundCounter(n); | |||
} | |||
} | |||
class Handler | |||
class TCPHandler | |||
{ | |||
//public Encryptor encryptor; | |||
// public Encryptor encryptor; | |||
public IEncryptor encryptor; | |||
public Server server; | |||
// Client socket. | |||
@@ -85,6 +93,7 @@ namespace Shadowsocks.Controller | |||
public DateTime lastActivity; | |||
private const int maxRetry = 4; | |||
private int retryCount = 0; | |||
private bool connected; | |||
@@ -117,6 +126,12 @@ namespace Shadowsocks.Controller | |||
private object decryptionLock = new object(); | |||
private DateTime _startConnectTime; | |||
private TCPRelay tcprelay; // TODO: tcprelay ?= relay | |||
public TCPHandler(TCPRelay tcprelay) | |||
{ | |||
this.tcprelay = tcprelay; | |||
} | |||
public void CreateRemote() | |||
{ | |||
@@ -125,23 +140,23 @@ namespace Shadowsocks.Controller | |||
{ | |||
throw new ArgumentException("No server configured"); | |||
} | |||
this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false); | |||
encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.auth, false); | |||
this.server = server; | |||
} | |||
public void Start(byte[] firstPacket, int length) | |||
{ | |||
this._firstPacket = firstPacket; | |||
this._firstPacketLength = length; | |||
this.HandshakeReceive(); | |||
this.lastActivity = DateTime.Now; | |||
_firstPacket = firstPacket; | |||
_firstPacketLength = length; | |||
HandshakeReceive(); | |||
lastActivity = DateTime.Now; | |||
} | |||
private void CheckClose() | |||
{ | |||
if (connectionShutdown && remoteShutdown) | |||
{ | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -149,7 +164,6 @@ namespace Shadowsocks.Controller | |||
{ | |||
lock (relay.Handlers) | |||
{ | |||
Logging.Debug($"TCP connections: {relay.Handlers.Count}"); | |||
relay.Handlers.Remove(this); | |||
} | |||
lock (this) | |||
@@ -215,18 +229,17 @@ namespace Shadowsocks.Controller | |||
response = new byte[] { 0, 91 }; | |||
Logging.Error("socks 5 protocol error"); | |||
} | |||
Logging.Debug($"======Send Local Port, size:" + response.Length); | |||
connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(HandshakeSendCallback), null); | |||
} | |||
else | |||
{ | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -240,21 +253,19 @@ namespace Shadowsocks.Controller | |||
{ | |||
connection.EndSend(ar); | |||
// +----+-----+-------+------+----------+----------+ | |||
// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | | |||
// +----+-----+-------+------+----------+----------+ | |||
// | 1 | 1 | X'00' | 1 | Variable | 2 | | |||
// +----+-----+-------+------+----------+----------+ | |||
// +-----+-----+-------+------+----------+----------+ | |||
// | VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | | |||
// +-----+-----+-------+------+----------+----------+ | |||
// | 1 | 1 | X'00' | 1 | Variable | 2 | | |||
// +-----+-----+-------+------+----------+----------+ | |||
// Skip first 3 bytes | |||
// TODO validate | |||
Logging.Debug($"======Receive Local Port, size:" + 3); | |||
connection.BeginReceive(connetionRecvBuffer, 0, 3, 0, | |||
new AsyncCallback(handshakeReceive2Callback), null); | |||
connection.BeginReceive(connetionRecvBuffer, 0, 3, 0, new AsyncCallback(handshakeReceive2Callback), null); | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -274,7 +285,6 @@ namespace Shadowsocks.Controller | |||
if (command == 1) | |||
{ | |||
byte[] response = { 5, 0, 0, 1, 0, 0, 0, 0, 0, 0 }; | |||
Logging.Debug($"======Send Local Port, size:" + response.Length); | |||
connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(ResponseCallback), null); | |||
} | |||
else if (command == 3) | |||
@@ -284,14 +294,14 @@ namespace Shadowsocks.Controller | |||
} | |||
else | |||
{ | |||
Logging.Error("failed to recv data in handshakeReceive2Callback"); | |||
this.Close(); | |||
Logging.Debug("failed to recv data in Shadowsocks.Controller.TCPHandler.handshakeReceive2Callback()"); | |||
Close(); | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -313,7 +323,6 @@ namespace Shadowsocks.Controller | |||
address.CopyTo(response, 4); | |||
response[response.Length - 1] = (byte)(port & 0xFF); | |||
response[response.Length - 2] = (byte)((port >> 8) & 0xFF); | |||
Logging.Debug($"======Send Local Port, size:" + response.Length); | |||
connection.BeginSend(response, 0, response.Length, 0, new AsyncCallback(ReadAll), true); | |||
} | |||
@@ -328,29 +337,27 @@ namespace Shadowsocks.Controller | |||
if (ar.AsyncState != null) | |||
{ | |||
connection.EndSend(ar); | |||
Logging.Debug($"======Receive Local Port, size:" + RecvSize); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, | |||
new AsyncCallback(ReadAll), null); | |||
Logging.Debug(remote, RecvSize, "TCP Relay"); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, new AsyncCallback(ReadAll), null); | |||
} | |||
else | |||
{ | |||
int bytesRead = connection.EndReceive(ar); | |||
if (bytesRead > 0) | |||
{ | |||
Logging.Debug($"======Receive Local Port, size:" + RecvSize); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, | |||
new AsyncCallback(ReadAll), null); | |||
Logging.Debug(remote, RecvSize, "TCP Relay"); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, new AsyncCallback(ReadAll), null); | |||
} | |||
else | |||
{ | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -366,15 +373,16 @@ namespace Shadowsocks.Controller | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
// inner class | |||
private class ServerTimer : Timer | |||
{ | |||
public Server Server; | |||
public ServerTimer(int p) :base(p) | |||
public ServerTimer(int p) : base(p) | |||
{ | |||
} | |||
} | |||
@@ -408,14 +416,12 @@ namespace Shadowsocks.Controller | |||
connected = false; | |||
// Connect to the remote endpoint. | |||
Logging.Debug($"++++++Connect Server Port"); | |||
remote.BeginConnect(remoteEP, | |||
new AsyncCallback(ConnectCallback), connectTimer); | |||
remote.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), connectTimer); | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -438,15 +444,15 @@ namespace Shadowsocks.Controller | |||
private void RetryConnect() | |||
{ | |||
if (retryCount < 4) | |||
if (retryCount < maxRetry) | |||
{ | |||
Logging.Debug("Connection failed, retrying"); | |||
Logging.Debug($"Connection failed, retry ({retryCount})"); | |||
StartConnect(); | |||
retryCount++; | |||
} | |||
else | |||
{ | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -507,17 +513,13 @@ namespace Shadowsocks.Controller | |||
} | |||
try | |||
{ | |||
Logging.Debug($"++++++Receive Server Port, size:" + RecvSize); | |||
remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0, | |||
new AsyncCallback(PipeRemoteReceiveCallback), null); | |||
Logging.Debug($"======Receive Local Port, size:"+ RecvSize); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, | |||
new AsyncCallback(PipeConnectionReceiveCallback), null); | |||
remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0, new AsyncCallback(PipeRemoteReceiveCallback), null); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, new AsyncCallback(PipeConnectionReceiveCallback), null); | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -531,10 +533,11 @@ namespace Shadowsocks.Controller | |||
{ | |||
int bytesRead = remote.EndReceive(ar); | |||
totalRead += bytesRead; | |||
tcprelay.UpdateInboundCounter(bytesRead); | |||
if (bytesRead > 0) | |||
{ | |||
this.lastActivity = DateTime.Now; | |||
lastActivity = DateTime.Now; | |||
int bytesToSend; | |||
lock (decryptionLock) | |||
{ | |||
@@ -544,13 +547,13 @@ namespace Shadowsocks.Controller | |||
} | |||
encryptor.Decrypt(remoteRecvBuffer, bytesRead, remoteSendBuffer, out bytesToSend); | |||
} | |||
Logging.Debug($"======Send Local Port, size:" + bytesToSend); | |||
Logging.Debug(remote, bytesToSend, "TCP Relay", "@PipeRemoteReceiveCallback() (download)"); | |||
connection.BeginSend(remoteSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeConnectionSendCallback), null); | |||
IStrategy strategy = controller.GetCurrentStrategy(); | |||
if (strategy != null) | |||
{ | |||
strategy.UpdateLastRead(this.server); | |||
strategy.UpdateLastRead(server); | |||
} | |||
} | |||
else | |||
@@ -559,18 +562,18 @@ namespace Shadowsocks.Controller | |||
connectionShutdown = true; | |||
CheckClose(); | |||
if (totalRead == 0) | |||
{ | |||
// closed before anything received, reports as failure | |||
// disable this feature | |||
// controller.GetCurrentStrategy().SetFailure(this.server); | |||
} | |||
//if (totalRead == 0) | |||
//{ | |||
// // closed before anything received, reports as failure | |||
// // disable this feature | |||
// controller.GetCurrentStrategy().SetFailure(this.server); | |||
//} | |||
} | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -584,6 +587,7 @@ namespace Shadowsocks.Controller | |||
{ | |||
int bytesRead = connection.EndReceive(ar); | |||
totalWrite += bytesRead; | |||
tcprelay.UpdateOutboundCounter(bytesRead); | |||
if (bytesRead > 0) | |||
{ | |||
@@ -596,13 +600,13 @@ namespace Shadowsocks.Controller | |||
} | |||
encryptor.Encrypt(connetionRecvBuffer, bytesRead, connetionSendBuffer, out bytesToSend); | |||
} | |||
Logging.Debug($"++++++Send Server Port, size:" + bytesToSend); | |||
Logging.Debug(remote, bytesToSend, "TCP Relay", "@PipeConnectionReceiveCallback() (upload)"); | |||
remote.BeginSend(connetionSendBuffer, 0, bytesToSend, 0, new AsyncCallback(PipeRemoteSendCallback), null); | |||
IStrategy strategy = controller.GetCurrentStrategy(); | |||
if (strategy != null) | |||
{ | |||
strategy.UpdateLastWrite(this.server); | |||
strategy.UpdateLastWrite(server); | |||
} | |||
} | |||
else | |||
@@ -615,7 +619,7 @@ namespace Shadowsocks.Controller | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -628,14 +632,12 @@ namespace Shadowsocks.Controller | |||
try | |||
{ | |||
remote.EndSend(ar); | |||
Logging.Debug($"======Receive Local Port, size:" + RecvSize); | |||
connection.BeginReceive(this.connetionRecvBuffer, 0, RecvSize, 0, | |||
new AsyncCallback(PipeConnectionReceiveCallback), null); | |||
connection.BeginReceive(connetionRecvBuffer, 0, RecvSize, 0, new AsyncCallback(PipeConnectionReceiveCallback), null); | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
@@ -648,14 +650,12 @@ namespace Shadowsocks.Controller | |||
try | |||
{ | |||
connection.EndSend(ar); | |||
Logging.Debug($"++++++Receive Server Port, size:" + RecvSize); | |||
remote.BeginReceive(this.remoteRecvBuffer, 0, RecvSize, 0, | |||
new AsyncCallback(PipeRemoteReceiveCallback), null); | |||
remote.BeginReceive(remoteRecvBuffer, 0, RecvSize, 0, new AsyncCallback(PipeRemoteReceiveCallback), null); | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.LogUsefulException(e); | |||
this.Close(); | |||
Close(); | |||
} | |||
} | |||
} | |||
@@ -1,12 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using Shadowsocks.Encryption; | |||
using Shadowsocks.Model; | |||
using System.Net.Sockets; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Runtime.CompilerServices; | |||
using Shadowsocks.Controller.Strategy; | |||
using Shadowsocks.Encryption; | |||
using Shadowsocks.Model; | |||
namespace Shadowsocks.Controller | |||
{ | |||
@@ -14,6 +14,10 @@ namespace Shadowsocks.Controller | |||
{ | |||
private ShadowsocksController _controller; | |||
private LRUCache<IPEndPoint, UDPHandler> _cache; | |||
public long outbound = 0; | |||
public long inbound = 0; | |||
public UDPRelay(ShadowsocksController controller) | |||
{ | |||
this._controller = controller; | |||
@@ -70,8 +74,8 @@ namespace Shadowsocks.Controller | |||
} | |||
_remoteEndPoint = new IPEndPoint(ipAddress, server.server_port); | |||
_remote = new Socket(_remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); | |||
} | |||
public void Send(byte[] data, int length) | |||
{ | |||
IEncryptor encryptor = EncryptorFactory.GetEncryptor(_server.method, _server.password, _server.auth, true); | |||
@@ -80,15 +84,17 @@ namespace Shadowsocks.Controller | |||
byte[] dataOut = new byte[length - 3 + 16 + IVEncryptor.ONETIMEAUTH_BYTES]; | |||
int outlen; | |||
encryptor.Encrypt(dataIn, length - 3, dataOut, out outlen); | |||
Logging.Debug($"++++++Send Server Port, size:" + outlen); | |||
Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); | |||
_remote.SendTo(dataOut, outlen, SocketFlags.None, _remoteEndPoint); | |||
} | |||
public void Receive() | |||
{ | |||
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); | |||
Logging.Debug($"++++++Receive Server Port, size:" + _buffer.Length); | |||
_remote.BeginReceiveFrom(_buffer, 0, _buffer.Length, 0, ref remoteEndPoint, new AsyncCallback(RecvFromCallback), null); | |||
} | |||
public void RecvFromCallback(IAsyncResult ar) | |||
{ | |||
try | |||
@@ -105,7 +111,7 @@ namespace Shadowsocks.Controller | |||
byte[] sendBuf = new byte[outlen + 3]; | |||
Array.Copy(dataOut, 0, sendBuf, 3, outlen); | |||
Logging.Debug($"======Send Local Port, size:" + (outlen + 3)); | |||
Logging.Debug(_localEndPoint, _remoteEndPoint, outlen, "UDP Relay"); | |||
_local.SendTo(sendBuf, outlen + 3, 0, _localEndPoint); | |||
Receive(); | |||
} | |||
@@ -121,6 +127,7 @@ namespace Shadowsocks.Controller | |||
{ | |||
} | |||
} | |||
public void Close() | |||
{ | |||
try | |||
@@ -142,7 +149,6 @@ namespace Shadowsocks.Controller | |||
} | |||
} | |||
// cc by-sa 3.0 http://stackoverflow.com/a/3719378/1124054 | |||
class LRUCache<K, V> where V : UDPRelay.UDPHandler | |||
{ | |||
@@ -1,14 +1,15 @@ | |||
using System.IO; | |||
using Shadowsocks.Model; | |||
using System; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Net; | |||
using System.Net.Sockets; | |||
using System.Text; | |||
using System.Threading; | |||
using System.Net.Sockets; | |||
using Shadowsocks.Controller.Strategy; | |||
using System.Net; | |||
using Shadowsocks.Util; | |||
using Shadowsocks.Model; | |||
using Shadowsocks.Properties; | |||
using Shadowsocks.Util; | |||
namespace Shadowsocks.Controller | |||
{ | |||
@@ -30,6 +31,9 @@ namespace Shadowsocks.Controller | |||
public AvailabilityStatistics availabilityStatistics { get; private set; } | |||
public StatisticsStrategyConfiguration StatisticsConfiguration { get; private set; } | |||
public long inboundCounter = 0; | |||
public long outboundCounter = 0; | |||
private bool stopped = false; | |||
private bool _systemProxyIsDirty = false; | |||
@@ -62,7 +66,6 @@ namespace Shadowsocks.Controller | |||
StartReleasingMemory(); | |||
} | |||
public void Start() | |||
{ | |||
Reload(); | |||
@@ -302,6 +305,16 @@ namespace Shadowsocks.Controller | |||
Configuration.Save(_config); | |||
} | |||
public void UpdateInboundCounter(long n) | |||
{ | |||
inboundCounter += n; | |||
} | |||
public void UpdateOutboundCounter(long n) | |||
{ | |||
outboundCounter += n; | |||
} | |||
protected void Reload() | |||
{ | |||
// some logic in configuration updated the config when saving, we need to read it again | |||
@@ -1,10 +1,8 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.IO.Compression; | |||
using System.Runtime.InteropServices; | |||
using System.Text; | |||
using System.Windows.Forms; | |||
using Shadowsocks.Controller; | |||
@@ -85,6 +83,33 @@ namespace Shadowsocks.Util | |||
} | |||
} | |||
public static string FormatBandwide(long n) | |||
{ | |||
float f = n; | |||
string unit = "B"; | |||
if (f > 1024) | |||
{ | |||
f = f / 1024; | |||
unit = "KiB"; | |||
} | |||
if (f > 1024) | |||
{ | |||
f = f / 1024; | |||
unit = "MiB"; | |||
} | |||
if (f > 1024) | |||
{ | |||
f = f / 1024; | |||
unit = "GiB"; | |||
} | |||
if (f > 1024) | |||
{ | |||
f = f / 1024; | |||
unit = "TiB"; | |||
} | |||
return $"{f:.##}{unit}"; | |||
} | |||
[DllImport("kernel32.dll")] | |||
[return: MarshalAs(UnmanagedType.Bool)] | |||
private static extern bool SetProcessWorkingSetSize(IntPtr process, | |||
@@ -57,13 +57,13 @@ | |||
this.LogMessageTextBox.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.LogMessageTextBox.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); | |||
this.LogMessageTextBox.ForeColor = System.Drawing.Color.White; | |||
this.LogMessageTextBox.Location = new System.Drawing.Point(3, 38); | |||
this.LogMessageTextBox.Location = new System.Drawing.Point(3, 40); | |||
this.LogMessageTextBox.MaxLength = 2147483647; | |||
this.LogMessageTextBox.Multiline = true; | |||
this.LogMessageTextBox.Name = "LogMessageTextBox"; | |||
this.LogMessageTextBox.ReadOnly = true; | |||
this.LogMessageTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; | |||
this.LogMessageTextBox.Size = new System.Drawing.Size(378, 99); | |||
this.LogMessageTextBox.Size = new System.Drawing.Size(378, 131); | |||
this.LogMessageTextBox.TabIndex = 0; | |||
// | |||
// MainMenu | |||
@@ -141,12 +141,12 @@ | |||
// | |||
// TopMostCheckBox | |||
// | |||
this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||
this.TopMostCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||
| System.Windows.Forms.AnchorStyles.Left))); | |||
this.TopMostCheckBox.AutoSize = true; | |||
this.TopMostCheckBox.Location = new System.Drawing.Point(249, 3); | |||
this.TopMostCheckBox.Location = new System.Drawing.Point(247, 3); | |||
this.TopMostCheckBox.Name = "TopMostCheckBox"; | |||
this.TopMostCheckBox.Size = new System.Drawing.Size(72, 23); | |||
this.TopMostCheckBox.Size = new System.Drawing.Size(71, 25); | |||
this.TopMostCheckBox.TabIndex = 3; | |||
this.TopMostCheckBox.Text = "&Top Most"; | |||
this.TopMostCheckBox.UseVisualStyleBackColor = true; | |||
@@ -157,7 +157,7 @@ | |||
this.ChangeFontButton.AutoSize = true; | |||
this.ChangeFontButton.Location = new System.Drawing.Point(84, 3); | |||
this.ChangeFontButton.Name = "ChangeFontButton"; | |||
this.ChangeFontButton.Size = new System.Drawing.Size(75, 23); | |||
this.ChangeFontButton.Size = new System.Drawing.Size(75, 25); | |||
this.ChangeFontButton.TabIndex = 2; | |||
this.ChangeFontButton.Text = "&Font"; | |||
this.ChangeFontButton.UseVisualStyleBackColor = true; | |||
@@ -168,7 +168,7 @@ | |||
this.CleanLogsButton.AutoSize = true; | |||
this.CleanLogsButton.Location = new System.Drawing.Point(3, 3); | |||
this.CleanLogsButton.Name = "CleanLogsButton"; | |||
this.CleanLogsButton.Size = new System.Drawing.Size(75, 23); | |||
this.CleanLogsButton.Size = new System.Drawing.Size(75, 25); | |||
this.CleanLogsButton.TabIndex = 1; | |||
this.CleanLogsButton.Text = "&Clean Logs"; | |||
this.CleanLogsButton.UseVisualStyleBackColor = true; | |||
@@ -176,12 +176,12 @@ | |||
// | |||
// WrapTextCheckBox | |||
// | |||
this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||
this.WrapTextCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | |||
| System.Windows.Forms.AnchorStyles.Left))); | |||
this.WrapTextCheckBox.AutoSize = true; | |||
this.WrapTextCheckBox.Location = new System.Drawing.Point(165, 3); | |||
this.WrapTextCheckBox.Name = "WrapTextCheckBox"; | |||
this.WrapTextCheckBox.Size = new System.Drawing.Size(78, 23); | |||
this.WrapTextCheckBox.Size = new System.Drawing.Size(76, 25); | |||
this.WrapTextCheckBox.TabIndex = 0; | |||
this.WrapTextCheckBox.Text = "&Wrap Text"; | |||
this.WrapTextCheckBox.UseVisualStyleBackColor = true; | |||
@@ -199,7 +199,7 @@ | |||
this.tableLayoutPanel1.RowCount = 2; | |||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | |||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); | |||
this.tableLayoutPanel1.Size = new System.Drawing.Size(384, 140); | |||
this.tableLayoutPanel1.Size = new System.Drawing.Size(384, 174); | |||
this.tableLayoutPanel1.TabIndex = 2; | |||
// | |||
// ToolbarFlowLayoutPanel | |||
@@ -212,17 +212,17 @@ | |||
this.ToolbarFlowLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill; | |||
this.ToolbarFlowLayoutPanel.Location = new System.Drawing.Point(3, 3); | |||
this.ToolbarFlowLayoutPanel.Name = "ToolbarFlowLayoutPanel"; | |||
this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(378, 29); | |||
this.ToolbarFlowLayoutPanel.Size = new System.Drawing.Size(378, 31); | |||
this.ToolbarFlowLayoutPanel.TabIndex = 2; | |||
// | |||
// LogForm | |||
// | |||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); | |||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); | |||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; | |||
this.ClientSize = new System.Drawing.Size(384, 140); | |||
this.ClientSize = new System.Drawing.Size(384, 174); | |||
this.Controls.Add(this.tableLayoutPanel1); | |||
this.Menu = this.MainMenu; | |||
this.MinimumSize = new System.Drawing.Size(400, 200); | |||
this.MinimumSize = new System.Drawing.Size(400, 213); | |||
this.Name = "LogForm"; | |||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; | |||
this.Text = "Log Viewer"; | |||
@@ -1,16 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel; | |||
using System.Data; | |||
using System.Drawing; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Windows.Forms; | |||
using Shadowsocks.Controller; | |||
using Shadowsocks.Properties; | |||
using Shadowsocks.Model; | |||
using Shadowsocks.Util; | |||
namespace Shadowsocks.View | |||
{ | |||
@@ -112,11 +108,14 @@ namespace Shadowsocks.View | |||
lastOffset = reader.BaseStream.Position; | |||
} | |||
this.Text = $"Log Viewer [in: {Utils.FormatBandwide(controller.inboundCounter)}, out: {Utils.FormatBandwide(controller.outboundCounter)}]"; | |||
} | |||
private void LogForm_Load(object sender, EventArgs e) | |||
{ | |||
InitContent(); | |||
timer = new Timer(); | |||
timer.Interval = 300; | |||
timer.Tick += Timer_Tick; | |||
@@ -117,7 +117,31 @@ | |||
<resheader name="writer"> | |||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> | |||
</resheader> | |||
<metadata name="LogMessageTextBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="MainMenu.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> | |||
<value>17, 17</value> | |||
</metadata> | |||
<metadata name="TopMostCheckBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="ChangeFontButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="CleanLogsButton.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="WrapTextCheckBox.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="tableLayoutPanel1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="ToolbarFlowLayoutPanel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | |||
<value>True</value> | |||
</metadata> | |||
</root> |