From e950c502ad0e24bcec9a2957ec7fbf6e32af5096 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 26 May 2023 20:27:24 +0100 Subject: [PATCH] change share of almost empty class httpclient, to just share of used SocketsHttpHandler, This simpifies handling of timeout, otherwise problematic --- OpenSim/Framework/RestClient.cs | 21 ++- OpenSim/Framework/Util.cs | 7 +- OpenSim/Framework/WebUtil.cs | 132 +++++++----------- .../InstantMessage/MessageTransferModule.cs | 9 +- .../Scripting/XMLRPC/XMLRPCModule.cs | 6 +- .../RegionReadyModule/RegionReadyModule.cs | 4 +- .../Hypergrid/GatekeeperServiceConnector.cs | 7 +- .../Hypergrid/UserAgentServiceConnector.cs | 13 +- .../InstantMessageServiceConnector.cs | 5 +- .../Inventory/XInventoryServicesConnector.cs | 18 +-- .../Connectors/Land/LandServicesConnector.cs | 4 +- .../Neighbour/NeighbourServicesConnector.cs | 9 +- bin/XMLRPC.dll | Bin 28160 -> 28160 bytes 13 files changed, 108 insertions(+), 127 deletions(-) diff --git a/OpenSim/Framework/RestClient.cs b/OpenSim/Framework/RestClient.cs index 5c168722b0..49c7f632a5 100644 --- a/OpenSim/Framework/RestClient.cs +++ b/OpenSim/Framework/RestClient.cs @@ -88,7 +88,7 @@ namespace OpenSim.Framework /// /// Default time out period /// - private const int DefaultTimeout = 90; // 90 seconds timeout + private const int DefaultTimeout = 90000; // 90 seconds timeout /// /// Default Buffer size of a block requested from the web-server @@ -258,10 +258,10 @@ namespace OpenSim.Framework Uri uri = null; HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(DefaultTimeout); uri = buildUri(); request = new(new HttpMethod(RequestMethod), uri); @@ -278,13 +278,12 @@ namespace OpenSim.Framework //else // request.Headers.TryAddWithoutValidation("Connection", "close"); - cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(DefaultTimeout)); if (WebUtil.DebugLevel >= 3) m_log.DebugFormat("[REST CLIENT] {0} to {1}", RequestMethod, uri); //_request.ContentType = "application/xml"; - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Token); + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); Stream respStream = responseMessage.Content.ReadAsStream(); @@ -326,7 +325,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } if (_resource != null) @@ -348,10 +347,10 @@ namespace OpenSim.Framework Uri uri = null; HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(DefaultTimeout); uri = buildUri(); request = new(HttpMethod.Post, uri); @@ -368,13 +367,11 @@ namespace OpenSim.Framework //else // request.Headers.TryAddWithoutValidation("Connection", "close"); - cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(DefaultTimeout)); - request.Content = new ByteArrayContent(src); request.Content.Headers.TryAddWithoutValidation("Content-Type", "application/xml"); request.Content.Headers.TryAddWithoutValidation("Content-Length", src.Length.ToString()); - responseMessage = client.Send(request, HttpCompletionOption.ResponseContentRead, cancellationToken.Token); + responseMessage = client.Send(request, HttpCompletionOption.ResponseContentRead); responseMessage.EnsureSuccessStatusCode(); } catch (HttpRequestException e) @@ -402,7 +399,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 6543295c08..56ec2b08d6 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -55,6 +55,7 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using Amib.Threading; using System.Collections.Concurrent; +using System.Net.Http; namespace OpenSim.Framework { @@ -2194,6 +2195,7 @@ namespace OpenSim.Framework return ms; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args) { return SendXmlRpcCommand(url, methodName, args); @@ -2201,8 +2203,9 @@ namespace OpenSim.Framework public static XmlRpcResponse SendXmlRpcCommand(string url, string methodName, object[] args) { - XmlRpcRequest client = new(methodName, args); - return client.Send(url, WebUtil.SharedHttpClientWithRedir, 6000); + XmlRpcRequest xmlclient = new(methodName, args); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + return xmlclient.Send(url, hclient); } /// diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index afbb29050e..1a9d9cc1e5 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -60,11 +60,8 @@ namespace OpenSim.Framework { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public static SocketsHttpHandler SharedSocketsHttpHandlerNoRedir = null; public static SocketsHttpHandler SharedSocketsHttpHandler = null; - public static HttpClient SharedHttpClient = null; - - public static SocketsHttpHandler SharedSocketsHttpHandlerWithRedir = null; - public static HttpClient SharedHttpClientWithRedir = null; public static ExpiringKey GlobalExpiringBadURLs = new(30000); /// @@ -177,15 +174,7 @@ namespace OpenSim.Framework shh.UseProxy = true; } - var client = new HttpClient(shh) - { - Timeout = TimeSpan.FromMilliseconds(30000), - MaxResponseContentBufferSize = 250 * 1024 * 1024, - }; - client.DefaultRequestHeaders.ExpectContinue = false; - - SharedSocketsHttpHandler = shh; - SharedHttpClient = client; + SharedSocketsHttpHandlerNoRedir = shh; // **************** @@ -250,16 +239,29 @@ namespace OpenSim.Framework shh.Proxy = proxy; shh.UseProxy = true; } + SharedSocketsHttpHandler = shh; + } - client = new HttpClient(shh) + public static HttpClient GetNewGlobalHttpClient(int timeout) + { + var client = new HttpClient(SharedSocketsHttpHandler, false) { - Timeout = TimeSpan.FromMilliseconds(30000), + Timeout = TimeSpan.FromMilliseconds(timeout > 0 ? timeout : 30000), MaxResponseContentBufferSize = 250 * 1024 * 1024, }; client.DefaultRequestHeaders.ExpectContinue = false; + return client; + } - SharedSocketsHttpHandlerWithRedir = shh; - SharedHttpClientWithRedir = client; + public static HttpClient GetGlobalNoRedirHttpClient(int timeout) + { + var client = new HttpClient(SharedSocketsHttpHandlerNoRedir, false) + { + Timeout = TimeSpan.FromMilliseconds(timeout > 0 ? timeout : 30000), + MaxResponseContentBufferSize = 250 * 1024 * 1024, + }; + client.DefaultRequestHeaders.ExpectContinue = false; + return client; } /// @@ -366,11 +368,10 @@ namespace OpenSim.Framework int rcvlen = 0; HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = SharedHttpClientWithRedir; - + client = GetNewGlobalHttpClient(timeout); request = new(new HttpMethod(method), url); if (data is not null) @@ -418,16 +419,9 @@ namespace OpenSim.Framework else request.Headers.TryAddWithoutValidation("Connection", "close"); - if(timeout > 0) - cancellationToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeout)); - request.Headers.TryAddWithoutValidation(OSHeaderRequestID, reqnum.ToString()); - if (cancellationToken is null) - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); - else - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Token); - + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); Stream resStream = responseMessage.Content.ReadAsStream(); @@ -455,7 +449,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); ticks = Util.EnvironmentTickCountSubtract(ticks); if (ticks > LongCallTime) @@ -549,10 +543,10 @@ namespace OpenSim.Framework HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = GetNewGlobalHttpClient(timeout); request = new(HttpMethod.Post, url); @@ -568,9 +562,6 @@ namespace OpenSim.Framework //else request.Headers.TryAddWithoutValidation("Connection", "close"); - if (timeout > 0) - cancellationToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(timeout)); - request.Headers.TryAddWithoutValidation(OSHeaderRequestID, reqnum.ToString()); if (data is not null) @@ -596,10 +587,7 @@ namespace OpenSim.Framework request.Content.Headers.TryAddWithoutValidation("Content-Length", "0"); } - if (cancellationToken is null) - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); - else - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Token); + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); using StreamReader reader = new(responseMessage.Content.ReadAsStream()); @@ -627,7 +615,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); ticks = Util.EnvironmentTickCountSubtract(ticks); if (ticks > LongCallTime) @@ -1160,13 +1148,13 @@ namespace OpenSim.Framework int ticks = Util.EnvironmentTickCount(); HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; string respstring = String.Empty; int sendlen = 0; int rcvlen = 0; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(timeoutsecs * 1000); request = new(new HttpMethod(method), requestUrl); @@ -1175,9 +1163,6 @@ namespace OpenSim.Framework request.Headers.ExpectContinue = false; request.Headers.TransferEncodingChunked = false; if (timeoutsecs > 0) - if(timeoutsecs > 0) - cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutsecs)); - if (keepalive) { request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10"); @@ -1202,10 +1187,7 @@ namespace OpenSim.Framework 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 = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); if ((responseMessage.Content.Headers.ContentLength is long contentLength) && contentLength != 0) @@ -1224,7 +1206,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } ticks = Util.EnvironmentTickCountSubtract(ticks); @@ -1259,14 +1241,13 @@ namespace OpenSim.Framework int ticks = Util.EnvironmentTickCount(); HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; string respstring = String.Empty; int sendlen = 0; int rcvlen = 0; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; - + client = WebUtil.GetNewGlobalHttpClient(timeoutsecs * 1000); request = new(HttpMethod.Post, requestUrl); auth?.AddAuthorization(request.Headers); @@ -1283,9 +1264,6 @@ namespace OpenSim.Framework else request.Headers.TryAddWithoutValidation("Connection", "close"); - if (timeoutsecs > 0) - cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutsecs)); - byte[] data = Util.UTF8NBGetbytes(obj); sendlen = data.Length; request.Content = new ByteArrayContent(data); @@ -1295,10 +1273,7 @@ namespace OpenSim.Framework if (WebUtil.DebugLevel >= 5) WebUtil.LogOutgoingDetail("SEND", reqnum, System.Text.Encoding.UTF8.GetString(data)); - if (cancellationToken is null) - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); - else - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Token); + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); if ((responseMessage.Content.Headers.ContentLength is long contentLength) && contentLength != 0) { @@ -1315,7 +1290,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } ticks = Util.EnvironmentTickCountSubtract(ticks); @@ -1401,11 +1376,11 @@ namespace OpenSim.Framework TResponse deserial = default; HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(pTimeout); request = new(new HttpMethod(method), requestUrl); @@ -1423,9 +1398,6 @@ namespace OpenSim.Framework //else // request.Headers.TryAddWithoutValidation("Connection", "close"); - if (pTimeout != 0) - cancellationToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(pTimeout)); - if (method.Equals("POST",StringComparison.OrdinalIgnoreCase) || method.Equals("PUT", StringComparison.OrdinalIgnoreCase)) { byte[] data; @@ -1448,10 +1420,7 @@ namespace OpenSim.Framework 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 = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); int rcvlen = 0; @@ -1508,7 +1477,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } return deserial; @@ -1525,12 +1494,10 @@ namespace OpenSim.Framework TResponse deserial = default; HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; - - + client = WebUtil.GetNewGlobalHttpClient(pTimeout); request = new(HttpMethod.Get, requestUrl); auth?.AddAuthorization(request.Headers); @@ -1547,13 +1514,7 @@ namespace OpenSim.Framework //else // request.Headers.TryAddWithoutValidation("Connection", "close"); - if (pTimeout != 0) - cancellationToken = new CancellationTokenSource(TimeSpan.FromMilliseconds(pTimeout)); - - if (cancellationToken is null) - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); - else - responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Token); + responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); int rcvlen = 0; @@ -1608,7 +1569,7 @@ namespace OpenSim.Framework { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } return deserial; } @@ -1674,7 +1635,7 @@ namespace OpenSim.Framework int tickstart = Util.EnvironmentTickCount(); string responseStr = null; - + HttpClient client = null; try { ArrayList SendParams = new() @@ -1691,7 +1652,8 @@ namespace OpenSim.Framework WebUtil.LogOutgoingDetail("SEND", reqnum, str); } - XmlRpcResponse Resp = Req.Send(url, WebUtil.SharedHttpClientWithRedir, 30000); + client = WebUtil.GetNewGlobalHttpClient(-1); + XmlRpcResponse Resp = Req.Send(url, client); try { @@ -1719,6 +1681,8 @@ namespace OpenSim.Framework } finally { + client?.Dispose(); + int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > WebUtil.LongCallTime) { diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 558ef4cdb3..5bed9deffe 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -41,6 +41,7 @@ using OpenSim.Region.Framework.Scenes; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using OpenSim.Services.Interfaces; +using System.Net.Http; namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { @@ -597,9 +598,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage ArrayList SendParams = new ArrayList(); SendParams.Add(xmlrpcdata); XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); + HttpClient hclient = null; try { - XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, WebUtil.SharedHttpClientWithRedir, 6000); + hclient = WebUtil.GetNewGlobalHttpClient(10000); + XmlRpcResponse GridResp = GridReq.Send(reginfo.ServerURI, hclient); Hashtable responseData = (Hashtable)GridResp.Value; if (responseData.ContainsKey("success")) { @@ -621,6 +624,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} : {1}", reginfo.ServerURI.ToString(), e.Message); } + finally + { + hclient?.Dispose(); + } return false; } diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index fd7ba447a7..0839ee0910 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -42,6 +42,7 @@ using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using Mono.Addins; +using System.Net.Http; /***************************************************** * @@ -686,9 +687,11 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC ArrayList parameters = new ArrayList(); parameters.Add(param); XmlRpcRequest req = new XmlRpcRequest(mName, parameters); + HttpClient hclient = null; try { - XmlRpcResponse resp = req.Send(DestURL, WebUtil.SharedHttpClientWithRedir, 30000); + hclient = WebUtil.GetNewGlobalHttpClient(-1); + XmlRpcResponse resp = req.Send(DestURL, hclient); if (resp != null) { Hashtable respParms; @@ -733,6 +736,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC _finished = true; httpThread = null; Watchdog.RemoveThread(); + hclient?.Dispose(); } } diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index bb96a7eca0..6e05ef90cb 100755 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -283,9 +283,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(-1); request = new(HttpMethod.Post, m_uri); request.Headers.ExpectContinue = false; @@ -307,6 +308,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { request?.Dispose(); responseMessage?.Dispose(); + client?.Dispose(); } } } diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index 66d97cc1a5..05355fb18d 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -42,6 +42,7 @@ using Nwc.XmlRpc; using log4net; using OpenSim.Services.Connectors.Simulation; +using System.Net.Http; namespace OpenSim.Services.Connectors.Hypergrid { @@ -94,7 +95,8 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(info.ServerURI, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + response = request.Send(info.ServerURI, hclient); } catch (Exception e) { @@ -230,7 +232,8 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(gatekeeper.ServerURI, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + response = request.Send(gatekeeper.ServerURI, hclient); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index f7b322e4e9..b7090fcae0 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -41,6 +41,7 @@ using OpenMetaverse.StructuredData; using log4net; using Nwc.XmlRpc; using Nini.Config; +using System.Net.Http; namespace OpenSim.Services.Connectors.Hypergrid { @@ -162,7 +163,8 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + response = request.Send(m_ServerURL, hclient); } catch (Exception e) { @@ -336,7 +338,8 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, WebUtil.SharedHttpClientWithRedir, 6000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + response = request.Send(m_ServerURL, hclient); } catch { @@ -408,7 +411,8 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + response = request.Send(m_ServerURL, hclient); } catch { @@ -558,7 +562,8 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + response = request.Send(m_ServerURL, hclient); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index 58a16ed36f..08bf11507c 100644 --- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -35,6 +35,7 @@ using Nwc.XmlRpc; using log4net; using OpenSim.Framework; +using System.Net.Http; namespace OpenSim.Services.Connectors.InstantMessage { @@ -60,8 +61,8 @@ namespace OpenSim.Services.Connectors.InstantMessage XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); try { - - XmlRpcResponse GridResp = GridReq.Send(url, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + XmlRpcResponse GridResp = GridReq.Send(url, hclient); Hashtable responseData = (Hashtable)GridResp.Value; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs index 5b37f4520e..02679ed599 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs @@ -62,7 +62,7 @@ namespace OpenSim.Services.Connectors /// /// In this case, -1 is default timeout (100 seconds), not infinite. /// - private int m_requestTimeoutSecs = -1; + private int m_requestTimeout = -1; private readonly string m_configName = "InventoryService"; private const double CACHE_EXPIRATION_SECONDS = 30.0; @@ -114,7 +114,7 @@ namespace OpenSim.Services.Connectors else m_InventoryURL = serviceURI + "/xinventory"; - m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs); + m_requestTimeout = 1000 * config.GetInt("RemoteRequestTimeout", -1); StatsManager.RegisterStat( new Stat( @@ -761,10 +761,10 @@ namespace OpenSim.Services.Connectors int rcvlen = 0; HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(m_requestTimeout); request = new(HttpMethod.Post, m_InventoryURL); @@ -782,9 +782,6 @@ namespace OpenSim.Services.Connectors 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; @@ -792,10 +789,7 @@ namespace OpenSim.Services.Connectors 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 = client.Send(request, HttpCompletionOption.ResponseHeadersRead); responseMessage.EnsureSuccessStatusCode(); if ((responseMessage.Content.Headers.ContentLength is long contentLength) && contentLength != 0) @@ -813,7 +807,7 @@ namespace OpenSim.Services.Connectors { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } ticks = Util.EnvironmentTickCountSubtract(ticks); diff --git a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs index 5e5f1fc726..977176f6e8 100644 --- a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs @@ -38,6 +38,7 @@ using OpenSim.Services.Interfaces; using OpenMetaverse; using Nwc.XmlRpc; using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using System.Net.Http; namespace OpenSim.Services.Connectors { @@ -92,7 +93,8 @@ namespace OpenSim.Services.Connectors paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); - XmlRpcResponse response = request.Send(info.ServerURI, WebUtil.SharedHttpClientWithRedir, 10000); + using HttpClient hclient = WebUtil.GetNewGlobalHttpClient(10000); + XmlRpcResponse response = request.Send(info.ServerURI, hclient); if (response.IsFault) { m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString); diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs index 8fc7fe90ab..30411111db 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs @@ -108,10 +108,10 @@ namespace OpenSim.Services.Connectors HttpResponseMessage responseMessage = null; HttpRequestMessage request = null; - CancellationTokenSource cancellationToken = null; + HttpClient client = null; try { - HttpClient client = WebUtil.SharedHttpClientWithRedir; + client = WebUtil.GetNewGlobalHttpClient(10000); request = new(HttpMethod.Post, uri); request.Headers.ExpectContinue = false; request.Headers.TransferEncodingChunked = false; @@ -127,10 +127,9 @@ namespace OpenSim.Services.Connectors request.Content.Headers.TryAddWithoutValidation("Content-Type", "application/json"); request.Content.Headers.TryAddWithoutValidation("Content-Length", buffer.Length.ToString()); - cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(10)); //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri); - responseMessage = client.Send(request, HttpCompletionOption.ResponseContentRead, cancellationToken.Token); + responseMessage = client.Send(request, HttpCompletionOption.ResponseContentRead); responseMessage.EnsureSuccessStatusCode(); //using StreamReader sr = new(responseMessage.Content.ReadAsStream()); @@ -149,7 +148,7 @@ namespace OpenSim.Services.Connectors { request?.Dispose(); responseMessage?.Dispose(); - cancellationToken?.Dispose(); + client?.Dispose(); } return false; } diff --git a/bin/XMLRPC.dll b/bin/XMLRPC.dll index bc7c01a8dcbf1caeffe4807d324599254f71e90e..1800342e51d8b117a50b9894842c5f6dfeec1d46 100755 GIT binary patch delta 8116 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 RDtzCd4s+qZSX)2+{{c4nvZeq4 delta 8360 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 U?p^SW!guv=w-)`4wf52fA8mK?3IG5A