Skip to content

Commit a883481

Browse files
authored
Extend SendFile to accept byte arrays (#163)
* feat: sending files as byte arrays * Added TcpKeepAlive and ConnectionLimit
1 parent 58f410e commit a883481

15 files changed

+133
-67
lines changed

.pubnub.yml

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
name: c-sharp
2-
version: "6.14.0"
2+
version: "6.15.0"
33
schema: 1
44
scm: github.com/pubnub/c-sharp
55
changelog:
6+
- date: 2023-03-16
7+
version: v6.15.0
8+
changes:
9+
- type: feature
10+
text: "Sending files as raw byte arrays."
11+
- type: improvement
12+
text: "Added TcpKeepAlive and ConnectionLimit to improve performance."
613
- date: 2023-02-27
714
version: v6.14.0
815
changes:
@@ -706,7 +713,7 @@ features:
706713
- QUERY-PARAM
707714
supported-platforms:
708715
-
709-
version: Pubnub 'C#' 6.14.0
716+
version: Pubnub 'C#' 6.15.0
710717
platforms:
711718
- Windows 10 and up
712719
- Windows Server 2008 and up
@@ -716,7 +723,7 @@ supported-platforms:
716723
- .Net Framework 4.5
717724
- .Net Framework 4.6.1+
718725
-
719-
version: PubnubPCL 'C#' 6.14.0
726+
version: PubnubPCL 'C#' 6.15.0
720727
platforms:
721728
- Xamarin.Android
722729
- Xamarin.iOS
@@ -736,7 +743,7 @@ supported-platforms:
736743
- .Net Core
737744
- .Net 6.0
738745
-
739-
version: PubnubUWP 'C#' 6.14.0
746+
version: PubnubUWP 'C#' 6.15.0
740747
platforms:
741748
- Windows Phone 10
742749
- Universal Windows Apps
@@ -760,7 +767,7 @@ sdks:
760767
distribution-type: source
761768
distribution-repository: GitHub
762769
package-name: Pubnub
763-
location: https://github.com/pubnub/c-sharp/releases/tag/v6.14.0.0
770+
location: https://github.com/pubnub/c-sharp/releases/tag/v6.15.0.0
764771
requires:
765772
-
766773
name: ".Net"
@@ -1043,7 +1050,7 @@ sdks:
10431050
distribution-type: source
10441051
distribution-repository: GitHub
10451052
package-name: PubNubPCL
1046-
location: https://github.com/pubnub/c-sharp/releases/tag/v6.14.0.0
1053+
location: https://github.com/pubnub/c-sharp/releases/tag/v6.15.0.0
10471054
requires:
10481055
-
10491056
name: ".Net Core"
@@ -1402,7 +1409,7 @@ sdks:
14021409
distribution-type: source
14031410
distribution-repository: GitHub
14041411
package-name: PubnubUWP
1405-
location: https://github.com/pubnub/c-sharp/releases/tag/v6.14.0.0
1412+
location: https://github.com/pubnub/c-sharp/releases/tag/v6.15.0.0
14061413
requires:
14071414
-
14081415
name: "Universal Windows Platform Development"

CHANGELOG

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
v6.15.0 - March 16 2023
2+
-----------------------------
3+
- Added: sending files as raw byte arrays.
4+
5+
- Modified: added TcpKeepAlive and ConnectionLimit to improve performance.
6+
17
v6.14.0 - February 27 2023
28
-----------------------------
39
- Modified: undeprecated GrantToken methods/properties.

src/Api/PubnubApi/ClientNetworkStatus.cs

+3
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,9 @@ private static async Task<bool> GetTimeWithTaskFactoryAsync(Uri requestUri)
303303
HttpWebRequest myRequest = null;
304304
myRequest = (HttpWebRequest)System.Net.WebRequest.Create(requestUri);
305305
myRequest.Method = "GET";
306+
#if NET35 || NET40 || NET45 || NET61 || NET48
307+
myRequest.KeepAlive = true;
308+
#endif
306309
using (HttpWebResponse response = await Task.Factory.FromAsync<HttpWebResponse>(myRequest.BeginGetResponse, asyncPubnubResult => (HttpWebResponse)myRequest.EndGetResponse(asyncPubnubResult), null).ConfigureAwait(false))
307310
{
308311
if (response != null)

src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs

+27-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public class SendFileOperation : PubnubCoreBase
2525
private object publishMessage;
2626
private string sendFileFullPath;
2727
private string sendFileName = "";
28+
private byte[] sendFileBytes = null;
2829
private string currentFileCipherKey;
2930
private string currentFileId;
3031
private bool storeInHistory = true;
@@ -90,7 +91,8 @@ public SendFileOperation File(string fileNameWithFullPath)
9091
{
9192
this.sendFileFullPath = fileNameWithFullPath;
9293
#if !NETSTANDARD10 && !NETSTANDARD11
93-
if (System.IO.File.Exists(fileNameWithFullPath))
94+
// manually set filename should take precedence
95+
if (System.IO.File.Exists(fileNameWithFullPath) && string.IsNullOrEmpty(sendFileName))
9496
{
9597
sendFileName = System.IO.Path.GetFileName(fileNameWithFullPath);
9698
}
@@ -100,6 +102,28 @@ public SendFileOperation File(string fileNameWithFullPath)
100102
#endif
101103
}
102104

105+
public SendFileOperation File(byte[] byteArray)
106+
{
107+
this.sendFileBytes = byteArray ?? throw new ArgumentException("File byte array not provided.");
108+
return this;
109+
}
110+
111+
public SendFileOperation FileName(string fileName)
112+
{
113+
if (string.IsNullOrEmpty(fileName))
114+
{
115+
throw new ArgumentException("File name is missing");
116+
}
117+
118+
if (fileName.Trim() != fileName)
119+
{
120+
throw new ArgumentException("File name should not contain leading or trailing whitespace");
121+
}
122+
123+
this.sendFileName = fileName;
124+
return this;
125+
}
126+
103127
public SendFileOperation CipherKey(string cipherKeyForFile)
104128
{
105129
this.currentFileCipherKey = cipherKeyForFile;
@@ -167,7 +191,7 @@ private void ProcessFileUpload(Dictionary<string, object> externalQueryParam, PN
167191

168192
requestState.UsePostMethod = true;
169193

170-
byte[] sendFileByteArray = GetByteArrayFromFilePath(sendFileFullPath);
194+
byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath);
171195

172196

173197
string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid());
@@ -269,7 +293,7 @@ private async Task<PNResult<PNFileUploadResult>> ProcessFileUpload(Dictionary<st
269293

270294
requestState.UsePostMethod = true;
271295

272-
byte[] sendFileByteArray = GetByteArrayFromFilePath(sendFileFullPath);
296+
byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath);
273297

274298
string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid());
275299
string contentType = "multipart/form-data; boundary=" + dataBoundary;

src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs

+2
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ private void MultiChannelSubscribeRequest<T>(PNOperationType type, string[] chan
672672
pubnubRequestState.Reconnect = reconnect;
673673
pubnubRequestState.Timetoken = Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture);
674674
pubnubRequestState.Region = region;
675+
pubnubRequestState.TimeQueued = DateTime.Now;
675676

676677
// Wait for message
677678
string json = "";
@@ -1417,6 +1418,7 @@ void OnPresenceHeartbeatIntervalTimeout<T>(System.Object presenceHeartbeatState)
14171418
requestState.PubnubCallback = null;
14181419
requestState.Reconnect = false;
14191420
requestState.Response = null;
1421+
requestState.TimeQueued = DateTime.Now;
14201422

14211423
UrlProcessRequest(request, requestState, false).ContinueWith(r =>
14221424
{

src/Api/PubnubApi/Interface/IPubnubHttp.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ public interface IPubnubHttp
1111
HttpWebRequest SetTimeout<T>(RequestState<T> pubnubRequestState, HttpWebRequest request);
1212

1313
HttpWebRequest SetNoCache<T>(HttpWebRequest request);
14-
15-
HttpWebRequest SetServicePointSetTcpKeepAlive(HttpWebRequest request);
14+
HttpWebRequest SetServicePointConnectionLimit<T>(RequestState<T> pubnubRequestState, HttpWebRequest request);
15+
HttpWebRequest SetServicePointSetTcpKeepAlive<T>(RequestState<T> pubnubRequestState, HttpWebRequest request);
16+
HttpWebRequest SetTcpKeepAlive(HttpWebRequest request);
1617

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

src/Api/PubnubApi/Model/RequestState.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace PubnubApi
55
{
66
public sealed class RequestState<T>
77
{
8+
public DateTime? TimeQueued { get; internal set; }
89
public HttpWebRequest Request { get; internal set; }
910
public HttpWebResponse Response { get; internal set; }
1011
public bool GotJsonResponse { get; internal set; }

src/Api/PubnubApi/Properties/AssemblyInfo.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
[assembly: AssemblyProduct("Pubnub C# SDK")]
1212
[assembly: AssemblyCopyright("Copyright © 2021")]
1313
[assembly: AssemblyTrademark("")]
14-
[assembly: AssemblyVersion("6.14.0.0")]
15-
[assembly: AssemblyFileVersion("6.14.0.0")]
14+
[assembly: AssemblyVersion("6.15.0.0")]
15+
[assembly: AssemblyFileVersion("6.15.0.0")]
1616
// Setting ComVisible to false makes the types in this assembly not visible
1717
// to COM components. If you need to access a type in this assembly from
1818
// COM, set the ComVisible attribute to true on that type.

src/Api/PubnubApi/PubnubApi.csproj

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@
1313

1414
<PropertyGroup>
1515
<PackageId>Pubnub</PackageId>
16-
<PackageVersion>6.14.0.0</PackageVersion>
16+
<PackageVersion>6.15.0.0</PackageVersion>
1717
<Title>PubNub C# .NET - Web Data Push API</Title>
1818
<Authors>Pandu Masabathula</Authors>
1919
<Owners>PubNub</Owners>
2020
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
2121
<PackageIconUrl>http://pubnub.s3.amazonaws.com/2011/powered-by-pubnub/pubnub-icon-600x600.png</PackageIconUrl>
2222
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
2323
<RepositoryUrl>https://github.com/pubnub/c-sharp/</RepositoryUrl>
24-
<PackageReleaseNotes>Undeprecated GrantToken methods/properties.</PackageReleaseNotes>
24+
<PackageReleaseNotes>Sending files as raw byte arrays.
25+
Added TcpKeepAlive and ConnectionLimit to improve performance.</PackageReleaseNotes>
2526
<PackageTags>Web Data Push Real-time Notifications ESB Message Broadcasting Distributed Computing</PackageTags>
2627
<!--<Summary>PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously</Summary>-->
2728
<Description>PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously</Description>

src/Api/PubnubApi/PubnubCoreBase.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1076,10 +1076,12 @@ internal protected async Task<Tuple<string, PNStatus>> UrlProcessRequest<T>(Uri
10761076
#else
10771077
// Create Request
10781078
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
1079-
1079+
request = pubnubHttp.SetServicePointConnectionLimit(pubnubRequestState, request);
10801080
request = pubnubHttp.SetNoCache<T>(request);
10811081
request = pubnubHttp.SetProxy<T>(request);
10821082
request = pubnubHttp.SetTimeout<T>(pubnubRequestState, request);
1083+
request = pubnubHttp.SetServicePointSetTcpKeepAlive(pubnubRequestState, request);
1084+
request = pubnubHttp.SetTcpKeepAlive(request);
10831085
if (string.IsNullOrEmpty(contentType))
10841086
{
10851087
contentType = "application/json";

src/Api/PubnubApi/PubnubHttp.cs

+62-28
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,37 @@ HttpWebRequest IPubnubHttp.SetNoCache<T>(HttpWebRequest request)
6969
return request;
7070
}
7171

72+
HttpWebRequest IPubnubHttp.SetServicePointConnectionLimit<T>(RequestState<T> pubnubRequestState, HttpWebRequest request)
73+
{
74+
#if NET35 || NET40 || NET45 || NET461 || NET48
75+
if (pubnubRequestState.ResponseType == PNOperationType.PNHeartbeatOperation)
76+
{
77+
int estimateConnectionLimit = pubnubConfig.SubscribeTimeout/pubnubConfig.PresenceInterval;
78+
if (estimateConnectionLimit > request.ServicePoint.ConnectionLimit)
79+
{
80+
request.ServicePoint.ConnectionLimit = estimateConnectionLimit;
81+
}
82+
}
83+
#endif
84+
return request;
85+
}
86+
87+
HttpWebRequest IPubnubHttp.SetServicePointSetTcpKeepAlive<T>(RequestState<T> pubnubRequestState, HttpWebRequest request)
88+
{
89+
#if NET35 || NET40 || NET45 || NET461 || NET48
90+
if (pubnubConfig.PresenceInterval > 0)
91+
{
92+
request.ServicePoint.SetTcpKeepAlive(true, pubnubConfig.PresenceInterval * 1000, 1000);
93+
}
94+
#endif
95+
return request;
96+
}
7297

73-
HttpWebRequest IPubnubHttp.SetServicePointSetTcpKeepAlive(HttpWebRequest request)
98+
HttpWebRequest IPubnubHttp.SetTcpKeepAlive(HttpWebRequest request)
7499
{
75-
//do nothing
100+
#if NET35 || NET40 || NET45 || NET461 || NET48
101+
request.KeepAlive = true;
102+
#endif
76103
return request;
77104
}
78105

@@ -559,40 +586,47 @@ async Task<string> SendRequestAndGetJsonResponseTaskFactory<T>(RequestState<T> p
559586
try
560587
{
561588
request.Method = FindHttpGetOrDeleteMethod(pubnubRequestState);
562-
var _ = new Timer(OnPubnubWebRequestTimeout<T>, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite);
563589
System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
564590
stopWatch.Start();
591+
var _ = new Timer(OnPubnubWebRequestTimeout<T>, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite);
565592
response = await Task.Factory.FromAsync<HttpWebResponse>(request.BeginGetResponse, asyncPubnubResult => (HttpWebResponse)request.EndGetResponse(asyncPubnubResult), pubnubRequestState).ConfigureAwait(false);
566593
stopWatch.Stop();
567594
if (pubnubConfig.EnableTelemetry && pubnubTelemetryMgr != null)
568595
{
569596
await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false);
570597
}
571-
pubnubRequestState.Response = response;
572-
System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got PubnubWebResponse for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), request.RequestUri.ToString()));
573-
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
574-
{
575-
//Need to return this response
576-
#if NET35 || NET40
577-
string jsonString = streamReader.ReadToEnd();
578-
#else
579-
string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false);
580-
#endif
581-
System.Diagnostics.Debug.WriteLine(jsonString);
582-
pubnubRequestState.GotJsonResponse = true;
583-
System.Diagnostics.Debug.WriteLine("");
584-
System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture)));
585-
586-
if (pubnubRequestState.Response != null)
598+
if (response != null)
599+
{
600+
pubnubRequestState.Response = response;
601+
System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got PubnubWebResponse for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), request.RequestUri.ToString()));
602+
using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
587603
{
588-
#if NET35 || NET40 || NET45 || NET461 || NET48
589-
pubnubRequestState.Response.Close();
590-
#endif
591-
pubnubRequestState.Response = null;
592-
pubnubRequestState.Request = null;
593-
}
604+
//Need to return this response
605+
#if NET35 || NET40
606+
string jsonString = streamReader.ReadToEnd();
607+
#else
608+
string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false);
609+
#endif
610+
System.Diagnostics.Debug.WriteLine(jsonString);
611+
pubnubRequestState.GotJsonResponse = true;
612+
System.Diagnostics.Debug.WriteLine("");
613+
System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture)));
594614

595-
return jsonString;
615+
if (pubnubRequestState.Response != null)
616+
{
617+
#if NET35 || NET40 || NET45 || NET461 || NET48
618+
pubnubRequestState.Response.Close();
619+
#endif
620+
pubnubRequestState.Response = null;
621+
pubnubRequestState.Request = null;
622+
}
623+
624+
return jsonString;
625+
}
626+
}
627+
else
628+
{
629+
return "";
596630
}
597631
}
598632
catch (WebException ex)
@@ -1311,14 +1345,14 @@ protected void OnPubnubWebRequestTimeout<T>(System.Object requestState)
13111345
if (currentState != null && currentState.Response == null && currentState.Request != null)
13121346
{
13131347
currentState.Timeout = true;
1348+
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);
1349+
13141350
try
13151351
{
13161352
currentState.Request.Abort();
13171353
}
13181354
catch { /* ignore */ }
13191355

1320-
LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, **WP7 OnPubnubWebRequestTimeout**", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity);
1321-
13221356
if (currentState.ResponseType != PNOperationType.PNSubscribeOperation
13231357
&& currentState.ResponseType != PNOperationType.Presence
13241358
&& currentState.ResponseType != PNOperationType.PNHeartbeatOperation

src/Api/PubnubApiPCL/PubnubApiPCL.csproj

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@
1414

1515
<PropertyGroup>
1616
<PackageId>PubnubPCL</PackageId>
17-
<PackageVersion>6.14.0.0</PackageVersion>
17+
<PackageVersion>6.15.0.0</PackageVersion>
1818
<Title>PubNub C# .NET - Web Data Push API</Title>
1919
<Authors>Pandu Masabathula</Authors>
2020
<Owners>PubNub</Owners>
2121
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
2222
<PackageIconUrl>http://pubnub.s3.amazonaws.com/2011/powered-by-pubnub/pubnub-icon-600x600.png</PackageIconUrl>
2323
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
2424
<RepositoryUrl>https://github.com/pubnub/c-sharp/</RepositoryUrl>
25-
<PackageReleaseNotes>Undeprecated GrantToken methods/properties.</PackageReleaseNotes>
25+
<PackageReleaseNotes>Sending files as raw byte arrays.
26+
Added TcpKeepAlive and ConnectionLimit to improve performance.</PackageReleaseNotes>
2627
<PackageTags>Web Data Push Real-time Notifications ESB Message Broadcasting Distributed Computing</PackageTags>
2728
<!--<Summary>PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously</Summary>-->
2829
<Description>PubNub is a Massively Scalable Web Push Service for Web and Mobile Games. This is a cloud-based service for broadcasting messages to thousands of web and mobile clients simultaneously</Description>

0 commit comments

Comments
 (0)