http: longer timeouts for ws

This commit is contained in:
uwaa 2025-01-20 22:28:00 +00:00
parent 242982ff0b
commit a0db75bfdd
3 changed files with 36 additions and 16 deletions

View file

@ -60,6 +60,11 @@ public sealed class HttpServer
/// </summary>
public TimeSpan Timeout = TimeSpan.FromSeconds(20);
/// <summary>
/// The maximum time a websocket may be inactive before it is presumed dead and closed.
/// </summary>
public TimeSpan TimeoutWS = TimeSpan.FromSeconds(60);
readonly Dictionary<IPAddress, int> IPCounts = new Dictionary<IPAddress, int>();
readonly SemaphoreSlim IPCountsLock = new SemaphoreSlim(1, 1);
@ -165,6 +170,9 @@ public sealed class HttpServer
if (response is SwitchingProtocols swp)
{
httpStream.Timeout = TimeoutWS;
httpStream.KeepAlive();
//Create and run websocket
WebsocketRemote ws = new WebsocketRemote(req, clientInfo, httpStream, swp.Fields.WebSocketProtocol);
CloseStatus closeStatus = await swp.Callback(ws);

View file

@ -1,8 +1,6 @@
using System.Buffers;
using System.Collections.Specialized;
using System.Net.Sockets;
using System.Text;
using System.Web;
namespace Uwaa.HTTP;
@ -28,19 +26,27 @@ class HttpStream : IDisposable
/// </summary>
public TimeSpan Timeout;
internal readonly CancellationTokenSource CancelSrc = new CancellationTokenSource();
public HttpStream(Stream stream, TimeSpan timeout) : base()
{
Stream = stream;
Timeout = timeout;
Buffer = new BufferedStream(stream);
Decoder = Encoding.ASCII.GetDecoder();
}
/// <summary>
/// Resets the timeout timer.
/// </summary>
public void KeepAlive()
{
CancelSrc.CancelAfter(Timeout);
}
public async ValueTask<string> ReadLine()
{
CancellationTokenSource cancelSrc = new CancellationTokenSource();
cancelSrc.CancelAfter(Timeout);
CancelSrc.CancelAfter(Timeout);
const int maxChars = 4096;
byte[] dataBuffer = ArrayPool<byte>.Shared.Rent(1);
@ -50,7 +56,7 @@ class HttpStream : IDisposable
int charBufferIndex = 0;
while (true)
{
if (await Buffer.ReadAsync(dataBuffer.AsMemory(0, 1), cancelSrc.Token) == 0)
if (await Stream.ReadAsync(dataBuffer.AsMemory(0, 1), CancelSrc.Token) == 0)
if (charBufferIndex == 0)
throw new SocketException((int)SocketError.ConnectionReset);
else
@ -87,15 +93,14 @@ class HttpStream : IDisposable
public async ValueTask<int> Read(Memory<byte> buffer)
{
CancellationTokenSource cancelSrc = new CancellationTokenSource();
cancelSrc.CancelAfter(Timeout);
CancelSrc.CancelAfter(Timeout);
try
{
int index = 0;
while (index < buffer.Length)
{
int count = await Buffer.ReadAsync(buffer[index..], cancelSrc.Token);
int count = await Stream.ReadAsync(buffer[index..], CancelSrc.Token);
if (count == 0)
break;
@ -134,11 +139,10 @@ class HttpStream : IDisposable
public ValueTask Write(ReadOnlyMemory<byte> bytes)
{
CancellationTokenSource cancelSrc = new CancellationTokenSource();
cancelSrc.CancelAfter(Timeout);
CancelSrc.CancelAfter(Timeout);
try
{
return Buffer.WriteAsync(bytes, cancelSrc.Token);
return Buffer.WriteAsync(bytes, CancelSrc.Token);
}
catch (IOException e)
{
@ -151,12 +155,11 @@ class HttpStream : IDisposable
public async Task Flush()
{
CancellationTokenSource cancelSrc = new CancellationTokenSource();
cancelSrc.CancelAfter(Timeout);
CancelSrc.CancelAfter(Timeout);
try
{
await Buffer.FlushAsync(cancelSrc.Token);
await Stream.FlushAsync(cancelSrc.Token);
await Buffer.FlushAsync(CancelSrc.Token);
await Stream.FlushAsync(CancelSrc.Token);
}
catch (IOException e)
{

View file

@ -14,6 +14,15 @@ public class Websocket
/// </summary>
public readonly string? SubProtocol;
/// <summary>
/// The maximum time the websocket may be inactive before it is presumed dead and closed.
/// </summary>
public TimeSpan Timeout
{
get => Stream.Timeout;
set => Stream.Timeout = value;
}
internal readonly HttpStream Stream;
readonly List<byte> finalPayload = new List<byte>();