diff --git a/src/Api/PubnubApi/ClientNetworkStatus.cs b/src/Api/PubnubApi/ClientNetworkStatus.cs index 99801f902..15bcc07a7 100644 --- a/src/Api/PubnubApi/ClientNetworkStatus.cs +++ b/src/Api/PubnubApi/ClientNetworkStatus.cs @@ -303,6 +303,9 @@ private static async Task GetTimeWithTaskFactoryAsync(Uri requestUri) HttpWebRequest myRequest = null; myRequest = (HttpWebRequest)System.Net.WebRequest.Create(requestUri); myRequest.Method = "GET"; + #if NET35 || NET40 || NET45 || NET61 || NET48 + myRequest.KeepAlive = true; + #endif using (HttpWebResponse response = await Task.Factory.FromAsync(myRequest.BeginGetResponse, asyncPubnubResult => (HttpWebResponse)myRequest.EndGetResponse(asyncPubnubResult), null).ConfigureAwait(false)) { if (response != null) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs index cd418d758..8d71f3f94 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs @@ -672,6 +672,7 @@ private void MultiChannelSubscribeRequest(PNOperationType type, string[] chan pubnubRequestState.Reconnect = reconnect; pubnubRequestState.Timetoken = Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture); pubnubRequestState.Region = region; + pubnubRequestState.TimeQueued = DateTime.Now; // Wait for message string json = ""; @@ -1417,6 +1418,7 @@ void OnPresenceHeartbeatIntervalTimeout(System.Object presenceHeartbeatState) requestState.PubnubCallback = null; requestState.Reconnect = false; requestState.Response = null; + requestState.TimeQueued = DateTime.Now; UrlProcessRequest(request, requestState, false).ContinueWith(r => { diff --git a/src/Api/PubnubApi/Interface/IPubnubHttp.cs b/src/Api/PubnubApi/Interface/IPubnubHttp.cs index 580dd10a6..7358956be 100644 --- a/src/Api/PubnubApi/Interface/IPubnubHttp.cs +++ b/src/Api/PubnubApi/Interface/IPubnubHttp.cs @@ -11,8 +11,9 @@ public interface IPubnubHttp HttpWebRequest SetTimeout(RequestState pubnubRequestState, HttpWebRequest request); HttpWebRequest SetNoCache(HttpWebRequest request); - - HttpWebRequest SetServicePointSetTcpKeepAlive(HttpWebRequest request); + HttpWebRequest SetServicePointConnectionLimit(RequestState pubnubRequestState, HttpWebRequest request); + HttpWebRequest SetServicePointSetTcpKeepAlive(RequestState pubnubRequestState, HttpWebRequest request); + HttpWebRequest SetTcpKeepAlive(HttpWebRequest request); Task SendRequestAndGetJsonResponse(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request); diff --git a/src/Api/PubnubApi/Model/RequestState.cs b/src/Api/PubnubApi/Model/RequestState.cs index d3a0214a5..cfb8d3014 100644 --- a/src/Api/PubnubApi/Model/RequestState.cs +++ b/src/Api/PubnubApi/Model/RequestState.cs @@ -5,6 +5,7 @@ namespace PubnubApi { public sealed class RequestState { + public DateTime? TimeQueued { get; internal set; } public HttpWebRequest Request { get; internal set; } public HttpWebResponse Response { get; internal set; } public bool GotJsonResponse { get; internal set; } diff --git a/src/Api/PubnubApi/PubnubCoreBase.cs b/src/Api/PubnubApi/PubnubCoreBase.cs index e61a51598..0b818f936 100644 --- a/src/Api/PubnubApi/PubnubCoreBase.cs +++ b/src/Api/PubnubApi/PubnubCoreBase.cs @@ -1076,10 +1076,12 @@ internal protected async Task> UrlProcessRequest(Uri #else // Create Request HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri); - + request = pubnubHttp.SetServicePointConnectionLimit(pubnubRequestState, request); request = pubnubHttp.SetNoCache(request); request = pubnubHttp.SetProxy(request); request = pubnubHttp.SetTimeout(pubnubRequestState, request); + request = pubnubHttp.SetServicePointSetTcpKeepAlive(pubnubRequestState, request); + request = pubnubHttp.SetTcpKeepAlive(request); if (string.IsNullOrEmpty(contentType)) { contentType = "application/json"; diff --git a/src/Api/PubnubApi/PubnubHttp.cs b/src/Api/PubnubApi/PubnubHttp.cs index 1935a6cb2..4f0d7aeb5 100644 --- a/src/Api/PubnubApi/PubnubHttp.cs +++ b/src/Api/PubnubApi/PubnubHttp.cs @@ -69,10 +69,37 @@ HttpWebRequest IPubnubHttp.SetNoCache(HttpWebRequest request) return request; } + HttpWebRequest IPubnubHttp.SetServicePointConnectionLimit(RequestState pubnubRequestState, HttpWebRequest request) + { +#if NET35 || NET40 || NET45 || NET461 || NET48 + if (pubnubRequestState.ResponseType == PNOperationType.PNHeartbeatOperation) + { + int estimateConnectionLimit = pubnubConfig.SubscribeTimeout/pubnubConfig.PresenceInterval; + if (estimateConnectionLimit > request.ServicePoint.ConnectionLimit) + { + request.ServicePoint.ConnectionLimit = estimateConnectionLimit; + } + } +#endif + return request; + } + + HttpWebRequest IPubnubHttp.SetServicePointSetTcpKeepAlive(RequestState pubnubRequestState, HttpWebRequest request) + { +#if NET35 || NET40 || NET45 || NET461 || NET48 + if (pubnubConfig.PresenceInterval > 0) + { + request.ServicePoint.SetTcpKeepAlive(true, pubnubConfig.PresenceInterval * 1000, 1000); + } +#endif + return request; + } - HttpWebRequest IPubnubHttp.SetServicePointSetTcpKeepAlive(HttpWebRequest request) + HttpWebRequest IPubnubHttp.SetTcpKeepAlive(HttpWebRequest request) { - //do nothing +#if NET35 || NET40 || NET45 || NET461 || NET48 + request.KeepAlive = true; +#endif return request; } @@ -559,40 +586,47 @@ async Task SendRequestAndGetJsonResponseTaskFactory(RequestState p try { request.Method = FindHttpGetOrDeleteMethod(pubnubRequestState); - var _ = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); + var _ = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); response = await Task.Factory.FromAsync(request.BeginGetResponse, asyncPubnubResult => (HttpWebResponse)request.EndGetResponse(asyncPubnubResult), pubnubRequestState).ConfigureAwait(false); stopWatch.Stop(); if (pubnubConfig.EnableTelemetry && pubnubTelemetryMgr != null) { await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); } - pubnubRequestState.Response = response; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got PubnubWebResponse for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), request.RequestUri.ToString())); - using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) - { - //Need to return this response -#if NET35 || NET40 - string jsonString = streamReader.ReadToEnd(); -#else - string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); -#endif - System.Diagnostics.Debug.WriteLine(jsonString); - pubnubRequestState.GotJsonResponse = true; - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - - if (pubnubRequestState.Response != null) + if (response != null) + { + pubnubRequestState.Response = response; + System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got PubnubWebResponse for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), request.RequestUri.ToString())); + using (StreamReader streamReader = new StreamReader(response.GetResponseStream())) { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } + //Need to return this response + #if NET35 || NET40 + string jsonString = streamReader.ReadToEnd(); + #else + string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); + #endif + System.Diagnostics.Debug.WriteLine(jsonString); + pubnubRequestState.GotJsonResponse = true; + System.Diagnostics.Debug.WriteLine(""); + System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; + if (pubnubRequestState.Response != null) + { + #if NET35 || NET40 || NET45 || NET461 || NET48 + pubnubRequestState.Response.Close(); + #endif + pubnubRequestState.Response = null; + pubnubRequestState.Request = null; + } + + return jsonString; + } + } + else + { + return ""; } } catch (WebException ex) @@ -1311,14 +1345,14 @@ protected void OnPubnubWebRequestTimeout(System.Object requestState) if (currentState != null && currentState.Response == null && currentState.Request != null) { currentState.Timeout = true; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, **WP7 OnPubnubWebRequestTimeout** Initiated at {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentState.TimeQueued.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); + try { currentState.Request.Abort(); } catch { /* ignore */ } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, **WP7 OnPubnubWebRequestTimeout**", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - if (currentState.ResponseType != PNOperationType.PNSubscribeOperation && currentState.ResponseType != PNOperationType.Presence && currentState.ResponseType != PNOperationType.PNHeartbeatOperation diff --git a/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj b/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj index 88b19f749..b5169b946 100644 --- a/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj +++ b/src/UnitTests/AcceptanceTests/AcceptanceTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs index 27cdb6704..0e27c2d4a 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs @@ -53,9 +53,6 @@ public static void Init() pubnub = createPubNubInstance(config); - string expected = "{\"message\":\"Success\",\"payload\":{\"level\":\"channel-group\",\"subscribe_key\":\"demo-36\",\"ttl\":20,\"channel-groups\":{\"hello_my_group\":{\"r\":1,\"w\":0,\"m\":1}}},\"service\":\"Access Manager\",\"status\":200}"; - - pubnub.Grant().Channels(new[] { channelName }).AuthKeys(new[] { authKey }).Read(true).Write(true).Manage(true).Delete(true).Update(true).Get(true).TTL(20) .Execute(new PNAccessManagerGrantResultExt((r,s)=> { @@ -123,8 +120,6 @@ public static void ThenSendFileShouldReturnSuccess() pubnub.Subscribe().Channels(new string[] { channelName }).Execute(); mre.WaitOne(2000); - string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; - mre = new ManualResetEvent(false); string fileId = ""; @@ -255,8 +250,6 @@ public static async Task ThenWithAsyncSendFileShouldReturnSuccess() pubnub.Subscribe().Channels(new string[] { channelName }).Execute(); mre.WaitOne(2000); - string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; - mre = new ManualResetEvent(false); string fileId = ""; @@ -360,8 +353,6 @@ public static void ThenDownloadFileShouldReturnSuccess() } pubnub = createPubNubInstance(config); - string expected = ""; - mre = new ManualResetEvent(false); string fileId = "b0a5c0df-7523-432e-8ea9-01567c93da7d"; string fileName = "pandu_test.gif"; @@ -411,8 +402,6 @@ public static void ThenGetFileUrlShouldReturnSuccess() } pubnub = createPubNubInstance(config); - string expected = ""; - mre = new ManualResetEvent(false); string fileId = "bc03db55-6345-4a0f-aa58-beac970b2c5b"; string fileName = "whoami.txt"; @@ -462,8 +451,6 @@ public static void ThenListFilesShouldReturnSuccess() } pubnub = createPubNubInstance(config); - string expected = ""; - receivedMessage = false; mre = new ManualResetEvent(false); pubnub.ListFiles().Channel(channelName) @@ -511,8 +498,6 @@ public static void ThenDeleteFileShouldReturnSuccess() } pubnub = createPubNubInstance(config); - string expected = ""; - receivedMessage = false; PNResult listFilesResponse = pubnub.ListFiles().Channel(channelName).ExecuteAsync().Result; if (listFilesResponse.Result != null && listFilesResponse.Result.FilesList != null && listFilesResponse.Result.FilesList.Count > 0 && !listFilesResponse.Status.Error) @@ -591,8 +576,6 @@ public static async Task ThenWithAsyncDeleteFileShouldReturnSuccess() } pubnub = createPubNubInstance(config); - string expected = ""; - receivedMessage = false; #if NET40 PNResult listFilesResponse = Task.Factory.StartNew(async () => await pubnub.ListFiles().Channel(channelName).ExecuteAsync()).Result.Result;