mirror of
https://github.com/AlexMacocian/MTSC.git
synced 2026-07-15 14:59:33 +00:00
Improvements to stream reading routine
This commit is contained in:
@@ -40,7 +40,7 @@ namespace MTSC
|
||||
return new Message((uint)ms.Length, ms.ToArray());
|
||||
}
|
||||
|
||||
public static Message GetMessage(ClientData client, TimeSpan ReadTimeout)
|
||||
public static async Task<Message> GetMessage(ClientData client, TimeSpan ReadTimeout)
|
||||
{
|
||||
Stream stream;
|
||||
if (client.SslStream != null)
|
||||
@@ -58,9 +58,11 @@ namespace MTSC
|
||||
int bytesRead;
|
||||
do
|
||||
{
|
||||
bytesRead = stream.Read(buffer, 0, buffer.Length);
|
||||
using var cts = new CancellationTokenSource();
|
||||
cts.CancelAfter((int)ReadTimeout.TotalMilliseconds);
|
||||
bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cts.Token);
|
||||
ms.Write(buffer, 0, bytesRead);
|
||||
} while (bytesRead > 0);
|
||||
} while (bytesRead > 0 && client.TcpClient.Available > 0);
|
||||
return new Message((uint)ms.Length, ms.ToArray());
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -5,13 +5,13 @@
|
||||
<TargetFrameworks>netcoreapp2.1;net48;netstandard2.0;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<Version>4.1.1</Version>
|
||||
<Version>4.1.2</Version>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Authors>Alexandru-Victor Macocian</Authors>
|
||||
<Product>MTSC</Product>
|
||||
<Description>Modular TCP Server and Client</Description>
|
||||
<AssemblyVersion>4.1.1.0</AssemblyVersion>
|
||||
<FileVersion>4.1.1.0</FileVersion>
|
||||
<AssemblyVersion>4.1.2.0</AssemblyVersion>
|
||||
<FileVersion>4.1.2.0</FileVersion>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
<PackageProjectUrl>https://github.com/AlexMacocian/MTSC</PackageProjectUrl>
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace MTSC.ServerSide.Handlers
|
||||
Initialized
|
||||
}
|
||||
|
||||
private List<IFtpModule> ftpModules = new();
|
||||
private readonly List<IFtpModule> ftpModules = new();
|
||||
|
||||
public TimeSpan ReadyDelay { get; set; } = TimeSpan.FromSeconds(1);
|
||||
|
||||
|
||||
@@ -102,11 +102,11 @@ namespace MTSC.ServerSide.Handlers
|
||||
bool IHandler.HandleReceivedMessage(Server server, ClientData client, Message message)
|
||||
{
|
||||
// Parse the request. If the message is incomplete, return 100 and queue the message to be parsed later.
|
||||
HttpRequest request = null;
|
||||
byte[] messageBytes = null;
|
||||
HttpRequest request;
|
||||
try
|
||||
{
|
||||
var trimmedMessageBytes = message.MessageBytes.TrimTrailingNullBytes();
|
||||
byte[] messageBytes;
|
||||
if (client.Resources.TryGetResource<FragmentedMessage>(out var fragmentedMessage))
|
||||
{
|
||||
var previousBytes = fragmentedMessage.Message;
|
||||
@@ -147,7 +147,7 @@ namespace MTSC.ServerSide.Handlers
|
||||
else
|
||||
{
|
||||
client.SetAffinity(this);
|
||||
this.HandleIncompleteRequest(client, server, messageBytes, partialRequest);
|
||||
this.HandleIncompleteRequest(client, server, messageBytes);
|
||||
if (partialRequest != null && partialRequest.Headers.ContainsHeader(RequestHeaders.Expect) &&
|
||||
partialRequest.Headers[RequestHeaders.Expect].Equals("100-continue", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -287,7 +287,7 @@ namespace MTSC.ServerSide.Handlers
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void HandleIncompleteRequest(ClientData client, Server server, byte[] messageBytes, PartialHttpRequest partialRequest = null)
|
||||
private void HandleIncompleteRequest(ClientData client, Server server, byte[] messageBytes)
|
||||
{
|
||||
client.Resources.SetResource(new FragmentedMessage() { Message = messageBytes, LastReceived = DateTime.Now });
|
||||
server.LogDebug("Incomplete request received!");
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace MTSC.ServerSide.Handlers
|
||||
Closed
|
||||
}
|
||||
#region Fields
|
||||
private byte[] emptyData = new byte[0];
|
||||
private readonly byte[] emptyData = new byte[0];
|
||||
private DateTime ellapsedTime = DateTime.Now;
|
||||
private DateTime previousHeartbeatProc = DateTime.Now;
|
||||
private readonly Dictionary<string, (Type, Func<Server, HttpRequest, ClientData, RouteEnablerResponse>)> moduleDictionary =
|
||||
|
||||
+16
-29
@@ -36,7 +36,6 @@ namespace MTSC.ServerSide
|
||||
private readonly List<IExceptionHandler> exceptionHandlers = new();
|
||||
private readonly List<IServerUsageMonitor> serverUsageMonitors = new();
|
||||
private readonly ProducerConsumerQueue<(ClientData, byte[])> messageOutQueue = new();
|
||||
private readonly IServiceManager serviceManager = new ServiceManager();
|
||||
#endregion
|
||||
#region Private Properties
|
||||
private IConsumerQueue<ClientData> ConsumerClientQueue { get => this.addQueue; }
|
||||
@@ -103,7 +102,7 @@ namespace MTSC.ServerSide
|
||||
/// <summary>
|
||||
/// <see cref="IServiceManager"/> for configuring and retrieving services.
|
||||
/// </summary>
|
||||
public IServiceManager ServiceManager { get => this.serviceManager; }
|
||||
public IServiceManager ServiceManager { get; } = new ServiceManager();
|
||||
#endregion
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
@@ -162,7 +161,7 @@ namespace MTSC.ServerSide
|
||||
where TService : TInterface
|
||||
where TInterface : class
|
||||
{
|
||||
this.serviceManager.RegisterTransient<TInterface, TService>();
|
||||
this.ServiceManager.RegisterTransient<TInterface, TService>();
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -172,7 +171,7 @@ namespace MTSC.ServerSide
|
||||
public Server AddTransientService<TService>()
|
||||
where TService : class
|
||||
{
|
||||
this.serviceManager.RegisterTransient<TService>();
|
||||
this.ServiceManager.RegisterTransient<TService>();
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -183,7 +182,7 @@ namespace MTSC.ServerSide
|
||||
where TService : TInterface
|
||||
where TInterface : class
|
||||
{
|
||||
this.serviceManager.RegisterTransient<TInterface, TService>(serviceFactory);
|
||||
this.ServiceManager.RegisterTransient<TInterface, TService>(serviceFactory);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -193,7 +192,7 @@ namespace MTSC.ServerSide
|
||||
public Server AddTransientService<TService>(Func<Slim.IServiceProvider, TService> serviceFactory)
|
||||
where TService : class
|
||||
{
|
||||
this.serviceManager.RegisterTransient<TService>(serviceFactory);
|
||||
this.ServiceManager.RegisterTransient<TService>(serviceFactory);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -204,7 +203,7 @@ namespace MTSC.ServerSide
|
||||
where TService : TInterface
|
||||
where TInterface : class
|
||||
{
|
||||
this.serviceManager.RegisterSingleton<TInterface, TService>();
|
||||
this.ServiceManager.RegisterSingleton<TInterface, TService>();
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -214,7 +213,7 @@ namespace MTSC.ServerSide
|
||||
public Server AddSingletonService<TService>()
|
||||
where TService : class
|
||||
{
|
||||
this.serviceManager.RegisterSingleton<TService>();
|
||||
this.ServiceManager.RegisterSingleton<TService>();
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -225,7 +224,7 @@ namespace MTSC.ServerSide
|
||||
where TService : TInterface
|
||||
where TInterface : class
|
||||
{
|
||||
this.serviceManager.RegisterSingleton<TInterface, TService>(serviceFactory);
|
||||
this.ServiceManager.RegisterSingleton<TInterface, TService>(serviceFactory);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -235,7 +234,7 @@ namespace MTSC.ServerSide
|
||||
public Server AddSingletonService<TService>(Func<Slim.IServiceProvider, TService> serviceFactory)
|
||||
where TService : class
|
||||
{
|
||||
this.serviceManager.RegisterSingleton<TService>(serviceFactory);
|
||||
this.ServiceManager.RegisterSingleton<TService>(serviceFactory);
|
||||
return this;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -406,7 +405,7 @@ namespace MTSC.ServerSide
|
||||
public T GetService<T>()
|
||||
where T : class
|
||||
{
|
||||
return this.serviceManager.GetService<T>();
|
||||
return this.ServiceManager.GetService<T>();
|
||||
}
|
||||
/// <summary>
|
||||
/// Get handler of provided type
|
||||
@@ -528,8 +527,8 @@ namespace MTSC.ServerSide
|
||||
toBeRunOnStartup.OnStartup(this);
|
||||
}
|
||||
|
||||
this.serviceManager.RegisterServiceManager();
|
||||
this.serviceManager.RegisterSingleton<Server, Server>(sp => this);
|
||||
this.ServiceManager.RegisterServiceManager();
|
||||
this.ServiceManager.RegisterSingleton<Server, Server>(sp => this);
|
||||
DateTime startLoopTime;
|
||||
while (this.running)
|
||||
{
|
||||
@@ -666,13 +665,6 @@ namespace MTSC.ServerSide
|
||||
while (this.ConsumerMessageOutQueue.TryDequeue(out var tuple))
|
||||
{
|
||||
(var client, var bytes) = tuple;
|
||||
if (client.TcpClient.Available > 0)
|
||||
{
|
||||
/*
|
||||
* Don't send while client is still sending
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
@@ -744,19 +736,14 @@ namespace MTSC.ServerSide
|
||||
if (client.TcpClient.Available > 0 && !(client as IActiveClient).ReadingData)
|
||||
{
|
||||
(client as IActiveClient).ReadingData = true;
|
||||
Task.Run(() =>
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeout = this.ReadTimeout;
|
||||
if (client.TcpClient.Available < 1000)
|
||||
{
|
||||
timeout = TimeSpan.FromMilliseconds(50);
|
||||
}
|
||||
|
||||
var message = CommunicationPrimitives.GetMessage(client, timeout);
|
||||
var message = await CommunicationPrimitives.GetMessage(client, timeout);
|
||||
(client as IQueueHolder<Message>).Enqueue(message);
|
||||
this.LogDebug($"Received message from {(client.TcpClient.Client.RemoteEndPoint as IPEndPoint)} Message length: {message.MessageLength}");
|
||||
this.LogDebug($"Received message from {client.TcpClient.Client.RemoteEndPoint as IPEndPoint} Message length: {message.MessageLength}");
|
||||
if (this.LogMessageContents)
|
||||
{
|
||||
this.LogDebug(Encoding.UTF8.GetString(message.MessageBytes));
|
||||
@@ -852,7 +839,7 @@ namespace MTSC.ServerSide
|
||||
this.EncryptionPolicy);
|
||||
client.SslStream = sslStream;
|
||||
|
||||
if(sslStream.AuthenticateAsServerAsync(this.certificate, this.RequestClientCertificate, this.SslProtocols, false).Wait(this.SslAuthenticationTimeout))
|
||||
if (sslStream.AuthenticateAsServerAsync(this.certificate, this.RequestClientCertificate, this.SslProtocols, false).Wait(this.SslAuthenticationTimeout))
|
||||
{
|
||||
/*
|
||||
* Client authenticated in the alloted time
|
||||
|
||||
Reference in New Issue
Block a user