replace beginaccept

UbitUmarov [2024-04-28 09:58:27]
replace beginaccept
Filename
OpenSim/Framework/ExpiringCacheOS.cs
OpenSim/Framework/Servers/HttpServer/OSHttpServer/ContextTimeoutManager.cs
OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpListener.cs
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();
             }
         }
     }
ViewGit