Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added TcpKeepAlive and ConnectionLimit #164

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Api/PubnubApi/ClientNetworkStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ private static async Task<bool> 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<HttpWebResponse>(myRequest.BeginGetResponse, asyncPubnubResult => (HttpWebResponse)myRequest.EndGetResponse(asyncPubnubResult), null).ConfigureAwait(false))
{
if (response != null)
Expand Down
2 changes: 2 additions & 0 deletions src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ private void MultiChannelSubscribeRequest<T>(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 = "";
Expand Down Expand Up @@ -1417,6 +1418,7 @@ void OnPresenceHeartbeatIntervalTimeout<T>(System.Object presenceHeartbeatState)
requestState.PubnubCallback = null;
requestState.Reconnect = false;
requestState.Response = null;
requestState.TimeQueued = DateTime.Now;

UrlProcessRequest(request, requestState, false).ContinueWith(r =>
{
Expand Down
5 changes: 3 additions & 2 deletions src/Api/PubnubApi/Interface/IPubnubHttp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ public interface IPubnubHttp
HttpWebRequest SetTimeout<T>(RequestState<T> pubnubRequestState, HttpWebRequest request);

HttpWebRequest SetNoCache<T>(HttpWebRequest request);

HttpWebRequest SetServicePointSetTcpKeepAlive(HttpWebRequest request);
HttpWebRequest SetServicePointConnectionLimit<T>(RequestState<T> pubnubRequestState, HttpWebRequest request);
HttpWebRequest SetServicePointSetTcpKeepAlive<T>(RequestState<T> pubnubRequestState, HttpWebRequest request);
HttpWebRequest SetTcpKeepAlive(HttpWebRequest request);

Task<string> SendRequestAndGetJsonResponse<T>(Uri requestUri, RequestState<T> pubnubRequestState, HttpWebRequest request);

Expand Down
1 change: 1 addition & 0 deletions src/Api/PubnubApi/Model/RequestState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace PubnubApi
{
public sealed class RequestState<T>
{
public DateTime? TimeQueued { get; internal set; }
public HttpWebRequest Request { get; internal set; }
public HttpWebResponse Response { get; internal set; }
public bool GotJsonResponse { get; internal set; }
Expand Down
4 changes: 3 additions & 1 deletion src/Api/PubnubApi/PubnubCoreBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1076,10 +1076,12 @@ internal protected async Task<Tuple<string, PNStatus>> UrlProcessRequest<T>(Uri
#else
// Create Request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);

request = pubnubHttp.SetServicePointConnectionLimit(pubnubRequestState, request);
request = pubnubHttp.SetNoCache<T>(request);
request = pubnubHttp.SetProxy<T>(request);
request = pubnubHttp.SetTimeout<T>(pubnubRequestState, request);
request = pubnubHttp.SetServicePointSetTcpKeepAlive(pubnubRequestState, request);
request = pubnubHttp.SetTcpKeepAlive(request);
if (string.IsNullOrEmpty(contentType))
{
contentType = "application/json";
Expand Down
90 changes: 62 additions & 28 deletions src/Api/PubnubApi/PubnubHttp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,37 @@ HttpWebRequest IPubnubHttp.SetNoCache<T>(HttpWebRequest request)
return request;
}

HttpWebRequest IPubnubHttp.SetServicePointConnectionLimit<T>(RequestState<T> 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<T>(RequestState<T> 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;
}

Expand Down Expand Up @@ -559,40 +586,47 @@ async Task<string> SendRequestAndGetJsonResponseTaskFactory<T>(RequestState<T> p
try
{
request.Method = FindHttpGetOrDeleteMethod(pubnubRequestState);
var _ = new Timer(OnPubnubWebRequestTimeout<T>, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite);
System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();
var _ = new Timer(OnPubnubWebRequestTimeout<T>, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite);
response = await Task.Factory.FromAsync<HttpWebResponse>(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)
Expand Down Expand Up @@ -1311,14 +1345,14 @@ protected void OnPubnubWebRequestTimeout<T>(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
Expand Down
17 changes: 0 additions & 17 deletions src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)=>
{
Expand Down Expand Up @@ -123,8 +120,6 @@ public static void ThenSendFileShouldReturnSuccess()
pubnub.Subscribe<string>().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 = "";
Expand Down Expand Up @@ -255,8 +250,6 @@ public static async Task ThenWithAsyncSendFileShouldReturnSuccess()
pubnub.Subscribe<string>().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 = "";
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -462,8 +451,6 @@ public static void ThenListFilesShouldReturnSuccess()
}
pubnub = createPubNubInstance(config);

string expected = "";

receivedMessage = false;
mre = new ManualResetEvent(false);
pubnub.ListFiles().Channel(channelName)
Expand Down Expand Up @@ -511,8 +498,6 @@ public static void ThenDeleteFileShouldReturnSuccess()
}
pubnub = createPubNubInstance(config);

string expected = "";

receivedMessage = false;
PNResult<PNListFilesResult> listFilesResponse = pubnub.ListFiles().Channel(channelName).ExecuteAsync().Result;
if (listFilesResponse.Result != null && listFilesResponse.Result.FilesList != null && listFilesResponse.Result.FilesList.Count > 0 && !listFilesResponse.Status.Error)
Expand Down Expand Up @@ -591,8 +576,6 @@ public static async Task ThenWithAsyncDeleteFileShouldReturnSuccess()
}
pubnub = createPubNubInstance(config);

string expected = "";

receivedMessage = false;
#if NET40
PNResult<PNListFilesResult> listFilesResponse = Task.Factory.StartNew(async () => await pubnub.ListFiles().Channel(channelName).ExecuteAsync()).Result.Result;
Expand Down