This commit is contained in:
jsaey 2023-11-17 09:43:03 +01:00
parent cbfb1a9407
commit bcc9a6d44c
69 changed files with 1149 additions and 1461 deletions

View File

@ -8,7 +8,7 @@ using System.Security.Cryptography.X509Certificates;
internal class Program
{
private static WebSocket _client;
private static WSClient _client;
private static WSServer _server;
private static async Task Main(string[] args)
@ -66,8 +66,8 @@ internal class Program
StartServer(serverUri, certificatePath, certificatePassword, requiredPassword);
// Start the client in the main thread
_client = new WebSocket(clientUri);
_client.SslConfiguration.Certificates.Add(new X509Certificate(certificatePath, certificatePassword));
_client = new WSClient(clientUri);
_client.SSL.Certificates.Add(new X509Certificate(certificatePath, certificatePassword));
_client.OnConnect += (sender, e) => Console.WriteLine($"Connected to server");
_client.OnMessageReceived += (sender, e) => Console.WriteLine($"Received message from server: {e.Data}");
_client.OnDisconnect += (sender, e) => Console.WriteLine($"Disconnected from server: {e.Code} : {e.Reason}");

View File

@ -7,13 +7,13 @@ namespace EonaCat.BlockChain
{
public class P2PClient
{
private readonly IDictionary<string, WebSocket> wsDict = new Dictionary<string, WebSocket>();
private readonly IDictionary<string, WSClient> wsDict = new Dictionary<string, WSClient>();
public void Connect(string url)
{
if (!wsDict.ContainsKey(url))
{
WebSocket webSocket = new WebSocket(url);
WSClient webSocket = new WSClient(url);
webSocket.OnMessageReceived += (sender, e) =>
{
if (e.Data == "Hi Client")

View File

@ -211,24 +211,6 @@ namespace EonaCat.Quic.Connections
TerminateConnection();
}
private void OnStreamDataBlockedFrame(Frame frame)
{
StreamDataBlockedFrame sdbf = (StreamDataBlockedFrame)frame;
StreamId streamId = sdbf.StreamId;
if (_streams.ContainsKey(streamId.Id) == false)
{
return;
}
QuicStream stream = _streams[streamId.Id];
stream.ProcessStreamDataBlocked(sdbf);
// Remove the stream from the connection
_streams.Remove(streamId.Id);
}
internal QuicConnection(ConnectionData connection)
{
_currentTransferRate = 0;

View File

@ -146,10 +146,7 @@ namespace EonaCat.Quic.Infrastructure
break;
}
if (result != null)
{
result.Decode(_array);
}
result?.Decode(_array);
return result;
}

View File

@ -60,8 +60,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(ActualType);
List<byte> result = new List<byte>
{
ActualType
};
result.AddRange(ErrorCode.ToByteArray());
if (ActualType == 0x1c)
{

View File

@ -28,8 +28,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(Type);
List<byte> result = new List<byte>
{
Type
};
result.AddRange(MaximumData.ToByteArray());
return result.ToArray();

View File

@ -20,9 +20,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(Type);
List<byte> result = new List<byte>
{
Type
};
result.AddRange(MaximumData.ToByteArray());
return result.ToArray();

View File

@ -34,9 +34,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(Type);
List<byte> result = new List<byte>
{
Type
};
result.AddRange(StreamId.ToByteArray());
result.AddRange(MaximumStreamData.ToByteArray());

View File

@ -28,9 +28,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(Type);
List<byte> result = new List<byte>
{
Type
};
result.AddRange(MaximumStreams.ToByteArray());
return result.ToArray();

View File

@ -17,8 +17,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> data = new List<byte>();
data.Add(Type);
List<byte> data = new List<byte>
{
Type
};
return data.ToArray();
}

View File

@ -17,8 +17,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> data = new List<byte>();
data.Add(Type);
List<byte> data = new List<byte>
{
Type
};
return data.ToArray();
}

View File

@ -23,9 +23,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(Type);
List<byte> result = new List<byte>
{
Type
};
result.AddRange(StreamId.ToByteArray());
result.AddRange(ApplicationProtocolErrorCode.ToByteArray());
result.AddRange(FinalSize.ToByteArray());

View File

@ -32,9 +32,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
public override byte[] Encode()
{
List<byte> result = new List<byte>();
result.Add(Type);
List<byte> result = new List<byte>
{
Type
};
result.AddRange(StreamId.ToByteArray());
result.AddRange(MaximumStreamData.ToByteArray());

View File

@ -79,8 +79,10 @@ namespace EonaCat.Quic.Infrastructure.Frames
byte LEN_BIT = (byte)(ActualType & 0x02);
byte FIN_BIT = (byte)(ActualType & 0x01);
List<byte> result = new List<byte>();
result.Add(ActualType);
List<byte> result = new List<byte>
{
ActualType
};
byte[] streamId = StreamId;
result.AddRange(streamId);

View File

@ -72,8 +72,10 @@ namespace EonaCat.Quic.Infrastructure.Packets
{
byte[] frames = EncodeFrames();
List<byte> result = new List<byte>();
result.Add((byte)(Type | (PacketNumber.Size - 1)));
List<byte> result = new List<byte>
{
(byte)(Type | (PacketNumber.Size - 1))
};
result.AddRange(ByteHelpers.GetBytes(Version));
result.Add(DestinationConnectionId.Size);

View File

@ -59,9 +59,10 @@ namespace EonaCat.Quic.Infrastructure.Packets
{
byte[] frames = EncodeFrames();
List<byte> result = new List<byte>();
result.Add(EncodeTypeField());
List<byte> result = new List<byte>
{
EncodeTypeField()
};
result.AddRange(ByteHelpers.GetBytes(Version));
result.Add(DestinationConnectionId.Size);

View File

@ -38,8 +38,10 @@ namespace EonaCat.Quic.Infrastructure.Packets
{
byte[] frames = EncodeFrames();
List<byte> result = new List<byte>();
result.Add((byte)(Type | (PacketNumber.Size - 1)));
List<byte> result = new List<byte>
{
(byte)(Type | (PacketNumber.Size - 1))
};
result.AddRange(DestinationConnectionId.ToByteArray());
byte[] pnBytes = PacketNumber;

View File

@ -107,7 +107,6 @@ namespace EonaCat.Quic
private QuicConnection ProcessInitialPacket(Packet packet, IPEndPoint endPoint)
{
QuicConnection result = null;
ulong availableConnectionId;
byte[] data;
// Unsupported version. Version negotiation packet is sent only on initial connection. All other packets are dropped. (5.2.2 / 16th draft)
if (packet.Version != QuicVersion.CurrentVersion || !QuicVersion.SupportedVersions.Contains(packet.Version))
@ -127,7 +126,7 @@ namespace EonaCat.Quic
{
ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.PROTOCOL_VIOLATION, 0x00, ErrorConstants.PMTUNotReached));
}
else if (ConnectionPool.AddConnection(new ConnectionData(new PacketWireTransfer(_client, endPoint), cast.SourceConnectionId, 0), out availableConnectionId) == true)
else if (ConnectionPool.AddConnection(new ConnectionData(new PacketWireTransfer(_client, endPoint), cast.SourceConnectionId, 0), out ulong availableConnectionId) == true)
{
// Tell the peer the available connection id
ip.SourceConnectionId = (byte)availableConnectionId;

View File

@ -291,9 +291,11 @@ namespace EonaCat.Network
user = user.Substring(i + 1);
}
var res = new NameValueCollection();
res["username"] = user;
res["password"] = pass;
var res = new NameValueCollection
{
["username"] = user,
["password"] = pass
};
return res;
}

View File

@ -281,8 +281,7 @@ namespace EonaCat.Network
private static string Convert(string key)
{
HttpHeaderInfo info;
return _headers.TryGetValue(key, out info) ? info.Name : string.Empty;
return _headers.TryGetValue(key, out HttpHeaderInfo info) ? info.Name : string.Empty;
}
private void DoWithCheckingState(

View File

@ -16,21 +16,21 @@ namespace EonaCat.Network
/// This class provides access to various properties and methods for interacting with the WebSocket connection
/// within the context of an HTTP request handled by an <see cref="HttpListener"/>.
/// </remarks>
/// <seealso cref="WebSocketContext"/>
public class HttpListenerWebSocketContext : WebSocketContext
/// <seealso cref="WSContext"/>
public class HttpListenerWSContext : WSContext
{
private readonly HttpListenerContext _context;
private readonly WebSocket _websocket;
private readonly WSClient _websocket;
/// <summary>
/// Initializes a new instance of the <see cref="HttpListenerWebSocketContext"/> class.
/// Initializes a new instance of the <see cref="HttpListenerWSContext"/> class.
/// </summary>
/// <param name="context">The <see cref="HttpListenerContext"/> associated with the WebSocket connection.</param>
/// <param name="protocol">The WebSocket protocol negotiated during the connection.</param>
internal HttpListenerWebSocketContext(HttpListenerContext context, string protocol)
internal HttpListenerWSContext(HttpListenerContext context, string protocol)
{
_context = context;
_websocket = new WebSocket(this, protocol);
_websocket = new WSClient(this, protocol);
}
/// <summary>
@ -83,7 +83,7 @@ namespace EonaCat.Network
public override System.Net.IPEndPoint UserEndPoint => _context.Connection.RemoteEndPoint;
public override WebSocket WebSocket => _websocket;
public override WSClient WebSocket => _websocket;
/// <summary>
/// Closes the WebSocket connection.

View File

@ -19,7 +19,7 @@ namespace EonaCat.Network
/// This internal class provides access to various properties and methods for interacting with the WebSocket connection
/// within the context of a TCP listener.
/// </remarks>
internal class TcpListenerWebSocketContext : WebSocketContext
internal class TcpListenerWSContext : WSContext
{
private CookieCollection _cookies;
private NameValueCollection _queryString;
@ -28,21 +28,21 @@ namespace EonaCat.Network
private readonly TcpClient _tcpClient;
private readonly Uri _uri;
private IPrincipal _user;
private readonly WebSocket _websocket;
private readonly WSClient _websocket;
/// <summary>
/// Initializes a new instance of the <see cref="TcpListenerWebSocketContext"/> class.
/// Initializes a new instance of the <see cref="TcpListenerWSContext"/> class.
/// </summary>
/// <param name="tcpClient">The <see cref="TcpClient"/> associated with the WebSocket connection.</param>
/// <param name="protocol">The WebSocket protocol negotiated during the connection.</param>
/// <param name="secure">A boolean indicating whether the connection is secure.</param>
/// <param name="sslConfig">The SSL configuration for secure connections.</param>
/// <param name="logger">The logger for logging.</param>
internal TcpListenerWebSocketContext(
internal TcpListenerWSContext(
TcpClient tcpClient,
string protocol,
bool secure,
SSLConfigurationServer sslConfig
SSLConfigServer sslConfig
)
{
_tcpClient = tcpClient;
@ -74,7 +74,7 @@ namespace EonaCat.Network
_request.RequestUri, _request.Headers["Host"], _request.IsWebSocketRequest, secure
);
_websocket = new WebSocket(this, protocol);
_websocket = new WSClient(this, protocol);
}
/// <summary>
@ -100,7 +100,7 @@ namespace EonaCat.Network
public override NameValueCollection QueryString => _queryString ??=
HttpUtility.InternalParseQueryString(
_uri != null ? _uri.Query : null, Encoding.UTF8
_uri?.Query, Encoding.UTF8
)
;
@ -131,7 +131,7 @@ namespace EonaCat.Network
public override System.Net.IPEndPoint UserEndPoint => (System.Net.IPEndPoint)_tcpClient.Client.RemoteEndPoint;
public override WebSocket WebSocket => _websocket;
public override WSClient WebSocket => _websocket;
/// <summary>
/// Authenticates the WebSocket connection based on the specified authentication scheme.

View File

@ -15,12 +15,12 @@ namespace EonaCat.Network
/// This abstract class defines properties and methods for accessing information related to a WebSocket connection,
/// such as headers, cookies, authentication status, and more.
/// </remarks>
public abstract class WebSocketContext
public abstract class WSContext
{
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketContext"/> class.
/// Initializes a new instance of the <see cref="WSContext"/> class.
/// </summary>
protected WebSocketContext()
protected WSContext()
{
}
@ -107,6 +107,6 @@ namespace EonaCat.Network
/// <summary>
/// Gets the WebSocket instance associated with the context.
/// </summary>
public abstract WebSocket WebSocket { get; }
public abstract WSClient WebSocket { get; }
}
}

View File

@ -226,10 +226,9 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSetName(value, out msg))
if (!canSetName(value, out string message))
{
throw new CookieException(msg);
throw new CookieException(message);
}
_name = value;
@ -272,8 +271,7 @@ namespace EonaCat.Network
"The value specified for the Port attribute isn't enclosed in double quotes.");
}
string err;
if (!tryCreatePorts(value, out _ports, out err))
if (!tryCreatePorts(value, out _ports, out string err))
{
throw new CookieException(
string.Format(
@ -308,10 +306,9 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSetValue(value, out msg))
if (!canSetValue(value, out string message))
{
throw new CookieException(msg);
throw new CookieException(message);
}
_value = value.Length > 0 ? value : "\"\"";

View File

@ -236,13 +236,12 @@ namespace EonaCat.Network
buff.AppendFormat(", {0}", pairs[++i].Trim());
}
DateTime expires;
if (!DateTime.TryParseExact(
buff.ToString(),
new[] { "ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'", "r" },
CultureInfo.CreateSpecificCulture("en-US"),
DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal,
out expires))
out DateTime expires))
{
expires = DateTime.Now;
}

View File

@ -37,7 +37,7 @@ namespace EonaCat.Network
IPEndPoint endpoint,
bool secure,
string certificateFolderPath,
SSLConfigurationServer sslConfig,
SSLConfigServer sslConfig,
bool reuseAddress
)
{
@ -52,8 +52,8 @@ namespace EonaCat.Network
}
IsSecure = true;
SslConfiguration = new SSLConfigurationServer(sslConfig);
SslConfiguration.Certificate = cert;
SSL = new SSLConfigServer(sslConfig);
SSL.Certificate = cert;
}
_endpoint = endpoint;
@ -91,7 +91,7 @@ namespace EonaCat.Network
/// <summary>
/// Gets the SSL configuration for the secure endpoint.
/// </summary>
public SSLConfigurationServer SslConfiguration { get; }
public SSLConfigServer SSL { get; }
private static void addSpecial(List<HttpListenerPrefix> prefixes, HttpListenerPrefix prefix)
{
@ -183,7 +183,7 @@ namespace EonaCat.Network
}
catch (SocketException)
{
// TODO: Should log the error code when this class has a logging.
// Do nothing
}
catch (ObjectDisposedException)
{
@ -196,10 +196,7 @@ namespace EonaCat.Network
}
catch
{
if (sock != null)
{
sock.Close();
}
sock?.Close();
return;
}
@ -436,8 +433,10 @@ namespace EonaCat.Network
return;
}
prefs2 = new Dictionary<HttpListenerPrefix, HttpListener>(prefs);
prefs2[prefix] = listener;
prefs2 = new Dictionary<HttpListenerPrefix, HttpListener>(prefs)
{
[prefix] = listener
};
}
while (Interlocked.CompareExchange(ref _prefixes, prefs2, prefs) != prefs);
}

View File

@ -40,8 +40,7 @@ namespace EonaCat.Network
throw new HttpListenerException(87, "Includes an invalid host.");
}
int port;
if (!int.TryParse(pref.Port, out port))
if (!int.TryParse(pref.Port, out int port))
{
throw new HttpListenerException(87, "Includes an invalid port.");
}
@ -64,8 +63,7 @@ namespace EonaCat.Network
var endpoint = new IPEndPoint(addr, port);
EndPointListener lsnr;
if (_endpoints.TryGetValue(endpoint, out lsnr))
if (_endpoints.TryGetValue(endpoint, out EndPointListener lsnr))
{
if (lsnr.IsSecure ^ pref.IsSecure)
{
@ -104,8 +102,7 @@ namespace EonaCat.Network
return;
}
int port;
if (!int.TryParse(pref.Port, out port))
if (!int.TryParse(pref.Port, out int port))
{
return;
}
@ -128,8 +125,7 @@ namespace EonaCat.Network
var endpoint = new IPEndPoint(addr, port);
EndPointListener lsnr;
if (!_endpoints.TryGetValue(endpoint, out lsnr))
if (!_endpoints.TryGetValue(endpoint, out EndPointListener lsnr))
{
return;
}
@ -151,8 +147,7 @@ namespace EonaCat.Network
{
lock (((ICollection)_endpoints).SyncRoot)
{
EndPointListener lsnr;
if (!_endpoints.TryGetValue(endpoint, out lsnr))
if (!_endpoints.TryGetValue(endpoint, out EndPointListener lsnr))
{
return false;
}

View File

@ -19,6 +19,8 @@ namespace EonaCat.Network
{
private byte[] _buffer;
private const int _bufferLength = 8192;
private const int TIMEOUT_CONTINUE = 15000;
private const int TIMEOUT_INITIAL = 90000;
private HttpListenerContext _context;
private bool _contextRegistered;
private StringBuilder _currentLine;
@ -31,7 +33,7 @@ namespace EonaCat.Network
private int _position;
private MemoryStream _requestBuffer;
private Socket _socket;
private readonly object _sync;
private readonly object _lock;
private int _timeout;
private readonly Dictionary<int, bool> _timeoutCanceled;
private Timer _timer;
@ -47,11 +49,11 @@ namespace EonaCat.Network
_listener = listener;
IsSecure = listener.IsSecure;
var netStream = new NetworkStream(socket, false);
var networkStream = new NetworkStream(socket, false);
if (IsSecure)
{
var conf = listener.SslConfiguration;
var sslStream = new SslStream(netStream, false, conf.ClientCertificateValidationCallback);
var conf = listener.SSL;
var sslStream = new SslStream(networkStream, false, conf.ClientCertificateValidationCallback);
sslStream.AuthenticateAsServer(
conf.Certificate,
conf.IsClientCertificateRequired,
@ -63,15 +65,15 @@ namespace EonaCat.Network
}
else
{
Stream = netStream;
Stream = networkStream;
}
_sync = new object();
_timeout = 90000; // 90k ms for first request, 15k ms from then on.
_lock = new object();
_timeout = TIMEOUT_INITIAL;
_timeoutCanceled = new Dictionary<int, bool>();
_timer = new Timer(onTimeout, this, Timeout.Infinite, Timeout.Infinite);
_timer = new Timer(OnTimeout, this, Timeout.Infinite, Timeout.Infinite);
init();
Setup();
}
/// <summary>
@ -106,24 +108,24 @@ namespace EonaCat.Network
private void close()
{
lock (_sync)
lock (_lock)
{
if (_socket == null)
{
return;
}
disposeTimer();
disposeRequestBuffer();
disposeStream();
closeSocket();
DisposeTimer();
DisposeRequestBuffer();
DisposeStream();
CloseSocket();
}
unregisterContext();
removeConnection();
UnregisterContext();
RemoveConnection();
}
private void closeSocket()
private void CloseSocket()
{
try
{
@ -137,7 +139,7 @@ namespace EonaCat.Network
_socket = null;
}
private void disposeRequestBuffer()
private void DisposeRequestBuffer()
{
if (_requestBuffer == null)
{
@ -148,7 +150,7 @@ namespace EonaCat.Network
_requestBuffer = null;
}
private void disposeStream()
private void DisposeStream()
{
if (Stream == null)
{
@ -162,7 +164,7 @@ namespace EonaCat.Network
Stream = null;
}
private void disposeTimer()
private void DisposeTimer()
{
if (_timer == null)
{
@ -181,7 +183,7 @@ namespace EonaCat.Network
_timer = null;
}
private void init()
private void Setup()
{
_context = new HttpListenerContext(this);
_inputState = InputState.RequestLine;
@ -192,17 +194,17 @@ namespace EonaCat.Network
_requestBuffer = new MemoryStream();
}
private static void onRead(IAsyncResult asyncResult)
private static void OnRead(IAsyncResult asyncResult)
{
var conn = (HttpConnection)asyncResult.AsyncState;
if (conn._socket == null)
var httpConnection = (HttpConnection)asyncResult.AsyncState;
if (httpConnection._socket == null)
{
return;
}
lock (conn._sync)
lock (httpConnection._lock)
{
if (conn._socket == null)
if (httpConnection._socket == null)
{
return;
}
@ -211,111 +213,110 @@ namespace EonaCat.Network
var len = 0;
try
{
var current = conn.Reuses;
if (!conn._timeoutCanceled[current])
var current = httpConnection.Reuses;
if (!httpConnection._timeoutCanceled[current])
{
conn._timer.Change(Timeout.Infinite, Timeout.Infinite);
conn._timeoutCanceled[current] = true;
httpConnection._timer.Change(Timeout.Infinite, Timeout.Infinite);
httpConnection._timeoutCanceled[current] = true;
}
nread = conn.Stream.EndRead(asyncResult);
conn._requestBuffer.Write(conn._buffer, 0, nread);
len = (int)conn._requestBuffer.Length;
nread = httpConnection.Stream.EndRead(asyncResult);
httpConnection._requestBuffer.Write(httpConnection._buffer, 0, nread);
len = (int)httpConnection._requestBuffer.Length;
}
catch (Exception ex)
catch (Exception exception)
{
if (conn._requestBuffer != null && conn._requestBuffer.Length > 0)
if (httpConnection._requestBuffer != null && httpConnection._requestBuffer.Length > 0)
{
conn.SendError(ex.Message, 400);
httpConnection.SendError(exception.Message, 400);
return;
}
conn.close();
httpConnection.close();
return;
}
if (nread <= 0)
{
conn.close();
httpConnection.close();
return;
}
if (conn.processInput(conn._requestBuffer.GetBuffer(), len))
if (httpConnection.ProcessInput(httpConnection._requestBuffer.GetBuffer(), len))
{
if (!conn._context.HasError)
if (!httpConnection._context.HasError)
{
conn._context.Request.FinishInitialization();
httpConnection._context.Request.FinishInitialization();
}
if (conn._context.HasError)
if (httpConnection._context.HasError)
{
conn.SendError();
httpConnection.SendError();
return;
}
HttpListener lsnr;
if (!conn._listener.TrySearchHttpListener(conn._context.Request.Url, out lsnr))
if (!httpConnection._listener.TrySearchHttpListener(httpConnection._context.Request.Url, out HttpListener httpListener))
{
conn.SendError(null, 404);
httpConnection.SendError(null, 404);
return;
}
if (conn._lastListener != lsnr)
if (httpConnection._lastListener != httpListener)
{
conn.removeConnection();
if (!lsnr.AddConnection(conn))
httpConnection.RemoveConnection();
if (!httpListener.AddConnection(httpConnection))
{
conn.close();
httpConnection.close();
return;
}
conn._lastListener = lsnr;
httpConnection._lastListener = httpListener;
}
conn._context.Listener = lsnr;
if (!conn._context.Authenticate())
httpConnection._context.Listener = httpListener;
if (!httpConnection._context.Authenticate())
{
return;
}
if (conn._context.Register())
if (httpConnection._context.Register())
{
conn._contextRegistered = true;
httpConnection._contextRegistered = true;
}
return;
}
conn.Stream.BeginRead(conn._buffer, 0, _bufferLength, onRead, conn);
httpConnection.Stream.BeginRead(httpConnection._buffer, 0, _bufferLength, OnRead, httpConnection);
}
}
private static void onTimeout(object state)
private static void OnTimeout(object state)
{
var conn = (HttpConnection)state;
var current = conn.Reuses;
if (conn._socket == null)
var httpConnection = (HttpConnection)state;
var current = httpConnection.Reuses;
if (httpConnection._socket == null)
{
return;
}
lock (conn._sync)
lock (httpConnection._lock)
{
if (conn._socket == null)
if (httpConnection._socket == null)
{
return;
}
if (conn._timeoutCanceled[current])
if (httpConnection._timeoutCanceled[current])
{
return;
}
conn.SendError(null, 408);
httpConnection.SendError(null, 408);
}
}
private bool processInput(byte[] data, int length)
private bool ProcessInput(byte[] data, int length)
{
_currentLine ??= new StringBuilder(64);
@ -323,7 +324,7 @@ namespace EonaCat.Network
try
{
string line;
while ((line = readLineFrom(data, _position, length, out nread)) != null)
while ((line = ReadLineFrom(data, _position, length, out nread)) != null)
{
_position += nread;
if (line.Length == 0)
@ -358,9 +359,9 @@ namespace EonaCat.Network
}
}
}
catch (Exception ex)
catch (Exception exception)
{
_context.ErrorMessage = ex.Message;
_context.ErrorMessage = exception.Message;
return true;
}
@ -374,22 +375,22 @@ namespace EonaCat.Network
return false;
}
private string readLineFrom(byte[] buffer, int offset, int length, out int read)
private string ReadLineFrom(byte[] buffer, int offset, int length, out int read)
{
read = 0;
for (var i = offset; i < length && _lineState != LineState.Lf; i++)
for (var i = offset; i < length && _lineState != LineState.LineFeed; i++)
{
read++;
var b = buffer[i];
if (b == 13)
{
_lineState = LineState.Cr;
_lineState = LineState.CarriageReturn;
}
else if (b == 10)
{
_lineState = LineState.Lf;
_lineState = LineState.LineFeed;
}
else
{
@ -397,7 +398,7 @@ namespace EonaCat.Network
}
}
if (_lineState != LineState.Lf)
if (_lineState != LineState.LineFeed)
{
return null;
}
@ -410,7 +411,7 @@ namespace EonaCat.Network
return line;
}
private void removeConnection()
private void RemoveConnection()
{
if (_lastListener != null)
{
@ -422,7 +423,7 @@ namespace EonaCat.Network
}
}
private void unregisterContext()
private void UnregisterContext()
{
if (!_contextRegistered)
{
@ -444,7 +445,7 @@ namespace EonaCat.Network
return;
}
lock (_sync)
lock (_lock)
{
if (_socket == null)
{
@ -458,17 +459,16 @@ namespace EonaCat.Network
{
// Don't close. Keep working.
Reuses++;
disposeRequestBuffer();
unregisterContext();
init();
DisposeRequestBuffer();
UnregisterContext();
Setup();
BeginReadRequest();
return;
}
}
else if (_outputStream != null)
else
{
_outputStream.Close(true);
_outputStream?.Close(true);
}
close();
@ -484,14 +484,14 @@ namespace EonaCat.Network
if (Reuses == 1)
{
_timeout = 15000;
_timeout = TIMEOUT_CONTINUE;
}
try
{
_timeoutCanceled.Add(Reuses, false);
_timer.Change(_timeout, Timeout.Infinite);
Stream.BeginRead(_buffer, 0, _bufferLength, onRead, this);
Stream.BeginRead(_buffer, 0, _bufferLength, OnRead, this);
}
catch
{
@ -520,7 +520,7 @@ namespace EonaCat.Network
return _inputStream;
}
lock (_sync)
lock (_lock)
{
if (_socket == null)
{
@ -529,7 +529,7 @@ namespace EonaCat.Network
var buff = _requestBuffer.GetBuffer();
var len = (int)_requestBuffer.Length;
disposeRequestBuffer();
DisposeRequestBuffer();
if (chunked)
{
_context.Response.SendInChunks = true;
@ -557,7 +557,7 @@ namespace EonaCat.Network
return _outputStream;
}
lock (_sync)
lock (_lock)
{
if (_socket == null)
{
@ -592,7 +592,7 @@ namespace EonaCat.Network
return;
}
lock (_sync)
lock (_lock)
{
if (_socket == null)
{
@ -601,12 +601,12 @@ namespace EonaCat.Network
try
{
var res = _context.Response;
res.StatusCode = status;
res.ContentType = "text/html";
var httpResponse = _context.Response;
httpResponse.StatusCode = status;
httpResponse.ContentType = "text/html";
var content = new StringBuilder(64);
content.AppendFormat("<html><head><title>EonaCat.Network Error</title></head><body><h1>{0} {1}", status, res.StatusDescription);
content.AppendFormat("<html><head><title>EonaCat.Network Error</title></head><body><h1>{0} {1}", status, httpResponse.StatusDescription);
if (message != null && message.Length > 0)
{
content.AppendFormat(" ({0})</h1></body></html>", message);
@ -616,12 +616,12 @@ namespace EonaCat.Network
content.Append("</h1></body></html>");
}
var enc = Encoding.UTF8;
var entity = enc.GetBytes(content.ToString());
res.ContentEncoding = enc;
res.ContentLength64 = entity.LongLength;
var encoding = Encoding.UTF8;
var entity = encoding.GetBytes(content.ToString());
httpResponse.ContentEncoding = encoding;
httpResponse.ContentLength64 = entity.LongLength;
res.Close(entity, true);
httpResponse.Close(entity, true);
}
catch
{

View File

@ -80,11 +80,13 @@ namespace EonaCat.Network
string password, string realm, string method, string entity
)
{
var copied = new NameValueCollection(_parameters);
copied["password"] = password;
copied["realm"] = realm;
copied["method"] = method;
copied["entity"] = entity;
var copied = new NameValueCollection(_parameters)
{
["password"] = password,
["realm"] = realm,
["method"] = method,
["entity"] = entity
};
var expected = AuthenticationResponse.CreateRequestDigest(copied);
return _parameters["response"] == expected;

View File

@ -68,8 +68,7 @@ namespace EonaCat.Network
/// <returns>True if the header is restricted, false otherwise.</returns>
public bool IsRestricted(bool response)
{
return (Type & HttpHeaderType.Restricted) == HttpHeaderType.Restricted
&& (response ? IsResponse : IsRequest);
return (Type & HttpHeaderType.Restricted) == HttpHeaderType.Restricted && (response ? IsResponse : IsRequest);
}
}
}

View File

@ -18,19 +18,19 @@ namespace EonaCat.Network
private string _certFolderPath;
private readonly Dictionary<HttpConnection, HttpConnection> _connections;
private readonly object _connectionsSync;
private readonly List<HttpListenerContext> _ctxQueue;
private readonly object _ctxQueueSync;
private readonly Dictionary<HttpListenerContext, HttpListenerContext> _ctxRegistry;
private readonly object _ctxRegistrySync;
private readonly List<HttpListenerContext> contextQueue;
private readonly object _contextQueueLock;
private readonly Dictionary<HttpListenerContext, HttpListenerContext> _contextRegistry;
private readonly object _contextRegistryLock;
private static readonly string _defaultRealm;
private bool _ignoreWriteExceptions;
private volatile bool _listening;
private readonly HttpListenerPrefixCollection _prefixes;
private string _realm;
private SSLConfigurationServer _sslConfig;
private SSLConfigServer _sslConfig;
private Func<IIdentity, NetworkCredential> _userCredFinder;
private readonly List<HttpListenerAsyncResult> _waitQueue;
private readonly object _waitQueueSync;
private readonly object _waitQueueLock;
static HttpListener()
{
@ -47,16 +47,16 @@ namespace EonaCat.Network
_connections = new Dictionary<HttpConnection, HttpConnection>();
_connectionsSync = ((ICollection)_connections).SyncRoot;
_ctxQueue = new List<HttpListenerContext>();
_ctxQueueSync = ((ICollection)_ctxQueue).SyncRoot;
contextQueue = new List<HttpListenerContext>();
_contextQueueLock = ((ICollection)contextQueue).SyncRoot;
_ctxRegistry = new Dictionary<HttpListenerContext, HttpListenerContext>();
_ctxRegistrySync = ((ICollection)_ctxRegistry).SyncRoot;
_contextRegistry = new Dictionary<HttpListenerContext, HttpListenerContext>();
_contextRegistryLock = ((ICollection)_contextRegistry).SyncRoot;
_prefixes = new HttpListenerPrefixCollection(this);
_waitQueue = new List<HttpListenerAsyncResult>();
_waitQueueSync = ((ICollection)_waitQueue).SyncRoot;
_waitQueueLock = ((ICollection)_waitQueue).SyncRoot;
}
internal bool IsDisposed { get; private set; }
@ -154,12 +154,12 @@ namespace EonaCat.Network
}
}
public SSLConfigurationServer SslConfiguration
public SSLConfigServer SslConfiguration
{
get
{
CheckDisposed();
return _sslConfig ??= new SSLConfigurationServer();
return _sslConfig ??= new SSLConfigServer();
}
set
@ -197,9 +197,9 @@ namespace EonaCat.Network
}
}
private void cleanupConnections()
private void CleanupConnections()
{
HttpConnection[] conns = null;
HttpConnection[] httpConnections = null;
lock (_connectionsSync)
{
if (_connections.Count == 0)
@ -209,29 +209,29 @@ namespace EonaCat.Network
// Need to copy this since closing will call the RemoveConnection method.
var keys = _connections.Keys;
conns = new HttpConnection[keys.Count];
keys.CopyTo(conns, 0);
httpConnections = new HttpConnection[keys.Count];
keys.CopyTo(httpConnections, 0);
_connections.Clear();
}
for (var i = conns.Length - 1; i >= 0; i--)
for (var i = httpConnections.Length - 1; i >= 0; i--)
{
conns[i].Close(true);
httpConnections[i].Close(true);
}
}
private void cleanupContextQueue(bool sendServiceUnavailable)
private void CleanupContextQueue(bool sendServiceUnavailable)
{
HttpListenerContext[] ctxs = null;
lock (_ctxQueueSync)
HttpListenerContext[] httpContextQueues = null;
lock (_contextQueueLock)
{
if (_ctxQueue.Count == 0)
if (contextQueue.Count == 0)
{
return;
}
ctxs = _ctxQueue.ToArray();
_ctxQueue.Clear();
httpContextQueues = contextQueue.ToArray();
contextQueue.Clear();
}
if (!sendServiceUnavailable)
@ -239,54 +239,54 @@ namespace EonaCat.Network
return;
}
foreach (var ctx in ctxs)
foreach (var currentContext in httpContextQueues)
{
var res = ctx.Response;
res.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
res.Close();
var response = currentContext.Response;
response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
response.Close();
}
}
private void cleanupContextRegistry()
private void CleanupContextRegistry()
{
HttpListenerContext[] ctxs = null;
lock (_ctxRegistrySync)
HttpListenerContext[] contexts = null;
lock (_contextRegistryLock)
{
if (_ctxRegistry.Count == 0)
if (_contextRegistry.Count == 0)
{
return;
}
// Need to copy this since closing will call the UnregisterContext method.
var keys = _ctxRegistry.Keys;
ctxs = new HttpListenerContext[keys.Count];
keys.CopyTo(ctxs, 0);
_ctxRegistry.Clear();
var keys = _contextRegistry.Keys;
contexts = new HttpListenerContext[keys.Count];
keys.CopyTo(contexts, 0);
_contextRegistry.Clear();
}
for (var i = ctxs.Length - 1; i >= 0; i--)
for (var i = contexts.Length - 1; i >= 0; i--)
{
ctxs[i].Connection.Close(true);
contexts[i].Connection.Close(true);
}
}
private void cleanupWaitQueue(Exception exception)
private void CleanupWaitQueue(Exception exception)
{
HttpListenerAsyncResult[] aress = null;
lock (_waitQueueSync)
HttpListenerAsyncResult[] results = null;
lock (_waitQueueLock)
{
if (_waitQueue.Count == 0)
{
return;
}
aress = _waitQueue.ToArray();
results = _waitQueue.ToArray();
_waitQueue.Clear();
}
foreach (var ares in aress)
foreach (var currentResult in results)
{
ares.Complete(exception);
currentResult.Complete(exception);
}
}
@ -298,19 +298,19 @@ namespace EonaCat.Network
EndPointManager.RemoveListener(this);
}
lock (_ctxRegistrySync)
lock (_contextRegistryLock)
{
cleanupContextQueue(!force);
CleanupContextQueue(!force);
}
cleanupContextRegistry();
cleanupConnections();
cleanupWaitQueue(new ObjectDisposedException(GetType().ToString()));
CleanupContextRegistry();
CleanupConnections();
CleanupWaitQueue(new ObjectDisposedException(GetType().ToString()));
IsDisposed = true;
}
private HttpListenerAsyncResult getAsyncResultFromQueue()
private HttpListenerAsyncResult GetAsyncResultFromQueue()
{
if (_waitQueue.Count == 0)
{
@ -323,15 +323,15 @@ namespace EonaCat.Network
return ares;
}
private HttpListenerContext getContextFromQueue()
private HttpListenerContext GetContextFromQueue()
{
if (_ctxQueue.Count == 0)
if (contextQueue.Count == 0)
{
return null;
}
var ctx = _ctxQueue[0];
_ctxQueue.RemoveAt(0);
var ctx = contextQueue[0];
contextQueue.RemoveAt(0);
return ctx;
}
@ -357,14 +357,14 @@ namespace EonaCat.Network
internal HttpListenerAsyncResult BeginGetContext(HttpListenerAsyncResult asyncResult)
{
lock (_ctxRegistrySync)
lock (_contextRegistryLock)
{
if (!_listening)
{
throw new HttpListenerException(995);
}
var ctx = getContextFromQueue();
var ctx = GetContextFromQueue();
if (ctx == null)
{
_waitQueue.Add(asyncResult);
@ -404,23 +404,23 @@ namespace EonaCat.Network
return false;
}
lock (_ctxRegistrySync)
lock (_contextRegistryLock)
{
if (!_listening)
{
return false;
}
_ctxRegistry[context] = context;
_contextRegistry[context] = context;
var ares = getAsyncResultFromQueue();
if (ares == null)
var result = GetAsyncResultFromQueue();
if (result == null)
{
_ctxQueue.Add(context);
contextQueue.Add(context);
}
else
{
ares.Complete(context);
result.Complete(context);
}
return true;
@ -455,9 +455,9 @@ namespace EonaCat.Network
internal void UnregisterContext(HttpListenerContext context)
{
lock (_ctxRegistrySync)
lock (_contextRegistryLock)
{
_ctxRegistry.Remove(context);
_contextRegistry.Remove(context);
}
}
@ -522,23 +522,23 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(asyncResult));
}
if (asyncResult is not HttpListenerAsyncResult ares)
if (asyncResult is not HttpListenerAsyncResult result)
{
throw new ArgumentException("A wrong IAsyncResult.", nameof(asyncResult));
}
if (ares.EndCalled)
if (result.EndCalled)
{
throw new InvalidOperationException("This IAsyncResult cannot be reused.");
}
ares.EndCalled = true;
if (!ares.IsCompleted)
result.EndCalled = true;
if (!result.IsCompleted)
{
ares.AsyncWaitHandle.WaitOne();
result.AsyncWaitHandle.WaitOne();
}
return ares.GetContext(); // This may throw an exception.
return result.GetContext();
}
/// <summary>
@ -558,10 +558,10 @@ namespace EonaCat.Network
throw new InvalidOperationException("The listener hasn't been started.");
}
var ares = BeginGetContext(new HttpListenerAsyncResult(null, null));
ares.InGet = true;
var result = BeginGetContext(new HttpListenerAsyncResult(null, null));
result.InGet = true;
return EndGetContext(ares);
return EndGetContext(result);
}
/// <summary>
@ -593,14 +593,14 @@ namespace EonaCat.Network
_listening = false;
EndPointManager.RemoveListener(this);
lock (_ctxRegistrySync)
lock (_contextRegistryLock)
{
cleanupContextQueue(true);
CleanupContextQueue(true);
}
cleanupContextRegistry();
cleanupConnections();
cleanupWaitQueue(new HttpListenerException(995, "The listener is closed."));
CleanupContextRegistry();
CleanupConnections();
CleanupWaitQueue(new HttpListenerException(995, "The listener is closed."));
}
/// <summary>

View File

@ -86,10 +86,7 @@ namespace EonaCat.Network
asyncResult._completed = true;
var waitHandle = asyncResult._waitHandle;
if (waitHandle != null)
{
waitHandle.Set();
}
waitHandle?.Set();
}
var callback = asyncResult._callback;

View File

@ -11,7 +11,7 @@ namespace EonaCat.Network
/// </summary>
public sealed class HttpListenerContext
{
private HttpListenerWebSocketContext _websocketContext;
private HttpListenerWSContext _websocketContext;
/// <summary>
/// Initializes a new instance of the <see cref="HttpListenerContext"/> class.
@ -124,8 +124,8 @@ namespace EonaCat.Network
/// Accepts a WebSocket connection with the specified protocol.
/// </summary>
/// <param name="protocol">The WebSocket subprotocol to negotiate.</param>
/// <returns>The <see cref="HttpListenerWebSocketContext"/> for the WebSocket connection.</returns>
public HttpListenerWebSocketContext AcceptWebSocket(string protocol)
/// <returns>The <see cref="HttpListenerWSContext"/> for the WebSocket connection.</returns>
public HttpListenerWSContext AcceptWebSocket(string protocol)
{
if (_websocketContext != null)
{
@ -145,7 +145,7 @@ namespace EonaCat.Network
}
}
_websocketContext = new HttpListenerWebSocketContext(this, protocol);
_websocketContext = new HttpListenerWSContext(this, protocol);
return _websocketContext;
}
}

View File

@ -251,8 +251,7 @@ namespace EonaCat.Network
if (lower == "content-length")
{
long len;
if (long.TryParse(val, out len) && len >= 0)
if (long.TryParse(val, out long len) && len >= 0)
{
ContentLength64 = len;
_contentLengthSet = true;
@ -359,13 +358,13 @@ namespace EonaCat.Network
{
try
{
var ares = InputStream.BeginRead(buff, 0, len, null, null);
if (!ares.IsCompleted && !ares.AsyncWaitHandle.WaitOne(100))
var result = InputStream.BeginRead(buff, 0, len, null, null);
if (!result.IsCompleted && !result.AsyncWaitHandle.WaitOne(100))
{
return false;
}
if (InputStream.EndRead(ares) <= 0)
if (InputStream.EndRead(result) <= 0)
{
return true;
}

View File

@ -218,8 +218,7 @@ namespace EonaCat.Network
return;
}
Uri uri = null;
if (!value.MaybeUri() || !Uri.TryCreate(value, UriKind.Absolute, out uri))
if (!value.MaybeUri() || !Uri.TryCreate(value, UriKind.Absolute, out Uri uri))
{
throw new ArgumentException("Not an absolute URL.", nameof(value));
}
@ -405,10 +404,7 @@ namespace EonaCat.Network
if (templateResponse._headers != null)
{
if (_headers != null)
{
_headers.Clear();
}
_headers?.Clear();
Headers.Add(templateResponse._headers);
}
@ -447,8 +443,7 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(url));
}
Uri uri = null;
if (!url.MaybeUri() || !Uri.TryCreate(url, UriKind.Absolute, out uri))
if (!url.MaybeUri() || !Uri.TryCreate(url, UriKind.Absolute, out Uri uri))
{
throw new ArgumentException("Not an absolute URL.", nameof(url));
}

View File

@ -9,7 +9,7 @@ namespace EonaCat.Network
internal class HttpStreamAsyncResult : IAsyncResult
{
private readonly AsyncCallback _callback;
private bool _completed;
private bool _isCompleted;
private readonly object _sync;
private ManualResetEvent _waitHandle;
@ -40,7 +40,7 @@ namespace EonaCat.Network
{
lock (_sync)
{
return _waitHandle ??= new ManualResetEvent(_completed);
return _waitHandle ??= new ManualResetEvent(_isCompleted);
}
}
}
@ -53,7 +53,7 @@ namespace EonaCat.Network
{
lock (_sync)
{
return _completed;
return _isCompleted;
}
}
}
@ -62,17 +62,14 @@ namespace EonaCat.Network
{
lock (_sync)
{
if (_completed)
if (_isCompleted)
{
return;
}
_completed = true;
_isCompleted = true;
if (_waitHandle != null)
{
_waitHandle.Set();
}
_waitHandle?.Set();
_callback?.Invoke(this);
}

View File

@ -71,7 +71,7 @@ namespace EonaCat.Network
{
if (_entities == null)
{
initEntities();
GenerateHtmlEntityRefrencesDictionary();
}
return _entities;
@ -90,10 +90,9 @@ namespace EonaCat.Network
: -1;
}
private static void initEntities()
private static void GenerateHtmlEntityRefrencesDictionary()
{
// Build the dictionary of HTML entity references.
// This list comes from the HTML 4.01 W3C recommendation.
_entities = new Dictionary<string, char>
{
{ "nbsp", '\u00A0' },
@ -491,8 +490,7 @@ namespace EonaCat.Network
}
else if (requestUri.MaybeUri())
{
Uri uri;
var valid = Uri.TryCreate(requestUri, UriKind.Absolute, out uri) &&
var valid = Uri.TryCreate(requestUri, UriKind.Absolute, out Uri uri) &&
(((schm = uri.Scheme).StartsWith("http") && !websocketRequest) ||
(schm.StartsWith("ws") && websocketRequest));
@ -523,8 +521,7 @@ namespace EonaCat.Network
var url = string.Format("{0}://{1}{2}", schm, host, path);
Uri res;
if (!Uri.TryCreate(url, UriKind.Absolute, out res))
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri res))
{
return null;
}

View File

@ -5,12 +5,24 @@ using System;
namespace EonaCat.Network
{
/// <summary>
/// Represents HTTP versions.
/// </summary>
public class HttpVersion
{
/// <summary>
/// Gets the HTTP version 1.0.
/// </summary>
public static readonly Version Version10 = new Version(1, 0);
/// <summary>
/// Gets the HTTP version 1.1.
/// </summary>
public static readonly Version Version11 = new Version(1, 1);
/// <summary>
/// Initializes a new instance of the <see cref="HttpVersion"/> class.
/// </summary>
public HttpVersion()
{
}

View File

@ -6,7 +6,15 @@ namespace EonaCat.Network
internal enum LineState
{
None,
Cr,
Lf
/// <summary>
/// Moves the cursor to the beginning of the current line
/// </summary>
CarriageReturn,
/// <summary>
/// Moves the cursor down to the next line and then to the beginning of the line
/// </summary>
LineFeed
}
}

View File

@ -8,24 +8,24 @@ using System.Security.Cryptography.X509Certificates;
namespace EonaCat.Network
{
public class SSLConfigurationClient
public class SSLConfigClient
{
private LocalCertificateSelectionCallback _clientCertSelectionCallback;
private X509CertificateCollection _clientCertificates;
private RemoteCertificateValidationCallback _serverCertValidationCallback;
public SSLConfigurationClient()
public SSLConfigClient()
{
SslProtocols = SslProtocols.Tls12;
}
public SSLConfigurationClient(string targetHost)
public SSLConfigClient(string targetHost)
{
TargetHost = targetHost;
SslProtocols = SslProtocols.Tls12;
}
public SSLConfigurationClient(SSLConfigurationClient configuration)
public SSLConfigClient(SSLConfigClient configuration)
{
if (configuration == null)
{

View File

@ -8,22 +8,22 @@ using System.Security.Cryptography.X509Certificates;
namespace EonaCat.Network
{
public class SSLConfigurationServer
public class SSLConfigServer
{
private RemoteCertificateValidationCallback _clientCertValidationCallback;
private RemoteCertificateValidationCallback _clientCertificationValidationCallback;
public SSLConfigurationServer()
public SSLConfigServer()
{
SslProtocols = SslProtocols.Tls12;
}
public SSLConfigurationServer(X509Certificate2 certificate)
public SSLConfigServer(X509Certificate2 certificate)
{
Certificate = certificate;
SslProtocols = SslProtocols.Tls12;
}
public SSLConfigurationServer(SSLConfigurationServer configuration)
public SSLConfigServer(SSLConfigServer configuration)
{
if (configuration == null)
{
@ -32,7 +32,7 @@ namespace EonaCat.Network
CheckForCertificateRevocation = configuration.CheckForCertificateRevocation;
IsClientCertificateRequired = configuration.IsClientCertificateRequired;
_clientCertValidationCallback = configuration._clientCertValidationCallback;
_clientCertificationValidationCallback = configuration._clientCertificationValidationCallback;
SslProtocols = configuration.SslProtocols;
Certificate = configuration.Certificate;
}
@ -45,14 +45,14 @@ namespace EonaCat.Network
{
get
{
_clientCertValidationCallback ??= ValidateClientCertificate;
_clientCertificationValidationCallback ??= ValidateClientCertificate;
return _clientCertValidationCallback;
return _clientCertificationValidationCallback;
}
set
{
_clientCertValidationCallback = value;
_clientCertificationValidationCallback = value;
}
}

View File

@ -54,7 +54,7 @@ namespace EonaCat.Network
// Returns 0 if we can keep reading from the base stream,
// > 0 if we read something from the buffer,
// -1 if we had a content length set and we finished reading that many bytes.
private int fillFromBuffer(byte[] buffer, int offset, int count)
private int FillFromBuffer(byte[] buffer, int offset, int count)
{
if (buffer == null)
{
@ -71,8 +71,8 @@ namespace EonaCat.Network
throw new ArgumentOutOfRangeException(nameof(count), "A negative value.");
}
var len = buffer.Length;
if (offset + count > len)
var bufferLength = buffer.Length;
if (offset + count > bufferLength)
{
throw new ArgumentException(
"The sum of 'offset' and 'count' is greater than 'buffer' length.");
@ -117,17 +117,16 @@ namespace EonaCat.Network
throw new ObjectDisposedException(GetType().ToString());
}
var nread = fillFromBuffer(buffer, offset, count);
var nread = FillFromBuffer(buffer, offset, count);
if (nread > 0 || nread == -1)
{
var ares = new HttpStreamAsyncResult(callback, state);
ares.Buffer = buffer;
ares.Offset = offset;
ares.Count = count;
ares.SyncRead = nread > 0 ? nread : 0;
ares.Complete();
return ares;
var result = new HttpStreamAsyncResult(callback, state);
result.Buffer = buffer;
result.Offset = offset;
result.Count = count;
result.SyncRead = nread > 0 ? nread : 0;
result.Complete();
return result;
}
// Avoid reading past the end of the request to allow for HTTP pipelining.
@ -164,13 +163,13 @@ namespace EonaCat.Network
if (asyncResult is HttpStreamAsyncResult)
{
var ares = (HttpStreamAsyncResult)asyncResult;
if (!ares.IsCompleted)
var result = (HttpStreamAsyncResult)asyncResult;
if (!result.IsCompleted)
{
ares.AsyncWaitHandle.WaitOne();
result.AsyncWaitHandle.WaitOne();
}
return ares.SyncRead;
return result.SyncRead;
}
// Close on exception?
@ -200,7 +199,7 @@ namespace EonaCat.Network
}
// Call the fillFromBuffer method to check for buffer boundaries even when _bodyLeft is 0.
var nread = fillFromBuffer(buffer, offset, count);
var nread = FillFromBuffer(buffer, offset, count);
if (nread == -1) // No more bytes available (Content-Length).
{
return 0;

View File

@ -11,24 +11,24 @@ namespace EonaCat.Network
private bool _dataSet;
private readonly byte[] _rawData;
internal MessageEventArgs(WebSocketFrame frame)
internal MessageEventArgs(WSFrame frame)
{
Opcode = frame.Opcode;
_rawData = frame.PayloadData.ApplicationData;
}
internal MessageEventArgs(Opcode opcode, byte[] rawData)
internal MessageEventArgs(OperationCode opcode, byte[] rawData)
{
if ((ulong)rawData.LongLength > PayloadData.MaxLength)
{
throw new WebSocketException(CloseStatusCode.TooBig);
throw new WSException(CloseStatusCode.TooBig);
}
Opcode = opcode;
_rawData = rawData;
}
internal Opcode Opcode { get; }
internal OperationCode Opcode { get; }
public string Data
{
@ -39,11 +39,11 @@ namespace EonaCat.Network
}
}
public bool IsBinary => Opcode == Opcode.Binary;
public bool IsBinary => Opcode == OperationCode.Binary;
public bool IsPing => Opcode == Opcode.Ping;
public bool IsPing => Opcode == OperationCode.Ping;
public bool IsText => Opcode == Opcode.Text;
public bool IsText => Opcode == OperationCode.Text;
public byte[] RawData
{
@ -61,7 +61,7 @@ namespace EonaCat.Network
return;
}
if (Opcode == Opcode.Binary)
if (Opcode == OperationCode.Binary)
{
_dataSet = true;
return;

View File

@ -406,9 +406,9 @@ namespace EonaCat.Network
return opcode > 0x7 && opcode < 0x10;
}
internal static bool IsControl(this Opcode opcode)
internal static bool IsControl(this OperationCode opcode)
{
return opcode >= Opcode.Close;
return opcode >= OperationCode.Close;
}
internal static bool IsData(this byte opcode)
@ -416,9 +416,9 @@ namespace EonaCat.Network
return opcode == 0x1 || opcode == 0x2;
}
internal static bool IsData(this Opcode opcode)
internal static bool IsData(this OperationCode opcode)
{
return opcode == Opcode.Text || opcode == Opcode.Binary;
return opcode == OperationCode.Text || opcode == OperationCode.Binary;
}
internal static bool IsPortNumber(this int value)
@ -428,10 +428,10 @@ namespace EonaCat.Network
internal static bool IsReserved(this ushort code)
{
return code == 1004
|| code == 1005
|| code == 1006
|| code == 1015;
return code == (ushort)CloseStatusCode.Undefined
|| code == (ushort)CloseStatusCode.NoStatus
|| code == (ushort)CloseStatusCode.Abnormal
|| code == (ushort)CloseStatusCode.TlsHandshakeFailure;
}
internal static bool IsReserved(this CloseStatusCode code)
@ -444,7 +444,7 @@ namespace EonaCat.Network
internal static bool IsSupported(this byte opcode)
{
return Enum.IsDefined(typeof(Opcode), opcode);
return Enum.IsDefined(typeof(OperationCode), opcode);
}
internal static bool IsText(this string value)
@ -855,8 +855,7 @@ namespace EonaCat.Network
return null;
}
System.Net.IPAddress addr;
if (System.Net.IPAddress.TryParse(value, out addr))
if (System.Net.IPAddress.TryParse(value, out System.Net.IPAddress addr))
{
return addr;
}
@ -1542,7 +1541,7 @@ namespace EonaCat.Network
? BitConverter.GetBytes((uint)(object)value)
: type == typeof(ulong)
? BitConverter.GetBytes((ulong)(object)value)
: WebSocket.EmptyBytes;
: WSClient.EmptyBytes;
if (bytes.Length > 1 && !order.IsHostOrder())
{
@ -1586,9 +1585,8 @@ namespace EonaCat.Network
public static Uri ToUri(this string value)
{
Uri ret;
Uri.TryCreate(
value, value.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out ret
value, value.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri ret
);
return ret;

View File

@ -3,7 +3,7 @@
namespace EonaCat.Network
{
internal enum Opcode : byte
internal enum OperationCode : byte
{
Cont = 0x0,

View File

@ -28,10 +28,10 @@ namespace EonaCat.Network
internal PayloadData()
{
_code = 1005;
_code = (ushort)CloseStatusCode.NoStatus;
_reason = string.Empty;
_data = WebSocket.EmptyBytes;
_data = WSClient.EmptyBytes;
_codeSet = true;
_reasonSet = true;
@ -68,7 +68,7 @@ namespace EonaCat.Network
{
_code = _length > 1
? _data.SubArray(0, 2).ToUInt16(ByteOrder.Big)
: (ushort)1005;
: (ushort)CloseStatusCode.NoStatus;
_codeSet = true;
}
@ -104,7 +104,7 @@ namespace EonaCat.Network
public byte[] ExtensionData => ExtensionDataLength > 0
? _data.SubArray(0, ExtensionDataLength)
: WebSocket.EmptyBytes;
: WSClient.EmptyBytes;
public ulong Length => (ulong)_length;

View File

@ -74,8 +74,7 @@ namespace EonaCat.Network
throw new ArgumentException("It contains '..'.", nameof(path));
}
byte[] contents;
tryReadFile(createFilePath(path), out contents);
tryReadFile(createFilePath(path), out byte[] contents);
return contents;
}

View File

@ -40,11 +40,9 @@ namespace EonaCat.Network
throw new ArgumentException("An empty string.", nameof(url));
}
Uri uri;
string msg;
if (!tryCreateUri(url, out uri, out msg))
if (!tryCreateUri(url, out Uri uri, out string message))
{
throw new ArgumentException(msg, nameof(url));
throw new ArgumentException(message, nameof(url));
}
var host = uri.GetDnsSafeHost(true);
@ -52,14 +50,14 @@ namespace EonaCat.Network
var addr = host.ToIPAddress();
if (addr == null)
{
msg = "The host part could not be converted to an IP address.";
throw new ArgumentException(msg, nameof(url));
message = "The host part could not be converted to an IP address.";
throw new ArgumentException(message, nameof(url));
}
if (!addr.IsLocal())
{
msg = "The IP address of the host is not a local IP address.";
throw new ArgumentException(msg, nameof(url));
message = "The IP address of the host is not a local IP address.";
throw new ArgumentException(message, nameof(url));
}
init(host, addr, uri.Port, uri.Scheme == "https");
@ -69,8 +67,8 @@ namespace EonaCat.Network
{
if (!port.IsPortNumber())
{
var msg = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), msg);
var message = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), message);
}
init("*", System.Net.IPAddress.Any, port, secure);
@ -95,8 +93,8 @@ namespace EonaCat.Network
if (!port.IsPortNumber())
{
var msg = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), msg);
var message = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), message);
}
init(address.ToString(true), address, port, secure);
@ -113,18 +111,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -190,18 +187,17 @@ namespace EonaCat.Network
throw new ArgumentException("An absolute root.", nameof(value));
}
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -240,18 +236,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -269,18 +264,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -289,14 +283,14 @@ namespace EonaCat.Network
}
}
public SSLConfigurationServer SslConfiguration
public SSLConfigServer SslConfiguration
{
get
{
if (!IsSecure)
{
var msg = "This instance does not provide secure connections.";
throw new InvalidOperationException(msg);
var message = "This instance does not provide secure connections.";
throw new InvalidOperationException(message);
}
return _listener.SslConfiguration;
@ -312,18 +306,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -381,7 +374,7 @@ namespace EonaCat.Network
{
try
{
WebSocketServices.Stop(1006, string.Empty);
WebSocketServices.Stop((ushort)CloseStatusCode.Abnormal, string.Empty);
}
finally
{
@ -440,15 +433,6 @@ namespace EonaCat.Network
return true;
}
private string createFilePath(string childPath)
{
childPath = childPath.TrimStart('/', '\\');
return new StringBuilder(_docRootPath, 32)
.AppendFormat("/{0}", childPath)
.ToString()
.Replace('\\', '/');
}
private static HttpListener createListener(
string hostname, int port, bool secure
)
@ -512,12 +496,11 @@ namespace EonaCat.Network
context.Response.Close();
}
private void processRequest(HttpListenerWebSocketContext context)
private void processRequest(HttpListenerWSContext context)
{
var path = context.RequestUri.AbsolutePath;
WSEndpointHost host;
if (!WebSocketServices.InternalTryGetServiceHost(path, out host))
if (!WebSocketServices.InternalTryGetServiceHost(path, out WSEndpointHost host))
{
context.Close(HttpStatusCode.NotImplemented);
return;
@ -572,10 +555,7 @@ namespace EonaCat.Network
Logger.Error(ex.Message);
Logger.Debug(ex.ToString());
if (ctx != null)
{
ctx.Connection.Close(true);
}
ctx?.Connection.Close(true);
break;
}
@ -623,7 +603,7 @@ namespace EonaCat.Network
}
catch
{
WebSocketServices.Stop(1011, string.Empty);
WebSocketServices.Stop((ushort)CloseStatusCode.ServerError, string.Empty);
throw;
}
@ -637,10 +617,10 @@ namespace EonaCat.Network
{
_listener.Start();
}
catch (Exception ex)
catch (Exception exception)
{
var msg = "The underlying listener has failed to start.";
throw new InvalidOperationException(msg, ex);
var message = "The underlying listener has failed to start.";
throw new InvalidOperationException(message, exception);
}
_receiveThread = new Thread(new ThreadStart(receiveRequest));
@ -650,7 +630,7 @@ namespace EonaCat.Network
private void stop(ushort code, string reason)
{
if (_state == ServerState.Ready)
if (_state == ServerState.Started)
{
Logger.Info("The server is not started.");
return;
@ -796,10 +776,9 @@ namespace EonaCat.Network
{
if (IsSecure)
{
string msg;
if (!checkCertificate(out msg))
if (!checkCertificate(out string message))
{
throw new InvalidOperationException(msg);
throw new InvalidOperationException(message);
}
}
@ -808,42 +787,41 @@ namespace EonaCat.Network
public void Stop()
{
stop(1005, string.Empty);
stop((ushort)CloseStatusCode.NoStatus, string.Empty);
}
public void Stop(ushort code, string reason)
{
if (!code.IsCloseStatusCode())
{
var msg = "Less than 1000 or greater than 4999.";
throw new ArgumentOutOfRangeException(nameof(code), msg);
var message = "Less than 1000 or greater than 4999.";
throw new ArgumentOutOfRangeException(nameof(code), message);
}
if (code == 1010)
if (code == (ushort)CloseStatusCode.MandatoryExtension)
{
var msg = "1010 cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = $"{(ushort)CloseStatusCode.MandatoryExtension} cannot be used.";
throw new ArgumentException(message, nameof(code));
}
if (!reason.IsNullOrEmpty())
{
if (code == 1005)
if (code == (ushort)CloseStatusCode.NoStatus)
{
var msg = "1005 cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = $"{(ushort)CloseStatusCode.NoStatus} cannot be used.";
throw new ArgumentException(message, nameof(code));
}
byte[] bytes;
if (!reason.TryGetUTF8EncodedBytes(out bytes))
if (!reason.TryGetUTF8EncodedBytes(out byte[] bytes))
{
var msg = "It could not be UTF-8-encoded.";
throw new ArgumentException(msg, nameof(reason));
var message = "It could not be UTF-8-encoded.";
throw new ArgumentException(message, nameof(reason));
}
if (bytes.Length > 123)
{
var msg = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), msg);
var message = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), message);
}
}
@ -854,29 +832,28 @@ namespace EonaCat.Network
{
if (code == CloseStatusCode.MandatoryExtension)
{
var msg = "MandatoryExtension cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = "MandatoryExtension cannot be used.";
throw new ArgumentException(message, nameof(code));
}
if (!reason.IsNullOrEmpty())
{
if (code == CloseStatusCode.NoStatus)
{
var msg = "NoStatus cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = "NoStatus cannot be used.";
throw new ArgumentException(message, nameof(code));
}
byte[] bytes;
if (!reason.TryGetUTF8EncodedBytes(out bytes))
if (!reason.TryGetUTF8EncodedBytes(out byte[] bytes))
{
var msg = "It could not be UTF-8-encoded.";
throw new ArgumentException(msg, nameof(reason));
var message = "It could not be UTF-8-encoded.";
throw new ArgumentException(message, nameof(reason));
}
if (bytes.Length > 123)
{
var msg = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), msg);
var message = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), message);
}
}

View File

@ -7,7 +7,7 @@ namespace EonaCat.Network
{
public interface IWSSession
{
WebSocketContext Context { get; }
WSContext Context { get; }
string ID { get; }
@ -15,6 +15,6 @@ namespace EonaCat.Network
DateTime StartTime { get; }
WebSocketState State { get; }
WSState State { get; }
}
}

View File

@ -5,7 +5,7 @@ namespace EonaCat.Network
{
internal enum ServerState
{
Ready,
Started,
Start,
ShuttingDown,
Stop

View File

@ -10,7 +10,7 @@ namespace EonaCat.Network
{
private bool _emitOnPing;
private string _protocol;
private WebSocket _websocket;
private WSClient _websocket;
protected WSEndpoint()
{
@ -19,7 +19,7 @@ namespace EonaCat.Network
protected WSSessionManager Sessions { get; private set; }
public WebSocketContext Context { get; private set; }
public WSContext Context { get; private set; }
public Func<CookieCollection, CookieCollection, bool> CookiesValidator { get; set; }
@ -57,7 +57,7 @@ namespace EonaCat.Network
set
{
if (State != WebSocketState.Connecting)
if (State != WSState.Connecting)
{
return;
}
@ -73,9 +73,9 @@ namespace EonaCat.Network
public DateTime StartTime { get; private set; }
public WebSocketState State => _websocket != null ? _websocket.ReadyState : WebSocketState.Connecting;
public WSState State => _websocket != null ? _websocket.ReadyState : WSState.Connecting;
private string checkHandshakeRequest(WebSocketContext context)
private string checkHandshakeRequest(WSContext context)
{
return OriginValidator != null && !OriginValidator(context.Origin)
? "Includes no Origin header, or it has an invalid value."
@ -119,7 +119,7 @@ namespace EonaCat.Network
OnOpen();
}
internal void Start(WebSocketContext context, WSSessionManager sessions)
internal void Start(WSContext context, WSSessionManager sessions)
{
if (_websocket != null)
{
@ -178,58 +178,37 @@ namespace EonaCat.Network
protected void Send(byte[] data)
{
if (_websocket != null)
{
_websocket.Send(data);
}
_websocket?.Send(data);
}
protected void Send(FileInfo file)
{
if (_websocket != null)
{
_websocket.Send(file);
}
_websocket?.Send(file);
}
protected void Send(string data)
{
if (_websocket != null)
{
_websocket.Send(data);
}
_websocket?.Send(data);
}
protected void SendAsync(byte[] data, Action<bool> completed)
{
if (_websocket != null)
{
_websocket.SendAsync(data, completed);
}
_websocket?.SendAsync(data, completed);
}
protected void SendAsync(FileInfo file, Action<bool> completed)
{
if (_websocket != null)
{
_websocket.SendAsync(file, completed);
}
_websocket?.SendAsync(file, completed);
}
protected void SendAsync(string data, Action<bool> completed)
{
if (_websocket != null)
{
_websocket.SendAsync(data, completed);
}
_websocket?.SendAsync(data, completed);
}
protected void SendAsync(Stream stream, int length, Action<bool> completed)
{
if (_websocket != null)
{
_websocket.SendAsync(stream, length, completed);
}
_websocket?.SendAsync(stream, length, completed);
}
}
}

View File

@ -52,7 +52,7 @@ namespace EonaCat.Network
Sessions.Start();
}
internal void StartSession(WebSocketContext context)
internal void StartSession(WSContext context)
{
CreateSession().Start(context, Sessions);
}

View File

@ -21,7 +21,7 @@ namespace EonaCat.Network
{
_clean = true;
_hosts = new Dictionary<string, WSEndpointHost>();
_state = ServerState.Ready;
_state = ServerState.Started;
_sync = ((ICollection)_hosts).SyncRoot;
_waitTime = TimeSpan.FromSeconds(1);
}
@ -69,12 +69,11 @@ namespace EonaCat.Network
if (path.IndexOfAny(new[] { '?', '#' }) > -1)
{
var msg = "It includes either or both query and fragment components.";
throw new ArgumentException(msg, nameof(path));
var message = "It includes either or both query and fragment components.";
throw new ArgumentException(message, nameof(path));
}
WSEndpointHost host;
InternalTryGetServiceHost(path, out host);
InternalTryGetServiceHost(path, out WSEndpointHost host);
return host;
}
@ -89,18 +88,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -139,18 +137,17 @@ namespace EonaCat.Network
throw new ArgumentOutOfRangeException(nameof(value), "Zero or less.");
}
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -164,7 +161,7 @@ namespace EonaCat.Network
}
}
private void broadcast(Opcode opcode, byte[] data, Action completed)
private void broadcast(OperationCode opcode, byte[] data, Action completed)
{
var cache = new Dictionary<CompressionMethod, byte[]>();
@ -196,7 +193,7 @@ namespace EonaCat.Network
}
}
private void broadcast(Opcode opcode, Stream stream, Action completed)
private void broadcast(OperationCode opcode, Stream stream, Action completed)
{
var cache = new Dictionary<CompressionMethod, Stream>();
@ -233,41 +230,6 @@ namespace EonaCat.Network
}
}
private void broadcastAsync(Opcode opcode, byte[] data, Action completed)
{
ThreadPool.QueueUserWorkItem(
state => broadcast(opcode, data, completed)
);
}
private void broadcastAsync(Opcode opcode, Stream stream, Action completed)
{
ThreadPool.QueueUserWorkItem(
state => broadcast(opcode, stream, completed)
);
}
private Dictionary<string, Dictionary<string, bool>> broadping(
byte[] frameAsBytes, TimeSpan timeout
)
{
var ret = new Dictionary<string, Dictionary<string, bool>>();
foreach (var host in Hosts)
{
if (_state != ServerState.Start)
{
Logger.Error("The server is shutting down.");
break;
}
var res = host.Sessions.Broadping(frameAsBytes, timeout);
ret.Add(host.Path, res);
}
return ret;
}
private bool canSet(out string message)
{
message = null;
@ -294,8 +256,7 @@ namespace EonaCat.Network
lock (_sync)
{
WSEndpointHost host;
if (_hosts.TryGetValue(path, out host))
if (_hosts.TryGetValue(path, out WSEndpointHost host))
{
throw new ArgumentException("Already in use.", nameof(path));
}
@ -385,16 +346,15 @@ namespace EonaCat.Network
if (path.IndexOfAny(new[] { '?', '#' }) > -1)
{
var msg = "It includes either or both query and fragment components.";
throw new ArgumentException(msg, nameof(path));
var message = "It includes either or both query and fragment components.";
throw new ArgumentException(message, nameof(path));
}
path = HttpUtility.UrlDecode(path).TrimSlashFromEnd();
lock (_sync)
{
WSEndpointHost host;
if (_hosts.TryGetValue(path, out host))
if (_hosts.TryGetValue(path, out WSEndpointHost host))
{
throw new ArgumentException("Already in use.", nameof(path));
}
@ -436,7 +396,7 @@ namespace EonaCat.Network
{
if (host.State == ServerState.Start)
{
host.Stop(1001, string.Empty);
host.Stop((ushort)CloseStatusCode.Away, string.Empty);
}
}
}
@ -460,8 +420,8 @@ namespace EonaCat.Network
if (path.IndexOfAny(new[] { '?', '#' }) > -1)
{
var msg = "It includes either or both query and fragment components.";
throw new ArgumentException(msg, nameof(path));
var message = "It includes either or both query and fragment components.";
throw new ArgumentException(message, nameof(path));
}
path = HttpUtility.UrlDecode(path).TrimSlashFromEnd();
@ -479,7 +439,7 @@ namespace EonaCat.Network
if (host.State == ServerState.Start)
{
host.Stop(1001, string.Empty);
host.Stop((ushort)CloseStatusCode.Away, string.Empty);
}
return true;
@ -504,8 +464,8 @@ namespace EonaCat.Network
if (path.IndexOfAny(new[] { '?', '#' }) > -1)
{
var msg = "It includes either or both query and fragment components.";
throw new ArgumentException(msg, nameof(path));
var message = "It includes either or both query and fragment components.";
throw new ArgumentException(message, nameof(path));
}
return InternalTryGetServiceHost(path, out host);

View File

@ -22,8 +22,8 @@ namespace EonaCat.Network
private string _realmInUse;
private Thread _receiveThread;
private bool _reuseAddress;
private SSLConfigurationServer _sslConfig;
private SSLConfigurationServer _sslConfigInUse;
private SSLConfigServer _sslConfig;
private SSLConfigServer _sslConfigInUse;
private volatile ServerState _state;
private object _sync;
private Func<IIdentity, NetworkCredential> _userCredentialsFinder;
@ -56,11 +56,9 @@ namespace EonaCat.Network
throw new ArgumentException("An empty string.", nameof(url));
}
Uri uri;
string msg;
if (!tryCreateUri(url, out uri, out msg))
if (!tryCreateUri(url, out Uri uri, out string message))
{
throw new ArgumentException(msg, nameof(url));
throw new ArgumentException(message, nameof(url));
}
var host = uri.DnsSafeHost;
@ -68,14 +66,14 @@ namespace EonaCat.Network
var addr = host.ToIPAddress();
if (addr == null)
{
msg = "The host part could not be converted to an IP address.";
throw new ArgumentException(msg, nameof(url));
message = "The host part could not be converted to an IP address.";
throw new ArgumentException(message, nameof(url));
}
if (!addr.IsLocal())
{
msg = "The IP address of the host is not a local IP address.";
throw new ArgumentException(msg, nameof(url));
message = "The IP address of the host is not a local IP address.";
throw new ArgumentException(message, nameof(url));
}
init(host, addr, uri.Port, uri.Scheme == "wss");
@ -85,8 +83,8 @@ namespace EonaCat.Network
{
if (!port.IsPortNumber())
{
var msg = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), msg);
var message = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), message);
}
var addr = System.Net.IPAddress.Any;
@ -112,8 +110,8 @@ namespace EonaCat.Network
if (!port.IsPortNumber())
{
var msg = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), msg);
var message = "Less than 1 or greater than 65535.";
throw new ArgumentOutOfRangeException(nameof(port), message);
}
init(address.ToString(), address, port, secure);
@ -130,18 +128,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!CanSet(out msg))
if (!CanSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!CanSet(out msg))
if (!CanSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -159,18 +156,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!CanSet(out msg))
if (!CanSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!CanSet(out msg))
if (!CanSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -210,18 +206,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!CanSet(out msg))
if (!CanSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!CanSet(out msg))
if (!CanSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -239,18 +234,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!CanSet(out msg))
if (!CanSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!CanSet(out msg))
if (!CanSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -259,14 +253,14 @@ namespace EonaCat.Network
}
}
public SSLConfigurationServer SslConfiguration
public SSLConfigServer SslConfiguration
{
get
{
if (!IsSecure)
{
var msg = "This instance does not provide secure connections.";
throw new InvalidOperationException(msg);
var message = "This instance does not provide secure connections.";
throw new InvalidOperationException(message);
}
return GetSslConfiguration();
@ -282,8 +276,7 @@ namespace EonaCat.Network
set
{
string message;
if (!CanSet(out message))
if (!CanSet(out string message))
{
Logger.Warning(message);
return;
@ -337,7 +330,7 @@ namespace EonaCat.Network
}
finally
{
Endpoints.Stop(1006, string.Empty);
Endpoints.Stop((ushort)CloseStatusCode.Abnormal, string.Empty);
}
}
catch
@ -374,7 +367,7 @@ namespace EonaCat.Network
}
private static bool CheckSslConfiguration(
SSLConfigurationServer configuration, out string message
SSLConfigServer configuration, out string message
)
{
message = null;
@ -394,9 +387,9 @@ namespace EonaCat.Network
return realm != null && realm.Length > 0 ? realm : _defaultRealm;
}
private SSLConfigurationServer GetSslConfiguration()
private SSLConfigServer GetSslConfiguration()
{
_sslConfig ??= new SSLConfigurationServer();
_sslConfig ??= new SSLConfigServer();
return _sslConfig;
}
@ -417,7 +410,7 @@ namespace EonaCat.Network
_sync = new object();
}
private void processRequest(TcpListenerWebSocketContext context)
private void processRequest(TcpListenerWSContext context)
{
var uri = context.RequestUri;
if (uri == null)
@ -441,8 +434,7 @@ namespace EonaCat.Network
}
}
WSEndpointHost host;
if (!Endpoints.InternalTryGetServiceHost(uri.AbsolutePath, out host))
if (!Endpoints.InternalTryGetServiceHost(uri.AbsolutePath, out WSEndpointHost host))
{
context.Close(HttpStatusCode.NotImplemented);
return;
@ -464,7 +456,7 @@ namespace EonaCat.Network
{
try
{
var ctx = new TcpListenerWebSocketContext(
var ctx = new TcpListenerWSContext(
cl, null, IsSecure, _sslConfigInUse);
if (!ctx.Authenticate(_authSchemes, _realmInUse, _userCredentialsFinder))
@ -502,10 +494,7 @@ namespace EonaCat.Network
Logger.Error(ex.Message);
Logger.Debug(ex.ToString());
if (cl != null)
{
cl.Close();
}
cl?.Close();
break;
}
@ -517,7 +506,7 @@ namespace EonaCat.Network
}
}
private void start(SSLConfigurationServer sslConfig)
private void start(SSLConfigServer sslConfig)
{
Logger.IsLoggingEnabled = IsLoggingEnabled;
Logger.DisableConsole = !IsConsoleLoggingEnabled;
@ -558,7 +547,7 @@ namespace EonaCat.Network
}
catch
{
Endpoints.Stop(1011, string.Empty);
Endpoints.Stop((ushort)CloseStatusCode.ServerError, string.Empty);
throw;
}
@ -581,8 +570,8 @@ namespace EonaCat.Network
}
catch (Exception ex)
{
var msg = "The underlying listener has failed to start.";
throw new InvalidOperationException(msg, ex);
var message = "The underlying listener has failed to start.";
throw new InvalidOperationException(message, ex);
}
_receiveThread = new Thread(new ThreadStart(receiveRequest));
@ -592,7 +581,7 @@ namespace EonaCat.Network
private void stop(ushort code, string reason)
{
if (_state == ServerState.Ready)
if (_state == ServerState.Started)
{
Logger.Info("The server is not started.");
return;
@ -668,8 +657,8 @@ namespace EonaCat.Network
}
catch (Exception ex)
{
var msg = "The underlying listener has failed to stop.";
throw new InvalidOperationException(msg, ex);
var message = "The underlying listener has failed to stop.";
throw new InvalidOperationException(message, ex);
}
_receiveThread.Join(millisecondsTimeout);
@ -712,14 +701,13 @@ namespace EonaCat.Network
public void Start()
{
SSLConfigurationServer sslConfig = null;
SSLConfigServer sslConfig = null;
if (IsSecure)
{
sslConfig = new SSLConfigurationServer(GetSslConfiguration());
sslConfig = new SSLConfigServer(GetSslConfiguration());
string message;
if (!CheckSslConfiguration(sslConfig, out message))
if (!CheckSslConfiguration(sslConfig, out string message))
{
throw new InvalidOperationException(message);
}
@ -730,42 +718,41 @@ namespace EonaCat.Network
public void Stop()
{
stop(1005, string.Empty);
stop((ushort)CloseStatusCode.NoStatus, string.Empty);
}
public void Stop(ushort code, string reason)
{
if (!code.IsCloseStatusCode())
{
var msg = "Less than 1000 or greater than 4999.";
throw new ArgumentOutOfRangeException(nameof(code), msg);
var message = "Less than 1000 or greater than 4999.";
throw new ArgumentOutOfRangeException(nameof(code), message);
}
if (code == 1010)
if (code == (ushort)CloseStatusCode.MandatoryExtension)
{
var msg = "1010 cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = $"{(ushort)CloseStatusCode.MandatoryExtension} cannot be used.";
throw new ArgumentException(message, nameof(code));
}
if (!reason.IsNullOrEmpty())
{
if (code == 1005)
if (code == (ushort)CloseStatusCode.NoStatus)
{
var msg = "1005 cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = $"{(ushort)CloseStatusCode.NoStatus} cannot be used.";
throw new ArgumentException(message, nameof(code));
}
byte[] bytes;
if (!reason.TryGetUTF8EncodedBytes(out bytes))
if (!reason.TryGetUTF8EncodedBytes(out byte[] bytes))
{
var msg = "It could not be UTF-8-encoded.";
throw new ArgumentException(msg, nameof(reason));
var message = "It could not be UTF-8-encoded.";
throw new ArgumentException(message, nameof(reason));
}
if (bytes.Length > 123)
{
var msg = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), msg);
var message = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), message);
}
}
@ -776,29 +763,28 @@ namespace EonaCat.Network
{
if (code == CloseStatusCode.MandatoryExtension)
{
var msg = "MandatoryExtension cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = "MandatoryExtension cannot be used.";
throw new ArgumentException(message, nameof(code));
}
if (!reason.IsNullOrEmpty())
{
if (code == CloseStatusCode.NoStatus)
{
var msg = "NoStatus cannot be used.";
throw new ArgumentException(msg, nameof(code));
var message = "NoStatus cannot be used.";
throw new ArgumentException(message, nameof(code));
}
byte[] bytes;
if (!reason.TryGetUTF8EncodedBytes(out bytes))
if (!reason.TryGetUTF8EncodedBytes(out byte[] bytes))
{
var msg = "It could not be UTF-8-encoded.";
throw new ArgumentException(msg, nameof(reason));
var message = "It could not be UTF-8-encoded.";
throw new ArgumentException(message, nameof(reason));
}
if (bytes.Length > 123)
{
var msg = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), msg);
var message = "Its size is greater than 123 bytes.";
throw new ArgumentOutOfRangeException(nameof(reason), message);
}
}

View File

@ -26,7 +26,7 @@ namespace EonaCat.Network
_clean = true;
_forSweep = new object();
_sessions = new Dictionary<string, IWSSession>();
_state = ServerState.Ready;
_state = ServerState.Started;
_sync = ((ICollection)_sessions).SyncRoot;
_waitTime = TimeSpan.FromSeconds(1);
@ -39,7 +39,7 @@ namespace EonaCat.Network
{
get
{
foreach (var res in broadping(WebSocketFrame.EmptyPingBytes))
foreach (var res in broadping(WSFrame.EmptyPingBytes))
{
if (res.Value)
{
@ -85,7 +85,7 @@ namespace EonaCat.Network
{
get
{
foreach (var res in broadping(WebSocketFrame.EmptyPingBytes))
foreach (var res in broadping(WSFrame.EmptyPingBytes))
{
if (!res.Value)
{
@ -109,8 +109,7 @@ namespace EonaCat.Network
throw new ArgumentException("An empty string.", nameof(id));
}
IWSSession session;
tryGetSession(id, out session);
tryGetSession(id, out IWSSession session);
return session;
}
@ -125,18 +124,17 @@ namespace EonaCat.Network
set
{
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -180,18 +178,17 @@ namespace EonaCat.Network
throw new ArgumentOutOfRangeException(nameof(value), "Zero or less.");
}
string msg;
if (!canSet(out msg))
if (!canSet(out string message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
lock (_sync)
{
if (!canSet(out msg))
if (!canSet(out message))
{
Logger.Warning(msg);
Logger.Warning(message);
return;
}
@ -200,7 +197,7 @@ namespace EonaCat.Network
}
}
private void broadcast(Opcode opcode, byte[] data, Action completed)
private void broadcast(OperationCode opcode, byte[] data, Action completed)
{
var cache = new Dictionary<CompressionMethod, byte[]>();
@ -233,7 +230,7 @@ namespace EonaCat.Network
}
}
private void broadcast(Opcode opcode, Stream stream, Action completed)
private void broadcast(OperationCode opcode, Stream stream, Action completed)
{
var cache = new Dictionary<CompressionMethod, Stream>();
@ -271,14 +268,14 @@ namespace EonaCat.Network
}
}
private void broadcastAsync(Opcode opcode, byte[] data, Action completed)
private void broadcastAsync(OperationCode opcode, byte[] data, Action completed)
{
ThreadPool.QueueUserWorkItem(
state => broadcast(opcode, data, completed)
);
}
private void broadcastAsync(Opcode opcode, Stream stream, Action completed)
private void broadcastAsync(OperationCode opcode, Stream stream, Action completed)
{
ThreadPool.QueueUserWorkItem(
state => broadcast(opcode, stream, completed)
@ -337,7 +334,7 @@ namespace EonaCat.Network
private void stop(PayloadData payloadData, bool send)
{
var bytes = send
? WebSocketFrame.CreateCloseFrame(payloadData, false).ToArray()
? WSFrame.CreateCloseFrame(payloadData, false).ToArray()
: null;
lock (_sync)
@ -391,7 +388,7 @@ namespace EonaCat.Network
}
internal void Broadcast(
Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache
OperationCode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache
)
{
foreach (var session in Sessions)
@ -407,7 +404,7 @@ namespace EonaCat.Network
}
internal void Broadcast(
Opcode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache
OperationCode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache
)
{
foreach (var session in Sessions)
@ -462,7 +459,7 @@ namespace EonaCat.Network
internal void Stop(ushort code, string reason)
{
if (code == 1005)
if (code == (ushort)CloseStatusCode.NoStatus)
{ // == no status
stop(PayloadData.Empty, true);
return;
@ -475,8 +472,8 @@ namespace EonaCat.Network
{
if (_state != ServerState.Start)
{
var msg = "The current state of the manager is not Start.";
throw new InvalidOperationException(msg);
var message = "The current state of the manager is not Start.";
throw new InvalidOperationException(message);
}
if (data == null)
@ -484,13 +481,13 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(data));
}
if (data.LongLength <= WebSocket.FragmentLength)
if (data.LongLength <= WSClient.FragmentLength)
{
broadcast(Opcode.Binary, data, null);
broadcast(OperationCode.Binary, data, null);
}
else
{
broadcast(Opcode.Binary, new MemoryStream(data), null);
broadcast(OperationCode.Binary, new MemoryStream(data), null);
}
}
@ -498,8 +495,8 @@ namespace EonaCat.Network
{
if (_state != ServerState.Start)
{
var msg = "The current state of the manager is not Start.";
throw new InvalidOperationException(msg);
var message = "The current state of the manager is not Start.";
throw new InvalidOperationException(message);
}
if (data == null)
@ -507,20 +504,19 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(data));
}
byte[] bytes;
if (!data.TryGetUTF8EncodedBytes(out bytes))
if (!data.TryGetUTF8EncodedBytes(out byte[] bytes))
{
var msg = "It could not be UTF-8-encoded.";
throw new ArgumentException(msg, nameof(data));
var message = "It could not be UTF-8-encoded.";
throw new ArgumentException(message, nameof(data));
}
if (bytes.LongLength <= WebSocket.FragmentLength)
if (bytes.LongLength <= WSClient.FragmentLength)
{
broadcast(Opcode.Text, bytes, null);
broadcast(OperationCode.Text, bytes, null);
}
else
{
broadcast(Opcode.Text, new MemoryStream(bytes), null);
broadcast(OperationCode.Text, new MemoryStream(bytes), null);
}
}
@ -528,8 +524,8 @@ namespace EonaCat.Network
{
if (_state != ServerState.Start)
{
var msg = "The current state of the manager is not Start.";
throw new InvalidOperationException(msg);
var message = "The current state of the manager is not Start.";
throw new InvalidOperationException(message);
}
if (stream == null)
@ -539,14 +535,14 @@ namespace EonaCat.Network
if (!stream.CanRead)
{
var msg = "It cannot be read.";
throw new ArgumentException(msg, nameof(stream));
var message = "It cannot be read.";
throw new ArgumentException(message, nameof(stream));
}
if (length < 1)
{
var msg = "Less than 1.";
throw new ArgumentException(msg, nameof(length));
var message = "Less than 1.";
throw new ArgumentException(message, nameof(length));
}
var bytes = stream.ReadBytes(length);
@ -554,8 +550,8 @@ namespace EonaCat.Network
var len = bytes.Length;
if (len == 0)
{
var msg = "No data could be read from it.";
throw new ArgumentException(msg, nameof(stream));
var message = "No data could be read from it.";
throw new ArgumentException(message, nameof(stream));
}
if (len < length)
@ -568,13 +564,13 @@ namespace EonaCat.Network
);
}
if (len <= WebSocket.FragmentLength)
if (len <= WSClient.FragmentLength)
{
broadcast(Opcode.Binary, bytes, null);
broadcast(OperationCode.Binary, bytes, null);
}
else
{
broadcast(Opcode.Binary, new MemoryStream(bytes), null);
broadcast(OperationCode.Binary, new MemoryStream(bytes), null);
}
}
@ -582,8 +578,8 @@ namespace EonaCat.Network
{
if (_state != ServerState.Start)
{
var msg = "The current state of the manager is not Start.";
throw new InvalidOperationException(msg);
var message = "The current state of the manager is not Start.";
throw new InvalidOperationException(message);
}
if (data == null)
@ -591,13 +587,13 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(data));
}
if (data.LongLength <= WebSocket.FragmentLength)
if (data.LongLength <= WSClient.FragmentLength)
{
broadcastAsync(Opcode.Binary, data, completed);
broadcastAsync(OperationCode.Binary, data, completed);
}
else
{
broadcastAsync(Opcode.Binary, new MemoryStream(data), completed);
broadcastAsync(OperationCode.Binary, new MemoryStream(data), completed);
}
}
@ -605,8 +601,8 @@ namespace EonaCat.Network
{
if (_state != ServerState.Start)
{
var msg = "The current state of the manager is not Start.";
throw new InvalidOperationException(msg);
var message = "The current state of the manager is not Start.";
throw new InvalidOperationException(message);
}
if (data == null)
@ -614,20 +610,19 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(data));
}
byte[] bytes;
if (!data.TryGetUTF8EncodedBytes(out bytes))
if (!data.TryGetUTF8EncodedBytes(out byte[] bytes))
{
var msg = "It could not be UTF-8-encoded.";
throw new ArgumentException(msg, nameof(data));
var message = "It could not be UTF-8-encoded.";
throw new ArgumentException(message, nameof(data));
}
if (bytes.LongLength <= WebSocket.FragmentLength)
if (bytes.LongLength <= WSClient.FragmentLength)
{
broadcastAsync(Opcode.Text, bytes, completed);
broadcastAsync(OperationCode.Text, bytes, completed);
}
else
{
broadcastAsync(Opcode.Text, new MemoryStream(bytes), completed);
broadcastAsync(OperationCode.Text, new MemoryStream(bytes), completed);
}
}
@ -635,8 +630,8 @@ namespace EonaCat.Network
{
if (_state != ServerState.Start)
{
var msg = "The current state of the manager is not Start.";
throw new InvalidOperationException(msg);
var message = "The current state of the manager is not Start.";
throw new InvalidOperationException(message);
}
if (stream == null)
@ -646,14 +641,14 @@ namespace EonaCat.Network
if (!stream.CanRead)
{
var msg = "It cannot be read.";
throw new ArgumentException(msg, nameof(stream));
var message = "It cannot be read.";
throw new ArgumentException(message, nameof(stream));
}
if (length < 1)
{
var msg = "Less than 1.";
throw new ArgumentException(msg, nameof(length));
var message = "Less than 1.";
throw new ArgumentException(message, nameof(length));
}
var bytes = stream.ReadBytes(length);
@ -661,8 +656,8 @@ namespace EonaCat.Network
var len = bytes.Length;
if (len == 0)
{
var msg = "No data could be read from it.";
throw new ArgumentException(msg, nameof(stream));
var message = "No data could be read from it.";
throw new ArgumentException(message, nameof(stream));
}
if (len < length)
@ -675,23 +670,22 @@ namespace EonaCat.Network
);
}
if (len <= WebSocket.FragmentLength)
if (len <= WSClient.FragmentLength)
{
broadcastAsync(Opcode.Binary, bytes, completed);
broadcastAsync(OperationCode.Binary, bytes, completed);
}
else
{
broadcastAsync(Opcode.Binary, new MemoryStream(bytes), completed);
broadcastAsync(OperationCode.Binary, new MemoryStream(bytes), completed);
}
}
public void CloseSession(string id)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.Close();
@ -699,11 +693,10 @@ namespace EonaCat.Network
public void CloseSession(string id, ushort code, string reason)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.Close(code, reason);
@ -711,11 +704,10 @@ namespace EonaCat.Network
public void CloseSession(string id, CloseStatusCode code, string reason)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.Close(code, reason);
@ -723,11 +715,10 @@ namespace EonaCat.Network
public bool PingTo(string id)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
return session.Context.WebSocket.Ping();
@ -735,11 +726,10 @@ namespace EonaCat.Network
public bool PingTo(string message, string id)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var pingMessage = "The session could not be found.";
throw new InvalidOperationException(pingMessage);
}
return session.Context.WebSocket.Ping(message);
@ -747,11 +737,10 @@ namespace EonaCat.Network
public void SendTo(byte[] data, string id)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.Send(data);
@ -759,11 +748,10 @@ namespace EonaCat.Network
public void SendTo(string data, string id)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.Send(data);
@ -771,11 +759,10 @@ namespace EonaCat.Network
public void SendTo(Stream stream, int length, string id)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.Send(stream, length);
@ -783,11 +770,10 @@ namespace EonaCat.Network
public void SendToAsync(byte[] data, string id, Action<bool> completed)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.SendAsync(data, completed);
@ -795,11 +781,10 @@ namespace EonaCat.Network
public void SendToAsync(string data, string id, Action<bool> completed)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.SendAsync(data, completed);
@ -809,11 +794,10 @@ namespace EonaCat.Network
Stream stream, int length, string id, Action<bool> completed
)
{
IWSSession session;
if (!TryGetSession(id, out session))
if (!TryGetSession(id, out IWSSession session))
{
var msg = "The session could not be found.";
throw new InvalidOperationException(msg);
var message = "The session could not be found.";
throw new InvalidOperationException(message);
}
session.Context.WebSocket.SendAsync(stream, length, completed);
@ -852,15 +836,14 @@ namespace EonaCat.Network
break;
}
IWSSession session;
if (_sessions.TryGetValue(id, out session))
if (_sessions.TryGetValue(id, out IWSSession session))
{
var state = session.State;
if (state == WebSocketState.Open)
if (state == WSState.Open)
{
session.Context.WebSocket.Close(CloseStatusCode.Abnormal);
}
else if (state == WebSocketState.Closing)
else if (state == WSState.Closing)
{
continue;
}

View File

@ -5,44 +5,44 @@ using System;
namespace EonaCat.Network
{
public class WebSocketException : Exception
public class WSException : Exception
{
internal WebSocketException()
internal WSException()
: this(CloseStatusCode.Abnormal, null, null)
{
}
internal WebSocketException(Exception innerException)
internal WSException(Exception innerException)
: this(CloseStatusCode.Abnormal, null, innerException)
{
}
internal WebSocketException(string message)
internal WSException(string message)
: this(CloseStatusCode.Abnormal, message, null)
{
}
internal WebSocketException(CloseStatusCode code)
internal WSException(CloseStatusCode code)
: this(code, null, null)
{
}
internal WebSocketException(string message, Exception innerException)
internal WSException(string message, Exception innerException)
: this(CloseStatusCode.Abnormal, message, innerException)
{
}
internal WebSocketException(CloseStatusCode code, Exception innerException)
internal WSException(CloseStatusCode code, Exception innerException)
: this(code, null, innerException)
{
}
internal WebSocketException(CloseStatusCode code, string message)
internal WSException(CloseStatusCode code, string message)
: this(code, message, null)
{
}
internal WebSocketException(
internal WSException(
CloseStatusCode code, string message, Exception innerException
)
: base("EonaCat Network: " + (message ?? code.GetMessage()), innerException)

View File

@ -9,33 +9,33 @@ using System.Text;
namespace EonaCat.Network
{
internal class WebSocketFrame : IEnumerable<byte>
internal class WSFrame : IEnumerable<byte>
{
private const int BUFFER_SIZE = 1024;
internal static readonly byte[] EmptyPingBytes;
static WebSocketFrame()
static WSFrame()
{
EmptyPingBytes = CreatePingFrame(false).ToArray();
}
private WebSocketFrame()
private WSFrame()
{
}
internal WebSocketFrame(Opcode opcode, PayloadData payloadData, bool mask)
internal WSFrame(OperationCode opcode, PayloadData payloadData, bool mask)
: this(FinalFrame.Final, opcode, payloadData, false, mask)
{
}
internal WebSocketFrame(FinalFrame finalFrame, Opcode opcode, byte[] data, bool compressed, bool mask)
internal WSFrame(FinalFrame finalFrame, OperationCode opcode, byte[] data, bool compressed, bool mask)
: this(finalFrame, opcode, new PayloadData(data), compressed, mask)
{
}
internal WebSocketFrame(
FinalFrame fin, Opcode opcode, PayloadData payloadData, bool compressed, bool mask)
internal WSFrame(
FinalFrame fin, OperationCode opcode, PayloadData payloadData, bool compressed, bool mask)
{
Fin = fin;
Rsv1 = opcode.IsData() && compressed ? Rsv.On : Rsv.Off;
@ -47,7 +47,7 @@ namespace EonaCat.Network
if (len < 126)
{
PayloadLength = (byte)len;
ExtendedPayloadLength = WebSocket.EmptyBytes;
ExtendedPayloadLength = WSClient.EmptyBytes;
}
else if (len < 0x010000)
{
@ -69,7 +69,7 @@ namespace EonaCat.Network
else
{
Mask = Mask.Off;
MaskingKey = WebSocket.EmptyBytes;
MaskingKey = WSClient.EmptyBytes;
}
PayloadData = payloadData;
@ -87,29 +87,29 @@ namespace EonaCat.Network
public FinalFrame Fin { get; private set; }
public bool IsBinary => Opcode == Opcode.Binary;
public bool IsBinary => Opcode == OperationCode.Binary;
public bool IsClose => Opcode == Opcode.Close;
public bool IsClose => Opcode == OperationCode.Close;
public bool IsCompressed => Rsv1 == Rsv.On;
public bool IsContinuation => Opcode == Opcode.Cont;
public bool IsContinuation => Opcode == OperationCode.Cont;
public bool IsControl => Opcode >= Opcode.Close;
public bool IsControl => Opcode >= OperationCode.Close;
public bool IsData => Opcode == Opcode.Text || Opcode == Opcode.Binary;
public bool IsData => Opcode == OperationCode.Text || Opcode == OperationCode.Binary;
public bool IsFinal => Fin == FinalFrame.Final;
public bool IsFragment => Fin == FinalFrame.More || Opcode == Opcode.Cont;
public bool IsFragment => Fin == FinalFrame.More || Opcode == OperationCode.Cont;
public bool IsMasked => Mask == Mask.On;
public bool IsPing => Opcode == Opcode.Ping;
public bool IsPing => Opcode == OperationCode.Ping;
public bool IsPong => Opcode == Opcode.Pong;
public bool IsPong => Opcode == OperationCode.Pong;
public bool IsText => Opcode == Opcode.Text;
public bool IsText => Opcode == OperationCode.Text;
public ulong Length => 2 + (ulong)(ExtendedPayloadLength.Length + MaskingKey.Length) + PayloadData.Length;
@ -117,7 +117,7 @@ namespace EonaCat.Network
public byte[] MaskingKey { get; private set; }
public Opcode Opcode { get; private set; }
public OperationCode Opcode { get; private set; }
public PayloadData PayloadData { get; private set; }
@ -132,12 +132,12 @@ namespace EonaCat.Network
private static byte[] createMaskingKey()
{
var key = new byte[4];
WebSocket.RandomNumber.GetBytes(key);
WSClient.RandomNumber.GetBytes(key);
return key;
}
private static string dump(WebSocketFrame frame)
private static string dump(WSFrame frame)
{
var len = frame.Length;
var cnt = (long)(len / 4);
@ -213,7 +213,7 @@ namespace EonaCat.Network
return output.ToString();
}
private static string print(WebSocketFrame frame)
private static string print(WSFrame frame)
{
// Payload Length
var payloadLen = frame.PayloadLength;
@ -259,11 +259,11 @@ Extended Payload Length: {7}
payload);
}
private static WebSocketFrame processHeader(byte[] header)
private static WSFrame processHeader(byte[] header)
{
if (header.Length != 2)
{
throw new WebSocketException("The header of a frame cannot be read from the stream.");
throw new WSException("The header of a frame cannot be read from the stream.");
}
// FIN
@ -299,34 +299,34 @@ Extended Payload Length: {7}
if (err != null)
{
throw new WebSocketException(CloseStatusCode.ProtocolError, err);
throw new WSException(CloseStatusCode.ProtocolError, err);
}
var frame = new WebSocketFrame();
var frame = new WSFrame();
frame.Fin = fin;
frame.Rsv1 = rsv1;
frame.Rsv2 = rsv2;
frame.Rsv3 = rsv3;
frame.Opcode = (Opcode)opcode;
frame.Opcode = (OperationCode)opcode;
frame.Mask = mask;
frame.PayloadLength = payloadLen;
return frame;
}
private static WebSocketFrame readExtendedPayloadLength(Stream stream, WebSocketFrame frame)
private static WSFrame readExtendedPayloadLength(Stream stream, WSFrame frame)
{
var len = frame.ExtendedPayloadLengthCount;
if (len == 0)
{
frame.ExtendedPayloadLength = WebSocket.EmptyBytes;
frame.ExtendedPayloadLength = WSClient.EmptyBytes;
return frame;
}
var bytes = stream.ReadBytes(len);
if (bytes.Length != len)
{
throw new WebSocketException(
throw new WSException(
"The extended payload length of a frame cannot be read from the stream.");
}
@ -336,14 +336,14 @@ Extended Payload Length: {7}
private static void readExtendedPayloadLengthAsync(
Stream stream,
WebSocketFrame frame,
Action<WebSocketFrame> completed,
WSFrame frame,
Action<WSFrame> completed,
Action<Exception> error)
{
var len = frame.ExtendedPayloadLengthCount;
if (len == 0)
{
frame.ExtendedPayloadLength = WebSocket.EmptyBytes;
frame.ExtendedPayloadLength = WSClient.EmptyBytes;
completed(frame);
return;
@ -355,7 +355,7 @@ Extended Payload Length: {7}
{
if (bytes.Length != len)
{
throw new WebSocketException(
throw new WSException(
"The extended payload length of a frame cannot be read from the stream.");
}
@ -365,30 +365,30 @@ Extended Payload Length: {7}
error);
}
private static WebSocketFrame readHeader(Stream stream)
private static WSFrame readHeader(Stream stream)
{
return processHeader(stream.ReadBytes(2));
}
private static void readHeaderAsync(
Stream stream, Action<WebSocketFrame> completed, Action<Exception> error)
Stream stream, Action<WSFrame> completed, Action<Exception> error)
{
stream.ReadBytesAsync(2, bytes => completed(processHeader(bytes)), error);
}
private static WebSocketFrame readMaskingKey(Stream stream, WebSocketFrame frame)
private static WSFrame readMaskingKey(Stream stream, WSFrame frame)
{
var len = frame.IsMasked ? 4 : 0;
if (len == 0)
{
frame.MaskingKey = WebSocket.EmptyBytes;
frame.MaskingKey = WSClient.EmptyBytes;
return frame;
}
var bytes = stream.ReadBytes(len);
if (bytes.Length != len)
{
throw new WebSocketException("The masking key of a frame cannot be read from the stream.");
throw new WSException("The masking key of a frame cannot be read from the stream.");
}
frame.MaskingKey = bytes;
@ -397,14 +397,14 @@ Extended Payload Length: {7}
private static void readMaskingKeyAsync(
Stream stream,
WebSocketFrame frame,
Action<WebSocketFrame> completed,
WSFrame frame,
Action<WSFrame> completed,
Action<Exception> error)
{
var len = frame.IsMasked ? 4 : 0;
if (len == 0)
{
frame.MaskingKey = WebSocket.EmptyBytes;
frame.MaskingKey = WSClient.EmptyBytes;
completed(frame);
return;
@ -416,7 +416,7 @@ Extended Payload Length: {7}
{
if (bytes.Length != len)
{
throw new WebSocketException(
throw new WSException(
"The masking key of a frame cannot be read from the stream.");
}
@ -426,7 +426,7 @@ Extended Payload Length: {7}
error);
}
private static WebSocketFrame readPayloadData(Stream stream, WebSocketFrame frame)
private static WSFrame readPayloadData(Stream stream, WSFrame frame)
{
var len = frame.FullPayloadLength;
if (len == 0)
@ -437,7 +437,7 @@ Extended Payload Length: {7}
if (len > PayloadData.MaxLength)
{
throw new WebSocketException(CloseStatusCode.TooBig, "A frame has a long payload length.");
throw new WSException(CloseStatusCode.TooBig, "A frame has a long payload length.");
}
var llen = (long)len;
@ -447,7 +447,7 @@ Extended Payload Length: {7}
if (bytes.LongLength != llen)
{
throw new WebSocketException(
throw new WSException(
"The payload data of a frame cannot be read from the stream.");
}
@ -457,8 +457,8 @@ Extended Payload Length: {7}
private static void readPayloadDataAsync(
Stream stream,
WebSocketFrame frame,
Action<WebSocketFrame> completed,
WSFrame frame,
Action<WSFrame> completed,
Action<Exception> error)
{
var len = frame.FullPayloadLength;
@ -472,7 +472,7 @@ Extended Payload Length: {7}
if (len > PayloadData.MaxLength)
{
throw new WebSocketException(CloseStatusCode.TooBig, "A frame has a long payload length.");
throw new WSException(CloseStatusCode.TooBig, "A frame has a long payload length.");
}
var llen = (long)len;
@ -480,7 +480,7 @@ Extended Payload Length: {7}
{
if (bytes.LongLength != llen)
{
throw new WebSocketException(
throw new WSException(
"The payload data of a frame cannot be read from the stream.");
}
@ -497,39 +497,39 @@ Extended Payload Length: {7}
stream.ReadBytesAsync(llen, BUFFER_SIZE, compl, error);
}
internal static WebSocketFrame CreateCloseFrame(
internal static WSFrame CreateCloseFrame(
PayloadData payloadData, bool mask
)
{
return new WebSocketFrame(
FinalFrame.Final, Opcode.Close, payloadData, false, mask
return new WSFrame(
FinalFrame.Final, OperationCode.Close, payloadData, false, mask
);
}
internal static WebSocketFrame CreatePingFrame(bool mask)
internal static WSFrame CreatePingFrame(bool mask)
{
return new WebSocketFrame(
FinalFrame.Final, Opcode.Ping, PayloadData.Empty, false, mask
return new WSFrame(
FinalFrame.Final, OperationCode.Ping, PayloadData.Empty, false, mask
);
}
internal static WebSocketFrame CreatePingFrame(byte[] data, bool mask)
internal static WSFrame CreatePingFrame(byte[] data, bool mask)
{
return new WebSocketFrame(
FinalFrame.Final, Opcode.Ping, new PayloadData(data), false, mask
return new WSFrame(
FinalFrame.Final, OperationCode.Ping, new PayloadData(data), false, mask
);
}
internal static WebSocketFrame CreatePongFrame(
internal static WSFrame CreatePongFrame(
PayloadData payloadData, bool mask
)
{
return new WebSocketFrame(
FinalFrame.Final, Opcode.Pong, payloadData, false, mask
return new WSFrame(
FinalFrame.Final, OperationCode.Pong, payloadData, false, mask
);
}
internal static WebSocketFrame ReadFrame(Stream stream, bool unmask)
internal static WSFrame ReadFrame(Stream stream, bool unmask)
{
var frame = readHeader(stream);
readExtendedPayloadLength(stream, frame);
@ -547,7 +547,7 @@ Extended Payload Length: {7}
internal static void ReadFrameAsync(
Stream stream,
bool unmask,
Action<WebSocketFrame> completed,
Action<WSFrame> completed,
Action<Exception> error
)
{
@ -593,7 +593,7 @@ Extended Payload Length: {7}
Mask = Mask.Off;
PayloadData.Mask(MaskingKey);
MaskingKey = WebSocket.EmptyBytes;
MaskingKey = WSClient.EmptyBytes;
}
public IEnumerator<byte> GetEnumerator()

View File

@ -3,7 +3,7 @@
namespace EonaCat.Network
{
public enum WebSocketState : ushort
public enum WSState : ushort
{
Connecting = 0,

View File

@ -50,8 +50,7 @@ namespace EonaCat.Network
private static byte[] readEntityBody(Stream stream, string length)
{
long len;
if (!long.TryParse(length, out len))
if (!long.TryParse(length, out long len))
{
throw new ArgumentException("Cannot be parsed.", nameof(length));
}
@ -98,7 +97,7 @@ namespace EonaCat.Network
if (!read)
{
throw new WebSocketException("The length of header part is greater than the max length.");
throw new WSException("The length of header part is greater than the max length.");
}
return Encoding.UTF8.GetString(buff.ToArray())
@ -142,15 +141,15 @@ namespace EonaCat.Network
timer.Dispose();
}
var msg = timeout
var message = timeout
? "A timeout has occurred while reading an HTTP request/response."
: exception != null
? "An exception has occurred while reading an HTTP request/response."
: null;
if (msg != null)
if (message != null)
{
throw new WebSocketException(msg, exception);
throw new WSException(message, exception);
}
return http;

View File

@ -114,7 +114,7 @@ namespace EonaCat.Network
}
catch (Exception e)
{
NetworkHelper.Logger.Error(string.Format(" {0}: at {1} is close ,error msg :{2}", para.ip, para.port, e.Message));
NetworkHelper.Logger.Error(string.Format(" {0}: at {1} is close ,error message :{2}", para.ip, para.port, e.Message));
}
finally
{

View File

@ -256,20 +256,5 @@ namespace EonaCat.Network
_Routes.Add(route);
}
}
private void Remove(ContentRoute route)
{
if (route == null)
{
throw new ArgumentNullException(nameof(route));
}
lock (_Lock)
{
_Routes.Remove(route);
}
return;
}
}
}

View File

@ -137,12 +137,6 @@ namespace EonaCat.Network
return "application/octet-stream";
}
private void Set204Response(HttpContext ctx)
{
ctx.Response.StatusCode = 204;
ctx.Response.ContentLength = 0;
}
private void Set404Response(HttpContext ctx)
{
ctx.Response.StatusCode = 404;

View File

@ -129,11 +129,10 @@ namespace EonaCat.Network
throw new ArgumentNullException(nameof(rawUrl));
}
object val = null;
if (Matcher.Match(
BuildConsolidatedRegex(method, rawUrl),
out val))
out object val))
{
if (val == null)
{

View File

@ -451,8 +451,7 @@ namespace EonaCat.Network
if (ctx.Request.Method == HttpMethod.GET || ctx.Request.Method == HttpMethod.HEAD)
{
ContentRoute cr = null;
if (_Routes.Content.Match(ctx.Request.Url.RawWithoutQuery, out cr))
if (_Routes.Content.Match(ctx.Request.Url.RawWithoutQuery, out ContentRoute cr))
{
if (_Settings.Debug.Routing)
{
@ -468,8 +467,7 @@ namespace EonaCat.Network
}
}
StaticRoute sr = null;
Func<HttpContext, Task> handler = _Routes.Static.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery, out sr);
Func<HttpContext, Task> handler = _Routes.Static.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery, out StaticRoute sr);
if (handler != null)
{
if (_Settings.Debug.Routing)
@ -485,9 +483,7 @@ namespace EonaCat.Network
return;
}
ParameterRoute pr = null;
Dictionary<string, string> parameters = null;
handler = _Routes.Parameter.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery, out parameters, out pr);
handler = _Routes.Parameter.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery, out Dictionary<string, string> parameters, out ParameterRoute pr);
if (handler != null)
{
ctx.Request.Url.Parameters = new Dictionary<string, string>(parameters);
@ -505,8 +501,7 @@ namespace EonaCat.Network
return;
}
DynamicRoute dr = null;
handler = _Routes.Dynamic.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery, out dr);
handler = _Routes.Dynamic.Match(ctx.Request.Method, ctx.Request.Url.RawWithoutQuery, out DynamicRoute dr);
if (handler != null)
{
if (_Settings.Debug.Routing)

View File

@ -577,43 +577,6 @@ namespace EonaCat.Network
}
}
private void ReadStreamFully()
{
if (Data == null)
{
return;
}
if (!Data.CanRead)
{
return;
}
if (_DataAsBytes == null)
{
if (!ChunkedTransfer)
{
_DataAsBytes = StreamToBytes(Data);
}
else
{
while (true)
{
Chunk chunk = ReadChunk().Result;
if (chunk.Data != null && chunk.Data.Length > 0)
{
_DataAsBytes = AppendBytes(_DataAsBytes, chunk.Data);
}
if (chunk.IsFinalChunk)
{
break;
}
}
}
}
}
private byte[] ReadStreamFully(Stream input)
{
if (input == null)

View File

@ -125,7 +125,7 @@ namespace EonaCat.Network
private readonly HttpRequest _Request = null;
private readonly System.Net.HttpListenerContext _Context = null;
private readonly System.Net.HttpListenerResponse _Response = null;
private readonly Stream _OutputStream = null;
private readonly Stream _outputStream = null;
private bool _HeadersSent = false;
private readonly EonaCatWebserverSettings _Settings = new EonaCatWebserverSettings();
private readonly EonaCatWebserverEvents _Events = new EonaCatWebserverEvents();
@ -168,7 +168,7 @@ namespace EonaCat.Network
_Settings = settings;
_Events = events;
_OutputStream = _Response.OutputStream;
_outputStream = _Response.OutputStream;
}
/// <summary>
@ -190,13 +190,10 @@ namespace EonaCat.Network
SendHeaders();
}
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
_OutputStream.Close();
await _outputStream.FlushAsync(token).ConfigureAwait(false);
_outputStream.Close();
if (_Response != null)
{
_Response.Close();
}
_Response?.Close();
ResponseSent = true;
return true;
@ -229,13 +226,10 @@ namespace EonaCat.Network
SendHeaders();
}
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
_OutputStream.Close();
await _outputStream.FlushAsync(token).ConfigureAwait(false);
_outputStream.Close();
if (_Response != null)
{
_Response.Close();
}
_Response?.Close();
ResponseSent = true;
return true;
@ -288,17 +282,14 @@ namespace EonaCat.Network
{
if (bytes != null && bytes.Length > 0)
{
await _OutputStream.WriteAsync(bytes, 0, bytes.Length, token).ConfigureAwait(false);
await _outputStream.WriteAsync(bytes, 0, bytes.Length, token).ConfigureAwait(false);
}
}
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
_OutputStream.Close();
await _outputStream.FlushAsync(token).ConfigureAwait(false);
_outputStream.Close();
if (_Response != null)
{
_Response.Close();
}
_Response?.Close();
ResponseSent = true;
return true;
@ -347,17 +338,14 @@ namespace EonaCat.Network
{
if (data != null && data.Length > 0)
{
await _OutputStream.WriteAsync(data, 0, data.Length, token).ConfigureAwait(false);
await _outputStream.WriteAsync(data, 0, data.Length, token).ConfigureAwait(false);
}
}
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
_OutputStream.Close();
await _outputStream.FlushAsync(token).ConfigureAwait(false);
_outputStream.Close();
if (_Response != null)
{
_Response.Close();
}
_Response?.Close();
ResponseSent = true;
return true;
@ -406,7 +394,7 @@ namespace EonaCat.Network
if (bytesRead > 0)
{
await Data.WriteAsync(buffer, 0, bytesRead, token).ConfigureAwait(false);
await _OutputStream.WriteAsync(buffer, 0, bytesRead, token).ConfigureAwait(false);
await _outputStream.WriteAsync(buffer, 0, bytesRead, token).ConfigureAwait(false);
bytesRemaining -= bytesRead;
}
}
@ -418,13 +406,10 @@ namespace EonaCat.Network
}
}
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
_OutputStream.Close();
await _outputStream.FlushAsync(token).ConfigureAwait(false);
_outputStream.Close();
if (_Response != null)
{
_Response.Close();
}
_Response?.Close();
ResponseSent = true;
return true;
@ -466,8 +451,8 @@ namespace EonaCat.Network
chunk = new byte[0];
}
await _OutputStream.WriteAsync(chunk, 0, numBytes, token).ConfigureAwait(false);
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
await _outputStream.WriteAsync(chunk, 0, numBytes, token).ConfigureAwait(false);
await _outputStream.FlushAsync(token).ConfigureAwait(false);
}
catch (Exception)
{
@ -504,19 +489,16 @@ namespace EonaCat.Network
{
if (chunk != null && chunk.Length > 0)
{
await _OutputStream.WriteAsync(chunk, 0, numBytes, token).ConfigureAwait(false);
await _outputStream.WriteAsync(chunk, 0, numBytes, token).ConfigureAwait(false);
}
byte[] endChunk = new byte[0];
await _OutputStream.WriteAsync(endChunk, 0, endChunk.Length, token).ConfigureAwait(false);
await _outputStream.WriteAsync(endChunk, 0, endChunk.Length, token).ConfigureAwait(false);
await _OutputStream.FlushAsync(token).ConfigureAwait(false);
_OutputStream.Close();
await _outputStream.FlushAsync(token).ConfigureAwait(false);
_outputStream.Close();
if (_Response != null)
{
_Response.Close();
}
_Response?.Close();
ResponseSent = true;
return true;
@ -647,32 +629,6 @@ namespace EonaCat.Network
}
}
private byte[] PackageChunk(byte[] chunk)
{
if (chunk == null || chunk.Length < 1)
{
return Encoding.UTF8.GetBytes("0\r\n\r\n");
}
MemoryStream ms = new MemoryStream();
string newlineStr = "\r\n";
byte[] newline = Encoding.UTF8.GetBytes(newlineStr);
string chunkLenHex = chunk.Length.ToString("X");
byte[] chunkLen = Encoding.UTF8.GetBytes(chunkLenHex);
ms.Write(chunkLen, 0, chunkLen.Length);
ms.Write(newline, 0, newline.Length);
ms.Write(chunk, 0, chunk.Length);
ms.Write(newline, 0, newline.Length);
ms.Seek(0, SeekOrigin.Begin);
byte[] ret = ms.ToArray();
return ret;
}
private byte[] ReadStreamFully(Stream input)
{
if (input == null)

View File

@ -613,8 +613,7 @@ namespace EonaCat.Network
extension = "." + extension;
}
string mime;
return data.TryGetValue(extension.ToLower(), out mime) ? mime : "application/octet-stream";
return data.TryGetValue(extension.ToLower(), out string mime) ? mime : "application/octet-stream";
}
}
}

View File

@ -218,20 +218,5 @@ namespace EonaCat.Network
_Routes.Add(route);
}
}
private void Remove(StaticRoute route)
{
if (route == null)
{
throw new ArgumentNullException(nameof(route));
}
lock (_Lock)
{
_Routes.Remove(route);
}
return;
}
}
}