diff --git a/OpenSim/Framework/ExpiringCacheOS.cs b/OpenSim/Framework/ExpiringCacheOS.cs
index 00be73d..6f6de40 100644
--- a/OpenSim/Framework/ExpiringCacheOS.cs
+++ b/OpenSim/Framework/ExpiringCacheOS.cs
@@ -30,6 +30,7 @@ using System;
using System.Threading;
using System.Collections.Generic;
using Timer = System.Threading.Timer;
+using System.Runtime.InteropServices;
namespace OpenSim.Framework
{
@@ -460,6 +461,59 @@ namespace OpenSim.Framework
return success;
}
+ public ref TValue1 TryGetOrDefaultValue(TKey1 key, out bool existed)
+ {
+ bool gotLock = false;
+ try
+ {
+ try { }
+ finally
+ {
+ m_rwLock.ExitUpgradeableReadLock();
+ gotLock = true;
+ }
+
+ return ref CollectionsMarshal.GetValueRefOrAddDefault(m_values, key, out existed);
+ }
+ finally
+ {
+ if (gotLock)
+ m_rwLock.ExitUpgradeableReadLock();
+ }
+ }
+
+ public ref TValue1 TryGetOrDefaultValue(TKey1 key, int expireMS, out bool existed)
+ {
+ bool gotLock = false;
+ try
+ {
+ try { }
+ finally
+ {
+ m_rwLock.EnterWriteLock();
+ gotLock = true;
+ }
+
+ ref TValue1 ret = ref CollectionsMarshal.GetValueRefOrAddDefault(m_values, key, out existed);
+ int now;
+ if (expireMS > 0)
+ {
+ expireMS = (expireMS > m_expire) ? expireMS : m_expire;
+ now = (int)(Util.GetTimeStampMS() - m_startTS) + expireMS;
+ }
+ else
+ now = int.MinValue;
+
+ m_expireControl[key] = now;
+ return ref ret;
+ }
+ finally
+ {
+ if (gotLock)
+ m_rwLock.EnterWriteLock();
+ }
+ }
+
public TValue1[] Values
{
get
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs
index dbf0c2d..bebe2fb 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs
@@ -322,7 +322,7 @@ namespace OSHttpServer
default:
return;
}
- m_processWaitEven.Set();
+ m_processWaitEven?.Set();
}
public static void PulseWaitSend()
diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs
index af9f9ea..4be0632 100644
--- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs
+++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs
@@ -5,6 +5,8 @@ using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
+using System.Threading.Tasks;
+using System.Runtime.CompilerServices;
namespace OSHttpServer
{
@@ -19,8 +21,8 @@ namespace OSHttpServer
private TcpListener m_listener;
private ILogWriter m_logWriter = NullLogWriter.Instance;
- private int m_pendingAccepts;
private bool m_shutdown;
+ public readonly CancellationTokenSource m_CancellationSource = new();
protected RemoteCertificateValidationCallback m_clientCertValCallback = null;
public event EventHandler<ClientAcceptedEventArgs> Accepted;
@@ -86,6 +88,7 @@ namespace OSHttpServer
return new OSHttpListener(address, port, certificate, protocols);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void OnRequestReceived(object sender, RequestEventArgs e)
{
RequestReceived?.Invoke(sender, e);
@@ -120,76 +123,53 @@ namespace OSHttpServer
/// </summary>
public bool UseTraceLogs { get; set; }
-
- /// <exception cref="Exception"><c>Exception</c>.</exception>
- private void OnAccept(IAsyncResult ar)
+ private async void AcceptLoop()
{
- bool beginAcceptCalled = false;
try
{
- int count = Interlocked.Decrement(ref m_pendingAccepts);
- if (m_shutdown)
+ while (true)
{
- if (count == 0)
+ if (m_shutdown)
+ {
m_shutdownEvent.Set();
- return;
- }
-
- Interlocked.Increment(ref m_pendingAccepts);
- m_listener.BeginAcceptSocket(OnAccept, null);
- beginAcceptCalled = true;
- Socket socket = m_listener.EndAcceptSocket(ar);
- if (!socket.Connected)
- {
- socket.Dispose();
- return;
- }
-
- socket.NoDelay = true;
-
- if (!OnAcceptingSocket(socket))
- {
- socket.Disconnect(true);
- return;
- }
-
- if(socket.Connected)
- {
- m_logWriter.Write(this, LogPrio.Debug, $"Accepted connection from: {socket.RemoteEndPoint}");
-
- if (m_certificate is not null)
- m_contextFactory.CreateSecureContext(socket, m_certificate, m_sslProtocols, m_clientCertValCallback);
+ break;
+ }
+
+ Socket socket = await m_listener.AcceptSocketAsync(m_CancellationSource.Token).ConfigureAwait(false); ;
+ if (!socket.Connected)
+ {
+ socket.Dispose();
+ continue;
+ }
+
+ socket.NoDelay = true;
+
+ if (!OnAcceptingSocket(socket))
+ {
+ socket.Disconnect(true);
+ continue;
+ }
+ if (socket.Connected)
+ {
+ m_logWriter.Write(this, LogPrio.Debug, $"Accepted connection from: {socket.RemoteEndPoint}");
+
+ if (m_certificate is not null)
+ m_contextFactory.CreateSecureContext(socket, m_certificate, m_sslProtocols, m_clientCertValCallback);
+ else
+ m_contextFactory.CreateContext(socket);
+ }
else
- m_contextFactory.CreateContext(socket);
+ socket.Dispose();
}
- else
- socket.Dispose();
}
- catch (Exception err)
+ catch (OperationCanceledException)
{
- m_logWriter.Write(this, LogPrio.Debug, err.Message);
- ExceptionThrown?.Invoke(this, err);
-
- if (!beginAcceptCalled)
- RetryBeginAccept();
- }
- }
-
- /// <summary>
- /// Will try to accept connections one more time.
- /// </summary>
- /// <exception cref="Exception">If any exceptions is thrown.</exception>
- private void RetryBeginAccept()
- {
- try
- {
- m_logWriter.Write(this, LogPrio.Error, "Trying to accept connections again.");
- m_listener.BeginAcceptSocket(OnAccept, null);
+ m_shutdownEvent.Set();
}
catch (Exception err)
{
- m_logWriter.Write(this, LogPrio.Fatal, err.Message);
- ExceptionThrown?.Invoke(this, err);
+ m_logWriter.Write(this, LogPrio.Debug, err.Message);
+ ExceptionThrown?.Invoke(this, err);
}
}
@@ -221,8 +201,7 @@ namespace OSHttpServer
m_listener = new TcpListener(m_address, m_port);
m_listener.Start(backlog);
- Interlocked.Increment(ref m_pendingAccepts);
- m_listener.BeginAcceptSocket(OnAccept, null);
+ Task.Run(AcceptLoop).ConfigureAwait(false);
}
/// <summary>
@@ -232,10 +211,11 @@ namespace OSHttpServer
public void Stop()
{
m_shutdown = true;
+ m_CancellationSource.Cancel();
m_contextFactory.Shutdown();
- m_listener.Stop();
if (!m_shutdownEvent.WaitOne())
m_logWriter.Write(this, LogPrio.Error, "Failed to shutdown listener properly.");
+ m_listener.Stop();
m_listener = null;
Dispose();
}
@@ -251,6 +231,7 @@ namespace OSHttpServer
if (m_shutdownEvent != null)
{
m_shutdownEvent.Dispose();
+ m_CancellationSource.Dispose();
}
}
}