diff --git a/OpenSim/Framework/RestClient.cs b/OpenSim/Framework/RestClient.cs index a87a52e434..d0dfc9d060 100644 --- a/OpenSim/Framework/RestClient.cs +++ b/OpenSim/Framework/RestClient.cs @@ -269,6 +269,15 @@ namespace OpenSim.Framework request.Headers.ExpectContinue = false; request.Headers.TransferEncodingChunked = false; + //if (keepalive) + { + request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); + request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; + } + //else + // request.Headers.TryAddWithoutValidation("Connection", "close"); + cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(DefaultTimeout)); if (WebUtil.DebugLevel >= 3) diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 29b24a1de0..101d9c7ff0 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -411,6 +411,7 @@ namespace OpenSim.Framework { request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; } else request.Headers.TryAddWithoutValidation("Connection", "close"); @@ -560,6 +561,7 @@ namespace OpenSim.Framework //{ // request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); // request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + // request.Headers.ConnectionClose = false; //} //else request.Headers.TryAddWithoutValidation("Connection", "close"); @@ -1178,6 +1180,7 @@ namespace OpenSim.Framework { request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; } else request.Headers.TryAddWithoutValidation("Connection", "close"); @@ -1273,6 +1276,7 @@ namespace OpenSim.Framework { request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; } else request.Headers.TryAddWithoutValidation("Connection", "close"); @@ -1412,6 +1416,7 @@ namespace OpenSim.Framework { request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; } //else // request.Headers.TryAddWithoutValidation("Connection", "close"); @@ -1535,6 +1540,7 @@ namespace OpenSim.Framework { request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; } //else // request.Headers.TryAddWithoutValidation("Connection", "close"); diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 17053cd8ab..5b37f4520e 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Net; +using System.Net.Http; using System.Reflection; using Nini.Config; @@ -40,6 +41,7 @@ using OpenSim.Services.Interfaces; using OpenSim.Server.Base; using OpenMetaverse; using System.Text; +using System.Threading; namespace OpenSim.Services.Connectors { @@ -747,54 +749,59 @@ namespace OpenSim.Services.Connectors { if (WebUtil.DebugLevel >= 3) m_log.Debug($"[XInventory]: HTTP OUT SynchronousRestForms POST to {m_InventoryURL}"); - - int tickstart = Util.EnvironmentTickCount(); - - HttpWebRequest request; - try + if (string.IsNullOrEmpty(obj)) { - request = (HttpWebRequest)WebRequest.Create(m_InventoryURL); - request.Method = "POST"; - if (m_requestTimeoutSecs > 0) - request.Timeout = m_requestTimeoutSecs * 1000; - if (m_Auth is not null) - m_Auth.AddAuthorization(request.Headers); - - request.AllowWriteStreamBuffering = false; - request.ContentType = "application/x-www-form-urlencoded"; - } - catch (Exception e) - { - m_log.Info($"[XInventory]: Error creating POST request to {m_InventoryURL}: {e.Message}"); - throw; - } - - int sendlen; - try - { - byte[] data = Util.UTF8NBGetbytes(obj); - sendlen = data.Length; - request.ContentLength = sendlen; - - using (Stream requestStream = request.GetRequestStream()) - requestStream.Write(data, 0, sendlen); - data = null; - } - catch (Exception e) - { - m_log.Info($"[XInventory]: Error sending POST request to {m_InventoryURL}: {e.Message}"); - throw; + m_log.Warn($"[XInventory]: empty post data"); + return new Dictionary(); } Dictionary respDic = null; + int ticks = Util.EnvironmentTickCount(); + int sendlen = 0; int rcvlen = 0; + HttpResponseMessage responseMessage = null; + HttpRequestMessage request = null; + CancellationTokenSource cancellationToken = null; try { - using WebResponse resp = request.GetResponse(); - if (resp.ContentLength != 0) + HttpClient client = WebUtil.SharedHttpClientWithRedir; + + request = new(HttpMethod.Post, m_InventoryURL); + + m_Auth?.AddAuthorization(request.Headers); + + //if (keepalive) { - rcvlen = (int)resp.ContentLength; - respDic = ServerUtils.ParseXmlResponse(resp.GetResponseStream()); + request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); + request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive"); + request.Headers.ConnectionClose = false; + } + //else + // request.Headers.TryAddWithoutValidation("Connection", "close"); + + request.Headers.ExpectContinue = false; + request.Headers.TransferEncodingChunked = false; + + if (m_requestTimeoutSecs > 0) + cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(m_requestTimeoutSecs)); + + byte[] data = Util.UTF8NBGetbytes(obj); + sendlen = data.Length; + + request.Content = new ByteArrayContent(data); + request.Content.Headers.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded"); + request.Content.Headers.TryAddWithoutValidation("Content-Length", sendlen.ToString()); + + if (cancellationToken is null) + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); + else + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Token); + responseMessage.EnsureSuccessStatusCode(); + + if ((responseMessage.Content.Headers.ContentLength is long contentLength) && contentLength != 0) + { + rcvlen = (int)contentLength; + respDic = ServerUtils.ParseXmlResponse(responseMessage.Content.ReadAsStream()); } } catch (Exception e) @@ -802,11 +809,17 @@ namespace OpenSim.Services.Connectors m_log.Info($"[XInventory]: Error receiving response from {m_InventoryURL}: {e.Message}"); throw; } - - int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); - if (tickdiff > WebUtil.LongCallTime) + finally { - m_log.Info($"[XInventory]: POST {m_InventoryURL} took {tickdiff}ms {sendlen}/{rcvlen}bytes"); + request?.Dispose(); + responseMessage?.Dispose(); + cancellationToken?.Dispose(); + } + + ticks = Util.EnvironmentTickCountSubtract(ticks); + if (ticks > WebUtil.LongCallTime) + { + m_log.Info($"[XInventory]: POST {m_InventoryURL} took {ticks}ms {sendlen}/{rcvlen}bytes"); } return respDic ?? new Dictionary();