diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2a6c6299a..f20941540 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ -* @mohitpubnub @xavrax @marcin-cebo -README.md @techwritermat @kazydek @mohitpubnub @xavrax +* @mohitpubnub @xavrax @marcin-cebo @jakub-grzesiowski +README.md @techwritermat @kazydek @mohitpubnub @xavrax @jakub-grzesiowski diff --git a/.github/workflows/commands-handler.yml b/.github/workflows/commands-handler.yml index 48f71d24a..51f8668fa 100644 --- a/.github/workflows/commands-handler.yml +++ b/.github/workflows/commands-handler.yml @@ -12,7 +12,7 @@ jobs: name: Process command if: github.event.issue.pull_request && endsWith(github.repository, '-private') != true runs-on: - group: Default + group: organization/Default steps: - name: Check referred user id: user-check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d28338e3..55a901c87 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: name: Check release required if: github.event.pull_request.merged && endsWith(github.repository, '-private') != true runs-on: - group: Default + group: organization/Default outputs: release: ${{ steps.check.outputs.ready }} steps: @@ -69,7 +69,7 @@ jobs: name: Publish package needs: publish-nuget runs-on: - group: Default + group: organization/Default steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 82d6f87ab..1ef6b91ef 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -11,7 +11,7 @@ jobs: tests: name: Integration and Unit tests runs-on: - group: windows-gh + group: organization/windows-gh defaults: run: shell: powershell @@ -31,7 +31,6 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 3.x 5.0.x 6.0.x 7.0.x @@ -39,19 +38,22 @@ jobs: env: WORKSPACE_PATH: ${{ github.workspace }} run: .\\.github\\workflows\\release\\build-packages.ps1 - # - name: Run unit tests - # env: - # PN_PUB_KEY: ${{ secrets.PN_PUB_KEY }} - # PN_SUB_KEY: ${{ secrets.PN_SUB_KEY }} - # PN_SEC_KEY: ${{ secrets.PN_SEC_KEY }} - # run: dotnet test .\\src\\UnitTests\\PubnubApiPCL.Tests\\PubnubApiPCL.Tests.csproj --verbosity normal --logger trx + - name: Run unit tests + env: + PN_PUB_KEY: ${{ secrets.SDK_PUB_KEY }} + PN_SUB_KEY: ${{ secrets.SDK_SUB_KEY }} + PN_SEC_KEY: ${{ secrets.SDK_SEC_KEY }} + PN_PAM_PUB_KEY: ${{ secrets.SDK_PAM_PUB_KEY }} + PN_PAM_SUB_KEY: ${{ secrets.SDK_PAM_SUB_KEY }} + PN_PAM_SEC_KEY: ${{ secrets.SDK_PAM_SEC_KEY }} + run: dotnet test .\\src\\UnitTests\\PubnubApiPCL.Tests\\PubnubApiPCL.Tests.csproj --verbosity normal --logger "console;verbosity=detailed" - name: Cancel workflow runs for commit on error if: failure() uses: ./.github/.release/actions/actions/utils/fast-jobs-failure acceptance-tests: name: Acceptance tests runs-on: - group: windows-gh + group: organization/windows-gh defaults: run: shell: powershell @@ -91,7 +93,7 @@ jobs: run: | Copy-Item -Path "${{ github.workspace }}/sdk-specifications/features/access/*" -Destination "${{ github.workspace }}/src/UnitTests/AcceptanceTests/Features" -Recurse cd ./UnitTests/AcceptanceTests - dotnet test --no-build --verbosity normal --logger trx --results-directory ./results + dotnet test --no-build --verbosity normal --logger "console;verbosity=detailed" --results-directory ./results - name: Upload acceptance tests reports if: always() uses: actions/upload-artifact@v4 @@ -107,7 +109,7 @@ jobs: name: Tests needs: [tests, acceptance-tests] runs-on: - group: Default + group: organization/Default steps: - name: Tests summary run: echo -e "\033[38;2;95;215;0m\033[1mAll tests successfully passed" diff --git a/.github/workflows/run-validations.yml b/.github/workflows/run-validations.yml index 929f49cc3..41d01dea8 100644 --- a/.github/workflows/run-validations.yml +++ b/.github/workflows/run-validations.yml @@ -11,7 +11,7 @@ jobs: pubnub-yml: name: "Validate .pubnub.yml" runs-on: - group: Default + group: organization/Default steps: - name: Checkout project uses: actions/checkout@v4 @@ -33,7 +33,7 @@ jobs: name: Validations needs: [pubnub-yml] runs-on: - group: Default + group: organization/Default steps: - name: Validations summary run: echo -e "\033[38;2;95;215;0m\033[1mAll validations passed" diff --git a/.pubnub.yml b/.pubnub.yml index fba2a8153..bc746049e 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -797,6 +797,7 @@ supported-platforms: - .Net Framework 4.0 - .Net Framework 4.5 - .Net Framework 4.6.1+ + - .Net Framework 6.0 - version: PubnubPCL 'C#' 6.20.1 platforms: @@ -892,9 +893,9 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - - .NET 4.x + - .NET 6.x minimum-os-version: - Windows 10 Home - Windows 10 Pro @@ -1031,9 +1032,9 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - - .NET 4.x + - .NET 6.x minimum-os-version: - Windows 10 Home - Windows 10 Pro @@ -1152,10 +1153,10 @@ sdks: supported-operating-systems: Android: runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x target-api-level: - 11 minimum-api-level: @@ -1172,10 +1173,10 @@ sdks: - ARMv7 (Cortex) CPU with NEON support iOS: runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x minimum-os-version: - iOS 9.0 maximum-os-version: @@ -1189,10 +1190,10 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x minimum-os-version: - Windows 10 Home - Windows 10 Pro @@ -1269,7 +1270,7 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 maximum-os-version: @@ -1280,10 +1281,10 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x minimum-os-version: - Mac OS X 10.8 maximum-os-version: @@ -1330,7 +1331,7 @@ sdks: supported-operating-systems: Android: runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 target-api-level: @@ -1349,10 +1350,10 @@ sdks: - ARMv7 (Cortex) CPU with NEON support iOS: runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x minimum-os-version: - iOS 9.0 maximum-os-version: @@ -1366,10 +1367,10 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x minimum-os-version: - Windows 10 Home - Windows 10 Pro @@ -1446,10 +1447,10 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x maximum-os-version: - Ubuntu 20.04 LTS minimum-os-version: @@ -1458,10 +1459,10 @@ sdks: target-architecture: - x86-64 runtime-version: - - .NET 4.x Equivalent + - .NET 6.x Equivalent api-compatibility: - .NET Core 2 - - .NET 4.x + - .NET 6.x minimum-os-version: - Mac OS X 10.8 maximum-os-version: @@ -1643,4 +1644,4 @@ sdks: - Windows Server 2012 R2 Foundation - Windows Server 2012 R2 Essentials - Windows Server 2012 R2 Standard - - Windows Server 2012 R2 Datacenter + - Windows Server 2012 R2 Datacenter \ No newline at end of file diff --git a/src/Api/PubnubApi/Builder/ResponseBuilder.cs b/src/Api/PubnubApi/Builder/ResponseBuilder.cs index 2c8a932ac..937039e9c 100644 --- a/src/Api/PubnubApi/Builder/ResponseBuilder.cs +++ b/src/Api/PubnubApi/Builder/ResponseBuilder.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace PubnubApi { @@ -13,9 +10,9 @@ internal class ResponseBuilder public ResponseBuilder(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubLog log) { - this.config = pubnubConfig; - this.jsonLib = jsonPluggableLibrary; - this.pubnubLog = log; + config = pubnubConfig; + jsonLib = jsonPluggableLibrary; + pubnubLog = log; } public T JsonToObject(List result, bool internalObject) @@ -28,7 +25,7 @@ public T JsonToObject(List result, bool internalObject) } else { - NewtonsoftJsonDotNet jsonNewtonLib = new NewtonsoftJsonDotNet(this.config, this.pubnubLog); + NewtonsoftJsonDotNet jsonNewtonLib = new NewtonsoftJsonDotNet(config, pubnubLog); ret = jsonNewtonLib.DeserializeToObject(result); } diff --git a/src/Api/PubnubApi/Builder/StatusBuilder.cs b/src/Api/PubnubApi/Builder/StatusBuilder.cs index 071b1f14d..196ff5b64 100644 --- a/src/Api/PubnubApi/Builder/StatusBuilder.cs +++ b/src/Api/PubnubApi/Builder/StatusBuilder.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Text; namespace PubnubApi { - public class StatusBuilder + public class StatusBuilder { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; @@ -98,11 +96,11 @@ public PNStatus CreateStatusResponse(PNOperationType type, PNStatusCategory c if (asyncRequestState != null) { - if (asyncRequestState.Request != null) + if (asyncRequestState.RequestCancellationTokenSource != null) { - status.ClientRequest = asyncRequestState.Request; + status.ClientRequest = asyncRequestState.RequestCancellationTokenSource; - HttpValueCollection restUriQueryCollection = HttpUtility.ParseQueryString(asyncRequestState.Request.RequestUri.Query); + HttpValueCollection restUriQueryCollection = HttpUtility.ParseQueryString(new Uri(asyncRequestState.Response.RequestUrl).Query); if (restUriQueryCollection.ContainsKey("auth")) { string auth = restUriQueryCollection["auth"]; diff --git a/src/Api/PubnubApi/Builder/UriUtil.cs b/src/Api/PubnubApi/Builder/UriUtil.cs index ecb9bf4f8..ed89e779d 100644 --- a/src/Api/PubnubApi/Builder/UriUtil.cs +++ b/src/Api/PubnubApi/Builder/UriUtil.cs @@ -1,10 +1,13 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Text; +using PubnubApi.EndPoint; namespace PubnubApi { - public class UriUtil + public static class UriUtil { public static string EncodeUriComponent(string s, PNOperationType type, bool ignoreComma, bool ignoreColon, bool ignorePercent2fEncode) { @@ -75,13 +78,7 @@ public static string EncodeUriComponent(string s, PNOperationType type, bool ign } else { - string escapeChar = System.Uri.EscapeDataString(ch.ToString()); -#if NET35 || NET40 - if (escapeChar == ch.ToString() && IsUnsafeToEncode(ch, ignoreComma, ignoreColon)) - { - escapeChar = string.Format(CultureInfo.InvariantCulture, "%{0}{1}", ToHex(ch / 16), ToHex(ch % 16)); - } -#endif + string escapeChar = Uri.EscapeDataString(ch.ToString()); o.Append(escapeChar); } } @@ -160,7 +157,7 @@ private static int ConvertToUtf32(string s, int index) } // Check if the character at index is a high surrogate. - int temp1 = (int)s[index] - HighSurrogateStart; + int temp1 = s[index] - HighSurrogateStart; if (temp1 >= 0 && temp1 <= 0x7ff) { // Found a surrogate char. @@ -169,7 +166,7 @@ private static int ConvertToUtf32(string s, int index) // Found a high surrogate. if (index < s.Length - 1) { - int temp2 = (int)s[index + 1] - LowSurrogateStart; + int temp2 = s[index + 1] - LowSurrogateStart; if (temp2 >= 0 && temp2 <= 0x3ff) { // Found a low surrogate. @@ -194,7 +191,33 @@ private static int ConvertToUtf32(string s, int index) } // Not a high-surrogate or low-surrogate. Genereate the UTF32 value for the BMP characters. - return (int)s[index]; + return s[index]; + } + + public static string BuildQueryString(Dictionary queryStringParamMap) + { + return string.Join("&", queryStringParamMap?.OrderBy(kvp => kvp.Key, StringComparer.Ordinal).Select(kvp => string.Format(CultureInfo.InvariantCulture, "{0}={1}", kvp.Key, kvp.Value)).ToArray() ?? Array.Empty()); + } + + public static string GetFileUrl(string fileId, string fileName, string channel, PNConfiguration pnConfiguration, Pubnub pubnub, TokenManager tokenmanager) + { + var requestParameters = new RequestParameter() + { + RequestType = Constants.GET, + PathSegment = [ + "v1", + "files", + pnConfiguration.SubscribeKey, + "channels", + channel, + "files", + fileId, + fileName + ], + Query = new Dictionary() + }; + var transportRequest = pubnub.transportMiddleware.PreapareTransportRequest(requestParameter:requestParameters, PNOperationType.PNFileUrlOperation); + return transportRequest.RequestUrl; } } } diff --git a/src/Api/PubnubApi/Builder/UrlParameterConverter.cs b/src/Api/PubnubApi/Builder/UrlParameterConverter.cs new file mode 100644 index 000000000..6b8dc1562 --- /dev/null +++ b/src/Api/PubnubApi/Builder/UrlParameterConverter.cs @@ -0,0 +1,35 @@ +using System; + +namespace PubnubApi.EndPoint +{ + + internal static class UrlParameterConverter + { + public static string MapEnumValueToEndpoint(string enumValue) + { + string endpointParameterName = String.Empty; + if (enumValue.ToLowerInvariant() == "custom") + { + endpointParameterName = "custom"; + } + else if (enumValue.ToLowerInvariant() == "uuid") + { + endpointParameterName = "uuid"; + } + else if (enumValue.ToLowerInvariant() == "channel") + { + endpointParameterName = "channel"; + } + else if (enumValue.ToLowerInvariant() == "channel_custom") + { + endpointParameterName = "channel.custom"; + } + else if (enumValue.ToLowerInvariant() == "uuid_custom") + { + endpointParameterName = "uuid.custom"; + } + + return endpointParameterName; + } + } +} \ No newline at end of file diff --git a/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs b/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs deleted file mode 100644 index 09843e259..000000000 --- a/src/Api/PubnubApi/Builder/UrlRequestBuilder.cs +++ /dev/null @@ -1,2306 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Globalization; -using System.Threading.Tasks; -using System.Threading; -using PubnubApi.Security.Crypto.Common; -#if !NETSTANDARD10 && !NETSTANDARD11 && !NETSTANDARD12 && !WP81 -using System.Reflection; -#endif -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif -using PubnubApi.Security.Crypto; -using PubnubApi.Security.Crypto.Cryptors; - -namespace PubnubApi -{ - public sealed class UrlRequestBuilder : IUrlRequestBuilder - { - private ConcurrentDictionary pubnubConfig { get; } = new ConcurrentDictionary(); - private readonly IJsonPluggableLibrary jsonLib ; - private readonly IPubnubUnitTest pubnubUnitTest; - private readonly IPubnubLog pubnubLog; - private readonly string pubnubInstanceId; - private readonly EndPoint.TelemetryManager telemetryMgr; - private readonly EndPoint.TokenManager tokenMgr; - - public UrlRequestBuilder(PNConfiguration config, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnitTest, IPubnubLog log, EndPoint.TelemetryManager pubnubTelemetryMgr, EndPoint.TokenManager pubnubTokenMgr, string pnInstanceId) - { - pubnubConfig.AddOrUpdate(pnInstanceId, config, (k, o) => config); - this.jsonLib = jsonPluggableLibrary; - this.pubnubUnitTest = pubnubUnitTest; - this.pubnubLog = log; - this.telemetryMgr = pubnubTelemetryMgr; - this.tokenMgr = pubnubTokenMgr; - this.pubnubInstanceId = string.IsNullOrEmpty(pnInstanceId) ? "" : pnInstanceId; - } - - Uri IUrlRequestBuilder.BuildTimeRequest(string requestMethod, string requestBody, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNTimeOperation; - - List url = new List(); - url.Add("time"); - url.Add("0"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildMultiChannelSubscribeRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, long timetoken, int region, string channelsJsonState, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNSubscribeOperation; - string channelForUrl = (channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - - List url = new List(); - url.Add("v2"); - url.Add("subscribe"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add(channelForUrl); - url.Add("0"); - - Dictionary internalInitialSubscribeUrlParams = new Dictionary(); - if (initialSubscribeUrlParams != null) - { - internalInitialSubscribeUrlParams = initialSubscribeUrlParams; - } - - Dictionary requestQueryStringParams = new Dictionary(internalInitialSubscribeUrlParams); - - if (!requestQueryStringParams.ContainsKey("filter-expr") && pubnubConfig.ContainsKey(pubnubInstanceId) && !string.IsNullOrEmpty(pubnubConfig[pubnubInstanceId].FilterExpression)) - { - requestQueryStringParams.Add("filter-expr", UriUtil.EncodeUriComponent(pubnubConfig[pubnubInstanceId].FilterExpression, currentType, false, false, false)); - } - - if (!requestQueryStringParams.ContainsKey("ee") && pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].EnableEventEngine) - { - requestQueryStringParams.Add("ee", ""); - } - - if (!requestQueryStringParams.ContainsKey("tt")) - { - requestQueryStringParams.Add("tt", timetoken.ToString(CultureInfo.InvariantCulture)); - } - - if (!requestQueryStringParams.ContainsKey("tr") && region > 0) - { - requestQueryStringParams.Add("tr", region.ToString(CultureInfo.InvariantCulture)); - } - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].PresenceTimeout != 0) - { - requestQueryStringParams.Add("heartbeat", pubnubConfig[pubnubInstanceId].PresenceTimeout.ToString(CultureInfo.InvariantCulture)); - } - - if (channelGroups != null && channelGroups.Length > 0 && channelGroups[0] != "") - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), currentType, false, false, false)); - } - - if (channelsJsonState != "{}" && channelsJsonState != "") - { - requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(channelsJsonState, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildMultiChannelLeaveRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, string jsonUserState, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.Leave; - string multiChannel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - - List url = new List(); - url.Add("v2"); - url.Add("presence"); - url.Add("sub_key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(multiChannel); - url.Add("leave"); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].PresenceTimeout != 0) - { - requestQueryStringParams.Add("heartbeat", pubnubConfig[pubnubInstanceId].PresenceTimeout.ToString(CultureInfo.InvariantCulture)); - } - - string channelsJsonState = jsonUserState; - if (channelsJsonState != "{}" && channelsJsonState != "") - { - requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(channelsJsonState, currentType, false, false, false)); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()),currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildPublishRequest(string requestMethod, string requestBody, string channel, object originalMessage, bool storeInHistory, int ttl, Dictionary userMetaData, Dictionary additionalUrlParams, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNPublishOperation; - - List url = new List(); - url.Add("publish"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].PublishKey : ""); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("0"); - url.Add(channel); - url.Add("0"); - if (requestMethod.ToUpperInvariant() == "GET") - { - string message = JsonEncodePublishMsg(originalMessage, currentType); - url.Add(message); - } - - Dictionary additionalUrlParamsDic = new Dictionary(); - if (additionalUrlParams != null) - { - additionalUrlParamsDic = additionalUrlParams; - } - - Dictionary requestQueryStringParams = new Dictionary(additionalUrlParamsDic); - - if (userMetaData != null) - { - string jsonMetaData = jsonLib.SerializeToJsonString(userMetaData); - requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, currentType, false, false, false)); - } - - if (storeInHistory && ttl >= 0) - { - requestQueryStringParams.Add("tt1", ttl.ToString(CultureInfo.InvariantCulture)); - } - - if (!storeInHistory) - { - requestQueryStringParams.Add("store", "0"); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - bool allowPAMv3Sign = requestMethod.ToUpperInvariant() != "POST"; - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, allowPAMv3Sign); - } - - Uri IUrlRequestBuilder.BuildSignalRequest(string requestMethod, string requestBody, string channel, object originalMessage, Dictionary userMetaData, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNSignalOperation; - - List url = new List(); - url.Add("signal"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].PublishKey : ""); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("0"); - url.Add(channel); - url.Add("0"); - if (requestMethod.ToUpperInvariant() == "GET") - { - string message = JsonEncodePublishMsg(originalMessage, currentType); - url.Add(message); - } - - Dictionary requestQueryStringParams = new Dictionary(); - if (userMetaData != null) - { - string jsonMetaData = jsonLib.SerializeToJsonString(userMetaData); - requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildHereNowRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, bool showUUIDList, bool includeUserState, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNHereNowOperation; - if ((channels == null || channels.Length == 0) && (channelGroups == null || channelGroups.Length == 0)) { - throw new ArgumentException("Please provide Channels or ChannelGroups."); - } - string channel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - - List url = new List(); - url.Add("v2"); - url.Add("presence"); - url.Add("sub_key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - - int disableUUID = showUUIDList ? 0 : 1; - int userState = includeUserState ? 1 : 0; - - Dictionary requestQueryStringParams = new Dictionary(); - - string commaDelimitedchannelGroup = (channelGroups != null) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; - if (!string.IsNullOrEmpty(commaDelimitedchannelGroup) && commaDelimitedchannelGroup.Trim().Length > 0) - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(commaDelimitedchannelGroup, currentType, false, false, false)); - } - - requestQueryStringParams.Add("disable_uuids", disableUUID.ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("state", userState.ToString(CultureInfo.InvariantCulture)); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildHistoryRequest(string requestMethod, string requestBody, string channel, long start, long end, int count, bool reverse, bool includeToken, bool includeMeta, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNHistoryOperation; - - List url = new List(); - url.Add("v2"); - url.Add("history"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - - Dictionary requestQueryStringParams = new Dictionary(); - - requestQueryStringParams.Add("count", (count <= -1) ? "100" : count.ToString(CultureInfo.InvariantCulture)); - - if (reverse) - { - requestQueryStringParams.Add("reverse", "true"); - } - if (start != -1) - { - requestQueryStringParams.Add("start", start.ToString(CultureInfo.InvariantCulture)); - } - if (end != -1) - { - requestQueryStringParams.Add("end", end.ToString(CultureInfo.InvariantCulture)); - } - - if (includeToken) - { - requestQueryStringParams.Add("include_token", "true"); - } - - if (includeMeta) - { - requestQueryStringParams.Add("include_meta", "true"); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach(KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildFetchRequest(string requestMethod, string requestBody, string[] channels, long start, long end, int count, bool reverse, bool includeMeta, bool includeMessageActions, bool includeUuid, bool includeMessageType, Dictionary externalQueryParam) - { - string channel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ""; - - PNOperationType currentType = PNOperationType.PNFetchHistoryOperation; - - List url = new List(); - url.Add("v3"); - url.Add(includeMessageActions ? "history-with-actions" : "history"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - - Dictionary requestQueryStringParams = new Dictionary(); - - requestQueryStringParams.Add("max", (count <= -1) ? (includeMessageActions || (channels != null && channels.Length > 1) ? "25" : "100") : count.ToString(CultureInfo.InvariantCulture)); - - if (reverse) - { - requestQueryStringParams.Add("reverse", "true"); - } - if (start != -1) - { - requestQueryStringParams.Add("start", start.ToString(CultureInfo.InvariantCulture)); - } - if (end != -1) - { - requestQueryStringParams.Add("end", end.ToString(CultureInfo.InvariantCulture)); - } - - if (includeMeta) - { - requestQueryStringParams.Add("include_meta", "true"); - } - - if (includeUuid) - { - requestQueryStringParams.Add("include_uuid", "true"); - } - - if (includeMessageType) - { - requestQueryStringParams.Add("include_message_type", "true"); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildMessageCountsRequest(string requestMethod, string requestBody, string[] channels, long[] timetokens, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNMessageCountsOperation; - string channel = (channels != null && channels.Length > 0) ? string.Join(",", channels) : ""; - - List url = new List(); - url.Add("v3"); - url.Add("history"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("message-counts"); - if (!string.IsNullOrEmpty(channel)) - { - url.Add(UriUtil.EncodeUriComponent(channel, currentType, true, false, false)); - } - - Dictionary requestQueryStringParams = new Dictionary(); - - if (timetokens != null && timetokens.Length > 0) - { - string tt = string.Join(",", timetokens.Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray()); - if (timetokens.Length == 1) - { - requestQueryStringParams.Add("timetoken", tt); - } - else - { - requestQueryStringParams.Add("channelsTimetoken", UriUtil.EncodeUriComponent(tt, currentType, false, false, false)); - } - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildDeleteMessageRequest(string requestMethod, string requestBody, string channel, long start, long end, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNDeleteMessageOperation; - - List url = new List(); - url.Add("v3"); - url.Add("history"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (start != -1) - { - requestQueryStringParams.Add("start", start.ToString(CultureInfo.InvariantCulture)); - } - if (end != -1) - { - requestQueryStringParams.Add("end", end.ToString(CultureInfo.InvariantCulture)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildWhereNowRequest(string requestMethod, string requestBody, string uuid, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNWhereNowOperation; - - List url = new List(); - url.Add("v2"); - url.Add("presence"); - url.Add("sub_key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuid"); - url.Add(uuid); - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGrantV2AccessRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string channelGroupsCommaDelimited, string targetUuidsCommaDelimited, string authKeysCommaDelimited, bool read, bool write, bool delete, bool manage, bool get, bool update, bool join, long ttl, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNAccessManagerGrant; - - List url = new List(); - url.Add("v2"); - url.Add("auth"); - url.Add("grant"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (!string.IsNullOrEmpty(authKeysCommaDelimited)) - { - requestQueryStringParams.Add("auth", UriUtil.EncodeUriComponent(authKeysCommaDelimited, currentType, false, false, false)); - } - - if (!string.IsNullOrEmpty(channelsCommaDelimited)) - { - requestQueryStringParams.Add("channel", UriUtil.EncodeUriComponent(channelsCommaDelimited, currentType, false, false, false)); - } - - if (!string.IsNullOrEmpty(channelGroupsCommaDelimited)) - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroupsCommaDelimited, currentType, false, false, false)); - } - - if (!string.IsNullOrEmpty(targetUuidsCommaDelimited)) - { - requestQueryStringParams.Add("target-uuid", UriUtil.EncodeUriComponent(targetUuidsCommaDelimited, currentType, false, false, false)); - } - - if (ttl > -1) - { - requestQueryStringParams.Add("ttl", ttl.ToString(CultureInfo.InvariantCulture)); - } - - requestQueryStringParams.Add("r", Convert.ToInt32(read).ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("w", Convert.ToInt32(write).ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("d", Convert.ToInt32(delete).ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("m", Convert.ToInt32(manage).ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("g", Convert.ToInt32(get).ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("u", Convert.ToInt32(update).ToString(CultureInfo.InvariantCulture)); - requestQueryStringParams.Add("j", Convert.ToInt32(join).ToString(CultureInfo.InvariantCulture)); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGrantV3AccessRequest(string requestMethod, string requestBody, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNAccessManagerGrantToken; - - List url = new List(); - url.Add("v3"); - url.Add("pam"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("grant"); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildRevokeV3AccessRequest(string requestMethod, string requestBody, string token, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNAccessManagerRevokeToken; - - List url = new List(); - url.Add("v3"); - url.Add("pam"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("grant"); - url.Add(token); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildAuditAccessRequest(string requestMethod, string requestBody, string channel, string channelGroup, string authKeysCommaDelimited, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNAccessManagerAudit; - - List url = new List(); - url.Add("v2"); - url.Add("auth"); - url.Add("audit"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (!string.IsNullOrEmpty(authKeysCommaDelimited)) - { - requestQueryStringParams.Add("auth", UriUtil.EncodeUriComponent(authKeysCommaDelimited, currentType, false, false, false)); - } - - if (!string.IsNullOrEmpty(channel)) - { - requestQueryStringParams.Add("channel", UriUtil.EncodeUriComponent(channel, currentType, false, false, false)); - } - - if (!string.IsNullOrEmpty(channelGroup)) - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroup, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetUserStateRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string channelGroupsCommaDelimited, string uuid, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetStateOperation; - - List url = new List(); - url.Add("v2"); - url.Add("presence"); - url.Add("sub_key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - - if (string.IsNullOrEmpty(channelsCommaDelimited) || channelsCommaDelimited.Trim().Length <= 0) - { - url.Add(","); - } - else - { - url.Add(channelsCommaDelimited); - } - - url.Add("uuid"); - url.Add(uuid); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (!string.IsNullOrEmpty(channelGroupsCommaDelimited) && channelGroupsCommaDelimited.Trim().Length > 0) - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroupsCommaDelimited, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildSetUserStateRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string channelGroupsCommaDelimited, string uuid, string jsonUserState, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNSetStateOperation; - string internalChannelsCommaDelimited; - - if (string.IsNullOrEmpty(channelsCommaDelimited) || channelsCommaDelimited.Trim().Length <= 0) - { - internalChannelsCommaDelimited = ","; - } - else - { - internalChannelsCommaDelimited = channelsCommaDelimited; - } - - List url = new List(); - url.Add("v2"); - url.Add("presence"); - url.Add("sub_key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(internalChannelsCommaDelimited); - url.Add("uuid"); - url.Add(uuid); - url.Add("data"); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (!string.IsNullOrEmpty(channelGroupsCommaDelimited) && channelGroupsCommaDelimited.Trim().Length > 0) - { - requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(jsonUserState, currentType, false, false, false)); - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroupsCommaDelimited, currentType, false, false, false)); - } - else - { - requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(jsonUserState, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildAddChannelsToChannelGroupRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string nameSpace, string groupName, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNAddChannelsToGroupOperation; - - List url = new List(); - url.Add("v1"); - url.Add("channel-registration"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - if (!string.IsNullOrEmpty(nameSpace) && nameSpace.Trim().Length > 0) - { - url.Add("namespace"); - url.Add(nameSpace); - } - url.Add("channel-group"); - url.Add(groupName); - - Dictionary requestQueryStringParams = new Dictionary(); - - requestQueryStringParams.Add("add", UriUtil.EncodeUriComponent(channelsCommaDelimited, currentType,false, false, false)); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildRemoveChannelsFromChannelGroupRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string nameSpace, string groupName, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNRemoveGroupOperation; - - bool groupNameAvailable = false; - bool nameSpaceAvailable = false; - bool channelAvaiable = false; - - List url = new List(); - url.Add("v1"); - url.Add("channel-registration"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - if (!string.IsNullOrEmpty(nameSpace) && nameSpace.Trim().Length > 0) - { - nameSpaceAvailable = true; - url.Add("namespace"); - url.Add(nameSpace); - } - - if (!string.IsNullOrEmpty(groupName) && groupName.Trim().Length > 0) - { - groupNameAvailable = true; - url.Add("channel-group"); - url.Add(groupName); - } - - if (!String.IsNullOrEmpty(channelsCommaDelimited)) - { - channelAvaiable = true; - } - - if (nameSpaceAvailable && groupNameAvailable && !channelAvaiable) - { - url.Add("remove"); - } - else if (nameSpaceAvailable && !groupNameAvailable && !channelAvaiable) - { - url.Add("remove"); - } - else if (!nameSpaceAvailable && groupNameAvailable && !channelAvaiable) - { - url.Add("remove"); - } - - Dictionary requestQueryStringParams = new Dictionary(); - - if (channelAvaiable) - { - requestQueryStringParams.Add("remove", UriUtil.EncodeUriComponent(channelsCommaDelimited, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetChannelsForChannelGroupRequest(string requestMethod, string requestBody, string nameSpace, string groupName, bool limitToChannelGroupScopeOnly, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.ChannelGroupGet; - - bool groupNameAvailable = false; - bool nameSpaceAvailable = false; - - List url = new List(); - url.Add("v1"); - url.Add("channel-registration"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - if (!string.IsNullOrEmpty(nameSpace) && nameSpace.Trim().Length > 0) - { - nameSpaceAvailable = true; - url.Add("namespace"); - url.Add(nameSpace); - } - if (limitToChannelGroupScopeOnly) - { - url.Add("channel-group"); - } - else - { - if (!string.IsNullOrEmpty(groupName) && groupName.Trim().Length > 0) - { - groupNameAvailable = true; - url.Add("channel-group"); - url.Add(groupName); - } - - if (!nameSpaceAvailable && !groupNameAvailable) - { - url.Add("namespace"); - } - else if (nameSpaceAvailable && !groupNameAvailable) - { - url.Add("channel-group"); - } - } - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetAllChannelGroupRequest(string requestMethod, string requestBody, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.ChannelGroupAllGet; - - List url = new List(); - url.Add("v1"); - url.Add("channel-registration"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel-group"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildRegisterDevicePushRequest(string requestMethod, string requestBody, string channel, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PushRegister; - - List url = new List(); - if (pushType == PNPushType.APNS2) - { - url.Add("v2"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices-apns2"); - url.Add(pushToken); - } - else - { - url.Add("v1"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices"); - url.Add(pushToken); - } - - Dictionary requestQueryStringParams = new Dictionary(); - if (pushType == PNPushType.APNS2) - { - requestQueryStringParams.Add("environment", environment.ToString().ToLowerInvariant()); - requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, currentType, false, false, false)); - } - else - { - requestQueryStringParams.Add("type", pushType.ToString().ToLowerInvariant()); - } - requestQueryStringParams.Add("add", UriUtil.EncodeUriComponent(channel, currentType, false, false, false)); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildUnregisterDevicePushRequest(string requestMethod, string requestBody, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PushUnregister; - - List url = new List(); - if (pushType == PNPushType.APNS2) - { - url.Add("v2"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices-apns2"); - url.Add(pushToken); - url.Add("remove"); - } - else - { - url.Add("v1"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices"); - url.Add(pushToken); - url.Add("remove"); - } - - Dictionary requestQueryStringParams = new Dictionary(); - if (pushType == PNPushType.APNS2) - { - requestQueryStringParams.Add("environment", environment.ToString().ToLowerInvariant()); - requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, currentType, false, false, false)); - } - else - { - requestQueryStringParams.Add("type", pushType.ToString().ToLowerInvariant()); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildRemoveChannelPushRequest(string requestMethod, string requestBody, string channel, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PushRemove; - - List url = new List(); - if (pushType == PNPushType.APNS2) - { - url.Add("v2"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices-apns2"); - url.Add(pushToken); - } - else - { - url.Add("v1"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices"); - url.Add(pushToken); - } - - Dictionary requestQueryStringParams = new Dictionary(); - if (pushType == PNPushType.APNS2) - { - requestQueryStringParams.Add("environment", environment.ToString().ToLowerInvariant()); - requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, currentType, false, false, false)); - } - else - { - requestQueryStringParams.Add("type", pushType.ToString().ToLowerInvariant()); - } - requestQueryStringParams.Add("remove", UriUtil.EncodeUriComponent(channel, currentType, false, false, false)); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetChannelsPushRequest(string requestMethod, string requestBody, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PushGet; - - List url = new List(); - if (pushType == PNPushType.APNS2) - { - url.Add("v2"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices-apns2"); - url.Add(pushToken); - } - else - { - url.Add("v1"); - url.Add("push"); - url.Add("sub-key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("devices"); - url.Add(pushToken); - } - - Dictionary requestQueryStringParams = new Dictionary(); - - if (pushType == PNPushType.APNS2) - { - requestQueryStringParams.Add("environment", environment.ToString().ToLowerInvariant()); - requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, currentType, false, false, false)); - } - else - { - requestQueryStringParams.Add("type", pushType.ToString().ToLowerInvariant()); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildPresenceHeartbeatRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, string jsonUserState) - { - PNOperationType currentType = PNOperationType.PNHeartbeatOperation; - - string multiChannel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - - List url = new List(); - url.Add("v2"); - url.Add("presence"); - url.Add("sub_key"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(multiChannel); - url.Add("heartbeat"); - - Dictionary requestQueryStringParams = new Dictionary(); - - string channelsJsonState = jsonUserState; - if (channelsJsonState != "{}" && channelsJsonState != "") - { - requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(channelsJsonState, currentType, false, false, false)); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), currentType, false, false, false)); - } - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].PresenceTimeout != 0) - { - requestQueryStringParams.Add("heartbeat", pubnubConfig[pubnubInstanceId].PresenceTimeout.ToString(CultureInfo.InvariantCulture)); - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildSetUuidMetadataRequest(string requestMethod, string requestBody, string uuid, bool includeCustom, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNSetUuidMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuids"); - url.Add(string.IsNullOrEmpty(uuid) ? "" : uuid); - - Dictionary requestQueryStringParams = new Dictionary(); - if (includeCustom) - { - requestQueryStringParams.Add("include", "custom"); - } - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildDeleteUuidMetadataRequest(string requestMethod, string requestBody, string uuid, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNDeleteUuidMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuids"); - url.Add(string.IsNullOrEmpty(uuid) ? "" : uuid); - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetAllUuidMetadataRequest(string requestMethod, string requestBody, string start, string end, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetAllUuidMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuids"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (!string.IsNullOrEmpty(start)) - { - requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(start, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(end)) - { - requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(end, currentType, false, false, false)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - if (includeCount) - { - requestQueryStringParams.Add("count", "true"); - } - if (includeCustom) - { - requestQueryStringParams.Add("include", "custom"); - } - if (!string.IsNullOrEmpty(filter)) - { - requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(filter, currentType, false, false, false)); - } - if (sort != null && sort.Count > 0) - { - requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",",sort.ToArray()), currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetSingleUuidMetadataRequest(string requestMethod, string requestBody, string uuid, bool includeCustom, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetUuidMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuids"); - url.Add(string.IsNullOrEmpty(uuid) ? "": uuid); - - Dictionary requestQueryStringParams = new Dictionary(); - if (includeCustom) - { - requestQueryStringParams.Add("include", "custom"); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildSetChannelMetadataRequest(string requestMethod, string requestBody, string channel, bool includeCustom, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNSetChannelMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(string.IsNullOrEmpty(channel) ? "" : channel); - - Dictionary requestQueryStringParams = new Dictionary(); - if (includeCustom) - { - requestQueryStringParams.Add("include", "custom"); - } - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildDeleteChannelMetadataRequest(string requestMethod, string requestBody, string channel, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNDeleteChannelMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(string.IsNullOrEmpty(channel) ? "" : channel); - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetAllChannelMetadataRequest(string requestMethod, string requestBody, string start, string end, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetAllChannelMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (!string.IsNullOrEmpty(start)) - { - requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(start, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(end)) - { - requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(end, currentType, false, false, false)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - if (includeCount) - { - requestQueryStringParams.Add("count", "true"); - } - if (includeCustom) - { - requestQueryStringParams.Add("include", "custom"); - } - if (!string.IsNullOrEmpty(filter)) - { - requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(filter, currentType, false, false, false)); - } - if (sort != null && sort.Count > 0) - { - requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sort.ToArray()), currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetSingleChannelMetadataRequest(string requestMethod, string requestBody, string channel, bool includeCustom, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetChannelMetadataOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(string.IsNullOrEmpty(channel) ? "" : channel); - - Dictionary requestQueryStringParams = new Dictionary(); - if (includeCustom) - { - requestQueryStringParams.Add("include", "custom"); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildMembershipSetRemoveManageUserRequest(PNOperationType type, string requestMethod, string requestBody, string uuid, string start, string end, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNOperationType currentType = type; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuids"); - url.Add(string.IsNullOrEmpty(uuid) ? "" : uuid); - url.Add("channels"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (!string.IsNullOrEmpty(start)) - { - requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(start, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(end)) - { - requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(end, currentType, false, false, false)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - if (includeCount) - { - requestQueryStringParams.Add("count", "true"); - } - if (!string.IsNullOrEmpty(includeOptions)) - { - requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(includeOptions, currentType, false, false, false)); - } - if (sort != null && sort.Count > 0) - { - requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sort.ToArray()), currentType, false, false, false)); - } - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildMemberAddUpdateRemoveChannelRequest(string requestMethod, string requestBody, string channel, string start, string end, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNManageChannelMembersOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(string.IsNullOrEmpty(channel) ? "" : channel); - url.Add("uuids"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (!string.IsNullOrEmpty(start)) - { - requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(start, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(end)) - { - requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(end, currentType, false, false, false)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - if (includeCount) - { - requestQueryStringParams.Add("count", "true"); - } - if (!string.IsNullOrEmpty(includeOptions)) - { - requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(includeOptions, currentType, false, false, false)); - } - if (sort != null && sort.Count > 0) - { - requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sort.ToArray()), currentType, false, false, false)); - } - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetAllMembershipsRequest(string requestMethod, string requestBody, string uuid, string start, string end, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetMembershipsOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("uuids"); - url.Add(string.IsNullOrEmpty(uuid) ? "" : uuid); - url.Add("channels"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (!string.IsNullOrEmpty(start)) - { - requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(start, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(end)) - { - requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(end, currentType, false, false, false)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - if (includeCount) - { - requestQueryStringParams.Add("count", "true"); - } - if (!string.IsNullOrEmpty(includeOptions)) - { - requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(includeOptions, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(filter)) - { - requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(filter, currentType, false, false, false)); - } - if (sort != null && sort.Count > 0) - { - requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sort.ToArray()), currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetAllMembersRequest(string requestMethod, string requestBody, string channel, string start, string end, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetChannelMembersOperation; - - List url = new List(); - url.Add("v2"); - url.Add("objects"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(string.IsNullOrEmpty(channel) ? "" : channel); - url.Add("uuids"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (!string.IsNullOrEmpty(start)) - { - requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(start, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(end)) - { - requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(end, currentType, false, false, false)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - if (includeCount) - { - requestQueryStringParams.Add("count", "true"); - } - if (!string.IsNullOrEmpty(includeOptions)) - { - requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(includeOptions, currentType, false, false, false)); - } - if (!string.IsNullOrEmpty(filter)) - { - requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(filter, currentType, false, false, false)); - } - if (sort != null && sort.Count > 0) - { - requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sort.ToArray()), currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildAddMessageActionRequest(string requestMethod, string requestBody, string channel, long messageTimetoken, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNAddMessageActionOperation; - - List url = new List(); - url.Add("v1"); - url.Add("message-actions"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - url.Add("message"); - url.Add(messageTimetoken.ToString(CultureInfo.InvariantCulture)); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildRemoveMessageActionRequest(string requestMethod, string requestBody, string channel, long messageTimetoken, long actionTimetoken, string messageActionUuid, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNRemoveMessageActionOperation; - - List url = new List(); - url.Add("v1"); - url.Add("message-actions"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - url.Add("message"); - url.Add(messageTimetoken.ToString(CultureInfo.InvariantCulture)); - url.Add("action"); - url.Add(actionTimetoken.ToString(CultureInfo.InvariantCulture)); - - Dictionary requestQueryStringParams = new Dictionary(); - if (messageActionUuid != null) - { - requestQueryStringParams.Add("uuid", UriUtil.EncodeUriComponent(messageActionUuid, currentType, false, false, false)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetMessageActionsRequest(string requestMethod, string requestBody, string channel, long start, long end, int limit, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGetMessageActionsOperation; - - List url = new List(); - url.Add("v1"); - url.Add("message-actions"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channel"); - url.Add(channel); - - Dictionary requestQueryStringParams = new Dictionary(); - if (start >= 0) - { - requestQueryStringParams.Add("start", start.ToString(CultureInfo.InvariantCulture)); - } - if (end >= 0) - { - requestQueryStringParams.Add("end", end.ToString(CultureInfo.InvariantCulture)); - } - if (limit >= 0) - { - requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGenerateFileUploadUrlRequest(string requestMethod, string requestBody, string channel, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNGenerateFileUploadUrlOperation; - - List url = new List(); - url.Add("v1"); - url.Add("files"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(channel); - url.Add("generate-upload-url"); - - Dictionary requestQueryStringParams = new Dictionary(); - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildPublishFileMessageRequest(string requestMethod, string requestBody, string channel, object originalMessage, bool storeInHistory, int ttl, Dictionary userMetaData, Dictionary additionalUrlParams, Dictionary externalQueryParam) - { - PNOperationType currentType = PNOperationType.PNPublishFileMessageOperation; - - List url = new List(); - url.Add("v1"); - url.Add("files"); - url.Add("publish-file"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].PublishKey : ""); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("0"); - url.Add(channel); - url.Add("0"); - if (requestMethod.ToUpperInvariant() == "GET") - { - string message = JsonEncodePublishMsg(originalMessage, currentType); - url.Add(message); - } - - Dictionary additionalUrlParamsDic = new Dictionary(); - if (additionalUrlParams != null) - { - additionalUrlParamsDic = additionalUrlParams; - } - - Dictionary requestQueryStringParams = new Dictionary(additionalUrlParamsDic); - - if (userMetaData != null) - { - string jsonMetaData = jsonLib.SerializeToJsonString(userMetaData); - requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, currentType, false, false, false)); - } - - if (storeInHistory && ttl >= 0) - { - requestQueryStringParams.Add("tt1", ttl.ToString(CultureInfo.InvariantCulture)); - } - - if (!storeInHistory) - { - requestQueryStringParams.Add("store", "0"); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildGetFileUrlOrDeleteReqest(string requestMethod, string requestBody, string channel, string fileId, string fileName, Dictionary externalQueryParam, PNOperationType operationType) - { - PNOperationType currentType = operationType; - - List url = new List(); - url.Add("v1"); - url.Add("files"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(channel); - url.Add("files"); - url.Add(fileId); - url.Add(fileName); - - Dictionary requestQueryStringParams = new Dictionary(); - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - Uri IUrlRequestBuilder.BuildListFilesReqest(string requestMethod, string requestBody, string channel, int limit, string nextToken, Dictionary externalQueryParam, PNOperationType operationType) - { - PNOperationType currentType = operationType; - - List url = new List(); - url.Add("v1"); - url.Add("files"); - url.Add(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].SubscribeKey : ""); - url.Add("channels"); - url.Add(channel); - url.Add("files"); - - Dictionary requestQueryStringParams = new Dictionary(); - requestQueryStringParams.Add("limit", (limit <= -1) ? "100" : limit.ToString(CultureInfo.InvariantCulture)); - if (!string.IsNullOrEmpty(nextToken)) - { - requestQueryStringParams.Add("next", nextToken); - } - - if (externalQueryParam != null && externalQueryParam.Count > 0) - { - foreach (KeyValuePair kvp in externalQueryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), currentType, false, false, false)); - } - } - } - - string queryString = BuildQueryString(currentType, requestQueryStringParams); - - return BuildRestApiRequest(requestMethod, requestBody, url, currentType, queryString, true); - } - - - private Dictionary GenerateCommonQueryParams(PNOperationType type, string uuid) - { - long timeStamp = TranslateUtcDateTimeToSeconds(DateTime.UtcNow); - string requestid = Guid.NewGuid().ToString(); - - if (pubnubUnitTest != null) - { - timeStamp = pubnubUnitTest.Timetoken; - requestid = string.IsNullOrEmpty(pubnubUnitTest.RequestId) ? "" : pubnubUnitTest.RequestId; - } - - Dictionary ret = new Dictionary(); - if (pubnubUnitTest != null && pubnubConfig.ContainsKey(pubnubInstanceId)) - { - if (pubnubUnitTest.IncludeUuid) - { - ret.Add("uuid", UriUtil.EncodeUriComponent(pubnubConfig[pubnubInstanceId].UserId, PNOperationType.PNSubscribeOperation, false, false, true)); - } - - if (pubnubUnitTest.IncludePnsdk) - { - ret.Add("pnsdk", UriUtil.EncodeUriComponent(Pubnub.Version, PNOperationType.PNSubscribeOperation, false, false, true)); - } - } - else - { - ret.Add("uuid", UriUtil.EncodeUriComponent(uuid != null ? uuid : - (pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].UserId.ToString() : ""), - PNOperationType.PNSubscribeOperation, false, false, true)); - ret.Add("pnsdk", UriUtil.EncodeUriComponent(Pubnub.Version, PNOperationType.PNSubscribeOperation, false, false, true)); - } - - if (pubnubConfig != null) - { - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].IncludeRequestIdentifier) - { - ret.Add("requestid", requestid); - } - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].IncludeInstanceIdentifier && !string.IsNullOrEmpty(pubnubInstanceId) && pubnubInstanceId.Trim().Length > 0) - { - ret.Add("instanceid", pubnubInstanceId); - } - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].EnableTelemetry && telemetryMgr != null) - { - Dictionary opsLatency = telemetryMgr.GetOperationsLatency().ConfigureAwait(false).GetAwaiter().GetResult(); - if (opsLatency != null && opsLatency.Count > 0) - { - foreach (string key in opsLatency.Keys) - { - ret.Add(key, opsLatency[key]); - } - } - } - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && !string.IsNullOrEmpty(pubnubConfig[pubnubInstanceId].SecretKey)) - { - ret.Add("timestamp", timeStamp.ToString(CultureInfo.InvariantCulture)); - } - - if (type != PNOperationType.PNTimeOperation - && type != PNOperationType.PNAccessManagerGrant && type != PNOperationType.PNAccessManagerGrantToken && type != PNOperationType.PNAccessManagerRevokeToken && type != PNOperationType.ChannelGroupGrantAccess - && type != PNOperationType.PNAccessManagerAudit && type != PNOperationType.ChannelGroupAuditAccess) - { - if (tokenMgr != null && !string.IsNullOrEmpty(tokenMgr.AuthToken) && tokenMgr.AuthToken.Trim().Length > 0) - { - ret.Add("auth", UriUtil.EncodeUriComponent(tokenMgr.AuthToken, type, false, false, false)); - } - else if (pubnubConfig.ContainsKey(pubnubInstanceId) && !string.IsNullOrEmpty(pubnubConfig[pubnubInstanceId].AuthKey) && pubnubConfig[pubnubInstanceId].AuthKey.Trim().Length > 0) - { - ret.Add("auth", UriUtil.EncodeUriComponent(pubnubConfig[pubnubInstanceId].AuthKey, type, false, false, false)); - } - } - } - - return ret; - } - - private string GeneratePAMv2Signature(string queryStringToSign, string partialUrl, PNOperationType opType) - { - string signature = ""; - StringBuilder string_to_sign = new StringBuilder(); - if (pubnubConfig.ContainsKey(pubnubInstanceId)) - { - string_to_sign.Append(pubnubConfig[pubnubInstanceId].SubscribeKey).Append('\n').Append(pubnubConfig[pubnubInstanceId].PublishKey).Append('\n'); - string_to_sign.Append(partialUrl).Append('\n'); - string_to_sign.Append(queryStringToSign); - - signature = Util.PubnubAccessManagerSign(pubnubConfig[pubnubInstanceId].SecretKey, string_to_sign.ToString()); - if (this.pubnubLog != null && this.pubnubConfig != null) - { - LoggingMethod.WriteToLog(pubnubLog, "string_to_sign = " + string_to_sign, pubnubConfig[pubnubInstanceId].LogVerbosity); - LoggingMethod.WriteToLog(pubnubLog, "signature = " + signature, pubnubConfig[pubnubInstanceId].LogVerbosity); - } - else - { - System.Diagnostics.Debug.WriteLine("string_to_sign = " + string_to_sign); - System.Diagnostics.Debug.WriteLine("signature = " + signature); - } - } - return signature; - } - - private string GeneratePAMv3Signature(string method, string requestBody, string queryStringToSign, string partialUrl, PNOperationType opType) - { - string signature = ""; - StringBuilder string_to_sign = new StringBuilder(); - if (pubnubConfig.ContainsKey(pubnubInstanceId)) - { - string_to_sign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", method.ToUpperInvariant()); - string_to_sign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", pubnubConfig[pubnubInstanceId].PublishKey); - string_to_sign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", partialUrl); - string_to_sign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", queryStringToSign); - string_to_sign.Append(requestBody); - - signature = Util.PubnubAccessManagerSign(pubnubConfig[pubnubInstanceId].SecretKey, string_to_sign.ToString()); - signature = string.Format(CultureInfo.InvariantCulture, "v2.{0}", signature.TrimEnd(new[] { '=' })); - if (this.pubnubLog != null && this.pubnubConfig != null) - { - LoggingMethod.WriteToLog(pubnubLog, "string_to_sign = " + string_to_sign, pubnubConfig[pubnubInstanceId].LogVerbosity); - LoggingMethod.WriteToLog(pubnubLog, "signature = " + signature, pubnubConfig[pubnubInstanceId].LogVerbosity); - } - else - { - System.Diagnostics.Debug.WriteLine("string_to_sign = " + string_to_sign); - System.Diagnostics.Debug.WriteLine("signature = " + signature); - } - } - return signature; - } - - private string BuildQueryString(PNOperationType type, Dictionary queryStringParamDic) - { - string queryString = ""; - - try - { - Dictionary internalQueryStringParamDic = new Dictionary(); - if (queryStringParamDic != null) - { - internalQueryStringParamDic = queryStringParamDic; - } - - string qsUuid = internalQueryStringParamDic.ContainsKey("uuid") ? internalQueryStringParamDic["uuid"] : null; - - Dictionary commonQueryStringParams = GenerateCommonQueryParams(type, qsUuid); - Dictionary queryStringParams = new Dictionary(commonQueryStringParams.Concat(internalQueryStringParamDic).GroupBy(item => item.Key).ToDictionary(item => item.Key, item => item.First().Value)); - - queryString = string.Join("&", queryStringParams.OrderBy(kvp => kvp.Key, StringComparer.Ordinal).Select(kvp => string.Format(CultureInfo.InvariantCulture, "{0}={1}", kvp.Key, kvp.Value)).ToArray()); - - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, "UrlRequestBuilder => BuildQueryString error " + ex, pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].LogVerbosity : PNLogVerbosity.BODY); - } - - return queryString; - } - - private Uri BuildRestApiRequest(string requestMethod, string requestBody, List urlComponents, PNOperationType type, string queryString, bool isPamV3Sign) - { - StringBuilder url = new StringBuilder(); - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].Secure) - { - url.Append("https://"); - } - else - { - url.Append("http://"); - } - - url.Append(pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].Origin : ""); - - for (int componentIndex = 0; componentIndex < urlComponents.Count; componentIndex++) - { - url.Append('/'); - - if ((type == PNOperationType.PNPublishOperation || type == PNOperationType.PNPublishFileMessageOperation) && componentIndex == urlComponents.Count - 1) - { - url.Append(UriUtil.EncodeUriComponent(urlComponents[componentIndex], type, false, true, false)); - } - else if (type == PNOperationType.PNAccessManagerRevokeToken) - { - url.Append(UriUtil.EncodeUriComponent(urlComponents[componentIndex], type, false, false, false)); - } - else - { - url.Append(UriUtil.EncodeUriComponent(urlComponents[componentIndex], type, true, false, false)); - } - } - - url.Append('?'); - url.Append(queryString); - System.Diagnostics.Debug.WriteLine("sb = " + url); - Uri requestUri = new Uri(url.ToString()); - - if (type == PNOperationType.PNPublishOperation || type == PNOperationType.PNPublishFileMessageOperation || type == PNOperationType.PNSubscribeOperation || type == PNOperationType.Presence) - { - ForceCanonicalPathAndQuery(requestUri); - } - System.Diagnostics.Debug.WriteLine("Uri = " + requestUri.ToString()); - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && pubnubConfig[pubnubInstanceId].SecretKey.Length > 0) - { - StringBuilder partialUrl = new StringBuilder(); - partialUrl.Append(requestUri.AbsolutePath); - - string signature; - if (isPamV3Sign) - { - signature = GeneratePAMv3Signature(requestMethod, requestBody, queryString, partialUrl.ToString(), type); - } - else - { - signature = GeneratePAMv2Signature(queryString, partialUrl.ToString(), type); - } - string queryStringWithSignature = string.Format(CultureInfo.InvariantCulture, "{0}&signature={1}", queryString, signature); - UriBuilder uriBuilder = new UriBuilder(requestUri); - uriBuilder.Query = queryStringWithSignature; - - requestUri = uriBuilder.Uri; - } - - return requestUri; - } - - private string JsonEncodePublishMsg(object originalMessage, PNOperationType opType) - { - string message = jsonLib.SerializeToJsonString(originalMessage); - - if (pubnubConfig.ContainsKey(pubnubInstanceId) && (pubnubConfig[pubnubInstanceId].CryptoModule != null || pubnubConfig[pubnubInstanceId].CipherKey.Length > 0) && opType != PNOperationType.PNSignalOperation) - { - pubnubConfig[pubnubInstanceId].CryptoModule ??= new CryptoModule(new LegacyCryptor(pubnubConfig[pubnubInstanceId].CipherKey, pubnubConfig[pubnubInstanceId].UseRandomInitializationVector, pubnubLog), null); - string encryptMessage = pubnubConfig[pubnubInstanceId].CryptoModule.Encrypt(message); - message = jsonLib.SerializeToJsonString(encryptMessage); - } - - return message; - } - - private void ForceCanonicalPathAndQuery(Uri requestUri) - { -#if !NETSTANDARD10 && !NETSTANDARD11 && !NETSTANDARD12 && !WP81 - LoggingMethod.WriteToLog(pubnubLog, "Inside ForceCanonicalPathAndQuery = " + requestUri.ToString(), pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].LogVerbosity : PNLogVerbosity.NONE); - try - { - FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic); - if (flagsFieldInfo != null) - { - ulong flags = (ulong)flagsFieldInfo.GetValue(requestUri); - flags &= ~((ulong)0x30); // Flags.PathNotCanonical|Flags.QueryNotCanonical - flagsFieldInfo.SetValue(requestUri, flags); - } - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, "Exception Inside ForceCanonicalPathAndQuery = " + ex, pubnubConfig.ContainsKey(pubnubInstanceId) ? pubnubConfig[pubnubInstanceId].LogVerbosity : PNLogVerbosity.BODY); - } -#endif - } - - public static long TranslateUtcDateTimeToSeconds(DateTime dotNetUTCDateTime) - { - TimeSpan timeSpan = dotNetUTCDateTime - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - long timeStamp = Convert.ToInt64(timeSpan.TotalSeconds); - return timeStamp; - } - - } -} diff --git a/src/Api/PubnubApi/ClientNetworkStatus.cs b/src/Api/PubnubApi/ClientNetworkStatus.cs index d706e6b9a..84cf056f5 100644 --- a/src/Api/PubnubApi/ClientNetworkStatus.cs +++ b/src/Api/PubnubApi/ClientNetworkStatus.cs @@ -1,154 +1,46 @@ using System; -using System.Threading; -using System.Net; using System.Threading.Tasks; -using System.IO; using System.Globalization; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 -using System.Net.Http; -using System.Net.Http.Headers; -#endif +using System.Collections.Generic; namespace PubnubApi { - #region "Network Status -- code split required" internal static class ClientNetworkStatus { - private static IJsonPluggableLibrary jsonLib; - private static PNConfiguration pubnubConfig; - private static IPubnubUnitTest unit; - private static IPubnubLog pubnubLog; + private static IJsonPluggableLibrary jsonLib; + private static PNConfiguration pubnubConfig; + private static IPubnubUnitTest unit; + private static IPubnubLog pubnubLog; + private static Pubnub pubnubInstance; - private static bool networkStatus = true; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - private static HttpClient httpClient; -#endif + private static bool networkStatus = true; - public static PNConfiguration PubnubConfiguation - { - set - { - pubnubConfig = value; - } - get - { - return pubnubConfig; - } - } + public static Pubnub PubnubInstance { get; set; } - public static IJsonPluggableLibrary JsonLibrary - { - set - { - jsonLib = value; - } - get - { - return jsonLib; - } - } + public static PNConfiguration PubnubConfiguation { get; set; } - public static IPubnubUnitTest PubnubUnitTest - { - set - { - unit = value; - } - get - { - return unit; - } - } + public static IJsonPluggableLibrary JsonLibrary { get; set; } - public static IPubnubLog PubnubLog - { - set - { - pubnubLog = value; - } - get - { - return pubnubLog; - } - } + public static IPubnubUnitTest PubnubUnitTest { get; set; } -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - public static HttpClient RefHttpClient - { - set - { - httpClient = value; - if (httpClient == null) - { - if (pubnubConfig.Proxy != null) - { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - if (httpClientHandler.SupportsProxy) - { - httpClientHandler.Proxy = pubnubConfig.Proxy; - httpClientHandler.UseProxy = true; - } - PubnubHttpClientHandler pubnubHttpClientHandler = new PubnubHttpClientHandler("PubnubHttpClientHandler", httpClientHandler, pubnubConfig, jsonLib, unit, pubnubLog); + public static IPubnubLog PubnubLog { get; set; } - httpClient = new HttpClient(pubnubHttpClientHandler); - } - else - { - httpClient = new HttpClient(); - } - httpClient.DefaultRequestHeaders.Accept.Clear(); - httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - httpClient.Timeout = TimeSpan.FromSeconds(pubnubConfig.NonSubscribeRequestTimeout); - } - - } - get - { - return httpClient; - } - } -#endif - - internal static bool CheckInternetStatus(bool systemActive, PNOperationType type, PNCallback callback, string[] channels, string[] channelGroups) + internal static bool CheckInternetStatus(bool systemActive, PNOperationType type, PNCallback callback, string[] channels, string[] channelGroups) { - if (unit != null) - { - return unit.InternetAvailable; - } - else - { - try - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task[] tasks = new Task[1]; - tasks[0] = Task.Factory.StartNew(async() => - { - await CheckClientNetworkAvailability(CallbackClientNetworkStatus, type, callback, channels, channelGroups).ConfigureAwait(false); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); - tasks[0].ConfigureAwait(false); - Task.WaitAll(tasks); -#else - Thread networkCheckThread = new Thread(async () => - { - await CheckClientNetworkAvailability(CallbackClientNetworkStatus, type, callback, channels, channelGroups).ConfigureAwait(false); - }) - { IsBackground = true }; - networkCheckThread.Start(); - networkCheckThread.Join(pubnubConfig.NonSubscribeRequestTimeout * 1000); -#endif - } - catch (AggregateException ae) { - foreach (var ie in ae.InnerExceptions) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} AggregateException CheckInternetStatus Error: {1} {2} ", DateTime.Now.ToString(CultureInfo.InvariantCulture), ie.GetType().Name, ie.Message), pubnubConfig.LogVerbosity); - } - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} Exception CheckInternetStatus Error: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); - } - - return networkStatus; + if (unit != null) { + return unit.InternetAvailable; + } else { + try { + return CheckClientNetworkAvailability(CallbackClientNetworkStatus, type, callback, channels, channelGroups); + } catch (AggregateException ae) { + foreach (var ie in ae.InnerExceptions) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} AggregateException CheckInternetStatus Error: {1} {2} ", DateTime.Now.ToString(CultureInfo.InvariantCulture), ie.GetType().Name, ie.Message), pubnubConfig.LogVerbosity); + } + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} Exception CheckInternetStatus Error: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); + } + + return networkStatus; } } @@ -157,239 +49,118 @@ private static void CallbackClientNetworkStatus(bool status) networkStatus = status; } - private static object internetCheckLock = new object(); - private static bool isInternetCheckRunning; + private static object internetCheckLock = new object(); + private static bool isInternetCheckRunning; - internal static bool IsInternetCheckRunning() - { - return isInternetCheckRunning; - } - - private static async Task CheckClientNetworkAvailability(Action internalCallback, PNOperationType type, PNCallback callback, string[] channels, string[] channelGroups) + internal static bool IsInternetCheckRunning() { - lock (internetCheckLock) - { - if (isInternetCheckRunning) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} InternetCheckRunning Already running", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - return networkStatus; - } - } + return isInternetCheckRunning; + } - InternetState state = new InternetState(); - state.InternalCallback = internalCallback; - state.PubnubCallbacck = callback; - state.ResponseType = type; - state.Channels = channels; - state.ChannelGroups = channelGroups; + private static bool CheckClientNetworkAvailability(Action internalCallback, PNOperationType type, PNCallback callback, string[] channels, string[] channelGroups) + { + lock (internetCheckLock) { + if (isInternetCheckRunning) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} InternetCheckRunning Already running", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); + return networkStatus; + } + } - networkStatus = await CheckSocketConnect(state).ConfigureAwait(false); - return networkStatus; + InternetState state = new InternetState + { + InternalCallback = internalCallback, + PubnubCallbacck = callback, + ResponseType = type, + Channels = channels, + ChannelGroups = channelGroups + }; + + CheckSocketConnect(state).ConfigureAwait(false); + return networkStatus; } - private static async Task CheckSocketConnect(object internetState) + private static async Task CheckSocketConnect(object internetState) { - lock (internetCheckLock) - { - isInternetCheckRunning = true; - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} CheckSocketConnect Entered", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - - Action internalCallback = null; - PNCallback pubnubCallback = null; - PNOperationType type = PNOperationType.None; + lock (internetCheckLock) { + isInternetCheckRunning = true; + } - var t = new TaskCompletionSource(); + Action internalCallback = null; + PNCallback pubnubCallback = null; + PNOperationType type = PNOperationType.None; - InternetState state = internetState as InternetState; - if (state != null) - { - internalCallback = state.InternalCallback; - type = state.ResponseType; - pubnubCallback = state.PubnubCallbacck; - } + var t = new TaskCompletionSource(); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(pubnubConfig, jsonLib, unit, pubnubLog, null, null, ""); - Uri requestUri = urlBuilder.BuildTimeRequest("GET", "", null); - try - { - bool gotTimeResp = false; - if (pubnubConfig.UseClassicHttpWebRequest) - { - gotTimeResp = await GetTimeWithClassicHttp(requestUri).ConfigureAwait(false); - t.TrySetResult(gotTimeResp); - } - else - { -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubConfig.UseTaskFactoryAsyncInsteadOfHttpClient) - { - gotTimeResp = await GetTimeWithTaskFactoryAsync(requestUri).ConfigureAwait(false); - } - else - { - gotTimeResp = await GetTimeWithHttpClient(requestUri).ConfigureAwait(false); - } - t.TrySetResult(gotTimeResp); -#else - gotTimeResp = await GetTimeWithTaskFactoryAsync(requestUri).ConfigureAwait(false); - t.TrySetResult(gotTimeResp); -#endif - } - } - catch (Exception ex) - { - networkStatus = false; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} CheckSocketConnect (HttpClient Or Task.Factory) Failed {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); - if (!networkStatus) - { - t.TrySetResult(false); - isInternetCheckRunning = false; - ParseCheckSocketConnectException(ex, type, pubnubCallback, internalCallback); - } - } - finally - { - isInternetCheckRunning = false; - } - return await t.Task.ConfigureAwait(false); + InternetState state = internetState as InternetState; + if (state != null) { + internalCallback = state.InternalCallback; + type = state.ResponseType; + pubnubCallback = state.PubnubCallbacck; + } + try { + var gotTimeResp = await GetTimeWithTaskFactoryAsync().ConfigureAwait(false); + isInternetCheckRunning = gotTimeResp; + networkStatus = gotTimeResp; + } catch (Exception ex) { + networkStatus = false; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} CheckSocketConnect (HttpClient Or Task.Factory) Failed {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); + if (!networkStatus) { + t.TrySetResult(false); + isInternetCheckRunning = false; + ParseCheckSocketConnectException(ex, type, pubnubCallback, internalCallback); + } + } + return isInternetCheckRunning; } - private static void ParseCheckSocketConnectException(Exception ex, PNOperationType type, PNCallback callback, Action internalcallback) + private static void ParseCheckSocketConnectException(Exception ex, PNOperationType type, PNCallback callback, Action internalcallback) { - PNStatusCategory errorCategory = PNStatusCategoryHelper.GetPNStatusCategory(ex); - StatusBuilder statusBuilder = new StatusBuilder(pubnubConfig, jsonLib); - PNStatus status = statusBuilder.CreateStatusResponse(type, errorCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException(ex)); + PNStatusCategory errorCategory = PNStatusCategoryHelper.GetPNStatusCategory(ex); + StatusBuilder statusBuilder = new StatusBuilder(pubnubConfig, jsonLib); + PNStatus status = statusBuilder.CreateStatusResponse(type, errorCategory, null, 404, new PNException(ex)); - if (callback != null) - { - callback.OnResponse(default(T), status); - } + if (callback != null) { + callback.OnResponse(default(T), status); + } LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} ParseCheckSocketConnectException Error. {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); internalcallback(false); } -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - private static async Task GetTimeWithHttpClient(Uri requestUri) - { - bool successFlag = false; - try - { - var response = await httpClient.GetAsync(requestUri).ConfigureAwait(false); - successFlag = response.IsSuccessStatusCode; - if (successFlag) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GetTimeWithHttpClient Resp OK", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GetTimeWithHttpClient FAILED", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - } - } - finally - { - networkStatus = successFlag; - } - return networkStatus; - } -#endif - private static async Task GetTimeWithTaskFactoryAsync(Uri requestUri) - { - bool successFlag = false; - try - { - 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) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GetTimeWithTaskFactoryAsync Resp {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), response.StatusCode.ToString()), pubnubConfig.LogVerbosity); - successFlag = response.StatusCode == HttpStatusCode.OK; - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GetTimeWithTaskFactoryAsync FAILED.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - } - } - } - finally - { - networkStatus = successFlag; - } - return networkStatus; - } - - private static async Task GetTimeWithClassicHttp(Uri requestUri) - { - bool successFlag = true; - try - { - HttpWebRequest myRequest = (HttpWebRequest)System.Net.WebRequest.Create(requestUri); - myRequest.Method = "GET"; - - RequestState pubnubRequestState = new RequestState(); - pubnubRequestState.Request = myRequest; - - myRequest.BeginGetResponse(new AsyncCallback( - (asynchronousResult) => { - RequestState asyncRequestState = asynchronousResult.AsyncState as RequestState; - HttpWebRequest asyncWebRequest = asyncRequestState.Request as HttpWebRequest; - if (asyncWebRequest != null) - { - HttpWebResponse asyncWebResponse = (HttpWebResponse)asyncWebRequest.EndGetResponse(asynchronousResult); - if (asyncWebResponse != null) - { - successFlag = asyncWebResponse.StatusCode == HttpStatusCode.OK; - } - if (asyncRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - asyncRequestState.Response = null; - asyncRequestState.Request = null; - } - } - } - ), pubnubRequestState); - - var _ = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, pubnubConfig.NonSubscribeRequestTimeout * 1000, Timeout.Infinite); - } - finally - { -#if NET35 || NET40 - await Task.Factory.StartNew(() => { }).ConfigureAwait(false); -#else - await Task.Delay(1).ConfigureAwait(false); -#endif - networkStatus = successFlag; - } - return networkStatus; - } + private static async Task GetTimeWithTaskFactoryAsync() + { + bool successFlag = false; + try + { + var transportResponse = await TimeRequest().ConfigureAwait(false); + if (transportResponse.Error == null) + { + successFlag = transportResponse.StatusCode == 200; + } + } + finally { + networkStatus = successFlag; + } + return successFlag; + } - private static void OnPubnubWebRequestTimeout(System.Object requestState) - { - RequestState currentState = requestState as RequestState; - if (currentState != null && currentState.Response == null && currentState.Request != null) - { - currentState.Timeout = true; - try - { - currentState.Request.Abort(); - } - catch { /* ignore */ } + private static async Task TimeRequest() + { + List pathSegments = + [ + "time", + "0" + ]; + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments + }; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNTimeOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + return transportResponse; + } + } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, GetTimeWithClassicHttp timedout", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - } - } - } -#endregion } diff --git a/src/Api/PubnubApi/Constants.cs b/src/Api/PubnubApi/Constants.cs index 70ab7c19e..1de248fc7 100644 --- a/src/Api/PubnubApi/Constants.cs +++ b/src/Api/PubnubApi/Constants.cs @@ -1,9 +1,17 @@ -using System; -namespace PubnubApi +namespace PubnubApi { public static class Constants { public static readonly string Pnpres = "-pnpres"; + + public const string GET = "GET"; + public const string POST = "POST"; + public const string PATCH = "PATCH"; + public const string PUT = "PUT"; + public const string DELETE = "DELETE"; + + public const int ResourceNotFoundStatusCode = 404; + public const int HttpRequestSuccessStatusCode = 200; + public const int HttpRequestEntityTooLargeStatusCode = 413; } } - diff --git a/src/Api/PubnubApi/EndPoint/Access/AuditOperation.cs b/src/Api/PubnubApi/EndPoint/Access/AuditOperation.cs index 2e4368e52..52abec465 100644 --- a/src/Api/PubnubApi/EndPoint/Access/AuditOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Access/AuditOperation.cs @@ -3,213 +3,217 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; -using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class AuditOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string channelName; - private string channelGroupName; - private string[] authenticationKeys; - private PNCallback savedCallback; - private Dictionary queryParam; - - public AuditOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, null, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public AuditOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public AuditOperation ChannelGroup(string channelGroup) - { - this.channelGroupName = channelGroup; - return this; - } - - public AuditOperation AuthKeys(string[] authKeys) - { - this.authenticationKeys = authKeys; - return this; - } - - public AuditOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - - public async Task> ExecuteAsync() - { - return await AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void AuditAccess(string channel, string channelGroup, string[] authKeys, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) - { - throw new MissingMemberException("Invalid secret key"); - } - - string authKeysCommaDelimited = (authKeys != null && authKeys.Length > 0) ? string.Join(",", authKeys.OrderBy(x => x).ToArray()) : ""; - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildAuditAccessRequest("GET", "", channel, channelGroup, authKeysCommaDelimited, externalQueryParam); - - RequestState requestState = new RequestState(); - if (!string.IsNullOrEmpty(channel)) - { - requestState.Channels = new [] { channel }; - } - if (!string.IsNullOrEmpty(channelGroup)) - { - requestState.ChannelGroups = new [] { channelGroup }; - } - requestState.ResponseType = PNOperationType.PNAccessManagerAudit; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - - } - - internal async Task> AuditAccess(string channel, string channelGroup, string[] authKeys, Dictionary externalQueryParam) - { - if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) - { - throw new MissingMemberException("Invalid secret key"); - } - - PNResult ret = new PNResult(); - - string authKeysCommaDelimited = (authKeys != null && authKeys.Length > 0) ? string.Join(",", authKeys.OrderBy(x => x).ToArray()) : ""; - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildAuditAccessRequest("GET", "", channel, channelGroup, authKeysCommaDelimited, externalQueryParam); - - RequestState requestState = new RequestState(); - if (!string.IsNullOrEmpty(channel)) - { - requestState.Channels = new[] { channel }; - } - if (!string.IsNullOrEmpty(channelGroup)) - { - requestState.ChannelGroups = new[] { channelGroup }; - } - requestState.ResponseType = PNOperationType.PNAccessManagerAudit; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - if (result != null) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNAccessManagerAuditResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class AuditOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelName; + private string channelGroupName; + private string[] authenticationKeys; + private PNCallback savedCallback; + private Dictionary queryParam; + + public AuditOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, null, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public AuditOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public AuditOperation ChannelGroup(string channelGroup) + { + this.channelGroupName = channelGroup; + return this; + } + + public AuditOperation AuthKeys(string[] authKeys) + { + this.authenticationKeys = authKeys; + return this; + } + + public AuditOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam, callback); + } + + + public async Task> ExecuteAsync() + { + return await AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + AuditAccess(this.channelName, this.channelGroupName, this.authenticationKeys, this.queryParam, savedCallback); + } + + internal void AuditAccess(string channel, string channelGroup, string[] authKeys, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) { + throw new MissingMemberException("Invalid secret key"); + } + RequestState requestState = new RequestState(); + if (!string.IsNullOrEmpty(channel)) { + requestState.Channels = new[] { channel }; + } + if (!string.IsNullOrEmpty(channelGroup)) { + requestState.ChannelGroups = new[] { channelGroup }; + } + requestState.ResponseType = PNOperationType.PNAccessManagerAudit; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerAudit); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerAudit, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + + } + + internal async Task> AuditAccess(string channel, string channelGroup, string[] authKeys, Dictionary externalQueryParam) + { + if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) { + throw new MissingMemberException("Invalid secret key"); + } + + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNAccessManagerAudit; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + if (!string.IsNullOrEmpty(channel)) { + requestState.Channels = new[] { channel }; + } + if (!string.IsNullOrEmpty(channelGroup)) { + requestState.ChannelGroups = new[] { channelGroup }; + } + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerAudit); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) + { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List result = ProcessJsonResponse(requestState, json); + if (result != null) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNAccessManagerAuditResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerAudit, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "auth", + "audit", + "sub-key", + config.SubscribeKey + }; + + Dictionary requestQueryStringParams = new Dictionary(); + string authKeysCommaDelimited = (authenticationKeys != null && authenticationKeys.Length > 0) ? string.Join(",", authenticationKeys.OrderBy(x => x).ToArray()) : string.Empty; + if (!string.IsNullOrEmpty(authKeysCommaDelimited)) { + requestQueryStringParams.Add("auth", UriUtil.EncodeUriComponent(authKeysCommaDelimited, PNOperationType.PNAccessManagerAudit, false, false, false)); + } + + if (!string.IsNullOrEmpty(channelName)) { + requestQueryStringParams.Add("channel", UriUtil.EncodeUriComponent(channelName, PNOperationType.PNAccessManagerAudit, false, false, false)); + } + + if (!string.IsNullOrEmpty(channelGroupName)) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroupName, PNOperationType.PNAccessManagerAudit, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNAccessManagerAudit, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs b/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs index d11eab87b..fe11b5370 100644 --- a/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs @@ -1,24 +1,18 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; -using System.Threading; -using System.Net; using System.Globalization; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class GrantOperation : PubnubCoreBase + public class GrantOperation : PubnubCoreBase { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private string[] pubnubChannelNames; private string[] pubnubChannelGroupNames; @@ -35,13 +29,12 @@ public class GrantOperation : PubnubCoreBase private PNCallback savedCallback; private Dictionary queryParam; - public GrantOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, null, instance) + public GrantOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, null, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; } public GrantOperation Channels(string[] channels) @@ -138,20 +131,8 @@ public void Execute(PNCallback callback) { throw new InvalidOperationException("Only Get/Update/Delete permissions are allowed for UUID"); } -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GrantAccess(callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GrantAccess(callback); - }) - { IsBackground = true }.Start(); -#endif + this.savedCallback = callback; + GrantAccess(callback); } public async Task> ExecuteAsync() @@ -169,18 +150,7 @@ public async Task> ExecuteAsync() internal void Retry() { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GrantAccess(savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GrantAccess(savedCallback); - }) - { IsBackground = true }.Start(); -#endif + GrantAccess(savedCallback); } internal void GrantAccess(PNCallback callback) @@ -189,44 +159,6 @@ internal void GrantAccess(PNCallback callback) { throw new MissingMemberException("Invalid secret key"); } - - List channelList = new List(); - List channelGroupList = new List(); - List uuidList = new List(); - List authList = new List(); - - if (this.pubnubChannelNames != null && this.pubnubChannelNames.Length > 0) - { - channelList = new List(this.pubnubChannelNames); - channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); - } - - if (this.pubnubChannelGroupNames != null && this.pubnubChannelGroupNames.Length > 0) - { - channelGroupList = new List(this.pubnubChannelGroupNames); - channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); - } - - if (this.pubnubTargetUuids != null && this.pubnubTargetUuids.Length > 0) - { - uuidList = new List(this.pubnubTargetUuids); - uuidList = uuidList.Where(uuid => !string.IsNullOrEmpty(uuid) && uuid.Trim().Length > 0).Distinct().ToList(); - } - - if (this.pamAuthenticationKeys != null && this.pamAuthenticationKeys.Length > 0) - { - authList = new List(this.pamAuthenticationKeys); - authList = authList.Where(auth => !string.IsNullOrEmpty(auth) && auth.Trim().Length > 0).Distinct().ToList(); - } - - string channelsCommaDelimited = string.Join(",", channelList.OrderBy(x => x).ToArray()); - string channelGroupsCommaDelimited = string.Join(",", channelGroupList.OrderBy(x => x).ToArray()); - string targetUuidsCommaDelimited = string.Join(",", uuidList.OrderBy(x => x).ToArray()); - string authKeysCommaDelimited = string.Join(",", authList.OrderBy(x => x).ToArray()); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGrantV2AccessRequest("GET", "", channelsCommaDelimited, channelGroupsCommaDelimited, targetUuidsCommaDelimited, authKeysCommaDelimited, this.grantRead, this.grantWrite, this.grantDelete, this.grantManage, this.grantGet, this.grantUpdate, this.grantJoin, this.grantTTL, this.queryParam); - RequestState requestState = new RequestState(); requestState.Channels = this.pubnubChannelNames; requestState.ChannelGroups = this.pubnubChannelGroupNames; @@ -234,17 +166,27 @@ internal void GrantAccess(PNCallback callback) requestState.PubnubCallback = callback; requestState.Reconnect = false; requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerGrant); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerGrant, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); } internal async Task> GrantAccess() @@ -254,8 +196,58 @@ internal async Task> GrantAccess() throw new MissingMemberException("Invalid secret key"); } - PNResult ret = new PNResult(); + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = this.pubnubChannelNames; + requestState.ChannelGroups = this.pubnubChannelGroupNames; + requestState.ResponseType = PNOperationType.PNAccessManagerGrant; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerGrant); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) + { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) + { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNAccessManagerGrantResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) + { + returnValue.Result = responseResult; + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerGrant, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { List channelList = new List(); List channelGroupList = new List(); List uuidList = new List(); @@ -290,52 +282,67 @@ internal async Task> GrantAccess() string targetUuidsCommaDelimited = string.Join(",", uuidList.OrderBy(x => x).ToArray()); string authKeysCommaDelimited = string.Join(",", authList.OrderBy(x => x).ToArray()); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGrantV2AccessRequest("GET", "", channelsCommaDelimited, channelGroupsCommaDelimited, targetUuidsCommaDelimited,authKeysCommaDelimited, this.grantRead, this.grantWrite, this.grantDelete, this.grantManage, this.grantGet, this.grantUpdate, this.grantJoin, this.grantTTL, this.queryParam); + List pathSegments = new List() { + "v2", + "auth", + "grant", + "sub-key", + config.SubscribeKey + }; - RequestState requestState = new RequestState(); - requestState.Channels = this.pubnubChannelNames; - requestState.ChannelGroups = this.pubnubChannelGroupNames; - requestState.ResponseType = PNOperationType.PNAccessManagerGrant; - requestState.Reconnect = false; - requestState.EndPointOperation = this; + Dictionary requestQueryStringParams = new Dictionary(); - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) + if (!string.IsNullOrEmpty(authKeysCommaDelimited)) { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNAccessManagerGrantResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } + requestQueryStringParams.Add("auth", UriUtil.EncodeUriComponent(authKeysCommaDelimited, PNOperationType.PNAccessManagerGrant, false, false, false)); } - - return ret; - } - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; + if (!string.IsNullOrEmpty(channelsCommaDelimited)) + { + requestQueryStringParams.Add("channel", UriUtil.EncodeUriComponent(channelsCommaDelimited, PNOperationType.PNAccessManagerGrant, false, false, false)); + } - if (!ChannelRequest.ContainsKey(instance.InstanceId)) + if (!string.IsNullOrEmpty(channelGroupsCommaDelimited)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroupsCommaDelimited, PNOperationType.PNAccessManagerGrant, false, false, false)); } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) + + if (!string.IsNullOrEmpty(targetUuidsCommaDelimited)) { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + requestQueryStringParams.Add("target-uuid", UriUtil.EncodeUriComponent(targetUuidsCommaDelimited, PNOperationType.PNAccessManagerGrant, false, false, false)); } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) + + if (grantTTL > -1) { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + requestQueryStringParams.Add("ttl", grantTTL.ToString(CultureInfo.InvariantCulture)); } + + requestQueryStringParams.Add("r", Convert.ToInt32(grantRead).ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("w", Convert.ToInt32(grantWrite).ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("d", Convert.ToInt32(grantDelete).ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("m", Convert.ToInt32(grantManage).ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("g", Convert.ToInt32(grantGet).ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("u", Convert.ToInt32(grantUpdate).ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("j", Convert.ToInt32(grantJoin).ToString(CultureInfo.InvariantCulture)); + + if (queryParam != null && queryParam.Count > 0) + { + foreach (KeyValuePair kvp in queryParam) + { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) + { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNAccessManagerGrant, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; } } } diff --git a/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs b/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs index 5ab257582..a827e2f81 100644 --- a/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs @@ -3,531 +3,418 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; -using System.Net; using System.Globalization; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GrantTokenOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNTokenResources pubnubResources = new PNTokenResources - { - Channels = new Dictionary(), - Spaces = new Dictionary(), - ChannelGroups = new Dictionary(), - Uuids = new Dictionary(), - Users = new Dictionary() - }; - private PNTokenPatterns pubnubPatterns = new PNTokenPatterns - { - Channels = new Dictionary(), - Spaces = new Dictionary(), - ChannelGroups = new Dictionary(), - Uuids = new Dictionary(), - Users = new Dictionary() - }; - - private int grantTTL = -1; - private PNCallback savedCallbackGrantToken; - private Dictionary queryParam; - private Dictionary grantMeta; - private string pubnubAuthorizedUuid = string.Empty; - private string pubnubAuthorizedUserId = string.Empty; - - public GrantTokenOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - PubnubInstance = instance; - - InitializeDefaultVariableObjectStates(); - } - - public GrantTokenOperation AuthorizedUuid(string uuid) - { - if (!string.IsNullOrEmpty(pubnubAuthorizedUserId)) - { - throw new ArgumentException("Either UUID or UserId can be used. Not both."); - } - pubnubAuthorizedUuid = uuid; - return this; - } - - public GrantTokenOperation AuthorizedUserId(UserId user) - { - if (!string.IsNullOrEmpty(pubnubAuthorizedUuid)) - { - throw new ArgumentException("Either UUID or UserId can be used. Not both."); - } - pubnubAuthorizedUserId = user; - return this; - } - - public GrantTokenOperation Resources(PNTokenResources resources) - { - if (pubnubResources != null && resources != null) - { - if (resources.Channels != null && resources.Channels.Count > 0 && - resources.Spaces != null && resources.Spaces.Count > 0) - { - throw new ArgumentException("Either Channels or Spaces can be used. Not both."); - } - if (resources.Uuids != null && resources.Uuids.Count > 0 && - resources.Users != null && resources.Users.Count > 0) - { - throw new ArgumentException("Either Uuids or Users can be used. Not both."); - } - pubnubResources = resources; - if (pubnubResources.Channels == null) - { - pubnubResources.Channels = new Dictionary(); - } - if (pubnubResources.Spaces == null) - { - pubnubResources.Spaces = new Dictionary(); - } - if (pubnubResources.ChannelGroups == null) - { - pubnubResources.ChannelGroups = new Dictionary(); - } - if (pubnubResources.Uuids == null) - { - pubnubResources.Uuids = new Dictionary(); - } - if (pubnubResources.Users == null) - { - pubnubResources.Users = new Dictionary(); - } - } - return this; - } - - public GrantTokenOperation Patterns(PNTokenPatterns patterns) - { - if (pubnubPatterns != null && patterns != null) - { - if (patterns.Channels != null && patterns.Channels.Count > 0 && - patterns.Spaces != null && patterns.Spaces.Count > 0) - { - throw new ArgumentException("Either Channels or Spaces can be used. Not both."); - } - if (patterns.Uuids != null && patterns.Uuids.Count > 0 && - patterns.Users != null && patterns.Users.Count > 0) - { - throw new ArgumentException("Either Uuids or Users can be used. Not both."); - } - - pubnubPatterns = patterns; - if (pubnubPatterns.Channels == null) - { - pubnubPatterns.Channels = new Dictionary(); - } - if (pubnubPatterns.Spaces == null) - { - pubnubPatterns.Spaces = new Dictionary(); - } - if (pubnubPatterns.ChannelGroups == null) - { - pubnubPatterns.ChannelGroups = new Dictionary(); - } - if (pubnubPatterns.Uuids == null) - { - pubnubPatterns.Uuids = new Dictionary(); - } - if (pubnubPatterns.Users == null) - { - pubnubPatterns.Users = new Dictionary(); - } - - } - return this; - } - - public GrantTokenOperation TTL(int ttl) - { - this.grantTTL = ttl; - return this; - } - - public GrantTokenOperation Meta(Dictionary metaObject) - { - this.grantMeta = metaObject; - return this; - } - - public GrantTokenOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallbackGrantToken = callback; - GrantAccess(callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallbackGrantToken = callback; - GrantAccess(callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GrantAccess().ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GrantAccess(savedCallbackGrantToken); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GrantAccess(savedCallbackGrantToken); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void GrantAccess(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) - { - throw new MissingMemberException("Invalid secret key"); - } - - if (this.grantTTL <= 0) - { - throw new MissingMemberException("Invalid TTL value"); - } - - RequestState requestState = new RequestState(); - requestState.Channels = pubnubResources.Channels.Keys.ToArray(); - requestState.ChannelGroups = pubnubResources.ChannelGroups.Keys.ToArray(); - requestState.ResponseType = PNOperationType.PNAccessManagerGrantToken; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - - requestState.UsePostMethod = true; - - bool atleastOnePermission = false; - Dictionary chBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Channels, atleastOnePermission, out chBitmaskPermCollection); - - Dictionary chPatternBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Channels, atleastOnePermission, out chPatternBitmaskPermCollection); - - Dictionary spBitmaskPermCollection = null; - Dictionary spPatternBitmaskPermCollection = null; - if (pubnubResources.Channels.Count == 0 && pubnubPatterns.Channels.Count == 0) - { - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Spaces, atleastOnePermission, out spBitmaskPermCollection); - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Spaces, atleastOnePermission, out spPatternBitmaskPermCollection); - } - else - { - spBitmaskPermCollection = new Dictionary(); - spPatternBitmaskPermCollection = new Dictionary(); - } - - Dictionary cgBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.ChannelGroups, atleastOnePermission, out cgBitmaskPermCollection); - - Dictionary cgPatternBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.ChannelGroups, atleastOnePermission, out cgPatternBitmaskPermCollection); - - Dictionary uuidBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Uuids, atleastOnePermission, out uuidBitmaskPermCollection); - - Dictionary uuidPatternBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Uuids, atleastOnePermission, out uuidPatternBitmaskPermCollection); - - Dictionary userBitmaskPermCollection = null; - Dictionary userPatternBitmaskPermCollection = null; - if (pubnubResources.Uuids.Count == 0 && pubnubPatterns.Uuids.Count == 0) - { - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Users, atleastOnePermission, out userBitmaskPermCollection); - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Users, atleastOnePermission, out userPatternBitmaskPermCollection); - } - else - { - userBitmaskPermCollection = new Dictionary(); - userPatternBitmaskPermCollection = new Dictionary(); - - } - - if (!atleastOnePermission) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} At least one permission is needed for at least one or more of uuids/users, channels/spaces or groups",DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); - } - - Dictionary resourcesCollection = new Dictionary(); - resourcesCollection.Add("channels", chBitmaskPermCollection); - resourcesCollection.Add("groups", cgBitmaskPermCollection); - resourcesCollection.Add("uuids", uuidBitmaskPermCollection); - resourcesCollection.Add("users", userBitmaskPermCollection); - resourcesCollection.Add("spaces", spBitmaskPermCollection); - - Dictionary patternsCollection = new Dictionary(); - patternsCollection.Add("channels", chPatternBitmaskPermCollection); - patternsCollection.Add("groups", cgPatternBitmaskPermCollection); - patternsCollection.Add("uuids", uuidPatternBitmaskPermCollection); - patternsCollection.Add("users", userPatternBitmaskPermCollection); - patternsCollection.Add("spaces", spPatternBitmaskPermCollection); - - Dictionary optimizedMeta = new Dictionary(); - if (this.grantMeta != null) - { - optimizedMeta = this.grantMeta; - } - - Dictionary permissionCollection = new Dictionary(); - permissionCollection.Add("resources", resourcesCollection); - permissionCollection.Add("patterns", patternsCollection); - permissionCollection.Add("meta", optimizedMeta); - if (!string.IsNullOrEmpty(this.pubnubAuthorizedUuid) && this.pubnubAuthorizedUuid.Trim().Length > 0) - { - permissionCollection.Add("uuid", this.pubnubAuthorizedUuid); - } - else if (!string.IsNullOrEmpty(this.pubnubAuthorizedUserId) && this.pubnubAuthorizedUserId.Trim().Length > 0) - { - permissionCollection.Add("uuid", this.pubnubAuthorizedUserId); - } - Dictionary messageEnvelope = new Dictionary(); - messageEnvelope.Add("ttl", this.grantTTL); - messageEnvelope.Add("permissions", permissionCollection); - - string requestMethodName = "POST"; - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGrantV3AccessRequest(requestMethodName, postMessage, this.queryParam); - - UrlProcessRequest(request, requestState, false, postData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private bool FillPermissionMappingWithMaskValues(Dictionary dPerms, bool currentAtleastOnePermission, out Dictionary dPermsWithMaskValues) - { - dPermsWithMaskValues = new Dictionary(); - bool internalAtleastOnePermission = currentAtleastOnePermission; - foreach (KeyValuePair kvp in dPerms) - { - PNTokenAuthValues perm = kvp.Value; - int bitMaskPermissionValue = 0; - if (!string.IsNullOrEmpty(kvp.Key) && kvp.Key.Trim().Length > 0 && perm != null) - { - bitMaskPermissionValue = CalculateGrantBitMaskValue(perm); - if (!internalAtleastOnePermission && bitMaskPermissionValue > 0) { internalAtleastOnePermission = true; } - } - dPermsWithMaskValues.Add(kvp.Key, bitMaskPermissionValue); - } - return internalAtleastOnePermission; - } - - internal async Task> GrantAccess() - { - if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) - { - throw new MissingMemberException("Invalid secret key"); - } - - if (this.grantTTL <= 0) - { - throw new MissingMemberException("Invalid TTL value"); - } - - PNResult ret = new PNResult(); - - bool atleastOnePermission = false; - Dictionary chBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Channels, atleastOnePermission, out chBitmaskPermCollection); - - Dictionary chPatternBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Channels, atleastOnePermission, out chPatternBitmaskPermCollection); - Dictionary spBitmaskPermCollection = null; - Dictionary spPatternBitmaskPermCollection = null; - if (pubnubResources.Channels.Count == 0 && pubnubPatterns.Channels.Count == 0) - { - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Spaces, atleastOnePermission, out spBitmaskPermCollection); - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Spaces, atleastOnePermission, out spPatternBitmaskPermCollection); - } - else - { - spBitmaskPermCollection = new Dictionary(); - spPatternBitmaskPermCollection = new Dictionary(); - } - - Dictionary cgBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.ChannelGroups, atleastOnePermission, out cgBitmaskPermCollection); - - Dictionary cgPatternBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.ChannelGroups, atleastOnePermission, out cgPatternBitmaskPermCollection); - - Dictionary uuidBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Uuids, atleastOnePermission, out uuidBitmaskPermCollection); - - Dictionary uuidPatternBitmaskPermCollection = null; - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Uuids, atleastOnePermission, out uuidPatternBitmaskPermCollection); - - Dictionary userBitmaskPermCollection = null; - Dictionary userPatternBitmaskPermCollection = null; - if (pubnubResources.Uuids.Count == 0 && pubnubPatterns.Uuids.Count == 0) - { - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Users, atleastOnePermission, out userBitmaskPermCollection); - atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Users, atleastOnePermission, out userPatternBitmaskPermCollection); - } - else - { - userBitmaskPermCollection = new Dictionary(); - userPatternBitmaskPermCollection = new Dictionary(); - - } - - if (!atleastOnePermission) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} At least one permission is needed for at least one or more of uuids, channels or groups", DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); - } - - Dictionary resourcesCollection = new Dictionary(); - resourcesCollection.Add("channels", chBitmaskPermCollection); - resourcesCollection.Add("groups", cgBitmaskPermCollection); - resourcesCollection.Add("uuids", uuidBitmaskPermCollection); - resourcesCollection.Add("users", userBitmaskPermCollection); - resourcesCollection.Add("spaces", spBitmaskPermCollection); - - Dictionary patternsCollection = new Dictionary(); - patternsCollection.Add("channels", chPatternBitmaskPermCollection); - patternsCollection.Add("groups", cgPatternBitmaskPermCollection); - patternsCollection.Add("uuids", uuidPatternBitmaskPermCollection); - patternsCollection.Add("users", new Dictionary()); //Empty object for users for json structure - patternsCollection.Add("spaces", new Dictionary()); //Empty object for spaces for json structure - - Dictionary optimizedMeta = new Dictionary(); - if (this.grantMeta != null) - { - optimizedMeta = this.grantMeta; - } - - Dictionary permissionCollection = new Dictionary(); - permissionCollection.Add("resources", resourcesCollection); - permissionCollection.Add("patterns", patternsCollection); - permissionCollection.Add("meta", optimizedMeta); - if (!string.IsNullOrEmpty(this.pubnubAuthorizedUuid) && this.pubnubAuthorizedUuid.Trim().Length > 0) - { - permissionCollection.Add("uuid", this.pubnubAuthorizedUuid); - } - - Dictionary messageEnvelope = new Dictionary(); - messageEnvelope.Add("ttl", this.grantTTL); - messageEnvelope.Add("permissions", permissionCollection); - - string requestMethodName = "POST"; - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGrantV3AccessRequest(requestMethodName, postMessage, this.queryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = pubnubResources.Channels.Keys.ToArray(); - requestState.ChannelGroups = pubnubResources.ChannelGroups.Keys.ToArray(); - requestState.ResponseType = PNOperationType.PNAccessManagerGrantToken; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = true; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, postData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNAccessManagerTokenResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - - return ret; - } - - private static int CalculateGrantBitMaskValue(PNTokenAuthValues perm) - { - int result = 0; - - if (perm.Read) - { - result = (int)GrantBitFlag.READ; - } - if (perm.Write) - { - result = result + (int)GrantBitFlag.WRITE; - } - if (perm.Manage) - { - result = result + (int)GrantBitFlag.MANAGE; - } - if (perm.Delete) - { - result = result + (int)GrantBitFlag.DELETE; - } - if (perm.Create) - { - result = result + (int)GrantBitFlag.CREATE; - } - if (perm.Get) - { - result = result + (int)GrantBitFlag.GET; - } - if (perm.Update) - { - result = result + (int)GrantBitFlag.UPDATE; - } - if (perm.Join) - { - result = result + (int)GrantBitFlag.JOIN; - } - - return result; - } - } + public class GrantTokenOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNTokenResources pubnubResources = new PNTokenResources { + Channels = new Dictionary(), + Spaces = new Dictionary(), + ChannelGroups = new Dictionary(), + Uuids = new Dictionary(), + Users = new Dictionary() + }; + private PNTokenPatterns pubnubPatterns = new PNTokenPatterns { + Channels = new Dictionary(), + Spaces = new Dictionary(), + ChannelGroups = new Dictionary(), + Uuids = new Dictionary(), + Users = new Dictionary() + }; + + private int grantTTL = -1; + private PNCallback savedCallbackGrantToken; + private Dictionary queryParam; + private Dictionary grantMeta; + private string pubnubAuthorizedUuid = string.Empty; + private string pubnubAuthorizedUserId = string.Empty; + + public GrantTokenOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + PubnubInstance = instance; + + InitializeDefaultVariableObjectStates(); + } + + public GrantTokenOperation AuthorizedUuid(string uuid) + { + if (!string.IsNullOrEmpty(pubnubAuthorizedUserId)) { + throw new ArgumentException("Either UUID or UserId can be used. Not both."); + } + pubnubAuthorizedUuid = uuid; + return this; + } + + public GrantTokenOperation AuthorizedUserId(UserId user) + { + if (!string.IsNullOrEmpty(pubnubAuthorizedUuid)) { + throw new ArgumentException("Either UUID or UserId can be used. Not both."); + } + pubnubAuthorizedUserId = user; + return this; + } + + public GrantTokenOperation Resources(PNTokenResources resources) + { + if (pubnubResources != null && resources != null) { + if (resources.Channels != null && resources.Channels.Count > 0 && + resources.Spaces != null && resources.Spaces.Count > 0) { + throw new ArgumentException("Either Channels or Spaces can be used. Not both."); + } + if (resources.Uuids != null && resources.Uuids.Count > 0 && + resources.Users != null && resources.Users.Count > 0) { + throw new ArgumentException("Either Uuids or Users can be used. Not both."); + } + pubnubResources = resources; + if (pubnubResources.Channels == null) { + pubnubResources.Channels = new Dictionary(); + } + if (pubnubResources.Spaces == null) { + pubnubResources.Spaces = new Dictionary(); + } + if (pubnubResources.ChannelGroups == null) { + pubnubResources.ChannelGroups = new Dictionary(); + } + if (pubnubResources.Uuids == null) { + pubnubResources.Uuids = new Dictionary(); + } + if (pubnubResources.Users == null) { + pubnubResources.Users = new Dictionary(); + } + } + return this; + } + + public GrantTokenOperation Patterns(PNTokenPatterns patterns) + { + if (pubnubPatterns != null && patterns != null) { + if (patterns.Channels != null && patterns.Channels.Count > 0 && + patterns.Spaces != null && patterns.Spaces.Count > 0) { + throw new ArgumentException("Either Channels or Spaces can be used. Not both."); + } + if (patterns.Uuids != null && patterns.Uuids.Count > 0 && + patterns.Users != null && patterns.Users.Count > 0) { + throw new ArgumentException("Either Uuids or Users can be used. Not both."); + } + + pubnubPatterns = patterns; + if (pubnubPatterns.Channels == null) { + pubnubPatterns.Channels = new Dictionary(); + } + if (pubnubPatterns.Spaces == null) { + pubnubPatterns.Spaces = new Dictionary(); + } + if (pubnubPatterns.ChannelGroups == null) { + pubnubPatterns.ChannelGroups = new Dictionary(); + } + if (pubnubPatterns.Uuids == null) { + pubnubPatterns.Uuids = new Dictionary(); + } + if (pubnubPatterns.Users == null) { + pubnubPatterns.Users = new Dictionary(); + } + + } + return this; + } + + public GrantTokenOperation TTL(int ttl) + { + this.grantTTL = ttl; + return this; + } + + public GrantTokenOperation Meta(Dictionary metaObject) + { + this.grantMeta = metaObject; + return this; + } + + public GrantTokenOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + GrantAccess(callback); + } + + public async Task> ExecuteAsync() + { + return await GrantAccess().ConfigureAwait(false); + } + + internal void Retry() + { + GrantAccess(savedCallbackGrantToken); + } + + internal void GrantAccess(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) { + throw new MissingMemberException("Invalid secret key"); + } + + if (this.grantTTL <= 0) { + throw new MissingMemberException("Invalid TTL value"); + } + + RequestState requestState = new RequestState(); + requestState.Channels = pubnubResources.Channels.Keys.ToArray(); + requestState.ChannelGroups = pubnubResources.ChannelGroups.Keys.ToArray(); + requestState.ResponseType = PNOperationType.PNAccessManagerGrantToken; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerGrantToken); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerGrantToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNAccessManagerTokenResult), status); + } + }); + } + + private bool FillPermissionMappingWithMaskValues(Dictionary dPerms, bool currentAtleastOnePermission, out Dictionary dPermsWithMaskValues) + { + dPermsWithMaskValues = new Dictionary(); + bool internalAtleastOnePermission = currentAtleastOnePermission; + foreach (KeyValuePair kvp in dPerms) { + PNTokenAuthValues perm = kvp.Value; + int bitMaskPermissionValue = 0; + if (!string.IsNullOrEmpty(kvp.Key) && kvp.Key.Trim().Length > 0 && perm != null) { + bitMaskPermissionValue = CalculateGrantBitMaskValue(perm); + if (!internalAtleastOnePermission && bitMaskPermissionValue > 0) { internalAtleastOnePermission = true; } + } + dPermsWithMaskValues.Add(kvp.Key, bitMaskPermissionValue); + } + return internalAtleastOnePermission; + } + + internal async Task> GrantAccess() + { + if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) { + throw new MissingMemberException("Invalid secret key"); + } + + if (this.grantTTL <= 0) { + throw new MissingMemberException("Invalid TTL value"); + } + RequestState requestState = new RequestState(); + requestState.Channels = pubnubResources.Channels.Keys.ToArray(); + requestState.ChannelGroups = pubnubResources.ChannelGroups.Keys.ToArray(); + requestState.ResponseType = PNOperationType.PNAccessManagerGrantToken; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + Tuple JsonAndStatusTuple; + + PNResult returnValue = new PNResult(); + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerGrantToken); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNAccessManagerTokenResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerGrantToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private static int CalculateGrantBitMaskValue(PNTokenAuthValues perm) + { + int result = 0; + + if (perm.Read) { + result = (int)GrantBitFlag.READ; + } + if (perm.Write) { + result = result + (int)GrantBitFlag.WRITE; + } + if (perm.Manage) { + result = result + (int)GrantBitFlag.MANAGE; + } + if (perm.Delete) { + result = result + (int)GrantBitFlag.DELETE; + } + if (perm.Create) { + result = result + (int)GrantBitFlag.CREATE; + } + if (perm.Get) { + result = result + (int)GrantBitFlag.GET; + } + if (perm.Update) { + result = result + (int)GrantBitFlag.UPDATE; + } + if (perm.Join) { + result = result + (int)GrantBitFlag.JOIN; + } + + return result; + } + + private RequestParameter CreateRequestParameter() + { + bool atleastOnePermission = false; + Dictionary chBitmaskPermCollection = null; + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Channels, atleastOnePermission, out chBitmaskPermCollection); + + Dictionary chPatternBitmaskPermCollection = null; + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Channels, atleastOnePermission, out chPatternBitmaskPermCollection); + + Dictionary spBitmaskPermCollection = null; + Dictionary spPatternBitmaskPermCollection = null; + if (pubnubResources.Channels.Count == 0 && pubnubPatterns.Channels.Count == 0) { + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Spaces, atleastOnePermission, out spBitmaskPermCollection); + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Spaces, atleastOnePermission, out spPatternBitmaskPermCollection); + } else { + spBitmaskPermCollection = new Dictionary(); + spPatternBitmaskPermCollection = new Dictionary(); + } + + Dictionary cgBitmaskPermCollection = null; + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.ChannelGroups, atleastOnePermission, out cgBitmaskPermCollection); + + Dictionary cgPatternBitmaskPermCollection = null; + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.ChannelGroups, atleastOnePermission, out cgPatternBitmaskPermCollection); + + Dictionary uuidBitmaskPermCollection = null; + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Uuids, atleastOnePermission, out uuidBitmaskPermCollection); + + Dictionary uuidPatternBitmaskPermCollection = null; + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Uuids, atleastOnePermission, out uuidPatternBitmaskPermCollection); + + Dictionary userBitmaskPermCollection = null; + Dictionary userPatternBitmaskPermCollection = null; + if (pubnubResources.Uuids.Count == 0 && pubnubPatterns.Uuids.Count == 0) { + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubResources.Users, atleastOnePermission, out userBitmaskPermCollection); + atleastOnePermission = FillPermissionMappingWithMaskValues(this.pubnubPatterns.Users, atleastOnePermission, out userPatternBitmaskPermCollection); + } else { + userBitmaskPermCollection = new Dictionary(); + userPatternBitmaskPermCollection = new Dictionary(); + } + + if (!atleastOnePermission) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} At least one permission is needed for at least one or more of uuids/users, channels/spaces or groups", DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); + } + + Dictionary resourcesCollection = new Dictionary + { + { "channels", chBitmaskPermCollection }, + { "groups", cgBitmaskPermCollection }, + { "uuids", uuidBitmaskPermCollection }, + { "users", userBitmaskPermCollection }, + { "spaces", spBitmaskPermCollection } + }; + + Dictionary patternsCollection = new Dictionary + { + { "channels", chPatternBitmaskPermCollection }, + { "groups", cgPatternBitmaskPermCollection }, + { "uuids", uuidPatternBitmaskPermCollection }, + { "users", userPatternBitmaskPermCollection }, + { "spaces", spPatternBitmaskPermCollection } + }; + + Dictionary optimizedMeta = new Dictionary(); + if (this.grantMeta != null) { + optimizedMeta = this.grantMeta; + } + + Dictionary permissionCollection = new Dictionary + { + { "resources", resourcesCollection }, + { "patterns", patternsCollection }, + { "meta", optimizedMeta } + }; + if (!string.IsNullOrEmpty(this.pubnubAuthorizedUuid) && this.pubnubAuthorizedUuid.Trim().Length > 0) { + permissionCollection.Add("uuid", this.pubnubAuthorizedUuid); + } else if (!string.IsNullOrEmpty(this.pubnubAuthorizedUserId) && this.pubnubAuthorizedUserId.Trim().Length > 0) { + permissionCollection.Add("uuid", this.pubnubAuthorizedUserId); + } + Dictionary messageEnvelope = new Dictionary + { + { "ttl", this.grantTTL }, + { "permissions", permissionCollection } + }; + string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + byte[] postData = Encoding.UTF8.GetBytes(postMessage); + + List pathSegments = new List() { + "v3", + "pam", + config.SubscribeKey, + "grant" + }; + + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNAccessManagerGrantToken, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.POST, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = postMessage + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Access/RevokeTokenOperation.cs b/src/Api/PubnubApi/EndPoint/Access/RevokeTokenOperation.cs index cddae2111..3a58b59d2 100644 --- a/src/Api/PubnubApi/EndPoint/Access/RevokeTokenOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Access/RevokeTokenOperation.cs @@ -1,155 +1,167 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class RevokeTokenOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string pnToken = string.Empty; - private PNCallback savedCallbackRevokeToken; - private Dictionary queryParam; - - public RevokeTokenOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - PubnubInstance = instance; - - InitializeDefaultVariableObjectStates(); - } - - public RevokeTokenOperation Token(string tokenToBeRevoked) - { - this.pnToken = tokenToBeRevoked; - return this; - } - - public RevokeTokenOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallbackRevokeToken = callback; - RevokeAccess(callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallbackRevokeToken = callback; - RevokeAccess(callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RevokeAccess().ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RevokeAccess(savedCallbackRevokeToken); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RevokeAccess(savedCallbackRevokeToken); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void RevokeAccess(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) - { - throw new MissingMemberException("Invalid secret key"); - } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNAccessManagerRevokeToken; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - string requestMethodName = "DELETE"; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildRevokeV3AccessRequest(requestMethodName, null, pnToken, this.queryParam); - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> RevokeAccess() - { - if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) - { - throw new MissingMemberException("Invalid secret key"); - } - - PNResult ret = new PNResult(); - - string requestMethodName = "DELETE"; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildRevokeV3AccessRequest(requestMethodName, null, pnToken, queryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNAccessManagerRevokeToken; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNAccessManagerRevokeTokenResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - - return ret; - } - - } + public class RevokeTokenOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string pnToken = string.Empty; + private PNCallback savedCallbackRevokeToken; + private Dictionary queryParam; + + public RevokeTokenOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + PubnubInstance = instance; + + InitializeDefaultVariableObjectStates(); + } + + public RevokeTokenOperation Token(string tokenToBeRevoked) + { + this.pnToken = tokenToBeRevoked; + return this; + } + + public RevokeTokenOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + this.savedCallbackRevokeToken = callback; + RevokeAccess(callback); + } + + public async Task> ExecuteAsync() + { + return await RevokeAccess().ConfigureAwait(false); + } + + internal void Retry() + { + RevokeAccess(savedCallbackRevokeToken); + } + + internal void RevokeAccess(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) { + throw new MissingMemberException("Invalid secret key"); + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNAccessManagerRevokeToken; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerRevokeToken); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNAccessManagerRevokeTokenResult), status); + } + }); + } + + internal async Task> RevokeAccess() + { + if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0) { + throw new MissingMemberException("Invalid secret key"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNAccessManagerRevokeToken; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAccessManagerRevokeToken); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNAccessManagerRevokeTokenResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List() { + "v3", + "pam", + config.SubscribeKey, + "grant", + pnToken + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.ChannelGroupRevokeAccess, false, false, false)); + } + } + } + + string queryString = UriUtil.BuildQueryString(requestQueryStringParams); + + var requestParameter = new RequestParameter() { + RequestType = Constants.DELETE, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/ChannelGroup/AddChannelsToChannelGroupOperation.cs b/src/Api/PubnubApi/EndPoint/ChannelGroup/AddChannelsToChannelGroupOperation.cs index e5b382245..beb1bc0a2 100644 --- a/src/Api/PubnubApi/EndPoint/ChannelGroup/AddChannelsToChannelGroupOperation.cs +++ b/src/Api/PubnubApi/EndPoint/ChannelGroup/AddChannelsToChannelGroupOperation.cs @@ -2,205 +2,204 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class AddChannelsToChannelGroupOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pnTelemetryMgr; - - private string channelGroupName = ""; - private string[] channelNames; - private PNCallback savedCallback; - private Dictionary queryParam; - - public AddChannelsToChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pnTelemetryMgr = telemetryManager; - } - - public AddChannelsToChannelGroupOperation ChannelGroup(string channelGroup) - { - this.channelGroupName = channelGroup; - return this; - } - - public AddChannelsToChannelGroupOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - public AddChannelsToChannelGroupOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void AddChannelsToChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam, PNCallback callback) - { - if (channels == null || channels.Length == 0) - { - throw new ArgumentException("Missing channel(s)"); - } - - if (nameSpace == null) - { - throw new ArgumentException("Missing nameSpace"); - } - - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pnTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - string channelsCommaDelimited = string.Join(",", channels.OrderBy(x => x).ToArray()); - - Uri request = urlBuilder.BuildAddChannelsToChannelGroupRequest("GET", "", channelsCommaDelimited, nameSpace, groupName, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNAddChannelsToGroupOperation; - requestState.Channels = new string[] { }; - requestState.ChannelGroups = new [] { groupName }; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> AddChannelsToChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam) - { - if (channels == null || channels.Length == 0) - { - throw new ArgumentException("Missing channel(s)"); - } - - if (nameSpace == null) - { - throw new ArgumentException("Missing nameSpace"); - } - - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pnTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - string channelsCommaDelimited = string.Join(",", channels.OrderBy(x => x).ToArray()); - - Uri request = urlBuilder.BuildAddChannelsToChannelGroupRequest("GET", "", channelsCommaDelimited, nameSpace, groupName, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNAddChannelsToGroupOperation; - requestState.Channels = new string[] { }; - requestState.ChannelGroups = new[] { groupName }; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelGroupsAddChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class AddChannelsToChannelGroupOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelGroupName = ""; + private string[] channelNames; + private PNCallback savedCallback; + private Dictionary queryParam; + + public AddChannelsToChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public AddChannelsToChannelGroupOperation ChannelGroup(string channelGroup) + { + this.channelGroupName = channelGroup; + return this; + } + + public AddChannelsToChannelGroupOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + public AddChannelsToChannelGroupOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + AddChannelsToChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, savedCallback); + } + + internal void AddChannelsToChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam, PNCallback callback) + { + if (channels == null || channels.Length == 0) { + throw new ArgumentException("Missing channel(s)"); + } + + if (nameSpace == null) { + throw new ArgumentException("Missing nameSpace"); + } + + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNAddChannelsToGroupOperation; + requestState.Channels = new string[] { }; + requestState.ChannelGroups = new[] { groupName }; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAddChannelsToGroupOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAddChannelsToGroupOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNChannelGroupsAddChannelResult), status); + } + }); + } + + internal async Task> AddChannelsToChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam) + { + if (channels == null || channels.Length == 0) { + throw new ArgumentException("Missing channel(s)"); + } + + if (nameSpace == null) { + throw new ArgumentException("Missing nameSpace"); + } + + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNAddChannelsToGroupOperation; + requestState.Channels = new string[] { }; + requestState.ChannelGroups = new[] { groupName }; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNAddChannelsToGroupOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelGroupsAddChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAccessManagerRevokeToken, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "channel-registration", + "sub-key", + config.SubscribeKey, + "channel-group", + channelGroupName + }; + + Dictionary requestQueryStringParams = new Dictionary + { + { "add", UriUtil.EncodeUriComponent(string.Join(",", channelNames.OrderBy(x => x).ToArray()), PNOperationType.PNAddChannelsToGroupOperation, false, false, false) } + }; + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNAddChannelsToGroupOperation, false, false, false)); + } + } + } + + string queryString = UriUtil.BuildQueryString(requestQueryStringParams); + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/ChannelGroup/DeleteChannelGroupOperation.cs b/src/Api/PubnubApi/EndPoint/ChannelGroup/DeleteChannelGroupOperation.cs index af125b23f..f372a22fb 100644 --- a/src/Api/PubnubApi/EndPoint/ChannelGroup/DeleteChannelGroupOperation.cs +++ b/src/Api/PubnubApi/EndPoint/ChannelGroup/DeleteChannelGroupOperation.cs @@ -1,173 +1,179 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Text; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class DeleteChannelGroupOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string channelGroupName = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public DeleteChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public DeleteChannelGroupOperation ChannelGroup(string channelGroup) - { - this.channelGroupName = channelGroup; - return this; - } - - public DeleteChannelGroupOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - DeleteChannelGroup(this.channelGroupName, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - DeleteChannelGroup(this.channelGroupName, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await DeleteChannelGroup(this.channelGroupName, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - DeleteChannelGroup(this.channelGroupName, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - DeleteChannelGroup(this.channelGroupName, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void DeleteChannelGroup(string groupName, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildRemoveChannelsFromChannelGroupRequest("GET", "", null, "", groupName, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveGroupOperation; - requestState.Channels = new string[] { }; - requestState.ChannelGroups = new [] { groupName }; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> DeleteChannelGroup(string groupName, Dictionary externalQueryParam) - { - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildRemoveChannelsFromChannelGroupRequest("GET", "", null, "", groupName, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveGroupOperation; - requestState.Channels = new string[] { }; - requestState.ChannelGroups = new[] { groupName }; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelGroupsDeleteGroupResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - } + public class DeleteChannelGroupOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelGroupName = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public DeleteChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public DeleteChannelGroupOperation ChannelGroup(string channelGroup) + { + this.channelGroupName = channelGroup; + return this; + } + + public DeleteChannelGroupOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + DeleteChannelGroup(this.channelGroupName, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await DeleteChannelGroup(this.channelGroupName, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + DeleteChannelGroup(this.channelGroupName, this.queryParam, savedCallback); + } + + internal void DeleteChannelGroup(string groupName, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveGroupOperation; + requestState.Channels = new string[] { }; + requestState.ChannelGroups = new[] { groupName }; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveGroupOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveGroupOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNChannelGroupsDeleteGroupResult), status); + } + }); + } + + internal async Task> DeleteChannelGroup(string groupName, Dictionary externalQueryParam) + { + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveGroupOperation; + requestState.Channels = new string[] { }; + requestState.ChannelGroups = new[] { groupName }; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveGroupOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelGroupsDeleteGroupResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveGroupOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { + + List pathSegments = new List + { + "v1", + "channel-registration", + "sub-key", + config.SubscribeKey, + "channel-group", + channelGroupName, + "remove" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNRemoveGroupOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/ChannelGroup/ListAllChannelGroupOperation.cs b/src/Api/PubnubApi/EndPoint/ChannelGroup/ListAllChannelGroupOperation.cs index 36409c2c4..f764efd9e 100644 --- a/src/Api/PubnubApi/EndPoint/ChannelGroup/ListAllChannelGroupOperation.cs +++ b/src/Api/PubnubApi/EndPoint/ChannelGroup/ListAllChannelGroupOperation.cs @@ -1,152 +1,171 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class ListAllChannelGroupOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public ListAllChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public ListAllChannelGroupOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetAllChannelGroup(this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetAllChannelGroup(this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetAllChannelGroup(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetAllChannelGroup(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetAllChannelGroup(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void GetAllChannelGroup(Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGetAllChannelGroupRequest("GET", "", externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.ChannelGroupAllGet; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> GetAllChannelGroup(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGetAllChannelGroupRequest("GET", "", externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.ChannelGroupAllGet; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelGroupsListAllResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class ListAllChannelGroupOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public ListAllChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public ListAllChannelGroupOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + GetAllChannelGroup(this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await GetAllChannelGroup(this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetAllChannelGroup(this.queryParam, savedCallback); + } + + internal void GetAllChannelGroup(Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.ChannelGroupAllGet; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.ChannelGroupAllGet); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.ChannelGroupAllGet, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNChannelGroupsListAllResult), status); + } + }); + } + + internal async Task> GetAllChannelGroup(Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.ChannelGroupAllGet; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.ChannelGroupAllGet); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelGroupsListAllResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.ChannelGroupAllGet, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "channel-registration", + "sub-key", + config.SubscribeKey, + "channel-group" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.ChannelGroupAllGet, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/ChannelGroup/ListChannelsForChannelGroupOperation.cs b/src/Api/PubnubApi/EndPoint/ChannelGroup/ListChannelsForChannelGroupOperation.cs index e939d0a03..daf1f3417 100644 --- a/src/Api/PubnubApi/EndPoint/ChannelGroup/ListChannelsForChannelGroupOperation.cs +++ b/src/Api/PubnubApi/EndPoint/ChannelGroup/ListChannelsForChannelGroupOperation.cs @@ -1,173 +1,186 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class ListChannelsForChannelGroupOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string channelGroupName = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public ListChannelsForChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - - public ListChannelsForChannelGroupOperation ChannelGroup(string channelGroup) - { - this.channelGroupName = channelGroup; - return this; - } - - public ListChannelsForChannelGroupOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetChannelsForChannelGroup(this.channelGroupName, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetChannelsForChannelGroup(this.channelGroupName, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetChannelsForChannelGroup(this.channelGroupName, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetChannelsForChannelGroup(this.channelGroupName, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetChannelsForChannelGroup(this.channelGroupName, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void GetChannelsForChannelGroup(string groupName, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetChannelsForChannelGroupRequest("GET", "", null, groupName, false, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.ChannelGroupGet; - requestState.ChannelGroups = new [] { groupName }; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> GetChannelsForChannelGroup(string groupName, Dictionary externalQueryParam) - { - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetChannelsForChannelGroupRequest("GET", "", null, groupName, false, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.ChannelGroupGet; - requestState.ChannelGroups = new[] { groupName }; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelGroupsAllChannelsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class ListChannelsForChannelGroupOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelGroupName = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public ListChannelsForChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + + public ListChannelsForChannelGroupOperation ChannelGroup(string channelGroup) + { + this.channelGroupName = channelGroup; + return this; + } + + public ListChannelsForChannelGroupOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + GetChannelsForChannelGroup(this.channelGroupName, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await GetChannelsForChannelGroup(this.channelGroupName, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetChannelsForChannelGroup(this.channelGroupName, this.queryParam, savedCallback); + } + + internal void GetChannelsForChannelGroup(string groupName, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + var requestParameter = CreateRequestParameter(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.ChannelGroupGet; + requestState.ChannelGroups = new[] { groupName }; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.ChannelGroupGet); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.ChannelGroupGet, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNChannelGroupsAllChannelsResult), status); + } + }); + } + + internal async Task> GetChannelsForChannelGroup(string groupName, Dictionary externalQueryParam) + { + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.ChannelGroupGet; + requestState.ChannelGroups = new[] { groupName }; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.ChannelGroupGet); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelGroupsAllChannelsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.ChannelGroupGet, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "channel-registration", + "sub-key", + config.SubscribeKey, + "channel-group", + channelGroupName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.ChannelGroupGet, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/ChannelGroup/RemoveChannelsFromChannelGroupOperation.cs b/src/Api/PubnubApi/EndPoint/ChannelGroup/RemoveChannelsFromChannelGroupOperation.cs index cc6a2c8a1..41474e3b3 100644 --- a/src/Api/PubnubApi/EndPoint/ChannelGroup/RemoveChannelsFromChannelGroupOperation.cs +++ b/src/Api/PubnubApi/EndPoint/ChannelGroup/RemoveChannelsFromChannelGroupOperation.cs @@ -2,207 +2,216 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class RemoveChannelsFromChannelGroupOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string channelGroupName = ""; - private string[] channelNames; - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemoveChannelsFromChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public RemoveChannelsFromChannelGroupOperation ChannelGroup(string channelGroup) - { - this.channelGroupName = channelGroup; - return this; - } - - public RemoveChannelsFromChannelGroupOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - public RemoveChannelsFromChannelGroupOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void RemoveChannelsFromChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam, PNCallback callback) - { - if (channels == null || channels.Length == 0) - { - throw new ArgumentException("Missing channel(s)"); - } - - if (nameSpace == null) - { - throw new ArgumentException("Missing nameSpace"); - } - - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - string channelsCommaDelimited = string.Join(",", channels.OrderBy(x => x).ToArray()); - - - Uri request = urlBuilder.BuildRemoveChannelsFromChannelGroupRequest("GET", "", channelsCommaDelimited, nameSpace, groupName, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveChannelsFromGroupOperation; - requestState.Channels = new string[] { }; - requestState.ChannelGroups = new [] { groupName }; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> RemoveChannelsFromChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam) - { - if (channels == null || channels.Length == 0) - { - throw new ArgumentException("Missing channel(s)"); - } - - if (nameSpace == null) - { - throw new ArgumentException("Missing nameSpace"); - } - - if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) - { - throw new ArgumentException("Missing groupName"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - string channelsCommaDelimited = string.Join(",", channels.OrderBy(x => x).ToArray()); - - - Uri request = urlBuilder.BuildRemoveChannelsFromChannelGroupRequest("GET", "", channelsCommaDelimited, nameSpace, groupName, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveChannelsFromGroupOperation; - requestState.Channels = new string[] { }; - requestState.ChannelGroups = new[] { groupName }; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelGroupsRemoveChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class RemoveChannelsFromChannelGroupOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelGroupName = ""; + private string[] channelNames; + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemoveChannelsFromChannelGroupOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public RemoveChannelsFromChannelGroupOperation ChannelGroup(string channelGroup) + { + this.channelGroupName = channelGroup; + return this; + } + + public RemoveChannelsFromChannelGroupOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + public RemoveChannelsFromChannelGroupOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RemoveChannelsFromChannelGroup(this.channelNames, "", this.channelGroupName, this.queryParam, savedCallback); + } + + internal void RemoveChannelsFromChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam, PNCallback callback) + { + if (channels == null || channels.Length == 0) { + throw new ArgumentException("Missing channel(s)"); + } + + if (nameSpace == null) { + throw new ArgumentException("Missing nameSpace"); + } + + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveChannelsFromGroupOperation; + requestState.Channels = new string[] { }; + requestState.ChannelGroups = new[] { groupName }; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveChannelsFromGroupOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveChannelsFromGroupOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNChannelGroupsRemoveChannelResult), status); + } + }); + } + + internal async Task> RemoveChannelsFromChannelGroup(string[] channels, string nameSpace, string groupName, Dictionary externalQueryParam) + { + if (channels == null || channels.Length == 0) { + throw new ArgumentException("Missing channel(s)"); + } + + if (nameSpace == null) { + throw new ArgumentException("Missing nameSpace"); + } + + if (string.IsNullOrEmpty(groupName) || groupName.Trim().Length == 0) { + throw new ArgumentException("Missing groupName"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveChannelsFromGroupOperation; + requestState.Channels = new string[] { }; + requestState.ChannelGroups = new[] { groupName }; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveChannelsFromGroupOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelGroupsRemoveChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveChannelsFromGroupOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private RequestParameter CreateRequestParameter() + { + + List pathSegments = new List + { + "v1", + "channel-registration", + "sub-key", + config.SubscribeKey, + "channel-group", + channelGroupName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (channelNames.Length > 0) { + string channelsCommaDelimited = string.Join(",", channelNames.OrderBy(x => x).ToArray()); + requestQueryStringParams.Add("remove", UriUtil.EncodeUriComponent(channelsCommaDelimited, PNOperationType.PNRemoveChannelsFromGroupOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNRemoveChannelsFromGroupOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs index e24165d97..e0e59d88d 100644 --- a/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/DeleteFileOperation.cs @@ -1,218 +1,204 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class DeleteFileOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNCallback savedCallback; - private Dictionary queryParam; - - private string channelName; - private string currentFileId; - private string currentFileName; - - public DeleteFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public DeleteFileOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public DeleteFileOperation FileId(string fileId) - { - this.currentFileId = fileId; - return this; - } - - public DeleteFileOperation FileName(string fileName) - { - this.currentFileName = fileName; - return this; - } - - public DeleteFileOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - if (string.IsNullOrEmpty(this.channelName)) - { - throw new ArgumentException("Missing Channel Name"); - } - if (string.IsNullOrEmpty(this.currentFileId)) - { - throw new ArgumentException("Missing File Id"); - } - if (string.IsNullOrEmpty(this.currentFileName)) - { - throw new ArgumentException("Missing File Name"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessDeleteFileRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessDeleteFileRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessDeleteFileRequest(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessDeleteFileRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessDeleteFileRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessDeleteFileRequest(Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest("DELETE", "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDeleteFileOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDeleteFileOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> ProcessDeleteFileRequest(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.channelName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Channel name", new ArgumentException("Invalid Channel name")) }; - ret.Status = errStatus; - return ret; - } - if (string.IsNullOrEmpty(this.currentFileId)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(this.currentFileName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; - ret.Status = errStatus; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest("DELETE", "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDeleteFileOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDeleteFileOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNDeleteFileResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - } + public class DeleteFileOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNCallback savedCallback; + private Dictionary queryParam; + + private string channelName; + private string fileId; + private string fileName; + + public DeleteFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public DeleteFileOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public DeleteFileOperation FileId(string fileId) + { + this.fileId = fileId; + return this; + } + + public DeleteFileOperation FileName(string fileName) + { + this.fileName = fileName; + return this; + } + + public DeleteFileOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + if (string.IsNullOrEmpty(this.channelName)) { + throw new ArgumentException("Missing Channel Name"); + } + if (string.IsNullOrEmpty(this.fileId)) { + throw new ArgumentException("Missing File Id"); + } + if (string.IsNullOrEmpty(this.fileName)) { + throw new ArgumentException("Missing File Name"); + } + + this.savedCallback = callback; + ProcessDeleteFileRequest(this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await ProcessDeleteFileRequest(this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + ProcessDeleteFileRequest(this.queryParam, savedCallback); + } + + private void ProcessDeleteFileRequest(Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDeleteFileOperation; + requestState.PubnubCallback = callback; + requestState.UsePostMethod = false; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteFileOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteFileOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> ProcessDeleteFileRequest(Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(this.channelName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Channel name", new ArgumentException("Invalid Channel name")) }; + returnValue.Status = errStatus; + return returnValue; + } + if (string.IsNullOrEmpty(this.fileId)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(this.fileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; + returnValue.Status = errStatus; + return returnValue; + } + var requestParameter = CreateRequestParameter(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDeleteFileOperation; + requestState.Reconnect = false; + requestState.UsePostMethod = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteFileOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNDeleteFileResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteFileOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "files", + config.SubscribeKey, + "channels", + channelName, + "files", + fileId, + fileName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDeleteFileOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.DELETE, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs index 93896da53..ac3e82108 100644 --- a/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs @@ -1,260 +1,233 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; namespace PubnubApi.EndPoint { - public class DownloadFileOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNCallback savedCallback; - private Dictionary queryParam; - - private string channelName; - private string currentFileId; - private string currentFileName; - private string currentFileCipherKey; - - public DownloadFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public DownloadFileOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public DownloadFileOperation FileId(string fileId) - { - this.currentFileId = fileId; - return this; - } - - public DownloadFileOperation FileName(string fileName) - { - this.currentFileName = fileName; - return this; - } - - public DownloadFileOperation CipherKey(string cipherKeyForFile) - { - this.currentFileCipherKey = cipherKeyForFile; - return this; - } - - public DownloadFileOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - - if (string.IsNullOrEmpty(this.currentFileId)) - { - throw new ArgumentException("Missing File Id"); - } - if (string.IsNullOrEmpty(this.currentFileName)) - { - throw new ArgumentException("Missing File Name"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessFileDownloadRequest(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessFileDownloadRequest(Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDownloadFileOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDownloadFileOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - byte[] item1Bytes = null; - UrlProcessRequestForStream(request, requestState, false,"").ContinueWith(r => - { - item1Bytes = r.Result.Item1; - if (item1Bytes != null) - { - byte[] outputBytes = null; - if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) - { - outputBytes = item1Bytes; - } - else - { - CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); - try - { - outputBytes = currentCryptoModule.Decrypt(item1Bytes); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), item1Bytes.Length), config.LogVerbosity); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine("{0}\nMessage might be not encrypted, returning as is...", ex.ToString()); - outputBytes = item1Bytes; - } - } - PNDownloadFileResult result = new PNDownloadFileResult(); - result.FileBytes = outputBytes; - result.FileName = currentFileName; - callback.OnResponse(result, r.Result.Item2); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - - - } - - private async Task> ProcessFileDownloadRequest(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.currentFileId)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(this.currentFileName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; - ret.Status = errStatus; - return ret; - } - - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDownloadFileOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDownloadFileOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequestForStream(request, requestState, false,"").ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - byte[] item1Bytes = JsonAndStatusTuple.Item1; - if (item1Bytes != null) - { - byte[] outputBytes = null; - if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) - { - outputBytes = item1Bytes; - } - else - { - CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); - try - { - outputBytes = currentCryptoModule.Decrypt(item1Bytes); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), item1Bytes.Length), config.LogVerbosity); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine("{0}\nMessage might be not encrypted, returning as is...", ex.ToString()); - outputBytes = item1Bytes; - ret.Status = new PNStatus { Error = true, ErrorData = new PNErrorData("Decryption error", ex) }; - } - } - - PNDownloadFileResult result = new PNDownloadFileResult(); - result.FileBytes = outputBytes; - result.FileName = currentFileName; - ret.Result = result; - } - - return ret; - } - - } + public class DownloadFileOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNCallback savedCallback; + private Dictionary queryParam; + + private string channelName; + private string currentFileId; + private string currentFileName; + private string currentFileCipherKey; + + public DownloadFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public DownloadFileOperation Channel(string channel) + { + channelName = channel; + return this; + } + + public DownloadFileOperation FileId(string fileId) + { + currentFileId = fileId; + return this; + } + + public DownloadFileOperation FileName(string fileName) + { + currentFileName = fileName; + return this; + } + + public DownloadFileOperation CipherKey(string cipherKeyForFile) + { + currentFileCipherKey = cipherKeyForFile; + return this; + } + + public DownloadFileOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(currentFileId)) { + throw new ArgumentException("Missing File Id"); + } + if (string.IsNullOrEmpty(currentFileName)) { + throw new ArgumentException("Missing File Name"); + } + + savedCallback = callback ?? throw new ArgumentException("Missing callback"); + ProcessFileDownloadRequest(savedCallback); + } + + public async Task> ExecuteAsync() + { + return await ProcessFileDownloadRequest().ConfigureAwait(false); + } + + internal void Retry() + { + ProcessFileDownloadRequest(savedCallback); + } + + private void ProcessFileDownloadRequest(PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDownloadFileOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDownloadFileOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) + { + var fileContentBytes = transportResponse.Content; + if (fileContentBytes != null) { + requestState.GotJsonResponse = true; + byte[] outputBytes; + if (string.IsNullOrEmpty(currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) { + outputBytes = fileContentBytes; + } else { + CryptoModule currentCryptoModule = !string.IsNullOrEmpty(currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); + try { + outputBytes = currentCryptoModule.Decrypt(fileContentBytes); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), fileContentBytes.Length), config.LogVerbosity); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine("{0}\nMessage might be not encrypted, returning as is...", ex.ToString()); + outputBytes = fileContentBytes; + } + } + PNDownloadFileResult result = new PNDownloadFileResult + { + FileBytes = outputBytes, + FileName = currentFileName + }; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + callback.OnResponse(result, status); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, null); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDownloadFileOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + private async Task> ProcessFileDownloadRequest() + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(currentFileId)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(currentFileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; + returnValue.Status = errStatus; + return returnValue; + } + + RequestState requestState = new RequestState + { + ResponseType = PNOperationType.PNDownloadFileOperation, + Reconnect = false, + EndPointOperation = this + }; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDownloadFileOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) + { + var fileContentBytes = transportResponse.Content; + if (fileContentBytes != null) { + byte[] outputBytes; + requestState.GotJsonResponse = true; + if (string.IsNullOrEmpty(currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) { + outputBytes = fileContentBytes; + } else { + CryptoModule currentCryptoModule = !string.IsNullOrEmpty(currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); + try { + outputBytes = currentCryptoModule.Decrypt(fileContentBytes); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), fileContentBytes.Length), config.LogVerbosity); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine("{0}\nFile content might be not encrypted, returning as is...", ex.ToString()); + outputBytes = fileContentBytes; + returnValue.Status = new PNStatus { Error = true, ErrorData = new PNErrorData("Decryption error", ex) }; + } + } + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + PNDownloadFileResult result = new PNDownloadFileResult + { + FileBytes = outputBytes, + FileName = currentFileName + }; + returnValue.Result = result; + returnValue.Status = status; + } else { + PNStatus errorStatus = GetStatusIfError(requestState, null); + returnValue.Status = errorStatus; + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDownloadFileOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + var pathSegments = new List + { + "v1", + "files", + config.SubscribeKey, + "channels", + channelName, + "files", + currentFileId, + currentFileName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDownloadFileOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/GenerateFileUploadUrlOperation.cs b/src/Api/PubnubApi/EndPoint/Files/GenerateFileUploadUrlOperation.cs index bed5b7551..618b8fd8b 100644 --- a/src/Api/PubnubApi/EndPoint/Files/GenerateFileUploadUrlOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/GenerateFileUploadUrlOperation.cs @@ -1,179 +1,182 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - internal class GenerateFileUploadUrlOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private Dictionary queryParam; - - private string channelName; - private string sendFileName; - - public GenerateFileUploadUrlOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public GenerateFileUploadUrlOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public GenerateFileUploadUrlOperation FileName(string fileName) - { - this.sendFileName = fileName; - return this; - } - - public GenerateFileUploadUrlOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - - if (string.IsNullOrEmpty(this.sendFileName)) - { - throw new ArgumentException("Missing File Name"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GenerateFileUploadUrl(this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GenerateFileUploadUrl(this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GenerateFileUploadUrl(this.queryParam).ConfigureAwait(false); - } - - private void GenerateFileUploadUrl(Dictionary externalQueryParam, PNCallback callback) - { - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - if (!string.IsNullOrEmpty(sendFileName)) - { - messageEnvelope.Add("name", sendFileName); - } - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGenerateFileUploadUrlRequest("POST", postMessage, this.channelName, externalQueryParam); - - UrlProcessRequest(request, requestState, false, postData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> GenerateFileUploadUrl(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - if (string.IsNullOrEmpty(sendFileName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; - ret.Status = errStatus; - return ret; - } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - if (!string.IsNullOrEmpty(sendFileName)) - { - messageEnvelope.Add("name", sendFileName); - } - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGenerateFileUploadUrlRequest("POST", postMessage, this.channelName, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, postData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGenerateFileUploadUrlResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - } + internal class GenerateFileUploadUrlOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private Dictionary queryParam; + + private string channelName; + private string sendFileName; + + public GenerateFileUploadUrlOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + PubnubInstance = instance; + } + + public GenerateFileUploadUrlOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public GenerateFileUploadUrlOperation FileName(string fileName) + { + this.sendFileName = fileName; + return this; + } + + public GenerateFileUploadUrlOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + if (string.IsNullOrEmpty(this.sendFileName)) { + throw new ArgumentException("Missing File Name"); + } + + GenerateFileUploadUrl(callback); + } + + public async Task> ExecuteAsync() + { + return await GenerateFileUploadUrl().ConfigureAwait(false); + } + + private void GenerateFileUploadUrl(PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.UsePostMethod = true; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGenerateFileUploadUrlOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGenerateFileUploadUrlOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> GenerateFileUploadUrl() + { + PNResult returnValue = new PNResult(); + if (string.IsNullOrEmpty(sendFileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; + returnValue.Status = errStatus; + return returnValue; + } + + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; + requestState.Reconnect = false; + requestState.UsePostMethod = true; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGenerateFileUploadUrlOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + Tuple jsonAndStatusTuple; + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + jsonAndStatusTuple = new Tuple(responseString, status); + } else { + jsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = jsonAndStatusTuple.Item2; + string json = jsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGenerateFileUploadUrlResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGenerateFileUploadUrlOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "files", + config.SubscribeKey, + "channels", + channelName, + "generate-upload-url" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGenerateFileUploadUrlOperation, false, false, false)); + } + } + } + Dictionary messageEnvelope = new Dictionary(); + if (!string.IsNullOrEmpty(sendFileName)) { + messageEnvelope.Add("name", sendFileName); + } + string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + var requestParameter = new RequestParameter() { + RequestType = Constants.POST, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = postMessage + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/GetFileUrlOperation.cs b/src/Api/PubnubApi/EndPoint/Files/GetFileUrlOperation.cs index 15f71572a..baced70dd 100644 --- a/src/Api/PubnubApi/EndPoint/Files/GetFileUrlOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/GetFileUrlOperation.cs @@ -1,24 +1,15 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetFileUrlOperation : PubnubCoreBase + public class GetFileUrlOperation : PubnubCoreBase { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private PNCallback savedCallback; private Dictionary queryParam; @@ -27,29 +18,13 @@ public class GetFileUrlOperation : PubnubCoreBase private string currentFileId; private string currentFileName; - public GetFileUrlOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public GetFileUrlOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } + PubnubInstance = instance; } public GetFileUrlOperation Channel(string channel) @@ -90,21 +65,8 @@ public void Execute(PNCallback callback) { throw new ArgumentException("Missing File Name"); } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessGetFileUrl(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessGetFileUrl(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif + this.savedCallback = callback; + ProcessGetFileUrl(this.queryParam, savedCallback); } public async Task> ExecuteAsync() @@ -114,67 +76,84 @@ public async Task> ExecuteAsync() internal void Retry() { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessGetFileUrl(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessGetFileUrl(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif + ProcessGetFileUrl(this.queryParam, savedCallback); } private void ProcessGetFileUrl(Dictionary externalQueryParam, PNCallback callback) { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNFileUrlOperation); - + var requestParameter = CreateRequestParameter(); PNFileUrlResult result = new PNFileUrlResult(); - result.Url = request.ToString(); - + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNFileUrlOperation); + result.Url = transportRequest.RequestUrl; PNStatus status = new PNStatus { Error = false, StatusCode = 200 }; - callback.OnResponse(result, status); } - private async Task> ProcessGetFileUrl(Dictionary externalQueryParam) + private Task> ProcessGetFileUrl(Dictionary externalQueryParam) { - PNResult ret = new PNResult(); + var requestParameter = CreateRequestParameter(); + PNResult returnValue = new PNResult(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNFileUrlOperation); if (string.IsNullOrEmpty(this.currentFileId)) { PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; - ret.Status = errStatus; - return ret; + returnValue.Status = errStatus; + return Task.FromResult(returnValue); } if (string.IsNullOrEmpty(this.currentFileName)) { PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; - ret.Status = errStatus; - return ret; + returnValue.Status = errStatus; + return Task.FromResult(returnValue); } - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNFileUrlOperation); - PNFileUrlResult result = new PNFileUrlResult(); - result.Url = request.ToString(); + result.Url = transportRequest.RequestUrl; PNStatus status = new PNStatus { Error = false, StatusCode = 200 }; - ret.Result = result; - ret.Status = status; - await Task.Factory.StartNew(() =>{ }).ConfigureAwait(false);//dummy stmt. + returnValue.Result = result; + returnValue.Status = status; - return ret; + return Task.FromResult(returnValue); } + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "files", + config.SubscribeKey, + "channels", + channelName, + "files", + currentFileId, + currentFileName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) + { + foreach (KeyValuePair kvp in queryParam) + { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) + { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDownloadFileOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } } } diff --git a/src/Api/PubnubApi/EndPoint/Files/ListFilesOperation.cs b/src/Api/PubnubApi/EndPoint/Files/ListFilesOperation.cs index 68f5b264b..d21f8a19f 100644 --- a/src/Api/PubnubApi/EndPoint/Files/ListFilesOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/ListFilesOperation.cs @@ -1,197 +1,194 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Globalization; namespace PubnubApi.EndPoint { - public class ListFilesOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNCallback savedCallback; - private Dictionary queryParam; - - private string channelName; - private string nextFileBatchToken; - private int limitFileCount=-1; - - public ListFilesOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public ListFilesOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public ListFilesOperation Limit(int count) - { - this.limitFileCount = count; - return this; - } - - public ListFilesOperation Next(string nextToken) - { - this.nextFileBatchToken = nextToken; - return this; - } - - public ListFilesOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - if (string.IsNullOrEmpty(this.channelName)) - { - throw new ArgumentException("Missing Channel Name"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessListFilesRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessListFilesRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessListFilesRequest(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessListFilesRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessListFilesRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessListFilesRequest(Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildListFilesReqest("GET", "", this.channelName, this.limitFileCount, this.nextFileBatchToken, externalQueryParam, PNOperationType.PNListFilesOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNListFilesOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> ProcessListFilesRequest(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.channelName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Channel name", new ArgumentException("Invalid Channel name")) }; - ret.Status = errStatus; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildListFilesReqest("GET", "", this.channelName, this.limitFileCount, this.nextFileBatchToken, externalQueryParam, PNOperationType.PNListFilesOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNListFilesOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNListFilesResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - } + public class ListFilesOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNCallback savedCallback; + private Dictionary queryParam; + + private string channelName; + private string nextFileBatchToken; + private int limitFileCount = -1; + + public ListFilesOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public ListFilesOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public ListFilesOperation Limit(int count) + { + this.limitFileCount = count; + return this; + } + + public ListFilesOperation Next(string nextToken) + { + this.nextFileBatchToken = nextToken; + return this; + } + + public ListFilesOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + if (string.IsNullOrEmpty(this.channelName)) { + throw new ArgumentException("Missing Channel Name"); + } + this.savedCallback = callback; + ProcessListFilesRequest(savedCallback); + } + + public async Task> ExecuteAsync() + { + return await ProcessListFilesRequest().ConfigureAwait(false); + } + + internal void Retry() + { + ProcessListFilesRequest(savedCallback); + } + + private void ProcessListFilesRequest(PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNListFilesOperation; + requestState.PubnubCallback = callback; + requestState.UsePostMethod = false; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNListFilesOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNListFilesOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> ProcessListFilesRequest() + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(this.channelName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Channel name", new ArgumentException("Invalid Channel name")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNListFilesOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = false; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNListFilesOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + Tuple jsonAndStatusTuple; + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + jsonAndStatusTuple = new Tuple(responseString, status); + } else { + jsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = jsonAndStatusTuple.Item2; + string json = jsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNListFilesResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNListFilesOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "files", + config.SubscribeKey, + "channels", + channelName, + "files" + }; + + Dictionary requestQueryStringParams = new Dictionary + { + { "limit", (limitFileCount <= -1) ? "100" : limitFileCount.ToString(CultureInfo.InvariantCulture) } + }; + if (!string.IsNullOrEmpty(nextFileBatchToken)) { + requestQueryStringParams.Add("next", nextFileBatchToken); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNListFilesOperation, false, false, false)); + } + } + } + + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs b/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs index 5fc623dee..5f7c5083d 100644 --- a/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs +++ b/src/Api/PubnubApi/EndPoint/Files/PublishFileMessage.cs @@ -1,284 +1,281 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Globalization; +using PubnubApi.Security.Crypto; +using PubnubApi.Security.Crypto.Cryptors; +using System.Net; namespace PubnubApi.EndPoint { - public class PublishFileMessageOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNCallback savedCallback; - private Dictionary queryParam; - - private string channelName; - private string currentFileId; - private string currentFileName; - private object msg; - private bool storeInHistory = true; - private Dictionary userMetadata; - private int ttl = -1; - - public PublishFileMessageOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public PublishFileMessageOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public PublishFileMessageOperation Message(object message) - { - this.msg = message; - return this; - } - - public PublishFileMessageOperation ShouldStore(bool store) - { - this.storeInHistory = store; - return this; - } - - public PublishFileMessageOperation Meta(Dictionary metadata) - { - this.userMetadata = metadata; - return this; - } - - public PublishFileMessageOperation Ttl(int ttl) - { - this.ttl = ttl; - return this; - } - - public PublishFileMessageOperation FileId(string id) - { - this.currentFileId = id; - return this; - } - - public PublishFileMessageOperation FileName(string name) - { - this.currentFileName = name; - return this; - } - - public PublishFileMessageOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - - if (string.IsNullOrEmpty(this.currentFileId) || string.IsNullOrEmpty(this.currentFileName)) - { - throw new ArgumentException("Missing File Id or Name"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessFileMessagePublish(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessFileMessagePublish(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessFileMessagePublish(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessFileMessagePublish(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessFileMessagePublish(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessFileMessagePublish(Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")); - callback.OnResponse(null, status); - return; - } - - Dictionary publishPayload = new Dictionary(); - if (this.msg != null && !string.IsNullOrEmpty(this.msg.ToString())) - { - publishPayload.Add("message", this.msg); - } - publishPayload.Add("file", new Dictionary { - { "id", currentFileId }, - { "name", currentFileName } }); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNPublishFileMessageOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildPublishFileMessageRequest("GET", "", this.channelName, publishPayload, this.storeInHistory, this.ttl, this.userMetadata, null, externalQueryParam); - - string json = ""; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - json = r.Result.Item1; - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - ProcessResponseCallbacks(result, requestState); - } - else - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishFileMessageOperation, category, requestState, 400, new PNException(json)); - if (requestState.PubnubCallback != null) - { - requestState.PubnubCallback.OnResponse(default(PNPublishFileMessageResult), status); - } - } - } - else - { - ProcessResponseCallbacks(result, requestState); - } - } - } - - private async Task> ProcessFileMessagePublish(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - if (string.IsNullOrEmpty(this.currentFileId) || string.IsNullOrEmpty(this.currentFileName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id or Name", new ArgumentException("Missing File Id or Name")) }; - ret.Status = errStatus; - return ret; - } - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; - } - - Dictionary publishPayload = new Dictionary(); - if (this.msg != null && !string.IsNullOrEmpty(this.msg.ToString())) - { - publishPayload.Add("message", this.msg); - } - publishPayload.Add("file", new Dictionary { - { "id", currentFileId }, - { "name", currentFileName } }); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNPublishFileMessageOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildPublishFileMessageRequest("GET", "", this.channelName, publishPayload, this.storeInHistory, this.ttl, this.userMetadata, null, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPublishFileMessageResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - } - } - - return ret; - } - - } + public class PublishFileMessageOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNCallback savedCallback; + private Dictionary queryParam; + + private string channelName; + private string currentFileId; + private string currentFileName; + private object publishMessageContent; + private bool storeInHistory = true; + private Dictionary userMetadata; + private int ttl = -1; + + public PublishFileMessageOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public PublishFileMessageOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public PublishFileMessageOperation Message(object message) + { + this.publishMessageContent = message; + return this; + } + + public PublishFileMessageOperation ShouldStore(bool store) + { + this.storeInHistory = store; + return this; + } + + public PublishFileMessageOperation Meta(Dictionary metadata) + { + this.userMetadata = metadata; + return this; + } + + public PublishFileMessageOperation Ttl(int ttl) + { + this.ttl = ttl; + return this; + } + + public PublishFileMessageOperation FileId(string id) + { + this.currentFileId = id; + return this; + } + + public PublishFileMessageOperation FileName(string name) + { + this.currentFileName = name; + return this; + } + + public PublishFileMessageOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + if (string.IsNullOrEmpty(this.currentFileId) || string.IsNullOrEmpty(this.currentFileName)) { + throw new ArgumentException("Missing File Id or Name"); + } + this.savedCallback = callback; + ProcessFileMessagePublish(this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await ProcessFileMessagePublish(this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + ProcessFileMessagePublish(this.queryParam, savedCallback); + } + + private void ProcessFileMessagePublish(Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")); + callback.OnResponse(null, status); + return; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNPublishFileMessageOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNPublishOperation); + + PubnubInstance.transportMiddleware.Send(transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + if (result != null && result.Count >= 3) { + int publishStatus; + var _ = int.TryParse(result[0].ToString(), out publishStatus); + if (publishStatus == 1) { + ProcessResponseCallbacks(result, requestState); + } else { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishFileMessageOperation, category, requestState, 400, new PNException(responseString)); + requestState.PubnubCallback.OnResponse(default, status); + + } + } else { + ProcessResponseCallbacks(result, requestState); + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishFileMessageOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> ProcessFileMessagePublish(Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + if (string.IsNullOrEmpty(this.currentFileId) || string.IsNullOrEmpty(this.currentFileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id or Name", new ArgumentException("Missing File Id or Name")) }; + returnValue.Status = errStatus; + return returnValue; + } + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; + returnValue.Status = errStatus; + return returnValue; + } + + var requestParameter = CreateRequestParameter(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNPublishFileMessageOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNPublishFileMessageOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List result = ProcessJsonResponse(requestState, json); + + if (result != null && result.Count >= 3) { + int publishStatus; + var _ = int.TryParse(result[0].ToString(), out publishStatus); + if (publishStatus == 1) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPublishFileMessageResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishFileMessageOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary publishPayload = new Dictionary(); + if (this.publishMessageContent != null && !string.IsNullOrEmpty(this.publishMessageContent.ToString())) { + publishPayload.Add("message", this.publishMessageContent); + } + publishPayload.Add("file", new Dictionary { + { "id", currentFileId }, + { "name", currentFileName } }); + List pathSegments = new List + { + "v1", + "files", + "publish-file", + config.PublishKey, + config.SubscribeKey, + "0", + channelName, + "0", + PrepareContent(publishPayload) + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (userMetadata != null) { + string jsonMetaData = jsonLibrary.SerializeToJsonString(userMetadata); + requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, PNOperationType.PNPublishFileMessageOperation, false, false, false)); + } + + if (storeInHistory && ttl >= 0) { + requestQueryStringParams.Add("tt1", ttl.ToString(CultureInfo.InvariantCulture)); + } + + if (!storeInHistory) { + requestQueryStringParams.Add("store", "0"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNPublishFileMessageOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + PathSegment = pathSegments, + RequestType = Constants.GET, + Query = requestQueryStringParams + }; + return requestParameter; + } + + private string PrepareContent(object originalMessage) + { + string message = jsonLibrary.SerializeToJsonString(originalMessage); + if (config.CryptoModule != null || config.CipherKey.Length > 0) { + config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); + string encryptMessage = config.CryptoModule.Encrypt(message); + message = jsonLibrary.SerializeToJsonString(encryptMessage); + } + return message; + } + + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs index b6101ed69..78c22c900 100644 --- a/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs @@ -2,543 +2,597 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; -using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; namespace PubnubApi.EndPoint { - public class SendFileOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private Dictionary queryParam; - - private string channelName; - private object publishMessage; - private string sendFileFullPath; - private string sendFileName = ""; - private byte[] sendFileBytes = null; - private string currentFileCipherKey; - private string currentFileId; - private bool storeInHistory = true; - private Dictionary userMetadata; - private int ttl = -1; - - public SendFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public SendFileOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public SendFileOperation Message(object message) - { - this.publishMessage = message; - return this; - } - - public SendFileOperation ShouldStore(bool store) - { - this.storeInHistory = store; - return this; - } - - public SendFileOperation Meta(Dictionary metadata) - { - this.userMetadata = metadata; - return this; - } - - public SendFileOperation Ttl(int ttl) - { - this.ttl = ttl; - return this; - } - - public SendFileOperation File(string fileNameWithFullPath) - { - this.sendFileFullPath = fileNameWithFullPath; -#if !NETSTANDARD10 && !NETSTANDARD11 - // manually set filename should take precedence - if (System.IO.File.Exists(fileNameWithFullPath) && string.IsNullOrEmpty(sendFileName)) - { - sendFileName = System.IO.Path.GetFileName(fileNameWithFullPath); - } - return this; -#else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); -#endif - } - - public SendFileOperation File(byte[] byteArray) - { - this.sendFileBytes = byteArray ?? throw new ArgumentException("File byte array not provided."); - return this; - } - - public SendFileOperation FileName(string fileName) - { - if (string.IsNullOrEmpty(fileName)) - { - throw new ArgumentException("File name is missing"); - } - - if (fileName.Trim() != fileName) - { - throw new ArgumentException("File name should not contain leading or trailing whitespace"); - } - - this.sendFileName = fileName; - return this; - } - - public SendFileOperation CipherKey(string cipherKeyForFile) - { - this.currentFileCipherKey = cipherKeyForFile; - return this; - } - - public SendFileOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - - if (string.IsNullOrEmpty(this.sendFileName)) - { - throw new ArgumentException("Missing File"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessFileUpload(this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessFileUpload(this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessFileUpload(this.queryParam).ConfigureAwait(false); - } - - private void ProcessFileUpload(Dictionary externalQueryParam, PNCallback callback) - { - PNResult generateFileUploadUrl = GenerateFileUploadUrl(externalQueryParam).Result; - PNGenerateFileUploadUrlResult generateFileUploadUrlResult = generateFileUploadUrl.Result; - PNStatus generateFileUploadUrlStatus = generateFileUploadUrl.Status; - if (generateFileUploadUrlStatus.Error || generateFileUploadUrlResult == null) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Error in GenerateFileUploadUrl. Try again.", new ArgumentException("Error in GenerateFileUploadUrl. Try again.")) }; - if (callback != null) - { - callback.OnResponse(null, errStatus); - } - return; - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNFileUploadOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = true; - - byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath); - - - string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); - string contentType = "multipart/form-data; boundary=" + dataBoundary; - CryptoModule currentCryptoModule = null; - if (!string.IsNullOrEmpty(this.currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null) - { - currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); - } - byte[] postData = GetMultipartFormData(sendFileByteArray,generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog); - - string json; - UrlProcessRequest(new Uri(generateFileUploadUrlResult.FileUploadRequest.Url), requestState, false, postData, contentType).ContinueWith(r => - { - json = r.Result.Item1; - if (!string.IsNullOrEmpty(json) && string.Equals(json,"{}", StringComparison.OrdinalIgnoreCase)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - //do internal publish after successful file upload - - Dictionary publishPayload = new Dictionary(); - if (this.publishMessage != null && !string.IsNullOrEmpty(this.publishMessage.ToString())){ - publishPayload.Add("message", this.publishMessage); - } - publishPayload.Add("file", new Dictionary { - { "id", generateFileUploadUrlResult.FileId }, - { "name", generateFileUploadUrlResult.FileName } }); - - int publishFileRetryLimit = config.FileMessagePublishRetryLimit; - int currentFileRetryCount = 0; - bool publishFailed = false; - do - { - currentFileRetryCount += 1; - PNResult publishFileMessageResponse = PublishFileMessage(publishPayload, queryParam).Result; - PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; - PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; - if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) - { - publishFailed = false; - PNFileUploadResult result = new PNFileUploadResult(); - result.Timetoken = publishFileMessage.Timetoken; - result.FileId = generateFileUploadUrlResult.FileId; - result.FileName = generateFileUploadUrlResult.FileName; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - r.Result.Item2.Error = false; - callback.OnResponse(result, r.Result.Item2); - } - else - { - publishFailed = true; - if (currentFileRetryCount == publishFileRetryLimit) - { - callback.OnResponse(null, publishFileMessageStatus); - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); -#if !NET35 && !NET40 - Task.Delay(1000).Wait(); -#else - Thread.Sleep(1000); -#endif - } - } - while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> ProcessFileUpload(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.sendFileName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File", new ArgumentException("Missing File")) }; - ret.Status = errStatus; - return ret; - } - - - PNResult generateFileUploadUrl = await GenerateFileUploadUrl(externalQueryParam).ConfigureAwait(false); - PNGenerateFileUploadUrlResult generateFileUploadUrlResult = generateFileUploadUrl.Result; - PNStatus generateFileUploadUrlStatus = generateFileUploadUrl.Status; - if (generateFileUploadUrlStatus.Error || generateFileUploadUrlResult == null) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Error in GenerateFileUploadUrl. Try again.", new ArgumentException("Error in GenerateFileUploadUrl. Try again.")) }; - ret.Status = errStatus; - return ret; - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNFileUploadOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = true; - - byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath); - - string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); - string contentType = "multipart/form-data; boundary=" + dataBoundary; - CryptoModule currentCryptoModule = null; - if (!string.IsNullOrEmpty(this.currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null) - { - currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); - } - byte[] postData = GetMultipartFormData(sendFileByteArray, generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(new Uri(generateFileUploadUrlResult.FileUploadRequest.Url), requestState, false, postData, contentType).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); //do internal publish after successful file upload - - Dictionary publishPayload = new Dictionary(); - if (this.publishMessage != null && !string.IsNullOrEmpty(this.publishMessage.ToString())) - { - publishPayload.Add("message", this.publishMessage); - } - currentFileId = generateFileUploadUrlResult.FileId; - publishPayload.Add("file", new Dictionary { - { "id", generateFileUploadUrlResult.FileId }, - { "name", generateFileUploadUrlResult.FileName } }); - - int publishFileRetryLimit = config.FileMessagePublishRetryLimit; - int currentFileRetryCount = 0; - bool publishFailed = false; - do - { - currentFileRetryCount += 1; - PNResult publishFileMessageResponse = await PublishFileMessage(publishPayload, queryParam).ConfigureAwait(false); - PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; - PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; - if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) - { - publishFailed = false; - PNFileUploadResult result = new PNFileUploadResult(); - result.Timetoken = publishFileMessage.Timetoken; - result.FileId = generateFileUploadUrlResult.FileId; - result.FileName = generateFileUploadUrlResult.FileName; - ret.Result = result; - ret.Status.Error = false; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); //do internal publish after successful file upload - } - else - { - publishFailed = true; - ret.Status = publishFileMessageStatus; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); -#if !NET35 && !NET40 - Task.Delay(1000).Wait(); -#else - Thread.Sleep(1000); -#endif - } - } - while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); - } - - return ret; - } - - private async Task> GenerateFileUploadUrl(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - if (!string.IsNullOrEmpty(sendFileName)) - { - messageEnvelope.Add("name", sendFileName); - } - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGenerateFileUploadUrlRequest("POST", postMessage, this.channelName, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, postData, "application/json").ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGenerateFileUploadUrlResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private async Task> PublishFileMessage(object message, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildPublishFileMessageRequest("GET", "", this.channelName, message, this.storeInHistory, this.ttl, this.userMetadata, null, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { this.channelName }; - requestState.ResponseType = PNOperationType.PNPublishFileMessageOperation; - requestState.PubnubCallback = null; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - string json = ""; - - await UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPublishFileMessageResult publishResult = responseBuilder.JsonToObject(result, true); - StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - if (publishResult != null) - { - ret.Result = publishResult; - PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); - ret.Status = status; - } - else - { - PNException ex = new PNException("File has been upload but the notification couldn't be sent to the subscribed users"); - PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNUnknownCategory, requestState, (int)HttpStatusCode.BadRequest, ex); - status.AdditonalData = new Dictionary { {"FileId", currentFileId }, {"FileName", sendFileName } }; - ret.Status = status; - } - } - else - { - ret.Status = r.Result.Item2; - if (ret.Status == null) - { - PNException ex = new PNException("PublishFileMessage failed."); - StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNUnknownCategory, requestState, (int)HttpStatusCode.BadRequest, ex); - status.AdditonalData = new Dictionary { { "FileId", currentFileId }, { "FileName", sendFileName } }; - ret.Status = status; - } - } - }, TaskContinuationOptions.ExecuteSynchronously); - - return ret; - } - - private static byte[] GetByteArrayFromFilePath(string filePath) - { -#if !NETSTANDARD10 && !NETSTANDARD11 - byte[] byteArray = null; - if (!string.IsNullOrEmpty(filePath)) - { - byteArray = System.IO.File.ReadAllBytes(filePath); - } - return byteArray; -#else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); -#endif - - } - - private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string fileName, Dictionary formFields, string dataBoundary, CryptoModule currentCryptoModule, PNConfiguration config, IPubnubLog pubnubLog) - { - byte[] ret = null; - string fileContentType = "application/octet-stream"; - using (Stream dataStream = new System.IO.MemoryStream()) - { - foreach (var kvp in formFields) - { - if (kvp.Key == "Content-Type" && kvp.Value != null && !string.IsNullOrEmpty(kvp.Value.ToString())) - { - fileContentType = kvp.Value.ToString(); - } - string postParamData = string.Format(CultureInfo.InvariantCulture, "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", - dataBoundary, - kvp.Key, - kvp.Value); - byte[] postParam = Encoding.UTF8.GetBytes(postParamData); - dataStream.Write(postParam, 0, postParam.Length); - - string emptyLine = "\r\n"; - byte[] emptyData = Encoding.UTF8.GetBytes(emptyLine); - dataStream.Write(emptyData, 0, emptyData.Length); - } - string header = string.Format(CultureInfo.InvariantCulture, "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", - dataBoundary, - "file", - fileName, - fileContentType); - byte[] postHeaderData = Encoding.UTF8.GetBytes(header); - - dataStream.Write(postHeaderData, 0, postHeaderData.Length); - if (currentCryptoModule != null) - { - try - { - byte[] encryptBytes = currentCryptoModule.Encrypt(sendFileByteArray); - dataStream.Write(encryptBytes, 0, encryptBytes.Length); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(ex.ToString()); - } - } - else - { - dataStream.Write(sendFileByteArray, 0, sendFileByteArray.Length); - } - - string footer = "\r\n--" + dataBoundary + "--\r\n"; - byte[] postFooterData = Encoding.UTF8.GetBytes(footer); - dataStream.Write(postFooterData, 0, postFooterData.Length); - - dataStream.Position = 0; - ret = new byte[dataStream.Length]; - int bytesRead = dataStream.Read(ret, 0, ret.Length); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "MultipartFormData byte count = {0}", bytesRead)); -#if NET35 || NET40 || NET45 || NET461 || NET48 - dataStream.Close(); -#endif - } - return ret; - } - } + public class SendFileOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private Dictionary queryParam; + + private string channelName; + private object publishFileMessageContent; + private string sendFileFullPath; + private string sendFileName = string.Empty; + private byte[] sendFileBytes = null; + private string currentFileCipherKey; + private string currentFileId; + private bool storeInHistory = true; + private Dictionary userMetadata; + private int ttl = -1; + + public SendFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public SendFileOperation Channel(string channel) + { + channelName = channel; + return this; + } + + public SendFileOperation Message(object message) + { + publishFileMessageContent = message; + return this; + } + + public SendFileOperation ShouldStore(bool store) + { + storeInHistory = store; + return this; + } + + public SendFileOperation Meta(Dictionary metadata) + { + userMetadata = metadata; + return this; + } + + public SendFileOperation Ttl(int ttl) + { + this.ttl = ttl; + return this; + } + + public SendFileOperation File(string fileNameWithFullPath) + { + sendFileFullPath = fileNameWithFullPath; + + if (System.IO.File.Exists(fileNameWithFullPath) && string.IsNullOrEmpty(sendFileName)) { + sendFileName = Path.GetFileName(fileNameWithFullPath); + } + return this; + } + + public SendFileOperation File(byte[] byteArray) + { + sendFileBytes = byteArray ?? throw new ArgumentException("File byte array not provided."); + return this; + } + + public SendFileOperation FileName(string fileName) + { + if (string.IsNullOrEmpty(fileName)) { + throw new ArgumentException("File name is missing"); + } + + if (fileName.Trim() != fileName) { + throw new ArgumentException("File name should not contain leading or trailing whitespace"); + } + + sendFileName = fileName; + return this; + } + + public SendFileOperation CipherKey(string cipherKeyForFile) + { + currentFileCipherKey = cipherKeyForFile; + return this; + } + + public SendFileOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + if (string.IsNullOrEmpty(sendFileName)) { + throw new ArgumentException("Missing File"); + } + ProcessFileUpload(callback); + } + + public async Task> ExecuteAsync() + { + return await ProcessFileUpload().ConfigureAwait(false); + } + + private void ProcessFileUpload(PNCallback callback) + { + PNResult generateFileUploadUrl = GenerateFileUploadUrl().Result; + PNGenerateFileUploadUrlResult generateFileUploadUrlResult = generateFileUploadUrl.Result; + PNStatus generateFileUploadUrlStatus = generateFileUploadUrl.Status; + + if (generateFileUploadUrlStatus.Error || generateFileUploadUrlResult == null) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Error in GenerateFileUploadUrl. Try again.", new ArgumentException("Error in GenerateFileUploadUrl. Try again.")) }; + if (callback != null) { + callback.OnResponse(null, errStatus); + } + return; + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl executed.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNFileUploadOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = true; + byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath); + string dataBoundary = string.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); + string contentType = "multipart/form-data; boundary=" + dataBoundary; + CryptoModule currentCryptoModule = null; + if (!string.IsNullOrEmpty(currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null) { + currentCryptoModule = !string.IsNullOrEmpty(currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); + } + byte[] postData = GetMultipartFormData(sendFileByteArray, generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog); + var transportRequest = new TransportRequest() { + RequestType = Constants.POST, + RequestUrl = generateFileUploadUrlResult.FileUploadRequest.Url, + BodyContentBytes = postData, + }; + transportRequest.Headers.Add("Content-Type", contentType); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + if (transportResponse.StatusCode == 204 && transportResponse.Error == null) + { + requestState.GotJsonResponse = true; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} file upload request executed.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + Dictionary publishPayload = new Dictionary(); + if (publishFileMessageContent != null && !string.IsNullOrEmpty(publishFileMessageContent.ToString())) { + publishPayload.Add("message", publishFileMessageContent); + } + currentFileId = generateFileUploadUrlResult.FileId; + sendFileName = generateFileUploadUrlResult.FileName; + publishPayload.Add("file", new Dictionary { + { "id", generateFileUploadUrlResult.FileId }, + { "name", generateFileUploadUrlResult.FileName } }); + int publishFileRetryLimit = config.FileMessagePublishRetryLimit; + int currentFileRetryCount = 0; + bool publishFailed; + do { + currentFileRetryCount += 1; + PNResult publishFileMessageResponse = PublishFileMessage(publishPayload, queryParam).Result; + PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; + PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; + if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) { + publishFailed = false; + PNFileUploadResult result = new PNFileUploadResult(); + result.Timetoken = publishFileMessage.Timetoken; + result.FileId = generateFileUploadUrlResult.FileId; + result.FileName = generateFileUploadUrlResult.FileName; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + var status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + callback.OnResponse(result, status); + } else { + publishFailed = true; + if (currentFileRetryCount == publishFileRetryLimit) { + callback.OnResponse(null, publishFileMessageStatus); + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); + } + } + while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFileUploadOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + } + }); + } + + private async Task> ProcessFileUpload() + { + PNResult returnValue = new PNResult(); + if (string.IsNullOrEmpty(sendFileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File", new ArgumentException("Missing File")) }; + returnValue.Status = errStatus; + return returnValue; + } + PNResult generateFileUploadUrl = await GenerateFileUploadUrl().ConfigureAwait(false); + PNGenerateFileUploadUrlResult generateFileUploadUrlResult = generateFileUploadUrl.Result; + PNStatus generateFileUploadUrlStatus = generateFileUploadUrl.Status; + if (generateFileUploadUrlStatus.Error || generateFileUploadUrlResult == null) { + returnValue.Status = generateFileUploadUrlStatus; + return returnValue; + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl executed.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNFileUploadOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = true; + byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath); + string dataBoundary = string.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); + string contentType = "multipart/form-data; boundary=" + dataBoundary; + CryptoModule currentCryptoModule = null; + if (!string.IsNullOrEmpty(currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null) { + currentCryptoModule = !string.IsNullOrEmpty(currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); + } + byte[] postData = GetMultipartFormData(sendFileByteArray, generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog); + CancellationTokenSource cts = new CancellationTokenSource(); + cts.CancelAfter(TimeSpan.FromMinutes(5)); + var transportRequest = new TransportRequest() { + RequestType = Constants.POST, + RequestUrl = generateFileUploadUrlResult.FileUploadRequest.Url, + BodyContentBytes = postData, + CancellationToken = cts.Token + }; + transportRequest.Headers.Add("Content-Type", contentType); + Tuple jsonAndStatusTuple; + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.StatusCode == 204 && transportResponse.Error == null) { + var responseString = "{}"; + PNStatus errStatus = GetStatusIfError(requestState, responseString); + if (errStatus == null) { + requestState.GotJsonResponse =true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + jsonAndStatusTuple = new Tuple(responseString, status); + } else { + jsonAndStatusTuple = new Tuple(string.Empty, errStatus); + } + } else + { + PNStatus error = new PNStatus(); + if (transportResponse.Content != null) + { + error = GetStatusIfError(requestState, Encoding.UTF8.GetString(transportResponse.Content)); + } + else + { + if (transportResponse.Error.Message != null) + { + error = GetStatusIfError(requestState, transportResponse.Error.Message); + } + else + { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(transportResponse.StatusCode, transportResponse.Error.Message); + error = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFileUploadOperation, category, requestState, transportResponse.StatusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + } + + } + jsonAndStatusTuple = new Tuple(string.Empty, error); + } + returnValue.Status = jsonAndStatusTuple.Item2; + string json = jsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); //do internal publish after successful file upload + + Dictionary publishPayload = new Dictionary(); + if (publishFileMessageContent != null && !string.IsNullOrEmpty(publishFileMessageContent.ToString())) { + publishPayload.Add("message", publishFileMessageContent); + } + currentFileId = generateFileUploadUrlResult.FileId; + sendFileName = generateFileUploadUrlResult.FileName; + publishPayload.Add("file", new Dictionary { + { "id", generateFileUploadUrlResult.FileId }, + { "name", generateFileUploadUrlResult.FileName } }); + + int publishFileRetryLimit = config.FileMessagePublishRetryLimit; + int currentFileRetryCount = 0; + bool publishFailed; + do { + currentFileRetryCount += 1; + PNResult publishFileMessageResponse = await PublishFileMessage(publishPayload, queryParam).ConfigureAwait(false); + PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; + PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; + if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) { + publishFailed = false; + PNFileUploadResult result = new PNFileUploadResult + { + Timetoken = publishFileMessage.Timetoken, + FileId = generateFileUploadUrlResult.FileId, + FileName = generateFileUploadUrlResult.FileName + }; + returnValue.Result = result; + if (returnValue.Status != null) returnValue.Status.Error = false; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> Success.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } else { + publishFailed = true; + returnValue.Status = publishFileMessageStatus; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); + await Task.Delay(1000); + } + } + while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); + } + + return returnValue; + } + + private async Task> GenerateFileUploadUrl() + { + PNResult returnValue = new PNResult(); + if (string.IsNullOrEmpty(sendFileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; + requestState.Reconnect = false; + requestState.UsePostMethod = true; + requestState.EndPointOperation = this; + + var requestParameter = CreateFileUploadUrlRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGenerateFileUploadUrlOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + Tuple jsonAndStatusTuple; + if (errorStatus == null) + { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + jsonAndStatusTuple = new Tuple(responseString, status); + } else { + jsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = jsonAndStatusTuple.Item2; + string json = jsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGenerateFileUploadUrlResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGenerateFileUploadUrlOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private async Task> PublishFileMessage(object message, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + var requestParameter = CreatePublishFileMessageRequestParameter(); + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channelName }; + requestState.ResponseType = PNOperationType.PNPublishFileMessageOperation; + requestState.PubnubCallback = null; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNPublishFileMessageOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPublishFileMessageResult publishResult = responseBuilder.JsonToObject(result, true); + StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); + if (publishResult != null) { + returnValue.Result = publishResult; + PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + returnValue.Status = status; + } else { + PNException ex = new PNException("File has been upload but the notification couldn't be sent to the subscribed users"); + PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNUnknownCategory, requestState, 400, ex); + status.AdditonalData = new Dictionary { { "FileId", currentFileId }, { "FileName", sendFileName } }; + returnValue.Status = status; + } + } else { + returnValue.Status = GetStatusIfError(requestState, responseString); + if (returnValue.Status == null) { + PNException ex = new PNException("PublishFileMessage failed."); + StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); + PNStatus status = statusBuilder.CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNUnknownCategory, requestState, 400, ex); + status.AdditonalData = new Dictionary { { "FileId", currentFileId }, { "FileName", sendFileName } }; + returnValue.Status = status; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishFileMessageOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private byte[] GetByteArrayFromFilePath(string filePath) + { + byte[] byteArray = null; + if (!string.IsNullOrEmpty(filePath) && System.IO.File.Exists(filePath)) { + byteArray = System.IO.File.ReadAllBytes(filePath); + } + else { + LoggingMethod.WriteToLog(pubnubLog, $"Error while reading file at {filePath}", config.LogVerbosity); + } + return byteArray; + } + + private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string fileName, Dictionary formFields, string dataBoundary, CryptoModule currentCryptoModule, PNConfiguration config, IPubnubLog pubnubLog) + { + byte[] multipartFormData; + string fileContentType = "application/octet-stream"; + using (Stream dataStream = new MemoryStream()) { + foreach (var kvp in formFields) { + if (kvp.Key == "Content-Type" && kvp.Value != null && !string.IsNullOrEmpty(kvp.Value.ToString())) { + fileContentType = kvp.Value.ToString(); + } + string postParamData = string.Format(CultureInfo.InvariantCulture, "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", + dataBoundary, + kvp.Key, + kvp.Value); + byte[] postParam = Encoding.UTF8.GetBytes(postParamData); + dataStream.Write(postParam, 0, postParam.Length); + + string emptyLine = "\r\n"; + byte[] emptyData = Encoding.UTF8.GetBytes(emptyLine); + dataStream.Write(emptyData, 0, emptyData.Length); + } + string header = string.Format(CultureInfo.InvariantCulture, "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", + dataBoundary, + "file", + fileName, + fileContentType); + byte[] postHeaderData = Encoding.UTF8.GetBytes(header); + + dataStream.Write(postHeaderData, 0, postHeaderData.Length); + if (currentCryptoModule != null) { + try { + byte[] encryptBytes = currentCryptoModule.Encrypt(sendFileByteArray); + dataStream.Write(encryptBytes, 0, encryptBytes.Length); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine(ex.ToString()); + } + } else { + dataStream.Write(sendFileByteArray, 0, sendFileByteArray.Length); + } + + string footer = "\r\n--" + dataBoundary + "--\r\n"; + byte[] postFooterData = Encoding.UTF8.GetBytes(footer); + dataStream.Write(postFooterData, 0, postFooterData.Length); + + dataStream.Position = 0; + multipartFormData = new byte[dataStream.Length]; + int bytesRead = dataStream.Read(multipartFormData, 0, multipartFormData.Length); + System.Diagnostics.Debug.WriteLine( $"MultipartFormData created for file content, byte-count = {bytesRead}"); + } + return multipartFormData; + } + + private RequestParameter CreateFileUploadUrlRequestParameter() + { + List pathSegments = new List + { + "v1", + "files", + config.SubscribeKey, + "channels", + channelName, + "generate-upload-url" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGenerateFileUploadUrlOperation, false, false, false)); + } + } + } + + Dictionary messageEnvelope = new Dictionary(); + if (!string.IsNullOrEmpty(sendFileName)) { + messageEnvelope.Add("name", sendFileName); + } + string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + var requestParameter = new RequestParameter() { + RequestType = Constants.POST, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = postMessage + }; + return requestParameter; + } + + private RequestParameter CreatePublishFileMessageRequestParameter() + { + Dictionary publishPayload = new Dictionary(); + if (publishFileMessageContent != null && !string.IsNullOrEmpty(publishFileMessageContent.ToString())) { + publishPayload.Add("message", publishFileMessageContent); + } + publishPayload.Add("file", new Dictionary { + { "id", currentFileId }, + { "name", sendFileName } }); + List pathSegments = new List + { + "v1", + "files", + "publish-file", + config.PublishKey, + config.SubscribeKey, + "0", + channelName, + "0", + PrepareContent(publishPayload) + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (userMetadata != null) { + string jsonMetaData = jsonLibrary.SerializeToJsonString(userMetadata); + requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, PNOperationType.PNPublishFileMessageOperation, false, false, false)); + } + + if (storeInHistory && ttl >= 0) { + requestQueryStringParams.Add("ttl", ttl.ToString(CultureInfo.InvariantCulture)); + } + + if (!storeInHistory) { + requestQueryStringParams.Add("store", "0"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNPublishFileMessageOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + PathSegment = pathSegments, + RequestType = Constants.GET, + Query = requestQueryStringParams + }; + return requestParameter; + } + + private string PrepareContent(object originalMessage) + { + string message = jsonLibrary.SerializeToJsonString(originalMessage); + if (config.CryptoModule != null || config.CipherKey.Length > 0) { + config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); + string encryptMessage = config.CryptoModule.Encrypt(message); + message = jsonLibrary.SerializeToJsonString(encryptMessage); + } + return message; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/GetAllChannelMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/GetAllChannelMetadataOperation.cs index 530c21fcf..43ece98cc 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/GetAllChannelMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/GetAllChannelMetadataOperation.cs @@ -1,202 +1,232 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Net; using System.Threading.Tasks; -#if !NET35 && !NET40 +using System.Globalization; +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetAllChannelMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private int limit = -1; - private bool includeCount; - private bool includeCustom; - private string channelsFilter; - private PNPageObject page; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetAllChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public GetAllChannelMetadataOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public GetAllChannelMetadataOperation Limit(int numberOfChannels) - { - this.limit = numberOfChannels; - return this; - } - - public GetAllChannelMetadataOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public GetAllChannelMetadataOperation IncludeCustom(bool includeCustomData) - { - this.includeCustom = includeCustomData; - return this; - } - - public GetAllChannelMetadataOperation Filter(string filterExpression) - { - this.channelsFilter = filterExpression; - return this; - } - - public GetAllChannelMetadataOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public GetAllChannelMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void GetAllChannelMetadataList(PNPageObject page, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGetAllChannelMetadataRequest("GET", "", internalPage.Next, internalPage.Prev, limit, includeCount, includeCustom, filter, sort, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetAllChannelMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> GetAllChannelMetadataList(PNPageObject page, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGetAllChannelMetadataRequest("GET", "", internalPage.Next, internalPage.Prev, limit, includeCount, includeCustom, filter, sort, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetAllChannelMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGetAllChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class GetAllChannelMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private int limit = -1; + private bool includeCount; + private bool includeCustom; + private string channelsFilter; + private PNPageObject page = new PNPageObject(); + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetAllChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public GetAllChannelMetadataOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public GetAllChannelMetadataOperation Limit(int numberOfChannels) + { + this.limit = numberOfChannels; + return this; + } + + public GetAllChannelMetadataOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public GetAllChannelMetadataOperation IncludeCustom(bool includeCustomData) + { + this.includeCustom = includeCustomData; + return this; + } + + public GetAllChannelMetadataOperation Filter(string filterExpression) + { + this.channelsFilter = filterExpression; + return this; + } + + public GetAllChannelMetadataOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public GetAllChannelMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetAllChannelMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.channelsFilter, this.sortField, this.queryParam, savedCallback); + } + + private void GetAllChannelMetadataList(PNPageObject page, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetAllChannelMetadataOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = false; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetAllChannelMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetAllChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> GetAllChannelMetadataList(PNPageObject page, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetAllChannelMetadataOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = false; + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetAllChannelMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGetAllChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetAllChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page?.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNGetAllChannelMetadataOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page?.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNGetAllChannelMetadataOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (includeCustom) { + requestQueryStringParams.Add("include", "custom"); + } + if (!string.IsNullOrEmpty(channelsFilter)) { + requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(channelsFilter, PNOperationType.PNGetAllChannelMetadataOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNGetAllChannelMetadataOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetAllChannelMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/GetAllUuidMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/GetAllUuidMetadataOperation.cs index 9770d9f3c..5f039b20d 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/GetAllUuidMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/GetAllUuidMetadataOperation.cs @@ -1,13 +1,11 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; -using System.Text; using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 +using System.Globalization; +using System.Text; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { @@ -17,31 +15,29 @@ public class GetAllUuidMetadataOperation : PubnubCoreBase private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private int limit = -1; private bool includeCount; private bool includeCustom; private string usersFilter; - private PNPageObject page; + private PNPageObject page = new PNPageObject(); private List sortField; private PNCallback savedCallback; private Dictionary queryParam; - public GetAllUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public GetAllUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; if (instance != null) { if (!ChannelRequest.ContainsKey(instance.InstanceId)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); } if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { @@ -96,20 +92,8 @@ public GetAllUuidMetadataOperation QueryParam(Dictionary customQ public void Execute(PNCallback callback) { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetUuidMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.usersFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetUuidMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.usersFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif + this.savedCallback = callback; + GetUuidMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.usersFilter, this.sortField, this.queryParam, savedCallback); } public async Task> ExecuteAsync() @@ -120,18 +104,7 @@ public async Task> ExecuteAsync() internal void Retry() { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetUuidMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.usersFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetUuidMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.usersFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif + GetUuidMetadataList(this.page, this.limit, this.includeCount, this.includeCustom, this.usersFilter, this.sortField, this.queryParam, savedCallback); } private void GetUuidMetadataList(PNPageObject page, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) @@ -140,50 +113,56 @@ private void GetUuidMetadataList(PNPageObject page, int limit, bool includeCount { throw new ArgumentException("Missing callback"); } - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGetAllUuidMetadataRequest("GET", "", internalPage.Next, internalPage.Prev, limit, includeCount, includeCustom, filter, sort, externalQueryParam); - RequestState requestState = new RequestState(); requestState.ResponseType = PNOperationType.PNGetAllUuidMetadataOperation; requestState.PubnubCallback = callback; requestState.Reconnect = false; requestState.EndPointOperation = this; - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetAllUuidMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetAllUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNGetAllUuidMetadataResult), status); + } + }); } private async Task> GetUuidMetadataList(PNPageObject page, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam) { - PNResult ret = new PNResult(); - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildGetAllUuidMetadataRequest("GET", "", internalPage.Next, internalPage.Prev, limit, includeCount, includeCustom, filter, sort, externalQueryParam); - + PNResult returnValue = new PNResult(); RequestState requestState = new RequestState(); requestState.ResponseType = PNOperationType.PNGetAllUuidMetadataOperation; requestState.Reconnect = false; - requestState.EndPointOperation = this; - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetAllUuidMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; string json = JsonAndStatusTuple.Item1; if (!string.IsNullOrEmpty(json)) { @@ -192,11 +171,77 @@ private async Task> GetUuidMetadataList(PNP PNGetAllUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); if (responseResult != null) { - ret.Result = responseResult; + returnValue.Result = responseResult; } } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetAllUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } - return ret; + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) + { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNGetAllUuidMetadataOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) + { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNGetAllUuidMetadataOperation, false, false, false)); + } + if (limit >= 0) + { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) + { + requestQueryStringParams.Add("count", "true"); + } + if (includeCustom) + { + requestQueryStringParams.Add("include", "custom"); + } + if (!string.IsNullOrEmpty(usersFilter)) + { + requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(usersFilter, PNOperationType.PNGetAllUuidMetadataOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) + { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",",sortField.ToArray()), PNOperationType.PNGetAllUuidMetadataOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) + { + foreach (KeyValuePair kvp in queryParam) + { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) + { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetAllUuidMetadataOperation, false, false, false)); + } + } + } + string queryString = UriUtil.BuildQueryString(requestQueryStringParams); + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; } } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/GetChannelMembersOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/GetChannelMembersOperation.cs index c4e52998e..98dc45115 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/GetChannelMembersOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/GetChannelMembersOperation.cs @@ -1,242 +1,262 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Net; using System.Threading.Tasks; -#if !NET35 && !NET40 +using System.Globalization; +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetChannelMembersOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string channelMetadataId = ""; - private int limit = -1; - private bool includeCount; - private string commandDelimitedIncludeOptions = ""; - private string membersFilter; - private PNPageObject page; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public GetChannelMembersOperation Channel(string channelName) - { - this.channelMetadataId = channelName; - return this; - } - - public GetChannelMembersOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public GetChannelMembersOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public GetChannelMembersOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public GetChannelMembersOperation Include(PNChannelMemberField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public GetChannelMembersOperation Filter(string filterExpression) - { - this.membersFilter = filterExpression; - return this; - } - - public GetChannelMembersOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public GetChannelMembersOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetMembersList(this.channelMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetMembersList(this.channelMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetMembersList(this.channelMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetMembersList(this.channelMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetMembersList(this.channelMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void GetMembersList(string spaceId, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) - { - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetAllMembersRequest("GET", "", spaceId, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, filter, sort, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetChannelMembersOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> GetMembersList(string spaceId, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetAllMembersRequest("GET", "", spaceId, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, filter, sort, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetChannelMembersOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid") - { - ret = "uuid"; - } - else if (enumValue.ToLowerInvariant() == "uuid_custom") - { - ret = "uuid.custom"; - } - return ret; - } - } + public class GetChannelMembersOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelId = ""; + private int limit = -1; + private bool includeCount; + private string commandDelimitedIncludeOptions = ""; + private string membersFilter; + private PNPageObject page = new PNPageObject(); + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public GetChannelMembersOperation Channel(string channelName) + { + this.channelId = channelName; + return this; + } + + public GetChannelMembersOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public GetChannelMembersOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public GetChannelMembersOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public GetChannelMembersOperation Include(PNChannelMemberField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public GetChannelMembersOperation Filter(string filterExpression) + { + this.membersFilter = filterExpression; + return this; + } + + public GetChannelMembersOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public GetChannelMembersOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + this.savedCallback = callback; + GetMembersList(this.channelId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await GetMembersList(this.channelId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetMembersList(this.channelId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membersFilter, this.sortField, this.queryParam, savedCallback); + } + + private void GetMembersList(string spaceId, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetChannelMembersOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.UsePostMethod = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetChannelMembersOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(null, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> GetMembersList(string spaceId, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetChannelMembersOperation; + requestState.Reconnect = false; + requestState.UsePostMethod = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetChannelMembersOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null&& transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private static string MapEnumValueToEndpoint(string enumValue) + { + string ret = ""; + if (enumValue.ToLowerInvariant() == "custom") { + ret = "custom"; + } else if (enumValue.ToLowerInvariant() == "uuid") { + ret = "uuid"; + } else if (enumValue.ToLowerInvariant() == "uuid_custom") { + ret = "uuid.custom"; + } + return ret; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegment = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? string.Empty : channelId, + "uuids" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNGetChannelMembersOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNGetChannelMembersOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNGetChannelMembersOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(membersFilter)) { + requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(membersFilter, PNOperationType.PNGetChannelMembersOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNGetChannelMembersOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetChannelMembersOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegment, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/GetChannelMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/GetChannelMetadataOperation.cs index 0abc78dfd..4183304cc 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/GetChannelMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/GetChannelMetadataOperation.cs @@ -1,188 +1,198 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetChannelMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string chMetadataId = ""; - private bool includeCustom; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public GetChannelMetadataOperation Channel(string channelName) - { - this.chMetadataId = channelName; - return this; - } - - public GetChannelMetadataOperation IncludeCustom(bool includeCustomData) - { - this.includeCustom = includeCustomData; - return this; - } - - public GetChannelMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - if (string.IsNullOrEmpty(this.chMetadataId)) - { - throw new ArgumentException("Missing Channel"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetSingleChannelMetadata(this.chMetadataId, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetSingleChannelMetadata(this.chMetadataId, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetSingleChannelMetadata(this.chMetadataId, this.includeCustom, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetSingleChannelMetadata(this.chMetadataId, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetSingleChannelMetadata(this.chMetadataId, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void GetSingleChannelMetadata(string spaceId, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetSingleChannelMetadataRequest("GET", "", spaceId, includeCustom, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetChannelMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> GetSingleChannelMetadata(string spaceId, bool includeCustom, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.chMetadataId)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetSingleChannelMetadataRequest("GET", "", spaceId, includeCustom, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetChannelMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGetChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class GetChannelMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelId = ""; + private bool includeCustom; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public GetChannelMetadataOperation Channel(string channelName) + { + this.channelId = channelName; + return this; + } + + public GetChannelMetadataOperation IncludeCustom(bool includeCustomData) + { + this.includeCustom = includeCustomData; + return this; + } + + public GetChannelMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + if (string.IsNullOrEmpty(this.channelId)) { + throw new ArgumentException("Missing Channel"); + } + + this.savedCallback = callback; + GetSingleChannelMetadata(this.channelId, this.includeCustom, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await GetSingleChannelMetadata(this.channelId, this.includeCustom, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetSingleChannelMetadata(this.channelId, this.includeCustom, this.queryParam, savedCallback); + } + + private void GetSingleChannelMetadata(string spaceId, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetChannelMetadataOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.UsePostMethod = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetChannelMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(null, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNGetChannelMetadataResult), status); + } + }); + } + + private async Task> GetSingleChannelMetadata(string spaceId, bool includeCustom, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(this.channelId)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetChannelMetadataOperation; + requestState.Reconnect = false; + requestState.UsePostMethod = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetChannelMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGetChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? string.Empty : channelId + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (includeCustom) { + requestQueryStringParams.Add("include", "custom"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetChannelMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } + diff --git a/src/Api/PubnubApi/EndPoint/Objects/GetMembershipsOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/GetMembershipsOperation.cs index 6ffd8db66..f62106826 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/GetMembershipsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/GetMembershipsOperation.cs @@ -1,253 +1,243 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Net; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Globalization; +using System.Text; namespace PubnubApi.EndPoint { - public class GetMembershipsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string uuidMetadataId = ""; - private int limit = -1; - private bool includeCount; - private string commandDelimitedIncludeOptions = ""; - private string membershipsFilter; - private PNPageObject page; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public GetMembershipsOperation Uuid(string id) - { - this.uuidMetadataId = id; - return this; - } - - public GetMembershipsOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public GetMembershipsOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public GetMembershipsOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public GetMembershipsOperation Include(PNMembershipField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public GetMembershipsOperation Filter(string filterExpression) - { - this.membershipsFilter = filterExpression; - return this; - } - - public GetMembershipsOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public GetMembershipsOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetMembershipsList(this.uuidMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetMembershipsList(this.uuidMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetMembershipsList(this.uuidMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetMembershipsList(this.uuidMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetMembershipsList(this.uuidMetadataId, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void GetMembershipsList(string uuid, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetAllMembershipsRequest("GET", "", uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, filter, sort, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetMembershipsOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - - } - - private async Task> GetMembershipsList(string uuid, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetAllMembershipsRequest("GET", "", uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, filter, sort, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetMembershipsOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "channel") - { - ret = "channel"; - } - else if (enumValue.ToLowerInvariant() == "channel_custom") - { - ret = "channel.custom"; - } - return ret; - } - } + public class GetMembershipsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string uuid = string.Empty; + private int limit = -1; + private bool includeCount; + private string commandDelimitedIncludeOptions = ""; + private string membershipsFilter; + private PNPageObject page = new PNPageObject(); + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public GetMembershipsOperation Uuid(string id) + { + this.uuid = id; + return this; + } + + public GetMembershipsOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public GetMembershipsOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public GetMembershipsOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public GetMembershipsOperation Include(PNMembershipField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public GetMembershipsOperation Filter(string filterExpression) + { + this.membershipsFilter = filterExpression; + return this; + } + + public GetMembershipsOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public GetMembershipsOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + this.savedCallback = callback; + GetMembershipsList(this.uuid, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await GetMembershipsList(this.uuid, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetMembershipsList(this.uuid, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.membershipsFilter, this.sortField, this.queryParam, savedCallback); + } + + private void GetMembershipsList(string uuid, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetMembershipsOperation; + requestState.PubnubCallback = callback; + requestState.UsePostMethod = false; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetMembershipsOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(null, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNMembershipsResult), status); + } + }); + } + + private async Task> GetMembershipsList(string uuid, PNPageObject page, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetMembershipsOperation; + requestState.UsePostMethod = false; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetMembershipsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(uuid) ? string.Empty : uuid, + "channels" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNGetMembershipsOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNGetMembershipsOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNGetMembershipsOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(membershipsFilter)) { + requestQueryStringParams.Add("filter", UriUtil.EncodeUriComponent(membershipsFilter, PNOperationType.PNGetMembershipsOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNGetMembershipsOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetMembershipsOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/GetUuidMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/GetUuidMetadataOperation.cs index ebb029bab..683e99144 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/GetUuidMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/GetUuidMetadataOperation.cs @@ -1,185 +1,195 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; +using System.Threading.Tasks; using System.Text; using System.Threading; -using System.Threading.Tasks; -#if !NET35 && !NET40 using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetUuidMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private bool includeCustom; - private string usrUuid = ""; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public GetUuidMetadataOperation Uuid(string uuid) - { - this.usrUuid = uuid; - return this; - } - - public GetUuidMetadataOperation IncludeCustom(bool includeCustomData) - { - this.includeCustom = includeCustomData; - return this; - } - - public GetUuidMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetSingleUuidMetadata(this.usrUuid, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetSingleUuidMetadata(this.usrUuid, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetSingleUuidMetadata(this.usrUuid, this.includeCustom, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetSingleUuidMetadata(this.usrUuid, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetSingleUuidMetadata(this.usrUuid, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void GetSingleUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetSingleUuidMetadataRequest("GET", "", uuid, includeCustom, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetUuidMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> GetSingleUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetSingleUuidMetadataRequest("GET", "", uuid, includeCustom, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNGetUuidMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePostMethod = false; - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGetUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class GetUuidMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private bool includeCustom; + private string uuid = string.Empty; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public GetUuidMetadataOperation Uuid(string uuid) + { + this.uuid = uuid; + return this; + } + + public GetUuidMetadataOperation IncludeCustom(bool includeCustomData) + { + this.includeCustom = includeCustomData; + return this; + } + + public GetUuidMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + GetSingleUuidMetadata(this.uuid, this.includeCustom, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await GetSingleUuidMetadata(this.uuid, this.includeCustom, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetSingleUuidMetadata(this.uuid, this.includeCustom, this.queryParam, savedCallback); + } + + private void GetSingleUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetUuidMetadataOperation; + requestState.PubnubCallback = callback; + requestState.UsePostMethod = false; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetUuidMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(null, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNGetUuidMetadataResult), status); + } + }); + } + + private async Task> GetSingleUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNGetUuidMetadataOperation; + requestState.Reconnect = false; + requestState.UsePostMethod = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetUuidMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGetUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(uuid) ? string.Empty : uuid + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (includeCustom) { + requestQueryStringParams.Add("include", "custom"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetUuidMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/ManageChannelMembersOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/ManageChannelMembersOperation.cs index 82002c736..7b2a0f7d0 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/ManageChannelMembersOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/ManageChannelMembersOperation.cs @@ -3,28 +3,25 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -using Newtonsoft.Json; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class ManageChannelMembersOperation : PubnubCoreBase + public class ManageChannelMembersOperation : PubnubCoreBase { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - private string chMetadataId = ""; + private string channelId = string.Empty; private List setMember; private List delMember; - private string commandDelimitedIncludeOptions = ""; - private PNPageObject page; + private string commandDelimitedIncludeOptions = string.Empty; + private PNPageObject page = new PNPageObject(); private int limit = -1; private bool includeCount; private List sortField; @@ -32,19 +29,18 @@ public class ManageChannelMembersOperation : PubnubCoreBase private PNCallback savedCallback; private Dictionary queryParam; - public ManageChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public ManageChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; if (instance != null) { if (!ChannelRequest.ContainsKey(instance.InstanceId)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); } if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { @@ -59,7 +55,7 @@ public ManageChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggabl public ManageChannelMembersOperation Channel(string channelName) { - this.chMetadataId = channelName; + this.channelId = channelName; return this; } @@ -79,7 +75,7 @@ public ManageChannelMembersOperation Include(PNChannelMemberField[] includeOptio { if (includeOptions != null) { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); } return this; @@ -117,7 +113,7 @@ public ManageChannelMembersOperation QueryParam(Dictionary custo public void Execute(PNCallback callback) { - if (string.IsNullOrEmpty(this.chMetadataId) || string.IsNullOrEmpty(chMetadataId.Trim())) + if (string.IsNullOrEmpty(this.channelId) || string.IsNullOrEmpty(channelId.Trim())) { throw new ArgumentException("Missing Channel"); } @@ -132,156 +128,125 @@ public void Execute(PNCallback callback) throw new ArgumentException("Missing callback"); } -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif + this.savedCallback = callback; + ProcessMembersOperationRequest(this.channelId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); } public async Task> ExecuteAsync() { - return await ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); + return await ProcessMembersOperationRequest(this.channelId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); } internal void Retry() { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif + ProcessMembersOperationRequest(this.channelId, this.setMember, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); } private void ProcessMembersOperationRequest(string spaceId, List setMemberList, List removeMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) { - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - RequestState requestState = new RequestState(); requestState.ResponseType = PNOperationType.PNManageChannelMembersOperation; requestState.PubnubCallback = callback; requestState.Reconnect = false; - requestState.EndPointOperation = this; - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMemberList != null) - { - List> setMemberFormatList = new List>(); - for (int index = 0; index < setMemberList.Count; index++) - { - Dictionary currentMemberFormat = new Dictionary(); - currentMemberFormat.Add("uuid", new Dictionary { { "id", setMemberList[index].Uuid } }); - if (setMemberList[index].Custom != null) - { - currentMemberFormat.Add("custom", setMemberList[index].Custom); - } - setMemberFormatList.Add(currentMemberFormat); - } - if (setMemberFormatList.Count > 0) - { - messageEnvelope.Add("set", setMemberFormatList); - } - } - if (removeMemberList != null) - { - List>> removeMemberFormatList = new List>>(); - for (int index = 0; index < removeMemberList.Count; index++) - { - Dictionary> currentMemberFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMemberList[index])) - { - currentMemberFormat.Add("uuid", new Dictionary { { "id", removeMemberList[index] } }); - removeMemberFormatList.Add(currentMemberFormat); - } - } - if (removeMemberFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMemberFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMemberAddUpdateRemoveChannelRequest("PATCH", patchMessage, spaceId, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); + requestState.EndPointOperation = this; - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNManageChannelMembersOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNManageChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); } private async Task> ProcessMembersOperationRequest(string channel, List setMemberList, List removeMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) { - PNResult ret = new PNResult(); + PNResult returnValue = new PNResult(); if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; + returnValue.Status = errStatus; + return returnValue; } if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; + returnValue.Status = errStatus; + return returnValue; } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - RequestState requestState = new RequestState(); requestState.ResponseType = PNOperationType.PNManageChannelMembersOperation; requestState.Reconnect = false; requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; requestState.UsePatchMethod = true; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNManageChannelMembersOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) + { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) + { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNManageChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { Dictionary messageEnvelope = new Dictionary(); - if (setMemberList != null) + if (setMember != null) { List> setMemberFormatList = new List>(); - for (int index = 0; index < setMemberList.Count; index++) + for (int index = 0; index < setMember.Count; index++) { - Dictionary currentMemberFormat = new Dictionary(); - currentMemberFormat.Add("uuid", new Dictionary { { "id", setMemberList[index].Uuid } }); - if (setMemberList[index].Custom != null) + Dictionary currentMemberFormat = new Dictionary + { + { "uuid", new Dictionary { { "id", setMember[index].Uuid } } } + }; + if (setMember[index].Custom != null) { - currentMemberFormat.Add("custom", setMemberList[index].Custom); + currentMemberFormat.Add("custom", setMember[index].Custom); } setMemberFormatList.Add(currentMemberFormat); } @@ -290,15 +255,15 @@ private async Task> ProcessMembersOperationRequ messageEnvelope.Add("set", setMemberFormatList); } } - if (removeMemberList != null) + if (delMember != null) { List>> removeMemberFormatList = new List>>(); - for (int index = 0; index < removeMemberList.Count; index++) + for (int index = 0; index < delMember.Count; index++) { Dictionary> currentMemberFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMemberList[index])) + if (!string.IsNullOrEmpty(delMember[index])) { - currentMemberFormat.Add("uuid", new Dictionary { { "id", removeMemberList[index] } }); + currentMemberFormat.Add("uuid", new Dictionary { { "id", delMember[index] } }); removeMemberFormatList.Add(currentMemberFormat); } } @@ -308,53 +273,60 @@ private async Task> ProcessMembersOperationRequ } } string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMemberAddUpdateRemoveChannelRequest("PATCH", patchMessage, channel, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? "" : channelId, + "uuids" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNManageChannelMembersOperation, false, false, false)); } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") + if (!string.IsNullOrEmpty(page.Prev)) { - ret = "custom"; + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNManageChannelMembersOperation, false, false, false)); } - else if (enumValue.ToLowerInvariant() == "uuid") + if (limit >= 0) { - ret = "uuid"; + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); } - else if (enumValue.ToLowerInvariant() == "channel") + if (includeCount) { - ret = "channel"; + requestQueryStringParams.Add("count", "true"); } - else if (enumValue.ToLowerInvariant() == "channel_custom") + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { - ret = "channel.custom"; + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNManageChannelMembersOperation, false, false, false)); } - else if (enumValue.ToLowerInvariant() == "uuid_custom") + if (sortField != null && sortField.Count > 0) { - ret = "uuid.custom"; + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNManageChannelMembersOperation, false, false, false)); + } + if (queryParam != null && queryParam.Count > 0) + { + foreach (KeyValuePair kvp in queryParam) + { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) + { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNManageChannelMembersOperation, false, false, false)); + } + } } - return ret; - } + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + return requestParameter; + } } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/ManageMembershipsOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/ManageMembershipsOperation.cs index 134f81e59..a55da7c48 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/ManageMembershipsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/ManageMembershipsOperation.cs @@ -3,355 +3,298 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -using Newtonsoft.Json; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class ManageMembershipsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string uuidMetadataId = ""; - private List addMembership; - private List delMembership; - private string commandDelimitedIncludeOptions = ""; - private PNPageObject page; - private int limit = -1; - private bool includeCount; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public ManageMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public ManageMembershipsOperation Uuid(string id) - { - this.uuidMetadataId = id; - return this; - } - - public ManageMembershipsOperation Set(List membership) - { - this.addMembership = membership; - return this; - } - - public ManageMembershipsOperation Remove(List channelIdList) - { - this.delMembership = channelIdList; - return this; - } - - public ManageMembershipsOperation Include(PNMembershipField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public ManageMembershipsOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public ManageMembershipsOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public ManageMembershipsOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public ManageMembershipsOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public ManageMembershipsOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ManageChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ManageChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ManageChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ManageChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ManageChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ManageChannelMembershipWithUuid(string uuid, List setMembership, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNManageMembershipsOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMembership != null) - { - List> setMembershipFormatList = new List>(); - for (int index=0; index < setMembership.Count; index++) - { - Dictionary currentMembershipFormat = new Dictionary(); - currentMembershipFormat.Add("channel", new Dictionary { { "id", setMembership[index].Channel } }); - if (setMembership[index].Custom != null) - { - currentMembershipFormat.Add("custom", setMembership[index].Custom); - } - setMembershipFormatList.Add(currentMembershipFormat); - } - if (setMembershipFormatList.Count > 0) - { - messageEnvelope.Add("set", setMembershipFormatList); - } - } - if (removeMembership != null) - { - List>> removeMembershipFormatList = new List>>(); - for (int index=0; index < removeMembership.Count; index++) - { - Dictionary> currentMembershipFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMembership[index])) - { - currentMembershipFormat.Add("channel", new Dictionary { { "id", removeMembership[index] } }); - removeMembershipFormatList.Add(currentMembershipFormat); - } - } - if (removeMembershipFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMembershipFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMembershipSetRemoveManageUserRequest(requestState.ResponseType, "PATCH", patchMessage, uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> ManageChannelMembershipWithUuid(string uuid, List setMembership, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNManageMembershipsOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMembership != null) - { - List> setMembershipFormatList = new List>(); - for (int index = 0; index < setMembership.Count; index++) - { - Dictionary currentMembershipFormat = new Dictionary(); - currentMembershipFormat.Add("channel", new Dictionary { { "id", setMembership[index].Channel } }); - if (setMembership[index].Custom != null) - { - currentMembershipFormat.Add("custom", setMembership[index].Custom); - } - setMembershipFormatList.Add(currentMembershipFormat); - } - if (setMembershipFormatList.Count > 0) - { - messageEnvelope.Add("set", setMembershipFormatList); - } - } - if (removeMembership != null) - { - List>> removeMembershipFormatList = new List>>(); - for (int index = 0; index < removeMembership.Count; index++) - { - Dictionary> currentMembershipFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMembership[index])) - { - currentMembershipFormat.Add("channel", new Dictionary { { "id", removeMembership[index] } }); - removeMembershipFormatList.Add(currentMembershipFormat); - } - } - if (removeMembershipFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMembershipFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMembershipSetRemoveManageUserRequest(requestState.ResponseType, "PATCH", patchMessage, uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid") - { - ret = "uuid"; - } - else if (enumValue.ToLowerInvariant() == "channel") - { - ret = "channel"; - } - else if (enumValue.ToLowerInvariant() == "channel_custom") - { - ret = "channel.custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid_custom") - { - ret = "uuid.custom"; - } - return ret; - } - - } + public class ManageMembershipsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string uuid = string.Empty; + private List addMembership; + private List delMembership; + private string commandDelimitedIncludeOptions = string.Empty; + private PNPageObject page = new PNPageObject(); + private int limit = -1; + private bool includeCount; + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public ManageMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public ManageMembershipsOperation Uuid(string id) + { + this.uuid = id; + return this; + } + + public ManageMembershipsOperation Set(List membership) + { + this.addMembership = membership; + return this; + } + + public ManageMembershipsOperation Remove(List channelIdList) + { + this.delMembership = channelIdList; + return this; + } + + public ManageMembershipsOperation Include(PNMembershipField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public ManageMembershipsOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public ManageMembershipsOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public ManageMembershipsOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public ManageMembershipsOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public ManageMembershipsOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + this.savedCallback = callback; + ManageChannelMembershipWithUuid(this.uuid, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await ManageChannelMembershipWithUuid(this.uuid, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + ManageChannelMembershipWithUuid(this.uuid, this.addMembership, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); + } + + private void ManageChannelMembershipWithUuid(string uuid, List setMembership, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNManageMembershipsOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNManageMembershipsOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(null, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNManageMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> ManageChannelMembershipWithUuid(string uuid, List setMembership, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNManageMembershipsOperation; + requestState.Reconnect = false; + requestState.UsePatchMethod = true; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNManageMembershipsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNManageMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (addMembership != null) { + List> setMembershipFormatList = new List>(); + for (int index = 0; index < addMembership.Count; index++) { + Dictionary currentMembershipFormat = new Dictionary(); + currentMembershipFormat.Add("channel", new Dictionary { { "id", addMembership[index].Channel } }); + if (addMembership[index].Custom != null) { + currentMembershipFormat.Add("custom", addMembership[index].Custom); + } + setMembershipFormatList.Add(currentMembershipFormat); + } + if (setMembershipFormatList.Count > 0) { + messageEnvelope.Add("set", setMembershipFormatList); + } + } + if (delMembership != null) { + List>> removeMembershipFormatList = new List>>(); + for (int index = 0; index < delMembership.Count; index++) { + Dictionary> currentMembershipFormat = new Dictionary>(); + if (!string.IsNullOrEmpty(delMembership[index])) { + currentMembershipFormat.Add("channel", new Dictionary { { "id", delMembership[index] } }); + removeMembershipFormatList.Add(currentMembershipFormat); + } + } + if (removeMembershipFormatList.Count > 0) { + messageEnvelope.Add("delete", removeMembershipFormatList); + } + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(uuid) ? string.Empty : uuid, + "channels" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNManageMembershipsOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNManageMembershipsOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNManageMembershipsOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNManageMembershipsOperation, false, false, false)); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNManageMembershipsOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMembersOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMembersOperation.cs index 3cfa60ced..93cabe261 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMembersOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMembersOperation.cs @@ -3,315 +3,279 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -using Newtonsoft.Json; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class RemoveChannelMembersOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string chMetadataId = ""; - private List delMember; - private string commandDelimitedIncludeOptions = ""; - private PNPageObject page; - private int limit = -1; - private bool includeCount; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemoveChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public RemoveChannelMembersOperation Channel(string channelName) - { - this.chMetadataId = channelName; - return this; - } - - public RemoveChannelMembersOperation Uuids(List uuidList) - { - this.delMember = uuidList; - return this; - } - - public RemoveChannelMembersOperation Include(PNChannelMemberField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public RemoveChannelMembersOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public RemoveChannelMembersOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public RemoveChannelMembersOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public RemoveChannelMembersOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public RemoveChannelMembersOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(this.chMetadataId) || string.IsNullOrEmpty(chMetadataId.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessRemoveChannelMembersOperationRequest(this.chMetadataId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessRemoveChannelMembersOperationRequest(this.chMetadataId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessRemoveChannelMembersOperationRequest(this.chMetadataId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessRemoveChannelMembersOperationRequest(this.chMetadataId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessRemoveChannelMembersOperationRequest(this.chMetadataId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessRemoveChannelMembersOperationRequest(string spaceId, List removeMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) - { - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveChannelMembersOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (removeMemberList != null) - { - List>> removeMemberFormatList = new List>>(); - for (int index = 0; index < removeMemberList.Count; index++) - { - Dictionary> currentMemberFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMemberList[index])) - { - currentMemberFormat.Add("uuid", new Dictionary { { "id", removeMemberList[index] } }); - removeMemberFormatList.Add(currentMemberFormat); - } - } - if (removeMemberFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMemberFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMemberAddUpdateRemoveChannelRequest("PATCH", patchMessage, spaceId, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> ProcessRemoveChannelMembersOperationRequest(string channel, List removeMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveChannelMembersOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (removeMemberList != null) - { - List>> removeMemberFormatList = new List>>(); - for (int index = 0; index < removeMemberList.Count; index++) - { - Dictionary> currentMemberFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMemberList[index])) - { - currentMemberFormat.Add("uuid", new Dictionary { { "id", removeMemberList[index] } }); - removeMemberFormatList.Add(currentMemberFormat); - } - } - if (removeMemberFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMemberFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMemberAddUpdateRemoveChannelRequest("PATCH", patchMessage, channel, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid") - { - ret = "uuid"; - } - else if (enumValue.ToLowerInvariant() == "channel") - { - ret = "channel"; - } - else if (enumValue.ToLowerInvariant() == "channel_custom") - { - ret = "channel.custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid_custom") - { - ret = "uuid.custom"; - } - return ret; - } - - } + public class RemoveChannelMembersOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelId = string.Empty; + private List delMember; + private string commandDelimitedIncludeOptions = string.Empty; + private PNPageObject page = new PNPageObject(); + private int limit = -1; + private bool includeCount; + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemoveChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public RemoveChannelMembersOperation Channel(string channelName) + { + this.channelId = channelName; + return this; + } + + public RemoveChannelMembersOperation Uuids(List uuidList) + { + this.delMember = uuidList; + return this; + } + + public RemoveChannelMembersOperation Include(PNChannelMemberField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public RemoveChannelMembersOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public RemoveChannelMembersOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public RemoveChannelMembersOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public RemoveChannelMembersOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public RemoveChannelMembersOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelId) || string.IsNullOrEmpty(channelId.Trim())) { + throw new ArgumentException("Missing Channel"); + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + this.savedCallback = callback; + ProcessRemoveChannelMembersOperationRequest(this.channelId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await ProcessRemoveChannelMembersOperationRequest(this.channelId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + ProcessRemoveChannelMembersOperationRequest(this.channelId, this.delMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); + } + + private void ProcessRemoveChannelMembersOperationRequest(string spaceId, List removeMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveChannelMembersOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveChannelMembersOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> ProcessRemoveChannelMembersOperationRequest(string channel, List removeMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveChannelMembersOperation; + requestState.Reconnect = false; + requestState.UsePatchMethod = true; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveChannelMembersOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (delMember != null) { + List>> removeMemberFormatList = new List>>(); + for (int index = 0; index < delMember.Count; index++) { + Dictionary> currentMemberFormat = new Dictionary>(); + if (!string.IsNullOrEmpty(delMember[index])) { + currentMemberFormat.Add("uuid", new Dictionary { { "id", delMember[index] } }); + removeMemberFormatList.Add(currentMemberFormat); + } + } + if (removeMemberFormatList.Count > 0) { + messageEnvelope.Add("delete", removeMemberFormatList); + } + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? string.Empty : channelId, + "uuids" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNRemoveChannelMembersOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNRemoveChannelMembersOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNRemoveChannelMembersOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNRemoveChannelMembersOperation, false, false, false)); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNRemoveChannelMembersOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMetadataOperation.cs index 7529a38e2..4824cd8a2 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/RemoveChannelMetadataOperation.cs @@ -1,188 +1,197 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class RemoveChannelMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - - private string chMetadataId = ""; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemoveChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public RemoveChannelMetadataOperation Channel(string channelName) - { - this.chMetadataId = channelName; - return this; - } - - public RemoveChannelMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(this.chMetadataId) || string.IsNullOrEmpty(this.chMetadataId.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid Subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveChannelMetadata(this.chMetadataId, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveChannelMetadata(this.chMetadataId, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RemoveChannelMetadata(this.chMetadataId, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveChannelMetadata(this.chMetadataId, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveChannelMetadata(this.chMetadataId, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void RemoveChannelMetadata(string spaceId, Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildDeleteChannelMetadataRequest("DELETE", "", spaceId, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDeleteChannelMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> RemoveChannelMetadata(string spaceId, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.chMetadataId) || string.IsNullOrEmpty(this.chMetadataId.Trim())) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildDeleteChannelMetadataRequest("DELETE", "", spaceId, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDeleteChannelMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNRemoveChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class RemoveChannelMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + + private string channelId = string.Empty; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemoveChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public RemoveChannelMetadataOperation Channel(string channelName) + { + this.channelId = channelName; + return this; + } + + public RemoveChannelMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelId) || string.IsNullOrEmpty(this.channelId.Trim())) { + throw new ArgumentException("Missing Channel"); + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid Subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + this.savedCallback = callback; + RemoveChannelMetadata(this.channelId, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await RemoveChannelMetadata(this.channelId, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RemoveChannelMetadata(this.channelId, this.queryParam, savedCallback); + } + + private void RemoveChannelMetadata(string spaceId, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDeleteChannelMetadataOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteChannelMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> RemoveChannelMetadata(string spaceId, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(this.channelId) || string.IsNullOrEmpty(this.channelId.Trim())) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDeleteChannelMetadataOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteChannelMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNRemoveChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? string.Empty : channelId + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDeleteChannelMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.DELETE, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/RemoveMembershipsOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/RemoveMembershipsOperation.cs index 6cde2d341..cce381429 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/RemoveMembershipsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/RemoveMembershipsOperation.cs @@ -3,311 +3,278 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -using Newtonsoft.Json; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class RemoveMembershipsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string uuidMetadataId = ""; - private List delMembership; - private string commandDelimitedIncludeOptions = ""; - private PNPageObject page; - private int limit = -1; - private bool includeCount; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - public RemoveMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public RemoveMembershipsOperation Uuid(string id) - { - this.uuidMetadataId = id; - return this; - } - - public RemoveMembershipsOperation Channels(List channelIdList) - { - this.delMembership = channelIdList; - return this; - } - - public RemoveMembershipsOperation Include(PNMembershipField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public RemoveMembershipsOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public RemoveMembershipsOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public RemoveMembershipsOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public RemoveMembershipsOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public RemoveMembershipsOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveUuidMemberships(this.uuidMetadataId, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveUuidMemberships(this.uuidMetadataId, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RemoveUuidMemberships(this.uuidMetadataId, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveUuidMemberships(this.uuidMetadataId, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveUuidMemberships(this.uuidMetadataId, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void RemoveUuidMemberships(string uuid, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveMembershipsOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (removeMembership != null) - { - List>> removeMembershipFormatList = new List>>(); - for (int index = 0; index < removeMembership.Count; index++) - { - Dictionary> currentMembershipFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMembership[index])) - { - currentMembershipFormat.Add("channel", new Dictionary { { "id", removeMembership[index] } }); - removeMembershipFormatList.Add(currentMembershipFormat); - } - } - if (removeMembershipFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMembershipFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMembershipSetRemoveManageUserRequest(requestState.ResponseType, "PATCH", patchMessage, uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> RemoveUuidMemberships(string uuid, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNRemoveMembershipsOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (removeMembership != null) - { - List>> removeMembershipFormatList = new List>>(); - for (int index = 0; index < removeMembership.Count; index++) - { - Dictionary> currentMembershipFormat = new Dictionary>(); - if (!string.IsNullOrEmpty(removeMembership[index])) - { - currentMembershipFormat.Add("channel", new Dictionary { { "id", removeMembership[index] } }); - removeMembershipFormatList.Add(currentMembershipFormat); - } - } - if (removeMembershipFormatList.Count > 0) - { - messageEnvelope.Add("delete", removeMembershipFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMembershipSetRemoveManageUserRequest(requestState.ResponseType, "PATCH", patchMessage, uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid") - { - ret = "uuid"; - } - else if (enumValue.ToLowerInvariant() == "channel") - { - ret = "channel"; - } - else if (enumValue.ToLowerInvariant() == "channel_custom") - { - ret = "channel.custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid_custom") - { - ret = "uuid.custom"; - } - return ret; - } - - } + public class RemoveMembershipsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string uuid = string.Empty; + private List delMembership; + private string commandDelimitedIncludeOptions = string.Empty; + private PNPageObject page = new PNPageObject(); + private int limit = -1; + private bool includeCount; + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + public RemoveMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public RemoveMembershipsOperation Uuid(string id) + { + this.uuid = id; + return this; + } + + public RemoveMembershipsOperation Channels(List channelIdList) + { + this.delMembership = channelIdList; + return this; + } + + public RemoveMembershipsOperation Include(PNMembershipField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public RemoveMembershipsOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public RemoveMembershipsOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public RemoveMembershipsOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public RemoveMembershipsOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public RemoveMembershipsOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + this.savedCallback = callback; + RemoveUuidMemberships(this.uuid, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await RemoveUuidMemberships(this.uuid, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RemoveUuidMemberships(this.uuid, this.delMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); + } + + private void RemoveUuidMemberships(string uuid, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveMembershipsOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.UsePatchMethod = true; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveMembershipsOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> RemoveUuidMemberships(string uuid, List removeMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNRemoveMembershipsOperation; + requestState.Reconnect = false; + requestState.UsePatchMethod = true; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveMembershipsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (delMembership != null) { + List>> removeMembershipFormatList = new List>>(); + for (int index = 0; index < delMembership.Count; index++) { + Dictionary> currentMembershipFormat = new Dictionary>(); + if (!string.IsNullOrEmpty(delMembership[index])) { + currentMembershipFormat.Add("channel", new Dictionary { { "id", delMembership[index] } }); + removeMembershipFormatList.Add(currentMembershipFormat); + } + } + if (removeMembershipFormatList.Count > 0) { + messageEnvelope.Add("delete", removeMembershipFormatList); + } + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(uuid) ? string.Empty : uuid, + "channels" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNRemoveMembershipsOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNRemoveMembershipsOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNRemoveMembershipsOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNRemoveMembershipsOperation, false, false, false)); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNRemoveMembershipsOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/RemoveUuidMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/RemoveUuidMetadataOperation.cs index c68183d31..6a825f10d 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/RemoveUuidMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/RemoveUuidMetadataOperation.cs @@ -1,187 +1,196 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class RemoveUuidMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string usrUuid = ""; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemoveUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public RemoveUuidMetadataOperation Uuid(string uuid) - { - this.usrUuid = uuid; - return this; - } - - public RemoveUuidMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid Subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveUuidMetadata(this.usrUuid, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveUuidMetadata(this.usrUuid, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - - public async Task> ExecuteAsync() - { - return await RemoveUuidMetadata(this.usrUuid, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveUuidMetadata(this.usrUuid, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveUuidMetadata(this.usrUuid, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void RemoveUuidMetadata(string uuid, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildDeleteUuidMetadataRequest("DELETE", "", uuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDeleteUuidMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - - } - - - private async Task> RemoveUuidMetadata(string uuid, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildDeleteUuidMetadataRequest("DELETE", "", uuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDeleteUuidMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNRemoveUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - - } - } + public class RemoveUuidMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string uuid = string.Empty; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemoveUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public RemoveUuidMetadataOperation Uuid(string uuid) + { + this.uuid = uuid; + return this; + } + + public RemoveUuidMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid Subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + + this.savedCallback = callback; + RemoveUuidMetadata(this.uuid, this.queryParam, callback); + } + + + public async Task> ExecuteAsync() + { + return await RemoveUuidMetadata(this.uuid, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + + RemoveUuidMetadata(this.uuid, this.queryParam, savedCallback); + } + + private void RemoveUuidMetadata(string uuid, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDeleteUuidMetadataOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteUuidMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + + private async Task> RemoveUuidMetadata(string uuid, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDeleteUuidMetadataOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveMembershipsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNRemoveUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(uuid) ? string.Empty : uuid + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDeleteUuidMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.DELETE, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/SetChannelMembersOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/SetChannelMembersOperation.cs index 0f0cdb95c..d0e58b28d 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/SetChannelMembersOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/SetChannelMembersOperation.cs @@ -3,317 +3,283 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -using Newtonsoft.Json; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class SetChannelMembersOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string chMetadataId = ""; - private List setMember; - private string commandDelimitedIncludeOptions = ""; - private PNPageObject page; - private int limit = -1; - private bool includeCount; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public SetChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public SetChannelMembersOperation Channel(string channelName) - { - this.chMetadataId = channelName; - return this; - } - - public SetChannelMembersOperation Uuids(List channelMembers) - { - this.setMember = channelMembers; - return this; - } - - public SetChannelMembersOperation Include(PNChannelMemberField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public SetChannelMembersOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public SetChannelMembersOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public SetChannelMembersOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public SetChannelMembersOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public SetChannelMembersOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(this.chMetadataId) || string.IsNullOrEmpty(chMetadataId.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessMembersOperationRequest(this.chMetadataId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessMembersOperationRequest(string spaceId, List setMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) - { - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetChannelMembersOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMemberList != null) - { - List> setMemberFormatList = new List>(); - for (int index = 0; index < setMemberList.Count; index++) - { - Dictionary currentMemberFormat = new Dictionary(); - currentMemberFormat.Add("uuid", new Dictionary { { "id", setMemberList[index].Uuid } }); - if (setMemberList[index].Custom != null) - { - currentMemberFormat.Add("custom", setMemberList[index].Custom); - } - setMemberFormatList.Add(currentMemberFormat); - } - if (setMemberFormatList.Count > 0) - { - messageEnvelope.Add("set", setMemberFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMemberAddUpdateRemoveChannelRequest("PATCH", patchMessage, spaceId, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> ProcessMembersOperationRequest(string channel, List setMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetChannelMembersOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMemberList != null) - { - List> setMemberFormatList = new List>(); - for (int index = 0; index < setMemberList.Count; index++) - { - Dictionary currentMemberFormat = new Dictionary(); - currentMemberFormat.Add("uuid", new Dictionary { { "id", setMemberList[index].Uuid } }); - if (setMemberList[index].Custom != null) - { - currentMemberFormat.Add("custom", setMemberList[index].Custom); - } - setMemberFormatList.Add(currentMemberFormat); - } - if (setMemberFormatList.Count > 0) - { - messageEnvelope.Add("set", setMemberFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMemberAddUpdateRemoveChannelRequest("PATCH", patchMessage, channel, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid") - { - ret = "uuid"; - } - else if (enumValue.ToLowerInvariant() == "channel") - { - ret = "channel"; - } - else if (enumValue.ToLowerInvariant() == "channel_custom") - { - ret = "channel.custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid_custom") - { - ret = "uuid.custom"; - } - return ret; - } - - } + public class SetChannelMembersOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelId = string.Empty; + private List setMember; + private string commandDelimitedIncludeOptions = string.Empty; + private PNPageObject page = new PNPageObject(); + private int limit = -1; + private bool includeCount; + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public SetChannelMembersOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public SetChannelMembersOperation Channel(string channelId) + { + this.channelId = channelId; + return this; + } + + public SetChannelMembersOperation Uuids(List channelMembers) + { + this.setMember = channelMembers; + return this; + } + + public SetChannelMembersOperation Include(PNChannelMemberField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public SetChannelMembersOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public SetChannelMembersOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public SetChannelMembersOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public SetChannelMembersOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public SetChannelMembersOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelId) || string.IsNullOrEmpty(channelId.Trim())) { + throw new ArgumentException("Missing Channel"); + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + this.savedCallback = callback; + ProcessMembersOperationRequest(this.channelId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await ProcessMembersOperationRequest(this.channelId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + ProcessMembersOperationRequest(this.channelId, this.setMember, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); + } + + private void ProcessMembersOperationRequest(string spaceId, List setMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetChannelMembersOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.UsePatchMethod = true; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetChannelMembersOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> ProcessMembersOperationRequest(string channel, List setMemberList, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetChannelMembersOperation; + requestState.Reconnect = false; + requestState.UsePatchMethod = true; + requestState.EndPointOperation = this; + + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetChannelMembersOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNChannelMembersResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetChannelMembersOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (setMember != null) { + List> setMemberFormatList = new List>(); + for (int index = 0; index < setMember.Count; index++) { + Dictionary currentMemberFormat = new Dictionary + { + { "uuid", new Dictionary { { "id", setMember[index].Uuid } } } + }; + if (setMember[index].Custom != null) { + currentMemberFormat.Add("custom", setMember[index].Custom); + } + setMemberFormatList.Add(currentMemberFormat); + } + if (setMemberFormatList.Count > 0) { + messageEnvelope.Add("set", setMemberFormatList); + } + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? string.Empty : channelId, + "uuids" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNSetChannelMembersOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNSetChannelMembersOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNSetChannelMembersOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNSetChannelMembersOperation, false, false, false)); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSetChannelMembersOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + return requestParameter; + } + + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/SetChannelMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/SetChannelMetadataOperation.cs index 7a54951a1..c681f56f4 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/SetChannelMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/SetChannelMetadataOperation.cs @@ -1,252 +1,233 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; -using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class SetChannelMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string chMetaId = ""; - private string chMetaName; - private string chMetaDesc; - private Dictionary chMetaCustom; - private bool includeCustom; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public SetChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public SetChannelMetadataOperation Channel(string channelName) - { - this.chMetaId = channelName; - return this; - } - - public SetChannelMetadataOperation Name(string channelMetadataName) - { - this.chMetaName = channelMetadataName; - return this; - } - - public SetChannelMetadataOperation Description(string channelMetadataDescription) - { - this.chMetaDesc = channelMetadataDescription; - return this; - } - - public SetChannelMetadataOperation Custom(Dictionary channelMetadataCustomObject) - { - this.chMetaCustom = channelMetadataCustomObject; - return this; - } - - public SetChannelMetadataOperation IncludeCustom(bool includeCustomData) - { - this.includeCustom = includeCustomData; - return this; - } - - - public SetChannelMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(chMetaId) || string.IsNullOrEmpty(chMetaId.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - SetChannelMetadata(this.chMetaId, this.includeCustom, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - SetChannelMetadata(this.chMetaId, this.includeCustom, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await SetChannelMetadata(this.chMetaId, this.includeCustom, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - SetChannelMetadata(this.chMetaId, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - SetChannelMetadata(this.chMetaId, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void SetChannelMetadata(string channelMetaId, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) - { - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetChannelMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - if (this.chMetaName != null) - { - messageEnvelope.Add("name", chMetaName); - } - if (this.chMetaDesc != null) - { - messageEnvelope.Add("description", chMetaDesc); - } - if (this.chMetaCustom != null) - { - messageEnvelope.Add("custom", chMetaCustom); - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildSetChannelMetadataRequest("PATCH", patchMessage, channelMetaId, includeCustom, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> SetChannelMetadata(string channelMetaId, bool includeCustom, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channelMetaId) || string.IsNullOrEmpty(channelMetaId.Trim())) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetChannelMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - if (this.chMetaName != null) - { - messageEnvelope.Add("name", chMetaName); - } - if (this.chMetaDesc != null) - { - messageEnvelope.Add("description", chMetaDesc); - } - if (this.chMetaCustom != null) - { - messageEnvelope.Add("custom", chMetaCustom); - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildSetChannelMetadataRequest("PATCH", patchMessage, channelMetaId, includeCustom, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNSetChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - } + public class SetChannelMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelId = string.Empty; + private string channelName; + private string channelDescription; + private Dictionary custom; + private bool includeCustom; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public SetChannelMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public SetChannelMetadataOperation Channel(string channelName) + { + this.channelId = channelName; + return this; + } + + public SetChannelMetadataOperation Name(string channelMetadataName) + { + this.channelName = channelMetadataName; + return this; + } + + public SetChannelMetadataOperation Description(string channelMetadataDescription) + { + this.channelDescription = channelMetadataDescription; + return this; + } + + public SetChannelMetadataOperation Custom(Dictionary channelMetadataCustomObject) + { + this.custom = channelMetadataCustomObject; + return this; + } + + public SetChannelMetadataOperation IncludeCustom(bool includeCustomData) + { + this.includeCustom = includeCustomData; + return this; + } + + + public SetChannelMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(channelId) || string.IsNullOrEmpty(channelId.Trim())) { + throw new ArgumentException("Missing Channel"); + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + + this.savedCallback = callback; + SetChannelMetadata(this.channelId, this.includeCustom, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await SetChannelMetadata(this.channelId, this.includeCustom, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + SetChannelMetadata(this.channelId, this.includeCustom, this.queryParam, savedCallback); + } + + private void SetChannelMetadata(string channelMetaId, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetChannelMetadataOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetChannelMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> SetChannelMetadata(string channelMetaId, bool includeCustom, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channelMetaId) || string.IsNullOrEmpty(channelMetaId.Trim())) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel", new ArgumentException("Missing Channel")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetChannelMetadataOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetChannelMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNSetChannelMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetChannelMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (this.channelName != null) { + messageEnvelope.Add("name", channelName); + } + if (this.channelDescription != null) { + messageEnvelope.Add("description", channelDescription); + } + if (this.custom != null) { + messageEnvelope.Add("custom", custom); + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "channels", + string.IsNullOrEmpty(channelId) ? string.Empty : channelId + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (includeCustom) { + requestQueryStringParams.Add("include", "custom"); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSetChannelMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs index 34c0c6495..7d90fc67e 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/SetMembershipsOperation.cs @@ -3,314 +3,269 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -using Newtonsoft.Json; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Globalization; namespace PubnubApi.EndPoint { - public class SetMembershipsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string uuidMetadataId = ""; - private List addMembership; - private string commandDelimitedIncludeOptions = ""; - private PNPageObject page; - private int limit = -1; - private bool includeCount; - private List sortField; - - private PNCallback savedCallback; - private Dictionary queryParam; - - public SetMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public SetMembershipsOperation Uuid(string id) - { - this.uuidMetadataId = id; - return this; - } - - public SetMembershipsOperation Channels(List memberships) - { - this.addMembership = memberships; - return this; - } - - public SetMembershipsOperation Include(PNMembershipField[] includeOptions) - { - if (includeOptions != null) - { - string[] arrayInclude = includeOptions.Select(x => MapEnumValueToEndpoint(x.ToString())).ToArray(); - this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); - } - return this; - } - - public SetMembershipsOperation Page(PNPageObject pageObject) - { - this.page = pageObject; - return this; - } - - public SetMembershipsOperation Limit(int numberOfObjects) - { - this.limit = numberOfObjects; - return this; - } - - public SetMembershipsOperation IncludeCount(bool includeTotalCount) - { - this.includeCount = includeTotalCount; - return this; - } - - public SetMembershipsOperation Sort(List sortByField) - { - this.sortField = sortByField; - return this; - } - - public SetMembershipsOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - SetChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - SetChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await SetChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - SetChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - SetChannelMembershipWithUuid(this.uuidMetadataId, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void SetChannelMembershipWithUuid(string uuid, List setMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetMembershipsOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMembership != null) - { - List> setMembershipFormatList = new List>(); - for (int index = 0; index < setMembership.Count; index++) - { - Dictionary currentMembershipFormat = new Dictionary(); - currentMembershipFormat.Add("channel", new Dictionary { { "id", setMembership[index].Channel } }); - if (setMembership[index].Custom != null) - { - currentMembershipFormat.Add("custom", setMembership[index].Custom); - } - setMembershipFormatList.Add(currentMembershipFormat); - } - if (setMembershipFormatList.Count > 0) - { - messageEnvelope.Add("set", setMembershipFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMembershipSetRemoveManageUserRequest(requestState.ResponseType, "PATCH", patchMessage, uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> SetChannelMembershipWithUuid(string uuid, List setMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - PNPageObject internalPage; - if (page == null) { internalPage = new PNPageObject(); } - else { internalPage = page; } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetMembershipsOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - Dictionary messageEnvelope = new Dictionary(); - if (setMembership != null) - { - List> setMembershipFormatList = new List>(); - for (int index = 0; index < setMembership.Count; index++) - { - Dictionary currentMembershipFormat = new Dictionary(); - currentMembershipFormat.Add("channel", new Dictionary { { "id", setMembership[index].Channel } }); - if (setMembership[index].Custom != null) - { - currentMembershipFormat.Add("custom", setMembership[index].Custom); - } - setMembershipFormatList.Add(currentMembershipFormat); - } - if (setMembershipFormatList.Count > 0) - { - messageEnvelope.Add("set", setMembershipFormatList); - } - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildMembershipSetRemoveManageUserRequest(requestState.ResponseType, "PATCH", patchMessage, uuid, internalPage.Next, internalPage.Prev, limit, includeCount, includeOptions, sort, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private static string MapEnumValueToEndpoint(string enumValue) - { - string ret = ""; - if (enumValue.ToLowerInvariant() == "custom") - { - ret = "custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid") - { - ret = "uuid"; - } - else if (enumValue.ToLowerInvariant() == "channel") - { - ret = "channel"; - } - else if (enumValue.ToLowerInvariant() == "channel_custom") - { - ret = "channel.custom"; - } - else if (enumValue.ToLowerInvariant() == "uuid_custom") - { - ret = "uuid.custom"; - } - return ret; - } - - } + public class SetMembershipsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string uuid = ""; + private List addMembership; + private string commandDelimitedIncludeOptions = ""; + private PNPageObject page = new PNPageObject(); + private int limit = -1; + private bool includeCount; + private List sortField; + + private PNCallback savedCallback; + private Dictionary queryParam; + + public SetMembershipsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public SetMembershipsOperation Uuid(string id) + { + this.uuid = id; + return this; + } + + public SetMembershipsOperation Channels(List memberships) + { + this.addMembership = memberships; + return this; + } + + public SetMembershipsOperation Include(PNMembershipField[] includeOptions) + { + if (includeOptions != null) { + string[] arrayInclude = includeOptions.Select(x => UrlParameterConverter.MapEnumValueToEndpoint(x.ToString())).ToArray(); + this.commandDelimitedIncludeOptions = string.Join(",", arrayInclude); + } + return this; + } + + public SetMembershipsOperation Page(PNPageObject pageObject) + { + this.page = pageObject; + return this; + } + + public SetMembershipsOperation Limit(int numberOfObjects) + { + this.limit = numberOfObjects; + return this; + } + + public SetMembershipsOperation IncludeCount(bool includeTotalCount) + { + this.includeCount = includeTotalCount; + return this; + } + + public SetMembershipsOperation Sort(List sortByField) + { + this.sortField = sortByField; + return this; + } + + public SetMembershipsOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + this.savedCallback = callback; + SetChannelMembershipWithUuid(this.uuid, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await SetChannelMembershipWithUuid(this.uuid, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + SetChannelMembershipWithUuid(this.uuid, this.addMembership, this.page, this.limit, this.includeCount, this.commandDelimitedIncludeOptions, this.sortField, this.queryParam, savedCallback); + } + + private void SetChannelMembershipWithUuid(string uuid, List setMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetMembershipsOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetMembershipsOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> SetChannelMembershipWithUuid(string uuid, List setMembership, PNPageObject page, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(uuid)) { + this.uuid = config.UserId; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid Subscribe key", new ArgumentException("Invalid Subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetMembershipsOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetMembershipsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNMembershipsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetMembershipsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (addMembership != null) { + List> setMembershipFormatList = new List>(); + for (int index = 0; index < addMembership.Count; index++) { + Dictionary currentMembershipFormat = new Dictionary + { + { "channel", new Dictionary { { "id", addMembership[index].Channel } } } + }; + if (addMembership[index].Custom != null) { + currentMembershipFormat.Add("custom", addMembership[index].Custom); + } + setMembershipFormatList.Add(currentMembershipFormat); + } + if (setMembershipFormatList.Count > 0) { + messageEnvelope.Add("set", setMembershipFormatList); + } + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(this.uuid) ? string.Empty : uuid, + "channels" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (!string.IsNullOrEmpty(page.Next)) { + requestQueryStringParams.Add("start", UriUtil.EncodeUriComponent(page.Next, PNOperationType.PNSetMembershipsOperation, false, false, false)); + } + if (!string.IsNullOrEmpty(page.Prev)) { + requestQueryStringParams.Add("end", UriUtil.EncodeUriComponent(page.Prev, PNOperationType.PNSetMembershipsOperation, false, false, false)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + if (includeCount) { + requestQueryStringParams.Add("count", "true"); + } + if (!string.IsNullOrEmpty(commandDelimitedIncludeOptions)) { + requestQueryStringParams.Add("include", UriUtil.EncodeUriComponent(commandDelimitedIncludeOptions, PNOperationType.PNSetMembershipsOperation, false, false, false)); + } + if (sortField != null && sortField.Count > 0) { + requestQueryStringParams.Add("sort", UriUtil.EncodeUriComponent(string.Join(",", sortField.ToArray()), PNOperationType.PNSetMembershipsOperation, false, false, false)); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSetMembershipsOperation, false, false, false)); + } + } + } + string queryString = UriUtil.BuildQueryString(requestQueryStringParams); + + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Objects/SetUuidMetadataOperation.cs b/src/Api/PubnubApi/EndPoint/Objects/SetUuidMetadataOperation.cs index 539378e5d..211726bb5 100644 --- a/src/Api/PubnubApi/EndPoint/Objects/SetUuidMetadataOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Objects/SetUuidMetadataOperation.cs @@ -1,262 +1,254 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class SetUuidMetadataOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string uuidId; - private string uuidName; - private string uuidEmail; - private string uuidExternalId; - private string uuidProfileUrl; - private Dictionary uuidCustom; - private bool includeCustom; - - - private PNCallback savedCallback; - private Dictionary queryParam; - - public SetUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public SetUuidMetadataOperation Uuid(string uuid) - { - this.uuidId = uuid; - return this; - } - - public SetUuidMetadataOperation Name(string name) - { - this.uuidName = name; - return this; - } - - public SetUuidMetadataOperation Email(string email) - { - this.uuidEmail = email; - return this; - } - - - public SetUuidMetadataOperation ExternalId(string externalId) - { - this.uuidExternalId = externalId; - return this; - } - - - public SetUuidMetadataOperation ProfileUrl(string profileUrl) - { - this.uuidProfileUrl = profileUrl; - return this; - } - - public SetUuidMetadataOperation Custom(Dictionary customObject) - { - this.uuidCustom = customObject; - return this; - } - - public SetUuidMetadataOperation IncludeCustom(bool includeCustomData) - { - this.includeCustom = includeCustomData; - return this; - } - - public SetUuidMetadataOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void SetUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetUuidMetadataOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - if (uuidName != null) - { - messageEnvelope.Add("name", uuidName); - } - if (uuidExternalId != null) - { - messageEnvelope.Add("externalId", uuidExternalId); - } - if (uuidProfileUrl != null) - { - messageEnvelope.Add("profileUrl", uuidProfileUrl); - } - if (uuidEmail != null) - { - messageEnvelope.Add("email", uuidEmail); - } - if (uuidCustom != null) - { - messageEnvelope.Add("custom", uuidCustom); - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildSetUuidMetadataRequest("PATCH", patchMessage, uuid, includeCustom, externalQueryParam); - - UrlProcessRequest(request, requestState, false, patchData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> SetUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam) - { - if (string.IsNullOrEmpty(uuid)) - { - uuid = config.UserId; - } - PNResult ret = new PNResult(); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNSetUuidMetadataOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - requestState.UsePatchMethod = true; - - Dictionary messageEnvelope = new Dictionary(); - messageEnvelope.Add("name", uuidName); - if (uuidExternalId != null) - { - messageEnvelope.Add("externalId", uuidExternalId); - } - if (uuidProfileUrl != null) - { - messageEnvelope.Add("profileUrl", uuidProfileUrl); - } - if (uuidEmail != null) - { - messageEnvelope.Add("email", uuidEmail); - } - if (uuidCustom != null) - { - messageEnvelope.Add("custom", uuidCustom); - } - string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] patchData = Encoding.UTF8.GetBytes(patchMessage); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri request = urlBuilder.BuildSetUuidMetadataRequest("PATCH", patchMessage, uuid, includeCustom, externalQueryParam); - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, patchData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNSetUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class SetUuidMetadataOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string uuidId; + private string uuidName; + private string uuidEmail; + private string uuidExternalId; + private string uuidProfileUrl; + private Dictionary uuidCustom; + private bool includeCustom; + + + private PNCallback savedCallback; + private Dictionary queryParam; + + public SetUuidMetadataOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + if (instance != null) { + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + } + + public SetUuidMetadataOperation Uuid(string uuid) + { + this.uuidId = uuid; + return this; + } + + public SetUuidMetadataOperation Name(string name) + { + this.uuidName = name; + return this; + } + + public SetUuidMetadataOperation Email(string email) + { + this.uuidEmail = email; + return this; + } + + + public SetUuidMetadataOperation ExternalId(string externalId) + { + this.uuidExternalId = externalId; + return this; + } + + + public SetUuidMetadataOperation ProfileUrl(string profileUrl) + { + this.uuidProfileUrl = profileUrl; + return this; + } + + public SetUuidMetadataOperation Custom(Dictionary customObject) + { + this.uuidCustom = customObject; + return this; + } + + public SetUuidMetadataOperation IncludeCustom(bool includeCustomData) + { + this.includeCustom = includeCustomData; + return this; + } + + public SetUuidMetadataOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + this.savedCallback = callback; + SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + SetUuidMetadata(this.uuidId, this.includeCustom, this.queryParam, savedCallback); + } + + private void SetUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuidId = config.UserId; + } + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetUuidMetadataOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetUuidMetadataOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> SetUuidMetadata(string uuid, bool includeCustom, Dictionary externalQueryParam) + { + if (string.IsNullOrEmpty(uuid)) { + this.uuidId = config.UserId; + } + + PNResult returnValue = new PNResult(); + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNSetUuidMetadataOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePatchMethod = true; + + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetUuidMetadataOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNSetUuidMetadataResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetUuidMetadataOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + Dictionary messageEnvelope = new Dictionary(); + if (uuidName != null) { + messageEnvelope.Add("name", uuidName); + } + if (uuidExternalId != null) { + messageEnvelope.Add("externalId", uuidExternalId); + } + if (uuidProfileUrl != null) { + messageEnvelope.Add("profileUrl", uuidProfileUrl); + } + if (uuidEmail != null) { + messageEnvelope.Add("email", uuidEmail); + } + if (uuidCustom != null) { + messageEnvelope.Add("custom", uuidCustom); + } + string patchMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); + + List pathSegments = new List + { + "v2", + "objects", + config.SubscribeKey, + "uuids", + string.IsNullOrEmpty(uuidId) ? string.Empty : uuidId + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (includeCustom) { + requestQueryStringParams.Add("include", "custom"); + } + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSetUuidMetadataOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.PATCH, + PathSegment = pathSegments, + Query = requestQueryStringParams, + BodyContentString = patchMessage + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/OtherOperation.cs b/src/Api/PubnubApi/EndPoint/OtherOperation.cs index 67e7efb8b..cfea3db8d 100644 --- a/src/Api/PubnubApi/EndPoint/OtherOperation.cs +++ b/src/Api/PubnubApi/EndPoint/OtherOperation.cs @@ -1,75 +1,25 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Threading; -using System.Net; -#if !NET35 && !NET40 using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - internal class OtherOperation : PubnubCoreBase + internal class OtherOperation : PubnubCoreBase { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - public OtherOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public OtherOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public void ChangeUserId(UserId newUserId) - { - if (newUserId == null || string.IsNullOrEmpty(newUserId.ToString().Trim()) || config.UserId.ToString() == newUserId.ToString()) - { - return; - } - - Task.Factory.StartNew(() => - { - try - { - config.UserId = newUserId; - CurrentUserId.AddOrUpdate(PubnubInstance.InstanceId, newUserId, (k, o) => newUserId); - UserIdChanged.AddOrUpdate(PubnubInstance.InstanceId, true, (k, o) => true); - - - string[] channels = GetCurrentSubscriberChannels(); - string[] channelGroups = GetCurrentSubscriberChannelGroups(); - - channels = (channels != null) ? channels : new string[] { }; - channelGroups = (channelGroups != null) ? channelGroups : new string[] { }; - - if (channels.Length > 0 || channelGroups.Length > 0) - { - string channelsJsonState = BuildJsonUserState(channels.ToArray(), channelGroups.ToArray(), false); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildMultiChannelLeaveRequest("GET", "", channels, channelGroups, channelsJsonState, null); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ChannelGroups = channelGroups; - requestState.ResponseType = PNOperationType.Leave; - requestState.Reconnect = false; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => { }, TaskContinuationOptions.ExecuteSynchronously).Wait(); // connectCallback = null - } - - TerminateCurrentSubscriberRequest(); - } - catch { /* ignore */ } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); } public UserId GetCurrentUserId() @@ -177,7 +127,7 @@ internal void CurrentPubnubInstance(Pubnub instance) if (!ChannelRequest.ContainsKey(instance.InstanceId)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); } if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { diff --git a/src/Api/PubnubApi/EndPoint/Presence/GetStateOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/GetStateOperation.cs index d3673c217..d0d4771d9 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/GetStateOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/GetStateOperation.cs @@ -3,214 +3,228 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetStateOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string[] channelNames; - private string[] channelGroupNames; - private string channelUUID = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetStateOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public GetStateOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - public GetStateOperation ChannelGroups(string[] channelGroups) - { - this.channelGroupNames = channelGroups; - return this; - } - - public GetStateOperation Uuid(string uuid) - { - this.channelUUID = uuid; - return this; - } - - public GetStateOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void GetUserState(string[] channels, string[] channelGroups, string uuid, Dictionary externalQueryParam, PNCallback callback) - { - if ((channels == null && channelGroups == null) - || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) - { - throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); - } - string internalUuid; - if (string.IsNullOrEmpty(uuid) || uuid.Trim().Length == 0) - { - internalUuid = config.UserId; - } - else { - internalUuid = uuid; - } - - string channelsCommaDelimited = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ""; - string channelGroupsCommaDelimited = (channelGroups != null && channelGroups.Length > 0) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetUserStateRequest("GET", "", channelsCommaDelimited, channelGroupsCommaDelimited, internalUuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ChannelGroups = channelGroups; - requestState.ResponseType = PNOperationType.PNGetStateOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> GetUserState(string[] channels, string[] channelGroups, string uuid, Dictionary externalQueryParam) - { - if ((channels == null && channelGroups == null) - || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) - { - throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); - } - PNResult ret = new PNResult(); - - string internalUuid; - if (string.IsNullOrEmpty(uuid) || uuid.Trim().Length == 0) - { - internalUuid = config.UserId; - } - else - { - internalUuid = uuid; - } - - string channelsCommaDelimited = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ""; - string channelGroupsCommaDelimited = (channelGroups != null && channelGroups.Length > 0) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetUserStateRequest("GET", "", channelsCommaDelimited, channelGroupsCommaDelimited, internalUuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ChannelGroups = channelGroups; - requestState.ResponseType = PNOperationType.PNGetStateOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGetStateResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class GetStateOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string[] channelNames; + private string[] channelGroupNames; + private string channelUUID = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetStateOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public GetStateOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + public GetStateOperation ChannelGroups(string[] channelGroups) + { + this.channelGroupNames = channelGroups; + return this; + } + + public GetStateOperation Uuid(string uuid) + { + this.channelUUID = uuid; + return this; + } + + public GetStateOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, this.queryParam, savedCallback); + } + + internal void GetUserState(string[] channels, string[] channelGroups, string uuid, Dictionary externalQueryParam, PNCallback callback) + { + if ((channels == null && channelGroups == null) + || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) { + throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); + } + string internalUuid; + if (string.IsNullOrEmpty(uuid) || uuid.Trim().Length == 0) { + internalUuid = config.UserId; + } else { + internalUuid = uuid; + } + RequestState requestState = new RequestState(); + requestState.Channels = channels; + requestState.ChannelGroups = channelGroups; + requestState.ResponseType = PNOperationType.PNGetStateOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetStateOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetStateOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + internal async Task> GetUserState(string[] channels, string[] channelGroups, string uuid, Dictionary externalQueryParam) + { + if ((channels == null && channelGroups == null) + || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) { + throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); + } + PNResult returnValue = new PNResult(); + + string internalUuid; + if (string.IsNullOrEmpty(uuid) || uuid.Trim().Length == 0) { + internalUuid = config.UserId; + } else { + internalUuid = uuid; + } + RequestState requestState = new RequestState(); + requestState.Channels = channels; + requestState.ChannelGroups = channelGroups; + requestState.ResponseType = PNOperationType.PNGetStateOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetStateOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGetStateResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetStateOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private RequestParameter CreateRequestParameter() + { + string requestUuid = string.IsNullOrEmpty(channelUUID) || channelUUID.Trim().Length == 0 ? config.UserId : channelUUID; + + string channelsCommaDelimited = (channelNames != null && channelNames.Length > 0) ? string.Join(",", channelNames.OrderBy(x => x).ToArray()) : string.Empty; + string channelGroupsCommaDelimited = (channelGroupNames != null && channelGroupNames.Length > 0) ? string.Join(",", channelGroupNames.OrderBy(x => x).ToArray()) : string.Empty; + + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config.SubscribeKey, + "channel", + string.IsNullOrEmpty(channelsCommaDelimited) || channelsCommaDelimited.Trim().Length <= 0 ? "," : channelsCommaDelimited, + "uuid", + requestUuid + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (!string.IsNullOrEmpty(channelGroupsCommaDelimited) && channelGroupsCommaDelimited.Trim().Length > 0) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(channelGroupsCommaDelimited, PNOperationType.PNGetStateOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetStateOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Presence/HeartbeatOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/HeartbeatOperation.cs index 23493811f..def3d7dfc 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/HeartbeatOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/HeartbeatOperation.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Net; +using System.Text; using System.Threading.Tasks; namespace PubnubApi.EndPoint @@ -12,44 +14,91 @@ public class HeartbeatOperation : PubnubCoreBase private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly TelemetryManager pubnubTelemetryMgr; - public HeartbeatOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public HeartbeatOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - PubnubInstance = instance; } internal async Task HeartbeatRequest(string[] channels, string[] channelGroups) { - PNStatus resp = null; + PNStatus responseStatus = null; try { string presenceState = string.Empty; if (config.MaintainPresenceState) presenceState = BuildJsonUserState(channels, channelGroups, true); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, ""); - Uri request = urlBuilder.BuildPresenceHeartbeatRequest("GET", "", channels, channelGroups, presenceState); RequestState pubnubRequestState = new RequestState(); pubnubRequestState.Channels = channels; pubnubRequestState.ChannelGroups = channelGroups; pubnubRequestState.ResponseType = PNOperationType.PNHeartbeatOperation; pubnubRequestState.TimeQueued = DateTime.Now; - await UrlProcessRequest(request, pubnubRequestState, false).ContinueWith(r => { - resp = r.Result.Item2; - }, TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false); + var requestParameter = CreateRequestParameter(channels: channels, channelGroups: channelGroups); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNHeartbeatOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + pubnubRequestState.GotJsonResponse = true; + PNStatus errorStatus = GetStatusIfError(pubnubRequestState, responseString); + if (errorStatus == null) { + responseStatus = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(pubnubRequestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, pubnubRequestState, (int)HttpStatusCode.OK, null); + } else { + responseStatus = errorStatus; + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + responseStatus = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNHeartbeatOperation, category, pubnubRequestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + } } catch (Exception ex) { LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} HeartbeatOperation=> HeartbeatRequest \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), string.Join(",", channelGroups.OrderBy(x => x).ToArray()), ex), config.LogVerbosity); return new PNStatus(ex, PNOperationType.PNHeartbeatOperation, PNStatusCategory.PNUnknownCategory, channels, channelGroups); } - return resp; + return responseStatus; } + private RequestParameter CreateRequestParameter(string[] channels, string[] channelGroups) + { + string channelString = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config.SubscribeKey, + "channel", + channelString, + "heartbeat" + }; + string presenceState = string.Empty; + + if (config.MaintainPresenceState) presenceState = BuildJsonUserState(channels, channelGroups, true); + Dictionary requestQueryStringParams = new Dictionary(); + + string channelsJsonState = presenceState; + if (channelsJsonState != "{}" && channelsJsonState != string.Empty) { + requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(channelsJsonState, PNOperationType.PNHeartbeatOperation, false, false, false)); + } + + if (channelGroups != null && channelGroups.Length > 0) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), PNOperationType.PNHeartbeatOperation, false, false, false)); + } + + if (config.PresenceTimeout != 0) { + requestQueryStringParams.Add("heartbeat", config.PresenceTimeout.ToString(CultureInfo.InvariantCulture)); + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } } } diff --git a/src/Api/PubnubApi/EndPoint/Presence/HereNowOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/HereNowOperation.cs index d872b2e31..2f86ee474 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/HereNowOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/HereNowOperation.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Linq; +using System.Globalization; +using System.Text; namespace PubnubApi.EndPoint { @@ -15,7 +14,7 @@ public class HereNowOperation : PubnubCoreBase private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; + private string[] channelNames; private string[] channelGroupNames; private bool includeUserState; @@ -23,13 +22,12 @@ public class HereNowOperation : PubnubCoreBase private PNCallback savedCallback; private Dictionary queryParam; - public HereNowOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public HereNowOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; } public HereNowOperation Channels(string[] channels) @@ -70,18 +68,7 @@ public void Async(PNCallback callback) public void Execute(PNCallback callback) { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - HereNow(this.channelNames, this.channelGroupNames, this.includeChannelUUIDs, this.includeUserState, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => { - this.savedCallback = callback; - HereNow(this.channelNames, this.channelGroupNames, this.includeChannelUUIDs, this.includeUserState, this.queryParam, callback); - }) { IsBackground = true }.Start(); -#endif + HereNow(this.channelNames, this.channelGroupNames, this.includeChannelUUIDs, this.includeUserState, this.queryParam, callback); } public async Task> ExecuteAsync() @@ -92,86 +79,131 @@ public async Task> ExecuteAsync() internal void Retry() { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - HereNow(this.channelNames, this.channelGroupNames, this.includeChannelUUIDs, this.includeUserState, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => { - HereNow(this.channelNames, this.channelGroupNames, this.includeChannelUUIDs, this.includeUserState, this.queryParam, savedCallback); - }) { IsBackground = true }.Start(); -#endif + HereNow(this.channelNames, this.channelGroupNames, this.includeChannelUUIDs, this.includeUserState, this.queryParam, savedCallback); } internal void HereNow(string[] channels, string[] channelGroups, bool showUUIDList, bool includeUserState, Dictionary externalQueryParam, PNCallback callback) { - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildHereNowRequest("GET", "", channels, channelGroups, showUUIDList, includeUserState, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ChannelGroups = channelGroups; - requestState.ResponseType = PNOperationType.PNHereNowOperation; - requestState.Reconnect = false; - requestState.PubnubCallback = callback; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); + RequestState requestState = new RequestState { + Channels = channels, + ChannelGroups = channelGroups, + ResponseType = PNOperationType.PNHereNowOperation, + Reconnect = false, + PubnubCallback = callback, + EndPointOperation = this + }; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNHereNowOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNHereNowOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); + }); } internal async Task> HereNow(string[] channels, string[] channelGroups, bool showUUIDList, bool includeUserState, Dictionary externalQueryParam) { - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildHereNowRequest("GET", "", channels, channelGroups, showUUIDList, includeUserState, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ChannelGroups = channelGroups; - requestState.ResponseType = PNOperationType.PNHereNowOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNHereNowResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) { - ret.Result = responseResult; + PNResult returnValue = new PNResult(); + + RequestState requestState = new RequestState { + Channels = channels, + ChannelGroups = channelGroups, + ResponseType = PNOperationType.PNHereNowOperation, + Reconnect = false, + EndPointOperation = this + }; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNHereNowOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + Tuple JsonAndStatusTuple; + if (errorStatus == null) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNHereNowResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNHereNowOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; } - return ret; + return returnValue; } + private RequestParameter CreateRequestParameter() + { + string channel = (channelNames != null && channelNames.Length > 0) ? string.Join(",", channelNames.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List() { + "v2", + "presence", + "sub_key", + config.SubscribeKey, + "channel", + channel + }; + + int disableUUID = includeChannelUUIDs ? 0 : 1; + int userState = includeUserState ? 1 : 0; + + Dictionary requestQueryStringParams = new Dictionary(); + + string commaDelimitedchannelGroup = (channelGroupNames != null) ? string.Join(",", channelGroupNames.OrderBy(x => x).ToArray()) : ""; + if (!string.IsNullOrEmpty(commaDelimitedchannelGroup) && commaDelimitedchannelGroup.Trim().Length > 0) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(commaDelimitedchannelGroup, PNOperationType.PNHereNowOperation, false, false, false)); + } + + requestQueryStringParams.Add("disable_uuids", disableUUID.ToString(CultureInfo.InvariantCulture)); + requestQueryStringParams.Add("state", userState.ToString(CultureInfo.InvariantCulture)); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNHereNowOperation, false, false, false)); + } + } + } + var queryString = UriUtil.BuildQueryString(requestQueryStringParams); + var requestParameter = new RequestParameter { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } internal void CurrentPubnubInstance(Pubnub instance) { PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } } } diff --git a/src/Api/PubnubApi/EndPoint/Presence/LeaveOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/LeaveOperation.cs index 6fdd8d250..2081dea7e 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/LeaveOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/LeaveOperation.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Net; +using System.Text; using System.Threading.Tasks; namespace PubnubApi.EndPoint @@ -11,37 +14,75 @@ public class LeaveOperation : PubnubCoreBase private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly TelemetryManager pubnubTelemetryManager; - public LeaveOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public LeaveOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryManager = telemetryManager; PubnubInstance = instance; } internal async Task LeaveRequest(string[] channels, string[] channelGroups) { - PNStatus resp = null; + PNStatus responseStatus = null; try { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryManager, null, string.Empty); - Uri request = urlBuilder.BuildMultiChannelLeaveRequest("GET", string.Empty, channels, channelGroups, string.Empty, null); + RequestState pubnubRequestState = new RequestState(); pubnubRequestState.Channels = channels; pubnubRequestState.ChannelGroups = channelGroups; pubnubRequestState.ResponseType = PNOperationType.Leave; pubnubRequestState.TimeQueued = DateTime.Now; - await UrlProcessRequest(request, pubnubRequestState, false).ContinueWith(r => { - resp = r.Result.Item2; - }, TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false); + + var requestParameter = CreateRequestParameter(channels: channels, channelGroups: channelGroups); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.Leave); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + pubnubRequestState.GotJsonResponse = true; + PNStatus errorStatus = GetStatusIfError(pubnubRequestState, responseString); + if (errorStatus == null) { + responseStatus = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(pubnubRequestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, pubnubRequestState, (int)HttpStatusCode.OK, null); + } else { + responseStatus = errorStatus; + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + responseStatus = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.Leave, category, pubnubRequestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + } } catch (Exception ex) { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} Leave=> LeaveRequest \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), string.Join(",", channelGroups.OrderBy(x => x).ToArray()), ex), config.LogVerbosity); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} HeartbeatOperation=> HeartbeatRequest \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), string.Join(",", channelGroups.OrderBy(x => x).ToArray()), ex), config.LogVerbosity); return new PNStatus(ex, PNOperationType.Leave, PNStatusCategory.PNUnknownCategory, channels, channelGroups); } - return resp; + return responseStatus; + } + private RequestParameter CreateRequestParameter(string[] channels, string[] channelGroups) + { + string channleString = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config.SubscribeKey, + "channel", + channleString, + "leave" + }; + + var requestQueryStringParams = new Dictionary(); + + if (channelGroups != null && channelGroups.Length > 0) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), PNOperationType.Leave, false, false, false)); + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; } } } diff --git a/src/Api/PubnubApi/EndPoint/Presence/PresenceOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/PresenceOperation.cs index d09a8c9c4..6d5c02b7e 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/PresenceOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/PresenceOperation.cs @@ -15,7 +15,7 @@ public class PresenceOperation private IPubnubUnitTest unit; private IPubnubLog pubnubLog; - public PresenceOperation(Pubnub instance, string instanceId, IPubnubLog pubnubLog, PNConfiguration configuration, TelemetryManager telemetryManager, TokenManager tokenManager, IPubnubUnitTest unit, PresenceEventEngineFactory presenceEventEngineFactory) + public PresenceOperation(Pubnub instance, string instanceId, IPubnubLog pubnubLog, PNConfiguration configuration, TokenManager tokenManager, IPubnubUnitTest unit, PresenceEventEngineFactory presenceEventEngineFactory) { this.pubnubLog = pubnubLog; this.unit = unit; @@ -26,7 +26,7 @@ public PresenceOperation(Pubnub instance, string instanceId, IPubnubLog pubnubLo if (this.presenceEventEngineFactory.HasEventEngine(instanceId)) { presenceEventEngine = this.presenceEventEngineFactory.GetEventEngine(instanceId); } else { - presenceEventEngine = this.presenceEventEngineFactory.InitializeEventEngine(instanceId, instance, pubnubLog, telemetryManager, tokenManager); + presenceEventEngine = this.presenceEventEngineFactory.InitializeEventEngine(instanceId, instance, pubnubLog, tokenManager); presenceEventEngine.OnEffectDispatch += OnEffectDispatch; presenceEventEngine.OnEventQueued += OnEventQueued; } diff --git a/src/Api/PubnubApi/EndPoint/Presence/SetStateOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/SetStateOperation.cs index 3889f196a..23325be5b 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/SetStateOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/SetStateOperation.cs @@ -3,560 +3,498 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; using System.Globalization; -#if !NET35 && !NET40 +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class SetStateOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string[] channelNames; - private string[] channelGroupNames; - private Dictionary userState; - private string channelUUID = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public SetStateOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelUserState.ContainsKey(instance.InstanceId)) - { - ChannelUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); - } - if (!ChannelGroupUserState.ContainsKey(instance.InstanceId)) - { - ChannelGroupUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); - } - if (!ChannelLocalUserState.ContainsKey(instance.InstanceId)) - { - ChannelLocalUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); - } - if (!ChannelGroupLocalUserState.ContainsKey(instance.InstanceId)) - { - ChannelGroupLocalUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); - } - } - - public SetStateOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - public SetStateOperation ChannelGroups(string[] channelGroups) - { - this.channelGroupNames = channelGroups; - return this; - } - - public SetStateOperation State(Dictionary state) - { - this.userState = state; - return this; - } - - public SetStateOperation Uuid(string uuid) - { - this.channelUUID = uuid; - return this; - } - - public SetStateOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - string serializedState = jsonLibrary.SerializeToJsonString(this.userState); - SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - string serializedState = jsonLibrary.SerializeToJsonString(this.userState); - SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { + public class SetStateOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string[] channelNames; + private string[] channelGroupNames; + private Dictionary userState; + private string channelUUID = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public SetStateOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelUserState.ContainsKey(instance.InstanceId)) { + ChannelUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); + } + if (!ChannelGroupUserState.ContainsKey(instance.InstanceId)) { + ChannelGroupUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); + } + if (!ChannelLocalUserState.ContainsKey(instance.InstanceId)) { + ChannelLocalUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); + } + if (!ChannelGroupLocalUserState.ContainsKey(instance.InstanceId)) { + ChannelGroupLocalUserState.GetOrAdd(instance.InstanceId, new ConcurrentDictionary>()); + } + } + + public SetStateOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + public SetStateOperation ChannelGroups(string[] channelGroups) + { + this.channelGroupNames = channelGroups; + return this; + } + + public SetStateOperation State(Dictionary state) + { + this.userState = state; + return this; + } + + public SetStateOperation Uuid(string uuid) + { + this.channelUUID = uuid; + return this; + } + + public SetStateOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + string serializedState = jsonLibrary.SerializeToJsonString(this.userState); + SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + string serializedState = jsonLibrary.SerializeToJsonString(this.userState); + return await SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { string serializedState = jsonLibrary.SerializeToJsonString(this.userState); - return await SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - string serializedState = jsonLibrary.SerializeToJsonString(this.userState); - SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - string serializedState = jsonLibrary.SerializeToJsonString(this.userState); - SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void SetUserState(string[] channels, string[] channelGroups, string uuid, string jsonUserState, Dictionary externalQueryParam, PNCallback callback) - { - if ((channels == null && channelGroups == null) - || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) - { - throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); - } - - if (string.IsNullOrEmpty(jsonUserState) || string.IsNullOrEmpty(jsonUserState.Trim())) - { - throw new ArgumentException("Missing User State"); - } - - List channelList = new List(); - List channelGroupList = new List(); - string[] filteredChannels = channels; - string[] filteredChannelGroups = channelGroups; - - if (channels != null && channels.Length > 0) - { - channelList = new List(channels); - channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); - filteredChannels = channelList.ToArray(); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - channelGroupList = new List(channelGroups); - channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); - filteredChannelGroups = channelGroupList.ToArray(); - } - - if (!jsonLibrary.IsDictionaryCompatible(jsonUserState, PNOperationType.PNSetStateOperation)) - { - throw new MissingMemberException("Missing json format for user state"); - } - else - { - Dictionary deserializeUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonUserState); - if (deserializeUserState == null) - { - throw new MissingMemberException("Missing json format user state"); - } - else - { - bool stateChanged = false; - - for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) - { - string currentChannel = channelList[channelIndex]; - - string oldJsonChannelState = GetLocalUserState(currentChannel, ""); - - if (oldJsonChannelState != jsonUserState) - { - stateChanged = true; - break; - } - } - - if (!stateChanged) - { - for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) - { - string currentChannelGroup = channelGroupList[channelGroupIndex]; - - string oldJsonChannelGroupState = GetLocalUserState("", currentChannelGroup); - - if (oldJsonChannelGroupState != jsonUserState) - { - stateChanged = true; - break; - } - } - } - - if (!stateChanged) - { - StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - PNStatus status = statusBuilder.CreateStatusResponse< PNSetStateResult>(PNOperationType.PNSetStateOperation, PNStatusCategory.PNUnknownCategory, null, (int)System.Net.HttpStatusCode.NotModified, null); - - Announce(status); - return; - } - - } - } - - SharedSetUserState(filteredChannels, filteredChannelGroups, uuid, jsonUserState, jsonUserState, externalQueryParam, callback); - } - - internal async Task> SetUserState(string[] channels, string[] channelGroups, string uuid, string jsonUserState, Dictionary externalQueryParam) - { - if ((channels == null && channelGroups == null) - || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) - { - throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); - } - - if (string.IsNullOrEmpty(jsonUserState) || string.IsNullOrEmpty(jsonUserState.Trim())) - { - throw new ArgumentException("Missing User State"); - } - - List channelList = new List(); - List channelGroupList = new List(); - string[] filteredChannels = channels; - string[] filteredChannelGroups = channelGroups; - - if (channels != null && channels.Length > 0) - { - channelList = new List(channels); - channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); - filteredChannels = channelList.ToArray(); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - channelGroupList = new List(channelGroups); - channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); - filteredChannelGroups = channelGroupList.ToArray(); - } - - if (!jsonLibrary.IsDictionaryCompatible(jsonUserState, PNOperationType.PNSetStateOperation)) - { - throw new MissingMemberException("Missing json format for user state"); - } - else - { - Dictionary deserializeUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonUserState); - if (deserializeUserState == null) - { - throw new MissingMemberException("Missing json format user state"); - } - else - { - bool stateChanged = false; - - for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) - { - string currentChannel = channelList[channelIndex]; - - string oldJsonChannelState = GetLocalUserState(currentChannel, ""); - - if (oldJsonChannelState != jsonUserState) - { - stateChanged = true; - break; - } - } - - if (!stateChanged) - { - for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) - { - string currentChannelGroup = channelGroupList[channelGroupIndex]; - - string oldJsonChannelGroupState = GetLocalUserState("", currentChannelGroup); - - if (oldJsonChannelGroupState != jsonUserState) - { - stateChanged = true; - break; - } - } - } - - if (!stateChanged) - { - PNResult errRet = new PNResult(); - - StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); - PNStatus status = statusBuilder.CreateStatusResponse(PNOperationType.PNSetStateOperation, PNStatusCategory.PNUnknownCategory, null, (int)System.Net.HttpStatusCode.NotModified, null); - errRet.Status = status; - return errRet; - } - - } - } - - return await SharedSetUserState(filteredChannels, filteredChannelGroups, uuid, jsonUserState, jsonUserState, externalQueryParam).ConfigureAwait(false); - } - - private void SharedSetUserState(string[] channels, string[] channelGroups, string uuid, string jsonChannelUserState, string jsonChannelGroupUserState, Dictionary externalQueryParam, PNCallback callback) - { - List channelList; - List channelGroupList; - string currentUuid = uuid; - - string[] channelArray = null; - if (channels != null && channels.Length > 0) - { - channelList = new List(channels); - channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); - channelArray = channelList.ToArray(); - } - - string[] channelGroupsArray = null; - if (channelGroups != null && channelGroups.Length > 0) - { - channelGroupList = new List(channelGroups); - channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); - channelGroupsArray = channelGroupList.ToArray(); - } - - string commaDelimitedChannels = (channelArray != null && channelArray.Length > 0) ? string.Join(",", channelArray.OrderBy(x => x).ToArray()) : ""; - string commaDelimitedChannelGroups = (channelGroupsArray != null && channelGroupsArray.Length > 0) ? string.Join(",", channelGroupsArray.OrderBy(x => x).ToArray()) : ""; - - if (string.IsNullOrEmpty(uuid)) - { - currentUuid = config.UserId; - } - - string jsonUserState = GetJsonSharedSetUserStateInternal(channels, channelGroups, jsonChannelUserState, jsonChannelGroupUserState); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildSetUserStateRequest("GET", "", commaDelimitedChannels, commaDelimitedChannelGroups, currentUuid, jsonUserState, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channelArray; - requestState.ChannelGroups = channelGroupsArray; - requestState.ResponseType = PNOperationType.PNSetStateOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - //Set TerminateSubRequest to true to bounce the long-polling subscribe requests to update user state - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> SharedSetUserState(string[] channels, string[] channelGroups, string uuid, string jsonChannelUserState, string jsonChannelGroupUserState, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - List channelList; - List channelGroupList; - string currentUuid = uuid; - - string[] channelArray = null; - if (channels != null && channels.Length > 0) - { - channelList = new List(channels); - channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); - channelArray = channelList.ToArray(); - } - - string[] channelGroupsArray = null; - if (channelGroups != null && channelGroups.Length > 0) - { - channelGroupList = new List(channelGroups); - channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); - channelGroupsArray = channelGroupList.ToArray(); - } - - string commaDelimitedChannels = (channelArray != null && channelArray.Length > 0) ? string.Join(",", channelArray.OrderBy(x => x).ToArray()) : ""; - string commaDelimitedChannelGroups = (channelGroupsArray != null && channelGroupsArray.Length > 0) ? string.Join(",", channelGroupsArray.OrderBy(x => x).ToArray()) : ""; - - if (string.IsNullOrEmpty(uuid)) - { - currentUuid = config.UserId; - } - - string jsonUserState = GetJsonSharedSetUserStateInternal(channels, channelGroups, jsonChannelUserState, jsonChannelGroupUserState); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildSetUserStateRequest("GET", "", commaDelimitedChannels, commaDelimitedChannelGroups, currentUuid, jsonUserState, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channelArray; - requestState.ChannelGroups = channelGroupsArray; - requestState.ResponseType = PNOperationType.PNSetStateOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - //Set TerminateSubRequest to true to bounce the long-polling subscribe requests to update user state - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNSetStateResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private string GetJsonSharedSetUserStateInternal(string[] channels, string[] channelGroups, string jsonChannelUserState, string jsonChannelGroupUserState) - { - List channelList = new List(); - List channelGroupList = new List(); - - if (channels != null && channels.Length > 0) - { - channelList = new List(channels); - channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - channelGroupList = new List(channelGroups); - channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); - } - - Dictionary deserializeChannelUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonChannelUserState); - Dictionary deserializeChannelGroupUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonChannelGroupUserState); - - for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) - { - string currentChannel = channelList[channelIndex]; - - ChannelUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannel.Trim(), deserializeChannelUserState, (oldState, newState) => deserializeChannelUserState); - ChannelLocalUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannel.Trim(), deserializeChannelUserState, (oldState, newState) => deserializeChannelUserState); - } - - for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) - { - string currentChannelGroup = channelGroupList[channelGroupIndex]; - - ChannelGroupUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannelGroup.Trim(), deserializeChannelGroupUserState, (oldState, newState) => deserializeChannelGroupUserState); - ChannelGroupLocalUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannelGroup.Trim(), deserializeChannelGroupUserState, (oldState, newState) => deserializeChannelGroupUserState); - } - - string jsonUserState = "{}"; - - if ((jsonChannelUserState == jsonChannelGroupUserState) || (jsonChannelUserState != "{}" && jsonChannelGroupUserState == "{}")) - { - jsonUserState = jsonChannelUserState; - } - else if (jsonChannelUserState == "{}" && jsonChannelGroupUserState != "{}") - { - jsonUserState = jsonChannelGroupUserState; - } - else if (jsonChannelUserState != "{}" && jsonChannelGroupUserState != "{}") - { - jsonUserState = ""; - for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) - { - string currentChannel = channelList[channelIndex]; - - if (jsonUserState == "") - { - jsonUserState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", currentChannel, jsonChannelUserState); - } - else - { - jsonUserState = string.Format(CultureInfo.InvariantCulture, "{0},\"{1}\":{{{2}}}", jsonUserState, currentChannel, jsonChannelUserState); - } - } - for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) - { - string currentChannelGroup = channelGroupList[channelGroupIndex]; - - if (jsonUserState == "") - { - jsonUserState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", currentChannelGroup, jsonChannelGroupUserState); - } - else - { - jsonUserState = string.Format(CultureInfo.InvariantCulture, "{0},\"{1}\":{{{2}}}", jsonUserState, currentChannelGroup, jsonChannelGroupUserState); - } - } - jsonUserState = string.Format(CultureInfo.InvariantCulture, "{{{0}}}", jsonUserState); - } - - return jsonUserState; - } - - private string GetLocalUserState(string channel, string channelGroup) - { - string retJsonUserState = ""; - StringBuilder jsonStateBuilder = new StringBuilder(); - - string channelJsonUserState = BuildJsonUserState(channel, "", false); - string channelGroupJsonUserState = BuildJsonUserState("", channelGroup, false); - - if (channelJsonUserState.Trim().Length > 0 && channelGroupJsonUserState.Trim().Length <= 0) - { - jsonStateBuilder.Append(channelJsonUserState); - } - else if (channelJsonUserState.Trim().Length <= 0 && channelGroupJsonUserState.Trim().Length > 0) - { - jsonStateBuilder.Append(channelGroupJsonUserState); - } - else if (channelJsonUserState.Trim().Length > 0 && channelGroupJsonUserState.Trim().Length > 0) - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}:{1},{2}:{3}", channel, channelJsonUserState, channelGroup, channelGroupJsonUserState); - } - - if (jsonStateBuilder.Length > 0) - { - retJsonUserState = string.Format(CultureInfo.InvariantCulture, "{{{0}}}", jsonStateBuilder); - } - - return retJsonUserState; - } - } + SetUserState(this.channelNames, this.channelGroupNames, this.channelUUID, serializedState, this.queryParam, savedCallback); + } + + internal void SetUserState(string[] channels, string[] channelGroups, string uuid, string jsonUserState, Dictionary externalQueryParam, PNCallback callback) + { + if ((channels == null && channelGroups == null) + || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) { + throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); + } + + if (string.IsNullOrEmpty(jsonUserState) || string.IsNullOrEmpty(jsonUserState.Trim())) { + throw new ArgumentException("Missing User State"); + } + + List channelList = new List(); + List channelGroupList = new List(); + string[] filteredChannels = channels; + string[] filteredChannelGroups = channelGroups; + + if (channels != null && channels.Length > 0) { + channelList = new List(channels); + channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); + filteredChannels = channelList.ToArray(); + } + + if (channelGroups != null && channelGroups.Length > 0) { + channelGroupList = new List(channelGroups); + channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); + filteredChannelGroups = channelGroupList.ToArray(); + } + + if (!jsonLibrary.IsDictionaryCompatible(jsonUserState, PNOperationType.PNSetStateOperation)) { + throw new MissingMemberException("Missing json format for user state"); + } else { + Dictionary deserializeUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonUserState); + if (deserializeUserState == null) { + throw new MissingMemberException("Missing json format user state"); + } else { + bool stateChanged = false; + + for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) { + string currentChannel = channelList[channelIndex]; + + string oldJsonChannelState = GetLocalUserState(currentChannel, ""); + + if (oldJsonChannelState != jsonUserState) { + stateChanged = true; + break; + } + } + + if (!stateChanged) { + for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) { + string currentChannelGroup = channelGroupList[channelGroupIndex]; + + string oldJsonChannelGroupState = GetLocalUserState("", currentChannelGroup); + + if (oldJsonChannelGroupState != jsonUserState) { + stateChanged = true; + break; + } + } + } + + if (!stateChanged) { + StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); + PNStatus status = statusBuilder.CreateStatusResponse(PNOperationType.PNSetStateOperation, PNStatusCategory.PNUnknownCategory, null, (int)System.Net.HttpStatusCode.NotModified, null); + + Announce(status); + return; + } + + } + } + + SharedSetUserState(filteredChannels, filteredChannelGroups, uuid, jsonUserState, jsonUserState, externalQueryParam, callback); + } + + internal async Task> SetUserState(string[] channels, string[] channelGroups, string uuid, string jsonUserState, Dictionary externalQueryParam) + { + if ((channels == null && channelGroups == null) + || (channels != null && channelGroups != null && channels.Length == 0 && channelGroups.Length == 0)) { + throw new ArgumentException("Either Channel Or Channel Group or Both should be provided"); + } + + if (string.IsNullOrEmpty(jsonUserState) || string.IsNullOrEmpty(jsonUserState.Trim())) { + throw new ArgumentException("Missing User State"); + } + + List channelList = new List(); + List channelGroupList = new List(); + string[] filteredChannels = channels; + string[] filteredChannelGroups = channelGroups; + + if (channels != null && channels.Length > 0) { + channelList = new List(channels); + channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); + filteredChannels = channelList.ToArray(); + } + + if (channelGroups != null && channelGroups.Length > 0) { + channelGroupList = new List(channelGroups); + channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); + filteredChannelGroups = channelGroupList.ToArray(); + } + + if (!jsonLibrary.IsDictionaryCompatible(jsonUserState, PNOperationType.PNSetStateOperation)) { + throw new MissingMemberException("Missing json format for user state"); + } else { + Dictionary deserializeUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonUserState); + if (deserializeUserState == null) { + throw new MissingMemberException("Missing json format user state"); + } else { + bool stateChanged = false; + + for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) { + string currentChannel = channelList[channelIndex]; + + string oldJsonChannelState = GetLocalUserState(currentChannel, ""); + + if (oldJsonChannelState != jsonUserState) { + stateChanged = true; + break; + } + } + + if (!stateChanged) { + for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) { + string currentChannelGroup = channelGroupList[channelGroupIndex]; + + string oldJsonChannelGroupState = GetLocalUserState("", currentChannelGroup); + + if (oldJsonChannelGroupState != jsonUserState) { + stateChanged = true; + break; + } + } + } + + if (!stateChanged) { + PNResult errRet = new PNResult(); + + StatusBuilder statusBuilder = new StatusBuilder(config, jsonLibrary); + PNStatus status = statusBuilder.CreateStatusResponse(PNOperationType.PNSetStateOperation, PNStatusCategory.PNUnknownCategory, null, (int)System.Net.HttpStatusCode.NotModified, null); + errRet.Status = status; + return errRet; + } + + } + } + + return await SharedSetUserState(filteredChannels, filteredChannelGroups, uuid, jsonUserState, jsonUserState, externalQueryParam).ConfigureAwait(false); + } + + private void SharedSetUserState(string[] channels, string[] channelGroups, string uuid, string jsonChannelUserState, string jsonChannelGroupUserState, Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.Channels = channelNames; + requestState.ChannelGroups = channelGroupNames; + requestState.ResponseType = PNOperationType.PNSetStateOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetStateOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetStateOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> SharedSetUserState(string[] channels, string[] channelGroups, string uuid, string jsonChannelUserState, string jsonChannelGroupUserState, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = channelNames; + requestState.ChannelGroups = channelGroupNames; + requestState.ResponseType = PNOperationType.PNSetStateOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSetStateOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + requestState.GotJsonResponse = true; + if (errorStatus == null) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNSetStateResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSetStateOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private string GetJsonSharedSetUserStateInternal(string[] channels, string[] channelGroups, string jsonChannelUserState, string jsonChannelGroupUserState) + { + List channelList = new List(); + List channelGroupList = new List(); + + if (channels != null && channels.Length > 0) { + channelList = new List(channels); + channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); + } + + if (channelGroups != null && channelGroups.Length > 0) { + channelGroupList = new List(channelGroups); + channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); + } + + Dictionary deserializeChannelUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonChannelUserState); + Dictionary deserializeChannelGroupUserState = jsonLibrary.DeserializeToDictionaryOfObject(jsonChannelGroupUserState); + + for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) { + string currentChannel = channelList[channelIndex]; + + ChannelUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannel.Trim(), deserializeChannelUserState, (oldState, newState) => deserializeChannelUserState); + ChannelLocalUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannel.Trim(), deserializeChannelUserState, (oldState, newState) => deserializeChannelUserState); + } + + for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) { + string currentChannelGroup = channelGroupList[channelGroupIndex]; + + ChannelGroupUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannelGroup.Trim(), deserializeChannelGroupUserState, (oldState, newState) => deserializeChannelGroupUserState); + ChannelGroupLocalUserState[PubnubInstance.InstanceId].AddOrUpdate(currentChannelGroup.Trim(), deserializeChannelGroupUserState, (oldState, newState) => deserializeChannelGroupUserState); + } + + string jsonUserState = "{}"; + + if ((jsonChannelUserState == jsonChannelGroupUserState) || (jsonChannelUserState != "{}" && jsonChannelGroupUserState == "{}")) { + jsonUserState = jsonChannelUserState; + } else if (jsonChannelUserState == "{}" && jsonChannelGroupUserState != "{}") { + jsonUserState = jsonChannelGroupUserState; + } else if (jsonChannelUserState != "{}" && jsonChannelGroupUserState != "{}") { + jsonUserState = ""; + for (int channelIndex = 0; channelIndex < channelList.Count; channelIndex++) { + string currentChannel = channelList[channelIndex]; + + if (jsonUserState == "") { + jsonUserState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", currentChannel, jsonChannelUserState); + } else { + jsonUserState = string.Format(CultureInfo.InvariantCulture, "{0},\"{1}\":{{{2}}}", jsonUserState, currentChannel, jsonChannelUserState); + } + } + for (int channelGroupIndex = 0; channelGroupIndex < channelGroupList.Count; channelGroupIndex++) { + string currentChannelGroup = channelGroupList[channelGroupIndex]; + + if (jsonUserState == "") { + jsonUserState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", currentChannelGroup, jsonChannelGroupUserState); + } else { + jsonUserState = string.Format(CultureInfo.InvariantCulture, "{0},\"{1}\":{{{2}}}", jsonUserState, currentChannelGroup, jsonChannelGroupUserState); + } + } + jsonUserState = string.Format(CultureInfo.InvariantCulture, "{{{0}}}", jsonUserState); + } + + return jsonUserState; + } + + private string GetLocalUserState(string channel, string channelGroup) + { + string retJsonUserState = ""; + StringBuilder jsonStateBuilder = new StringBuilder(); + + string channelJsonUserState = BuildJsonUserState(channel, "", false); + string channelGroupJsonUserState = BuildJsonUserState("", channelGroup, false); + + if (channelJsonUserState.Trim().Length > 0 && channelGroupJsonUserState.Trim().Length <= 0) { + jsonStateBuilder.Append(channelJsonUserState); + } else if (channelJsonUserState.Trim().Length <= 0 && channelGroupJsonUserState.Trim().Length > 0) { + jsonStateBuilder.Append(channelGroupJsonUserState); + } else if (channelJsonUserState.Trim().Length > 0 && channelGroupJsonUserState.Trim().Length > 0) { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}:{1},{2}:{3}", channel, channelJsonUserState, channelGroup, channelGroupJsonUserState); + } + + if (jsonStateBuilder.Length > 0) { + retJsonUserState = string.Format(CultureInfo.InvariantCulture, "{{{0}}}", jsonStateBuilder); + } + + return retJsonUserState; + } + + private RequestParameter CreateRequestParameter() + { + List channelList; + List channelGroupList; + string requestUuid = string.IsNullOrEmpty(channelUUID) ? config.UserId : channelUUID; + + string[] channelArray = null; + if (channelNames != null && channelNames.Length > 0) { + channelList = new List(channelNames); + channelList = channelList.Where(ch => !string.IsNullOrEmpty(ch) && ch.Trim().Length > 0).Distinct().ToList(); + channelArray = channelList.ToArray(); + } + + string[] channelGroupsArray = null; + if (channelGroupNames != null && channelGroupNames.Length > 0) { + channelGroupList = new List(channelGroupNames); + channelGroupList = channelGroupList.Where(cg => !string.IsNullOrEmpty(cg) && cg.Trim().Length > 0).Distinct().ToList(); + channelGroupsArray = channelGroupList.ToArray(); + } + + string commaDelimitedChannels = (channelArray != null && channelArray.Length > 0) ? string.Join(",", channelArray.OrderBy(x => x).ToArray()) : ""; + string commaDelimitedChannelGroups = (channelGroupsArray != null && channelGroupsArray.Length > 0) ? string.Join(",", channelGroupsArray.OrderBy(x => x).ToArray()) : ""; + + string serialisedState = jsonLibrary.SerializeToJsonString(userState); + string jsonUserState = GetJsonSharedSetUserStateInternal(channelArray, channelGroupsArray, serialisedState, serialisedState); + + string internalChannelsCommaDelimited; + + if (string.IsNullOrEmpty(commaDelimitedChannels) || commaDelimitedChannels.Trim().Length <= 0) { + internalChannelsCommaDelimited = ","; + } else { + internalChannelsCommaDelimited = commaDelimitedChannels; + } + + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config.SubscribeKey, + "channel", + internalChannelsCommaDelimited, + "uuid", + requestUuid, + "data" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (!string.IsNullOrEmpty(commaDelimitedChannelGroups) && commaDelimitedChannelGroups.Trim().Length > 0) { + requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(jsonUserState, PNOperationType.PNSetStateOperation, false, false, false)); + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(commaDelimitedChannelGroups, PNOperationType.PNSetStateOperation, false, false, false)); + } else { + requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(jsonUserState, PNOperationType.PNSetStateOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSetStateOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Presence/WhereNowOperation.cs b/src/Api/PubnubApi/EndPoint/Presence/WhereNowOperation.cs index e8056d7e4..e3060bf87 100644 --- a/src/Api/PubnubApi/EndPoint/Presence/WhereNowOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Presence/WhereNowOperation.cs @@ -1,195 +1,177 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class WhereNowOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string whereNowUUID = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public WhereNowOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public WhereNowOperation Uuid(string uuid) - { - this.whereNowUUID = uuid; - return this; - } - - public WhereNowOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - WhereNow(this.whereNowUUID, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - WhereNow(this.whereNowUUID, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await WhereNow(this.whereNowUUID, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - WhereNow(this.whereNowUUID, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - WhereNow(this.whereNowUUID, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void WhereNow(string uuid, Dictionary externalQueryParam, PNCallback callback) - { - if (jsonLibrary == null) - { - throw new MissingMemberException("Missing Json Pluggable Library for Pubnub Instance"); - } - - string currentUuid = ""; - if (string.IsNullOrEmpty(uuid)) - { - currentUuid = config.UserId; - } - else - { - currentUuid = uuid; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildWhereNowRequest("GET", "", currentUuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { currentUuid }; - requestState.ResponseType = PNOperationType.PNWhereNowOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> WhereNow(string uuid, Dictionary externalQueryParam) - { - if (jsonLibrary == null) - { - throw new MissingMemberException("Missing Json Pluggable Library for Pubnub Instance"); - } - - PNResult ret = new PNResult(); - string currentUuid = ""; - if (string.IsNullOrEmpty(uuid)) - { - currentUuid = config.UserId; - } - else - { - currentUuid = uuid; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildWhereNowRequest("GET", "", currentUuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { currentUuid }; - requestState.ResponseType = PNOperationType.PNWhereNowOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNWhereNowResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class WhereNowOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string whereNowUUID = string.Empty; + private PNCallback savedCallback; + private Dictionary queryParam; + + public WhereNowOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public WhereNowOperation Uuid(string uuid) + { + this.whereNowUUID = uuid; + return this; + } + + public WhereNowOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + WhereNow(this.whereNowUUID, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await WhereNow(this.whereNowUUID, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + WhereNow(this.whereNowUUID, this.queryParam, savedCallback); + } + + internal void WhereNow(string uuid, Dictionary externalQueryParam, PNCallback callback) + { + if (jsonLibrary == null) { + throw new MissingMemberException("Missing Json Pluggable Library for Pubnub Instance"); + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { whereNowUUID ?? config.UserId }; + requestState.ResponseType = PNOperationType.PNWhereNowOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNWhereNowOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNWhereNowOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + internal async Task> WhereNow(string uuid, Dictionary externalQueryParam) + { + if (jsonLibrary == null) { + throw new MissingMemberException("Missing Json Pluggable Library for Pubnub Instance"); + } + + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = new[] { whereNowUUID ?? config.UserId }; + requestState.ResponseType = PNOperationType.PNWhereNowOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNWhereNowOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNWhereNowResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNWhereNowOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + private RequestParameter CreateRequestParameter() + { + + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config.SubscribeKey, + "uuid", + string.IsNullOrEmpty(whereNowUUID) ? config.UserId : whereNowUUID + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNWhereNowOperation, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/AddMessageActionOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/AddMessageActionOperation.cs index 926036467..d60f3e771 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/AddMessageActionOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/AddMessageActionOperation.cs @@ -1,249 +1,250 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Globalization; namespace PubnubApi.EndPoint { - public class AddMessageActionOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string msgActionChannelName = ""; - private long messageTimetoken; - private PNMessageAction addMessageAction; - private PNCallback savedCallback; - private Dictionary queryParam; - - public AddMessageActionOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - - public AddMessageActionOperation Channel(string channelName) - { - msgActionChannelName = channelName; - return this; - } - - /// - /// The publish timetoken of a parent message - /// - /// - /// - public AddMessageActionOperation MessageTimetoken(long timetoken) - { - messageTimetoken = timetoken; - return this; - } - - public AddMessageActionOperation Action(PNMessageAction messageAction) - { - addMessageAction = messageAction; - return this; - } - - public AddMessageActionOperation QueryParam(Dictionary customQueryParam) - { - queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) - { - throw new MissingMemberException("subscribe key is required"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - Publish(this.msgActionChannelName, this.messageTimetoken, this.addMessageAction, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - Publish(this.msgActionChannelName, this.messageTimetoken, this.addMessageAction, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) - { - throw new MissingMemberException("subscribe key is required"); - } - - return await Publish(this.msgActionChannelName, this.messageTimetoken, this.addMessageAction, this.queryParam).ConfigureAwait(false); - } - - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - Publish(this.msgActionChannelName, this.messageTimetoken, this.addMessageAction, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - Publish(this.msgActionChannelName, this.messageTimetoken, this.addMessageAction, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void Publish(string channel, long messageTimetoken, PNMessageAction messageAction, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || messageAction == null) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); - callback.OnResponse(null, status); - return; - } - - if (callback == null) - { - return; - } - - string requestMethodName = "POST"; - string postMessage = jsonLibrary.SerializeToJsonString(messageAction); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildAddMessageActionRequest(requestMethodName, postMessage, channel, messageTimetoken, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNAddMessageActionOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - requestState.UsePostMethod = true; - - UrlProcessRequest(request, requestState, false, postData).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - ProcessResponseCallbacks(result, requestState); - } - CleanUp(); - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> Publish(string channel, long messageTimetoken, PNMessageAction messageAction, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || messageAction == null) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); - ret.Status = status; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); - ret.Status = status; - return ret; - } - - string requestMethodName = "POST"; - string postMessage = jsonLibrary.SerializeToJsonString(messageAction); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildAddMessageActionRequest(requestMethodName, postMessage, channel, messageTimetoken, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNAddMessageActionOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - requestState.UsePostMethod = true; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, postData).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNAddMessageActionResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private void CleanUp() - { - this.savedCallback = null; - } - } - + public class AddMessageActionOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelName = ""; + private long messageTimetoken; + private PNMessageAction messageAction; + private PNCallback savedCallback; + private Dictionary queryParam; + + public AddMessageActionOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + } + + + public AddMessageActionOperation Channel(string channel) + { + channelName = channel; + return this; + } + + /// + /// The publish timetoken of a parent message + /// + /// + /// + public AddMessageActionOperation MessageTimetoken(long timetoken) + { + messageTimetoken = timetoken; + return this; + } + + public AddMessageActionOperation Action(PNMessageAction messageAction) + { + this.messageAction = messageAction; + return this; + } + + public AddMessageActionOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) { + throw new MissingMemberException("subscribe key is required"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + + savedCallback = callback; + Publish(channelName, messageTimetoken, messageAction, queryParam, callback); + } + + public async Task> ExecuteAsync() + { + if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) { + throw new MissingMemberException("subscribe key is required"); + } + + return await Publish(this.channelName, this.messageTimetoken, this.messageAction, this.queryParam).ConfigureAwait(false); + } + + + internal void Retry() + { + Publish(this.channelName, this.messageTimetoken, this.messageAction, this.queryParam, savedCallback); + } + + private void Publish(string channel, long messageTimetoken, PNMessageAction messageAction, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(channelName) || string.IsNullOrEmpty(channelName.Trim()) || messageAction == null) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); + callback.OnResponse(null, status); + return; + } + + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channelName }; + requestState.ResponseType = PNOperationType.PNAddMessageActionOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = true; + Tuple JsonAndStatusTuple; + + var requestParameters = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameters, PNOperationType.PNPublishOperation); + + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + if (t.Result.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) + { + List result = ProcessJsonResponse(requestState, json); + ProcessResponseCallbacks(result, requestState); + } else { + requestState.PubnubCallback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNAddMessageActionResult), status); + } + CleanUp(); + }); + } + + private async Task> Publish(string channel, long messageTimetoken, PNMessageAction messageAction, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || messageAction == null) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); + returnValue.Status = status; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); + returnValue.Status = status; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNAddMessageActionOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + requestState.UsePostMethod = true; + + Tuple JsonAndStatusTuple; + + var requestParams = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParams, operationType: PNOperationType.PNAddMessageActionOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNAddMessageActionResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } else { + returnValue.Status = errorStatus; + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNAddMessageActionOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List urlSegments = new List() { + "v1", + "message-actions", + config.SubscribeKey, + "channel", + this.channelName, + "message", + messageTimetoken.ToString(CultureInfo.InvariantCulture) + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNAddMessageActionOperation, false, false, false)); + } + } + } + + string postMessage = jsonLibrary.SerializeToJsonString(messageAction); + var requestParam = new RequestParameter() { + RequestType = Constants.POST, + PathSegment = urlSegments, + BodyContentString = postMessage, + Query = requestQueryStringParams + }; + return requestParam; + } + + private void CleanUp() + { + this.savedCallback = null; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/FireOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/FireOperation.cs index e51c10e30..1a98f1ba1 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/FireOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/FireOperation.cs @@ -1,337 +1,304 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Net; -#if !NET35 && !NET40 +using PubnubApi.Security.Crypto; +using PubnubApi.Security.Crypto.Cryptors; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class FireOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private object msg; - private string channelName = ""; - private bool httpPost; - private Dictionary userMetadata; - private readonly int ttl = -1; - private PNCallback savedCallback; - private bool syncRequest; - private Dictionary queryParam; - - public FireOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public FireOperation Message(object message) - { - this.msg = message; - return this; - } - - public FireOperation Channel(string channelName) - { - this.channelName = channelName; - return this; - } - - public FireOperation Meta(Dictionary metadata) - { - this.userMetadata = metadata; - return this; - } - - public FireOperation UsePOST(bool post) - { - this.httpPost = post; - return this; - } - - public FireOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim()) || this.msg == null) - { - throw new ArgumentException("Missing Channel or Message"); - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - throw new MissingMemberException("Invalid publish key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - syncRequest = false; - this.savedCallback = callback; - Fire(this.channelName, this.msg, false, this.ttl, this.userMetadata, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - syncRequest = false; - this.savedCallback = callback; - Fire(this.channelName, this.msg, false, this.ttl, this.userMetadata, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - syncRequest = false; - return await Fire(this.channelName, this.msg, false, this.ttl, this.userMetadata, this.queryParam).ConfigureAwait(false); - } - - public PNPublishResult Sync() - { - System.Threading.ManualResetEvent syncEvent = new System.Threading.ManualResetEvent(false); - Task task = Task.Factory.StartNew(() => - { - syncRequest = true; - syncEvent = new System.Threading.ManualResetEvent(false); - Fire(this.channelName, this.msg, false, this.ttl, this.userMetadata, this.queryParam, new PNPublishResultExt((r,s)=> { SyncResult = r; syncEvent.Set(); })); - syncEvent.WaitOne(config.NonSubscribeRequestTimeout * 1000); - - return SyncResult; - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); - return task.Result; - } - - private static PNPublishResult SyncResult { get; set; } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - if (!syncRequest) - { - Fire(this.channelName, this.msg, false, this.ttl, this.userMetadata, this.queryParam, savedCallback); - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - if (!syncRequest) - { - Fire(this.channelName, this.msg, false, this.ttl, this.userMetadata, this.queryParam, savedCallback); - } - }) - { IsBackground = true }.Start(); -#endif - } - - private void Fire(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) - { - PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; - callback.OnResponse(null, status); - return; - } - - if (callback == null) - { - return; - } - - Dictionary urlParam = new Dictionary(); - urlParam.Add("norep", "true"); - - string requestMethodName = (this.httpPost) ? "POST" : "GET"; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildPublishRequest(requestMethodName, "", channel, message, storeInHistory, ttl, metaData, urlParam, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { channel }; - requestState.ResponseType = PNOperationType.PNFireOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - string json = ""; - - if (this.httpPost) - { - requestState.UsePostMethod = true; - Dictionary messageEnvelope = new Dictionary(); - messageEnvelope.Add("message", message); - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - UrlProcessRequest(request, requestState, false, postData).ContinueWith(r => - { - json = r.Result.Item1; - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - else - { - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - json = r.Result.Item1; - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - ProcessResponseCallbacks(result, requestState); - } - else - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFireOperation, category, requestState, 400, new PNException(json)); - if (requestState.PubnubCallback != null) - { - requestState.PubnubCallback.OnResponse(default(PNPublishResult), status); - } - } - } - else - { - ProcessResponseCallbacks(result, requestState); - } - } - } - - private async Task> Fire(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; - ret.Status = errStatus; - return ret; - } - - Dictionary urlParam = new Dictionary(); - urlParam.Add("norep", "true"); - - string requestMethodName = (this.httpPost) ? "POST" : "GET"; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildPublishRequest(requestMethodName, "", channel, message, storeInHistory, ttl, metaData, urlParam, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNFireOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple; - - if (this.httpPost) - { - requestState.UsePostMethod = true; - Dictionary messageEnvelope = new Dictionary(); - messageEnvelope.Add("message", message); - string postMessage = jsonLibrary.SerializeToJsonString(messageEnvelope); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, postData).ConfigureAwait(false); - } - else - { - JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - } - - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class FireOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private object publishContent; + private string channelName = ""; + private bool httpPost; + private Dictionary userMetadata; + private readonly int ttl = -1; + private PNCallback savedCallback; + private bool syncRequest; + private Dictionary queryParam; + + public FireOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public FireOperation Message(object message) + { + this.publishContent = message; + return this; + } + + public FireOperation Channel(string channelName) + { + this.channelName = channelName; + return this; + } + + public FireOperation Meta(Dictionary metadata) + { + this.userMetadata = metadata; + return this; + } + + public FireOperation UsePOST(bool post) + { + this.httpPost = post; + return this; + } + + public FireOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim()) || this.publishContent == null) { + throw new ArgumentException("Missing Channel or Message"); + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + throw new MissingMemberException("Invalid publish key"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + Fire(this.channelName, this.publishContent, false, this.ttl, this.userMetadata, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + syncRequest = false; + return await Fire(this.channelName, this.publishContent, false, this.ttl, this.userMetadata, this.queryParam).ConfigureAwait(false); + } + + public PNPublishResult Sync() + { + System.Threading.ManualResetEvent syncEvent = new System.Threading.ManualResetEvent(false); + syncRequest = true; + syncEvent = new System.Threading.ManualResetEvent(false); + Fire(this.channelName, this.publishContent, false, this.ttl, this.userMetadata, this.queryParam, new PNPublishResultExt((r, s) => { SyncResult = r; syncEvent.Set(); })); + syncEvent.WaitOne(config.NonSubscribeRequestTimeout * 1000); + return SyncResult; + } + + private static PNPublishResult SyncResult { get; set; } + + internal void Retry() + { + Fire(this.channelName, this.publishContent, false, this.ttl, this.userMetadata, this.queryParam, savedCallback); + } + + private void Fire(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) { + PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; + callback.OnResponse(null, status); + return; + } + + if (callback == null) { + return; + } + + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNFireOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNFireOperation); + + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + if (result != null && result.Count >= 3) { + int publishStatus; + var _ = Int32.TryParse(result[0].ToString(), out publishStatus); + if (publishStatus == 1) { + ProcessResponseCallbacks(result, requestState); + } else { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFireOperation, category, requestState, 400, new PNException(responseString)); + if (requestState.PubnubCallback != null) { + requestState.PubnubCallback.OnResponse(default(PNPublishResult), status); + } + } + } else { + ProcessResponseCallbacks(result, requestState); + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFireOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNPublishResult), status); + } + }); + } + + private async Task> Fire(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNFireOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNFireOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List result = ProcessJsonResponse(requestState, json); + if (result != null && result.Count >= 3) { + int publishStatus; + _ = int.TryParse(result[0].ToString(), out publishStatus); + if (publishStatus == 1) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFireOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private RequestParameter CreateRequestParameter() + { + List urlSegments = new List + { + "publish", + config.PublishKey?? "", + config.SubscribeKey??"", + "0", + channelName, + "0" + }; + if (!httpPost) { + urlSegments.Add(PrepareContent(this.publishContent)); + } + Dictionary requestQueryStringParams = new Dictionary(); + + if (userMetadata != null) { + string jsonMetaData = jsonLibrary.SerializeToJsonString(userMetadata); + requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, PNOperationType.PNPublishOperation, false, false, false)); + } + requestQueryStringParams.Add("norep", "true"); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNPublishOperation, false, false, false)); + } + } + } + var requestParam = new RequestParameter() { + RequestType = httpPost ? Constants.POST : Constants.GET, + PathSegment = urlSegments, + Query = requestQueryStringParams + }; + if (httpPost) { + string postMessage = PrepareContent(publishContent); + requestParam.BodyContentString = postMessage; + } + return requestParam; + } + private string PrepareContent(object originalMessage) + { + string message = jsonLibrary.SerializeToJsonString(originalMessage); + if (config.CryptoModule != null || config.CipherKey.Length > 0) { + config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); + string encryptMessage = config.CryptoModule.Encrypt(message); + message = jsonLibrary.SerializeToJsonString(encryptMessage); + } + return message; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/GetMessageActionsOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/GetMessageActionsOperation.cs index 163c30bf1..aa4a9a460 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/GetMessageActionsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/GetMessageActionsOperation.cs @@ -1,241 +1,257 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class GetMessageActionsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string messageActionChannelName = ""; - private long startTT = -1; - private long endTT = -1; - private int limitRecords = -1; - private PNCallback savedCallback; - private Dictionary queryParam; - - public GetMessageActionsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - public GetMessageActionsOperation Channel(string channelName) - { - messageActionChannelName = channelName; - return this; - } - - public GetMessageActionsOperation Start(long startTimetoken) - { - startTT = startTimetoken; - return this; - } - - public GetMessageActionsOperation End(long endTimetoken) - { - endTT = endTimetoken; - return this; - } - - public GetMessageActionsOperation Limit(int numberOfRecords) - { - limitRecords = numberOfRecords; - return this; - } - - public GetMessageActionsOperation QueryParam(Dictionary customQueryParam) - { - queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) - { - throw new MissingMemberException("subscribe key is required"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetMessageActions(this.messageActionChannelName, this.startTT, this.endTT, this.limitRecords, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetMessageActions(this.messageActionChannelName, this.startTT, this.endTT, this.limitRecords, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) - { - throw new MissingMemberException("subscribe key is required"); - } - - return await GetMessageActions(this.messageActionChannelName, this.startTT, this.endTT, this.limitRecords, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetMessageActions(this.messageActionChannelName, this.startTT, this.endTT, this.limitRecords, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetMessageActions(this.messageActionChannelName, this.startTT, this.endTT, this.limitRecords, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void GetMessageActions(string channel, long start, long end, int limit, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); - callback.OnResponse(null, status); - return; - } - - if (callback == null) - { - return; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetMessageActionsRequest("GET", "", channel, start, end, limit, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNGetMessageActionsOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - ProcessResponseCallbacks(result, requestState); - } - - CleanUp(); - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> GetMessageActions(string channel, long start, long end, int limit, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); - ret.Status = status; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); - ret.Status = status; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetMessageActionsRequest("GET", "", channel, start, end, limit, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNGetMessageActionsOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNGetMessageActionsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private void CleanUp() - { - this.savedCallback = null; - } - } + public class GetMessageActionsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string messageActionChannelName = ""; + private long startTimetoken = -1; + private long endTimetoken = -1; + private int limit = -1; + private PNCallback savedCallback; + private Dictionary queryParam; + + public GetMessageActionsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + public GetMessageActionsOperation Channel(string channelName) + { + messageActionChannelName = channelName; + return this; + } + + public GetMessageActionsOperation Start(long startTimetoken) + { + this.startTimetoken = startTimetoken; + return this; + } + + public GetMessageActionsOperation End(long endTimetoken) + { + this.endTimetoken = endTimetoken; + return this; + } + + public GetMessageActionsOperation Limit(int numberOfRecords) + { + limit = numberOfRecords; + return this; + } + + public GetMessageActionsOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) { + throw new MissingMemberException("subscribe key is required"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + + GetMessageActions(this.messageActionChannelName, this.startTimetoken, this.endTimetoken, this.limit, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) { + throw new MissingMemberException("subscribe key is required"); + } + + return await GetMessageActions(this.messageActionChannelName, this.startTimetoken, this.endTimetoken, this.limit, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetMessageActions(this.messageActionChannelName, this.startTimetoken, this.endTimetoken, this.limit, this.queryParam, savedCallback); + } + + private void GetMessageActions(string channel, long start, long end, int limit, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(messageActionChannelName) || string.IsNullOrEmpty(messageActionChannelName.Trim())) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); + callback.OnResponse(null, status); + return; + } + + if (callback == null) { + return; + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { messageActionChannelName }; + requestState.ResponseType = PNOperationType.PNGetMessageActionsOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + string responseString; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetMessageActionsOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + if (t.Result.Error == null) { + responseString = Encoding.UTF8.GetString(t.Result.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + ProcessResponseCallbacks(null, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNGetMessageActionsResult), status); + } + }); + CleanUp(); + } + + private async Task> GetMessageActions(string channel, long start, long end, int limit, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); + returnValue.Status = status; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); + returnValue.Status = status; + return returnValue; + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNGetMessageActionsOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNGetMessageActionsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNGetMessageActionsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNGetMessageActionsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private void CleanUp() + { + this.savedCallback = null; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "message-actions", + config.SubscribeKey, + "channel", + messageActionChannelName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (startTimetoken >= 0) { + requestQueryStringParams.Add("start", startTimetoken.ToString(CultureInfo.InvariantCulture)); + } + if (endTimetoken >= 0) { + requestQueryStringParams.Add("end", endTimetoken.ToString(CultureInfo.InvariantCulture)); + } + if (limit >= 0) { + requestQueryStringParams.Add("limit", limit.ToString(CultureInfo.InvariantCulture)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNGetMessageActionsOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/ListenerManager.cs b/src/Api/PubnubApi/EndPoint/PubSub/ListenerManager.cs index f31dfcf5e..34ba64eb5 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/ListenerManager.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/ListenerManager.cs @@ -16,7 +16,7 @@ public class ListenerManager : PubnubCoreBase private readonly PNConfiguration pubnubConfig; private readonly IPubnubLog pubnubLog; - public ListenerManager(PNConfiguration config, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(config, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public ListenerManager(PNConfiguration config, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(config, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { this.pubnubConfig = config; this.pubnubLog = log; diff --git a/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs index de3e175f1..48a14aa6a 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/PublishOperation.cs @@ -1,410 +1,351 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Threading; -using System.Net; using PubnubApi.Security.Crypto.Cryptors; using PubnubApi.Security.Crypto; -#if !NET35 && !NET40 +using System.Globalization; using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class PublishOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private object msg; - private string channelName = ""; - private bool storeInHistory = true; - private bool httpPost; - private Dictionary userMetadata; - private int ttl = -1; - private PNCallback savedCallback; - private bool syncRequest; - private Dictionary queryParam; - - public PublishOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - - public PublishOperation Message(object message) - { - this.msg = message; - return this; - } - - public PublishOperation Channel(string channelName) - { - this.channelName = channelName; - return this; - } - - public PublishOperation ShouldStore(bool store) - { - this.storeInHistory = store; - return this; - } - - public PublishOperation Meta(Dictionary metadata) - { - this.userMetadata = metadata; - return this; - } - - public PublishOperation UsePOST(bool post) - { - this.httpPost = post; - return this; - } - - /// - /// tttl in hours - /// - /// - /// - public PublishOperation Ttl(int ttl) - { - this.ttl = ttl; - return this; - } - - public PublishOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(channelName.Trim()) || this.msg == null) - { - throw new ArgumentException("Missing Channel or Message"); - } - - if (config == null || string.IsNullOrEmpty(config.PublishKey) || config.PublishKey.Trim().Length <= 0) - { - throw new MissingMemberException("publish key is required"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - syncRequest = false; - this.savedCallback = callback; - Publish(this.channelName, this.msg, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - syncRequest = false; - this.savedCallback = callback; - Publish(this.channelName, this.msg, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - syncRequest = false; - return await Publish(this.channelName, this.msg, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam).ConfigureAwait(false); - } - - public PNPublishResult Sync() - { - if (this.msg == null) - { - throw new ArgumentException("message cannot be null"); - } - - if (config == null || string.IsNullOrEmpty(config.PublishKey) || config.PublishKey.Trim().Length <= 0) - { - throw new MissingMemberException("publish key is required"); - } - - System.Threading.ManualResetEvent syncEvent = new System.Threading.ManualResetEvent(false); - Task task = Task.Factory.StartNew(() => - { - syncRequest = true; - syncEvent = new System.Threading.ManualResetEvent(false); - Publish(this.channelName, this.msg, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, new PNPublishResultExt((r, s) => { SyncResult = r; syncEvent.Set(); })); - syncEvent.WaitOne(config.NonSubscribeRequestTimeout * 1000); - - return SyncResult; - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); - return task.Result; - } - - private static PNPublishResult SyncResult { get; set; } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - if (!syncRequest) - { - Publish(this.channelName, this.msg, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, savedCallback); - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - if (!syncRequest) - { - Publish(this.channelName, this.msg, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, savedCallback); - } - }) - { IsBackground = true }.Start(); -#endif - } - - internal void Publish(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")); - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid publish key", new MissingMemberException("Invalid publish key")); - callback.OnResponse(null, status); - return; - } - - if (callback == null) - { - return; - } - - RequestState requestState = new RequestState(); - try - { - string requestMethodName = (this.httpPost) ? "POST" : "GET"; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildPublishRequest(requestMethodName, "", channel, message, storeInHistory, ttl, metaData, null, externalQueryParam); - - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNPublishOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - string json = ""; - - if (this.httpPost) - { - requestState.UsePostMethod = true; - string postMessage = JsonEncodePublishMsg(message); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - UrlProcessRequest(request, requestState, false, postData).ContinueWith(r => - { - json = r.Result.Item1; - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - else - { - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - json = r.Result.Item1; - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - ProcessResponseCallbacks(result, requestState); - } - else - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, 400, new PNException(json)); - if (requestState.PubnubCallback != null) - { - requestState.PubnubCallback.OnResponse(default(PNPublishResult), status); - } - } - } - else - { - ProcessResponseCallbacks(result, requestState); - } - } - - CleanUp(); - } - catch (Exception ex) - { - int statusCode = PNStatusCodeHelper.GetHttpStatusCode(ex.ToString()); - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, ex.ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(ex.ToString())); - if (requestState.PubnubCallback != null) - { - requestState.PubnubCallback.OnResponse(default(PNPublishResult), status); - } - - } - } - - internal async Task> Publish(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) - { - PNStatus errStatus = new PNStatus(); - errStatus.Error = true; - errStatus.ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")); - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - PNStatus errStatus = new PNStatus(); - errStatus.Error = true; - errStatus.ErrorData = new PNErrorData("Invalid publish key", new MissingMemberException("Invalid publish key")); - ret.Status = errStatus; - return ret; - } - - RequestState requestState = new RequestState(); - try - { - string requestMethodName = (this.httpPost) ? "POST" : "GET"; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildPublishRequest(requestMethodName, "", channel, message, storeInHistory, ttl, metaData, null, externalQueryParam); - - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNPublishOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple; - - if (this.httpPost) - { - requestState.UsePostMethod = true; - string postMessage = JsonEncodePublishMsg(message); - byte[] postData = Encoding.UTF8.GetBytes(postMessage); - JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false, postData).ConfigureAwait(false); - } - else - { - JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - } - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - } - } - } - catch (Exception ex) - { - int statusCode = PNStatusCodeHelper.GetHttpStatusCode(ex.ToString()); - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, ex.ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(ex.ToString())); - ret.Status = status; - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - private string JsonEncodePublishMsg(object originalMessage) - { - string message = jsonLibrary.SerializeToJsonString(originalMessage); - if (config.CryptoModule != null || config.CipherKey.Length > 0) - { - config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); - string encryptMessage = config.CryptoModule.Encrypt(message); - message = jsonLibrary.SerializeToJsonString(encryptMessage); - } - return message; - } - - private void CleanUp() - { - this.savedCallback = null; - } - } + public class PublishOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private object publishContent; + private string channelName = ""; + private bool storeInHistory = true; + private bool httpPost; + private Dictionary userMetadata; + private int ttl = -1; + private PNCallback savedCallback; + private bool syncRequest; + private Dictionary queryParam; + + public PublishOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public PublishOperation Message(object message) + { + this.publishContent = message; + return this; + } + + public PublishOperation Channel(string channelName) + { + this.channelName = channelName; + return this; + } + + public PublishOperation ShouldStore(bool store) + { + this.storeInHistory = store; + return this; + } + + public PublishOperation Meta(Dictionary metadata) + { + this.userMetadata = metadata; + return this; + } + + public PublishOperation UsePOST(bool post) + { + this.httpPost = post; + return this; + } + + /// + /// ttl in hours + /// + /// + /// + public PublishOperation Ttl(int ttl) + { + this.ttl = ttl; + return this; + } + + public PublishOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(channelName.Trim()) || this.publishContent == null) { + throw new ArgumentException("Missing Channel or Message"); + } + + if (config == null || string.IsNullOrEmpty(config.PublishKey) || config.PublishKey.Trim().Length <= 0) { + throw new MissingMemberException("publish key is required"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + this.savedCallback = callback; + Publish(channelName, this.publishContent, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + syncRequest = false; + return await Publish(this.channelName, this.publishContent, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam).ConfigureAwait(false); + } + + public PNPublishResult Sync() + { + if (this.publishContent == null) { + throw new ArgumentException("message cannot be null"); + } + + if (config == null || string.IsNullOrEmpty(config.PublishKey) || config.PublishKey.Trim().Length <= 0) { + throw new MissingMemberException("publish key is required"); + } + + ManualResetEvent syncEvent = new System.Threading.ManualResetEvent(false); + Task task = Task.Factory.StartNew(() => { + syncRequest = true; + syncEvent = new System.Threading.ManualResetEvent(false); + Publish(this.channelName, this.publishContent, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, new PNPublishResultExt((r, s) => { SyncResult = r; syncEvent.Set(); })); + syncEvent.WaitOne(config.NonSubscribeRequestTimeout * 1000); + + return SyncResult; + }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); + return task.Result; + } + + private static PNPublishResult SyncResult { get; set; } + + internal void Retry() + { + Publish(this.channelName, this.publishContent, this.storeInHistory, this.ttl, this.userMetadata, this.queryParam, savedCallback); + } + + internal void Publish(string channel, object message, bool storeInHistory, int ttl, Dictionary userMetadata, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")); + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid publish key", new MissingMemberException("Invalid publish key")); + callback.OnResponse(null, status); + return; + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNPublishOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameters = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameters, operationType: PNOperationType.PNPublishOperation); + + PubnubInstance.transportMiddleware.Send(transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + if (result != null && result.Count >= 3) { + _ = int.TryParse(result[0].ToString(), out var publishStatus); + if (publishStatus == 1) { + ProcessResponseCallbacks(result, requestState); + } else { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, 400, new PNException(responseString)); + if (requestState.PubnubCallback != null) { + requestState.PubnubCallback.OnResponse(default, status); + } + } + } else { + ProcessResponseCallbacks(result, requestState); + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + CleanUp(); + } + + internal async Task> Publish(string channel, object message, bool storeInHistory, int ttl, Dictionary metaData, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) { + PNStatus errStatus = new PNStatus + { + Error = true, + ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) + }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + PNStatus errStatus = new PNStatus(); + errStatus.Error = true; + errStatus.ErrorData = new PNErrorData("Invalid publish key", new MissingMemberException("Invalid publish key")); + returnValue.Status = errStatus; + return returnValue; + } + RequestState requestState = new RequestState(); + Tuple JsonAndStatusTuple; + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNPublishOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNPublishOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, Constants.HttpRequestSuccessStatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + + if (!string.IsNullOrEmpty(json)) { + List result = ProcessJsonResponse(requestState, json); + + if (result is { Count: >= 3 }) { + _ = int.TryParse(result[0].ToString(), out var publishStatus); + if (publishStatus == 1) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList is { Count: > 0 }) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } + } + } else { + var statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private string PrepareContent(object originalMessage) + { + string message = jsonLibrary.SerializeToJsonString(originalMessage); + if (config.CryptoModule != null || config.CipherKey.Length > 0) { + config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, config.UseRandomInitializationVector, pubnubLog), null); + string encryptMessage = config.CryptoModule.Encrypt(message); + message = jsonLibrary.SerializeToJsonString(encryptMessage); + } + return message; + } + + private RequestParameter CreateRequestParameter() + { + List urlSegments = new List + { + "publish", + config.PublishKey?? "", + config.SubscribeKey??"", + "0", + channelName, + "0" + }; + if (!httpPost) { + urlSegments.Add(PrepareContent(this.publishContent)); + } + Dictionary requestQueryStringParams = new Dictionary(); + + if (userMetadata != null) { + string jsonMetaData = jsonLibrary.SerializeToJsonString(userMetadata); + requestQueryStringParams.Add("meta", UriUtil.EncodeUriComponent(jsonMetaData, PNOperationType.PNPublishOperation, false, false, false)); + } + + if (storeInHistory && ttl >= 0) { + requestQueryStringParams.Add("tt1", ttl.ToString(CultureInfo.InvariantCulture)); + } + + if (!storeInHistory) { + requestQueryStringParams.Add("store", "0"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNPublishOperation, false, false, false)); + } + } + } + + var requestParam = new RequestParameter() { + RequestType = httpPost ? Constants.POST : Constants.GET, + PathSegment = urlSegments, + Query = requestQueryStringParams + }; + if (httpPost) { + string postMessage = PrepareContent(publishContent); + requestParam.BodyContentString = postMessage; + } + return requestParam; + } + + private void CleanUp() + { + savedCallback = null; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/RemoveMessageActionOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/RemoveMessageActionOperation.cs index e7da08f46..24e7b9626 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/RemoveMessageActionOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/RemoveMessageActionOperation.cs @@ -1,251 +1,250 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Globalization; namespace PubnubApi.EndPoint { - public class RemoveMessageActionOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private string msgActionChannelName = ""; - private long messageTimetoken; - private long actionTimetoken; - private string msgActionUuid; - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemoveMessageActionOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - public RemoveMessageActionOperation Channel(string channelName) - { - msgActionChannelName = channelName; - return this; - } - - /// - /// The publish timetoken of a parent message - /// - /// - /// - public RemoveMessageActionOperation MessageTimetoken(long timetoken) - { - messageTimetoken = timetoken; - return this; - } - - /// - /// The publish timetoken of the action - /// - /// - /// - public RemoveMessageActionOperation ActionTimetoken(long timetoken) - { - actionTimetoken = timetoken; - return this; - } - - public RemoveMessageActionOperation Uuid(string messageActionUuid) - { - msgActionUuid = messageActionUuid; - return this; - } - - public RemoveMessageActionOperation QueryParam(Dictionary customQueryParam) - { - queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) - { - throw new MissingMemberException("subscribe key is required"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveMessageAction(this.msgActionChannelName, this.messageTimetoken, this.actionTimetoken, this.msgActionUuid, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveMessageAction(this.msgActionChannelName, this.messageTimetoken, this.actionTimetoken, this.msgActionUuid, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) - { - throw new MissingMemberException("subscribe key is required"); - } - - return await RemoveMessageAction(this.msgActionChannelName, this.messageTimetoken, this.actionTimetoken, this.msgActionUuid, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveMessageAction(this.msgActionChannelName, this.messageTimetoken, this.actionTimetoken, this.msgActionUuid, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveMessageAction(this.msgActionChannelName, this.messageTimetoken, this.actionTimetoken, this.msgActionUuid, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void RemoveMessageAction(string channel, long messageTimetoken, long actionTimetoken, string messageActionUuid, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); - callback.OnResponse(null, status); - return; - } - - if (callback == null) - { - return; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildRemoveMessageActionRequest("DELETE", "", channel, messageTimetoken, actionTimetoken, messageActionUuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNRemoveMessageActionOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - ProcessResponseCallbacks(result, requestState); - } - - CleanUp(); - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> RemoveMessageAction(string channel, long messageTimetoken, long actionTimetoken, string messageActionUuid, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); - ret.Status = status; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus(); - status.Error = true; - status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); - ret.Status = status; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildRemoveMessageActionRequest("DELETE", "", channel, messageTimetoken, actionTimetoken, messageActionUuid, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNRemoveMessageActionOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNRemoveMessageActionResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - private void CleanUp() - { - this.savedCallback = null; - } - } + public class RemoveMessageActionOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private string channelName = ""; + private long messageTimetoken; + private long actionTimetoken; + private string actionUuid; + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemoveMessageActionOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + } + + public RemoveMessageActionOperation Channel(string channelName) + { + this.channelName = channelName; + return this; + } + + /// + /// The publish timetoken of a parent message + /// + /// + /// + public RemoveMessageActionOperation MessageTimetoken(long timetoken) + { + messageTimetoken = timetoken; + return this; + } + + /// + /// The publish timetoken of the action + /// + /// + /// + public RemoveMessageActionOperation ActionTimetoken(long timetoken) + { + actionTimetoken = timetoken; + return this; + } + + public RemoveMessageActionOperation Uuid(string messageActionUuid) + { + actionUuid = messageActionUuid; + return this; + } + + public RemoveMessageActionOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) { + throw new MissingMemberException("subscribe key is required"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + RemoveMessageAction(this.channelName, this.messageTimetoken, this.actionTimetoken, this.actionUuid, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + if (config == null || string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length <= 0) { + throw new MissingMemberException("subscribe key is required"); + } + + return await RemoveMessageAction(this.channelName, this.messageTimetoken, this.actionTimetoken, this.actionUuid, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RemoveMessageAction(this.channelName, this.messageTimetoken, this.actionTimetoken, this.actionUuid, this.queryParam, savedCallback); + } + + private void RemoveMessageAction(string channel, long messageTimetoken, long actionTimetoken, string messageActionUuid, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); + callback.OnResponse(null, status); + return; + } + + if (callback == null) { + return; + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNRemoveMessageActionOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveMessageActionOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + if (t.Result.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveMessageActionOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default(PNRemoveMessageActionResult), status); + } + CleanUp(); + }); + } + + private async Task> RemoveMessageAction(string channel, long messageTimetoken, long actionTimetoken, string messageActionUuid, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Missing Channel or MessageAction", new ArgumentException("Missing Channel or MessageAction")); + returnValue.Status = status; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus(); + status.Error = true; + status.ErrorData = new PNErrorData("Invalid subscribe key", new MissingMemberException("Invalid subscribe key")); + returnValue.Status = status; + return returnValue; + } + + RequestState requestState = new RequestState(); + Tuple JsonAndStatusTuple; + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNRemoveMessageActionOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNRemoveMessageActionOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNRemoveMessageActionResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNRemoveMessageActionOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private void CleanUp() + { + this.savedCallback = null; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "v1", + "message-actions", + config.SubscribeKey, + "channel", + channelName, + "message", + messageTimetoken.ToString(CultureInfo.InvariantCulture), + "action", + actionTimetoken.ToString(CultureInfo.InvariantCulture) + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (actionUuid != null) { + requestQueryStringParams.Add("uuid", UriUtil.EncodeUriComponent(actionUuid, PNOperationType.PNRemoveMessageActionOperation, false, false, false)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNRemoveMessageActionOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.DELETE, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs index ba2610a85..31fb5f5b1 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SignalOperation.cs @@ -1,283 +1,232 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; -using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class SignalOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private object msg; - private string channelName = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public SignalOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public SignalOperation Message(object message) - { - msg = message; - return this; - } - - public SignalOperation Channel(string channelName) - { - this.channelName = channelName; - return this; - } - - public SignalOperation QueryParam(Dictionary customQueryParam) - { - queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(channelName.Trim()) || this.msg == null) - { - throw new ArgumentException("Missing Channel or Message"); - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - throw new MissingMemberException("Invalid publish key"); - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - throw new MissingMemberException("Invalid subscribe key"); - } - - if (callback == null) - { - throw new ArgumentException("Missing userCallback"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - try - { - Signal(this.channelName, this.msg, null, this.queryParam, callback); - } - catch(Exception ex) - { - PNStatus unexpectedExceptionStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Unexpected exception", ex) }; - callback.OnResponse(null, unexpectedExceptionStatus); - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - try - { - Signal(this.channelName, this.msg, null, this.queryParam, callback); - } - catch(Exception ex) - { - PNStatus unexpectedExceptionStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Unexpected exception", ex) }; - callback.OnResponse(null, unexpectedExceptionStatus); - } - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await Signal(this.channelName, this.msg, null, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - Signal(this.channelName, this.msg, null, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - Signal(this.channelName, this.msg, null, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void Signal(string channel, object message, Dictionary metaData, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) - { - PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message"))}; - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; - callback.OnResponse(null, status); - return; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid subscribe key", new ArgumentException("Invalid subscribe key")) }; - callback.OnResponse(null, status); - return; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildSignalRequest("GET", "", channel, message, metaData, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNSignalOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - - if (result != null && result.Count >= 3) - { - int signalStatus; - var _ = Int32.TryParse(result[0].ToString(), out signalStatus); - if (signalStatus == 1) - { - ProcessResponseCallbacks(result, requestState); - } - else - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSignalOperation, category, requestState, 400, new PNException(json)); - if (requestState.PubnubCallback != null) - { - requestState.PubnubCallback.OnResponse(default(PNPublishResult), status); - } - } - } - else - { - ProcessResponseCallbacks(result, requestState); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - private async Task> Signal(string channel, object message, Dictionary metaData, Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid subscribe key", new ArgumentException("Invalid subscribe key")) }; - ret.Status = errStatus; - return ret; - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildSignalRequest("GET", "", channel, message, metaData, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNSignalOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - if (result != null && result.Count >= 3) - { - int publishStatus; - var _ = Int32.TryParse(result[0].ToString(), out publishStatus); - if (publishStatus == 1) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - else - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); - PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSignalOperation, category, requestState, 400, new PNException(json)); - ret.Status = status; - ret.Result = default(PNPublishResult); - } - } - } - } - - return ret; - } - } + public class SignalOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private object signalMessage; + private string channelName = string.Empty; + private PNCallback savedCallback; + private Dictionary queryParam; + + public SignalOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public SignalOperation Message(object message) + { + signalMessage = message; + return this; + } + + public SignalOperation Channel(string channelName) + { + this.channelName = channelName; + return this; + } + + public SignalOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(channelName.Trim()) || this.signalMessage == null) { + throw new ArgumentException("Missing Channel or Message"); + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + throw new MissingMemberException("Invalid publish key"); + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + throw new MissingMemberException("Invalid subscribe key"); + } + + if (callback == null) { + throw new ArgumentException("Missing userCallback"); + } + Signal(this.channelName, this.signalMessage, null, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await Signal(this.channelName, this.signalMessage, null, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + Signal(this.channelName, this.signalMessage, null, this.queryParam, savedCallback); + } + + private void Signal(string channel, object message, Dictionary metaData, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) { + PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; + callback.OnResponse(null, status); + return; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus status = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid subscribe key", new ArgumentException("Invalid subscribe key")) }; + callback.OnResponse(null, status); + return; + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNSignalOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameters = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameters, operationType: PNOperationType.PNSignalOperation); + PubnubInstance.transportMiddleware.Send(transportRequest).ContinueWith(t => { + if (t.Result.Error == null) { + var responseString = Encoding.UTF8.GetString(t.Result.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + + if (result != null && result.Count >= 3) + { + _ = Int32.TryParse(result[0].ToString(), out var signalStatus); + if (signalStatus == 1) { + ProcessResponseCallbacks(result, requestState); + } else { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(400, result[1].ToString()); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSignalOperation, category, requestState, 400, new PNException(responseString)); + requestState.PubnubCallback.OnResponse(default, status); + } + } else { + ProcessResponseCallbacks(result, requestState); + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(t.Result.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, t.Result.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSignalOperation, category, requestState, statusCode, new PNException(t.Result.Error.Message, t.Result.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + private async Task> Signal(string channel, object message, Dictionary metaData, Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim()) || message == null) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing Channel or Message", new ArgumentException("Missing Channel or Message")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.PublishKey) || string.IsNullOrEmpty(config.PublishKey.Trim()) || config.PublishKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid publish key", new ArgumentException("Invalid publish key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(config.SubscribeKey) || string.IsNullOrEmpty(config.SubscribeKey.Trim()) || config.SubscribeKey.Length <= 0) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid subscribe key", new ArgumentException("Invalid subscribe key")) }; + returnValue.Status = errStatus; + return returnValue; + } + + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNSignalOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSignalOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + string responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, Constants.HttpRequestSuccessStatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple("", errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + if (result != null && result.Count >= 3) + { + _ = int.TryParse(result[0].ToString(), out var publishStatus); + if (publishStatus == 1) { + List resultList = ProcessJsonResponse(requestState, responseString); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPublishResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } else { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(transportResponse.StatusCode, result[1].ToString()); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNSignalOperation, category, requestState, transportResponse.StatusCode, new PNException(responseString)); + returnValue.Status = status; + returnValue.Result = default; + } + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNPublishOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List urlSegments = new List() + { + "signal", + config.PublishKey, + config.SubscribeKey, + "0", + channelName, + "0", + jsonLibrary.SerializeToJsonString(this.signalMessage) + }; + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = urlSegments + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs index 133ec8eae..5e13ca538 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeEndpoint.cs @@ -15,7 +15,6 @@ public class SubscribeEndpoint: ISubscribeOperation private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private readonly EndPoint.TokenManager pubnubTokenMgr; private List subscribeChannelNames = new List(); @@ -36,14 +35,13 @@ public List SubscribeListenerList set; } = new List(); - public SubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager,SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceOperation presenceOperation , string instanceId, Pubnub instance) + public SubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager,SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceOperation presenceOperation , string instanceId, Pubnub instance) { PubnubInstance = instance; config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; pubnubTokenMgr = tokenManager; this.subscribeEventEngineFactory = subscribeEventEngineFactory; this.presenceOperation = presenceOperation; @@ -125,7 +123,7 @@ private void Subscribe(string[] channels, string[] channelGroups, SubscriptionCu if (subscribeEventEngineFactory.HasEventEngine(instanceId)) { subscribeEventEngine = subscribeEventEngineFactory.GetEventEngine(instanceId); } else { - var subscribeManager = new SubscribeManager2(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); + var subscribeManager = new SubscribeManager2(config, jsonLibrary, unit, pubnubLog, pubnubTokenMgr, PubnubInstance); subscribeEventEngine = subscribeEventEngineFactory.InitializeEventEngine(instanceId, PubnubInstance, config, subscribeManager, this.EventEmitter, jsonLibrary, StatusEmitter); subscribeEventEngine.OnStateTransition += SubscribeEventEngine_OnStateTransition; subscribeEventEngine.OnEventQueued += SubscribeEventEngine_OnEventQueued; diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs index 01801cbe9..026ee5130 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager.cs @@ -2,1486 +2,992 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Net; using System.Threading.Tasks; using System.Globalization; -#if !NET35 && !NET40 +using System.Text; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - internal class SubscribeManager : PubnubCoreBase, IDisposable - { - private static ConcurrentDictionary config { get; } = new ConcurrentDictionary(); - private static IJsonPluggableLibrary jsonLibrary; - private static IPubnubUnitTest unit; - private static IPubnubLog pubnubLog; - private static EndPoint.TelemetryManager pubnubTelemetryMgr; - - private static Timer SubscribeHeartbeatCheckTimer; - private Timer multiplexExceptionTimer; - private Dictionary customQueryParam; - - public SubscribeManager(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config.AddOrUpdate(instance.InstanceId, pubnubConfig, (k, o) => pubnubConfig); - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - -#pragma warning disable - internal void MultiChannelUnSubscribeAll(PNOperationType type, Dictionary externalQueryParam) -#pragma warning restore - { - //Retrieve the current channels already subscribed previously and terminate them - string[] currentChannels = (MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelSubscribe[PubnubInstance.InstanceId] != null) ? new List(MultiChannelSubscribe[PubnubInstance.InstanceId].Keys).ToArray() : null; - string[] currentChannelGroups = (MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelGroupSubscribe[PubnubInstance.InstanceId] != null) ? new List(MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys).ToArray() : null; - - if (currentChannels != null && currentChannels.Length >= 0) - { - string multiChannelName = (currentChannels.Length > 0) ? string.Join(",", currentChannels.OrderBy(x => x).ToArray()) : ","; - string multiChannelGroupName = (currentChannelGroups.Length > 0) ? string.Join(",", currentChannelGroups.OrderBy(x => x).ToArray()) : ""; - - Task.Factory.StartNew(() => - { - if (ChannelRequest[PubnubInstance.InstanceId].ContainsKey(multiChannelName)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Aborting previous subscribe/presence requests having channel(s)={1}; channelgroup(s)={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - - HttpWebRequest webRequest; - ChannelRequest[PubnubInstance.InstanceId].TryGetValue(multiChannelName, out webRequest); - ChannelRequest[PubnubInstance.InstanceId].TryUpdate(multiChannelName, null, webRequest); - - HttpWebRequest removedRequest; - bool removedChannel = ChannelRequest[PubnubInstance.InstanceId].TryRemove(multiChannelName, out removedRequest); - if (removedChannel) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Success to remove channel(s)={1}; channelgroup(s)={2} from _channelRequest (MultiChannelUnSubscribeInit).", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to remove channel(s)={1}; channelgroup(s)={2} from _channelRequest (MultiChannelUnSubscribeInit).", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - if (webRequest != null) - { - TerminatePendingWebRequest(webRequest); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to capture channel(s)={1}; channelgroup(s)={2} from _channelRequest to abort request.", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - - if (type == PNOperationType.PNUnsubscribeOperation && config.ContainsKey(PubnubInstance.InstanceId) && !config[PubnubInstance.InstanceId].SuppressLeaveEvents) - { - //just fire leave() event to REST API for safeguard - string channelsJsonState = BuildJsonUserState(currentChannels, currentChannelGroups, false); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config[PubnubInstance.InstanceId], jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildMultiChannelLeaveRequest("GET", "", currentChannels, currentChannelGroups, channelsJsonState, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = currentChannels; - requestState.ChannelGroups = currentChannelGroups; - requestState.ResponseType = PNOperationType.Leave; - requestState.Reconnect = false; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - MultiChannelSubscribe[PubnubInstance.InstanceId].Clear(); - MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Clear(); - }); - } - } - - } - - internal void MultiChannelUnSubscribeInit(PNOperationType type, string channel, string channelGroup, Dictionary externalQueryParam) - { - List validChannels = new List(); - List validChannelGroups = new List(); - - try - { - this.customQueryParam = externalQueryParam; - - if (PubnubInstance == null) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, PubnubInstance is null. exiting MultiChannelUnSubscribeInit", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - return; - } - - if (!MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - MultiChannelSubscribe.GetOrAdd(PubnubInstance.InstanceId, new ConcurrentDictionary()); - } - if (!MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - MultiChannelGroupSubscribe.GetOrAdd(PubnubInstance.InstanceId, new ConcurrentDictionary()); - } - - string[] rawChannels = (channel != null && channel.Trim().Length > 0) ? channel.Split(',') : new string[] { }; - string[] rawChannelGroups = (channelGroup != null && channelGroup.Trim().Length > 0) ? channelGroup.Split(',') : new string[] { }; - - if (rawChannels.Length > 0) - { - for (int index = 0; index < rawChannels.Length; index++) - { - if (rawChannels[index].Trim().Length > 0) - { - string channelName = rawChannels[index].Trim(); - if (string.IsNullOrEmpty(channelName)) - { - continue; - } - - if (config.ContainsKey(PubnubInstance.InstanceId) && MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelSubscribe[PubnubInstance.InstanceId] != null && !MultiChannelSubscribe[PubnubInstance.InstanceId].ContainsKey(channelName)) - { - PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNUnexpectedDisconnectCategory, null, (int)HttpStatusCode.NotFound, null); - if (!status.AffectedChannels.Contains(channelName)) - { - status.AffectedChannels.Add(channelName); - } - Announce(status); - } - else - { - validChannels.Add(channelName); - string presenceChannelName = string.Format(CultureInfo.InvariantCulture, "{0}-pnpres", channelName); - if (MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelSubscribe[PubnubInstance.InstanceId] != null && MultiChannelSubscribe[PubnubInstance.InstanceId].ContainsKey(presenceChannelName)) - { - validChannels.Add(presenceChannelName); - } - } - } - } - } - - if (rawChannelGroups.Length > 0) - { - for (int index = 0; index < rawChannelGroups.Length; index++) - { - if (rawChannelGroups[index].Trim().Length > 0) - { - string channelGroupName = rawChannelGroups[index].Trim(); - if (string.IsNullOrEmpty(channelGroupName)) - { - continue; - } - - if (config.ContainsKey(PubnubInstance.InstanceId) && MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelGroupSubscribe[PubnubInstance.InstanceId] != null && !MultiChannelGroupSubscribe[PubnubInstance.InstanceId].ContainsKey(channelGroupName)) - { - PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNUnexpectedDisconnectCategory, null, (int)HttpStatusCode.NotFound, null); - if (!status.AffectedChannelGroups.Contains(channelGroupName)) - { - status.AffectedChannelGroups.Add(channelGroupName); - } - Announce(status); - } - else - { - validChannelGroups.Add(channelGroupName); - string presenceChannelGroupName = string.Format(CultureInfo.InvariantCulture, "{0}-pnpres", channelGroupName); - if (MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelGroupSubscribe[PubnubInstance.InstanceId] != null && MultiChannelGroupSubscribe[PubnubInstance.InstanceId].ContainsKey(presenceChannelGroupName)) - { - validChannelGroups.Add(presenceChannelGroupName); - } - } - } - } - } - - if (validChannels.Count > 0 || validChannelGroups.Count > 0) - { - //Retrieve the current channels already subscribed previously and terminate them - string[] currentChannels = new List(MultiChannelSubscribe[PubnubInstance.InstanceId].Keys).ToArray(); - string[] currentChannelGroups = new List(MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys).ToArray(); - - if (currentChannels != null && currentChannels.Length >= 0) - { - string multiChannelName = (currentChannels.Length > 0) ? string.Join(",", currentChannels.OrderBy(x => x).ToArray()) : ","; - string multiChannelGroupName = (currentChannelGroups.Length > 0) ? string.Join(",", currentChannelGroups.OrderBy(x => x).ToArray()) : ""; - - Task.Factory.StartNew(() => - { - if (ChannelRequest[PubnubInstance.InstanceId].ContainsKey(multiChannelName)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Aborting previous subscribe/presence requests having channel(s)={1}; channelgroup(s)={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - - HttpWebRequest webRequest; - ChannelRequest[PubnubInstance.InstanceId].TryGetValue(multiChannelName, out webRequest); - ChannelRequest[PubnubInstance.InstanceId].TryUpdate(multiChannelName, null, webRequest); - - HttpWebRequest removedRequest; - bool removedChannel = ChannelRequest[PubnubInstance.InstanceId].TryRemove(multiChannelName, out removedRequest); - if (removedChannel) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Success to remove channel(s)={1}; channelgroup(s)={2} from _channelRequest (MultiChannelUnSubscribeInit).", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to remove channel(s)={1}; channelgroup(s)={2} from _channelRequest (MultiChannelUnSubscribeInit).", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - if (webRequest != null) - { - TerminatePendingWebRequest(webRequest); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to capture channel(s)={1}; channelgroup(s)={2} from _channelRequest to abort request.", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - - if (type == PNOperationType.PNUnsubscribeOperation && config.ContainsKey(PubnubInstance.InstanceId)) - { - //just fire leave() event to REST API for safeguard - string channelsJsonState = BuildJsonUserState(validChannels.ToArray(), validChannelGroups.ToArray(), false); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config[PubnubInstance.InstanceId], jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildMultiChannelLeaveRequest("GET", "", validChannels.ToArray(), validChannelGroups.ToArray(), channelsJsonState, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { channel }; - requestState.ChannelGroups = new [] { channelGroup }; - requestState.ResponseType = PNOperationType.Leave; - requestState.Reconnect = false; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => { }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - } - - Dictionary originalMultiChannelSubscribe = null; - Dictionary originalMultiChannelGroupSubscribe = null; - if (PubnubInstance != null && MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - originalMultiChannelSubscribe = MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0 ? MultiChannelSubscribe[PubnubInstance.InstanceId].ToDictionary(kvp => kvp.Key, kvp => kvp.Value) : null; - } - if (PubnubInstance != null && MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - originalMultiChannelGroupSubscribe = MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0 ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].ToDictionary(kvp => kvp.Key, kvp => kvp.Value) : null; - } - - PNStatus successStatus = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNDisconnectedCategory, null, (int)HttpStatusCode.OK, null); - PNStatus failStatus = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNDisconnectedCategory, null, (int)HttpStatusCode.NotFound, new PNException("Unsubscribe Error. Please retry unsubscribe operation")); - bool successExist = false; - bool failExist = false; - - //Remove the valid channels from subscribe list for unsubscribe - for (int index = 0; index < validChannels.Count; index++) - { - long timetokenValue; - string channelToBeRemoved = validChannels[index]; - bool unsubscribeStatus = false; - if (PubnubInstance != null && MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - unsubscribeStatus = MultiChannelSubscribe[PubnubInstance.InstanceId].TryRemove(channelToBeRemoved, out timetokenValue); - } - if (channelToBeRemoved.Contains("-pnpres")) - { - continue; //Do not send status for -pnpres channels - } - if (unsubscribeStatus) - { - successExist = true; - if (!successStatus.AffectedChannels.Contains(channelToBeRemoved)) - { - successStatus.AffectedChannels.Add(channelToBeRemoved); - } - - base.DeleteLocalChannelUserState(channelToBeRemoved); - } - else - { - failExist = true; - if (!failStatus.AffectedChannels.Contains(channelToBeRemoved)) - { - failStatus.AffectedChannels.Add(channelToBeRemoved); - } - } - } - for (int index = 0; index < validChannelGroups.Count; index++) - { - long timetokenValue; - string channelGroupToBeRemoved = validChannelGroups[index]; - bool unsubscribeStatus = false; - if (PubnubInstance != null && MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - unsubscribeStatus = MultiChannelGroupSubscribe[PubnubInstance.InstanceId].TryRemove(channelGroupToBeRemoved, out timetokenValue); - } - if (channelGroupToBeRemoved.Contains("-pnpres")) - { - continue; //Do not send status for -pnpres channel-groups - } - if (unsubscribeStatus) - { - successExist = true; - if (!successStatus.AffectedChannelGroups.Contains(channelGroupToBeRemoved)) - { - successStatus.AffectedChannelGroups.Add(channelGroupToBeRemoved); - } - - base.DeleteLocalChannelGroupUserState(channelGroupToBeRemoved); - } - else - { - failExist = true; - if (!failStatus.AffectedChannelGroups.Contains(channelGroupToBeRemoved)) - { - failStatus.AffectedChannelGroups.Add(channelGroupToBeRemoved); - } - } - } - - if (successExist && PubnubInstance != null) - { - Announce(successStatus); - } - - if (failExist && PubnubInstance != null) - { - Announce(failStatus); - } - - //Get all the channels - string[] channels = new string[] { }; - string[] channelGroups = new string[] { }; - - if (PubnubInstance != null && MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - channels = MultiChannelSubscribe[PubnubInstance.InstanceId].Keys.ToArray(); - //Check any chained subscribes while unsubscribe - for (int keyIndex = 0; keyIndex < MultiChannelSubscribe[PubnubInstance.InstanceId].Count; keyIndex++) - { - KeyValuePair kvp = MultiChannelSubscribe[PubnubInstance.InstanceId].ElementAt(keyIndex); - if (originalMultiChannelSubscribe != null && !originalMultiChannelSubscribe.ContainsKey(kvp.Key)) - { - return; - } - } - } - - if (PubnubInstance != null && MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId)) - { - channelGroups = MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys.ToArray(); - for (int keyIndex = 0; keyIndex < MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count; keyIndex++) - { - KeyValuePair kvp = MultiChannelGroupSubscribe[PubnubInstance.InstanceId].ElementAt(keyIndex); - if (originalMultiChannelGroupSubscribe != null && !originalMultiChannelGroupSubscribe.ContainsKey(kvp.Key)) - { - return; - } - } - } - - channels = (channels != null) ? channels : new string[] { }; - channelGroups = (channelGroups != null) ? channelGroups : new string[] { }; - - if (channels.Length > 0 || channelGroups.Length > 0) - { - string multiChannel = (channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - - RequestState state = new RequestState(); - ChannelRequest[PubnubInstance.InstanceId].AddOrUpdate(multiChannel, state.Request, (key, oldValue) => state.Request); - - ResetInternetCheckSettings(channels, channelGroups); - - - //Continue with any remaining channels for subscribe/presence - MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, channels, channelGroups, 0, 0, false, null, this.customQueryParam); - } - else - { - if (PresenceHeartbeatTimer != null) - { - // Stop the presence heartbeat timer if there are no channels subscribed - PresenceHeartbeatTimer.Dispose(); - PresenceHeartbeatTimer = null; - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, All channels are Unsubscribed. Further subscription was stopped", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager=> MultiChannelUnSubscribeInit \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", validChannels.OrderBy(x => x).ToArray()), string.Join(",", validChannelGroups.OrderBy(x => x).ToArray()), ex), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - - internal void MultiChannelSubscribeInit(PNOperationType responseType, string[] rawChannels, string[] rawChannelGroups, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) - { - List validChannels = new List(); - List validChannelGroups = new List(); - - try - { - bool channelGroupSubscribeOnly = false; - SubscribeDisconnected[PubnubInstance.InstanceId] = false; - - if (rawChannels != null && rawChannels.Length > 0) - { - string[] rawChannelsFiltered = rawChannels; - if (rawChannels.Length != rawChannels.Distinct().Count()) - { - rawChannelsFiltered = rawChannels.Distinct().ToArray(); - } - - for (int index = 0; index < rawChannelsFiltered.Length; index++) - { - if (rawChannelsFiltered[index].Trim().Length > 0) - { - string channelName = rawChannelsFiltered[index].Trim(); - if (!string.IsNullOrEmpty(channelName)) - { - if (MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId) && !MultiChannelSubscribe[PubnubInstance.InstanceId].ContainsKey(channelName)) - { - validChannels.Add(channelName); - } - } - } - } - } - - if (rawChannelGroups != null && rawChannelGroups.Length > 0) - { - string[] rawChannelGroupsFiltered = rawChannelGroups; - if (rawChannelGroups.Length != rawChannelGroups.Distinct().Count()) - { - rawChannelGroupsFiltered = rawChannelGroups.Distinct().ToArray(); - } - - for (int index = 0; index < rawChannelGroupsFiltered.Length; index++) - { - if (rawChannelGroupsFiltered[index].Trim().Length > 0) - { - string channelGroupName = rawChannelGroupsFiltered[index].Trim(); - if (MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId) && !MultiChannelGroupSubscribe[PubnubInstance.InstanceId].ContainsKey(channelGroupName)) - { - validChannelGroups.Add(channelGroupName); - } - } - } - } - - if (validChannels.Count > 0 || validChannelGroups.Count > 0 && config.ContainsKey(PubnubInstance.InstanceId)) - { - //Retrieve the current channels already subscribed previously and terminate them - List currentChannelsList = new List(MultiChannelSubscribe[PubnubInstance.InstanceId].Keys); - List currentChannelGroupsList = new List(MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys); - string[] currentChannels = new List(currentChannelsList).ToArray(); - string[] currentChannelGroups = new List(currentChannelGroupsList).ToArray(); - - if (currentChannels != null && currentChannels.Length >= 0) - { - string multiChannelGroupName = (currentChannelGroups.Length > 0) ? string.Join(",", currentChannelGroups.OrderBy(x => x).ToArray()) : ""; - if (ChannelRequest.ContainsKey(PubnubInstance.InstanceId)) - { - List keysList = new List(ChannelRequest[PubnubInstance.InstanceId].Keys); - for (int keyIndex = 0; keyIndex < keysList.Count; keyIndex++) - { - string multiChannelName = keysList[keyIndex]; - if (ChannelRequest[PubnubInstance.InstanceId].ContainsKey(multiChannelName)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Aborting previous subscribe/presence requests having channel(s)={1}; channelgroup(s)={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - HttpWebRequest webRequest; - ChannelRequest[PubnubInstance.InstanceId].TryGetValue(multiChannelName, out webRequest); - ChannelRequest[PubnubInstance.InstanceId].TryUpdate(multiChannelName, null, webRequest); - - HttpWebRequest removedRequest; - bool removedChannel = ChannelRequest[PubnubInstance.InstanceId].TryRemove(multiChannelName, out removedRequest); - if (removedChannel) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Success to remove channel(s)={1}; channelgroup(s)={2} from _channelRequest (MultiChannelSubscribeInit).", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to remove channel(s)={1}; channelgroup(s)={2} from _channelRequest (MultiChannelSubscribeInit).", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - if (webRequest != null) - { - TerminatePendingWebRequest(webRequest); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to capture channel(s)={1}; channelgroup(s)={2} from _channelRequest to abort request.", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannelName, multiChannelGroupName), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unable to find instance id = {1} from _channelRequest.", DateTime.Now.ToString(CultureInfo.InvariantCulture), PubnubInstance.InstanceId), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - - TerminateCurrentSubscriberRequest(); - - //Add the valid channels to the channels subscribe list for tracking - for (int index = 0; index < validChannels.Count; index++) - { - string currentLoopChannel = validChannels[index]; - MultiChannelSubscribe[PubnubInstance.InstanceId].GetOrAdd(currentLoopChannel, 0); - } - - - for (int index = 0; index < validChannelGroups.Count; index++) - { - string currentLoopChannelGroup = validChannelGroups[index]; - MultiChannelGroupSubscribe[PubnubInstance.InstanceId].GetOrAdd(currentLoopChannelGroup, 0); - } - - //Get all the channels - string[] channels = new List(MultiChannelSubscribe[PubnubInstance.InstanceId].Keys).ToArray(); - string[] channelGroups = new List(MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys).ToArray(); - - if (channelGroups != null && channelGroups.Length > 0 && (channels == null || channels.Length == 0)) - { - channelGroupSubscribeOnly = true; - } - - RequestState state = new RequestState(); - if (ChannelRequest.ContainsKey(PubnubInstance.InstanceId)) - { - if (channelGroupSubscribeOnly) - { - ChannelRequest[PubnubInstance.InstanceId].AddOrUpdate(",", state.Request, (key, oldValue) => state.Request); - } - else - { - ChannelRequest[PubnubInstance.InstanceId].AddOrUpdate(string.Join(",", channels.OrderBy(x => x).ToArray()), state.Request, (key, oldValue) => state.Request); - } - } - - ResetInternetCheckSettings(channels, channelGroups); - MultiChannelSubscribeRequest(responseType, channels, channelGroups, 0, 0, false, initialSubscribeUrlParams, externalQueryParam); - - if (SubscribeHeartbeatCheckTimer != null) - { - try - { - SubscribeHeartbeatCheckTimer.Change(Timeout.Infinite, Timeout.Infinite); - } - catch { /* ignore */ } - } - SubscribeHeartbeatCheckTimer = new Timer(StartSubscribeHeartbeatCheckCallback, null, config[PubnubInstance.InstanceId].SubscribeTimeout * 500, config[PubnubInstance.InstanceId].SubscribeTimeout * 500); - } - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager=> MultiChannelSubscribeInit \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", validChannels.OrderBy(x => x).ToArray()), string.Join(",", validChannelGroups.OrderBy(x => x).ToArray()), ex), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - - private void MultiChannelSubscribeRequest(PNOperationType type, string[] channels, string[] channelGroups, object timetoken, int region, bool reconnect, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) - { - if (!config.ContainsKey(PubnubInstance.InstanceId)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, InstanceId Not Available. Exiting MultiChannelSubscribeRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); - return; - } - if (SubscribeDisconnected[PubnubInstance.InstanceId]) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeDisconnected. Exiting MultiChannelSubscribeRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - return; - } - - //Exit if the channel is unsubscribed - if (MultiChannelSubscribe != null && MultiChannelSubscribe[PubnubInstance.InstanceId].Count <= 0 && MultiChannelGroupSubscribe != null && MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count <= 0) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Zero channels/channelGroups. Further subscription was stopped", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - return; - } - - string multiChannel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - string multiChannelGroup = (channelGroups != null && channelGroups.Length > 0) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; - - bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, type, null, channels, channelGroups); - - if (!networkConnection) - { - ConnectionErrors++; - UpdatePubnubNetworkTcpCheckIntervalInSeconds(); - ChannelInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(multiChannel, networkConnection, (key, oldValue) => networkConnection); - ChannelGroupInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(multiChannelGroup, networkConnection, (key, oldValue) => networkConnection); - } - - bool channelInternetFlag; - bool channelGroupInternetFlag; - if (((ChannelInternetStatus[PubnubInstance.InstanceId].ContainsKey(multiChannel) && ChannelInternetStatus[PubnubInstance.InstanceId].TryGetValue(multiChannel, out channelInternetFlag) && !channelInternetFlag) - || (multiChannelGroup != "" && ChannelGroupInternetStatus[PubnubInstance.InstanceId].ContainsKey(multiChannelGroup) && ChannelGroupInternetStatus[PubnubInstance.InstanceId].TryGetValue(multiChannelGroup, out channelGroupInternetFlag) && !channelGroupInternetFlag)) - && PubnetSystemActive) - { - if (ReconnectNetworkIfOverrideTcpKeepAlive(type, channels, channelGroups, timetoken, region, networkConnection)) - { - return; - } - } - - if (!ChannelRequest.ContainsKey(PubnubInstance.InstanceId) || (!multiChannel.Equals(",", StringComparison.OrdinalIgnoreCase) && !ChannelRequest[PubnubInstance.InstanceId].ContainsKey(multiChannel))) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, PubnubInstance.InstanceId NOT matching", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - return; - } - - - // Begin recursive subscribe - RequestState pubnubRequestState = null; - try - { - this.customQueryParam = externalQueryParam; - RegisterPresenceHeartbeatTimer(channels, channelGroups); - - long lastTimetoken = 0; - long minimumTimetoken1 = (MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelSubscribe[PubnubInstance.InstanceId].Min(token => token.Value) : 0; - long minimumTimetoken2 = (MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Min(token => token.Value) : 0; - long minimumTimetoken = Math.Max(minimumTimetoken1, minimumTimetoken2); - - long maximumTimetoken1 = (MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelSubscribe[PubnubInstance.InstanceId].Max(token => token.Value) : 0; - long maximumTimetoken2 = (MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Max(token => token.Value) : 0; - long maximumTimetoken = Math.Max(maximumTimetoken1, maximumTimetoken2); - - - if (minimumTimetoken == 0 || reconnect || UserIdChanged[PubnubInstance.InstanceId]) - { - lastTimetoken = 0; - UserIdChanged.AddOrUpdate(PubnubInstance.InstanceId, false, (k, o) => false); - } - else - { - if (LastSubscribeTimetoken[PubnubInstance.InstanceId] == maximumTimetoken) - { - lastTimetoken = maximumTimetoken; - } - else - { - lastTimetoken = LastSubscribeTimetoken[PubnubInstance.InstanceId]; - } - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Building request for channel(s)={1}, channelgroup(s)={2} with timetoken={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), multiChannel, multiChannelGroup, lastTimetoken), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - // Build URL - string channelsJsonState = BuildJsonUserState(channels, channelGroups, false); - config[PubnubInstance.InstanceId].UserId = CurrentUserId[PubnubInstance.InstanceId]; // to make sure we capture if UUID is changed - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config[PubnubInstance.InstanceId], jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildMultiChannelSubscribeRequest("GET", "", channels, channelGroups, (Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture) == 0) ? Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture) : lastTimetoken, region, channelsJsonState, initialSubscribeUrlParams, externalQueryParam); - - pubnubRequestState = new RequestState(); - pubnubRequestState.Channels = channels; - pubnubRequestState.ChannelGroups = channelGroups; - pubnubRequestState.ResponseType = type; - pubnubRequestState.Reconnect = reconnect; - pubnubRequestState.Timetoken = Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture); - pubnubRequestState.Region = region; - pubnubRequestState.TimeQueued = DateTime.Now; - - // Wait for message - string json = ""; - UrlProcessRequest(request, pubnubRequestState, false).ContinueWith(r => - { - json = r.Result.Item1; - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - if (!string.IsNullOrEmpty(json)) - { - string subscribedChannels = (MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelSubscribe[PubnubInstance.InstanceId].Keys.OrderBy(x=>x).Aggregate((x, y) => x + "," + y) : ""; - string currentChannels = (channels != null && channels.Length > 0) ? channels.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; - - string subscribedChannelGroups = (MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; - string currentChannelGroups = (channelGroups != null && channelGroups.Length > 0) ? channelGroups.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; - - if (subscribedChannels.Equals(currentChannels, StringComparison.OrdinalIgnoreCase) && subscribedChannelGroups.Equals(currentChannelGroups, StringComparison.OrdinalIgnoreCase)) - { - List result = ProcessJsonResponse(pubnubRequestState, json); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, result count of ProcessJsonResponse = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), (result != null) ? result.Count : -1), config[PubnubInstance.InstanceId].LogVerbosity); - - ProcessResponseCallbacks(result, pubnubRequestState); - - if ((pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation || pubnubRequestState.ResponseType == PNOperationType.Presence) && (result != null) && (result.Count > 0)) - { - long jsonTimetoken = GetTimetokenFromMultiplexResult(result); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, jsonTimetoken = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonTimetoken), config[PubnubInstance.InstanceId].LogVerbosity); - - if (jsonTimetoken > 0) - { - if (pubnubRequestState.Channels != null) - { - foreach (string currentChannel in pubnubRequestState.Channels) - { - MultiChannelSubscribe[PubnubInstance.InstanceId].AddOrUpdate(currentChannel, jsonTimetoken, (key, oldValue) => jsonTimetoken); - } - } - if (pubnubRequestState.ChannelGroups != null && pubnubRequestState.ChannelGroups.Length > 0) - { - foreach (string currentChannelGroup in pubnubRequestState.ChannelGroups) - { - MultiChannelGroupSubscribe[PubnubInstance.InstanceId].AddOrUpdate(currentChannelGroup, jsonTimetoken, (key, oldValue) => jsonTimetoken); - } - } - } - } - - if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) - { - MultiplexInternalCallback(pubnubRequestState.ResponseType, result); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, condition failed for subscribedChannels == currentChannels && subscribedChannelGroups == currentChannelGroups", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, subscribedChannels = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), subscribedChannels), config[PubnubInstance.InstanceId].LogVerbosity); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, currentChannels = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentChannels), config[PubnubInstance.InstanceId].LogVerbosity); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, subscribedChannelGroups = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), subscribedChannelGroups), config[PubnubInstance.InstanceId].LogVerbosity); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, currentChannelGroups = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentChannelGroups), config[PubnubInstance.InstanceId].LogVerbosity); - } - - } - else - { - if (multiplexExceptionTimer != null) - { - multiplexExceptionTimer.Change(Timeout.Infinite, Timeout.Infinite); - } - ConnectionErrors++; - UpdatePubnubNetworkTcpCheckIntervalInSeconds(); - multiplexExceptionTimer = new Timer(new TimerCallback(MultiplexExceptionHandlerTimerCallback), pubnubRequestState, - (-1 == PubnubNetworkTcpCheckIntervalInSeconds) ? Timeout.Infinite : PubnubNetworkTcpCheckIntervalInSeconds * 1000, - Timeout.Infinite); - } - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} method:_subscribe \n channel={1} \n timetoken={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), timetoken, ex), config[PubnubInstance.InstanceId].LogVerbosity); - - PNStatusCategory errorCategory = PNStatusCategoryHelper.GetPNStatusCategory(ex); - PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(type, errorCategory, pubnubRequestState, (int)HttpStatusCode.NotFound, new PNException(ex)); - if (channels != null && channels.Length > 0) - { - status.AffectedChannels.AddRange(channels); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - status.AffectedChannels.AddRange(channelGroups); - } - - Announce(status); - - MultiChannelSubscribeRequest(type, channels, channelGroups, LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, externalQueryParam); - } - } - - private void MultiplexExceptionHandlerTimerCallback(object state) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} MultiplexExceptionHandlerTimerCallback", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - RequestState currentState = state as RequestState; - if (currentState != null) - { - MultiplexExceptionHandler(currentState.ResponseType, currentState.Channels, currentState.ChannelGroups, false); - } - } - - private void MultiplexExceptionHandler(PNOperationType type, string[] channels, string[] channelGroups, bool resumeOnReconnect) - { - List result = new List(); - result.Add("0"); - if (resumeOnReconnect || LastSubscribeTimetoken == null || !LastSubscribeTimetoken.ContainsKey(PubnubInstance.InstanceId)) - { - result.Add(0); //send 0 time token to enable presence event - } - else - { - long lastTT = LastSubscribeTimetoken[PubnubInstance.InstanceId]; //get last timetoken of the current instance - int lastRegionId = (LastSubscribeRegion != null && LastSubscribeRegion.ContainsKey(PubnubInstance.InstanceId)) ? LastSubscribeRegion[PubnubInstance.InstanceId] : 0; //get last region of the current instance - - Dictionary dictTimetokenAndRegion = new Dictionary(); - dictTimetokenAndRegion.Add("t", lastTT); - dictTimetokenAndRegion.Add("r", lastRegionId); - - Dictionary dictEnvelope = new Dictionary(); - dictEnvelope.Add("t", dictTimetokenAndRegion); - result.Add(dictEnvelope); - } - - if (channelGroups != null && channelGroups.Length > 0) - { - result.Add(channelGroups); - } - result.Add(channels); //send channel name - - MultiplexInternalCallback(type, result); - } - - private void MultiplexInternalCallback(PNOperationType type, object multiplexResult) - { - List message = multiplexResult as List; - string[] channels = null; - string[] channelGroups = null; - if (message != null && message.Count >= 3) - { - if (message[message.Count - 1] is string[]) - { - channels = message[message.Count - 1] as string[]; - } - else - { - channels = message[message.Count - 1].ToString().Split(','); - } - - if (channels.Length == 1 && channels[0] == "") - { - channels = new string[] { }; - } - if (message.Count >= 4) - { - if (message[message.Count - 2] is string[]) - { - channelGroups = message[message.Count - 2] as string[]; - } - else if (message[message.Count - 2].ToString() != "") - { - channelGroups = message[message.Count - 2].ToString().Split(','); - } - } - - long timetoken = GetTimetokenFromMultiplexResult(message); - int region = GetRegionFromMultiplexResult(message); - Task.Factory.StartNew(() => - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} MultiplexInternalCallback timetoken = {1}; region = {2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), timetoken, region), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - MultiChannelSubscribeRequest(type, channels, channelGroups, timetoken, region, false, null, this.customQueryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Lost Channel Name for resubscribe", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - - private bool ReconnectNetworkIfOverrideTcpKeepAlive(PNOperationType type, string[] channels, string[] channelGroups, object timetoken, int region, bool networkAvailable) - { - if (OverrideTcpKeepAlive) - { - ReconnectState netState = new ReconnectState(); - netState.Channels = channels; - netState.ChannelGroups = channelGroups; - netState.ResponseType = type; - netState.Timetoken = timetoken; - netState.Region = region; - if (!config.ContainsKey(PubnubInstance.InstanceId)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, InstanceId Not Available. So no reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); - } - - if (SubscribeDisconnected[PubnubInstance.InstanceId]) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Subscribe is still Disconnected. So no reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - } - else if (config[PubnubInstance.InstanceId].ReconnectionPolicy != PNReconnectionPolicy.NONE) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Subscribe - No internet connection for channel={1} and channelgroup={2}; networkAvailable={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), channelGroups != null ? string.Join(",", channelGroups) : "", networkAvailable), config[PubnubInstance.InstanceId].LogVerbosity); - TerminateReconnectTimer(); - ReconnectNetwork(netState); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, reconnection policy is DISABLED, please handle reconnection manually.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - if (!networkAvailable) - { - PNStatusCategory errorCategory = PNStatusCategory.PNNetworkIssuesCategory; - PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(type, errorCategory, null, (int)HttpStatusCode.NotFound, new PNException("SDK Network related error")); - if (channels != null && channels.Length > 0) - { - status.AffectedChannels.AddRange(channels); - } - if (channelGroups != null && channelGroups.Length > 0) - { - status.AffectedChannels.AddRange(channelGroups); - } - Announce(status); - - } - } - return true; - } - else - { - return false; - } - } - - private void ReconnectNetwork(ReconnectState netState) - { - if (netState != null && ((netState.Channels != null && netState.Channels.Length > 0) || (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0))) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager ReconnectNetwork interval = {1} sec", DateTime.Now.ToString(CultureInfo.InvariantCulture), PubnubNetworkTcpCheckIntervalInSeconds), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - - System.Threading.Timer timer; - - if (netState.Channels != null && netState.Channels.Length > 0) - { - string reconnectChannelTimerKey = string.Join(",", netState.Channels.OrderBy(x => x).ToArray()); - - if (!ChannelReconnectTimer[PubnubInstance.InstanceId].ContainsKey(reconnectChannelTimerKey)) - { - timer = new Timer(new TimerCallback(ReconnectNetworkCallback), netState, 0, - (-1 == PubnubNetworkTcpCheckIntervalInSeconds) ? Timeout.Infinite : PubnubNetworkTcpCheckIntervalInSeconds * 1000); - ChannelReconnectTimer[PubnubInstance.InstanceId].AddOrUpdate(reconnectChannelTimerKey, timer, (key, oldState) => timer); - } - } - else if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - string reconnectChannelGroupTimerKey = string.Join(",", netState.ChannelGroups.OrderBy(x => x).ToArray()); - - if (!ChannelGroupReconnectTimer[PubnubInstance.InstanceId].ContainsKey(reconnectChannelGroupTimerKey)) - { - timer = new Timer(new TimerCallback(ReconnectNetworkCallback), netState, 0, - (-1 == PubnubNetworkTcpCheckIntervalInSeconds) ? Timeout.Infinite : PubnubNetworkTcpCheckIntervalInSeconds * 1000); - ChannelGroupReconnectTimer[PubnubInstance.InstanceId].AddOrUpdate(reconnectChannelGroupTimerKey, timer, (key, oldState) => timer); - } - } - } - } - - internal bool Reconnect(bool resetSubscribeTimetoken) - { - if (!SubscribeDisconnected[PubnubInstance.InstanceId]) //Check if disconnect is done before - { - return false; - } - - string[] channels = GetCurrentSubscriberChannels(); - string[] chananelGroups = GetCurrentSubscriberChannelGroups(); - - if ((channels != null && channels.Length > 0) || (chananelGroups != null && chananelGroups.Length > 0)) - { - string channel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - string channelGroup = (chananelGroups != null && chananelGroups.Length > 0) ? string.Join(",", chananelGroups.OrderBy(x => x).ToArray()) : ""; - - bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, PNOperationType.PNSubscribeOperation, null, channels, chananelGroups); - if (!networkConnection) - { - //Recheck for false alert with 1 sec delay -#if !NET35 && !NET40 - Task.Delay(1000).Wait(); -#else - Thread.Sleep(1000); -#endif - - networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, PNOperationType.PNSubscribeOperation, null, channels, chananelGroups); - } - if (networkConnection) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Network available for SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - if (!string.IsNullOrEmpty(channel) && ChannelInternetStatus[PubnubInstance.InstanceId].ContainsKey(channel)) - { - ChannelInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channel, networkConnection, (key, oldValue) => networkConnection); - } - if (!string.IsNullOrEmpty(channelGroup) && ChannelGroupInternetStatus[PubnubInstance.InstanceId].ContainsKey(channelGroup)) - { - ChannelGroupInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channelGroup, networkConnection, (key, oldValue) => networkConnection); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No network for SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - - PNStatusCategory errorCategory = PNStatusCategory.PNNetworkIssuesCategory; - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNSubscribeOperation, errorCategory, null, (int)HttpStatusCode.NotFound, new PNException("SDK Network related error")); - if (channels != null && channels.Length > 0) - { - status.AffectedChannels.AddRange(channels); - } - if (chananelGroups != null && chananelGroups.Length > 0) - { - status.AffectedChannels.AddRange(chananelGroups); - } - Announce(status); - - return false; - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No channels/channelgroups for SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - return false; - } - - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - SubscribeDisconnected[PubnubInstance.InstanceId] = false; - - Task.Factory.StartNew(() => - { - if (resetSubscribeTimetoken) - { - LastSubscribeTimetoken[PubnubInstance.InstanceId] = 0; - LastSubscribeRegion[PubnubInstance.InstanceId] = 0; - } - MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, GetCurrentSubscriberChannels(), GetCurrentSubscriberChannelGroups(), LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, this.customQueryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - - return true; - } - - internal bool Disconnect() - { - if (SubscribeDisconnected[PubnubInstance.InstanceId]) - { - return false; - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager Manual Disconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - SubscribeDisconnected[PubnubInstance.InstanceId] = true; - TerminateCurrentSubscriberRequest(); - PubnubCoreBase.TerminatePresenceHeartbeatTimer(); - TerminateReconnectTimer(); - - return true; - } - - internal void StartSubscribeHeartbeatCheckCallback(object state) - { - try - { - if (SubscribeDisconnected[PubnubInstance.InstanceId]) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - SubscribeDisconnected. No heartbeat check.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - return; - } - if (!config.ContainsKey(PubnubInstance.InstanceId)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, InstanceId Not Available. So No heartbeat check.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - return; - } - - string[] channels = GetCurrentSubscriberChannels(); - string[] chananelGroups = GetCurrentSubscriberChannelGroups(); - - if ((channels != null && channels.Length > 0) || (chananelGroups != null && chananelGroups.Length > 0)) - { - bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, PNOperationType.PNSubscribeOperation, null, channels, chananelGroups); - if (networkConnection && PubnubInstance != null && SubscribeRequestTracker.ContainsKey(PubnubInstance.InstanceId)) - { - DateTime lastSubscribeRequestTime = SubscribeRequestTracker[PubnubInstance.InstanceId]; - if ((DateTime.Now - lastSubscribeRequestTime).TotalSeconds < config[PubnubInstance.InstanceId].SubscribeTimeout) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - ok. expected subscribe within threshold limit of SubscribeTimeout. No action needed", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - } - else if ((DateTime.Now - lastSubscribeRequestTime).TotalSeconds > 2 * (config[PubnubInstance.InstanceId].SubscribeTimeout - config[PubnubInstance.InstanceId].SubscribeTimeout/2)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - **No auto subscribe within threshold limit of SubscribeTimeout**. Calling MultiChannelSubscribeRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - Task.Factory.StartNew(() => - { - TerminateCurrentSubscriberRequest(); - MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, channels, chananelGroups, LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, this.customQueryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - **No auto subscribe within threshold limit of SubscribeTimeout**. Calling TerminateCurrentSubscriberRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - Task.Factory.StartNew(() => - { - TerminateCurrentSubscriberRequest(); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - StartSubscribeHeartbeatCheckCallback - No network or no pubnub instance mapping", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - if (PubnubInstance != null && !networkConnection) - { - PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(PNOperationType.PNSubscribeOperation, PNStatusCategory.PNNetworkIssuesCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem during subscribe heartbeat.")); - if (channels != null && channels.Length > 0) - { - status.AffectedChannels.AddRange(channels.ToList()); - } - if (chananelGroups != null && chananelGroups.Length > 0) - { - status.AffectedChannelGroups.AddRange(chananelGroups.ToList()); - } - Announce(status); - - Task.Factory.StartNew(() => - { - TerminateCurrentSubscriberRequest(); - MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, GetCurrentSubscriberChannels(), GetCurrentSubscriberChannelGroups(), LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, this.customQueryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - } - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - StartSubscribeHeartbeatCheckCallback - No channels/cgs avaialable", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); - try - { - SubscribeHeartbeatCheckTimer.Change(Timeout.Infinite, Timeout.Infinite); - TerminateCurrentSubscriberRequest(); - } - catch { /* ignore */ } - } - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - StartSubscribeHeartbeatCheckCallback - EXCEPTION: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture),ex), config[PubnubInstance.InstanceId].LogVerbosity); - } - } - - - protected void ReconnectNetworkCallback(System.Object reconnectState) - { - string channel = ""; - string channelGroup = ""; - - ReconnectState netState = reconnectState as ReconnectState; - try - { - string subscribedChannels = (MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelSubscribe[PubnubInstance.InstanceId].Keys.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; - string subscribedChannelGroups = (MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; - List channelRequestKeyList = new List(ChannelRequest[PubnubInstance.InstanceId].Keys); - for(int keyIndex= 0; keyIndex < channelRequestKeyList.Count; keyIndex++) - { - string keyChannel = channelRequestKeyList[keyIndex]; - if (keyChannel != subscribedChannels) - { - if (ChannelRequest[PubnubInstance.InstanceId].ContainsKey(keyChannel)) - { - HttpWebRequest keyChannelRequest; - ChannelRequest[PubnubInstance.InstanceId].TryGetValue(keyChannel, out keyChannelRequest); - if (keyChannelRequest != null) - { - try - { - keyChannelRequest.Abort(); - } - catch { /* ignore */ } - ChannelRequest[PubnubInstance.InstanceId].TryUpdate(keyChannel, null, keyChannelRequest); - } - HttpWebRequest tempValue; - ChannelRequest[PubnubInstance.InstanceId].TryRemove(keyChannel, out tempValue); - } - } - } - - - if (netState != null && ((netState.Channels != null && netState.Channels.Length > 0) || (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0))) - { - if (netState.Channels == null) - { - netState.Channels = new string[] { }; - } - - if (netState.ChannelGroups == null) - { - netState.ChannelGroups = new string[] { }; - } - - bool channelInternetFlag; - bool channelGroupInternetFlag; - if (netState.Channels != null && netState.Channels.Length > 0) - { - channel = (netState.Channels.Length > 0) ? string.Join(",", netState.Channels.OrderBy(x=>x).ToArray()) : ","; - channelGroup = (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) ? string.Join(",", netState.ChannelGroups.OrderBy(x => x).ToArray()) : ""; - - if (channel == subscribedChannels && ChannelInternetStatus[PubnubInstance.InstanceId].ContainsKey(channel) - && (netState.ResponseType == PNOperationType.PNSubscribeOperation || netState.ResponseType == PNOperationType.Presence)) - { - bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); - if (networkConnection) { - //Re-try to avoid false alert - networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); - } - - if (ChannelInternetStatus[PubnubInstance.InstanceId].TryGetValue(channel, out channelInternetFlag) && channelInternetFlag) - { - //do nothing - } - else - { - ChannelInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channel, networkConnection, (key, oldValue) => networkConnection); - if (!string.IsNullOrEmpty(channelGroup) && channelGroup.Length > 0) - { - ChannelGroupInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channelGroup, networkConnection, (key, oldValue) => networkConnection); - } - - ConnectionErrors++; - UpdatePubnubNetworkTcpCheckIntervalInSeconds(); - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channel={1} {2} reconnectNetworkCallback. Retry", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - - if (netState.Channels != null && netState.Channels.Length > 0) - { - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNNetworkIssuesCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem. Retrying connection")); - if (netState.Channels != null && netState.Channels.Length > 0) - { - status.AffectedChannels.AddRange(netState.Channels.ToList()); - } - if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); - } - Announce(status); - } - - } - } - - if (ChannelInternetStatus[PubnubInstance.InstanceId].ContainsKey(channel) && ChannelInternetStatus[PubnubInstance.InstanceId].TryGetValue(channel, out channelInternetFlag) && channelInternetFlag) - { - if (ChannelReconnectTimer[PubnubInstance.InstanceId].ContainsKey(channel)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, {1} {2} terminating ch reconnectimer", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - TerminateReconnectTimer(); - } - - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNReconnectedCategory, null, (int)System.Net.HttpStatusCode.OK, null); - if (netState.Channels != null && netState.Channels.Length > 0) - { - status.AffectedChannels.AddRange(netState.Channels.ToList()); - } - if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); - } - Announce(status); - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channel={1} {2} reconnectNetworkCallback. Internet Available : {3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, netState.ResponseType, channelInternetFlag.ToString()), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - switch (netState.ResponseType) - { - case PNOperationType.PNSubscribeOperation: - case PNOperationType.Presence: - MultiChannelSubscribeRequest(netState.ResponseType, netState.Channels, netState.ChannelGroups, netState.Timetoken, netState.Region, true, null, this.customQueryParam); - break; - default: - break; - } - } - } - else if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - channelGroup = string.Join(",", netState.ChannelGroups.OrderBy(x => x).ToArray()); - channel = (netState.Channels != null && netState.Channels.Length > 0) ? string.Join(",", netState.Channels.OrderBy(x => x).ToArray()) : ","; - - if (subscribedChannelGroups == channelGroup && channelGroup != "" && ChannelGroupInternetStatus[PubnubInstance.InstanceId].ContainsKey(channelGroup) - && (netState.ResponseType == PNOperationType.PNSubscribeOperation || netState.ResponseType == PNOperationType.Presence)) - { - bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); - if (networkConnection) - { - //Re-try to avoid false alert - networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); - } - - if (ChannelGroupInternetStatus[PubnubInstance.InstanceId].TryGetValue(channelGroup, out channelGroupInternetFlag) && channelGroupInternetFlag) - { - //do nothing - } - else - { - ChannelGroupInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channelGroup, networkConnection, (key, oldValue) => networkConnection); - if (!string.IsNullOrEmpty(channel) && channel.Length > 0) - { - ChannelInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channel, networkConnection, (key, oldValue) => networkConnection); - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channelgroup={1} {2} reconnectNetworkCallback. Retrying", DateTime.Now.ToString(CultureInfo.InvariantCulture), channelGroup, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - - if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNReconnectedCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem. Retrying connection")); - if (netState.Channels != null && netState.Channels.Length > 0) - { - status.AffectedChannels.AddRange(netState.Channels.ToList()); - } - if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); - } - Announce(status); - } - } - } - - if (ChannelGroupInternetStatus[PubnubInstance.InstanceId].TryGetValue(channelGroup, out channelGroupInternetFlag) && channelGroupInternetFlag) - { - if (ChannelGroupReconnectTimer[PubnubInstance.InstanceId].ContainsKey(channelGroup)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, {1} {2} terminating cg reconnectimer", DateTime.Now.ToString(CultureInfo.InvariantCulture), channelGroup, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - TerminateReconnectTimer(); - } - - //Send one ReConnectedCategory message. If Channels NOT available then use this - if (netState.Channels.Length == 0 && netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNReconnectedCategory, null, (int)System.Net.HttpStatusCode.OK, null); - if (netState.Channels != null && netState.Channels.Length > 0) - { - status.AffectedChannels.AddRange(netState.Channels.ToList()); - } - if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); - } - Announce(status); - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channelgroup={1} {2} reconnectNetworkCallback. Internet Available", DateTime.Now.ToString(CultureInfo.InvariantCulture), channelGroup, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - switch (netState.ResponseType) - { - case PNOperationType.PNSubscribeOperation: - case PNOperationType.Presence: - MultiChannelSubscribeRequest(netState.ResponseType, netState.Channels, netState.ChannelGroups, netState.Timetoken, netState.Region, true, null, this.customQueryParam); - break; - default: - break; - } - } - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unknown request state in reconnectNetworkCallback", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - catch (Exception ex) - { - if (netState != null) - { - PNStatusCategory errorCategory = PNStatusCategoryHelper.GetPNStatusCategory(ex); - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, errorCategory, null, (int)HttpStatusCode.NotFound, new PNException(ex)); - if (netState.Channels != null && netState.Channels.Length > 0) - { - status.AffectedChannels.AddRange(netState.Channels.ToList()); - } - if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) - { - status.AffectedChannels.AddRange(netState.ChannelGroups.ToList()); - } - Announce(status); - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} method:reconnectNetworkCallback \n Exception Details={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); - } - } - - private void RegisterPresenceHeartbeatTimer(string[] channels, string[] channelGroups) - { - if (PresenceHeartbeatTimer != null) - { - try - { - PresenceHeartbeatTimer.Change(Timeout.Infinite, Timeout.Infinite); - PresenceHeartbeatTimer.Dispose(); - PresenceHeartbeatTimer = null; - } - catch { /* ignore */ } - } - if ((channels != null && channels.Length > 0 && channels.Where(s => s != null && s.Contains("-pnpres") == false).Any()) - || (channelGroups != null && channelGroups.Length > 0 && channelGroups.Where(s => s != null && s.Contains("-pnpres") == false).Any())) - { - RequestState presenceHeartbeatState = new RequestState(); - presenceHeartbeatState.Channels = channels; - presenceHeartbeatState.ChannelGroups = channelGroups; - presenceHeartbeatState.ResponseType = PNOperationType.PNHeartbeatOperation; - presenceHeartbeatState.Request = null; - presenceHeartbeatState.Response = null; - - if (config.ContainsKey(PubnubInstance.InstanceId) && config[PubnubInstance.InstanceId].PresenceInterval > 0) - { - PresenceHeartbeatTimer = new Timer(OnPresenceHeartbeatIntervalTimeout, presenceHeartbeatState, config[PubnubInstance.InstanceId].PresenceInterval * 1000, config[PubnubInstance.InstanceId].PresenceInterval * 1000); - } - } - } - -#pragma warning disable - void OnPresenceHeartbeatIntervalTimeout(System.Object presenceHeartbeatState) -#pragma warning restore - { - //Make presence heartbeat call - RequestState currentState = presenceHeartbeatState as RequestState; - if (currentState != null) - { - string[] subscriberChannels = (currentState.Channels != null) ? currentState.Channels.Where(s => s.Contains("-pnpres") == false).ToArray() : null; - string[] subscriberChannelGroups = (currentState.ChannelGroups != null) ? currentState.ChannelGroups.Where(s => s.Contains("-pnpres") == false).ToArray() : null; - - bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, currentState.ResponseType, currentState.PubnubCallback, currentState.Channels, currentState.ChannelGroups); - if (networkConnection) - { - if ((subscriberChannels != null && subscriberChannels.Length > 0) || (subscriberChannelGroups != null && subscriberChannelGroups.Length > 0)) - { - string channelsJsonState = BuildJsonUserState(subscriberChannels, subscriberChannelGroups, false); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildPresenceHeartbeatRequest("GET", "", subscriberChannels, subscriberChannelGroups, channelsJsonState); - - RequestState requestState = new RequestState(); - requestState.Channels = currentState.Channels; - requestState.ChannelGroups = currentState.ChannelGroups; - requestState.ResponseType = PNOperationType.PNHeartbeatOperation; - requestState.PubnubCallback = null; - requestState.Reconnect = false; - requestState.Response = null; - requestState.TimeQueued = DateTime.Now; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - } - else - { - if (PubnubInstance != null && !networkConnection) - { - PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNSubscribeOperation, PNStatusCategory.PNNetworkIssuesCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem during presence heartbeat.")); - if (subscriberChannels != null && subscriberChannels.Length > 0) - { - status.AffectedChannels.AddRange(subscriberChannels.ToList()); - } - if (subscriberChannelGroups != null && subscriberChannelGroups.Length > 0) - { - status.AffectedChannelGroups.AddRange(subscriberChannelGroups.ToList()); - } - Announce(status); - } - - } - } - - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - } - - #region IDisposable Support - private bool disposedValue; - - protected virtual void DisposeInternal(bool disposing) - { - if (!disposedValue) - { - if (SubscribeHeartbeatCheckTimer != null) - { - SubscribeHeartbeatCheckTimer.Dispose(); - } - - disposedValue = true; - } - } - - void IDisposable.Dispose() - { - DisposeInternal(true); - } - #endregion - - } + internal class SubscribeManager : PubnubCoreBase, IDisposable + { + private static ConcurrentDictionary config { get; } = new(); + private static IJsonPluggableLibrary jsonLibrary; + private static IPubnubUnitTest unit; + private static IPubnubLog pubnubLog; + + private static Timer SubscribeHeartbeatCheckTimer; + private Timer multiplexExceptionTimer; + private Dictionary customQueryParam; + + public SubscribeManager(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config.AddOrUpdate(instance.InstanceId, pubnubConfig, (k, o) => pubnubConfig); + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + + internal void MultiChannelUnSubscribeAll(PNOperationType type, Dictionary externalQueryParam) + { + //Retrieve the current channels already subscribed previously and terminate them + TerminateCurrentSubscriberRequest(); + string[] currentChannels = SubscriptionChannels.ContainsKey(PubnubInstance.InstanceId)? SubscriptionChannels[PubnubInstance.InstanceId].Keys?.ToArray()??[] : []; + string[] currentChannelGroups = SubscriptionChannelGroups.ContainsKey(PubnubInstance.InstanceId)? SubscriptionChannelGroups[PubnubInstance.InstanceId].Keys?.ToArray()??[] : []; + + if (type == PNOperationType.PNUnsubscribeOperation && config.ContainsKey(PubnubInstance.InstanceId) && !config[PubnubInstance.InstanceId].SuppressLeaveEvents) { + //just fire leave() event to REST API for safeguard + var leaveRequestParameter = CreateLeaveRequestParameter(currentChannels, currentChannelGroups); + var leaveTransportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: leaveRequestParameter, operationType: PNOperationType.Leave); + PubnubInstance.transportMiddleware.Send(transportRequest: leaveTransportRequest).ContinueWith(t => { + SubscriptionChannels[PubnubInstance.InstanceId]?.Clear(); + SubscriptionChannelGroups[PubnubInstance.InstanceId]?.Clear(); + }); + } + SubscriptionChannels[PubnubInstance.InstanceId]?.Clear(); + SubscriptionChannelGroups[PubnubInstance.InstanceId]?.Clear(); + TerminateCurrentSubscriberRequest(); + TerminateReconnectTimer(); + TerminatePresenceHeartbeatTimer(); + } + + internal void MultiChannelUnSubscribeInit(PNOperationType type, string channel, string channelGroup, Dictionary externalQueryParam) + { + List validChannels = new List(); + List validChannelGroups = new List(); + + try { + this.customQueryParam = externalQueryParam; + + if (PubnubInstance == null) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, PubnubInstance is null. exiting MultiChannelUnSubscribeInit", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + return; + } + + string[] rawChannels = (channel != null && channel.Trim().Length > 0) ? channel.Split(',') : new string[] { }; + string[] rawChannelGroups = (channelGroup != null && channelGroup.Trim().Length > 0) ? channelGroup.Split(',') : new string[] { }; + + if (rawChannels.Length > 0) { + for (int index = 0; index < rawChannels.Length; index++) { + if (rawChannels[index].Trim().Length > 0) { + string channelName = rawChannels[index].Trim(); + if (string.IsNullOrEmpty(channelName)) { + continue; + } + + if (config.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannels.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannels[PubnubInstance.InstanceId] != null && !SubscriptionChannels[PubnubInstance.InstanceId].ContainsKey(channelName)) { + PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNUnexpectedDisconnectCategory, null, Constants.ResourceNotFoundStatusCode, null); + if (!status.AffectedChannels.Contains(channelName)) { + status.AffectedChannels.Add(channelName); + } + Announce(status); + } else { + validChannels.Add(channelName); + string presenceChannelName = string.Format(CultureInfo.InvariantCulture, "{0}-pnpres", channelName); + if (SubscriptionChannels.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannels[PubnubInstance.InstanceId] != null && SubscriptionChannels[PubnubInstance.InstanceId].ContainsKey(presenceChannelName)) { + validChannels.Add(presenceChannelName); + } + } + } + } + } + + if (rawChannelGroups.Length > 0) { + for (int index = 0; index < rawChannelGroups.Length; index++) { + if (rawChannelGroups[index].Trim().Length > 0) { + string channelGroupName = rawChannelGroups[index].Trim(); + if (string.IsNullOrEmpty(channelGroupName)) { + continue; + } + + if (config.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannelGroups.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannelGroups[PubnubInstance.InstanceId] != null && !SubscriptionChannelGroups[PubnubInstance.InstanceId].ContainsKey(channelGroupName)) { + PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNUnexpectedDisconnectCategory, null, Constants.ResourceNotFoundStatusCode, null); + if (!status.AffectedChannelGroups.Contains(channelGroupName)) { + status.AffectedChannelGroups.Add(channelGroupName); + } + Announce(status); + } else { + validChannelGroups.Add(channelGroupName); + string presenceChannelGroupName = string.Format(CultureInfo.InvariantCulture, "{0}-pnpres", channelGroupName); + if (SubscriptionChannelGroups.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannelGroups[PubnubInstance.InstanceId] != null && SubscriptionChannelGroups[PubnubInstance.InstanceId].ContainsKey(presenceChannelGroupName)) { + validChannelGroups.Add(presenceChannelGroupName); + } + } + } + } + } + + if (validChannels.Count > 0 || validChannelGroups.Count > 0) { + TerminateCurrentSubscriberRequest(); + if (type == PNOperationType.PNUnsubscribeOperation && config.ContainsKey(PubnubInstance.InstanceId)) { + var leaveRequestParameter = CreateLeaveRequestParameter(validChannels.ToArray(), validChannelGroups.ToArray()); + var leaveTransportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: leaveRequestParameter, operationType: PNOperationType.Leave); + PubnubInstance.transportMiddleware.Send(transportRequest: leaveTransportRequest).ContinueWith(t => { }); + } + + PNStatus successStatus = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNUnsubscribeOperation, PNStatusCategory.PNDisconnectedCategory, null, Constants.HttpRequestSuccessStatusCode, null); + + //Remove the valid channels from subscribe list for unsubscribe + for (int index = 0; index < validChannels.Count; index++) { + string channelToBeRemoved = validChannels[index]; + bool unsubscribeStatus = false; + if (channelToBeRemoved.Contains("-pnpres")) { + continue; //Do not send status for -pnpres channels + } + if (!successStatus.AffectedChannels.Contains(channelToBeRemoved)) { + successStatus.AffectedChannels.Add(channelToBeRemoved); + } + base.DeleteLocalChannelUserState(channelToBeRemoved); + } + for (int index = 0; index < validChannelGroups.Count; index++) { + string channelGroupToBeRemoved = validChannelGroups[index]; + if (channelGroupToBeRemoved.Contains("-pnpres")) { + continue; //Do not send status for -pnpres channel-groups + } + if (!successStatus.AffectedChannelGroups.Contains(channelGroupToBeRemoved)) { + successStatus.AffectedChannelGroups.Add(channelGroupToBeRemoved); + } + base.DeleteLocalChannelGroupUserState(channelGroupToBeRemoved); + } + if (PubnubInstance != null) { + Announce(successStatus); + } + + foreach (var channelToRemove in validChannels) + { + try + { + if (SubscriptionChannels[PubnubInstance.InstanceId].ContainsKey(channelToRemove)) + SubscriptionChannels[PubnubInstance.InstanceId].TryRemove(channelToRemove, out _); + } + catch { } + } + foreach (var groupToRemove in validChannelGroups) + { + try + { + if (SubscriptionChannelGroups[PubnubInstance.InstanceId].ContainsKey(groupToRemove)) + SubscriptionChannelGroups[PubnubInstance.InstanceId].TryRemove(groupToRemove, out _); + } + catch { } + } + + var channelsToKeepSubscription = SubscriptionChannels[PubnubInstance.InstanceId].Keys.ToArray(); + var groupsToKeepSubscription = SubscriptionChannelGroups[PubnubInstance.InstanceId].Keys.ToArray(); + if (channelsToKeepSubscription.Length > 0 || groupsToKeepSubscription.Length > 0) { + MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, channelsToKeepSubscription, groupsToKeepSubscription, 0, 0, false, null, this.customQueryParam); + } else { + if (PresenceHeartbeatTimer != null) { + PresenceHeartbeatTimer.Dispose(); + PresenceHeartbeatTimer = null; + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, All channels are Unsubscribed. Further subscription was stopped", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + } + } + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager=> MultiChannelUnSubscribeInit \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", validChannels.OrderBy(x => x).ToArray()), string.Join(",", validChannelGroups.OrderBy(x => x).ToArray()), ex), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + } + } + + internal void MultiChannelSubscribeInit(PNOperationType responseType, string[] rawChannels, string[] rawChannelGroups, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + { + try { + bool channelGroupSubscribeOnly = false; + SubscribeDisconnected[PubnubInstance.InstanceId] = false; + bool isSubscriptionChanged = false; + if (!SubscriptionChannels.ContainsKey(PubnubInstance.InstanceId)) + SubscriptionChannels[PubnubInstance.InstanceId] = new(); + if (!SubscriptionChannelGroups.ContainsKey(PubnubInstance.InstanceId)) + SubscriptionChannelGroups[PubnubInstance.InstanceId] = new(); + foreach (string channel in rawChannels.Distinct()) + { + try { isSubscriptionChanged |= SubscriptionChannels[PubnubInstance.InstanceId].TryAdd(channel.Trim(), true); } catch { isSubscriptionChanged = true; } + } + + foreach (string group in rawChannelGroups.Distinct()) + { + try {isSubscriptionChanged |= SubscriptionChannelGroups[PubnubInstance.InstanceId].TryAdd(group.Trim(),true);} catch{isSubscriptionChanged = true;} + } + if (isSubscriptionChanged && config.ContainsKey(PubnubInstance.InstanceId)) { + //Retrieve the current channels already subscribed previously and terminate them + string[] channels = SubscriptionChannels[PubnubInstance.InstanceId].Keys.ToArray(); + string[] channelGroups = SubscriptionChannelGroups[PubnubInstance.InstanceId].Keys.ToArray(); + TerminateCurrentSubscriberRequest(); + if (channelGroups != null && channelGroups.Length > 0 && (channels == null || channels.Length == 0)) { + channelGroupSubscribeOnly = true; + } + MultiChannelSubscribeRequest(responseType, channels, channelGroups, 0, 0, false, initialSubscribeUrlParams, externalQueryParam); + + if (SubscribeHeartbeatCheckTimer != null) { + try { + SubscribeHeartbeatCheckTimer.Change(Timeout.Infinite, Timeout.Infinite); + } catch { /* ignore */ } + } + SubscribeHeartbeatCheckTimer = new Timer(StartSubscribeHeartbeatCheckCallback, null, config[PubnubInstance.InstanceId].SubscribeTimeout * 500, config[PubnubInstance.InstanceId].SubscribeTimeout * 500); + } + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, $"subscribe initialisation opeartion encountered error {ex.Message}", config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + } + } + + private void MultiChannelSubscribeRequest(PNOperationType type, string[] channels, string[] channelGroups, object timetoken, int region, bool reconnect, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + { + if (!config.ContainsKey(PubnubInstance.InstanceId)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, InstanceId Not Available. Exiting MultiChannelSubscribeRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); + return; + } + if (SubscribeDisconnected[PubnubInstance.InstanceId]) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeDisconnected. Exiting MultiChannelSubscribeRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + return; + } + //Exit if the channel is unsubscribed + if (SubscriptionChannels[PubnubInstance.InstanceId].Count <= 0 && SubscriptionChannelGroups[PubnubInstance.InstanceId].Count <= 0) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Zero channels/channelGroups. Further subscription was stopped", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + return; + } + TerminateCurrentSubscriberRequest(); + string multiChannel = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + string multiChannelGroup = (channelGroups != null && channelGroups.Length > 0) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; + + bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, type, null, channels, channelGroups); + + if (!networkConnection) { + ConnectionErrors++; + UpdatePubnubNetworkTcpCheckIntervalInSeconds(); + } + + if (!networkConnection) { + PNStatusCategory errorCategory = PNStatusCategory.PNNetworkIssuesCategory; + PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(type, errorCategory, null, Constants.ResourceNotFoundStatusCode, new PNException("SDK Network related error")); + if (channels != null && channels.Length > 0) { + status.AffectedChannels.AddRange(channels); + } + if (channelGroups != null && channelGroups.Length > 0) { + status.AffectedChannels.AddRange(channelGroups); + } + Announce(status); + } + + // Begin recursive subscribe + RequestState pubnubRequestState = null; + try { + this.customQueryParam = externalQueryParam; + RegisterPresenceHeartbeatTimer(channels, channelGroups); + long lastTimetoken = LastSubscribeTimetoken.ContainsKey(PubnubInstance.InstanceId)? LastSubscribeTimetoken[PubnubInstance.InstanceId] : 0; + LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, Building request for channel(s)={multiChannel}, channelgroup(s)={multiChannelGroup} with timetoken={lastTimetoken}", config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + string channelsJsonState = BuildJsonUserState(channels, channelGroups, false); + config[PubnubInstance.InstanceId].UserId = CurrentUserId[PubnubInstance.InstanceId]; // to make sure we capture if UUID is changed + pubnubRequestState = new RequestState + { + Channels = channels, + ChannelGroups = channelGroups, + ResponseType = type, + Reconnect = reconnect, + Timetoken = Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture), + Region = region, + TimeQueued = DateTime.Now + }; + var subscribeRequestParameter = CreateSubscribeRequestParameter(channels: channels, channelGroups: channelGroups,timetoken: (Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture) == 0) ? Convert.ToInt64(timetoken.ToString(), CultureInfo.InvariantCulture) : lastTimetoken,region: region,stateJsonValue: channelsJsonState, initialSubscribeUrlParams: initialSubscribeUrlParams, externalQueryParam: externalQueryParam); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: subscribeRequestParameter, operationType: PNOperationType.PNSubscribeOperation); + OngoingSubscriptionCancellationTokenSources[PubnubInstance.InstanceId] = CancellationTokenSource.CreateLinkedTokenSource(transportRequest.CancellationToken); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith( t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var json = Encoding.UTF8.GetString(transportResponse.Content); + pubnubRequestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(json)) { + List result = ProcessJsonResponse(pubnubRequestState, json); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, result count of ProcessJsonResponse = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), (result != null) ? result.Count : -1), config[PubnubInstance.InstanceId].LogVerbosity); + + ProcessResponseCallbacks(result, pubnubRequestState); + + if ((pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation || pubnubRequestState.ResponseType == PNOperationType.Presence) && (result != null) && (result.Count > 0)) { + long jsonTimetoken = GetTimetokenFromMultiplexResult(result); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, jsonTimetoken = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonTimetoken), config[PubnubInstance.InstanceId].LogVerbosity); + } + if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) { + MultiplexInternalCallback(pubnubRequestState.ResponseType, result); + } + } + } else { + LoggingMethod.WriteToLog(pubnubLog,$"Exception from TransportLayer\n\n transportResponse.Error.Message => {transportResponse.Error.Message} \n\n\n inner{transportResponse.Error.InnerException?.Message}", config[PubnubInstance.InstanceId].LogVerbosity); + if (multiplexExceptionTimer != null) { + multiplexExceptionTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + ConnectionErrors++; + UpdatePubnubNetworkTcpCheckIntervalInSeconds(); + multiplexExceptionTimer = new Timer(new TimerCallback(MultiplexExceptionHandlerTimerCallback), pubnubRequestState, + (-1 == PubnubNetworkTcpCheckIntervalInSeconds) ? Timeout.Infinite : PubnubNetworkTcpCheckIntervalInSeconds * 1000, + Timeout.Infinite); + } + }); + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} method:_subscribe \n channel={1} \n timetoken={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), timetoken, ex), config[PubnubInstance.InstanceId].LogVerbosity); + PNStatusCategory errorCategory = PNStatusCategoryHelper.GetPNStatusCategory(ex); + PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(type, errorCategory, pubnubRequestState, Constants.ResourceNotFoundStatusCode, new PNException(ex)); + if (channels != null && channels.Length > 0) { + status.AffectedChannels.AddRange(channels); + } + if (channelGroups != null && channelGroups.Length > 0) { + status.AffectedChannels.AddRange(channelGroups); + } + Announce(status); + MultiChannelSubscribeRequest(type, channels, channelGroups, LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, externalQueryParam); + } + } + + private void MultiplexExceptionHandlerTimerCallback(object state) + { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} MultiplexExceptionHandlerTimerCallback", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + RequestState currentState = state as RequestState; + if (currentState != null) { + MultiplexExceptionHandler(currentState.ResponseType, currentState.Channels, currentState.ChannelGroups, false); + } + } + + private void MultiplexExceptionHandler(PNOperationType type, string[] channels, string[] channelGroups, bool resumeOnReconnect) + { + List result = new List(); + result.Add("0"); + if (resumeOnReconnect || LastSubscribeTimetoken == null || !LastSubscribeTimetoken.ContainsKey(PubnubInstance.InstanceId)) { + result.Add(0); //send 0 time token to enable presence event + } else { + long lastTT = LastSubscribeTimetoken[PubnubInstance.InstanceId]; //get last timetoken of the current instance + int lastRegionId = (LastSubscribeRegion != null && LastSubscribeRegion.ContainsKey(PubnubInstance.InstanceId)) ? LastSubscribeRegion[PubnubInstance.InstanceId] : 0; //get last region of the current instance + + Dictionary dictTimetokenAndRegion = new Dictionary(); + dictTimetokenAndRegion.Add("t", lastTT); + dictTimetokenAndRegion.Add("r", lastRegionId); + + Dictionary dictEnvelope = new Dictionary(); + dictEnvelope.Add("t", dictTimetokenAndRegion); + result.Add(dictEnvelope); + } + + if (channelGroups != null && channelGroups.Length > 0) { + result.Add(channelGroups); + } + result.Add(channels); //send channel name + + MultiplexInternalCallback(type, result); + } + + private void MultiplexInternalCallback(PNOperationType type, object multiplexResult) + { + List message = multiplexResult as List; + string[] channels = null; + string[] channelGroups = null; + if (message != null && message.Count >= 3) { + if (message[message.Count - 1] is string[]) { + channels = message[message.Count - 1] as string[]; + } else { + channels = message[message.Count - 1].ToString().Split(','); + } + + if (channels.Length == 1 && channels[0] == "") { + channels = new string[] { }; + } + if (message.Count >= 4) { + if (message[message.Count - 2] is string[]) { + channelGroups = message[message.Count - 2] as string[]; + } else if (message[message.Count - 2].ToString() != "") { + channelGroups = message[message.Count - 2].ToString().Split(','); + } + } + + long timetoken = GetTimetokenFromMultiplexResult(message); + int region = GetRegionFromMultiplexResult(message); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} MultiplexInternalCallback timetoken = {1}; region = {2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), timetoken, region), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + MultiChannelSubscribeRequest(type, channels, channelGroups, timetoken, region, false, null, this.customQueryParam); + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Lost Channel Name for resubscribe", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + } + } + + private bool ReconnectNetworkIfOverrideTcpKeepAlive(PNOperationType type, string[] channels, string[] channelGroups, object timetoken, int region, bool networkAvailable) + { + if (OverrideTcpKeepAlive) { + ReconnectState netState = new ReconnectState(); + netState.Channels = channels; + netState.ChannelGroups = channelGroups; + netState.ResponseType = type; + netState.Timetoken = timetoken; + netState.Region = region; + if (!config.ContainsKey(PubnubInstance.InstanceId)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, InstanceId Not Available. So no reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), PNLogVerbosity.BODY); + } + + if (SubscribeDisconnected[PubnubInstance.InstanceId]) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Subscribe is still Disconnected. So no reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + } else if (config[PubnubInstance.InstanceId].ReconnectionPolicy != PNReconnectionPolicy.NONE) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Subscribe - No internet connection for channel={1} and channelgroup={2}; networkAvailable={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), channelGroups != null ? string.Join(",", channelGroups) : "", networkAvailable), config[PubnubInstance.InstanceId].LogVerbosity); + TerminateReconnectTimer(); + ReconnectNetwork(netState); + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, reconnection policy is DISABLED, please handle reconnection manually.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + if (!networkAvailable) { + PNStatusCategory errorCategory = PNStatusCategory.PNNetworkIssuesCategory; + PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(type, errorCategory, null, Constants.ResourceNotFoundStatusCode, new PNException("SDK Network related error")); + if (channels != null && channels.Length > 0) { + status.AffectedChannels.AddRange(channels); + } + if (channelGroups != null && channelGroups.Length > 0) { + status.AffectedChannels.AddRange(channelGroups); + } + Announce(status); + + } + } + return true; + } else { + return false; + } + } + + private void ReconnectNetwork(ReconnectState netState) + { + if (netState != null && ((netState.Channels != null && netState.Channels.Length > 0) || (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0))) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager ReconnectNetwork interval = {1} sec", DateTime.Now.ToString(CultureInfo.InvariantCulture), PubnubNetworkTcpCheckIntervalInSeconds), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + + System.Threading.Timer timer; + + if (netState.Channels != null && netState.Channels.Length > 0) { + string reconnectChannelTimerKey = string.Join(",", netState.Channels.OrderBy(x => x).ToArray()); + + if (!ChannelReconnectTimer[PubnubInstance.InstanceId].ContainsKey(reconnectChannelTimerKey)) { + timer = new Timer(new TimerCallback(ReconnectNetworkCallback), netState, 0, + (-1 == PubnubNetworkTcpCheckIntervalInSeconds) ? Timeout.Infinite : PubnubNetworkTcpCheckIntervalInSeconds * 1000); + ChannelReconnectTimer[PubnubInstance.InstanceId].AddOrUpdate(reconnectChannelTimerKey, timer, (key, oldState) => timer); + } + } else if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + string reconnectChannelGroupTimerKey = string.Join(",", netState.ChannelGroups.OrderBy(x => x).ToArray()); + + if (!ChannelGroupReconnectTimer[PubnubInstance.InstanceId].ContainsKey(reconnectChannelGroupTimerKey)) { + timer = new Timer(new TimerCallback(ReconnectNetworkCallback), netState, 0, + (-1 == PubnubNetworkTcpCheckIntervalInSeconds) ? Timeout.Infinite : PubnubNetworkTcpCheckIntervalInSeconds * 1000); + ChannelGroupReconnectTimer[PubnubInstance.InstanceId].AddOrUpdate(reconnectChannelGroupTimerKey, timer, (key, oldState) => timer); + } + } + } + } + + internal bool Reconnect(bool resetSubscribeTimetoken) + { + if (!SubscribeDisconnected[PubnubInstance.InstanceId]) //Check if disconnect is done before + { + return false; + } + + string[] channels = GetCurrentSubscriberChannels(); + string[] channelGroups = GetCurrentSubscriberChannelGroups(); + + if ((channels != null && channels.Length > 0) || (channelGroups != null && channelGroups.Length > 0)) { + bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, PNOperationType.PNSubscribeOperation, null, channels, channelGroups); + if (!networkConnection) { + networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, PNOperationType.PNSubscribeOperation, null, channels, channelGroups); + } + if (!networkConnection) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No network for SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + + PNStatusCategory errorCategory = PNStatusCategory.PNNetworkIssuesCategory; + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNSubscribeOperation, errorCategory, null, Constants.ResourceNotFoundStatusCode, new PNException("SDK Network related error")); + if (channels != null && channels.Length > 0) { + status.AffectedChannels.AddRange(channels); + } + if (channelGroups != null && channelGroups.Length > 0) { + status.AffectedChannels.AddRange(channelGroups); + } + Announce(status); + + return false; + } + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No channels/channelgroups for SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + return false; + } + + + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager Manual Reconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + SubscribeDisconnected[PubnubInstance.InstanceId] = false; + + Task.Factory.StartNew(() => { + if (resetSubscribeTimetoken) { + LastSubscribeTimetoken[PubnubInstance.InstanceId] = 0; + LastSubscribeRegion[PubnubInstance.InstanceId] = 0; + } + MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, GetCurrentSubscriberChannels(), GetCurrentSubscriberChannelGroups(), LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, this.customQueryParam); + }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); + + return true; + } + + internal bool Disconnect() + { + if (SubscribeDisconnected[PubnubInstance.InstanceId]) { + return false; + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager Manual Disconnect", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + SubscribeDisconnected[PubnubInstance.InstanceId] = true; + TerminateCurrentSubscriberRequest(); + TerminatePresenceHeartbeatTimer(); + TerminateReconnectTimer(); + + return true; + } + + internal void StartSubscribeHeartbeatCheckCallback(object state) + { + try { + if (SubscribeDisconnected[PubnubInstance.InstanceId]) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - SubscribeDisconnected. No heartbeat check.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + return; + } + if (!config.ContainsKey(PubnubInstance.InstanceId)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, InstanceId Not Available. So No heartbeat check.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + return; + } + + string[] channels = GetCurrentSubscriberChannels(); + string[] chananelGroups = GetCurrentSubscriberChannelGroups(); + + if ((channels != null && channels.Length > 0) || (chananelGroups != null && chananelGroups.Length > 0)) { + bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, PNOperationType.PNSubscribeOperation, null, channels, chananelGroups); + if (networkConnection && PubnubInstance != null && SubscribeRequestTracker.ContainsKey(PubnubInstance.InstanceId)) { + DateTime lastSubscribeRequestTime = SubscribeRequestTracker[PubnubInstance.InstanceId]; + if ((DateTime.Now - lastSubscribeRequestTime).TotalSeconds < config[PubnubInstance.InstanceId].SubscribeTimeout) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - ok. expected subscribe within threshold limit of SubscribeTimeout. No action needed", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + } else if ((DateTime.Now - lastSubscribeRequestTime).TotalSeconds > 2 * (config[PubnubInstance.InstanceId].SubscribeTimeout - config[PubnubInstance.InstanceId].SubscribeTimeout / 2)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - **No auto subscribe within threshold limit of SubscribeTimeout**. Calling MultiChannelSubscribeRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + Task.Factory.StartNew(() => { + TerminateCurrentSubscriberRequest(); + MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, channels, chananelGroups, LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, this.customQueryParam); + }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - **No auto subscribe within threshold limit of SubscribeTimeout**. Calling TerminateCurrentSubscriberRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + Task.Factory.StartNew(() => { + TerminateCurrentSubscriberRequest(); + }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); + } + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - StartSubscribeHeartbeatCheckCallback - No network or no pubnub instance mapping", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + if (PubnubInstance != null && !networkConnection) { + PNStatus status = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(PNOperationType.PNSubscribeOperation, PNStatusCategory.PNNetworkIssuesCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem during subscribe heartbeat.")); + if (channels != null && channels.Length > 0) { + status.AffectedChannels.AddRange(channels.ToList()); + } + if (chananelGroups != null && chananelGroups.Length > 0) { + status.AffectedChannelGroups.AddRange(chananelGroups.ToList()); + } + Announce(status); + + TerminateCurrentSubscriberRequest(); + MultiChannelSubscribeRequest(PNOperationType.PNSubscribeOperation, GetCurrentSubscriberChannels(), GetCurrentSubscriberChannelGroups(), LastSubscribeTimetoken[PubnubInstance.InstanceId], LastSubscribeRegion[PubnubInstance.InstanceId], false, null, this.customQueryParam); + + } + } + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - StartSubscribeHeartbeatCheckCallback - No channels/cgs avaialable", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config[PubnubInstance.InstanceId].LogVerbosity); + try { + SubscribeHeartbeatCheckTimer.Change(Timeout.Infinite, Timeout.Infinite); + TerminateCurrentSubscriberRequest(); + } catch { /* ignore */ } + } + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SubscribeManager - StartSubscribeHeartbeatCheckCallback - EXCEPTION: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config[PubnubInstance.InstanceId].LogVerbosity); + } + } + + + protected void ReconnectNetworkCallback(System.Object reconnectState) + { + string channel = ""; + string channelGroup = ""; + + ReconnectState netState = reconnectState as ReconnectState; + try { + string subscribedChannels = (SubscriptionChannels[PubnubInstance.InstanceId].Count > 0) ? SubscriptionChannels[PubnubInstance.InstanceId].Keys.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; + string subscribedChannelGroups = (SubscriptionChannelGroups[PubnubInstance.InstanceId].Count > 0) ? SubscriptionChannelGroups[PubnubInstance.InstanceId].Keys.OrderBy(x => x).Aggregate((x, y) => x + "," + y) : ""; + + + if (netState != null && ((netState.Channels != null && netState.Channels.Length > 0) || (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0))) { + if (netState.Channels == null) { + netState.Channels = new string[] { }; + } + + if (netState.ChannelGroups == null) { + netState.ChannelGroups = new string[] { }; + } + + bool channelInternetFlag; + bool channelGroupInternetFlag; + if (netState.Channels != null && netState.Channels.Length > 0) { + channel = (netState.Channels.Length > 0) ? string.Join(",", netState.Channels.OrderBy(x => x).ToArray()) : ","; + channelGroup = (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) ? string.Join(",", netState.ChannelGroups.OrderBy(x => x).ToArray()) : ""; + + if (netState.ResponseType == PNOperationType.PNSubscribeOperation || netState.ResponseType == PNOperationType.Presence) { + bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); + if (networkConnection) { + //Re-try to avoid false alert + networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); + } + if(!networkConnection){ + ConnectionErrors++; + UpdatePubnubNetworkTcpCheckIntervalInSeconds(); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channel={1} {2} reconnectNetworkCallback. Retry", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + if (netState.Channels != null && netState.Channels.Length > 0) { + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNNetworkIssuesCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem. Retrying connection")); + if (netState.Channels != null && netState.Channels.Length > 0) { + status.AffectedChannels.AddRange(netState.Channels.ToList()); + } + if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); + } + Announce(status); + } + } + } + + if (ChannelInternetStatus[PubnubInstance.InstanceId].ContainsKey(channel) && ChannelInternetStatus[PubnubInstance.InstanceId].TryGetValue(channel, out channelInternetFlag) && channelInternetFlag) { + if (ChannelReconnectTimer[PubnubInstance.InstanceId].ContainsKey(channel)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, {1} {2} terminating ch reconnectimer", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + TerminateReconnectTimer(); + } + + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNReconnectedCategory, null, (int)System.Net.HttpStatusCode.OK, null); + if (netState.Channels != null && netState.Channels.Length > 0) { + status.AffectedChannels.AddRange(netState.Channels.ToList()); + } + if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); + } + Announce(status); + + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channel={1} {2} reconnectNetworkCallback. Internet Available : {3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, netState.ResponseType, channelInternetFlag.ToString()), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + switch (netState.ResponseType) { + case PNOperationType.PNSubscribeOperation: + case PNOperationType.Presence: + MultiChannelSubscribeRequest(netState.ResponseType, netState.Channels, netState.ChannelGroups, netState.Timetoken, netState.Region, true, null, this.customQueryParam); + break; + default: + break; + } + } + } else if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + channelGroup = string.Join(",", netState.ChannelGroups.OrderBy(x => x).ToArray()); + channel = (netState.Channels != null && netState.Channels.Length > 0) ? string.Join(",", netState.Channels.OrderBy(x => x).ToArray()) : ","; + + if (subscribedChannelGroups == channelGroup && channelGroup != "" && ChannelGroupInternetStatus[PubnubInstance.InstanceId].ContainsKey(channelGroup) + && (netState.ResponseType == PNOperationType.PNSubscribeOperation || netState.ResponseType == PNOperationType.Presence)) { + bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); + if (networkConnection) { + //Re-try to avoid false alert + networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, netState.ResponseType, netState.PubnubCallback, netState.Channels, netState.ChannelGroups); + } + + if (ChannelGroupInternetStatus[PubnubInstance.InstanceId].TryGetValue(channelGroup, out channelGroupInternetFlag) && channelGroupInternetFlag) { + //do nothing + } else { + ChannelGroupInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channelGroup, networkConnection, (key, oldValue) => networkConnection); + if (!string.IsNullOrEmpty(channel) && channel.Length > 0) { + ChannelInternetStatus[PubnubInstance.InstanceId].AddOrUpdate(channel, networkConnection, (key, oldValue) => networkConnection); + } + + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channelgroup={1} {2} reconnectNetworkCallback. Retrying", DateTime.Now.ToString(CultureInfo.InvariantCulture), channelGroup, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + + if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNReconnectedCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem. Retrying connection")); + if (netState.Channels != null && netState.Channels.Length > 0) { + status.AffectedChannels.AddRange(netState.Channels.ToList()); + } + if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); + } + Announce(status); + } + } + } + + if (ChannelGroupInternetStatus[PubnubInstance.InstanceId].TryGetValue(channelGroup, out channelGroupInternetFlag) && channelGroupInternetFlag) { + if (ChannelGroupReconnectTimer[PubnubInstance.InstanceId].ContainsKey(channelGroup)) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, {1} {2} terminating cg reconnectimer", DateTime.Now.ToString(CultureInfo.InvariantCulture), channelGroup, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + TerminateReconnectTimer(); + } + + //Send one ReConnectedCategory message. If Channels NOT available then use this + if (netState.Channels.Length == 0 && netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, PNStatusCategory.PNReconnectedCategory, null, (int)System.Net.HttpStatusCode.OK, null); + if (netState.Channels != null && netState.Channels.Length > 0) { + status.AffectedChannels.AddRange(netState.Channels.ToList()); + } + if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + status.AffectedChannelGroups.AddRange(netState.ChannelGroups.ToList()); + } + Announce(status); + } + + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, channelgroup={1} {2} reconnectNetworkCallback. Internet Available", DateTime.Now.ToString(CultureInfo.InvariantCulture), channelGroup, netState.ResponseType), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + switch (netState.ResponseType) { + case PNOperationType.PNSubscribeOperation: + case PNOperationType.Presence: + MultiChannelSubscribeRequest(netState.ResponseType, netState.Channels, netState.ChannelGroups, netState.Timetoken, netState.Region, true, null, this.customQueryParam); + break; + default: + break; + } + } + } + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Unknown request state in reconnectNetworkCallback", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + } + } catch (Exception ex) { + if (netState != null) { + PNStatusCategory errorCategory = PNStatusCategoryHelper.GetPNStatusCategory(ex); + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(netState.ResponseType, errorCategory, null, Constants.ResourceNotFoundStatusCode, new PNException(ex)); + if (netState.Channels != null && netState.Channels.Length > 0) { + status.AffectedChannels.AddRange(netState.Channels.ToList()); + } + if (netState.ChannelGroups != null && netState.ChannelGroups.Length > 0) { + status.AffectedChannels.AddRange(netState.ChannelGroups.ToList()); + } + Announce(status); + } + + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} method:reconnectNetworkCallback \n Exception Details={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].LogVerbosity : PNLogVerbosity.NONE); + } + } + + private void RegisterPresenceHeartbeatTimer(string[] channels, string[] channelGroups) + { + if (PresenceHeartbeatTimer != null) { + try { + PresenceHeartbeatTimer.Change(Timeout.Infinite, Timeout.Infinite); + PresenceHeartbeatTimer.Dispose(); + PresenceHeartbeatTimer = null; + } catch { /* ignore */ } + } + if ((channels != null && channels.Length > 0 && channels.Where(s => s != null && s.Contains("-pnpres") == false).Any()) + || (channelGroups != null && channelGroups.Length > 0 && channelGroups.Where(s => s != null && s.Contains("-pnpres") == false).Any())) { + RequestState presenceHeartbeatState = new RequestState(); + presenceHeartbeatState.Channels = channels; + presenceHeartbeatState.ChannelGroups = channelGroups; + presenceHeartbeatState.ResponseType = PNOperationType.PNHeartbeatOperation; + presenceHeartbeatState.RequestCancellationTokenSource = null; + presenceHeartbeatState.Response = null; + + if (config.ContainsKey(PubnubInstance.InstanceId) && config[PubnubInstance.InstanceId].PresenceInterval > 0) { + PresenceHeartbeatTimer = new Timer(OnPresenceHeartbeatIntervalTimeout, presenceHeartbeatState, config[PubnubInstance.InstanceId].PresenceInterval * 1000, config[PubnubInstance.InstanceId].PresenceInterval * 1000); + } + } + } + + void OnPresenceHeartbeatIntervalTimeout(System.Object presenceHeartbeatState) + { + //Make presence heartbeat call + RequestState currentState = presenceHeartbeatState as RequestState; + if (currentState != null) { + string[] subscriberChannels = (currentState.Channels != null) ? currentState.Channels.Where(s => s.Contains("-pnpres") == false).ToArray() : null; + string[] subscriberChannelGroups = (currentState.ChannelGroups != null) ? currentState.ChannelGroups.Where(s => s.Contains("-pnpres") == false).ToArray() : null; + + bool networkConnection = CheckInternetConnectionStatus(PubnetSystemActive, currentState.ResponseType, currentState.PubnubCallback, currentState.Channels, currentState.ChannelGroups); + if (networkConnection) { + if ((subscriberChannels != null && subscriberChannels.Length > 0) || (subscriberChannelGroups != null && subscriberChannelGroups.Length > 0)) { + RequestState requestState = new RequestState(); + requestState.Channels = currentState.Channels; + requestState.ChannelGroups = currentState.ChannelGroups; + requestState.ResponseType = PNOperationType.PNHeartbeatOperation; + requestState.PubnubCallback = null; + requestState.Reconnect = false; + requestState.Response = null; + requestState.TimeQueued = DateTime.Now; + var heartbeatRequestParameter = CreateHeartbeatRequestParameter(subscriberChannels, subscriberChannelGroups); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: heartbeatRequestParameter, operationType: PNOperationType.PNHeartbeatOperation); + PNStatus responseStatus; + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) + { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + responseStatus = new StatusBuilder(config[PubnubInstance.InstanceId], jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + ProcessResponseCallbacks(result, requestState); + } else { + responseStatus = errorStatus; + ProcessResponseCallbacks(default, requestState); + } + } + }); + } + } else { + if (PubnubInstance != null && !networkConnection) { + PNStatus status = new StatusBuilder(config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId] : null, jsonLibrary).CreateStatusResponse(PNOperationType.PNSubscribeOperation, PNStatusCategory.PNNetworkIssuesCategory, null, (int)System.Net.HttpStatusCode.NotFound, new PNException("Internet connection problem during presence heartbeat.")); + if (subscriberChannels != null && subscriberChannels.Length > 0) { + status.AffectedChannels.AddRange(subscriberChannels.ToList()); + } + if (subscriberChannelGroups != null && subscriberChannelGroups.Length > 0) { + status.AffectedChannelGroups.AddRange(subscriberChannelGroups.ToList()); + } + Announce(status); + } + } + } + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateLeaveRequestParameter(string[] channels, string[] channelGroups) + { + string channleString = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config[PubnubInstance.InstanceId].SubscribeKey, + "channel", + channleString, + "leave" + }; + + var requestQueryStringParams = new Dictionary(); + + if (channelGroups != null && channelGroups.Length > 0) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), PNOperationType.Leave, false, false, false)); + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + + private RequestParameter CreateHeartbeatRequestParameter(string[] channels, string[] channelGroups) + { + string channelString = (channels != null && channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List + { + "v2", + "presence", + "sub_key", + config[PubnubInstance.InstanceId].SubscribeKey, + "channel", + channelString, + "heartbeat" + }; + string presenceState = string.Empty; + + presenceState = BuildJsonUserState(channels, channelGroups, false); + Dictionary requestQueryStringParams = new Dictionary(); + + string channelsJsonState = presenceState; + if (channelsJsonState != "{}" && channelsJsonState != string.Empty) { + requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(channelsJsonState, PNOperationType.PNHeartbeatOperation, false, false, false)); + } + + if (channelGroups != null && channelGroups.Length > 0) { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), PNOperationType.PNHeartbeatOperation, false, false, false)); + } + + if (config[PubnubInstance.InstanceId].PresenceTimeout != 0) { + requestQueryStringParams.Add("heartbeat", config[PubnubInstance.InstanceId].PresenceTimeout.ToString(CultureInfo.InvariantCulture)); + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + + private RequestParameter CreateSubscribeRequestParameter(string[] channels, string[] channelGroups, long timetoken, int region, string stateJsonValue, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + { + string channelsSegment = (channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List + { + "v2", + "subscribe", + config.ContainsKey(PubnubInstance.InstanceId) ? config[PubnubInstance.InstanceId].SubscribeKey : "", + channelsSegment, + "0" + }; + + Dictionary internalInitialSubscribeUrlParams = new Dictionary(); + if (initialSubscribeUrlParams != null) { + internalInitialSubscribeUrlParams = initialSubscribeUrlParams; + } + + Dictionary requestQueryStringParams = new Dictionary(internalInitialSubscribeUrlParams); + + if (!requestQueryStringParams.ContainsKey("filter-expr") && config.ContainsKey(PubnubInstance.InstanceId) && !string.IsNullOrEmpty(config[PubnubInstance.InstanceId].FilterExpression)) { + requestQueryStringParams.Add("filter-expr", UriUtil.EncodeUriComponent(config[PubnubInstance.InstanceId].FilterExpression, PNOperationType.PNSubscribeOperation, false, false, false)); + } + + if (!requestQueryStringParams.ContainsKey("ee") && config.ContainsKey(PubnubInstance.InstanceId) && config[PubnubInstance.InstanceId].EnableEventEngine) { + requestQueryStringParams.Add("ee", ""); + } + + if (!requestQueryStringParams.ContainsKey("tt")) { + requestQueryStringParams.Add("tt", timetoken.ToString(CultureInfo.InvariantCulture)); + } + + if (!requestQueryStringParams.ContainsKey("tr") && region > 0) { + requestQueryStringParams.Add("tr", region.ToString(CultureInfo.InvariantCulture)); + } + + if (config.ContainsKey(PubnubInstance.InstanceId) && config[PubnubInstance.InstanceId].PresenceTimeout != 0) { + requestQueryStringParams.Add("heartbeat", config[PubnubInstance.InstanceId].PresenceTimeout.ToString(CultureInfo.InvariantCulture)); + } + + if (channelGroups != null && channelGroups.Length > 0 && channelGroups[0] != "") { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), PNOperationType.PNSubscribeOperation, false, false, false)); + } + + if (stateJsonValue != "{}" && stateJsonValue != "") { + requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(stateJsonValue, PNOperationType.PNSubscribeOperation, false, false, false)); + } + + if (externalQueryParam != null && externalQueryParam.Count > 0) { + foreach (KeyValuePair kvp in externalQueryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSubscribeOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams, + }; + return requestParameter; + } + + + private bool disposedValue; + + protected virtual void DisposeInternal(bool disposing) + { + if (!disposedValue) { + if (SubscribeHeartbeatCheckTimer != null) { + SubscribeHeartbeatCheckTimer.Dispose(); + } + + disposedValue = true; + } + } + + void IDisposable.Dispose() + { + DisposeInternal(true); + } + + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs index d6c809293..6b9fe8dc5 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeManager2.cs @@ -2,606 +2,407 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using System.Net; using System.Threading.Tasks; using System.Globalization; -using System.Collections; using System.Text; using PubnubApi.EventEngine.Subscribe.Common; -using Newtonsoft.Json; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 -using System.Net.Http; -using System.Net.Http.Headers; -#endif namespace PubnubApi.EndPoint { - internal class SubscribeManager2 : IDisposable - { - private PNConfiguration config; - private IJsonPluggableLibrary jsonLibrary; - private IPubnubUnitTest unit; - private IPubnubLog pubnubLog; - private EndPoint.TelemetryManager pubnubTelemetryMgr; - private IPubnubHttp pubnubHttp; - - private Timer SubscribeHeartbeatCheckTimer; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - private HttpClient httpSubscribe { get; set; } - private HttpClient httpNonsubscribe { get; set; } - private HttpClient httpNetworkStatus { get; set; } - private PubnubHttpClientHandler pubnubHttpClientHandler { get; set; } -#else - private HttpWebRequest httpSubscribe { get; set; } -#endif - public SubscribeManager2(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - //PubnubInstance = instance; - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (httpSubscribe == null) - { - if (config.Proxy != null) - { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - if (httpClientHandler.SupportsProxy) - { - httpClientHandler.Proxy = config.Proxy; - httpClientHandler.UseProxy = true; - } - pubnubHttpClientHandler = new PubnubHttpClientHandler("PubnubHttpClientHandler", httpClientHandler, config, jsonLibrary, unit, log); - httpSubscribe = new HttpClient(pubnubHttpClientHandler); - } - else - { - httpSubscribe = new HttpClient(); - } - httpSubscribe.DefaultRequestHeaders.Accept.Clear(); - httpSubscribe.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - httpSubscribe.Timeout = TimeSpan.FromSeconds(config.SubscribeTimeout); - } - if (httpNonsubscribe == null) - { - if (config.Proxy != null) - { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - if (httpClientHandler.SupportsProxy) - { - httpClientHandler.Proxy = config.Proxy; - httpClientHandler.UseProxy = true; - } - pubnubHttpClientHandler = new PubnubHttpClientHandler("PubnubHttpClientHandler", httpClientHandler, config, jsonLibrary, unit, log); - httpNonsubscribe = new HttpClient(pubnubHttpClientHandler); - } - else - { - httpNonsubscribe = new HttpClient(); - } - httpNonsubscribe.DefaultRequestHeaders.Accept.Clear(); - httpNonsubscribe.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - httpNonsubscribe.Timeout = TimeSpan.FromSeconds(config.NonSubscribeRequestTimeout); - } - pubnubHttp = new PubnubHttp(config, jsonLibrary, log, pubnubTelemetryMgr, httpSubscribe, httpNonsubscribe); -#else - pubnubHttp = new PubnubHttp(config, jsonLibrary, log, pubnubTelemetryMgr); -#endif - } - -#pragma warning disable - - public async Task> HandshakeRequest(PNOperationType responseType, string[] channels, string[] channelGroups, long? timetoken, int? region, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) - { - string presenceState = string.Empty; - if (config.MaintainPresenceState) presenceState = BuildJsonUserState(channels, channelGroups, true); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, ""); - Uri request = urlBuilder.BuildMultiChannelSubscribeRequest("GET", "", channels, channelGroups, timetoken.GetValueOrDefault(), region.GetValueOrDefault(), presenceState, initialSubscribeUrlParams, externalQueryParam); - - RequestState pubnubRequestState = new RequestState(); - pubnubRequestState.Channels = channels; - pubnubRequestState.ChannelGroups = channelGroups; - pubnubRequestState.ResponseType = responseType; - pubnubRequestState.Timetoken = timetoken.GetValueOrDefault(); - pubnubRequestState.Region = region.GetValueOrDefault(); - pubnubRequestState.TimeQueued = DateTime.Now; - - Tuple responseTuple = await UrlProcessRequest(request, pubnubRequestState, false).ConfigureAwait(false); - if (!string.IsNullOrEmpty(responseTuple.Item1) && responseTuple.Item2 == null) - { - PNStatus status = new PNStatus(null, PNOperationType.PNSubscribeOperation, PNStatusCategory.PNConnectedCategory, channels, channelGroups); - HandshakeResponse handshakeResponse = jsonLibrary.DeserializeToObject(responseTuple.Item1); - return new Tuple(handshakeResponse, status); - } - - return new Tuple(null, responseTuple.Item2); - } - - internal void HandshakeRequestCancellation() - { - if (httpSubscribe != null) - { - try - { - #if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - httpSubscribe.CancelPendingRequests(); - #else - httpSubscribe.Abort(); - #endif - httpSubscribe = null; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation. Done.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation Exception: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - } - } - internal async Task, PNStatus>> ReceiveRequest(PNOperationType responseType, string[] channels, string[] channelGroups, long? timetoken, int? region, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) - { - Tuple, PNStatus> resp = new Tuple, PNStatus>(null, null); - - try - { - string channelsJsonState = BuildJsonUserState(channels, channelGroups, false); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, ""); - Uri request = urlBuilder.BuildMultiChannelSubscribeRequest("GET", "", channels, channelGroups, timetoken.GetValueOrDefault(), region.GetValueOrDefault(), channelsJsonState, initialSubscribeUrlParams, externalQueryParam); - - RequestState> pubnubRequestState = new RequestState>(); - pubnubRequestState.Channels = channels; - pubnubRequestState.ChannelGroups = channelGroups; - pubnubRequestState.ResponseType = responseType; - //pubnubRequestState.Reconnect = reconnect; - pubnubRequestState.Timetoken = timetoken.GetValueOrDefault(); - pubnubRequestState.Region = region.GetValueOrDefault(); - pubnubRequestState.TimeQueued = DateTime.Now; - - // Wait for message - var responseTuple = await UrlProcessRequest(request, pubnubRequestState, true).ConfigureAwait(false); - if (!string.IsNullOrEmpty(responseTuple.Item1) && responseTuple.Item2 == null) - { - PNStatus status = new PNStatus(null, PNOperationType.PNSubscribeOperation, PNStatusCategory.PNConnectedCategory, channels, channelGroups); - ReceivingResponse receiveResponse = jsonLibrary.DeserializeToObject>(responseTuple.Item1); - return new Tuple, PNStatus>(receiveResponse, status); - } - else if (responseTuple.Item2 != null) - { - return new Tuple, PNStatus>(null, responseTuple.Item2); - } - return new Tuple, PNStatus>(null, new PNStatus(new Exception("ReceiveRequest failed."), PNOperationType.PNSubscribeOperation, PNStatusCategory.PNUnknownCategory, channels, channelGroups)); - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager=> MultiChannelSubscribeInit \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), string.Join(",", channelGroups.OrderBy(x => x).ToArray()), ex), config.LogVerbosity); - } - return resp; - } - - internal void ReceiveRequestCancellation() - { - if (httpSubscribe != null) - { - try - { - #if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - httpSubscribe.CancelPendingRequests(); - #else - httpSubscribe.Abort(); - #endif - httpSubscribe = null; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveRequestCancellation. Done.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveRequestCancellation Exception: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => RequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - } - } - - internal void ReceiveReconnectRequestCancellation() - { - if (httpSubscribe != null) - { - try - { - #if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - httpSubscribe.CancelPendingRequests(); - #else - httpSubscribe.Abort(); - #endif - httpSubscribe = null; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveReconnectRequestCancellation. Done.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - } - catch(Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveReconnectRequestCancellation Exception: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveReconnectRequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - } - } - - internal protected async Task> UrlProcessRequest(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest) - { - return await UrlProcessRequest(requestUri, pubnubRequestState, terminateCurrentSubRequest, null).ConfigureAwait(false); - } - -#pragma warning disable - internal protected async Task> UrlProcessRequest(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest, byte[] postOrPatchData) -#pragma warning restore - { - return await UrlProcessRequest(requestUri, pubnubRequestState, terminateCurrentSubRequest, postOrPatchData,"").ConfigureAwait(false); - } - - internal protected async Task> UrlProcessRequest(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest, byte[] postOrPatchData, string contentType) - { - string channel = ""; - PNConfiguration currentConfig; - IPubnubLog currentLog; - - try - { - if (pubnubRequestState != null) - { - channel = (pubnubRequestState.Channels != null && pubnubRequestState.Channels.Length > 0) ? string.Join(",", pubnubRequestState.Channels.OrderBy(x => x).ToArray()) : ","; - - } - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - //do nothing -#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"; - } - request.ContentType = contentType; - - pubnubRequestState.Request = request; - httpSubscribe = request; -#endif - - string jsonString = ""; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubRequestState != null && pubnubRequestState.UsePostMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPOST(requestUri, pubnubRequestState, null, postOrPatchData, contentType).ConfigureAwait(false); - } - else if (pubnubRequestState != null && pubnubRequestState.UsePatchMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPATCH(requestUri, pubnubRequestState, null, postOrPatchData, contentType).ConfigureAwait(false); - } - else - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponse(requestUri, pubnubRequestState, null).ConfigureAwait(false); - } -#else - if (pubnubRequestState != null && pubnubRequestState.UsePostMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPOST(requestUri, pubnubRequestState, request, postOrPatchData, contentType).ConfigureAwait(false); - } - else if (pubnubRequestState != null && pubnubRequestState.UsePatchMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPATCH(requestUri, pubnubRequestState, request, postOrPatchData, contentType).ConfigureAwait(false); - } - else - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponse(requestUri, pubnubRequestState, request).ConfigureAwait(false); - } -#endif - if (pubnubLog != null && config != null) - { - LoggingMethod.WriteToLog(pubnubLog, $"DateTime {DateTime.Now.ToString(CultureInfo.InvariantCulture)}, JSON= {jsonString} for request={requestUri}", config.LogVerbosity); - } - PNStatus errStatus = GetStatusIfError(pubnubRequestState, jsonString); - return new Tuple((errStatus == null) ? jsonString : "", errStatus); - } - catch (Exception ex) - { - string errorMessage = ex.Message; - string exceptionMessage = ""; - Exception innerEx = null; - WebException webEx = null; - PNStatus status = null; - - if (ex.InnerException != null) - { - if (ex is WebException) - { - webEx = ex as WebException; - exceptionMessage = webEx.ToString(); - } - else - { - innerEx = ex.InnerException; - exceptionMessage = innerEx.ToString(); - } - } - else - { - innerEx = ex; - exceptionMessage = innerEx.ToString(); - } - - if (exceptionMessage.IndexOf("The request was aborted: The request was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 - && exceptionMessage.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.CurrentCultureIgnoreCase) == -1 - && (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation && exceptionMessage.IndexOf("The operation has timed out", StringComparison.CurrentCultureIgnoreCase) == -1) - && exceptionMessage.IndexOf("A task was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 - && errorMessage.IndexOf("The operation was canceled", StringComparison.CurrentCultureIgnoreCase) == -1) - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(webEx == null ? innerEx : webEx); - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(pubnubRequestState.ResponseType, category, pubnubRequestState, (int)HttpStatusCode.NotFound, new PNException(ex)); - //if (pubnubRequestState != null && pubnubRequestState.PubnubCallback != null) - //{ - // pubnubRequestState.PubnubCallback.OnResponse(default(T), status); - //} - //else - //{ - // Announce(status); - //} - - //if (PubnubInstance != null && pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - //{ - // LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PubnubBaseCore UrlProcessRequest Exception={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), webEx != null ? webEx.ToString() : exceptionMessage), currentConfig.LogVerbosity); - //} - } - - return new Tuple("", status); - } - } - - protected string BuildJsonUserState(string channel, string channelGroup, bool local) - { - Dictionary channelUserStateDictionary = null; - Dictionary channelGroupUserStateDictionary = null; - - if (!string.IsNullOrEmpty(channel) && !string.IsNullOrEmpty(channelGroup)) - { - throw new ArgumentException("BuildJsonUserState takes either channel or channelGroup at one time. Send one at a time by passing empty value for other."); - } - - StringBuilder jsonStateBuilder = new StringBuilder(); - - if (channelUserStateDictionary != null) - { - string[] channelUserStateKeys = channelUserStateDictionary.Keys.ToArray(); - - for (int keyIndex = 0; keyIndex < channelUserStateKeys.Length; keyIndex++) - { - string channelUserStateKey = channelUserStateKeys[keyIndex]; - object channelUserStateValue = channelUserStateDictionary[channelUserStateKey]; - if (channelUserStateValue == null) - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelUserStateKey, string.Format(CultureInfo.InvariantCulture, "\"{0}\"", "null")); - } - else if (channelUserStateValue.GetType().ToString() == "System.Boolean") - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelUserStateKey, channelUserStateValue.ToString().ToLowerInvariant()); - } - else - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelUserStateKey, (channelUserStateValue.GetType().ToString() == "System.String") ? string.Format(CultureInfo.InvariantCulture, "\"{0}\"", channelUserStateValue) : channelUserStateValue); - } - if (keyIndex < channelUserStateKeys.Length - 1) - { - jsonStateBuilder.Append(','); - } - } - } - if (channelGroupUserStateDictionary != null) - { - string[] channelGroupUserStateKeys = channelGroupUserStateDictionary.Keys.ToArray(); - - for (int keyIndex = 0; keyIndex < channelGroupUserStateKeys.Length; keyIndex++) - { - string channelGroupUserStateKey = channelGroupUserStateKeys[keyIndex]; - object channelGroupUserStateValue = channelGroupUserStateDictionary[channelGroupUserStateKey]; - if (channelGroupUserStateValue == null) - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelGroupUserStateKey, string.Format(CultureInfo.InvariantCulture, "\"{0}\"", "null")); - } - else if (channelGroupUserStateValue.GetType().ToString() == "System.Boolean") - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelGroupUserStateKey, channelGroupUserStateValue.ToString().ToLowerInvariant()); - } - else - { - jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelGroupUserStateKey, (channelGroupUserStateValue.GetType().ToString() == "System.String") ? string.Format(CultureInfo.InvariantCulture, "\"{0}\"", channelGroupUserStateValue) : channelGroupUserStateValue); - } - if (keyIndex < channelGroupUserStateKeys.Length - 1) - { - jsonStateBuilder.Append(','); - } - } - } - - return jsonStateBuilder.ToString(); - } - - protected string BuildJsonUserState(string[] channels, string[] channelGroups, bool local) - { - string retJsonUserState = ""; - - StringBuilder jsonStateBuilder = new StringBuilder(); - - if (channels != null && channels.Length > 0) - { - for (int index = 0; index < channels.Length; index++) - { - string currentJsonState = BuildJsonUserState(channels[index], "", local); - if (!string.IsNullOrEmpty(currentJsonState)) - { - currentJsonState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", channels[index], currentJsonState); - if (jsonStateBuilder.Length > 0) - { - jsonStateBuilder.Append(','); - } - jsonStateBuilder.Append(currentJsonState); - } - } - } - - if (channelGroups != null && channelGroups.Length > 0) - { - for (int index = 0; index < channelGroups.Length; index++) - { - string currentJsonState = BuildJsonUserState("", channelGroups[index], local); - if (!string.IsNullOrEmpty(currentJsonState)) - { - currentJsonState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", channelGroups[index], currentJsonState); - if (jsonStateBuilder.Length > 0) - { - jsonStateBuilder.Append(','); - } - jsonStateBuilder.Append(currentJsonState); - } - } - } - - if (jsonStateBuilder.Length > 0) - { - retJsonUserState = string.Format(CultureInfo.InvariantCulture, "{{{0}}}", jsonStateBuilder); - } - - return retJsonUserState; - } - - private PNStatus GetStatusIfError(RequestState asyncRequestState, string jsonString) - { - PNStatus status = null; - if (string.IsNullOrEmpty(jsonString)) { return status; } - - PNConfiguration currentConfig; - PNOperationType type = PNOperationType.None; - if (asyncRequestState != null) - { - type = asyncRequestState.ResponseType; - } - if (jsonLibrary.IsDictionaryCompatible(jsonString, type)) - { - Dictionary deserializeStatus = jsonLibrary.DeserializeToDictionaryOfObject(jsonString); - int statusCode = 0; //default. assuming all is ok - if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("error") && string.Equals(deserializeStatus["error"].ToString(), "true", StringComparison.OrdinalIgnoreCase)) - { - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, PNStatusCategory.PNUnknownCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); - } - else if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("error") && deserializeStatus.ContainsKey("status") && Int32.TryParse(deserializeStatus["status"].ToString(), out statusCode) && statusCode > 0) - { - string errorMessageJson = deserializeStatus["error"].ToString(); - Dictionary errorDic = jsonLibrary.DeserializeToDictionaryOfObject(errorMessageJson); - if (errorDic != null && errorDic.Count > 0 && errorDic.ContainsKey("message") - && statusCode != 200) - { - string statusMessage = errorDic["message"].ToString(); - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); - } - else if (statusCode != 200) - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, errorMessageJson); - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); - } - } - else if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("status") && string.Equals(deserializeStatus["status"].ToString(), "error", StringComparison.OrdinalIgnoreCase) && deserializeStatus.ContainsKey("error")) - { - string errorMessageJson = deserializeStatus["error"].ToString(); - Dictionary errorDic = jsonLibrary.DeserializeToDictionaryOfObject(errorMessageJson); - if (errorDic != null && errorDic.Count > 0 && errorDic.ContainsKey("code") && errorDic.ContainsKey("message")) - { - statusCode = PNStatusCodeHelper.GetHttpStatusCode(errorDic["code"].ToString()); - string statusMessage = errorDic["message"].ToString(); - if (statusCode != 200) - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); - } - } - } - else if (deserializeStatus.ContainsKey("status") && deserializeStatus.ContainsKey("message")) - { - var _ = Int32.TryParse(deserializeStatus["status"].ToString(), out statusCode); - string statusMessage = deserializeStatus["message"].ToString(); - - if (statusCode != 200) - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); - } - } - else if (deserializeStatus.ContainsKey("message") && statusCode != 200) { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, deserializeStatus["message"].ToString()); - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); - } - - } - else if (jsonString.ToLowerInvariant().TrimStart().IndexOf("(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); - } - else if (jsonString.ToLowerInvariant().TrimStart().IndexOf("(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); - } - else if (!NewtonsoftJsonDotNet.JsonFastCheck(jsonString)) - { - status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); - } - - return status; - } - - internal bool Disconnect() - { - return true; - } - - - #region IDisposable Support - private bool disposedValue; - - protected virtual void DisposeInternal(bool disposing) - { - if (!disposedValue) - { - if (SubscribeHeartbeatCheckTimer != null) - { - SubscribeHeartbeatCheckTimer.Dispose(); - } - - disposedValue = true; - } - } - - void IDisposable.Dispose() - { - DisposeInternal(true); - } - #endregion - - } + internal class SubscribeManager2 : IDisposable + { + private PNConfiguration config; + private IJsonPluggableLibrary jsonLibrary; + private IPubnubUnitTest unit; + private IPubnubLog pubnubLog; + private Pubnub pubnubInstance; + private CancellationTokenSource cancellationTokenSource; + private Timer SubscribeHeartbeatCheckTimer; + public SubscribeManager2(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + pubnubInstance = instance; + } + + public async Task> HandshakeRequest(PNOperationType responseType, string[] channels, string[] channelGroups, long? timetoken, int? region, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + { + string presenceState = string.Empty; + if (config.MaintainPresenceState) presenceState = BuildJsonUserState(channels, channelGroups, true); + var requestParameter = CreateSubscribeRequestParameter(channels: channels, channelGroups: channelGroups, timetoken: timetoken.GetValueOrDefault(), region: region.GetValueOrDefault(), stateJsonValue: presenceState, initialSubscribeUrlParams: initialSubscribeUrlParams, externalQueryParam: externalQueryParam); + var transportRequest = pubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSubscribeOperation); + cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(transportRequest.CancellationToken); + RequestState pubnubRequestState = new RequestState(); + pubnubRequestState.Channels = channels; + pubnubRequestState.ChannelGroups = channelGroups; + pubnubRequestState.ResponseType = responseType; + pubnubRequestState.Timetoken = timetoken.GetValueOrDefault(); + pubnubRequestState.Region = region.GetValueOrDefault(); + pubnubRequestState.TimeQueued = DateTime.Now; + var transportResponse = await pubnubInstance.transportMiddleware.Send(transportRequest: transportRequest); + + if (transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode && transportResponse.Error == null && transportResponse.Content != null) { + var responseJson = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus status = new PNStatus(null, PNOperationType.PNSubscribeOperation, PNStatusCategory.PNConnectedCategory, channels, channelGroups); + HandshakeResponse handshakeResponse = jsonLibrary.DeserializeToObject(responseJson); + return new Tuple(handshakeResponse, status); + } else { + PNStatus errStatus; + if (transportResponse.Error != null) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(transportResponse.Error); + errStatus = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(pubnubRequestState.ResponseType, category, pubnubRequestState, Constants.ResourceNotFoundStatusCode, new PNException(transportResponse.Error)); + } else { + string responseString = string.Empty; + if (transportResponse.Content != null) responseString = Encoding.UTF8.GetString(transportResponse.Content); + errStatus = GetStatusIfError(pubnubRequestState, responseString); + } + return new Tuple(null, errStatus); + } + } + + internal void HandshakeRequestCancellation() + { + try { + if (cancellationTokenSource != null) { + cancellationTokenSource.Cancel(); + cancellationTokenSource.Dispose(); + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation. Done.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => HandshakeRequestCancellation Exception: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); + } + } + internal async Task, PNStatus>> ReceiveRequest(PNOperationType responseType, string[] channels, string[] channelGroups, long? timetoken, int? region, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + { + Tuple, PNStatus> resp = new Tuple, PNStatus>(null, null); + try { + string channelsJsonState = BuildJsonUserState(channels, channelGroups, false); + var requestParameter = CreateSubscribeRequestParameter(channels: channels, channelGroups: channelGroups, timetoken: timetoken.GetValueOrDefault(), region: region.GetValueOrDefault(), stateJsonValue: channelsJsonState, initialSubscribeUrlParams: initialSubscribeUrlParams, externalQueryParam: externalQueryParam); + var transportRequest = pubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNSubscribeOperation); + cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(transportRequest.CancellationToken); + RequestState> pubnubRequestState = new RequestState>(); + pubnubRequestState.Channels = channels; + pubnubRequestState.ChannelGroups = channelGroups; + pubnubRequestState.ResponseType = responseType; + pubnubRequestState.Timetoken = timetoken.GetValueOrDefault(); + pubnubRequestState.Region = region.GetValueOrDefault(); + pubnubRequestState.TimeQueued = DateTime.Now; + + var transportResponse = await pubnubInstance.transportMiddleware.Send(transportRequest: transportRequest); + if (transportResponse.Content != null && transportResponse.Error == null && transportResponse.StatusCode == Constants.HttpRequestSuccessStatusCode) { + var responseJson = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus status = new PNStatus(null, PNOperationType.PNSubscribeOperation, PNStatusCategory.PNConnectedCategory, channels, channelGroups); + ReceivingResponse receiveResponse = jsonLibrary.DeserializeToObject>(responseJson); + return new Tuple, PNStatus>(receiveResponse, status); + } + PNStatus errStatus; + if (transportResponse.Error != null) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(transportResponse.Error); + errStatus = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(pubnubRequestState.ResponseType, category, pubnubRequestState, Constants.ResourceNotFoundStatusCode, new PNException(transportResponse.Error)); + } else { + string responseString = string.Empty; + if (transportResponse.Content != null) responseString = Encoding.UTF8.GetString(transportResponse.Content); + errStatus = GetStatusIfError(pubnubRequestState, responseString); + } + return new Tuple, PNStatus>(null, errStatus); + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager=> MultiChannelSubscribeInit \n channel(s)={1} \n cg(s)={2} \n Exception Details={3}", DateTime.Now.ToString(CultureInfo.InvariantCulture), string.Join(",", channels.OrderBy(x => x).ToArray()), string.Join(",", channelGroups.OrderBy(x => x).ToArray()), ex), config.LogVerbosity); + } + return resp; + } + + internal void ReceiveRequestCancellation() + { + try { + if (cancellationTokenSource != null) { + cancellationTokenSource.Cancel(); + cancellationTokenSource.Dispose(); + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => RequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveRequestCancellation. Done.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveRequestCancellation Exception: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); + } + } + + internal void ReceiveReconnectRequestCancellation() + { + try { + if (cancellationTokenSource != null) { + cancellationTokenSource.Cancel(); + cancellationTokenSource.Dispose(); + } else { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveReconnectRequestCancellation. No request to cancel.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveReconnectRequestCancellation. Done.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + } catch (Exception ex) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} SubscribeManager => ReceiveReconnectRequestCancellation Exception: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), config.LogVerbosity); + } + } + + protected string BuildJsonUserState(string channel, string channelGroup, bool local) + { + Dictionary channelUserStateDictionary = null; + Dictionary channelGroupUserStateDictionary = null; + + if (!string.IsNullOrEmpty(channel) && !string.IsNullOrEmpty(channelGroup)) { + throw new ArgumentException("BuildJsonUserState takes either channel or channelGroup at one time. Send one at a time by passing empty value for other."); + } + + StringBuilder jsonStateBuilder = new StringBuilder(); + + if (channelUserStateDictionary != null) { + string[] channelUserStateKeys = channelUserStateDictionary.Keys.ToArray(); + + for (int keyIndex = 0; keyIndex < channelUserStateKeys.Length; keyIndex++) { + string channelUserStateKey = channelUserStateKeys[keyIndex]; + object channelUserStateValue = channelUserStateDictionary[channelUserStateKey]; + if (channelUserStateValue == null) { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelUserStateKey, string.Format(CultureInfo.InvariantCulture, "\"{0}\"", "null")); + } else if (channelUserStateValue.GetType().ToString() == "System.Boolean") { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelUserStateKey, channelUserStateValue.ToString().ToLowerInvariant()); + } else { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelUserStateKey, (channelUserStateValue.GetType().ToString() == "System.String") ? string.Format(CultureInfo.InvariantCulture, "\"{0}\"", channelUserStateValue) : channelUserStateValue); + } + if (keyIndex < channelUserStateKeys.Length - 1) { + jsonStateBuilder.Append(','); + } + } + } + if (channelGroupUserStateDictionary != null) { + string[] channelGroupUserStateKeys = channelGroupUserStateDictionary.Keys.ToArray(); + + for (int keyIndex = 0; keyIndex < channelGroupUserStateKeys.Length; keyIndex++) { + string channelGroupUserStateKey = channelGroupUserStateKeys[keyIndex]; + object channelGroupUserStateValue = channelGroupUserStateDictionary[channelGroupUserStateKey]; + if (channelGroupUserStateValue == null) { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelGroupUserStateKey, string.Format(CultureInfo.InvariantCulture, "\"{0}\"", "null")); + } else if (channelGroupUserStateValue.GetType().ToString() == "System.Boolean") { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelGroupUserStateKey, channelGroupUserStateValue.ToString().ToLowerInvariant()); + } else { + jsonStateBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1}", channelGroupUserStateKey, (channelGroupUserStateValue.GetType().ToString() == "System.String") ? string.Format(CultureInfo.InvariantCulture, "\"{0}\"", channelGroupUserStateValue) : channelGroupUserStateValue); + } + if (keyIndex < channelGroupUserStateKeys.Length - 1) { + jsonStateBuilder.Append(','); + } + } + } + + return jsonStateBuilder.ToString(); + } + + protected string BuildJsonUserState(string[] channels, string[] channelGroups, bool local) + { + string retJsonUserState = ""; + + StringBuilder jsonStateBuilder = new StringBuilder(); + + if (channels != null && channels.Length > 0) { + for (int index = 0; index < channels.Length; index++) { + string currentJsonState = BuildJsonUserState(channels[index], "", local); + if (!string.IsNullOrEmpty(currentJsonState)) { + currentJsonState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", channels[index], currentJsonState); + if (jsonStateBuilder.Length > 0) { + jsonStateBuilder.Append(','); + } + jsonStateBuilder.Append(currentJsonState); + } + } + } + + if (channelGroups != null && channelGroups.Length > 0) { + for (int index = 0; index < channelGroups.Length; index++) { + string currentJsonState = BuildJsonUserState("", channelGroups[index], local); + if (!string.IsNullOrEmpty(currentJsonState)) { + currentJsonState = string.Format(CultureInfo.InvariantCulture, "\"{0}\":{{{1}}}", channelGroups[index], currentJsonState); + if (jsonStateBuilder.Length > 0) { + jsonStateBuilder.Append(','); + } + jsonStateBuilder.Append(currentJsonState); + } + } + } + + if (jsonStateBuilder.Length > 0) { + retJsonUserState = string.Format(CultureInfo.InvariantCulture, "{{{0}}}", jsonStateBuilder); + } + + return retJsonUserState; + } + + private PNStatus GetStatusIfError(RequestState asyncRequestState, string jsonString) + { + PNStatus status = null; + if (string.IsNullOrEmpty(jsonString)) { return status; } + + PNConfiguration currentConfig; + PNOperationType type = PNOperationType.None; + if (asyncRequestState != null) { + type = asyncRequestState.ResponseType; + } + if (jsonLibrary.IsDictionaryCompatible(jsonString, type)) { + Dictionary deserializeStatus = jsonLibrary.DeserializeToDictionaryOfObject(jsonString); + int statusCode = 0; //default. assuming all is ok + if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("error") && string.Equals(deserializeStatus["error"].ToString(), "true", StringComparison.OrdinalIgnoreCase)) { + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, PNStatusCategory.PNUnknownCategory, asyncRequestState, Constants.ResourceNotFoundStatusCode, new PNException(jsonString)); + } else if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("error") && deserializeStatus.ContainsKey("status") && Int32.TryParse(deserializeStatus["status"].ToString(), out statusCode) && statusCode > 0) { + string errorMessageJson = deserializeStatus["error"].ToString(); + Dictionary errorDic = jsonLibrary.DeserializeToDictionaryOfObject(errorMessageJson); + if (errorDic != null && errorDic.Count > 0 && errorDic.ContainsKey("message") + && statusCode != 200) { + string statusMessage = errorDic["message"].ToString(); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); + } else if (statusCode != 200) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, errorMessageJson); + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); + } + } else if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("status") && string.Equals(deserializeStatus["status"].ToString(), "error", StringComparison.OrdinalIgnoreCase) && deserializeStatus.ContainsKey("error")) { + string errorMessageJson = deserializeStatus["error"].ToString(); + Dictionary errorDic = jsonLibrary.DeserializeToDictionaryOfObject(errorMessageJson); + if (errorDic != null && errorDic.Count > 0 && errorDic.ContainsKey("code") && errorDic.ContainsKey("message")) { + statusCode = PNStatusCodeHelper.GetHttpStatusCode(errorDic["code"].ToString()); + string statusMessage = errorDic["message"].ToString(); + if (statusCode != 200) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); + } + } + } else if (deserializeStatus.ContainsKey("status") && deserializeStatus.ContainsKey("message")) { + var _ = Int32.TryParse(deserializeStatus["status"].ToString(), out statusCode); + string statusMessage = deserializeStatus["message"].ToString(); + + if (statusCode != 200) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, statusMessage); + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); + } + } else if (deserializeStatus.ContainsKey("message") && statusCode != 200) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, deserializeStatus["message"].ToString()); + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, category, asyncRequestState, statusCode, new PNException(jsonString)); + } + + } else if (jsonString.ToLowerInvariant().TrimStart().IndexOf("(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, Constants.ResourceNotFoundStatusCode, new PNException(jsonString)); + } else if (jsonString.ToLowerInvariant().TrimStart().IndexOf("(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, Constants.ResourceNotFoundStatusCode, new PNException(jsonString)); + } else if (!NewtonsoftJsonDotNet.JsonFastCheck(jsonString)) { + status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, Constants.ResourceNotFoundStatusCode, new PNException(jsonString)); + } + + return status; + } + + internal bool Disconnect() + { + return true; + } + + private bool disposedValue; + + protected virtual void DisposeInternal(bool disposing) + { + if (!disposedValue) { + if (SubscribeHeartbeatCheckTimer != null) { + SubscribeHeartbeatCheckTimer.Dispose(); + } + + disposedValue = true; + } + } + + void IDisposable.Dispose() + { + DisposeInternal(true); + } + + private RequestParameter CreateSubscribeRequestParameter(string[] channels, string[] channelGroups, long timetoken, int region, string stateJsonValue, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam) + { + string channelsSegment = (channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; + List pathSegments = new List + { + "v2", + "subscribe", + config.SubscribeKey, + channelsSegment, + "0" + }; + + Dictionary internalInitialSubscribeUrlParams = new Dictionary(); + if (initialSubscribeUrlParams != null) { + internalInitialSubscribeUrlParams = initialSubscribeUrlParams; + } + + Dictionary requestQueryStringParams = new Dictionary(internalInitialSubscribeUrlParams); + + if (!requestQueryStringParams.ContainsKey("filter-expr") && !string.IsNullOrEmpty(config.FilterExpression)) { + requestQueryStringParams.Add("filter-expr", UriUtil.EncodeUriComponent(config.FilterExpression, PNOperationType.PNSubscribeOperation, false, false, false)); + } + + if (!requestQueryStringParams.ContainsKey("ee")) { + requestQueryStringParams.Add("ee", ""); + } + + if (!requestQueryStringParams.ContainsKey("tt")) { + requestQueryStringParams.Add("tt", timetoken.ToString(CultureInfo.InvariantCulture)); + } + + if (!requestQueryStringParams.ContainsKey("tr") && region > 0) { + requestQueryStringParams.Add("tr", region.ToString(CultureInfo.InvariantCulture)); + } + + if (config.PresenceTimeout != 0) { + requestQueryStringParams.Add("heartbeat", config.PresenceTimeout.ToString(CultureInfo.InvariantCulture)); + } + + if (channelGroups != null && channelGroups.Length > 0 && channelGroups[0] != "") { + requestQueryStringParams.Add("channel-group", UriUtil.EncodeUriComponent(string.Join(",", channelGroups.OrderBy(x => x).ToArray()), PNOperationType.PNSubscribeOperation, false, false, false)); + } + + if (stateJsonValue != "{}" && stateJsonValue != "") { + requestQueryStringParams.Add("state", UriUtil.EncodeUriComponent(stateJsonValue, PNOperationType.PNSubscribeOperation, false, false, false)); + } + + if (externalQueryParam != null && externalQueryParam.Count > 0) { + foreach (KeyValuePair kvp in externalQueryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNSubscribeOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams, + }; + return requestParameter; + } + + private Tuple GetTupleFromException(Exception exception, RequestState pubnubRequestState) + { + string errorMessage = exception.Message; + string exceptionMessage = string.Empty; + if (exception.InnerException != null) exceptionMessage = exception.InnerException.ToString(); + if (exceptionMessage.IndexOf("The request was aborted: The request was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 + && exceptionMessage.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.CurrentCultureIgnoreCase) == -1 + && (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation && exceptionMessage.IndexOf("The operation has timed out", StringComparison.CurrentCultureIgnoreCase) == -1) + && exceptionMessage.IndexOf("A task was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 + && errorMessage.IndexOf("The operation was canceled", StringComparison.CurrentCultureIgnoreCase) == -1) { + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(exception.InnerException); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(pubnubRequestState.ResponseType, category, pubnubRequestState, Constants.ResourceNotFoundStatusCode, new PNException(exception)); + return new Tuple(default, status); + } + return new Tuple(default, null); + } + + } } diff --git a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation.cs index a5c129c0a..400287d51 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/SubscribeOperation.cs @@ -1,24 +1,20 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; -using System.Threading.Tasks; -using System.Net; using System.Globalization; -#if !NET35 && !NET40 using System.Collections.Concurrent; -#endif +using System.Threading.Tasks; + namespace PubnubApi.EndPoint { - public class SubscribeOperation : PubnubCoreBase, ISubscribeOperation + public class SubscribeOperation : PubnubCoreBase, ISubscribeOperation { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private readonly EndPoint.TokenManager pubnubTokenMgr; private List subscribeChannelNames = new List(); @@ -28,13 +24,12 @@ public class SubscribeOperation : PubnubCoreBase, ISubscribeOperation private SubscribeManager manager; private Dictionary queryParam; - public SubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public SubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; pubnubTokenMgr = tokenManager; PubnubInstance = instance; @@ -48,7 +43,7 @@ public SubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary js } if (!ChannelRequest.ContainsKey(instance.InstanceId)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); } if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { @@ -98,6 +93,14 @@ public SubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary js { SubscribeRequestTracker.GetOrAdd(instance.InstanceId, DateTime.Now); } + if (!SubscriptionChannels.ContainsKey(instance.InstanceId)) + { + SubscriptionChannels.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!SubscriptionChannelGroups.ContainsKey(instance.InstanceId)) + { + SubscriptionChannelGroups.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } } @@ -206,23 +209,10 @@ private void Subscribe(string[] channels, string[] channelGroups, Dictionary - { - manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - manager.CurrentPubnubInstance(PubnubInstance); - manager.MultiChannelSubscribeInit(PNOperationType.PNSubscribeOperation, channels, channelGroups, initialSubscribeUrlParams, externalQueryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - manager.CurrentPubnubInstance(PubnubInstance); - manager.MultiChannelSubscribeInit(PNOperationType.PNSubscribeOperation, channels, channelGroups, initialSubscribeUrlParams, externalQueryParam); - }) - { IsBackground = true }.Start(); -#endif + + manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTokenMgr, PubnubInstance); + manager.CurrentPubnubInstance(PubnubInstance); + manager.MultiChannelSubscribeInit(PNOperationType.PNSubscribeOperation, channels??[], channelGroups??[], initialSubscribeUrlParams, externalQueryParam); } internal bool Retry(bool reconnect) diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs index c483698e4..4e46bb0eb 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs @@ -9,19 +9,17 @@ public class UnsubscribeAllEndpoint: UnsubscribeAllOperation private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryManager; private readonly EndPoint.TokenManager pubnubTokenManager; private readonly SubscribeEventEngineFactory subscribeEventEngineFactory; private readonly PresenceEventEngineFactory presenceEventEngineFactory; private readonly string instanceId; - public UnsubscribeAllEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceEventEngineFactory presenceEventEngineFactory ,Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public UnsubscribeAllEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceEventEngineFactory presenceEventEngineFactory ,Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryManager = telemetryManager; pubnubTokenManager = tokenManager; this.subscribeEventEngineFactory = subscribeEventEngineFactory; this.presenceEventEngineFactory = presenceEventEngineFactory; diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs index 6d507649d..6b7d088a3 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs @@ -1,31 +1,24 @@ -using System; -using System.Collections.Generic; -using System.Net; +using System.Collections.Generic; using System.Threading; -using System.Threading.Tasks; -#if !NET35 && !NET40 using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class UnsubscribeAllOperation : PubnubCoreBase + public class UnsubscribeAllOperation : PubnubCoreBase { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private readonly EndPoint.TokenManager pubnubTokenMgr; private Dictionary queryParam; - public UnsubscribeAllOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public UnsubscribeAllOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; pubnubTokenMgr = tokenManager; CurrentPubnubInstance(instance); @@ -40,22 +33,9 @@ public UnsubscribeAllOperation QueryParam(Dictionary customQu private void UnsubscribeAll() { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - SubscribeManager manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - manager.CurrentPubnubInstance(PubnubInstance); - manager.MultiChannelUnSubscribeAll(PNOperationType.PNUnsubscribeOperation, this.queryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - SubscribeManager manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - manager.CurrentPubnubInstance(PubnubInstance); - manager.MultiChannelUnSubscribeAll(PNOperationType.PNUnsubscribeOperation, this.queryParam); - }) - { IsBackground = true }.Start(); -#endif + SubscribeManager manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTokenMgr, PubnubInstance); + manager.CurrentPubnubInstance(PubnubInstance); + manager.MultiChannelUnSubscribeAll(PNOperationType.PNUnsubscribeOperation, this.queryParam); } internal void CurrentPubnubInstance(Pubnub instance) @@ -64,7 +44,7 @@ internal void CurrentPubnubInstance(Pubnub instance) if (!ChannelRequest.ContainsKey(instance.InstanceId)) { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); } if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs index ef2efddb3..d690d668b 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeEndpoint.cs @@ -14,7 +14,6 @@ public class UnsubscribeEndpoint : PubnubCoreBase, IUnsubscribeOperation private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; private readonly EndPoint.TokenManager pubnubTokenMgr; private string[] subscribeChannelNames; @@ -26,14 +25,13 @@ public class UnsubscribeEndpoint : PubnubCoreBase, IUnsubscribeOperation private PresenceEventEngineFactory presenceEventEngineFactory; private string instanceId { get; set; } - public UnsubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceEventEngineFactory presenceEventEngineFactory, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public UnsubscribeEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceEventEngineFactory presenceEventEngineFactory, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { pubnubInstance = instance; config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; pubnubTokenMgr = tokenManager; this.subscribeEventEngineFactory = subscribeEventEngineFactory; this.presenceEventEngineFactory = presenceEventEngineFactory; @@ -94,11 +92,25 @@ private void Unsubscribe(string[] channels, string[] channelGroups) var channelsToRemove = FindUniqueCommonElements(subscribeEventEngine.Channels, channels.ToList()); var channelGroupsToRemove = FindUniqueCommonElements(subscribeEventEngine.ChannelGroups, channelGroups.ToList()); - subscribeEventEngine.Unsubscribe(channelsToRemove.ToArray(), channelGroupsToRemove.ToArray()); + var toRemove = channelsToRemove as string[] ?? channelsToRemove.ToArray(); + var channelNames = toRemove.ToList(); + foreach (var c in channelNames.ToList()) + { + if(!c.EndsWith(Constants.Pnpres)) channelNames.Add($"{c}{Constants.Pnpres}"); + } + + string[] groupsToRemove = channelGroupsToRemove as string[] ?? channelGroupsToRemove.ToArray(); + var channelGroupNames = groupsToRemove.ToList(); + foreach (var cg in channelGroupNames.ToList()) + { + if(!cg.EndsWith(Constants.Pnpres)) channelGroupNames.Add($"{cg}{Constants.Pnpres}"); + } + + subscribeEventEngine.Unsubscribe(channelNames.ToArray(), channelGroupNames.ToArray()); if (config.PresenceInterval > 0 && presenceEventEngineFactory.HasEventEngine(instanceId)) { PresenceEventEngine presenceEventEngine = presenceEventEngineFactory.GetEventEngine(instanceId); - presenceEventEngine.EventQueue.Enqueue(new EventEngine.Presence.Events.LeftEvent() { Input = new EventEngine.Presence.Common.PresenceInput() { Channels = channelsToRemove.ToArray(), ChannelGroups = channelGroupsToRemove.ToArray() } }); + presenceEventEngine.EventQueue.Enqueue(new EventEngine.Presence.Events.LeftEvent() { Input = new EventEngine.Presence.Common.PresenceInput() { Channels = toRemove.ToArray(), ChannelGroups = groupsToRemove.ToArray() } }); } if (config.MaintainPresenceState) { if (ChannelLocalUserState.TryGetValue(PubnubInstance.InstanceId, out diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs index 1bbc9990a..55ed02d9a 100644 --- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs +++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeOperation.cs @@ -2,36 +2,28 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Net; -using System.Threading; -using System.Threading.Tasks; using PubnubApi.Interface; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class UnsubscribeOperation : PubnubCoreBase, IUnsubscribeOperation + public class UnsubscribeOperation : PubnubCoreBase, IUnsubscribeOperation { private readonly PNConfiguration config; private readonly IJsonPluggableLibrary jsonLibrary; private readonly IPubnubUnitTest unit; private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - private readonly EndPoint.TokenManager pubnubTokenMgr; + private readonly TokenManager pubnubTokenMgr; private string[] subscribeChannelNames; private string[] subscribeChannelGroupNames; private Dictionary queryParam; - public UnsubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) + public UnsubscribeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) { config = pubnubConfig; jsonLibrary = jsonPluggableLibrary; unit = pubnubUnit; pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; pubnubTokenMgr = tokenManager; } @@ -55,7 +47,7 @@ public IUnsubscribeOperation QueryParam(Dictionary customQuer public void Execute() { - Unsubscribe(subscribeChannelNames, subscribeChannelGroupNames); + Unsubscribe(subscribeChannelNames, subscribeChannelGroupNames); } private void Unsubscribe(string[] channels, string[] channelGroups) @@ -69,49 +61,15 @@ private void Unsubscribe(string[] channels, string[] channelGroups) string channelGroup = (channelGroups != null) ? string.Join(",", channelGroups.OrderBy(x => x).ToArray()) : ""; LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, requested unsubscribe for channel(s)={1}, cg(s)={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), channel, channelGroup), config.LogVerbosity); - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - SubscribeManager manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - manager.CurrentPubnubInstance(PubnubInstance); - manager.MultiChannelUnSubscribeInit(PNOperationType.PNUnsubscribeOperation, channel, channelGroup, this.queryParam); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - SubscribeManager manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, pubnubTokenMgr, PubnubInstance); - manager.CurrentPubnubInstance(PubnubInstance); - manager.MultiChannelUnSubscribeInit(PNOperationType.PNUnsubscribeOperation, channel, channelGroup, this.queryParam); - }) - { IsBackground = true }.Start(); -#endif + + SubscribeManager manager = new SubscribeManager(config, jsonLibrary, unit, pubnubLog, pubnubTokenMgr, PubnubInstance); + manager.CurrentPubnubInstance(PubnubInstance); + manager.MultiChannelUnSubscribeInit(PNOperationType.PNUnsubscribeOperation, channel, channelGroup, this.queryParam); } internal void CurrentPubnubInstance(Pubnub instance) { PubnubInstance = instance; - - if (!MultiChannelSubscribe.ContainsKey(instance.InstanceId)) - { - MultiChannelSubscribe.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!MultiChannelGroupSubscribe.ContainsKey(instance.InstanceId)) - { - MultiChannelGroupSubscribe.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } } } } diff --git a/src/Api/PubnubApi/EndPoint/Push/AddPushChannelOperation.cs b/src/Api/PubnubApi/EndPoint/Push/AddPushChannelOperation.cs index 3c3f2a2c8..c78bda761 100644 --- a/src/Api/PubnubApi/EndPoint/Push/AddPushChannelOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Push/AddPushChannelOperation.cs @@ -3,230 +3,241 @@ using System.Linq; using System.Net; using System.Threading.Tasks; -using System.Threading; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class AddPushChannelOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNPushType pubnubPushType; - private string[] channelNames; - private string deviceTokenId = ""; - private PushEnvironment pushEnvironment = PushEnvironment.Development; - private string deviceTopic = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public AddPushChannelOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - public AddPushChannelOperation PushType(PNPushType pushType) - { - this.pubnubPushType = pushType; - return this; - } - - public AddPushChannelOperation DeviceId(string deviceId) - { - this.deviceTokenId = deviceId; - return this; - } - - public AddPushChannelOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - /// - /// Applies to APNS2 Only. Default = Development - /// - /// - /// - public AddPushChannelOperation Environment(PushEnvironment environment) - { - this.pushEnvironment = environment; - return this; - } - - /// - /// Applies to APNS2 Only - /// - /// - /// - public AddPushChannelOperation Topic(string deviceTopic) - { - this.deviceTopic = deviceTopic; - return this; - } - - public AddPushChannelOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void RegisterDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) - { - if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) - { - throw new ArgumentException("Missing Channel"); - } - - if (pushToken == null) - { - throw new ArgumentException("Missing deviceId"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - - string channel = string.Join(",", channels.OrderBy(x => x).ToArray()); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildRegisterDevicePushRequest("GET", "", channel, pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { channel }; - requestState.ResponseType = PNOperationType.PushRegister; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> RegisterDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) - { - throw new ArgumentException("Missing Channel"); - } - - if (pushToken == null) - { - throw new ArgumentException("Missing deviceId"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - PNResult ret = new PNResult(); - - string channel = string.Join(",", channels.OrderBy(x => x).ToArray()); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildRegisterDevicePushRequest("GET", "", channel, pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PushRegister; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPushAddChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class AddPushChannelOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNPushType pubnubPushType; + private string[] channelNames; + private string deviceTokenId = ""; + private PushEnvironment pushEnvironment = PushEnvironment.Development; + private string deviceTopic = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public AddPushChannelOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + } + + public AddPushChannelOperation PushType(PNPushType pushType) + { + this.pubnubPushType = pushType; + return this; + } + + public AddPushChannelOperation DeviceId(string deviceId) + { + this.deviceTokenId = deviceId; + return this; + } + + public AddPushChannelOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + /// + /// Applies to APNS2 Only. Default = Development + /// + /// + /// + public AddPushChannelOperation Environment(PushEnvironment environment) + { + this.pushEnvironment = environment; + return this; + } + + /// + /// Applies to APNS2 Only + /// + /// + /// + public AddPushChannelOperation Topic(string deviceTopic) + { + this.deviceTopic = deviceTopic; + return this; + } + + public AddPushChannelOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RegisterDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); + } + + internal void RegisterDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) + { + if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) { + throw new ArgumentException("Missing Channel"); + } + + if (pushToken == null) { + throw new ArgumentException("Missing deviceId"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + string channel = string.Join(",", channels.OrderBy(x => x).ToArray()); + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PushRegister; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushRegister); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushRegister, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNPushAddChannelResult), status); + } + }); + } + + internal async Task> RegisterDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) + { + if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) { + throw new ArgumentException("Missing Channel"); + } + + if (pushToken == null) { + throw new ArgumentException("Missing deviceId"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + string channel = string.Join(",", channels.OrderBy(x => x).ToArray()); + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PushRegister; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushRegister); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPushAddChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushRegister, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = pubnubPushType == PNPushType.APNS2 ? new List() { + "v2", + "push", + "sub-key", + config.SubscribeKey, + "devices-apns2", + deviceTokenId + } : new List() { + "v1", + "push", + "sub-key", + config.SubscribeKey, + "devices", + deviceTokenId + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (pubnubPushType == PNPushType.APNS2) { + requestQueryStringParams.Add("environment", pushEnvironment.ToString().ToLowerInvariant()); + requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, PNOperationType.PushRegister, false, false, false)); + } else { + requestQueryStringParams.Add("type", pubnubPushType.ToString().ToLowerInvariant()); + } + requestQueryStringParams.Add("add", UriUtil.EncodeUriComponent(string.Join(",", channelNames.OrderBy(x => x).ToArray()), PNOperationType.PushRegister, false, false, false)); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PushRegister, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Push/AuditPushChannelOperation.cs b/src/Api/PubnubApi/EndPoint/Push/AuditPushChannelOperation.cs index 4b23a95cf..ed06838eb 100644 --- a/src/Api/PubnubApi/EndPoint/Push/AuditPushChannelOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Push/AuditPushChannelOperation.cs @@ -1,211 +1,228 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class AuditPushChannelOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNPushType pubnubPushType; - private string deviceTokenId = ""; - private PushEnvironment pushEnvironment = PushEnvironment.Development; - private string deviceTopic = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public AuditPushChannelOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public AuditPushChannelOperation PushType(PNPushType pushType) - { - this.pubnubPushType = pushType; - return this; - } - - public AuditPushChannelOperation DeviceId(string deviceId) - { - this.deviceTokenId = deviceId; - return this; - } - - /// - /// Applies to APNS2 Only. Default = Development - /// - /// - /// - public AuditPushChannelOperation Environment(PushEnvironment environment) - { - this.pushEnvironment = environment; - return this; - } - - /// - /// Applies to APNS2 Only - /// - /// - /// - public AuditPushChannelOperation Topic(string deviceTopic) - { - this.deviceTopic = deviceTopic; - return this; - } - - public AuditPushChannelOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void GetChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) - { - if (pushToken == null) - { - throw new ArgumentException("Missing Uri"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetChannelsPushRequest("GET", "", pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PushGet; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> GetChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - if (pushToken == null) - { - throw new ArgumentException("Missing Uri"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetChannelsPushRequest("GET", "", pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PushGet; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPushListProvisionsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class AuditPushChannelOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNPushType pubnubPushType; + private string deviceTokenId = string.Empty; + private PushEnvironment pushEnvironment = PushEnvironment.Development; + private string deviceTopic = string.Empty; + private PNCallback savedCallback; + private Dictionary queryParam; + + public AuditPushChannelOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public AuditPushChannelOperation PushType(PNPushType pushType) + { + this.pubnubPushType = pushType; + return this; + } + + public AuditPushChannelOperation DeviceId(string deviceId) + { + this.deviceTokenId = deviceId; + return this; + } + + /// + /// Applies to APNS2 Only. Default = Development + /// + /// + /// + public AuditPushChannelOperation Environment(PushEnvironment environment) + { + this.pushEnvironment = environment; + return this; + } + + /// + /// Applies to APNS2 Only + /// + /// + /// + public AuditPushChannelOperation Topic(string deviceTopic) + { + this.deviceTopic = deviceTopic; + return this; + } + + public AuditPushChannelOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + GetChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); + } + + internal void GetChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) + { + if (pushToken == null) { + throw new ArgumentException("Missing Uri"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PushGet; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushGet); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushGet, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNPushListProvisionsResult), status); + } + }); + } + + internal async Task> GetChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) + { + if (pushToken == null) { + throw new ArgumentException("Missing Uri"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PushGet; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + PNResult returnValue = new PNResult(); + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushGet); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPushListProvisionsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushGet, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = pubnubPushType == PNPushType.APNS2 ? new List + { + "v2", + "push", + "sub-key", + config.SubscribeKey, + "devices-apns2", + deviceTokenId + } : new List + { + "v1", + "push", + "sub-key", + config.SubscribeKey, + "devices", + deviceTokenId + }; + + + + Dictionary requestQueryStringParams = new Dictionary(); + + if (pubnubPushType == PNPushType.APNS2) { + requestQueryStringParams.Add("environment", pushEnvironment.ToString().ToLowerInvariant()); + requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, PNOperationType.PushGet, false, false, false)); + } else { + requestQueryStringParams.Add("type", pubnubPushType.ToString().ToLowerInvariant()); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PushGet, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Push/RemoveAllPushChannelsOperation.cs b/src/Api/PubnubApi/EndPoint/Push/RemoveAllPushChannelsOperation.cs index dd90ab6ee..e0983981b 100644 --- a/src/Api/PubnubApi/EndPoint/Push/RemoveAllPushChannelsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Push/RemoveAllPushChannelsOperation.cs @@ -1,211 +1,226 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; -using System.Threading; -using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif +using System.Text; namespace PubnubApi.EndPoint { - public class RemoveAllPushChannelsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNPushType pubnubPushType; - private string deviceTokenId = ""; - private PushEnvironment pushEnvironment = PushEnvironment.Development; - private string deviceTopic = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemoveAllPushChannelsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public RemoveAllPushChannelsOperation PushType(PNPushType pushType) - { - this.pubnubPushType = pushType; - return this; - } - - public RemoveAllPushChannelsOperation DeviceId(string deviceId) - { - this.deviceTokenId = deviceId; - return this; - } - - /// - /// Applies to APNS2 Only. Default = Development - /// - /// - /// - public RemoveAllPushChannelsOperation Environment(PushEnvironment environment) - { - this.pushEnvironment = environment; - return this; - } - - /// - /// Applies to APNS2 Only - /// - /// - /// - public RemoveAllPushChannelsOperation Topic(string deviceTopic) - { - this.deviceTopic = deviceTopic; - return this; - } - - public RemoveAllPushChannelsOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void RemoveAllChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) - { - if (pushToken == null) - { - throw new ArgumentException("Missing deviceId"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildUnregisterDevicePushRequest("GET", "", pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PushUnregister; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> RemoveAllChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - if (pushToken == null) - { - throw new ArgumentException("Missing deviceId"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildUnregisterDevicePushRequest("GET", "", pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PushUnregister; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPushRemoveAllChannelsResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class RemoveAllPushChannelsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNPushType pubnubPushType; + private string deviceTokenId = string.Empty; + private PushEnvironment pushEnvironment = PushEnvironment.Development; + private string deviceTopic = string.Empty; + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemoveAllPushChannelsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public RemoveAllPushChannelsOperation PushType(PNPushType pushType) + { + this.pubnubPushType = pushType; + return this; + } + + public RemoveAllPushChannelsOperation DeviceId(string deviceId) + { + this.deviceTokenId = deviceId; + return this; + } + + /// + /// Applies to APNS2 Only. Default = Development + /// + /// + /// + public RemoveAllPushChannelsOperation Environment(PushEnvironment environment) + { + this.pushEnvironment = environment; + return this; + } + + /// + /// Applies to APNS2 Only + /// + /// + /// + public RemoveAllPushChannelsOperation Topic(string deviceTopic) + { + this.deviceTopic = deviceTopic; + return this; + } + + public RemoveAllPushChannelsOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RemoveAllChannelsForDevice(this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); + } + + internal void RemoveAllChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) + { + if (pushToken == null) { + throw new ArgumentException("Missing deviceId"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PushUnregister; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushUnregister); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushUnregister, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + internal async Task> RemoveAllChannelsForDevice(PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) + { + if (pushToken == null) { + throw new ArgumentException("Missing deviceId"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PushUnregister; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + Tuple JsonAndStatusTuple; + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushUnregister); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPushRemoveAllChannelsResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushUnregister, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = pubnubPushType == PNPushType.APNS2 ? new List + { + "v2", + "push", + "sub-key", + config.SubscribeKey, + "devices-apns2", + deviceTokenId, + "remove" + } : new List + { + "v1", + "push", + "sub-key", + config.SubscribeKey, + "devices", + deviceTokenId, + "remove" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (pubnubPushType == PNPushType.APNS2) { + requestQueryStringParams.Add("environment", pushEnvironment.ToString().ToLowerInvariant()); + requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, PNOperationType.PushUnregister, false, false, false)); + } else { + requestQueryStringParams.Add("type", pubnubPushType.ToString().ToLowerInvariant()); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PushUnregister, false, false, false)); + } + } + } + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Push/RemovePushChannelOperation.cs b/src/Api/PubnubApi/EndPoint/Push/RemovePushChannelOperation.cs index a95e65653..6b28dc3d7 100644 --- a/src/Api/PubnubApi/EndPoint/Push/RemovePushChannelOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Push/RemovePushChannelOperation.cs @@ -2,231 +2,254 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Text; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class RemovePushChannelOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private PNPushType pubnubPushType; - private string[] channelNames; - private string deviceTokenId = ""; - private PushEnvironment pushEnvironment = PushEnvironment.Development; - private string deviceTopic = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public RemovePushChannelOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - - public RemovePushChannelOperation PushType(PNPushType pushType) - { - this.pubnubPushType = pushType; - return this; - } - - public RemovePushChannelOperation DeviceId(string deviceId) - { - this.deviceTokenId = deviceId; - return this; - } - - public RemovePushChannelOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - /// - /// Applies to APNS2 Only. Default = Development - /// - /// - /// - public RemovePushChannelOperation Environment(PushEnvironment environment) - { - this.pushEnvironment = environment; - return this; - } - - /// - /// Applies to APNS2 Only - /// - /// - /// - public RemovePushChannelOperation Topic(string deviceTopic) - { - this.deviceTopic = deviceTopic; - return this; - } - - public RemovePushChannelOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void RemoveChannelForDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) - { - if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) - { - throw new ArgumentException("Missing Channel"); - } - - if (pushToken == null) - { - throw new ArgumentException("Missing deviceId"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - - string channel = string.Join(",", channels.OrderBy(x => x).ToArray()); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildRemoveChannelPushRequest("GET", "", channel, pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { channel }; - requestState.ResponseType = PNOperationType.PushRemove; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> RemoveChannelForDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) - { - if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) - { - throw new ArgumentException("Missing Channel"); - } - - if (pushToken == null) - { - throw new ArgumentException("Missing deviceId"); - } - - if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) - { - throw new ArgumentException("Missing Topic"); - } - PNResult ret = new PNResult(); - - string channel = string.Join(",", channels.OrderBy(x => x).ToArray()); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildRemoveChannelPushRequest("GET", "", channel, pushType, pushToken, environment, deviceTopic, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PushRemove; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNPushRemoveChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class RemovePushChannelOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNPushType pubnubPushType; + private string[] channelNames; + private string deviceTokenId = ""; + private PushEnvironment pushEnvironment = PushEnvironment.Development; + private string deviceTopic = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public RemovePushChannelOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + public RemovePushChannelOperation PushType(PNPushType pushType) + { + this.pubnubPushType = pushType; + return this; + } + + public RemovePushChannelOperation DeviceId(string deviceId) + { + this.deviceTokenId = deviceId; + return this; + } + + public RemovePushChannelOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + /// + /// Applies to APNS2 Only. Default = Development + /// + /// + /// + public RemovePushChannelOperation Environment(PushEnvironment environment) + { + this.pushEnvironment = environment; + return this; + } + + /// + /// Applies to APNS2 Only + /// + /// + /// + public RemovePushChannelOperation Topic(string deviceTopic) + { + this.deviceTopic = deviceTopic; + return this; + } + + public RemovePushChannelOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + RemoveChannelForDevice(this.channelNames, this.pubnubPushType, this.deviceTokenId, this.pushEnvironment, this.deviceTopic, this.queryParam, savedCallback); + } + + internal void RemoveChannelForDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam, PNCallback callback) + { + if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) { + throw new ArgumentException("Missing Channel"); + } + + if (pushToken == null) { + throw new ArgumentException("Missing deviceId"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + RequestState requestState = new RequestState(); + requestState.Channels = channels.Select(c => c).ToArray(); + requestState.ResponseType = PNOperationType.PushRemove; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushRemove); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushRemove, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNPushRemoveChannelResult), status); + } + }); + } + + internal async Task> RemoveChannelForDevice(string[] channels, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam) + { + if (channels == null || channels.Length == 0 || channels[0] == null || channels[0].Trim().Length == 0) { + throw new ArgumentException("Missing Channel"); + } + + if (pushToken == null) { + throw new ArgumentException("Missing deviceId"); + } + + if (pushType == PNPushType.APNS2 && string.IsNullOrEmpty(deviceTopic)) { + throw new ArgumentException("Missing Topic"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = channels.Select(c => c).ToArray(); + requestState.ResponseType = PNOperationType.PushRemove; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PushRemove); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNPushRemoveChannelResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PushRemove, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = pubnubPushType == PNPushType.APNS2 ? new List + { + "v2", + "push", + "sub-key", + config.SubscribeKey, + "devices-apns2", + deviceTokenId + } : new List + { + "v1", + "push", + "sub-key", + config.SubscribeKey, + "devices", + deviceTokenId + }; + + + Dictionary requestQueryStringParams = new Dictionary(); + if (pubnubPushType == PNPushType.APNS2) { + requestQueryStringParams.Add("environment", pushEnvironment.ToString().ToLowerInvariant()); + requestQueryStringParams.Add("topic", UriUtil.EncodeUriComponent(deviceTopic, PNOperationType.PushRemove, false, false, false)); + } else { + requestQueryStringParams.Add("type", pubnubPushType.ToString().ToLowerInvariant()); + } + + requestQueryStringParams.Add("remove", UriUtil.EncodeUriComponent(string.Join(",", channelNames.OrderBy(x => x).ToArray()), PNOperationType.PushRemove, false, false, false)); + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PushRemove, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/StoragePlayback/DeleteMessageOperation.cs b/src/Api/PubnubApi/EndPoint/StoragePlayback/DeleteMessageOperation.cs index 411892f2f..6b2fca0d6 100644 --- a/src/Api/PubnubApi/EndPoint/StoragePlayback/DeleteMessageOperation.cs +++ b/src/Api/PubnubApi/EndPoint/StoragePlayback/DeleteMessageOperation.cs @@ -1,197 +1,213 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class DeleteMessageOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private long startTimetoken = -1; - private long endTimetoken = -1; - - private string channelName = ""; - private PNCallback savedCallback; - private Dictionary queryParam; - - public DeleteMessageOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - - } - - public DeleteMessageOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public DeleteMessageOperation Start(long start) - { - this.startTimetoken = start; - return this; - } - - public DeleteMessageOperation End(long end) - { - this.endTimetoken = end; - return this; - } - - public DeleteMessageOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - - return await DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void DeleteMessage(string channel, long start, long end, Dictionary externalQueryParam, PNCallback callback) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildDeleteMessageRequest("DELETE", "", channel, start, end, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { channel }; - requestState.ResponseType = PNOperationType.PNDeleteMessageOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> DeleteMessage(string channel, long start, long end, Dictionary externalQueryParam) - { - if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildDeleteMessageRequest("DELETE", "", channel, start, end, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNDeleteMessageOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNDeleteMessageResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class DeleteMessageOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private long startTimetoken = -1; + private long endTimetoken = -1; + + private string channelName = ""; + private PNCallback savedCallback; + private Dictionary queryParam; + + public DeleteMessageOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + + } + + public DeleteMessageOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public DeleteMessageOperation Start(long start) + { + this.startTimetoken = start; + return this; + } + + public DeleteMessageOperation End(long end) + { + this.endTimetoken = end; + return this; + } + + public DeleteMessageOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + this.savedCallback = callback; + DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + + return await DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + DeleteMessage(this.channelName, this.startTimetoken, this.endTimetoken, this.queryParam, savedCallback); + } + + internal void DeleteMessage(string channel, long start, long end, Dictionary externalQueryParam, PNCallback callback) + { + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + throw new ArgumentException("Missing Channel"); + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNDeleteMessageOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteMessageOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + if (!string.IsNullOrEmpty(responseString)) { + requestState.GotJsonResponse = true; + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteMessageOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNDeleteMessageResult), status); + } + }); + } + + internal async Task> DeleteMessage(string channel, long start, long end, Dictionary externalQueryParam) + { + if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(channel.Trim())) { + throw new ArgumentException("Missing Channel"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNDeleteMessageOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDeleteMessageOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNDeleteMessageResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDeleteMessageOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List() { + "v3", + "history", + "sub-key", + config.SubscribeKey, + "channel", + channelName + }; + + Dictionary requestQueryStringParams = new Dictionary(); + + if (startTimetoken != -1) { + requestQueryStringParams.Add("start", startTimetoken.ToString(CultureInfo.InvariantCulture)); + } + if (endTimetoken != -1) { + requestQueryStringParams.Add("end", endTimetoken.ToString(CultureInfo.InvariantCulture)); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDeleteMessageOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.DELETE, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs b/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs index 6a7f9c072..4e5ba9a5f 100644 --- a/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs +++ b/src/Api/PubnubApi/EndPoint/StoragePlayback/FetchHistoryOperation.cs @@ -3,254 +3,287 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class FetchHistoryOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private bool reverseOption; - private bool withMetaOption; - private bool withMessageActionsOption; - private bool includeMessageType = true; //default to true - private bool withUuidOption = true; //default to true - private long startTimetoken = -1; - private long endTimetoken = -1; - private int perChannelCount = -1; - private Dictionary queryParam; - - private string[] channelNames; - private PNCallback savedCallback; - - public FetchHistoryOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - - } - - public FetchHistoryOperation Channels(string[] channelNames) - { - this.channelNames = channelNames; - return this; - } - - public FetchHistoryOperation Reverse(bool reverse) - { - this.reverseOption = reverse; - return this; - } - - public FetchHistoryOperation IncludeMeta(bool withMeta) - { - this.withMetaOption = withMeta; - return this; - } - - public FetchHistoryOperation IncludeMessageType(bool withMessageType) - { - includeMessageType = withMessageType; - return this; - } - - public FetchHistoryOperation IncludeUuid(bool withUuid) - { - withUuidOption = withUuid; - return this; - } - - public FetchHistoryOperation IncludeMessageActions(bool withMessageActions) - { - this.withMessageActionsOption = withMessageActions; - return this; - } - - public FetchHistoryOperation Start(long start) - { - this.startTimetoken = start; - return this; - } - - public FetchHistoryOperation End(long end) - { - this.endTimetoken = end; - return this; - } - - public FetchHistoryOperation MaximumPerChannel(int count) - { - this.perChannelCount = count; - return this; - } - - public FetchHistoryOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - - if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0])) - { - throw new MissingMemberException("Missing channel name(s)"); - } - - if (this.withMessageActionsOption && this.channelNames != null && this.channelNames.Length > 1) - { - throw new NotSupportedException("Only one channel can be used along with MessageActions"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - History(callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - History(callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - - if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0])) - { - throw new MissingMemberException("Missing channel name(s)"); - } - - if (this.withMessageActionsOption && this.channelNames != null && this.channelNames.Length > 1) - { - throw new NotSupportedException("Only one channel can be used along with MessageActions"); - } - - return await History().ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - History(savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - History(savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void History(PNCallback callback) - { - if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0]) || string.IsNullOrEmpty(this.channelNames[0].Trim())) - { - throw new ArgumentException("Missing Channel(s)"); - } - string channel = string.Join(",", this.channelNames); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildFetchRequest("GET", "", this.channelNames, this.startTimetoken, this.endTimetoken, this.perChannelCount, this.reverseOption, this.withMetaOption, this.withMessageActionsOption, this.withUuidOption, this.includeMessageType, this.queryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNFetchHistoryOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> History() - { - if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0]) || string.IsNullOrEmpty(this.channelNames[0].Trim())) - { - throw new ArgumentException("Missing Channel(s)"); - } - PNResult ret = new PNResult(); - string channel = string.Join(",", this.channelNames); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildFetchRequest("GET", "", this.channelNames, this.startTimetoken, this.endTimetoken, this.perChannelCount, this.reverseOption, this.withMetaOption, this.withMessageActionsOption, this.withUuidOption, this.includeMessageType, this.queryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { channel }; - requestState.ResponseType = PNOperationType.PNFetchHistoryOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNFetchHistoryResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } - + public class FetchHistoryOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private bool reverseOption; + private bool withMetaOption; + private bool withMessageActionsOption; + private bool includeMessageType = true; //default to true + private bool withUuidOption = true; //default to true + private long startTimetoken = -1; + private long endTimetoken = -1; + private int perChannelCount = -1; + private Dictionary queryParam; + + private string[] channelNames; + private PNCallback savedCallback; + + public FetchHistoryOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + + } + + public FetchHistoryOperation Channels(string[] channelNames) + { + this.channelNames = channelNames; + return this; + } + + public FetchHistoryOperation Reverse(bool reverse) + { + this.reverseOption = reverse; + return this; + } + + public FetchHistoryOperation IncludeMeta(bool withMeta) + { + this.withMetaOption = withMeta; + return this; + } + + public FetchHistoryOperation IncludeMessageType(bool withMessageType) + { + includeMessageType = withMessageType; + return this; + } + + public FetchHistoryOperation IncludeUuid(bool withUuid) + { + withUuidOption = withUuid; + return this; + } + + public FetchHistoryOperation IncludeMessageActions(bool withMessageActions) + { + this.withMessageActionsOption = withMessageActions; + return this; + } + + public FetchHistoryOperation Start(long start) + { + this.startTimetoken = start; + return this; + } + + public FetchHistoryOperation End(long end) + { + this.endTimetoken = end; + return this; + } + + public FetchHistoryOperation MaximumPerChannel(int count) + { + this.perChannelCount = count; + return this; + } + + public FetchHistoryOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + + if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0])) { + throw new MissingMemberException("Missing channel name(s)"); + } + + if (this.withMessageActionsOption && this.channelNames != null && this.channelNames.Length > 1) { + throw new NotSupportedException("Only one channel can be used along with MessageActions"); + } + this.savedCallback = callback; + History(callback); + } + + public async Task> ExecuteAsync() + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + + if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0])) { + throw new MissingMemberException("Missing channel name(s)"); + } + + if (this.withMessageActionsOption && this.channelNames != null && this.channelNames.Length > 1) { + throw new NotSupportedException("Only one channel can be used along with MessageActions"); + } + + return await History(); + } + + internal void Retry() + { + History(savedCallback); + } + + internal void History(PNCallback callback) + { + if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0]) || string.IsNullOrEmpty(this.channelNames[0].Trim())) { + throw new ArgumentException("Missing Channel(s)"); + } + string channel = string.Join(",", this.channelNames); + + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNFetchHistoryOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNFetchHistoryOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFetchHistoryOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + internal async Task> History() + { + if (this.channelNames == null || this.channelNames.Length == 0 || string.IsNullOrEmpty(this.channelNames[0]) || string.IsNullOrEmpty(this.channelNames[0].Trim())) { + throw new ArgumentException("Missing Channel(s)"); + } + PNResult returnValue = new PNResult(); + string channel = string.Join(",", this.channelNames); + RequestState requestState = new RequestState(); + requestState.Channels = new[] { channel }; + requestState.ResponseType = PNOperationType.PNFetchHistoryOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNFetchHistoryOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNFetchHistoryResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFetchHistoryOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { + string channelsString = (channelNames != null && channelNames.Length > 0) ? string.Join(",", channelNames.OrderBy(x => x).ToArray()) : ""; + + List pathSegments = new List() { + "v3", + withMessageActionsOption ? "history-with-actions" : "history", + "sub-key", + config.SubscribeKey, + "channel", + channelsString + }; + + Dictionary requestQueryStringParams = new Dictionary + { + { "max", (this.perChannelCount <= -1) ? (withMessageActionsOption || (channelNames != null && channelNames.Length > 1) ? "25" : "100") : perChannelCount.ToString(CultureInfo.InvariantCulture) } + }; + if (reverseOption) { + requestQueryStringParams.Add("reverse", "true"); + } + if (startTimetoken != -1) { + requestQueryStringParams.Add("start", startTimetoken.ToString(CultureInfo.InvariantCulture)); + } + if (endTimetoken != -1) { + requestQueryStringParams.Add("end", endTimetoken.ToString(CultureInfo.InvariantCulture)); + } + + if (withMetaOption) { + requestQueryStringParams.Add("include_meta", "true"); + } + + if (withUuidOption) { + requestQueryStringParams.Add("include_uuid", "true"); + } + + if (includeMessageType) { + requestQueryStringParams.Add("include_message_type", "true"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNFetchHistoryOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/StoragePlayback/HistoryOperation.cs b/src/Api/PubnubApi/EndPoint/StoragePlayback/HistoryOperation.cs index 871d56f71..9c083aa04 100644 --- a/src/Api/PubnubApi/EndPoint/StoragePlayback/HistoryOperation.cs +++ b/src/Api/PubnubApi/EndPoint/StoragePlayback/HistoryOperation.cs @@ -1,226 +1,256 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; using System.Net; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class HistoryOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private bool reverseOption; - private bool includeTimetokenOption; - private bool withMetaOption; - private long startTimetoken = -1; - private long endTimetoken = -1; - private int historyCount = -1; - private Dictionary queryParam; - - private string channelName = ""; - private PNCallback savedCallback; - - public HistoryOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - - } - - public HistoryOperation Channel(string channel) - { - channelName = channel; - return this; - } - - public HistoryOperation Reverse(bool reverse) - { - reverseOption = reverse; - return this; - } - - public HistoryOperation IncludeTimetoken(bool includeTimetoken) - { - includeTimetokenOption = includeTimetoken; - return this; - } - - public HistoryOperation IncludeMeta(bool withMeta) - { - withMetaOption = withMeta; - return this; - } - - public HistoryOperation Start(long start) - { - startTimetoken = start; - return this; - } - - public HistoryOperation End(long end) - { - endTimetoken = end; - return this; - } - - public HistoryOperation Count(int count) - { - historyCount = count; - return this; - } - - public HistoryOperation QueryParam(Dictionary customQueryParam) - { - queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - History(callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - History(callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - - return await History().ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - History(savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - History(savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void History(PNCallback callback) - { - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildHistoryRequest("GET", "", this.channelName, this.startTimetoken, this.endTimetoken, this.historyCount, this.reverseOption, this.includeTimetokenOption, this.withMetaOption, this.queryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new [] { this.channelName }; - requestState.ResponseType = PNOperationType.PNHistoryOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> History() - { - if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) - { - throw new ArgumentException("Missing Channel"); - } - - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildHistoryRequest("GET", "", this.channelName, this.startTimetoken, this.endTimetoken, this.historyCount, this.reverseOption, this.includeTimetokenOption, this.withMetaOption, this.queryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = new[] { this.channelName }; - requestState.ResponseType = PNOperationType.PNHistoryOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNHistoryResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - } + public class HistoryOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private bool reverseOption; + private bool includeTimetokenOption; + private bool withMetaOption; + private long startTimetoken = -1; + private long endTimetoken = -1; + private int historyCount = -1; + private Dictionary queryParam; + + private string channelName = ""; + private PNCallback savedCallback; + + public HistoryOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + + } + + public HistoryOperation Channel(string channel) + { + channelName = channel; + return this; + } + + public HistoryOperation Reverse(bool reverse) + { + reverseOption = reverse; + return this; + } + + public HistoryOperation IncludeTimetoken(bool includeTimetoken) + { + includeTimetokenOption = includeTimetoken; + return this; + } + + public HistoryOperation IncludeMeta(bool withMeta) + { + withMetaOption = withMeta; + return this; + } + + public HistoryOperation Start(long start) + { + startTimetoken = start; + return this; + } + + public HistoryOperation End(long end) + { + endTimetoken = end; + return this; + } + + public HistoryOperation Count(int count) + { + historyCount = count; + return this; + } + + public HistoryOperation QueryParam(Dictionary customQueryParam) + { + queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + this.savedCallback = callback; + History(callback); + } + + public async Task> ExecuteAsync() + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + + return await History().ConfigureAwait(false); + } + + internal void Retry() + { + History(savedCallback); + } + + internal void History(PNCallback callback) + { + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) { + throw new ArgumentException("Missing Channel"); + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { this.channelName }; + requestState.ResponseType = PNOperationType.PNHistoryOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParemeter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNHistoryOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNHistoryOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNHistoryResult), status); + } + }); + } + + internal async Task> History() + { + if (string.IsNullOrEmpty(this.channelName) || string.IsNullOrEmpty(this.channelName.Trim())) { + throw new ArgumentException("Missing Channel"); + } + RequestState requestState = new RequestState(); + requestState.Channels = new[] { this.channelName }; + requestState.ResponseType = PNOperationType.PNHistoryOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + PNResult returnValue = new PNResult(); + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParemeter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNHistoryOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNHistoryResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNHistoryOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParemeter() + { + List pathSegments = new List() + { + "v2", + "history", + "sub-key", + config.SubscribeKey, + "channel", + channelName + }; + + Dictionary requestQueryStringParams = new Dictionary + { + { "count", (historyCount <= -1) ? "100" : historyCount.ToString(CultureInfo.InvariantCulture) } + }; + + if (reverseOption) { + requestQueryStringParams.Add("reverse", "true"); + } + if (startTimetoken != -1) { + requestQueryStringParams.Add("start", startTimetoken.ToString(CultureInfo.InvariantCulture)); + } + if (endTimetoken != -1) { + requestQueryStringParams.Add("end", endTimetoken.ToString(CultureInfo.InvariantCulture)); + } + + if (includeTimetokenOption) { + requestQueryStringParams.Add("include_token", "true"); + } + + if (withMetaOption) { + requestQueryStringParams.Add("include_meta", "true"); + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNHistoryOperation, false, false, false)); + } + } + } + + var requestParemeter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParemeter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/StoragePlayback/MessageCountsOperation.cs b/src/Api/PubnubApi/EndPoint/StoragePlayback/MessageCountsOperation.cs index a765608a3..05ee689a7 100644 --- a/src/Api/PubnubApi/EndPoint/StoragePlayback/MessageCountsOperation.cs +++ b/src/Api/PubnubApi/EndPoint/StoragePlayback/MessageCountsOperation.cs @@ -3,190 +3,216 @@ using System.Linq; using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 +using System.Globalization; +using System.Threading; using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class MessageCountsOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private Dictionary queryParam; - - private string[] channelNames; - private long[] msgCountArrayTimetoken; - private PNCallback savedCallback; - - public MessageCountsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public MessageCountsOperation Channels(string[] channels) - { - this.channelNames = channels; - return this; - } - - public MessageCountsOperation ChannelsTimetoken(long[] timetokens) - { - this.msgCountArrayTimetoken = timetokens; - return this; - } - - public MessageCountsOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - MessageCounts(this.channelNames, this.msgCountArrayTimetoken, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - MessageCounts(this.channelNames, this.msgCountArrayTimetoken, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) - { - throw new MissingMemberException("Invalid Subscribe Key"); - } - - return await MessageCounts(this.channelNames, this.msgCountArrayTimetoken, this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - MessageCounts(this.channelNames, this.msgCountArrayTimetoken, this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - MessageCounts(this.channelNames, this.msgCountArrayTimetoken, this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void MessageCounts(string[] channels, long[] timetokens, Dictionary externalQueryParam, PNCallback callback) - { - if (channels == null || channels.Length == 0) - { - throw new ArgumentException("Missing Channel"); - } - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildMessageCountsRequest("GET", "", channels, timetokens, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ResponseType = PNOperationType.PNMessageCountsOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> MessageCounts(string[] channels, long[] timetokens, Dictionary externalQueryParam) - { - if (channels == null || channels.Length == 0) - { - throw new ArgumentException("Missing Channel"); - } - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildMessageCountsRequest("GET", "", channels, timetokens, externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = channels; - requestState.ResponseType = PNOperationType.PNMessageCountsOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNMessageCountResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class MessageCountsOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private Dictionary queryParam; + + private string[] channelNames; + private long[] timetokens; + private PNCallback savedCallback; + + public MessageCountsOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public MessageCountsOperation Channels(string[] channels) + { + this.channelNames = channels; + return this; + } + + public MessageCountsOperation ChannelsTimetoken(long[] timetokens) + { + this.timetokens = timetokens; + return this; + } + + public MessageCountsOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + this.savedCallback = callback; + MessageCounts(this.channelNames, this.timetokens, this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + if (string.IsNullOrEmpty(config.SubscribeKey) || config.SubscribeKey.Trim().Length == 0) { + throw new MissingMemberException("Invalid Subscribe Key"); + } + + return await MessageCounts(this.channelNames, this.timetokens, this.queryParam); + } + + internal void Retry() + { + MessageCounts(this.channelNames, this.timetokens, this.queryParam, savedCallback); + } + + internal void MessageCounts(string[] channels, long[] timetokens, Dictionary externalQueryParam, PNCallback callback) + { + if (channels == null || channels.Length == 0) { + throw new ArgumentException("Missing Channel"); + } + RequestState requestState = new RequestState(); + requestState.Channels = channels; + requestState.ResponseType = PNOperationType.PNMessageCountsOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNMessageCountsOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNMessageCountsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default(PNMessageCountResult), status); + } + }); + } + + internal async Task> MessageCounts(string[] channels, long[] timetokens, Dictionary externalQueryParam) + { + if (channels == null || channels.Length == 0) { + throw new ArgumentException("Missing Channel"); + } + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.Channels = channels; + requestState.ResponseType = PNOperationType.PNMessageCountsOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNMessageCountsOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, (int)HttpStatusCode.OK, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNMessageCountResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNMessageCountsOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + + if (!ChannelRequest.ContainsKey(instance.InstanceId)) { + ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) { + ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); + } + } + + private RequestParameter CreateRequestParameter() + { + string channelString = (channelNames != null && channelNames.Length > 0) ? string.Join(",", channelNames) : ""; + + List pathSegments = new List() { + "v3", + "history", + "sub-key", + config.SubscribeKey, + "message-counts" + }; + + if (!string.IsNullOrEmpty(channelString)) { + pathSegments.Add(UriUtil.EncodeUriComponent(channelString, PNOperationType.PNMessageCountsOperation, true, false, false)); + } + + Dictionary requestQueryStringParams = new Dictionary(); + + if (timetokens != null && timetokens.Length > 0) { + string tt = string.Join(",", timetokens.Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray()); + if (timetokens.Length == 1) { + requestQueryStringParams.Add("timetoken", tt); + } else { + requestQueryStringParams.Add("channelsTimetoken", UriUtil.EncodeUriComponent(tt, PNOperationType.PNMessageCountsOperation, false, false, false)); + } + } + + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNMessageCountsOperation, false, false, false)); + } + } + } + + var queryString = UriUtil.BuildQueryString(requestQueryStringParams); + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/TelemetryManager.cs b/src/Api/PubnubApi/EndPoint/TelemetryManager.cs deleted file mode 100644 index d5d510b16..000000000 --- a/src/Api/PubnubApi/EndPoint/TelemetryManager.cs +++ /dev/null @@ -1,315 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Globalization; -using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif - -namespace PubnubApi.EndPoint -{ - public class TelemetryManager: IDisposable - { - private const int TELEMETRY_TIMER_IN_SEC = 60; - - private PNConfiguration pubnubConfig; - private IPubnubLog pubnubLog; - - private static ConcurrentDictionary> dicEndpointLatency - { - get; - set; - } = new ConcurrentDictionary>(); - - private System.Threading.Timer telemetryTimer { get; set; } - - public TelemetryManager(PNConfiguration config, IPubnubLog log) - { - this.pubnubConfig = config; - this.pubnubLog = log; - if (config != null && config.EnableTelemetry) - { - StartTelemetryTimer(); - } - } - - private void StartTelemetryTimer() - { - StopTelemetryTimer(); - telemetryTimer = new Timer(OnTelemetryIntervalTimeout, null, 0, TELEMETRY_TIMER_IN_SEC * 1000); - } - - private void OnTelemetryIntervalTimeout(System.Object telemetryState) - { - CleanupTelemetryData(); - } - - private void StopTelemetryTimer() - { - try - { - if (telemetryTimer != null) - { - telemetryTimer.Change(Timeout.Infinite, Timeout.Infinite); - telemetryTimer.Dispose(); - } - } - catch { /* Ignore exception caused by dispose */ } - finally { telemetryTimer = null; } - } - - private static string EndpointNameForOperation(PNOperationType type) - { - string endpoint = ""; - switch (type) - { - case PNOperationType.PNPublishOperation: - endpoint = "l_pub"; - break; - case PNOperationType.PNHistoryOperation: - case PNOperationType.PNFetchHistoryOperation: - case PNOperationType.PNFireOperation: - case PNOperationType.PNDeleteMessageOperation: - endpoint = "l_hist"; - break; - case PNOperationType.PNUnsubscribeOperation: - case PNOperationType.PNWhereNowOperation: - case PNOperationType.PNHereNowOperation: - case PNOperationType.PNHeartbeatOperation: - case PNOperationType.PNSetStateOperation: - case PNOperationType.PNGetStateOperation: - endpoint = "l_pres"; - break; - case PNOperationType.PNAddChannelsToGroupOperation: - case PNOperationType.PNRemoveChannelsFromGroupOperation: - case PNOperationType.PNChannelGroupsOperation: - case PNOperationType.PNRemoveGroupOperation: - case PNOperationType.PNChannelsForGroupOperation: - endpoint = "l_cg"; - break; - case PNOperationType.PushGet: - case PNOperationType.PushRegister: - case PNOperationType.PushRemove: - case PNOperationType.PushUnregister: - endpoint = "l_push"; - break; - case PNOperationType.PNAccessManagerGrantToken: - case PNOperationType.PNAccessManagerRevokeToken: - endpoint = "l_pamv3"; - break; - case PNOperationType.PNAccessManagerAudit: - case PNOperationType.PNAccessManagerGrant: - endpoint = "l_pam"; - break; - case PNOperationType.PNTimeOperation: - endpoint = "l_time"; - break; - case PNOperationType.PNMessageCountsOperation: - endpoint = "l_mc"; - break; - case PNOperationType.PNSignalOperation: - endpoint = "l_sig"; - break; - case PNOperationType.PNSetUuidMetadataOperation: - case PNOperationType.PNDeleteUuidMetadataOperation: - case PNOperationType.PNGetAllUuidMetadataOperation: - case PNOperationType.PNGetUuidMetadataOperation: - case PNOperationType.PNSetChannelMetadataOperation: - case PNOperationType.PNDeleteChannelMetadataOperation: - case PNOperationType.PNGetAllChannelMetadataOperation: - case PNOperationType.PNGetChannelMetadataOperation: - case PNOperationType.PNGetMembershipsOperation: - case PNOperationType.PNManageMembershipsOperation: - case PNOperationType.PNSetMembershipsOperation: - case PNOperationType.PNRemoveMembershipsOperation: - case PNOperationType.PNGetChannelMembersOperation: - case PNOperationType.PNManageChannelMembersOperation: - case PNOperationType.PNSetChannelMembersOperation: - case PNOperationType.PNRemoveChannelMembersOperation: - endpoint = "l_obj"; - break; - case PNOperationType.PNAddMessageActionOperation: - case PNOperationType.PNRemoveMessageActionOperation: - case PNOperationType.PNGetMessageActionsOperation: - endpoint = "l_msga"; - break; - case PNOperationType.PNGenerateFileUploadUrlOperation: - case PNOperationType.PNPublishFileMessageOperation: - case PNOperationType.PNDownloadFileOperation: - endpoint = "l_file"; - break; - default: - endpoint = ""; - break; - } - - return endpoint; - } - - private static readonly object operationLatencyDataLock = new object(); - public async Task StoreLatency(long latencyMillisec, PNOperationType type) - { - await Task.Factory.StartNew(() => - { - try - { - string latencyEndPoint = EndpointNameForOperation(type); - if (latencyMillisec > 0 && !string.IsNullOrEmpty(latencyEndPoint)) - { - if (dicEndpointLatency == null) - { - dicEndpointLatency = new ConcurrentDictionary>(); - } - - double epochMillisec = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; - if (dicEndpointLatency.ContainsKey(latencyEndPoint) && dicEndpointLatency[latencyEndPoint] != null && dicEndpointLatency[latencyEndPoint].Keys.Count > 0) - { - if (epochMillisec - dicEndpointLatency[latencyEndPoint].Keys.Max() > 500) - { - lock (operationLatencyDataLock) - { - dicEndpointLatency[latencyEndPoint].AddOrUpdate(epochMillisec, latencyMillisec, (key, oldValue) => latencyMillisec); - } - } - } - else - { - lock (operationLatencyDataLock) - { - ConcurrentDictionary elapsedInfo = new ConcurrentDictionary(); - elapsedInfo.AddOrUpdate(epochMillisec, latencyMillisec, (o, n) => latencyMillisec); - dicEndpointLatency.AddOrUpdate(latencyEndPoint, elapsedInfo, (o, n) => elapsedInfo); - } - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, TelemetryManager - StoreLatency {1} latency = {2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), type, latencyMillisec), pubnubConfig.LogVerbosity); - } - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, TelemetryManager - StoreLatency error: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), pubnubConfig.LogVerbosity); - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - } - - public async Task> GetOperationsLatency() - { - return await Task>.Factory.StartNew(() => - { - Dictionary dictionaryOpsLatency = new Dictionary(); - try - { - lock (operationLatencyDataLock) - { - if (dicEndpointLatency != null) - { - foreach (string key in dicEndpointLatency.Keys) - { - if (dicEndpointLatency[key] != null && dicEndpointLatency[key].Count > 0) - { - - dictionaryOpsLatency.Add(key, Math.Round(((double)dicEndpointLatency[key].Average(kvp => kvp.Value) / 1000.0), 10).ToString(CultureInfo.InvariantCulture)); //Convert millisec to sec - } - } - } - } - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, TelemetryManager - GetOperationsLatency error: {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), pubnubConfig.LogVerbosity); - } - return dictionaryOpsLatency; - }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).ConfigureAwait(false); - } - - private void CleanupTelemetryData() - { - Task.Factory.StartNew(() => - { - lock (operationLatencyDataLock) - { - try - { - double currentEpochMillisec = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds; - string[] latencyOpKeys = (dicEndpointLatency != null) ? dicEndpointLatency.Keys.ToArray() : new string[]{ }; - for (int keyIndex = 0; keyIndex < latencyOpKeys.Length; keyIndex++) - { - string opKey = latencyOpKeys[keyIndex]; - ConcurrentDictionary outdatedLatencyValue = null; - dicEndpointLatency.TryGetValue(opKey, out outdatedLatencyValue); - if (outdatedLatencyValue != null) - { - IEnumerable> enumerableOutdatedLatencies = outdatedLatencyValue.Where(dt => currentEpochMillisec - dt.Key >= 60000); - if (enumerableOutdatedLatencies != null) - { - Dictionary dicOutdatedLatencies = enumerableOutdatedLatencies.ToDictionary(item => item.Key, item => item.Value); - if (dicOutdatedLatencies != null && dicOutdatedLatencies.Count > 0) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, TelemetryManager - CleanupTelemetryData => {1} dicOutdatedLatencies count = {2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), opKey, dicOutdatedLatencies.Count), pubnubConfig.LogVerbosity); - double[] outLatencyKeys = dicOutdatedLatencies.Keys.ToArray(); - for (int outdateIndex = 0; outdateIndex < outLatencyKeys.Length; outdateIndex++) - { - double outKey = outLatencyKeys[outdateIndex]; - ConcurrentDictionary currentEndPointLatency = null; - dicEndpointLatency.TryGetValue(opKey, out currentEndPointLatency); - if (currentEndPointLatency != null && currentEndPointLatency.ContainsKey(outKey)) - { - long removeOutdatedLatency; - if (!currentEndPointLatency.TryRemove(outKey, out removeOutdatedLatency)) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, TelemetryManager - CleanupTelemetryData => removed failed for key = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), outKey), pubnubConfig.LogVerbosity); - } - } - } - } - } - } - } - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, TelemetryManager - CleanupTelemetryData => Exception = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex), pubnubConfig.LogVerbosity); - } - } - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); - - } - - public void Destroy() - { - StopTelemetryTimer(); - dicEndpointLatency.Clear(); - dicEndpointLatency = null; - pubnubConfig = null; - pubnubLog = null; - } - - #region IDisposable Support - private bool disposedValue; - - protected virtual void DisposeInternal(bool disposing) - { - if (!disposedValue) - { - dicEndpointLatency.Clear(); - pubnubConfig = null; - pubnubLog = null; - if (telemetryTimer != null) - { - telemetryTimer.Dispose(); - telemetryTimer = null; - } - - disposedValue = true; - } - } - - void IDisposable.Dispose() - { - DisposeInternal(true); - } - #endregion - } -} - diff --git a/src/Api/PubnubApi/EndPoint/TimeOperation.cs b/src/Api/PubnubApi/EndPoint/TimeOperation.cs index a2a9f5dea..1f686d651 100644 --- a/src/Api/PubnubApi/EndPoint/TimeOperation.cs +++ b/src/Api/PubnubApi/EndPoint/TimeOperation.cs @@ -1,162 +1,161 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using System.Threading.Tasks; -using System.Threading; -using System.Net; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif namespace PubnubApi.EndPoint { - public class TimeOperation: PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; - - private Dictionary queryParam; - - private PNCallback savedCallback; - - public TimeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, telemetryManager, null, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; - } - - public TimeOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - [Obsolete("Async is deprecated, please use Execute instead.")] - public void Async(PNCallback callback) - { - Execute(callback); - } - - public void Execute(PNCallback callback) - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - Time(this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - Time(this.queryParam, callback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await Time(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - Time(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - Time(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - internal void Time(Dictionary externalQueryParam, PNCallback callback) - { - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildTimeRequest("GET", "", externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = null; - requestState.ResponseType = PNOperationType.PNTimeOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - UrlProcessRequest(request, requestState, false).ContinueWith(r => - { - string json = r.Result.Item1; - if (!string.IsNullOrEmpty(json)) - { - List result = ProcessJsonResponse(requestState, json); - ProcessResponseCallbacks(result, requestState); - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - } - - internal async Task> Time(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, pubnubTelemetryMgr, null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildTimeRequest("GET", "", externalQueryParam); - - RequestState requestState = new RequestState(); - requestState.Channels = null; - requestState.ResponseType = PNOperationType.PNTimeOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequest(request, requestState, false).ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - string json = JsonAndStatusTuple.Item1; - if (!string.IsNullOrEmpty(json)) - { - List resultList = ProcessJsonResponse(requestState, json); - if (resultList != null && resultList.Count > 0) - { - ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); - PNTimeResult responseResult = responseBuilder.JsonToObject(resultList, true); - if (responseResult != null) - { - ret.Result = responseResult; - } - } - } - - return ret; - } - - internal void CurrentPubnubInstance(Pubnub instance) - { - PubnubInstance = instance; - - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } + public class TimeOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private Dictionary queryParam; + + private PNCallback savedCallback; + + public TimeOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, null, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public TimeOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + [Obsolete("Async is deprecated, please use Execute instead.")] + public void Async(PNCallback callback) + { + Execute(callback); + } + + public void Execute(PNCallback callback) + { + this.savedCallback = callback; + Time(this.queryParam, callback); + } + + public async Task> ExecuteAsync() + { + return await Time(this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + Time(this.queryParam, savedCallback); + } + + internal void Time(Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.Channels = null; + requestState.ResponseType = PNOperationType.PNTimeOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNTimeOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + requestState.GotJsonResponse = true; + if (!string.IsNullOrEmpty(responseString)) { + List result = ProcessJsonResponse(requestState, responseString); + ProcessResponseCallbacks(result, requestState); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNTimeOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + + internal async Task> Time(Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNTimeOperation; + requestState.Channels = null; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + Tuple JsonAndStatusTuple; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNTimeOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ConfigureAwait(false); + if (transportResponse.Error == null) { + var responseString = Encoding.UTF8.GetString(transportResponse.Content); + PNStatus errorStatus = GetStatusIfError(requestState, responseString); + if (errorStatus == null) { + requestState.GotJsonResponse = true; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errorStatus); + } + returnValue.Status = JsonAndStatusTuple.Item2; + string json = JsonAndStatusTuple.Item1; + if (!string.IsNullOrEmpty(json)) { + List resultList = ProcessJsonResponse(requestState, json); + if (resultList != null && resultList.Count > 0) { + ResponseBuilder responseBuilder = new ResponseBuilder(config, jsonLibrary, pubnubLog); + PNTimeResult responseResult = responseBuilder.JsonToObject(resultList, true); + if (responseResult != null) { + returnValue.Result = responseResult; + } + } + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNTimeOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + + return returnValue; + } + + internal void CurrentPubnubInstance(Pubnub instance) + { + PubnubInstance = instance; + } + + private RequestParameter CreateRequestParameter() + { + List pathSegments = new List + { + "time", + "0" + }; + + Dictionary requestQueryStringParams = new Dictionary(); + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNTimeOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; + + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs b/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs index a56cfb132..a6bccc71b 100644 --- a/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs +++ b/src/Api/PubnubApi/EventEngine/Common/EventEmitter.cs @@ -252,10 +252,8 @@ public void EmitEvent(object e) Dictionary fileObjDic = jsonLibrary.ConvertToDictionaryObject(pnMsgObjDic["file"]); if (fileObjDic != null && fileObjDic.ContainsKey("id") && fileObjDic.ContainsKey("name")) { fileMessage.File = new PNFile { Id = fileObjDic["id"].ToString(), Name = fileObjDic["name"].ToString() }; - - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(configuration, jsonLibrary, null, log, null, tokenManager, (instance != null) ? instance.InstanceId : ""); - Uri fileUrlRequest = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", fileMessage.Channel, fileMessage.File.Id, fileMessage.File.Name, null, PNOperationType.PNGenerateFileUploadUrlOperation); - fileMessage.File.Url = fileUrlRequest.ToString(); + fileMessage.File.Url = UriUtil.GetFileUrl(fileName: fileMessage.File.Name, fileId: fileMessage.File.Id, channel:fileMessage.Channel, + pnConfiguration:configuration, pubnub:instance, tokenmanager:tokenManager); } } } else { diff --git a/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs b/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs index 53afdd87f..631729f3e 100644 --- a/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs +++ b/src/Api/PubnubApi/EventEngine/Presence/PresenceEventEngineFactory.cs @@ -25,10 +25,10 @@ internal PresenceEventEngine GetEventEngine(string instanceId) } internal PresenceEventEngine InitializeEventEngine(string instanceId, - Pubnub pubnubInstance, IPubnubLog pubnubLog, TelemetryManager telemetryManager, TokenManager tokenManager) + Pubnub pubnubInstance, IPubnubLog pubnubLog, TokenManager tokenManager) { - HeartbeatOperation heartbeatOperation = new HeartbeatOperation(pubnubInstance.PNConfig, pubnubInstance.JsonPluggableLibrary, pubnubInstance.PubnubUnitTest, pubnubLog, telemetryManager, tokenManager, pubnubInstance); - LeaveOperation leaveOperation = new LeaveOperation(pubnubInstance.PNConfig, pubnubInstance.JsonPluggableLibrary, pubnubInstance.PubnubUnitTest, pubnubLog, telemetryManager, tokenManager, pubnubInstance); + HeartbeatOperation heartbeatOperation = new HeartbeatOperation(pubnubInstance.PNConfig, pubnubInstance.JsonPluggableLibrary, pubnubInstance.PubnubUnitTest, pubnubLog, tokenManager, pubnubInstance); + LeaveOperation leaveOperation = new LeaveOperation(pubnubInstance.PNConfig, pubnubInstance.JsonPluggableLibrary, pubnubInstance.PubnubUnitTest, pubnubLog, tokenManager, pubnubInstance); var presenceEventEngine = new PresenceEventEngine(pubnubInstance.PNConfig, heartbeatOperation, leaveOperation); if (engineInstances.TryAdd(instanceId, presenceEventEngine)) { return presenceEventEngine; diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs index d9a5526cf..cec9eb9ae 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/Effects/ReceivingEffectHandler.cs @@ -38,17 +38,17 @@ public override async Task Run(ReceiveMessagesInvocation invocation) switch (invocation) { - case Invocations.ReceiveReconnectInvocation reconnectInvocation when response.Item2.Error: - eventQueue.Enqueue(new Events.ReceiveReconnectFailureEvent() { AttemptedRetries = (reconnectInvocation.AttemptedRetries + 1) % int.MaxValue, Status = response.Item2}); + case ReceiveReconnectInvocation reconnectInvocation when response.Item2.Error: + eventQueue.Enqueue(new ReceiveReconnectFailureEvent() { AttemptedRetries = (reconnectInvocation.AttemptedRetries + 1) % int.MaxValue, Status = response.Item2}); break; - case Invocations.ReceiveReconnectInvocation reconnectInvocation: - eventQueue.Enqueue(new Events.ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2, Messages = response.Item1 }); + case ReceiveReconnectInvocation reconnectInvocation: + eventQueue.Enqueue(new ReceiveReconnectSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Status = response.Item2, Messages = response.Item1 }); break; case { } when response.Item2.Error: - eventQueue.Enqueue(new Events.ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2, AttemptedRetries = 0}); + eventQueue.Enqueue(new ReceiveFailureEvent() { Cursor = invocation.Cursor, Status = response.Item2, AttemptedRetries = 0}); break; case { }: - eventQueue.Enqueue(new Events.ReceiveSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Messages= response.Item1, Status = response.Item2 }); + eventQueue.Enqueue(new ReceiveSuccessEvent() { Channels = invocation?.Channels, ChannelGroups = invocation?.ChannelGroups, Cursor = cursor, Messages= response.Item1, Status = response.Item2 }); break; } } @@ -58,7 +58,7 @@ public override bool IsBackground(ReceiveMessagesInvocation invocation) return true; } - private async Task, PNStatus>> MakeReceiveMessagesRequest(ReceiveMessagesInvocation invocation) + private async Task, PNStatus>> MakeReceiveMessagesRequest(ReceiveMessagesInvocation invocation) { return await manager.ReceiveRequest>( PNOperationType.PNSubscribeOperation, diff --git a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs index b23405b6b..a9d3f7881 100644 --- a/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs +++ b/src/Api/PubnubApi/EventEngine/Subscribe/SubscribeEventEngine.cs @@ -89,10 +89,11 @@ public void UnsubscribeAll() public void Unsubscribe(string[] channels, string[] channelGroups) { - this.EventQueue.Enqueue(new SubscriptionChangedEvent() { - Channels = this.Channels?.Except(channels ?? Enumerable.Empty()), - ChannelGroups = this.ChannelGroups?.Except(channelGroups ?? Enumerable.Empty()) - }); + if(channels.Length>0 || channelGroups.Length>0) + this.EventQueue.Enqueue(new SubscriptionChangedEvent() { + Channels = this.Channels?.Except(channels ?? Enumerable.Empty()), + ChannelGroups = this.ChannelGroups?.Except(channelGroups ?? Enumerable.Empty()) + }); } } } \ No newline at end of file diff --git a/src/Api/PubnubApi/Interface/IPubnubHttp.cs b/src/Api/PubnubApi/Interface/IPubnubHttp.cs deleted file mode 100644 index 7358956be..000000000 --- a/src/Api/PubnubApi/Interface/IPubnubHttp.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; - -namespace PubnubApi -{ - public interface IPubnubHttp - { - HttpWebRequest SetProxy(HttpWebRequest request); - - HttpWebRequest SetTimeout(RequestState pubnubRequestState, HttpWebRequest request); - - HttpWebRequest SetNoCache(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); - - Task SendRequestAndGetJsonResponseWithPOST(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request, byte[] postData, string contentType); - - Task SendRequestAndGetJsonResponseWithPATCH(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request, byte[] patchData, string contentType); - - Task SendRequestAndGetStreamResponse(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request); - } - -} diff --git a/src/Api/PubnubApi/Interface/IUrlRequestBuilder.cs b/src/Api/PubnubApi/Interface/IUrlRequestBuilder.cs deleted file mode 100644 index 687173a89..000000000 --- a/src/Api/PubnubApi/Interface/IUrlRequestBuilder.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace PubnubApi -{ - public interface IUrlRequestBuilder - { - Uri BuildTimeRequest(string requestMethod, string requestBody, Dictionary externalQueryParam); - - Uri BuildMultiChannelSubscribeRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, long timetoken, int region, string channelsJsonState, Dictionary initialSubscribeUrlParams, Dictionary externalQueryParam); - - Uri BuildMultiChannelLeaveRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, string jsonUserState, Dictionary externalQueryParam); - - Uri BuildPublishRequest(string requestMethod, string requestBody, string channel, object originalMessage, bool storeInHistory, int ttl, Dictionary userMetaData, Dictionary additionalUrlParams, Dictionary externalQueryParam); - - Uri BuildSignalRequest(string requestMethod, string requestBody, string channel, object originalMessage, Dictionary userMetaData, Dictionary externalQueryParam); - - Uri BuildHereNowRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, bool showUUIDList, bool includeUserState, Dictionary externalQueryParam); - - Uri BuildHistoryRequest(string requestMethod, string requestBody, string channel, long start, long end, int count, bool reverse, bool includeToken, bool includeMeta, Dictionary externalQueryParam); - - Uri BuildFetchRequest(string requestMethod, string requestBody, string[] channels, long start, long end, int count, bool reverse, bool includeMeta, bool includeMessageActions, bool includeUuid, bool includeMessageType, Dictionary externalQueryParam); - - Uri BuildDeleteMessageRequest(string requestMethod, string requestBody, string channel, long start, long end, Dictionary externalQueryParam); - - Uri BuildWhereNowRequest(string requestMethod, string requestBody, string uuid, Dictionary externalQueryParam); - - Uri BuildGrantV2AccessRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string channelGroupsCommaDelimited, string targetUuidsCommaDelimited, string authKeysCommaDelimited, bool read, bool write, bool delete, bool manage, bool get, bool update, bool join, long ttl, Dictionary externalQueryParam); - - Uri BuildGrantV3AccessRequest(string requestMethod, string requestBody, Dictionary externalQueryParam); - - Uri BuildRevokeV3AccessRequest(string requestMethod, string requestBody, string token, Dictionary externalQueryParam); - - Uri BuildAuditAccessRequest(string requestMethod, string requestBody, string channel, string channelGroup, string authKeysCommaDelimited, Dictionary externalQueryParam); - - Uri BuildGetUserStateRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string channelGroupsCommaDelimited, string uuid, Dictionary externalQueryParam); - - Uri BuildSetUserStateRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string channelGroupsCommaDelimited, string uuid, string jsonUserState, Dictionary externalQueryParam); - - Uri BuildAddChannelsToChannelGroupRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string nameSpace, string groupName, Dictionary externalQueryParam); - - Uri BuildRemoveChannelsFromChannelGroupRequest(string requestMethod, string requestBody, string channelsCommaDelimited, string nameSpace, string groupName, Dictionary externalQueryParam); - - Uri BuildGetChannelsForChannelGroupRequest(string requestMethod, string requestBody, string nameSpace, string groupName, bool limitToChannelGroupScopeOnly, Dictionary externalQueryParam); - - Uri BuildGetAllChannelGroupRequest(string requestMethod, string requestBody, Dictionary externalQueryParam); - - Uri BuildRegisterDevicePushRequest(string requestMethod, string requestBody, string channel, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam); - - Uri BuildUnregisterDevicePushRequest(string requestMethod, string requestBody, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam); - - Uri BuildRemoveChannelPushRequest(string requestMethod, string requestBody, string channel, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam); - - Uri BuildGetChannelsPushRequest(string requestMethod, string requestBody, PNPushType pushType, string pushToken, PushEnvironment environment, string deviceTopic, Dictionary externalQueryParam); - - Uri BuildPresenceHeartbeatRequest(string requestMethod, string requestBody, string[] channels, string[] channelGroups, string jsonUserState); - - Uri BuildMessageCountsRequest(string requestMethod, string requestBody, string[] channels, long[] timetokens, Dictionary externalQueryParam); - - Uri BuildSetUuidMetadataRequest(string requestMethod, string requestBody, string uuid, bool includeCustom, Dictionary externalQueryParam); - - Uri BuildDeleteUuidMetadataRequest(string requestMethod, string requestBody, string uuid, Dictionary externalQueryParam); - - Uri BuildGetAllUuidMetadataRequest(string requestMethod, string requestBody, string start, string end, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam); - - Uri BuildGetSingleUuidMetadataRequest(string requestMethod, string requestBody, string uuid, bool includeCustom, Dictionary externalQueryParam); - - Uri BuildSetChannelMetadataRequest(string requestMethod, string requestBody, string channel, bool includeCustom, Dictionary externalQueryParam); - - Uri BuildDeleteChannelMetadataRequest(string requestMethod, string requestBody, string channel, Dictionary externalQueryParam); - - Uri BuildGetAllChannelMetadataRequest(string requestMethod, string requestBody, string start, string end, int limit, bool includeCount, bool includeCustom, string filter, List sort, Dictionary externalQueryParam); - - Uri BuildGetSingleChannelMetadataRequest(string requestMethod, string requestBody, string channel, bool includeCustom, Dictionary externalQueryParam); - - Uri BuildMembershipSetRemoveManageUserRequest(PNOperationType type, string requestMethod, string requestBody, string uuid, string start, string end, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam); - - Uri BuildMemberAddUpdateRemoveChannelRequest(string requestMethod, string requestBody, string channel, string start, string end, int limit, bool includeCount, string includeOptions, List sort, Dictionary externalQueryParam); - - Uri BuildGetAllMembershipsRequest(string requestMethod, string requestBody, string uuid, string start, string end, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam); - - Uri BuildGetAllMembersRequest(string requestMethod, string requestBody, string channel, string start, string end, int limit, bool includeCount, string includeOptions, string filter, List sort, Dictionary externalQueryParam); - - Uri BuildAddMessageActionRequest(string requestMethod, string requestBody, string channel, long messageTimetoken, Dictionary externalQueryParam); - - Uri BuildRemoveMessageActionRequest(string requestMethod, string requestBody, string channel, long messageTimetoken, long actionTimetoken, string messageActionUuid, Dictionary externalQueryParam); - - Uri BuildGetMessageActionsRequest(string requestMethod, string requestBody, string channel, long start, long end, int limit, Dictionary externalQueryParam); - - Uri BuildGenerateFileUploadUrlRequest(string requestMethod, string requestBody, string channel, Dictionary externalQueryParam); - - Uri BuildPublishFileMessageRequest(string requestMethod, string requestBody, string channel, object originalMessage, bool storeInHistory, int ttl, Dictionary userMetaData, Dictionary additionalUrlParams, Dictionary externalQueryParam); - - Uri BuildGetFileUrlOrDeleteReqest(string requestMethod, string requestBody, string channel, string fileId, string fileName, Dictionary externalQueryParam, PNOperationType operationType); - - Uri BuildListFilesReqest(string requestMethod, string requestBody, string channel, int limit, string nextToken, Dictionary externalQueryParam, PNOperationType operationType); - } -} diff --git a/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs b/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs index 73d215306..e88375ef2 100644 --- a/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs +++ b/src/Api/PubnubApi/JsonDataParse/DeserializeToInternalObjectUtility.cs @@ -994,12 +994,11 @@ public static T DeserializeToInternalObject(IJsonPluggableLibrary jsonPlug, L { ret = (T)(object)listObject; } - catch + catch(Exception e) { - /* ignore */ + System.Diagnostics.Debug.WriteLine($"DeserializeToObject(list) exception {e.Message}"); } } - return ret; } } diff --git a/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs b/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs index 08b35dd7f..65713cbea 100644 --- a/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs +++ b/src/Api/PubnubApi/Model/Derived/Pubsub/SubscribeCallbackExt.cs @@ -45,7 +45,7 @@ public SubscribeCallbackExt(Action> messageCallb fileAction = null; } - public SubscribeCallbackExt(Action> messageCallback) + public SubscribeCallbackExt(Action> messageCallback, object presenceCallback) { subscribeAction = messageCallback; presenceAction = null; diff --git a/src/Api/PubnubApi/Model/RequestState.cs b/src/Api/PubnubApi/Model/RequestState.cs index cfb8d3014..0659068e5 100644 --- a/src/Api/PubnubApi/Model/RequestState.cs +++ b/src/Api/PubnubApi/Model/RequestState.cs @@ -1,13 +1,14 @@ using System; using System.Net; +using System.Threading; 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 CancellationTokenSource RequestCancellationTokenSource { get; internal set; } + public TransportResponse Response { get; internal set; } public bool GotJsonResponse { get; internal set; } public PNOperationType ResponseType { get; internal set; } public string[] Channels { get; internal set; } @@ -24,7 +25,7 @@ public sealed class RequestState public RequestState() { PubnubCallback = null; - Request = null; + RequestCancellationTokenSource = null; Response = null; Channels = null; ChannelGroups = null; diff --git a/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs b/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs index 51d5492ab..66d7d0518 100644 --- a/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs +++ b/src/Api/PubnubApi/NewtonsoftJsonDotNet.cs @@ -236,14 +236,6 @@ private bool IsGenericTypeForMessage() { bool ret = false; PNPlatform.Print(config, pubnubLog); - -#if (NET35 || NET40 || NET45 || NET461 || NET48) - if (typeof(T).IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(PNMessageResult<>)) - { - ret = true; - } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, NET35/40 IsGenericTypeForMessage = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ret.ToString()), config.LogVerbosity); -#elif (NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 || NETSTANDARD13 || NETSTANDARD14 || NETSTANDARD20 || NET60 || UAP || NETFX_CORE || WINDOWS_UWP) if (typeof(T).GetTypeInfo().IsGenericType && typeof(T).GetGenericTypeDefinition() == typeof(PNMessageResult<>)) { @@ -263,11 +255,6 @@ private bool IsGenericTypeForMessage() DateTime.Now.ToString(CultureInfo.InvariantCulture), typeof(T).GetGenericTypeDefinition().ToString()), config.LogVerbosity); } - - LoggingMethod.WriteToLog(pubnubLog, - string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, PCL/CORE IsGenericTypeForMessage = {1}", - DateTime.Now.ToString(CultureInfo.InvariantCulture), ret.ToString()), config.LogVerbosity); -#endif LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, IsGenericTypeForMessage = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ret.ToString()), config.LogVerbosity); @@ -277,81 +264,6 @@ private bool IsGenericTypeForMessage() private T DeserializeMessageToObjectBasedOnPlatform(List listObject) { T ret = default(T); - -#if NET35 || NET40 || NET45 || NET461 || NET48 - Type dataType = typeof(T).GetGenericArguments()[0]; - Type generic = typeof(PNMessageResult<>); - Type specific = generic.MakeGenericType(dataType); - - ConstructorInfo ci = specific.GetConstructors().FirstOrDefault(); - if (ci != null) - { - object message = ci.Invoke(new object[] { }); - - //Set data - PropertyInfo dataProp = specific.GetProperty("Message"); - - object userMessage = null; - if (listObject[0].GetType() == typeof(Newtonsoft.Json.Linq.JValue)) - { - JValue jsonValue = listObject[0] as JValue; - userMessage = jsonValue.Value; - userMessage = ConvertToDataType(dataType, userMessage); - - dataProp.SetValue(message, userMessage, null); - } - else if (listObject[0].GetType() == typeof(Newtonsoft.Json.Linq.JObject) || listObject[0].GetType() == typeof(Newtonsoft.Json.Linq.JArray)) - { - JToken token = listObject[0] as JToken; - if (dataProp.PropertyType == typeof(string)) - { - userMessage = JsonConvert.SerializeObject(token, defaultJsonSerializerSettings); - } - else - { - userMessage = token.ToObject(dataProp.PropertyType, JsonSerializer.Create()); - } - - dataProp.SetValue(message, userMessage, null); - } - else if (listObject[0].GetType() == typeof(System.String)) - { - userMessage = listObject[0] as string; - dataProp.SetValue(message, userMessage, null); - } - - //Set Time - PropertyInfo timeProp = specific.GetProperty("Timetoken"); - long timetoken; - var _ = Int64.TryParse(listObject[2].ToString(), out timetoken); - timeProp.SetValue(message, timetoken, null); - - //Set Publisher - PropertyInfo publisherProp = specific.GetProperty("Publisher"); - string publisherValue = (listObject[3] != null) ? listObject[3].ToString() : ""; - publisherProp.SetValue(message, publisherValue, null); - - // Set ChannelName - PropertyInfo channelNameProp = specific.GetProperty("Channel"); - channelNameProp.SetValue(message, (listObject.Count == 6) ? listObject[5].ToString() : listObject[4].ToString(), null); - - // Set ChannelGroup - if (listObject.Count == 6) - { - PropertyInfo subsciptionProp = specific.GetProperty("Subscription"); - subsciptionProp.SetValue(message, listObject[4].ToString(), null); - } - - //Set Metadata list second position, index=1 - if (listObject[1] != null) - { - PropertyInfo userMetadataProp = specific.GetProperty("UserMetadata"); - userMetadataProp.SetValue(message, listObject[1], null); - } - - ret = (T)Convert.ChangeType(message, specific, CultureInfo.InvariantCulture); - } -#elif NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 || NETSTANDARD13 || NETSTANDARD14 || NETSTANDARD20 || NET60 || UAP || NETFX_CORE || WINDOWS_UWP Type dataType = typeof(T).GetTypeInfo().GenericTypeArguments[0]; Type generic = typeof(PNMessageResult<>); Type specific = generic.MakeGenericType(dataType); @@ -365,7 +277,7 @@ private T DeserializeMessageToObjectBasedOnPlatform(List listObject) PropertyInfo dataProp = specific.GetRuntimeProperty("Message"); object userMessage = null; - if (listObject[0].GetType() == typeof(Newtonsoft.Json.Linq.JValue)) + if (listObject[0].GetType() == typeof(JValue)) { JValue jsonValue = listObject[0] as JValue; userMessage = jsonValue.Value; @@ -373,8 +285,8 @@ private T DeserializeMessageToObjectBasedOnPlatform(List listObject) dataProp.SetValue(message, userMessage, null); } - else if (listObject[0].GetType() == typeof(Newtonsoft.Json.Linq.JObject) || - listObject[0].GetType() == typeof(Newtonsoft.Json.Linq.JArray)) + else if (listObject[0].GetType() == typeof(JObject) || + listObject[0].GetType() == typeof(JArray)) { JToken token = listObject[0] as JToken; if (dataProp.PropertyType == typeof(string)) @@ -426,7 +338,6 @@ private T DeserializeMessageToObjectBasedOnPlatform(List listObject) ret = (T)Convert.ChangeType(message, specific, CultureInfo.InvariantCulture); } -#endif return ret; } @@ -698,7 +609,7 @@ private static object ConvertToDataType(Type dataType, object inputValue) userMessage = Convert.ChangeType(inputValue, typeof(System.String), CultureInfo.InvariantCulture); break; case "System.Object": - userMessage = Convert.ChangeType(inputValue, typeof(System.Object), CultureInfo.InvariantCulture); + userMessage = Convert.ChangeType(inputValue, typeof(Object), CultureInfo.InvariantCulture); break; default: break; diff --git a/src/Api/PubnubApi/PNConfiguration.cs b/src/Api/PubnubApi/PNConfiguration.cs index 233ca800c..4296d5265 100644 --- a/src/Api/PubnubApi/PNConfiguration.cs +++ b/src/Api/PubnubApi/PNConfiguration.cs @@ -1,8 +1,5 @@ using PubnubApi.Security.Crypto; using System; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; namespace PubnubApi { @@ -10,7 +7,7 @@ public class PNConfiguration { private int presenceHeartbeatTimeout; private int presenceHeartbeatInterval; - private UserId _userId; + private UserId userId; private bool uuidSetFromConstructor; private PNReconnectionPolicy reconnectionPolicy; @@ -22,10 +19,7 @@ internal void ResetUuidSetFromConstructor() public int PresenceTimeout { - get - { - return presenceHeartbeatTimeout; - } + get => presenceHeartbeatTimeout; set { presenceHeartbeatTimeout = value; @@ -33,13 +27,7 @@ public int PresenceTimeout } } - public int PresenceInterval - { - get - { - return presenceHeartbeatInterval; - } - } + public int PresenceInterval => presenceHeartbeatInterval; public bool Secure { get; set; } @@ -61,20 +49,17 @@ public int PresenceInterval [Obsolete("Uuid is deprecated, please use UserId instead.")] public string Uuid { - get - { - return _userId.ToString(); - } + get => userId.ToString(); set { - if (_userId != null && !uuidSetFromConstructor) + if (userId != null && !uuidSetFromConstructor) { throw new ArgumentException("Either UserId or Uuid can be used. Not both."); } if (value != null && value.Trim().Length > 0) { - _userId = new UserId(value); + userId = new UserId(value); } else { @@ -85,10 +70,7 @@ public string Uuid public UserId UserId { - get - { - return _userId; - } + get => userId; set { if (uuidSetFromConstructor) @@ -99,7 +81,7 @@ public UserId UserId if (value != null && !string.IsNullOrEmpty(value.ToString())) { uuidSetFromConstructor = false; - _userId = value; + userId = value; } else { @@ -114,9 +96,9 @@ public UserId UserId public Proxy Proxy { get; set; } - public int SubscribeTimeout { get; set; } //How long to keep the subscribe loop running before disconnect. + public int SubscribeTimeout { get; set; } = 310; - public int NonSubscribeRequestTimeout { get; set; } //On non subscribe operations, how long to wait for server response. + public int NonSubscribeRequestTimeout { get; set; } = 15; public PNHeartbeatNotificationOption HeartbeatNotificationOption { get; set; } @@ -138,12 +120,6 @@ public PNReconnectionPolicy ReconnectionPolicy { public int RequestMessageCountThreshold { get; set; } = 100; - public bool UseClassicHttpWebRequest { get; set; } - - public bool UseTaskFactoryAsyncInsteadOfHttpClient { get; set; } - - public bool EnableTelemetry { get; set; } = true; - public int MaximumMessagesCacheSize { get; set; } public bool DedupOnSubscribe { get; set; } @@ -189,7 +165,7 @@ private void ConstructorInit(UserId currentUserId) SubscribeKey = ""; SecretKey = ""; Secure = true; - ReconnectionPolicy = PNReconnectionPolicy.NONE; + ReconnectionPolicy = PNReconnectionPolicy.EXPONENTIAL; HeartbeatNotificationOption = PNHeartbeatNotificationOption.Failures; IncludeRequestIdentifier = true; IncludeInstanceIdentifier = false; @@ -198,8 +174,8 @@ private void ConstructorInit(UserId currentUserId) SuppressLeaveEvents = false; UseRandomInitializationVector = true; FileMessagePublishRetryLimit = 5; - _userId = currentUserId; - EnableEventEngine = false; + userId = currentUserId; + EnableEventEngine = true; } private void setDefaultRetryConfigurationFromPolicy(PNReconnectionPolicy policy) @@ -212,15 +188,13 @@ private void setDefaultRetryConfigurationFromPolicy(PNReconnectionPolicy policy) case PNReconnectionPolicy.EXPONENTIAL: RetryConfiguration = RetryConfiguration.Exponential(2, 150, 6); break; - default: - break; } } public PNConfiguration SetPresenceTimeoutWithCustomInterval(int timeout, int interval) { - this.presenceHeartbeatTimeout = timeout; - this.presenceHeartbeatInterval = interval; + presenceHeartbeatTimeout = timeout; + presenceHeartbeatInterval = interval; return this; } diff --git a/src/Api/PubnubApi/Pubnub.cs b/src/Api/PubnubApi/Pubnub.cs index c0b88703b..0dc9a8953 100644 --- a/src/Api/PubnubApi/Pubnub.cs +++ b/src/Api/PubnubApi/Pubnub.cs @@ -8,13 +8,10 @@ using PubnubApi.EventEngine.Subscribe.Common; using PubnubApi.Interface; using PubnubApi.EventEngine.Presence; - -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; using PubnubApi.EventEngine.Common; +using System.Collections.Concurrent; namespace PubnubApi { @@ -23,9 +20,8 @@ public class Pubnub private ConcurrentDictionary pubnubConfig { get; } = new ConcurrentDictionary(); private IPubnubUnitTest pubnubUnitTest; private IPubnubLog pubnubLog; - private EndPoint.ListenerManager listenerManager; - private readonly EndPoint.TelemetryManager telemetryManager; - private readonly EndPoint.TokenManager tokenManager; + private ListenerManager listenerManager; + private readonly TokenManager tokenManager; private object savedSubscribeOperation; private readonly string savedSdkVerion; private SubscribeEventEngineFactory subscribeEventEngineFactory; @@ -43,14 +39,12 @@ private List subscribeCallbackListenerList static Pubnub() { -#if NET35 || NET40 - var assemblyVersion = typeof(Pubnub).Assembly.GetName().Version; -#else var assembly = typeof(Pubnub).GetTypeInfo().Assembly; var assemblyName = new AssemblyName(assembly.FullName); string assemblyVersion = assemblyName.Version.ToString(); -#endif - Version = string.Format(CultureInfo.InvariantCulture, "{0}CSharp{1}", PNPlatform.Get(), assemblyVersion); + var targetFramework = assembly.GetCustomAttribute()?.FrameworkDisplayName?.Replace(".",string.Empty).Replace(" ", string.Empty); + + Version = string.Format(CultureInfo.InvariantCulture, "{0}/CSharp/{1}", targetFramework??"UNKNOWN", assemblyVersion); } #if UNITY @@ -71,17 +65,17 @@ public ISubscribeOperation Subscribe() if (pubnubConfig[InstanceId].EnableEventEngine) { if (pubnubConfig[InstanceId].PresenceInterval > 0) { - presenceOperation = new PresenceOperation(this, InstanceId, pubnubLog, pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null ,telemetryManager, tokenManager, pubnubUnitTest ,presenceEventengineFactory); + presenceOperation = new PresenceOperation(this, InstanceId, pubnubLog, pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null , tokenManager, pubnubUnitTest ,presenceEventengineFactory); } - EndPoint.SubscribeEndpoint subscribeOperation = new EndPoint.SubscribeEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this.subscribeEventEngineFactory, presenceOperation, InstanceId ,this); - subscribeOperation.EventEmitter = this.eventEmitter; + SubscribeEndpoint subscribeOperation = new SubscribeEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, subscribeEventEngineFactory, presenceOperation, InstanceId ,this); + subscribeOperation.EventEmitter = eventEmitter; subscribeOperation.SubscribeListenerList = subscribeCallbackListenerList; savedSubscribeOperation = subscribeOperation; return subscribeOperation; } else { - EndPoint.SubscribeOperation subscribeOperation = new EndPoint.SubscribeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + SubscribeOperation subscribeOperation = new SubscribeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); savedSubscribeOperation = subscribeOperation; return subscribeOperation; } @@ -91,271 +85,271 @@ public IUnsubscribeOperation Unsubscribe() { if (pubnubConfig[InstanceId].EnableEventEngine) { - EndPoint.UnsubscribeEndpoint unsubscribeOperation = new EndPoint.UnsubscribeEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, subscribeEventEngineFactory, presenceEventengineFactory, this); + UnsubscribeEndpoint unsubscribeOperation = new UnsubscribeEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, subscribeEventEngineFactory, presenceEventengineFactory, this); return unsubscribeOperation; } else { - EndPoint.UnsubscribeOperation unsubscribeOperation = new EndPoint.UnsubscribeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + UnsubscribeOperation unsubscribeOperation = new UnsubscribeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); unsubscribeOperation.CurrentPubnubInstance(this); return unsubscribeOperation; } } - public EndPoint.UnsubscribeAllOperation UnsubscribeAll() + public UnsubscribeAllOperation UnsubscribeAll() { if (pubnubConfig[InstanceId].EnableEventEngine) { - EndPoint.UnsubscribeAllEndpoint unsubscribeAllEndpoint = new EndPoint.UnsubscribeAllEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, subscribeEventEngineFactory, presenceEventengineFactory, this); + UnsubscribeAllEndpoint unsubscribeAllEndpoint = new UnsubscribeAllEndpoint(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, subscribeEventEngineFactory, presenceEventengineFactory, this); return unsubscribeAllEndpoint; } else { - EndPoint.UnsubscribeAllOperation unSubscribeAllOperation = new EndPoint.UnsubscribeAllOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + UnsubscribeAllOperation unSubscribeAllOperation = new UnsubscribeAllOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return unSubscribeAllOperation; } } - public EndPoint.PublishOperation Publish() + public PublishOperation Publish() { - EndPoint.PublishOperation publishOperation = new EndPoint.PublishOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + PublishOperation publishOperation = new PublishOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); publishOperation.CurrentPubnubInstance(this); return publishOperation; } - public EndPoint.FireOperation Fire() + public FireOperation Fire() { - EndPoint.FireOperation fireOperation = new EndPoint.FireOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + FireOperation fireOperation = new FireOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); fireOperation.CurrentPubnubInstance(this); return fireOperation; } - public EndPoint.SignalOperation Signal() + public SignalOperation Signal() { - EndPoint.SignalOperation signalOperation = new EndPoint.SignalOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SignalOperation signalOperation = new SignalOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return signalOperation; } - public EndPoint.HistoryOperation History() + public HistoryOperation History() { - EndPoint.HistoryOperation historyOperaton = new EndPoint.HistoryOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + HistoryOperation historyOperaton = new HistoryOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return historyOperaton; } - public EndPoint.FetchHistoryOperation FetchHistory() + public FetchHistoryOperation FetchHistory() { - EndPoint.FetchHistoryOperation historyOperaton = new EndPoint.FetchHistoryOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + FetchHistoryOperation historyOperaton = new FetchHistoryOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return historyOperaton; } - public EndPoint.DeleteMessageOperation DeleteMessages() + public DeleteMessageOperation DeleteMessages() { - EndPoint.DeleteMessageOperation deleteMessageOperaton = new EndPoint.DeleteMessageOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + DeleteMessageOperation deleteMessageOperaton = new DeleteMessageOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return deleteMessageOperaton; } - public EndPoint.MessageCountsOperation MessageCounts() + public MessageCountsOperation MessageCounts() { - EndPoint.MessageCountsOperation messageCount = new EndPoint.MessageCountsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + MessageCountsOperation messageCount = new MessageCountsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); messageCount.CurrentPubnubInstance(this); return messageCount; } - public EndPoint.HereNowOperation HereNow() + public HereNowOperation HereNow() { - EndPoint.HereNowOperation hereNowOperation = new EndPoint.HereNowOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + HereNowOperation hereNowOperation = new HereNowOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); hereNowOperation.CurrentPubnubInstance(this); return hereNowOperation; } - public EndPoint.WhereNowOperation WhereNow() + public WhereNowOperation WhereNow() { - EndPoint.WhereNowOperation whereNowOperation = new EndPoint.WhereNowOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + WhereNowOperation whereNowOperation = new WhereNowOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); whereNowOperation.CurrentPubnubInstance(this); return whereNowOperation; } - public EndPoint.TimeOperation Time() + public TimeOperation Time() { - EndPoint.TimeOperation timeOperation = new EndPoint.TimeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, this); + TimeOperation timeOperation = new TimeOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, this); timeOperation.CurrentPubnubInstance(this); return timeOperation; } - public EndPoint.AuditOperation Audit() + public AuditOperation Audit() { - EndPoint.AuditOperation auditOperation = new EndPoint.AuditOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, this); + AuditOperation auditOperation = new AuditOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, this); auditOperation.CurrentPubnubInstance(this); return auditOperation; } - public EndPoint.GrantTokenOperation GrantToken() + public GrantTokenOperation GrantToken() { - EndPoint.GrantTokenOperation grantOperation = new EndPoint.GrantTokenOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GrantTokenOperation grantOperation = new GrantTokenOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return grantOperation; } - public EndPoint.RevokeTokenOperation RevokeToken() + public RevokeTokenOperation RevokeToken() { - EndPoint.RevokeTokenOperation revokeTokenOperation = new EndPoint.RevokeTokenOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RevokeTokenOperation revokeTokenOperation = new RevokeTokenOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return revokeTokenOperation; } - public EndPoint.GrantOperation Grant() + public GrantOperation Grant() { - EndPoint.GrantOperation grantOperation = new EndPoint.GrantOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, this); + GrantOperation grantOperation = new GrantOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, this); grantOperation.CurrentPubnubInstance(this); return grantOperation; } - public EndPoint.SetStateOperation SetPresenceState() + public SetStateOperation SetPresenceState() { - EndPoint.SetStateOperation setStateOperation = new EndPoint.SetStateOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SetStateOperation setStateOperation = new SetStateOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return setStateOperation; } - public EndPoint.GetStateOperation GetPresenceState() + public GetStateOperation GetPresenceState() { - EndPoint.GetStateOperation getStateOperation = new EndPoint.GetStateOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetStateOperation getStateOperation = new GetStateOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); getStateOperation.CurrentPubnubInstance(this); return getStateOperation; } - public EndPoint.AddPushChannelOperation AddPushNotificationsOnChannels() + public AddPushChannelOperation AddPushNotificationsOnChannels() { - EndPoint.AddPushChannelOperation addPushChannelOperation = new EndPoint.AddPushChannelOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + AddPushChannelOperation addPushChannelOperation = new AddPushChannelOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return addPushChannelOperation; } - public EndPoint.RemovePushChannelOperation RemovePushNotificationsFromChannels() + public RemovePushChannelOperation RemovePushNotificationsFromChannels() { - EndPoint.RemovePushChannelOperation removePushChannelOperation = new EndPoint.RemovePushChannelOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemovePushChannelOperation removePushChannelOperation = new RemovePushChannelOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return removePushChannelOperation; } - public EndPoint.RemoveAllPushChannelsOperation RemoveAllPushNotificationsFromDeviceWithPushToken() + public RemoveAllPushChannelsOperation RemoveAllPushNotificationsFromDeviceWithPushToken() { - EndPoint.RemoveAllPushChannelsOperation removeAllPushChannelsOperation = new EndPoint.RemoveAllPushChannelsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveAllPushChannelsOperation removeAllPushChannelsOperation = new RemoveAllPushChannelsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); removeAllPushChannelsOperation.CurrentPubnubInstance(this); return removeAllPushChannelsOperation; } - public EndPoint.AuditPushChannelOperation AuditPushChannelProvisions() + public AuditPushChannelOperation AuditPushChannelProvisions() { - EndPoint.AuditPushChannelOperation auditPushChannelOperation = new EndPoint.AuditPushChannelOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + AuditPushChannelOperation auditPushChannelOperation = new AuditPushChannelOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); auditPushChannelOperation.CurrentPubnubInstance(this); return auditPushChannelOperation; } - public EndPoint.SetUuidMetadataOperation SetUuidMetadata() + public SetUuidMetadataOperation SetUuidMetadata() { - EndPoint.SetUuidMetadataOperation setUuidMetadataOperation = new EndPoint.SetUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SetUuidMetadataOperation setUuidMetadataOperation = new SetUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return setUuidMetadataOperation; } - public EndPoint.RemoveUuidMetadataOperation RemoveUuidMetadata() + public RemoveUuidMetadataOperation RemoveUuidMetadata() { - EndPoint.RemoveUuidMetadataOperation removeUuidMetadataOperation = new EndPoint.RemoveUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveUuidMetadataOperation removeUuidMetadataOperation = new RemoveUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return removeUuidMetadataOperation; } - public EndPoint.GetAllUuidMetadataOperation GetAllUuidMetadata() + public GetAllUuidMetadataOperation GetAllUuidMetadata() { - EndPoint.GetAllUuidMetadataOperation getAllUuidMetadataOperation = new EndPoint.GetAllUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetAllUuidMetadataOperation getAllUuidMetadataOperation = new GetAllUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getAllUuidMetadataOperation; } - public EndPoint.GetUuidMetadataOperation GetUuidMetadata() + public GetUuidMetadataOperation GetUuidMetadata() { - EndPoint.GetUuidMetadataOperation getUuidMetadataOperation = new EndPoint.GetUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetUuidMetadataOperation getUuidMetadataOperation = new GetUuidMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getUuidMetadataOperation; } - public EndPoint.SetChannelMetadataOperation SetChannelMetadata() + public SetChannelMetadataOperation SetChannelMetadata() { - EndPoint.SetChannelMetadataOperation setChannelMetadataOperation = new EndPoint.SetChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SetChannelMetadataOperation setChannelMetadataOperation = new SetChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return setChannelMetadataOperation; } - public EndPoint.RemoveChannelMetadataOperation RemoveChannelMetadata() + public RemoveChannelMetadataOperation RemoveChannelMetadata() { - EndPoint.RemoveChannelMetadataOperation removeChannelMetadataOperation = new EndPoint.RemoveChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveChannelMetadataOperation removeChannelMetadataOperation = new RemoveChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return removeChannelMetadataOperation; } - public EndPoint.GetAllChannelMetadataOperation GetAllChannelMetadata() + public GetAllChannelMetadataOperation GetAllChannelMetadata() { - EndPoint.GetAllChannelMetadataOperation getAllChannelMetadataOperation = new EndPoint.GetAllChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetAllChannelMetadataOperation getAllChannelMetadataOperation = new GetAllChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getAllChannelMetadataOperation; } - public EndPoint.GetChannelMetadataOperation GetChannelMetadata() + public GetChannelMetadataOperation GetChannelMetadata() { - EndPoint.GetChannelMetadataOperation getSingleSpaceOperation = new EndPoint.GetChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetChannelMetadataOperation getSingleSpaceOperation = new GetChannelMetadataOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getSingleSpaceOperation; } - public EndPoint.GetMembershipsOperation GetMemberships() + public GetMembershipsOperation GetMemberships() { - EndPoint.GetMembershipsOperation getMembershipOperation = new EndPoint.GetMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetMembershipsOperation getMembershipOperation = new GetMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getMembershipOperation; } - public EndPoint.SetMembershipsOperation SetMemberships() + public SetMembershipsOperation SetMemberships() { - EndPoint.SetMembershipsOperation setMembershipsOperation = new EndPoint.SetMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SetMembershipsOperation setMembershipsOperation = new SetMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return setMembershipsOperation; } - public EndPoint.RemoveMembershipsOperation RemoveMemberships() + public RemoveMembershipsOperation RemoveMemberships() { - EndPoint.RemoveMembershipsOperation removeMembershipsOperation = new EndPoint.RemoveMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveMembershipsOperation removeMembershipsOperation = new RemoveMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return removeMembershipsOperation; } - public EndPoint.ManageMembershipsOperation ManageMemberships() + public ManageMembershipsOperation ManageMemberships() { - EndPoint.ManageMembershipsOperation manageMembershipsOperation = new EndPoint.ManageMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + ManageMembershipsOperation manageMembershipsOperation = new ManageMembershipsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return manageMembershipsOperation; } - public EndPoint.GetChannelMembersOperation GetChannelMembers() + public GetChannelMembersOperation GetChannelMembers() { - EndPoint.GetChannelMembersOperation getChannelMembersOperation = new EndPoint.GetChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetChannelMembersOperation getChannelMembersOperation = new GetChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getChannelMembersOperation; } - public EndPoint.SetChannelMembersOperation SetChannelMembers() + public SetChannelMembersOperation SetChannelMembers() { - EndPoint.SetChannelMembersOperation setChannelMembersOperation = new EndPoint.SetChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SetChannelMembersOperation setChannelMembersOperation = new SetChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return setChannelMembersOperation; } - public EndPoint.RemoveChannelMembersOperation RemoveChannelMembers() + public RemoveChannelMembersOperation RemoveChannelMembers() { - EndPoint.RemoveChannelMembersOperation removeChannelMembersOperation = new EndPoint.RemoveChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveChannelMembersOperation removeChannelMembersOperation = new RemoveChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return removeChannelMembersOperation; } - public EndPoint.ManageChannelMembersOperation ManageChannelMembers() + public ManageChannelMembersOperation ManageChannelMembers() { - EndPoint.ManageChannelMembersOperation channelMembersOperation = new EndPoint.ManageChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + ManageChannelMembersOperation channelMembersOperation = new ManageChannelMembersOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return channelMembersOperation; } - public EndPoint.AddMessageActionOperation AddMessageAction() + public AddMessageActionOperation AddMessageAction() { - EndPoint.AddMessageActionOperation addMessageActionOperation = new EndPoint.AddMessageActionOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + AddMessageActionOperation addMessageActionOperation = new AddMessageActionOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return addMessageActionOperation; } - public EndPoint.RemoveMessageActionOperation RemoveMessageAction() + public RemoveMessageActionOperation RemoveMessageAction() { - EndPoint.RemoveMessageActionOperation removeMessageActionOperation = new EndPoint.RemoveMessageActionOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveMessageActionOperation removeMessageActionOperation = new RemoveMessageActionOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return removeMessageActionOperation; } - public EndPoint.GetMessageActionsOperation GetMessageActions() + public GetMessageActionsOperation GetMessageActions() { - EndPoint.GetMessageActionsOperation getMessageActionsOperation = new EndPoint.GetMessageActionsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetMessageActionsOperation getMessageActionsOperation = new GetMessageActionsOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getMessageActionsOperation; } @@ -363,37 +357,37 @@ public EndPoint.GetMessageActionsOperation GetMessageActions() #region "PubNub API Channel Group Methods" - public EndPoint.AddChannelsToChannelGroupOperation AddChannelsToChannelGroup() + public AddChannelsToChannelGroupOperation AddChannelsToChannelGroup() { - EndPoint.AddChannelsToChannelGroupOperation addChannelToChannelGroupOperation = new EndPoint.AddChannelsToChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + AddChannelsToChannelGroupOperation addChannelToChannelGroupOperation = new AddChannelsToChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); addChannelToChannelGroupOperation.CurrentPubnubInstance(this); return addChannelToChannelGroupOperation; } - public EndPoint.RemoveChannelsFromChannelGroupOperation RemoveChannelsFromChannelGroup() + public RemoveChannelsFromChannelGroupOperation RemoveChannelsFromChannelGroup() { - EndPoint.RemoveChannelsFromChannelGroupOperation removeChannelsFromChannelGroupOperation = new EndPoint.RemoveChannelsFromChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + RemoveChannelsFromChannelGroupOperation removeChannelsFromChannelGroupOperation = new RemoveChannelsFromChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); removeChannelsFromChannelGroupOperation.CurrentPubnubInstance(this); return removeChannelsFromChannelGroupOperation; } - public EndPoint.DeleteChannelGroupOperation DeleteChannelGroup() + public DeleteChannelGroupOperation DeleteChannelGroup() { - EndPoint.DeleteChannelGroupOperation deleteChannelGroupOperation = new EndPoint.DeleteChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + DeleteChannelGroupOperation deleteChannelGroupOperation = new DeleteChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); deleteChannelGroupOperation.CurrentPubnubInstance(this); return deleteChannelGroupOperation; } - public EndPoint.ListChannelsForChannelGroupOperation ListChannelsForChannelGroup() + public ListChannelsForChannelGroupOperation ListChannelsForChannelGroup() { - EndPoint.ListChannelsForChannelGroupOperation listChannelsForChannelGroupOperation = new EndPoint.ListChannelsForChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + ListChannelsForChannelGroupOperation listChannelsForChannelGroupOperation = new ListChannelsForChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); listChannelsForChannelGroupOperation.CurrentPubnubInstance(this); return listChannelsForChannelGroupOperation; } - public EndPoint.ListAllChannelGroupOperation ListChannelGroups() + public ListAllChannelGroupOperation ListChannelGroups() { - EndPoint.ListAllChannelGroupOperation listAllChannelGroupOperation = new EndPoint.ListAllChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + ListAllChannelGroupOperation listAllChannelGroupOperation = new ListAllChannelGroupOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); listAllChannelGroupOperation.CurrentPubnubInstance(this); return listAllChannelGroupOperation; } @@ -409,7 +403,7 @@ public bool AddListener(SubscribeCallback listener) { if (listenerManager == null) { - listenerManager = new EndPoint.ListenerManager(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + listenerManager = new ListenerManager(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); } return listenerManager.AddListener(listener); } @@ -426,58 +420,58 @@ public bool RemoveListener(SubscribeCallback listener) } #endregion - public EndPoint.SendFileOperation SendFile() + public SendFileOperation SendFile() { - EndPoint.SendFileOperation uploadFileOperation = new EndPoint.SendFileOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + SendFileOperation uploadFileOperation = new SendFileOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return uploadFileOperation; } - public EndPoint.GetFileUrlOperation GetFileUrl() + public GetFileUrlOperation GetFileUrl() { - EndPoint.GetFileUrlOperation getFileUrlOperation = new EndPoint.GetFileUrlOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + GetFileUrlOperation getFileUrlOperation = new GetFileUrlOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return getFileUrlOperation; } - public EndPoint.DownloadFileOperation DownloadFile() + public DownloadFileOperation DownloadFile() { - EndPoint.DownloadFileOperation downloadFileOperation = new EndPoint.DownloadFileOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + DownloadFileOperation downloadFileOperation = new DownloadFileOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return downloadFileOperation; } - public EndPoint.ListFilesOperation ListFiles() + public ListFilesOperation ListFiles() { - EndPoint.ListFilesOperation listFilesOperation = new EndPoint.ListFilesOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + ListFilesOperation listFilesOperation = new ListFilesOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return listFilesOperation; } - public EndPoint.DeleteFileOperation DeleteFile() + public DeleteFileOperation DeleteFile() { - EndPoint.DeleteFileOperation deleteFileOperation = new EndPoint.DeleteFileOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + DeleteFileOperation deleteFileOperation = new DeleteFileOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return deleteFileOperation; } - public EndPoint.PublishFileMessageOperation PublishFileMessage() + public PublishFileMessageOperation PublishFileMessage() { - EndPoint.PublishFileMessageOperation publshFileMessageOperation = new EndPoint.PublishFileMessageOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + PublishFileMessageOperation publshFileMessageOperation = new PublishFileMessageOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); return publshFileMessageOperation; } #region "PubNub API Other Methods" public void TerminateCurrentSubscriberRequest() { - EndPoint.OtherOperation endpoint = new EndPoint.OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + OtherOperation endpoint = new OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); endpoint.CurrentPubnubInstance(this); endpoint.TerminateCurrentSubscriberRequest(); } public void EnableMachineSleepModeForTestingOnly() { - EndPoint.OtherOperation.EnableMachineSleepModeForTestingOnly(); + PubnubCoreBase.EnableMachineSleepModeForTestingOnly(); } public void DisableMachineSleepModeForTestingOnly() { - EndPoint.OtherOperation.DisableMachineSleepModeForTestingOnly(); + PubnubCoreBase.DisableMachineSleepModeForTestingOnly(); } public Guid GenerateGuid() @@ -501,43 +495,43 @@ public void ChangeUserId(UserId newUserId) } throw new MissingMemberException("UserId cannot be null/empty"); } - EndPoint.OtherOperation endPoint = new EndPoint.OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + PNConfig.UserId = newUserId; + OtherOperation endPoint = new OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); endPoint.CurrentPubnubInstance(this); - endPoint.ChangeUserId(newUserId); } public static long TranslateDateTimeToPubnubUnixNanoSeconds(DateTime dotNetUTCDateTime) { - return EndPoint.OtherOperation.TranslateDateTimeToPubnubUnixNanoSeconds(dotNetUTCDateTime); + return OtherOperation.TranslateDateTimeToPubnubUnixNanoSeconds(dotNetUTCDateTime); } public static DateTime TranslatePubnubUnixNanoSecondsToDateTime(long unixNanoSecondTime) { - return EndPoint.OtherOperation.TranslatePubnubUnixNanoSecondsToDateTime(unixNanoSecondTime); + return OtherOperation.TranslatePubnubUnixNanoSecondsToDateTime(unixNanoSecondTime); } public static DateTime TranslatePubnubUnixNanoSecondsToDateTime(string unixNanoSecondTime) { - return EndPoint.OtherOperation.TranslatePubnubUnixNanoSecondsToDateTime(unixNanoSecondTime); + return OtherOperation.TranslatePubnubUnixNanoSecondsToDateTime(unixNanoSecondTime); } public UserId GetCurrentUserId() { - EndPoint.OtherOperation endPoint = new EndPoint.OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, telemetryManager, tokenManager, this); + OtherOperation endPoint = new OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); endPoint.CurrentPubnubInstance(this); return endPoint.GetCurrentUserId(); } public List GetSubscribedChannels() { - EndPoint.OtherOperation endpoint = new EndPoint.OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + OtherOperation endpoint = new OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); endpoint.CurrentPubnubInstance(this); return endpoint.GetSubscribedChannels(); } public List GetSubscribedChannelGroups() { - EndPoint.OtherOperation endpoint = new EndPoint.OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + OtherOperation endpoint = new OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); endpoint.CurrentPubnubInstance(this); return endpoint.GetSubscribedChannelGroups(); } @@ -545,7 +539,7 @@ public List GetSubscribedChannelGroups() public void Destroy() { savedSubscribeOperation = null; - EndPoint.OtherOperation endpoint = new EndPoint.OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, null, tokenManager, this); + OtherOperation endpoint = new OtherOperation(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, JsonPluggableLibrary, pubnubUnitTest, pubnubLog, tokenManager, this); endpoint.CurrentPubnubInstance(this); endpoint.EndPendingRequests(); } @@ -601,8 +595,8 @@ public bool Reconnect() }); } } else { - if (savedSubscribeOperation is EndPoint.SubscribeOperation) { - EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; + if (savedSubscribeOperation is SubscribeOperation) { + SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as SubscribeOperation; if (subscibeOperationInstance != null) { ret = subscibeOperationInstance.Retry(true, false); } @@ -638,9 +632,9 @@ public bool Reconnect(bool resetSubscribeTimetoken) } else { - if (savedSubscribeOperation is EndPoint.SubscribeOperation) + if (savedSubscribeOperation is SubscribeOperation) { - EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; + SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as SubscribeOperation; if (subscibeOperationInstance != null) { ret = subscibeOperationInstance.Retry(true, resetSubscribeTimetoken); @@ -668,9 +662,9 @@ public bool Disconnect() } else { - if (savedSubscribeOperation is EndPoint.SubscribeOperation) + if (savedSubscribeOperation is SubscribeOperation) { - EndPoint.SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as EndPoint.SubscribeOperation; + SubscribeOperation subscibeOperationInstance = savedSubscribeOperation as SubscribeOperation; if (subscibeOperationInstance != null) { ret = subscibeOperationInstance.Retry(false); @@ -813,8 +807,7 @@ public void EncryptFile(string sourceFile, string destinationFile, string cipher { throw new ArgumentException("sourceFile is not valid"); } - -#if !NETSTANDARD10 && !NETSTANDARD11 + bool validSource = System.IO.File.Exists(sourceFile); if (!validSource) { @@ -829,9 +822,6 @@ public void EncryptFile(string sourceFile, string destinationFile, string cipher byte[] inputBytes = System.IO.File.ReadAllBytes(sourceFile); byte[] outputBytes = EncryptFile(inputBytes, cipherKey); System.IO.File.WriteAllBytes(destinationFile, outputBytes); -#else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); -#endif } public byte[] DecryptFile(byte[] inputBytes) @@ -868,7 +858,6 @@ public void DecryptFile(string sourceFile, string destinationFile) { throw new ArgumentException("CryptoModule missing"); } - #if !NETSTANDARD10 && !NETSTANDARD11 bool validSource = System.IO.File.Exists(sourceFile); if (!validSource) { @@ -883,9 +872,6 @@ public void DecryptFile(string sourceFile, string destinationFile) byte[] inputBytes = System.IO.File.ReadAllBytes(sourceFile); byte[] outputBytes = DecryptFile(inputBytes); System.IO.File.WriteAllBytes(destinationFile, outputBytes); - #else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); - #endif } else { @@ -908,7 +894,6 @@ public void DecryptFile(string sourceFile, string destinationFile, string cipher { throw new ArgumentException("inputFile is not valid"); } -#if !NETSTANDARD10 && !NETSTANDARD11 bool validSource = System.IO.File.Exists(sourceFile); if (!validSource) { @@ -923,40 +908,21 @@ public void DecryptFile(string sourceFile, string destinationFile, string cipher byte[] inputBytes = System.IO.File.ReadAllBytes(sourceFile); byte[] outputBytes = DecryptFile(inputBytes, cipherKey); System.IO.File.WriteAllBytes(destinationFile, outputBytes); -#else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); -#endif } #endregion #region "Properties" public IPubnubUnitTest PubnubUnitTest { - get - { - return pubnubUnitTest; - } + get => pubnubUnitTest; set { pubnubUnitTest = value; - if (pubnubUnitTest != null) - { - Version = pubnubUnitTest.SdkVersion; - } - else - { - Version = savedSdkVerion; - } + Version = pubnubUnitTest != null ? pubnubUnitTest.SdkVersion : savedSdkVerion; } } - public PNConfiguration PNConfig - { - get - { - return pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null; - } - } + public PNConfiguration PNConfig => pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null; public IJsonPluggableLibrary JsonPluggableLibrary { get; internal set; } @@ -967,7 +933,7 @@ public void SetJsonPluggableLibrary(IJsonPluggableLibrary customJson) public static string Version { get; private set; } - + internal readonly ITransportMiddleware transportMiddleware; public string InstanceId { get; private set; } @@ -1002,17 +968,11 @@ public Pubnub(PNConfiguration config) PNPlatform.Print(config, pubnubLog); } - if (config.EnableTelemetry) - { - telemetryManager = new EndPoint.TelemetryManager(pubnubConfig[InstanceId], pubnubLog); - } CheckAndInitializeEmptyStringValues(config); - tokenManager = new EndPoint.TokenManager(pubnubConfig[InstanceId], JsonPluggableLibrary, pubnubLog, this.InstanceId); + tokenManager = new TokenManager(pubnubConfig[InstanceId], JsonPluggableLibrary, pubnubLog, InstanceId); - //Initialize JsonPluggableLibrary JsonPluggableLibrary = new NewtonsoftJsonDotNet(config, pubnubLog); - //Check PresenceTimeout if (config.PresenceTimeout < 20) { config.PresenceTimeout = 20; @@ -1021,13 +981,11 @@ public Pubnub(PNConfiguration config) LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, WARNING: The PresenceTimeout cannot be less than 20, defaulting the value to 20. Please update the settings in your code.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); } } - - //Check required UserId CheckRequiredUserId(config); eventEmitter = new EventEmitter(pubnubConfig.ContainsKey(InstanceId) ? pubnubConfig[InstanceId] : null, subscribeCallbackListenerList, JsonPluggableLibrary, tokenManager, pubnubLog, this); - //Check CryptoModule usage CheckCryptoModuleUsageForLogging(config); - + IHttpClientService httpClientService = new HttpClientService(config.Proxy); + transportMiddleware = new Middleware(httpClientService,config, this, tokenManager); } #if UNITY @@ -1047,8 +1005,7 @@ private void CheckRequiredUserId(PNConfiguration config) } throw new MissingMemberException("PNConfiguration.UserId is required to use the SDK"); } - - //Set flag to false + config.ResetUuidSetFromConstructor(); } private void CheckCryptoModuleUsageForLogging(PNConfiguration config) diff --git a/src/Api/PubnubApi/PubnubApi.csproj b/src/Api/PubnubApi/PubnubApi.csproj index 4ac474b47..2703e9eee 100644 --- a/src/Api/PubnubApi/PubnubApi.csproj +++ b/src/Api/PubnubApi/PubnubApi.csproj @@ -1,7 +1,7 @@  - net35;net40;net45;net461;net48 + net60 latest True pubnub.snk @@ -59,6 +59,10 @@ 0436; + + + + @@ -134,4 +138,8 @@ + + + + diff --git a/src/Api/PubnubApi/PubnubCoreBase.cs b/src/Api/PubnubApi/PubnubCoreBase.cs index 625cc4369..b1736de32 100644 --- a/src/Api/PubnubApi/PubnubCoreBase.cs +++ b/src/Api/PubnubApi/PubnubCoreBase.cs @@ -1,27 +1,18 @@ -//Build Date: April 13, 2017 -#region "Header" +#region "Header" #if (__MonoCS__) #define TRACE #endif using System; using System.Text; -using System.Net; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; +using System.Diagnostics; using System.Threading; using System.Globalization; using System.Linq; -using System.Threading.Tasks; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 -using System.Net.Http; -using System.Net.Http.Headers; -#endif -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; +using System.Collections.Concurrent; #endregion namespace PubnubApi @@ -33,40 +24,41 @@ public abstract class PubnubCoreBase protected static bool OverrideTcpKeepAlive { get; set; } = true; protected static System.Threading.Timer PresenceHeartbeatTimer { get; set; } protected static bool PubnetSystemActive { get; set; } = true; - protected Collection PushRemoteImageDomainUri { get; set; } = new Collection(); protected static int ConnectionErrors { get; set; } #endregion private const int MINEXPONENTIALBACKOFF = 1; private const int MAXEXPONENTIALBACKOFF = 32; private const int INTERVAL = 3; - - private static IPubnubHttp pubnubHttp; + private static ConcurrentDictionary pubnubConfig { get; } = new ConcurrentDictionary(); private static IJsonPluggableLibrary jsonLib; private static IPubnubUnitTest unitTest; private static ConcurrentDictionary pubnubLog { get; } = new ConcurrentDictionary(); - private static EndPoint.TelemetryManager pubnubTelemetryMgr; protected static ConcurrentDictionary PubnubTokenMgrCollection { get; } = new ConcurrentDictionary(); private static EndPoint.DuplicationManager pubnubSubscribeDuplicationManager { get; set; } -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - private static HttpClient httpClientSubscribe { get; set; } - private static HttpClient httpClientNonsubscribe { get; set; } - private static HttpClient httpClientNetworkStatus { get; set; } - private static PubnubHttpClientHandler pubnubHttpClientHandler { get; set; } -#endif private bool clientNetworkStatusInternetStatus = true; + protected static ConcurrentDictionary OngoingSubscriptionCancellationTokenSources { get; } = new(); protected static ConcurrentDictionary SubscribeDisconnected { get; set; } = new ConcurrentDictionary(); protected Pubnub PubnubInstance { get; set; } + protected static ConcurrentDictionary> SubscriptionChannels + { + get; + } = new(); + + protected static ConcurrentDictionary> SubscriptionChannelGroups + { + get; + } = new(); protected static ConcurrentDictionary UserIdChanged { get; set; } = new ConcurrentDictionary(); protected static ConcurrentDictionary CurrentUserId { get; set; } = new ConcurrentDictionary(); - protected static ConcurrentDictionary LastSubscribeTimetoken { get; set; } = new ConcurrentDictionary(); - protected static ConcurrentDictionary LastSubscribeRegion { get; set; } = new ConcurrentDictionary(); + protected static ConcurrentDictionary LastSubscribeTimetoken { get; } = new(); + protected static ConcurrentDictionary LastSubscribeRegion { get; } = new(); protected static int PubnubNetworkTcpCheckIntervalInSeconds { get; set; } = 3; private static int PubnubLocalHeartbeatCheckIntervalInSeconds { get; set; } = 30; @@ -101,11 +93,11 @@ protected static ConcurrentDictionary>(); - protected static ConcurrentDictionary> ChannelRequest + protected static ConcurrentDictionary> ChannelRequest { get; set; - } = new ConcurrentDictionary>(); + } = new ConcurrentDictionary>(); protected static ConcurrentDictionary> ChannelInternetStatus { @@ -148,8 +140,8 @@ protected static ConcurrentDictionary SubscribeRequestTracker get; set; } = new ConcurrentDictionary(); - - protected PubnubCoreBase(PNConfiguration pubnubConfiguation, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnitTest, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) + + protected PubnubCoreBase(PNConfiguration pubnubConfiguation, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnitTest, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) { if (pubnubConfiguation == null) { @@ -158,15 +150,15 @@ protected PubnubCoreBase(PNConfiguration pubnubConfiguation, IJsonPluggableLibra if (jsonPluggableLibrary == null) { - InternalConstructor(pubnubConfiguation, new NewtonsoftJsonDotNet(pubnubConfiguation,log), pubnubUnitTest, log, telemetryManager, tokenManager, instance); + InternalConstructor(pubnubConfiguation, new NewtonsoftJsonDotNet(pubnubConfiguation,log), pubnubUnitTest, log, tokenManager, instance); } else { - InternalConstructor(pubnubConfiguation, jsonPluggableLibrary, pubnubUnitTest, log, telemetryManager, tokenManager, instance); + InternalConstructor(pubnubConfiguation, jsonPluggableLibrary, pubnubUnitTest, log, tokenManager, instance); } } - private void InternalConstructor(PNConfiguration pubnubConfiguation, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnitTest, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, EndPoint.TokenManager tokenManager, Pubnub instance) + private void InternalConstructor(PNConfiguration pubnubConfiguation, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnitTest, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) { PubnubInstance = instance; pubnubConfig.AddOrUpdate(instance.InstanceId, pubnubConfiguation, (k,o)=> pubnubConfiguation); @@ -174,60 +166,9 @@ private void InternalConstructor(PNConfiguration pubnubConfiguation, IJsonPlugga unitTest = pubnubUnitTest; pubnubLog.AddOrUpdate(instance.InstanceId, log, (k, o) => log); PubnubTokenMgrCollection.AddOrUpdate(instance.InstanceId, tokenManager, (k,o)=> tokenManager); - pubnubTelemetryMgr = telemetryManager; pubnubSubscribeDuplicationManager = new EndPoint.DuplicationManager(pubnubConfiguation, jsonPluggableLibrary, log); CurrentUserId.AddOrUpdate(instance.InstanceId, pubnubConfiguation.UserId, (k,o) => pubnubConfiguation.UserId); - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (httpClientSubscribe == null) - { - if (pubnubConfiguation.Proxy != null) - { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - if (httpClientHandler.SupportsProxy) - { - httpClientHandler.Proxy = pubnubConfiguation.Proxy; - httpClientHandler.UseProxy = true; - } - pubnubHttpClientHandler = new PubnubHttpClientHandler("PubnubHttpClientHandler", httpClientHandler, pubnubConfiguation, jsonLib, unitTest, log); - httpClientSubscribe = new HttpClient(pubnubHttpClientHandler); - } - else - { - httpClientSubscribe = new HttpClient(); - } - httpClientSubscribe.DefaultRequestHeaders.Accept.Clear(); - httpClientSubscribe.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - httpClientSubscribe.Timeout = TimeSpan.FromSeconds(pubnubConfiguation.SubscribeTimeout); - } - if (httpClientNonsubscribe == null) - { - if (pubnubConfiguation.Proxy != null) - { - HttpClientHandler httpClientHandler = new HttpClientHandler(); - if (httpClientHandler.SupportsProxy) - { - httpClientHandler.Proxy = pubnubConfiguation.Proxy; - httpClientHandler.UseProxy = true; - } - pubnubHttpClientHandler = new PubnubHttpClientHandler("PubnubHttpClientHandler", httpClientHandler, pubnubConfiguation, jsonLib, unitTest, log); - httpClientNonsubscribe = new HttpClient(pubnubHttpClientHandler); - } - else - { - httpClientNonsubscribe = new HttpClient(); - } - httpClientNonsubscribe.DefaultRequestHeaders.Accept.Clear(); - httpClientNonsubscribe.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - httpClientNonsubscribe.Timeout = TimeSpan.FromSeconds(pubnubConfiguation.NonSubscribeRequestTimeout); - } - pubnubHttp = new PubnubHttp(pubnubConfiguation, jsonLib, log, pubnubTelemetryMgr, httpClientSubscribe, httpClientNonsubscribe); -#else - pubnubHttp = new PubnubHttp(pubnubConfiguation, jsonLib, log, pubnubTelemetryMgr); -#endif - - UpdatePubnubNetworkTcpCheckIntervalInSeconds(); if (pubnubConfiguation.PresenceInterval > 10) { @@ -302,26 +243,11 @@ protected bool CheckInternetConnectionStatus(bool systemActive, PNOperationTy ClientNetworkStatus.JsonLibrary = jsonLib; ClientNetworkStatus.PubnubUnitTest = unitTest; ClientNetworkStatus.PubnubLog = currentLog; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (httpClientNetworkStatus == null) - { - if (currentConfig.Proxy != null && pubnubHttpClientHandler != null) - { - httpClientNetworkStatus = new HttpClient(pubnubHttpClientHandler); - } - else - { - httpClientNetworkStatus = new HttpClient(); - } - httpClientNetworkStatus.DefaultRequestHeaders.Accept.Clear(); - httpClientNetworkStatus.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - httpClientNetworkStatus.Timeout = TimeSpan.FromSeconds(currentConfig.NonSubscribeRequestTimeout); - } - ClientNetworkStatus.RefHttpClient = httpClientNetworkStatus; -#endif + ClientNetworkStatus.PubnubInstance = PubnubInstance; if (!ClientNetworkStatus.IsInternetCheckRunning()) { - clientNetworkStatusInternetStatus = ClientNetworkStatus.CheckInternetStatus(PubnetSystemActive, type, callback, channels, channelGroups); + clientNetworkStatusInternetStatus = ClientNetworkStatus + .CheckInternetStatus(PubnetSystemActive, type, callback, channels, channelGroups); } return clientNetworkStatusInternetStatus; } @@ -352,7 +278,7 @@ protected static long GetTimetokenFromMultiplexResult(List result) } else { - var _ = Int64.TryParse(result[1].ToString(), out jsonTimetoken); + var _ = long.TryParse(result[1].ToString(), out jsonTimetoken); } } @@ -546,7 +472,7 @@ private bool IsTargetForDedup(SubscribeMessage message) return isTargetOfDedup; } - private bool IsZeroTimeTokenRequest(RequestState asyncRequestState, List result) + private bool IsZeroTimeTokenRequest(RequestState requestState, List result) { bool ret = false; PNConfiguration currentConfig = null; @@ -556,21 +482,12 @@ private bool IsZeroTimeTokenRequest(RequestState asyncRequestState, List 0) + if (requestState != null && requestState.ResponseType == PNOperationType.PNSubscribeOperation && requestState.Timetoken == 0 && result != null && result.Count > 0) { List message = GetMessageFromMultiplexResult(result); if (message != null && message.Count == 0) { - IEnumerable newChannels = from channel in MultiChannelSubscribe[PubnubInstance.InstanceId] - where channel.Value == 0 - select channel.Key; - IEnumerable newChannelGroups = from channelGroup in MultiChannelGroupSubscribe[PubnubInstance.InstanceId] - where channelGroup.Value == 0 - select channelGroup.Key; - if ((newChannels != null && newChannels.Any()) || (newChannelGroups != null && newChannelGroups.Any())) - { ret = true; - } } } } @@ -589,7 +506,7 @@ private void ResponseToConnectCallback(PNOperationType type, string[] channel PNConfiguration currentConfig; pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig); StatusBuilder statusBuilder = new StatusBuilder(currentConfig, jsonLib); - PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNConnectedCategory, asyncRequestState, (int)HttpStatusCode.OK, null); + PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNConnectedCategory, asyncRequestState, Constants.HttpRequestSuccessStatusCode, null); //Check callback exists and make sure previous timetoken = 0 if (channels != null && channels.Length > 0) @@ -638,7 +555,7 @@ private void ResponseToUserCallback(List result, PNOperationType type if (messageList.Count >= currentConfig.RequestMessageCountThreshold) { StatusBuilder statusBuilder = new StatusBuilder(currentConfig, jsonLib); - PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNRequestMessageCountExceededCategory, asyncRequestState, (int)HttpStatusCode.OK, null); + PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNRequestMessageCountExceededCategory, asyncRequestState, Constants.HttpRequestSuccessStatusCode, null); Announce(status); } @@ -713,7 +630,7 @@ private void ResponseToUserCallback(List result, PNOperationType type decryptMessage = "**DECRYPT ERROR**"; PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(ex); - PNStatus status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, category, null, (int)HttpStatusCode.NotFound, new PNException(ex)); + PNStatus status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, category, null, Constants.ResourceNotFoundStatusCode, new PNException(ex)); if (!string.IsNullOrEmpty(currentMessageChannel)) { status.AffectedChannels.Add(currentMessageChannel); @@ -836,9 +753,10 @@ private void ResponseToUserCallback(List result, PNOperationType type if (fileObjDic != null && fileObjDic.ContainsKey("id") && fileObjDic.ContainsKey("name")) { fileMessage.File = new PNFile { Id = fileObjDic["id"].ToString(), Name = fileObjDic["name"].ToString() }; - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(currentConfig, jsonLib, unitTest, currentLog, pubnubTelemetryMgr, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - Uri fileUrlRequest = urlBuilder.BuildGetFileUrlOrDeleteReqest("GET", "", fileMessage.Channel, fileMessage.File.Id, fileMessage.File.Name, null, type); - fileMessage.File.Url = fileUrlRequest.ToString(); + PubnubTokenMgrCollection.TryGetValue( + PubnubInstance.InstanceId ?? "", out var tokenManager); + fileMessage.File.Url = UriUtil.GetFileUrl(fileName: fileMessage.File.Name, fileId: fileMessage.File.Id, channel:fileMessage.Channel, + pnConfiguration:currentConfig, pubnub:PubnubInstance, tokenmanager: tokenManager); } } } @@ -945,7 +863,7 @@ private void ResponseToUserCallback(List result, PNOperationType type T userResult = responseBuilder.JsonToObject(result, true); StatusBuilder statusBuilder = new StatusBuilder(currentConfig, jsonLib); - PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNAcknowledgmentCategory, asyncRequestState, (int)HttpStatusCode.OK, null); + PNStatus status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNAcknowledgmentCategory, asyncRequestState,Constants.HttpRequestSuccessStatusCode, null); if (userCallback != null) { @@ -969,7 +887,7 @@ private void ResponseToUserCallback(List result, PNOperationType type PNException ex = null; if (userResult != null && userResult.Status == 200) { - status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNAcknowledgmentCategory, asyncRequestState, (int)HttpStatusCode.OK, null); + status = statusBuilder.CreateStatusResponse(type, PNStatusCategory.PNAcknowledgmentCategory, asyncRequestState, Constants.HttpRequestSuccessStatusCode, null); } else { @@ -1017,14 +935,12 @@ public static void DisableMachineSleepModeForTestingOnly() #endregion -#region "Helpers" - protected string[] GetCurrentSubscriberChannels() { string[] channels = null; - if (MultiChannelSubscribe != null && MultiChannelSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelSubscribe[PubnubInstance.InstanceId].Keys.Count > 0) + if (SubscriptionChannels.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannels[PubnubInstance.InstanceId] != null) { - channels = MultiChannelSubscribe[PubnubInstance.InstanceId].Keys.ToArray(); + channels = SubscriptionChannels[PubnubInstance.InstanceId].Keys.ToArray(); } return channels; @@ -1033,350 +949,14 @@ protected string[] GetCurrentSubscriberChannels() protected string[] GetCurrentSubscriberChannelGroups() { string[] channelGroups = null; - if (MultiChannelGroupSubscribe != null && MultiChannelGroupSubscribe.ContainsKey(PubnubInstance.InstanceId) && MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys.Count > 0) + if (SubscriptionChannelGroups.ContainsKey(PubnubInstance.InstanceId) && SubscriptionChannelGroups[PubnubInstance.InstanceId] != null) { - channelGroups = MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Keys.ToArray(); + channelGroups = SubscriptionChannelGroups[PubnubInstance.InstanceId].Keys.ToArray(); } return channelGroups; } -#endregion - -#region "Build, process and send request" - internal protected async Task> UrlProcessRequest(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest) - { - return await UrlProcessRequest(requestUri, pubnubRequestState, terminateCurrentSubRequest, null).ConfigureAwait(false); - } - -#pragma warning disable - internal protected async Task> UrlProcessRequest(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest, byte[] postOrPatchData) -#pragma warning restore - { - return await UrlProcessRequest(requestUri, pubnubRequestState, terminateCurrentSubRequest, postOrPatchData,"").ConfigureAwait(false); - } - - internal protected async Task> UrlProcessRequest(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest, byte[] postOrPatchData, string contentType) - { - string channel = ""; - PNConfiguration currentConfig; - IPubnubLog currentLog; - - try - { - if (terminateCurrentSubRequest) - { - TerminateCurrentSubscriberRequest(); - } - - if (PubnubInstance == null) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, PubnubInstance is null. Exiting UrlProcessRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return new Tuple("", null); - } - - if (pubnubRequestState != null) - { - channel = (pubnubRequestState.Channels != null && pubnubRequestState.Channels.Length > 0) ? string.Join(",", pubnubRequestState.Channels.OrderBy(x => x).ToArray()) : ","; - - if (ChannelRequest.ContainsKey(PubnubInstance.InstanceId) && !channel.Equals(",", StringComparison.OrdinalIgnoreCase) && !ChannelRequest[PubnubInstance.InstanceId].ContainsKey(channel) && (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation || pubnubRequestState.ResponseType == PNOperationType.Presence)) - { - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, UrlProcessRequest ChannelRequest PubnubInstance.InstanceId Channel NOT matching", DateTime.Now.ToString(CultureInfo.InvariantCulture)), currentConfig.LogVerbosity); - } - return new Tuple("", null); - } - } - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - //do nothing -#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"; - } - request.ContentType = contentType; - - pubnubRequestState.Request = request; - - if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation || pubnubRequestState.ResponseType == PNOperationType.Presence) - { - ChannelRequest[PubnubInstance.InstanceId].AddOrUpdate(channel, pubnubRequestState.Request, (key, oldState) => pubnubRequestState.Request); - } -#endif - - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Request={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri.ToString()), currentConfig.LogVerbosity); - } - - if (pubnubRequestState != null && pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) - { - SubscribeRequestTracker.AddOrUpdate(PubnubInstance.InstanceId, DateTime.Now, (key, oldState) => DateTime.Now); - } - - string jsonString = ""; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubRequestState != null && pubnubRequestState.UsePostMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPOST(requestUri, pubnubRequestState, null, postOrPatchData, contentType).ConfigureAwait(false); - } - else if (pubnubRequestState != null && pubnubRequestState.UsePatchMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPATCH(requestUri, pubnubRequestState, null, postOrPatchData, contentType).ConfigureAwait(false); - } - else - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponse(requestUri, pubnubRequestState, null).ConfigureAwait(false); - } -#else - if (pubnubRequestState != null && pubnubRequestState.UsePostMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPOST(requestUri, pubnubRequestState, request, postOrPatchData, contentType).ConfigureAwait(false); - } - else if (pubnubRequestState != null && pubnubRequestState.UsePatchMethod) - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponseWithPATCH(requestUri, pubnubRequestState, request, postOrPatchData, contentType).ConfigureAwait(false); - } - else - { - jsonString = await pubnubHttp.SendRequestAndGetJsonResponse(requestUri, pubnubRequestState, request).ConfigureAwait(false); - } -#endif - - if (SubscribeDisconnected.ContainsKey(PubnubInstance.InstanceId) && SubscribeDisconnected[PubnubInstance.InstanceId]) - { - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0},Received JSON but SubscribeDisconnected = {1} for request={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonString, requestUri), currentConfig.LogVerbosity); - } - throw new OperationCanceledException("Disconnected"); - } - - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, JSON= {1} for request={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), jsonString, requestUri), currentConfig.LogVerbosity); - } - PNStatus errStatus = GetStatusIfError(pubnubRequestState, jsonString); - if (errStatus == null && pubnubRequestState != null) - { - PNStatus status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(pubnubRequestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, pubnubRequestState, (int)HttpStatusCode.OK, null); - return new Tuple(jsonString, status); - } - else - { - jsonString = ""; - return new Tuple(jsonString, errStatus); - } - } - catch (Exception ex) - { - string errorMessage = ex.Message; - string exceptionMessage = ""; - Exception innerEx = null; - WebException webEx = null; - PNStatus status = null; - - if (ex.InnerException != null) - { - if (ex is WebException) - { - webEx = ex as WebException; - exceptionMessage = webEx.ToString(); - } - else - { - innerEx = ex.InnerException; - exceptionMessage = innerEx.ToString(); - } - } - else - { - innerEx = ex; - exceptionMessage = innerEx.ToString(); - } - - if (exceptionMessage.IndexOf("The request was aborted: The request was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 - && exceptionMessage.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.CurrentCultureIgnoreCase) == -1 - && (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation && exceptionMessage.IndexOf("The operation has timed out", StringComparison.CurrentCultureIgnoreCase) == -1) - && exceptionMessage.IndexOf("A task was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 - && errorMessage.IndexOf("The operation was canceled", StringComparison.CurrentCultureIgnoreCase) == -1) - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(webEx == null ? innerEx : webEx); - if (PubnubInstance != null && pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig)) - { - status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(pubnubRequestState.ResponseType, category, pubnubRequestState, (int)HttpStatusCode.NotFound, new PNException(ex)); - if (pubnubRequestState != null && pubnubRequestState.PubnubCallback != null) - { - pubnubRequestState.PubnubCallback.OnResponse(default(T), status); - } - else - { - Announce(status); - } - } - - if (PubnubInstance != null && pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PubnubBaseCore UrlProcessRequest Exception={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), webEx != null ? webEx.ToString() : exceptionMessage), currentConfig.LogVerbosity); - } - } - - return new Tuple("", status); - } - } - - internal protected async Task> UrlProcessRequestForStream(Uri requestUri, RequestState pubnubRequestState, bool terminateCurrentSubRequest, string contentType) - { - string channel = ""; - PNConfiguration currentConfig; - IPubnubLog currentLog; - - try - { - if (terminateCurrentSubRequest) - { - TerminateCurrentSubscriberRequest(); - } - - if (PubnubInstance == null) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, PubnubInstance is null. Exiting UrlProcessRequest", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return new Tuple(null, null); - } - - if (pubnubRequestState != null) - { - channel = (pubnubRequestState.Channels != null && pubnubRequestState.Channels.Length > 0) ? string.Join(",", pubnubRequestState.Channels.OrderBy(x => x).ToArray()) : ","; - - if (ChannelRequest.ContainsKey(PubnubInstance.InstanceId) && !channel.Equals(",", StringComparison.OrdinalIgnoreCase) && !ChannelRequest[PubnubInstance.InstanceId].ContainsKey(channel) && (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation || pubnubRequestState.ResponseType == PNOperationType.Presence)) - { - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, UrlProcessRequest ChannelRequest PubnubInstance.InstanceId Channel NOT matching", DateTime.Now.ToString(CultureInfo.InvariantCulture)), currentConfig.LogVerbosity); - } - return new Tuple(null, null); - } - } - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - //do nothing -#else - // Create Request - HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri); - - request = pubnubHttp.SetNoCache(request); - request = pubnubHttp.SetProxy(request); - request = pubnubHttp.SetTimeout(pubnubRequestState, request); - if (string.IsNullOrEmpty(contentType)) - { - contentType = "application/json"; - } - request.ContentType = contentType; - - pubnubRequestState.Request = request; - - if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation || pubnubRequestState.ResponseType == PNOperationType.Presence) - { - ChannelRequest[PubnubInstance.InstanceId].AddOrUpdate(channel, pubnubRequestState.Request, (key, oldState) => pubnubRequestState.Request); - } -#endif - - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Request={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri.ToString()), currentConfig.LogVerbosity); - } - - if (pubnubRequestState != null && pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) - { - SubscribeRequestTracker.AddOrUpdate(PubnubInstance.InstanceId, DateTime.Now, (key, oldState) => DateTime.Now); - } - - byte[] streamBytes; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - streamBytes = await pubnubHttp.SendRequestAndGetStreamResponse(requestUri, pubnubRequestState, null).ConfigureAwait(false); -#else - streamBytes = await pubnubHttp.SendRequestAndGetStreamResponse(requestUri, pubnubRequestState, request).ConfigureAwait(false); -#endif - if (streamBytes != null && pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length= {1} for request={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), streamBytes.Length, requestUri), currentConfig.LogVerbosity); - } - PNStatus errStatus = GetStatusIfError(pubnubRequestState, null); - if (errStatus == null && pubnubRequestState != null) - { - PNStatus status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(pubnubRequestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, pubnubRequestState, (int)HttpStatusCode.OK, null); - return new Tuple(streamBytes, status); - } - else - { - return new Tuple(null, errStatus); - } - } - catch (Exception ex) - { - string errorMessage = ex.Message; - string exceptionMessage = ""; - Exception innerEx = null; - WebException webEx = null; - PNStatus status = null; - - if (ex.InnerException != null) - { - if (ex is WebException) - { - webEx = ex as WebException; - exceptionMessage = webEx.ToString(); - } - else - { - innerEx = ex.InnerException; - exceptionMessage = innerEx.ToString(); - } - } - else - { - innerEx = ex; - exceptionMessage = innerEx.ToString(); - } - if (exceptionMessage.IndexOf("The request was aborted: The request was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 - && exceptionMessage.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.CurrentCultureIgnoreCase) == -1 - && (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation && exceptionMessage.IndexOf("The operation has timed out", StringComparison.CurrentCultureIgnoreCase) == -1) - && exceptionMessage.IndexOf("A task was canceled", StringComparison.CurrentCultureIgnoreCase) == -1 - && errorMessage.IndexOf("The operation was canceled", StringComparison.CurrentCultureIgnoreCase) == -1) - { - PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(webEx == null ? innerEx : webEx); - if (PubnubInstance != null && pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig)) - { - status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(pubnubRequestState.ResponseType, category, pubnubRequestState, (int)HttpStatusCode.NotFound, new PNException(ex)); - if (pubnubRequestState != null && pubnubRequestState.PubnubCallback != null) - { - pubnubRequestState.PubnubCallback.OnResponse(default(T), status); - } - else - { - Announce(status); - } - } - - if (PubnubInstance != null && pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PubnubBaseCore UrlProcessRequest Exception={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), webEx != null ? webEx.ToString() : exceptionMessage), currentConfig.LogVerbosity); - } - } - - return new Tuple(null, status); - } - } internal protected List ProcessJsonResponse(RequestState asyncRequestState, string jsonString) { List result = new List(); @@ -1403,7 +983,7 @@ internal protected List ProcessJsonResponse(RequestState asyncRequ return result; } - private PNStatus GetStatusIfError(RequestState asyncRequestState, string jsonString) + protected PNStatus GetStatusIfError(RequestState asyncRequestState, string jsonString) { PNStatus status = null; if (string.IsNullOrEmpty(jsonString)) { return status; } @@ -1422,7 +1002,7 @@ private PNStatus GetStatusIfError(RequestState asyncRequestState, string j { if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig)) { - status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, PNStatusCategory.PNUnknownCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); + status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, PNStatusCategory.PNUnknownCategory, asyncRequestState, Constants.ResourceNotFoundStatusCode, new PNException(jsonString)); } } else if (deserializeStatus.Count >= 1 && deserializeStatus.ContainsKey("error") && deserializeStatus.ContainsKey("status") && Int32.TryParse(deserializeStatus["status"].ToString(), out statusCode) && statusCode > 0) @@ -1485,7 +1065,7 @@ private PNStatus GetStatusIfError(RequestState asyncRequestState, string j { if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig)) { - status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); + status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, Constants.ResourceNotFoundStatusCode, new PNException(jsonString)); } } else if (jsonString.ToLowerInvariant().TrimStart().IndexOf("(RequestState asyncRequestState, string j { if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig)) { - status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, PNStatusCategory.PNNetworkIssuesCategory, asyncRequestState, (int)HttpStatusCode.NotFound, new PNException(jsonString)); + string message = ExtractValue(jsonString, "", ""); + string proposedSize = ExtractValue(jsonString, "", ""); + var errorMessage = string.IsNullOrEmpty((message)) ? jsonString : $"File upload failed: {message}"; + errorMessage+= string.IsNullOrEmpty(proposedSize)?"":$", maximum allowed size is {proposedSize}"; + status = new StatusBuilder(currentConfig, jsonLib).CreateStatusResponse(type, PNStatusCategory.PNUnknownCategory, asyncRequestState, Constants.HttpRequestEntityTooLargeStatusCode, new PNException(errorMessage)); } } return status; } + + private static string ExtractValue(string input, string startTag, string endTag) + { + int startIndex = input.IndexOf(startTag) + startTag.Length; + int endIndex = input.IndexOf(endTag, startIndex); + if (startIndex < 0 || endIndex < 0) + { + return null; + } + return input.Substring(startIndex, endIndex - startIndex).Trim(); + } protected List WrapResultBasedOnResponseType(PNOperationType type, string jsonString, string[] channels, string[] channelGroups, bool reconnect, long lastTimetoken, PNCallback callback) { List result = new List(); @@ -1524,11 +1119,11 @@ protected List WrapResultBasedOnResponseType(PNOperationType type, st { case PNOperationType.PNSubscribeOperation: case PNOperationType.Presence: - if (result.Count == 3 && result[0] is object[] && (result[0] as object[]).Length == 0 && result[2].ToString() == "") + if (result.Count == 3 && result[0] is object[] && ((object[])result[0]).Length == 0 && result[2].ToString() == "") { result.RemoveAt(2); } - if (result.Count == 4 && result[0] is object[] && (result[0] as object[]).Length == 0 && result[2].ToString() == "" && result[3].ToString() == "") + if (result.Count == 4 && result[0] is object[] && ((object[])result[0]).Length == 0 && result[2].ToString() == "" && result[3].ToString() == "") { result.RemoveRange(2, 2); } @@ -1539,51 +1134,8 @@ protected List WrapResultBasedOnResponseType(PNOperationType type, st LastSubscribeRegion[PubnubInstance.InstanceId] = receivedRegion; long receivedTimetoken = GetTimetokenFromMultiplexResult(result); - - long minimumTimetoken1 = (MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelSubscribe[PubnubInstance.InstanceId].Min(token => token.Value) : 0; - long minimumTimetoken2 = (MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Min(token => token.Value) : 0; - long minimumTimetoken = Math.Max(minimumTimetoken1, minimumTimetoken2); - - long maximumTimetoken1 = (MultiChannelSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelSubscribe[PubnubInstance.InstanceId].Max(token => token.Value) : 0; - long maximumTimetoken2 = (MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Count > 0) ? MultiChannelGroupSubscribe[PubnubInstance.InstanceId].Max(token => token.Value) : 0; - long maximumTimetoken = Math.Max(maximumTimetoken1, maximumTimetoken2); - - if (minimumTimetoken == 0 || lastTimetoken == 0) - { - if (maximumTimetoken == 0) - { - LastSubscribeTimetoken[PubnubInstance.InstanceId] = receivedTimetoken; - } - else - { - if (!enableResumeOnReconnect) - { - LastSubscribeTimetoken[PubnubInstance.InstanceId] = receivedTimetoken; - } - else - { - //do nothing. keep last subscribe token - } - } - } - else - { - if (reconnect) - { - if (enableResumeOnReconnect) - { - //do nothing. keep last subscribe token - } - else - { - LastSubscribeTimetoken[PubnubInstance.InstanceId] = receivedTimetoken; - } - } - else - { - LastSubscribeTimetoken[PubnubInstance.InstanceId] = receivedTimetoken; - } - } + if (receivedTimetoken != 0) + LastSubscribeTimetoken[PubnubInstance.InstanceId] = receivedTimetoken; break; case PNOperationType.PNHeartbeatOperation: Dictionary heartbeatadictionary = jsonLib.DeserializeToDictionaryOfObject(jsonString); @@ -1695,17 +1247,20 @@ protected List WrapResultBasedOnResponseType(PNOperationType type, st case PNOperationType.PNRemoveGroupOperation: case PNOperationType.ChannelGroupGet: case PNOperationType.ChannelGroupAllGet: - Dictionary channelGroupDictionary = jsonLib.DeserializeToDictionaryOfObject(jsonString); + Dictionary channelGroupDictionary = + jsonLib.DeserializeToDictionaryOfObject(jsonString); result = new List(); result.Add(channelGroupDictionary); if (multiChannelGroup != "") { result.Add(multiChannelGroup); } + if (multiChannel != "") { result.Add(multiChannel); } + break; default: break; @@ -1713,18 +1268,17 @@ protected List WrapResultBasedOnResponseType(PNOperationType type, st //switch stmt end } } - catch { /* ignore */ } + catch (Exception e) + { + Debug.WriteLine(e); + } return result; } protected void ProcessResponseCallbacks(List result, RequestState asyncRequestState) { - bool callbackAvailable = false; - if (result != null && result.Count >= 1 && (asyncRequestState.PubnubCallback != null || SubscribeCallbackListenerList.Count >= 1)) - { - callbackAvailable = true; - } + bool callbackAvailable = result != null && result.Count >= 1 && (asyncRequestState.PubnubCallback != null || SubscribeCallbackListenerList.Count >= 1); if (callbackAvailable) { bool zeroTimeTokenRequest = IsZeroTimeTokenRequest(asyncRequestState, result); @@ -1739,8 +1293,6 @@ protected void ProcessResponseCallbacks(List result, RequestState } } -#endregion - protected string BuildJsonUserState(string channel, string channelGroup, bool local) { Dictionary channelUserStateDictionary = null; @@ -1882,53 +1434,6 @@ protected string BuildJsonUserState(string[] channels, string[] channelGroups, b #region "Terminate requests and Timers" - protected void TerminatePendingWebRequest() - { - TerminatePendingWebRequest(null); - } - - protected void TerminatePendingWebRequest(RequestState state) - { - PNConfiguration currentConfig; - IPubnubLog currentLog; - if (state != null && state.Request != null) - { - try - { - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, TerminatePendingWebRequest - {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), state.Request.RequestUri.ToString()), currentConfig.LogVerbosity); - } - state.Request.Abort(); - } - catch { /* ignore */ } - } - else - { - ICollection keyCollection = ChannelRequest[PubnubInstance.InstanceId].Keys; - foreach (string key in keyCollection.ToList()) - { - HttpWebRequest currentRequest; - if (ChannelRequest[PubnubInstance.InstanceId].TryGetValue(key, out currentRequest) && currentRequest != null) - { - TerminatePendingWebRequest(currentRequest); - } - } - } - } - - protected static void TerminatePendingWebRequest(HttpWebRequest request) - { - if (request != null) - { - try - { - request.Abort(); - } - catch { /* ignore */ } - } - } - private void RemoveChannelDictionary() { RemoveChannelDictionary(null); @@ -1939,13 +1444,13 @@ private void RemoveChannelDictionary(RequestState state) PNConfiguration currentConfig; IPubnubLog currentLog; - if (state != null && state.Request != null) + if (state != null && state.RequestCancellationTokenSource != null) { string channel = (state.Channels != null) ? string.Join(",", state.Channels.OrderBy(x => x).ToArray()) : ","; if (ChannelRequest[PubnubInstance.InstanceId].ContainsKey(channel)) { - HttpWebRequest removedRequest; + CancellationTokenSource removedRequest; bool removeKey = ChannelRequest[PubnubInstance.InstanceId].TryRemove(channel, out removedRequest); if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) { @@ -1968,7 +1473,7 @@ private void RemoveChannelDictionary(RequestState state) List keysList = keyCollection.ToList(); foreach (string key in keysList) { - HttpWebRequest currentRequest; + CancellationTokenSource currentRequest; if (ChannelRequest[PubnubInstance.InstanceId].TryGetValue(key, out currentRequest) && currentRequest != null) { bool removeKey = ChannelRequest[PubnubInstance.InstanceId].TryRemove(key, out currentRequest); @@ -2109,14 +1614,6 @@ protected static void TerminatePresenceHeartbeatTimer() } } - protected static void TerminateTelemetry() - { - if (pubnubTelemetryMgr != null) - { - pubnubTelemetryMgr.Destroy(); - } - } - protected void TerminateTokenManagerCollection() { if (PubnubTokenMgrCollection != null && PubnubTokenMgrCollection.Count > 0) @@ -2306,11 +1803,9 @@ internal void EndPendingRequests() } RemoveChannelDictionary(); - TerminatePendingWebRequest(); TerminateReconnectTimer(); RemoveUserState(); - PubnubCoreBase.TerminatePresenceHeartbeatTimer(); - TerminateTelemetry(); + TerminatePresenceHeartbeatTimer(); TerminateDedupeManager(); TerminateTokenManagerCollection(); @@ -2343,81 +1838,25 @@ internal void EndPendingRequests() { ChannelGroupUserState[PubnubInstance.InstanceId].Clear(); } - - if (MultiChannelSubscribe.Count > 0 && !MultiChannelSubscribe.Where(t => t.Value.Keys.Count > 0).Any() - && MultiChannelGroupSubscribe.Count > 0 && !MultiChannelGroupSubscribe.Where(t => t.Value.Keys.Count > 0).Any()) - { - RemoveHttpClients(); - } + PubnubInstance = null; } - - internal static void RemoveHttpClients() - { - //Conditionalmethod logic -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (httpClientNetworkStatus != null) - { - try{ - httpClientNetworkStatus.CancelPendingRequests(); - httpClientNetworkStatus.Dispose(); - httpClientNetworkStatus = null; - } - catch { /* ignore */ } - } - if (httpClientSubscribe != null) - { - try{ - httpClientSubscribe.CancelPendingRequests(); - httpClientSubscribe.Dispose(); - httpClientSubscribe = null; - } - catch { /* ignore */ } - } - if (httpClientNonsubscribe != null) - { - try{ - httpClientNonsubscribe.CancelPendingRequests(); - httpClientNonsubscribe.Dispose(); - httpClientNonsubscribe = null; - } - catch { /* ignore */ } - } -#endif - } internal void TerminateCurrentSubscriberRequest() { - string[] channels = GetCurrentSubscriberChannels(); - if (channels != null) + if (OngoingSubscriptionCancellationTokenSources.ContainsKey(PubnubInstance.InstanceId) + && OngoingSubscriptionCancellationTokenSources[PubnubInstance.InstanceId] is not null) { - string multiChannel = (channels.Length > 0) ? string.Join(",", channels.OrderBy(x => x).ToArray()) : ","; - HttpWebRequest request; - if (ChannelRequest[PubnubInstance.InstanceId].ContainsKey(multiChannel) && ChannelRequest[PubnubInstance.InstanceId].TryGetValue(multiChannel, out request) && request != null) - { - PNConfiguration currentConfig; - IPubnubLog currentLog; - if (pubnubConfig.TryGetValue(PubnubInstance.InstanceId, out currentConfig) && pubnubLog.TryGetValue(PubnubInstance.InstanceId, out currentLog)) - { - LoggingMethod.WriteToLog(currentLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} TerminateCurrentSubsciberRequest {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), request.RequestUri.ToString()), currentConfig.LogVerbosity); - } - try - { - request.Abort(); - } - catch { /* ignore */ } + var cts = OngoingSubscriptionCancellationTokenSources[PubnubInstance.InstanceId]; + try { + cts.Cancel(); + cts.Dispose(); + OngoingSubscriptionCancellationTokenSources[PubnubInstance.InstanceId] = null; } - } -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (httpClientSubscribe != null) - { - try - { - httpClientSubscribe.CancelPendingRequests(); + catch { + // ignored } - catch { /* ignore */ } } -#endif } #endregion @@ -2511,7 +1950,7 @@ internal void InitializeDefaultVariableObjectStates() { if (!ChannelRequest.ContainsKey(PubnubInstance.InstanceId)) { - ChannelRequest.GetOrAdd(PubnubInstance.InstanceId, new ConcurrentDictionary()); + ChannelRequest.GetOrAdd(PubnubInstance.InstanceId, new ConcurrentDictionary()); } if (!ChannelInternetStatus.ContainsKey(PubnubInstance.InstanceId)) { diff --git a/src/Api/PubnubApi/PubnubHttp.cs b/src/Api/PubnubApi/PubnubHttp.cs deleted file mode 100644 index 818e23166..000000000 --- a/src/Api/PubnubApi/PubnubHttp.cs +++ /dev/null @@ -1,1415 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.IO; -using System.Net; -using System.Collections; -using System.Threading.Tasks; -using System.Globalization; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 -using System.Net.Http; -using System.Net.Http.Headers; -#endif - -namespace PubnubApi -{ - public class PubnubHttp : IPubnubHttp - { - private readonly PNConfiguration pubnubConfig; - private readonly IJsonPluggableLibrary jsonLib; - private readonly IPubnubLog pubnubLog; - private readonly EndPoint.TelemetryManager pubnubTelemetryMgr; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - private static HttpClient httpClientSubscribe; - private static HttpClient httpClientNonsubscribe; -#endif - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - public PubnubHttp(PNConfiguration config, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubLog log, EndPoint.TelemetryManager telemetryManager, HttpClient refHttpClientSubscribe, HttpClient refHttpClientNonsubscribe) -#else - public PubnubHttp(PNConfiguration config, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubLog log, EndPoint.TelemetryManager telemetryManager) -#endif - { - pubnubConfig = config; - jsonLib = jsonPluggableLibrary; - pubnubLog = log; - pubnubTelemetryMgr = telemetryManager; -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - httpClientSubscribe = refHttpClientSubscribe; - httpClientNonsubscribe = refHttpClientNonsubscribe; -#endif - } - - HttpWebRequest IPubnubHttp.SetProxy(HttpWebRequest request) - { -#if !NETSTANDARD10 - if (pubnubConfig.Proxy != null) - { - request.Proxy = pubnubConfig.Proxy; - } -#endif - return request; - } - - HttpWebRequest IPubnubHttp.SetTimeout(RequestState pubnubRequestState, HttpWebRequest request) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - request.Timeout = GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000; -#endif - return request; - } - - HttpWebRequest IPubnubHttp.SetNoCache(HttpWebRequest request) - { - request.Headers["Cache-Control"] = "no-cache"; - request.Headers["Pragma"] = "no-cache"; - - 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.SetTcpKeepAlive(HttpWebRequest request) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - request.KeepAlive = true; -#endif - return request; - } - - async Task IPubnubHttp.SendRequestAndGetJsonResponse(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request) - { - if (pubnubConfig.UseClassicHttpWebRequest) - { - return await SendRequestAndGetJsonResponseClassicHttp(requestUri, pubnubRequestState, request).ConfigureAwait(false); - } - else - { -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubConfig.UseTaskFactoryAsyncInsteadOfHttpClient) - { - return await SendRequestAndGetJsonResponseTaskFactory(pubnubRequestState, request).ConfigureAwait(false); - } - else - { - return await SendRequestAndGetJsonResponseHttpClient(requestUri, pubnubRequestState, request).ConfigureAwait(false); - } -#else - return await SendRequestAndGetJsonResponseTaskFactory(pubnubRequestState, request).ConfigureAwait(false); -#endif - } - - } - - async Task IPubnubHttp.SendRequestAndGetStreamResponse(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request) - { - if (pubnubConfig.UseClassicHttpWebRequest) - { - return await SendRequestAndGetStreamResponseClassicHttp(pubnubRequestState, request).ConfigureAwait(false); - } - else - { -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubConfig.UseTaskFactoryAsyncInsteadOfHttpClient) - { - return await SendRequestAndGetStreamResponseTaskFactory(pubnubRequestState, request).ConfigureAwait(false); - } - else - { - return await SendRequestAndGetStreamResponseHttpClient(requestUri, pubnubRequestState).ConfigureAwait(false); - } -#else - return await SendRequestAndGetStreamResponseTaskFactory(pubnubRequestState, request).ConfigureAwait(false); -#endif - } - - } - - async Task IPubnubHttp.SendRequestAndGetJsonResponseWithPOST(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request, byte[] postData, string contentType) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, postData bytearray len= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), postData.Length), pubnubConfig.LogVerbosity); - if (pubnubConfig.UseClassicHttpWebRequest) - { - return await SendRequestAndGetJsonResponseClassicHttpWithPOST(pubnubRequestState, request, postData, contentType).ConfigureAwait(false); - } - else - { -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubConfig.UseTaskFactoryAsyncInsteadOfHttpClient) - { - return await SendRequestAndGetJsonResponseTaskFactoryWithPOST(pubnubRequestState, request, postData, contentType).ConfigureAwait(false); - } - else - { - return await SendRequestAndGetJsonResponseHttpClientWithPOST(requestUri, pubnubRequestState, postData, contentType).ConfigureAwait(false); - } -#else - return await SendRequestAndGetJsonResponseTaskFactoryWithPOST(pubnubRequestState, request, postData, contentType).ConfigureAwait(false); -#endif - } - } - - async Task IPubnubHttp.SendRequestAndGetJsonResponseWithPATCH(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request, byte[] patchData, string contentType) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, patchData = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), Encoding.UTF8.GetString(patchData, 0, patchData.Length)), pubnubConfig.LogVerbosity); - if (pubnubConfig.UseClassicHttpWebRequest) - { - return await SendRequestAndGetJsonResponseClassicHttpWithPATCH(pubnubRequestState, request, patchData).ConfigureAwait(false); - } - else - { -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - if (pubnubConfig.UseTaskFactoryAsyncInsteadOfHttpClient) - { - return await SendRequestAndGetJsonResponseTaskFactoryWithPATCH(pubnubRequestState, request, patchData, contentType).ConfigureAwait(false); - } - else - { - return await SendRequestAndGetJsonResponseHttpClientWithPATCH(requestUri, pubnubRequestState, patchData, contentType).ConfigureAwait(false); - } -#else - return await SendRequestAndGetJsonResponseTaskFactoryWithPATCH(pubnubRequestState, request, patchData, contentType).ConfigureAwait(false); -#endif - } - } - -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 - async Task SendRequestAndGetJsonResponseHttpClient(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request) - { - string jsonString = ""; - HttpResponseMessage response = null; - CancellationTokenSource cts = new CancellationTokenSource(); - try - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetJsonResponseHttpClient", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - cts.CancelAfter(GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000); - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) - { - response = await httpClientSubscribe.GetAsync(requestUri, cts.Token).ConfigureAwait(false); - } - else if (string.Compare(FindHttpGetOrDeleteMethod(pubnubRequestState), "DELETE", StringComparison.CurrentCultureIgnoreCase) == 0) - { - response = await httpClientNonsubscribe.DeleteAsync(requestUri, cts.Token).ConfigureAwait(false); - } - else - { - response = await httpClientNonsubscribe.GetAsync(requestUri, cts.Token).ConfigureAwait(false); - } - if (response.IsSuccessStatusCode || response.Content != null) - { - var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType); - } - using (StreamReader streamReader = new StreamReader(stream)) - { - jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); - pubnubRequestState.GotJsonResponse = true; - } - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - else - { - stopWatch.Stop(); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - - } - catch (HttpRequestException httpReqEx) - { - if (httpReqEx.InnerException is WebException) - { - WebException currentWebException = httpReqEx.InnerException as WebException; - if (currentWebException != null) - { - if (currentWebException.Response != null) - { - pubnubRequestState.Response = currentWebException.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(currentWebException.Response.GetResponseStream())) - { - //Need to return this response - jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON from HttpClient WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClient InnerException WebException status {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ((WebException)httpReqEx.InnerException).Status.ToString()), pubnubConfig.LogVerbosity); - throw httpReqEx.InnerException; - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClient HttpRequestException {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), httpReqEx.Message), pubnubConfig.LogVerbosity); - throw; - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClient Exception {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); - throw; - } - finally - { - if (response != null && response.Content != null) - { - response.Content.Dispose(); - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - } - return jsonString; - } - - async Task SendRequestAndGetStreamResponseHttpClient(Uri requestUri, RequestState pubnubRequestState) - { - byte[] streamBytes = null; - HttpResponseMessage response = null; - CancellationTokenSource cts = new CancellationTokenSource(); - try - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetStreamResponseHttpClient", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - cts.CancelAfter(GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000); - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - response = await httpClientNonsubscribe.GetAsync(requestUri, cts.Token).ConfigureAwait(false); - if (response.IsSuccessStatusCode || response.Content != null) - { - var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType); - } - using (MemoryStream ms = new MemoryStream()) - { - stream.CopyTo(ms); - streamBytes = ms.ToArray(); - } - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - else - { - stopWatch.Stop(); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - - } - catch (HttpRequestException httpReqEx) - { - if (httpReqEx.InnerException is WebException) - { - WebException currentWebException = httpReqEx.InnerException as WebException; - if (currentWebException != null) - { - if (currentWebException.Response != null) - { - pubnubRequestState.Response = currentWebException.Response as HttpWebResponse; - var errorStream = currentWebException.Response.GetResponseStream(); - using (MemoryStream ms = new MemoryStream()) - { - errorStream.CopyTo(ms); - streamBytes = ms.ToArray(); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved Stream Bytes from HttpClient WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - } - } - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetStreamResponseHttpClient InnerException WebException status {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ((WebException)httpReqEx.InnerException).Status.ToString()), pubnubConfig.LogVerbosity); - throw httpReqEx.InnerException; - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetStreamResponseHttpClient HttpRequestException {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), httpReqEx.Message), pubnubConfig.LogVerbosity); - throw; - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetStreamResponseHttpClient Exception {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); - throw; - } - finally - { - if (response != null && response.Content != null) - { - response.Content.Dispose(); - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - } - return streamBytes; - } - - async Task SendRequestAndGetJsonResponseHttpClientWithPOST(Uri requestUri, RequestState pubnubRequestState, byte[] postData, string contentType) - { - string jsonString = ""; - HttpResponseMessage response = null; - CancellationTokenSource cts = new CancellationTokenSource(); - try - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SendRequestAndGetJsonResponseHttpClientPOST Before httpClient.GetAsync", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - cts.CancelAfter(GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000); - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - ByteArrayContent postDataContent = new ByteArrayContent(postData); - postDataContent.Headers.Remove("Content-Type"); - if (string.IsNullOrEmpty(contentType)) - { - postDataContent.Headers.TryAddWithoutValidation("Content-Type", "application/json"); - } - else - { - postDataContent.Headers.TryAddWithoutValidation("Content-Type", contentType); - } - if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) - { - response = await httpClientSubscribe.PostAsync(requestUri, postDataContent, cts.Token).ConfigureAwait(false); - } - else - { - response = await httpClientNonsubscribe.PostAsync(requestUri, postDataContent, cts.Token).ConfigureAwait(false); - } - - if (response.IsSuccessStatusCode || response.Content != null) - { - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got POST HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - if ((int)response.StatusCode == 204 && pubnubRequestState.ResponseType == PNOperationType.PNFileUploadOperation) - { - return "{}"; - } - else - { - var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - using (StreamReader streamReader = new StreamReader(stream)) - { - jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); - pubnubRequestState.GotJsonResponse = true; - } - } - } - else - { - stopWatch.Stop(); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No POST HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - - } - catch (HttpRequestException httpReqEx) - { - if (httpReqEx.InnerException is WebException) - { - WebException currentWebException = httpReqEx.InnerException as WebException; - if (currentWebException != null) - { - if (currentWebException.Response != null) - { - pubnubRequestState.Response = currentWebException.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(currentWebException.Response.GetResponseStream())) - { - //Need to return this response - jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON from HttpClient POST WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClientPOST InnerException WebException status {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ((WebException)httpReqEx.InnerException).Status.ToString()), pubnubConfig.LogVerbosity); - throw httpReqEx.InnerException; - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClientPOST HttpRequestException {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), httpReqEx.Message), pubnubConfig.LogVerbosity); - throw; - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClientPOST Exception {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); - throw; - } - finally - { - if (response != null && response.Content != null) - { - response.Content.Dispose(); - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - } - return jsonString; - } - - async Task SendRequestAndGetJsonResponseHttpClientWithPATCH(Uri requestUri, RequestState pubnubRequestState, byte[] patchData, string contentType) - { - string jsonString = ""; - HttpResponseMessage response = null; - CancellationTokenSource cts = new CancellationTokenSource(); - try - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SendRequestAndGetJsonResponseHttpClientWithPATCH Before httpClient.SendAsync", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - cts.CancelAfter(GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000); - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - HttpMethod httpMethod = new HttpMethod("PATCH"); - ByteArrayContent patchDataContent = new ByteArrayContent(patchData); - patchDataContent.Headers.Remove("Content-Type"); - if (string.IsNullOrEmpty(contentType)) - { - patchDataContent.Headers.TryAddWithoutValidation("Content-Type", "application/json"); - } - else - { - patchDataContent.Headers.TryAddWithoutValidation("Content-Type", contentType); - } - - HttpRequestMessage requestMsg = new HttpRequestMessage(httpMethod, requestUri) - { - Content = patchDataContent - }; - if (pubnubRequestState.ResponseType == PNOperationType.PNSubscribeOperation) - { - response = await httpClientSubscribe.SendAsync(requestMsg, cts.Token).ConfigureAwait(false); - } - else - { - response = await httpClientNonsubscribe.SendAsync(requestMsg, cts.Token).ConfigureAwait(false); - } - - if (response.IsSuccessStatusCode || response.Content != null) - { - var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - using (StreamReader streamReader = new StreamReader(stream)) - { - jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); - pubnubRequestState.GotJsonResponse = true; - } - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got POST HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - else - { - stopWatch.Stop(); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, No POST HttpResponseMessage for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), requestUri)); - } - - } - catch (HttpRequestException httpReqEx) - { - if (httpReqEx.InnerException is WebException) - { - WebException currentWebException = httpReqEx.InnerException as WebException; - if (currentWebException != null) - { - if (currentWebException.Response != null) - { - pubnubRequestState.Response = currentWebException.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(currentWebException.Response.GetResponseStream())) - { - //Need to return this response - jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON from HttpClient POST WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClientPOST InnerException WebException status {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ((WebException)httpReqEx.InnerException).Status.ToString()), pubnubConfig.LogVerbosity); - throw httpReqEx.InnerException; - } - - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClientPOST HttpRequestException {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), httpReqEx.Message), pubnubConfig.LogVerbosity); - throw; - } - catch (Exception ex) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, SendRequestAndGetJsonResponseHttpClientPOST Exception {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex.Message), pubnubConfig.LogVerbosity); - throw; - } - finally - { - if (response != null && response.Content != null) - { - response.Content.Dispose(); - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - } - return jsonString; - } -#endif - - async Task SendRequestAndGetJsonResponseTaskFactory(RequestState pubnubRequestState, HttpWebRequest request) - { - HttpWebResponse response = null; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetJsonResponseTaskFactory", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - try - { - request.Method = FindHttpGetOrDeleteMethod(pubnubRequestState); - 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); - } - 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())) - { - //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}, SendRequestAndGetJsonResponseTaskFactory => Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - - 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) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.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); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - throw; - } - return ""; - } - catch - { - throw; - } - } - - async Task SendRequestAndGetStreamResponseTaskFactory(RequestState pubnubRequestState, HttpWebRequest request) - { - HttpWebResponse response = null; - byte[] streamBytes; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetStreamResponseTaskFactory", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - 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(); - 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())); - int statusCode = (int)pubnubRequestState.Response.StatusCode; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, status code = {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), statusCode)); - using (Stream stream = response.GetResponseStream()) - { - long totalSize = 0; - long receivedSize = 0; - //Allocate 1K buffer - byte[] buffer = new byte[1024]; - using(MemoryStream ms = new MemoryStream()) - { -#if NET35 || NET40 - int bytesRead = stream.Read(buffer, 0, buffer.Length); -#else - int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); -#endif - receivedSize += bytesRead; - while (bytesRead > 0) - { - ms.Write(buffer, 0, bytesRead); - bytesRead = stream.Read(buffer, 0, buffer.Length); - receivedSize += bytesRead; - } - streamBytes = ms.ToArray(); - } - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, totalsize = {1}; received = {2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), totalSize, receivedSize)); - //Need to return this response - pubnubRequestState.GotJsonResponse = true; - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved Stream", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - - if (pubnubRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - - return streamBytes; - } - } - catch (WebException ex) - { - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - throw; - } - return null; - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Exception in SendRequestAndGetStreamResponseTaskFactory {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex)); - throw; - } - } - - async Task SendRequestAndGetJsonResponseTaskFactoryWithPOST(RequestState pubnubRequestState, HttpWebRequest request, byte[] postData, string contentType) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before Task.Factory.FromAsync With POST", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - try - { - request.Method = "POST"; - Timer webRequestTimer = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); - - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - - request.ContentType = contentType; - - using (var requestStream = await Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, pubnubRequestState).ConfigureAwait(false)) - { -#if NET35 || NET40 - requestStream.Write(postData, 0, postData.Length); - requestStream.Flush(); -#else - await requestStream.WriteAsync(postData, 0, postData.Length).ConfigureAwait(false); - await requestStream.FlushAsync().ConfigureAwait(false); -#endif - - } - - WebResponse response = await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, pubnubRequestState).ConfigureAwait(false); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - pubnubRequestState.Response = response as HttpWebResponse; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got PubnubWebResponse With POST for {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), request.RequestUri.ToString())); - int statusCode = (int)pubnubRequestState.Response.StatusCode; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, statusCode {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), statusCode)); - if (statusCode == 204 && pubnubRequestState.ResponseType == PNOperationType.PNFileUploadOperation) - { - return "{}"; - } - else - { - 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); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With POST", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - pubnubRequestState.GotJsonResponse = true; - - if (pubnubRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - - return jsonString; - } - } - } - catch (WebException ex) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.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); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With POST from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - throw; - } - return ""; - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Exception in SendRequestAndGetJsonResponseTaskFactoryWithPOST {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), ex)); - throw; - } - } - - async Task SendRequestAndGetJsonResponseTaskFactoryWithPATCH(RequestState pubnubRequestState, HttpWebRequest request, byte[] patchData, string contentType) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before Task.Factory.FromAsync With PATCH", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - try - { - request.Method = "PATCH"; - Timer webRequestTimer = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); - - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - - request.ContentType = "application/json"; - - using (var requestStream = await Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, pubnubRequestState).ConfigureAwait(false)) - { -#if NET35 || NET40 - requestStream.Write(patchData, 0, patchData.Length); - requestStream.Flush(); -#else - await requestStream.WriteAsync(patchData, 0, patchData.Length).ConfigureAwait(false); - await requestStream.FlushAsync().ConfigureAwait(false); -#endif - - } - - WebResponse response = await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, pubnubRequestState).ConfigureAwait(false); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - pubnubRequestState.Response = response as HttpWebResponse; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Got PubnubWebResponse With PATCH 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); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With PATCH", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - pubnubRequestState.GotJsonResponse = true; - - if (pubnubRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - pubnubRequestState.Response = null; - pubnubRequestState.Request = null; - } - - return jsonString; - } - } - catch (WebException ex) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.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); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With PATCH from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - throw; - } - return ""; - } - catch - { - throw; - } - } - - async Task SendRequestAndGetJsonResponseClassicHttp(Uri requestUri, RequestState pubnubRequestState, HttpWebRequest request) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetJsonResponseClassicHttp", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - var taskComplete = new TaskCompletionSource(); - try - { - request.Method = FindHttpGetOrDeleteMethod(pubnubRequestState); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before BeginGetResponse", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - request.BeginGetResponse(new AsyncCallback( - async (asynchronousResult) => { - RequestState asyncRequestState = asynchronousResult.AsyncState as RequestState; - HttpWebRequest asyncWebRequest = asyncRequestState.Request as HttpWebRequest; - if (asyncWebRequest != null) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before EndGetResponse", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - HttpWebResponse asyncWebResponse = (HttpWebResponse)asyncWebRequest.EndGetResponse(asynchronousResult); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - asyncRequestState.Response = asyncWebResponse; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, After EndGetResponse", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - using (StreamReader streamReader = new StreamReader(asyncWebResponse.GetResponseStream())) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Inside StreamReader", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - //Need to return this response - string jsonString = streamReader.ReadToEnd(); - asyncRequestState.GotJsonResponse = true; - - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SendRequestAndGetJsonResponseClassicHttp => Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - taskComplete.TrySetResult(jsonString); - } - if (asyncRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - asyncRequestState.Response = null; - asyncRequestState.Request = null; - } - } - } - ), pubnubRequestState); - - Timer webRequestTimer = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); - return taskComplete.Task.Result; - } - catch (WebException ex) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.Response.GetResponseStream())) - { - //Need to return this response -#if NET35 || NET40 - await Task.Factory.StartNew(() => { }).ConfigureAwait(false); - string jsonString = streamReader.ReadToEnd(); -#else - string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); -#endif - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - taskComplete.TrySetException(ex); - } - return ""; - } - catch (Exception ex) - { - taskComplete.TrySetException(ex); - return ""; - } - } - - async Task SendRequestAndGetStreamResponseClassicHttp(RequestState pubnubRequestState, HttpWebRequest request) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetStreamResponseClassicHttp", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - var taskComplete = new TaskCompletionSource(); - try - { - request.Method = FindHttpGetOrDeleteMethod(pubnubRequestState); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before BeginGetResponse", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - request.BeginGetResponse(new AsyncCallback( - async (asynchronousResult) => { - RequestState asyncRequestState = asynchronousResult.AsyncState as RequestState; - HttpWebRequest asyncWebRequest = asyncRequestState.Request as HttpWebRequest; - if (asyncWebRequest != null) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before EndGetResponse", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - HttpWebResponse asyncWebResponse = (HttpWebResponse)asyncWebRequest.EndGetResponse(asynchronousResult); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - asyncRequestState.Response = asyncWebResponse; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, After EndGetResponse", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - using (StreamReader streamReader = new StreamReader(asyncWebResponse.GetResponseStream())) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Inside StreamReader", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - //Need to return this response - string jsonString = streamReader.ReadToEnd(); - asyncRequestState.GotJsonResponse = true; - - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, SendRequestAndGetStreamResponseClassicHttp => Retrieved JSON", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - taskComplete.TrySetResult(null); - } - if (asyncRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - asyncRequestState.Response = null; - asyncRequestState.Request = null; - } - } - } - ), pubnubRequestState); - - Timer webRequestTimer = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); - return taskComplete.Task.Result; - } - catch (WebException ex) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.Response.GetResponseStream())) - { - //Need to return this response -#if NET35 || NET40 - await Task.Factory.StartNew(() => { }).ConfigureAwait(false); - string jsonString = streamReader.ReadToEnd(); -#else - string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); -#endif - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return null; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - taskComplete.TrySetException(ex); - } - return null; - } - catch (Exception ex) - { - taskComplete.TrySetException(ex); - return null; - } - } - - async Task SendRequestAndGetJsonResponseClassicHttpWithPOST(RequestState pubnubRequestState, HttpWebRequest request, byte[] postData, string contentType) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetJsonResponseClassicHttpWithPOST", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - var taskComplete = new TaskCompletionSource(); - try - { - request.Method = "POST"; - request.ContentType = contentType; - - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 - using (var requestStream = await Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, pubnubRequestState).ConfigureAwait(false)) - { - requestStream.Write(postData, 0, postData.Length); - requestStream.Flush(); - } -#else - using (var requestStream = request.GetRequestStream()) - { - requestStream.Write(postData, 0, postData.Length); - requestStream.Flush(); - } -#endif - - IAsyncResult asyncResult = request.BeginGetResponse(new AsyncCallback( - async (asynchronousResult) => { - RequestState asyncRequestState = asynchronousResult.AsyncState as RequestState; - HttpWebRequest asyncWebRequest = asyncRequestState.Request as HttpWebRequest; - if (asyncWebRequest != null) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before EndGetResponse With POST ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - HttpWebResponse asyncWebResponse = (HttpWebResponse)asyncWebRequest.EndGetResponse(asynchronousResult); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - asyncRequestState.Response = asyncWebResponse; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, After EndGetResponse With POST ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - using (StreamReader streamReader = new StreamReader(asyncWebResponse.GetResponseStream())) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Inside StreamReader With POST ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - //Need to return this response - string jsonString = streamReader.ReadToEnd(); - asyncRequestState.GotJsonResponse = true; - - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With POST ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - taskComplete.TrySetResult(jsonString); - } - if (asyncRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - asyncRequestState.Response = null; - asyncRequestState.Request = null; - } - - } - } - ), pubnubRequestState); - - Timer webRequestTimer = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); - return taskComplete.Task.Result; - } - catch (WebException ex) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.Response.GetResponseStream())) - { - //Need to return this response -#if NET35 || NET40 - await Task.Factory.StartNew(() => { }).ConfigureAwait(false); - string jsonString = streamReader.ReadToEnd(); -#else - string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); -#endif - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With POST from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - taskComplete.TrySetException(ex); - } - return ""; - } - catch (Exception ex) - { - taskComplete.TrySetException(ex); - return ""; - } - } - - async Task SendRequestAndGetJsonResponseClassicHttpWithPATCH(RequestState pubnubRequestState, HttpWebRequest request, byte[] patchData) - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, Inside SendRequestAndGetJsonResponseClassicHttpWithPATCH", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - var taskComplete = new TaskCompletionSource(); - try - { - request.Method = "PATCH"; - request.ContentType = "application/json"; - - System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 - using (var requestStream = await Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, pubnubRequestState).ConfigureAwait(false)) - { - requestStream.Write(patchData, 0, patchData.Length); - requestStream.Flush(); - } -#else - using (var requestStream = request.GetRequestStream()) - { - requestStream.Write(patchData, 0, patchData.Length); - requestStream.Flush(); - } -#endif - - IAsyncResult asyncResult = request.BeginGetResponse(new AsyncCallback( - async (asynchronousResult) => { - RequestState asyncRequestState = asynchronousResult.AsyncState as RequestState; - HttpWebRequest asyncWebRequest = asyncRequestState.Request as HttpWebRequest; - if (asyncWebRequest != null) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Before EndGetResponse With PATCH ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - HttpWebResponse asyncWebResponse = (HttpWebResponse)asyncWebRequest.EndGetResponse(asynchronousResult); - stopWatch.Stop(); - if (pubnubTelemetryMgr != null) - { - await pubnubTelemetryMgr.StoreLatency(stopWatch.ElapsedMilliseconds, pubnubRequestState.ResponseType).ConfigureAwait(false); - } - asyncRequestState.Response = asyncWebResponse; - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, After EndGetResponse With PATCH ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - using (StreamReader streamReader = new StreamReader(asyncWebResponse.GetResponseStream())) - { - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Inside StreamReader With PATCH ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - //Need to return this response - string jsonString = streamReader.ReadToEnd(); - asyncRequestState.GotJsonResponse = true; - - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With PATCH ", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - taskComplete.TrySetResult(jsonString); - } - if (asyncRequestState.Response != null) - { -#if NET35 || NET40 || NET45 || NET461 || NET48 - pubnubRequestState.Response.Close(); -#endif - asyncRequestState.Response = null; - asyncRequestState.Request = null; - } - - } - } - ), pubnubRequestState); - - Timer webRequestTimer = new Timer(OnPubnubWebRequestTimeout, pubnubRequestState, GetTimeoutInSecondsForResponseType(pubnubRequestState.ResponseType) * 1000, Timeout.Infinite); - return taskComplete.Task.Result; - } - catch (WebException ex) - { - if (ex.Response != null) - { - pubnubRequestState.Response = ex.Response as HttpWebResponse; - using (StreamReader streamReader = new StreamReader(ex.Response.GetResponseStream())) - { - //Need to return this response -#if NET35 || NET40 - await Task.Factory.StartNew(() => { }).ConfigureAwait(false); - string jsonString = streamReader.ReadToEnd(); -#else - string jsonString = await streamReader.ReadToEndAsync().ConfigureAwait(false); -#endif - System.Diagnostics.Debug.WriteLine(jsonString); - System.Diagnostics.Debug.WriteLine(""); - System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Retrieved JSON With PATCH from WebException response", DateTime.Now.ToString(CultureInfo.InvariantCulture))); - return jsonString; - } - } - - if (ex.Message.IndexOf("The request was aborted: The request was canceled", StringComparison.OrdinalIgnoreCase) == -1 - && ex.Message.IndexOf("Machine suspend mode enabled. No request will be processed.", StringComparison.OrdinalIgnoreCase) == -1) - { - taskComplete.TrySetException(ex); - } - return ""; - } - catch (Exception ex) - { - taskComplete.TrySetException(ex); - return ""; - } - } - - protected void OnPubnubWebRequestTimeout(object state, bool timeout) - { - if (timeout && state != null) - { - RequestState currentState = state as RequestState; - if (currentState != null) - { - HttpWebRequest request = currentState.Request; - if (request != null) - { - string currentMultiChannel = (currentState.Channels == null) ? "" : string.Join(",", currentState.Channels.OrderBy(x => x).ToArray()); - string currentMultiChannelGroup = (currentState.ChannelGroups == null) ? "" : string.Join(",", currentState.ChannelGroups.OrderBy(x => x).ToArray()); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, OnPubnubWebRequestTimeout: client request timeout reached.Request abort for channel={1} ;channelgroup={2}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentMultiChannel, currentMultiChannelGroup), pubnubConfig.LogVerbosity); - currentState.Timeout = true; - try - { - request.Abort(); - } - catch { /* ignore */ } - } - } - else - { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime: {0}, OnPubnubWebRequestTimeout: client request timeout reached. However state is unknown", DateTime.Now.ToString(CultureInfo.InvariantCulture)), pubnubConfig.LogVerbosity); - } - } - } - - protected void OnPubnubWebRequestTimeout(System.Object requestState) - { - RequestState currentState = requestState as 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 */ } - - if (currentState.ResponseType != PNOperationType.PNSubscribeOperation - && currentState.ResponseType != PNOperationType.Presence - && currentState.ResponseType != PNOperationType.PNHeartbeatOperation - && currentState.ResponseType != PNOperationType.Leave) - { - PNStatusCategory errorCategory = PNStatusCategory.PNTimeoutCategory; - PNStatus status = new StatusBuilder(pubnubConfig, jsonLib).CreateStatusResponse(currentState.ResponseType, errorCategory, currentState, (int)HttpStatusCode.NotFound, new PNException("Request timeout")); - - if (currentState.Channels != null && currentState.Channels.Length > 0) - { - status.AffectedChannels.AddRange(currentState.Channels); - } - - if (currentState.ChannelGroups != null && currentState.ChannelGroups.Length > 0) - { - status.AffectedChannels.AddRange(currentState.ChannelGroups); - } - - if (currentState.PubnubCallback != null) - { - currentState.PubnubCallback.OnResponse(default(T), status); - } - } - } - } - - protected int GetTimeoutInSecondsForResponseType(PNOperationType type) - { - int timeout; - if (type == PNOperationType.PNSubscribeOperation || type == PNOperationType.Presence) - { - timeout = pubnubConfig.SubscribeTimeout; - } - else if (type == PNOperationType.PNGenerateFileUploadUrlOperation) - { - timeout = pubnubConfig.NonSubscribeRequestTimeout*3; - } - else if (type == PNOperationType.PNFileUploadOperation || type == PNOperationType.PNDownloadFileOperation) - { - timeout = pubnubConfig.NonSubscribeRequestTimeout * 25; - } - else - { - timeout = pubnubConfig.NonSubscribeRequestTimeout; - } - return timeout; - } - - private static string FindHttpGetOrDeleteMethod(RequestState pubnubRequestState) - { - return (pubnubRequestState != null && (pubnubRequestState.ResponseType == PNOperationType.PNDeleteMessageOperation - || pubnubRequestState.ResponseType == PNOperationType.PNDeleteUuidMetadataOperation - || pubnubRequestState.ResponseType == PNOperationType.PNDeleteChannelMetadataOperation - || pubnubRequestState.ResponseType == PNOperationType.PNRemoveMessageActionOperation - || pubnubRequestState.ResponseType == PNOperationType.PNAccessManagerRevokeToken - || pubnubRequestState.ResponseType == PNOperationType.PNDeleteFileOperation)) ? "DELETE" : "GET"; - - } - } -} diff --git a/src/Api/PubnubApi/PubnubHttpClientHandler.cs b/src/Api/PubnubApi/PubnubHttpClientHandler.cs deleted file mode 100644 index 253e9e004..000000000 --- a/src/Api/PubnubApi/PubnubHttpClientHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -#if !NET35 && !NET40 && !NET45 && !NET461 && !NET48 && !NETSTANDARD10 -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace PubnubApi -{ - public class PubnubHttpClientHandler: DelegatingHandler - { - private readonly PNConfiguration pubnubConfig; - private readonly IPubnubLog pubnubLog; - - private readonly string pubnubHandlerName; - - public PubnubHttpClientHandler(string name, HttpClientHandler innerHandler, PNConfiguration config, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log) - { - base.InnerHandler = innerHandler; - pubnubHandlerName = string.IsNullOrEmpty(name) ? string.Empty : name; - pubnubConfig = config; - pubnubLog = log; - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PubnubHttpClientHandler {1} SendAsync ", DateTime.Now.ToString(CultureInfo.InvariantCulture), pubnubHandlerName), pubnubConfig.LogVerbosity); - return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); - } - } -} -#endif diff --git a/src/Api/PubnubApi/Security/Crypto/Common/Util.cs b/src/Api/PubnubApi/Security/Crypto/Common/Util.cs index 1f43ca580..7a4070a2c 100644 --- a/src/Api/PubnubApi/Security/Crypto/Common/Util.cs +++ b/src/Api/PubnubApi/Security/Crypto/Common/Util.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Security.Cryptography; using System.Text; diff --git a/src/Api/PubnubApi/Security/SecureMessage.cs b/src/Api/PubnubApi/Security/SecureMessage.cs index 2a15b2ed6..bb739683f 100644 --- a/src/Api/PubnubApi/Security/SecureMessage.cs +++ b/src/Api/PubnubApi/Security/SecureMessage.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Collections; +using System.Diagnostics; using System.Net; using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; @@ -59,19 +60,24 @@ public List HistoryDecodeDecryptLoop(PNOperationType type, List(type, category, null, (int)HttpStatusCode.NotFound, new PNException(ex)); + PNStatus status = new StatusBuilder(config, jsonLib).CreateStatusResponse(type, category, + null, (int)HttpStatusCode.NotFound, new PNException(ex)); if (channels != null && channels.Length > 0) { status.AffectedChannels.AddRange(channels); } + if (channelGroups != null && channelGroups.Length > 0) { status.AffectedChannelGroups.AddRange(channelGroups); } - pubnubLog.WriteToLog("Failed to decrypt message!\nMessage might be not encrypted, returning as is..."); + + LoggingMethod.WriteToLog(pubnubLog, "Failed to decrypt message!\nMessage might be not encrypted, returning as is...", config.LogVerbosity); } + object decodedMessage = jsonLib.DeserializeToObject((decryptMessage == "**DECRYPT ERROR**") ? jsonLib.SerializeToJsonString(element) : decryptMessage); receivedMsg.Add(decodedMessage); + } returnMessage.Add(receivedMsg); } @@ -149,7 +155,7 @@ public List FetchHistoryDecodeDecryptLoop(PNOperationType type, Dicti { status.AffectedChannelGroups.AddRange(channelGroups); } - pubnubLog.WriteToLog("Failed to decrypt message!\nMessage might be not encrypted, returning as is..."); + LoggingMethod.WriteToLog(pubnubLog, "Failed to decrypt message!\nMessage might be not encrypted, returning as is...",config.LogVerbosity); #endregion } object decodedMessage = jsonLib.DeserializeToObject((decryptMessage == "**DECRYPT ERROR**") ? jsonLib.SerializeToJsonString(kvpValue.Value) : decryptMessage); diff --git a/src/Api/PubnubApi/Timer.cs b/src/Api/PubnubApi/Timer.cs deleted file mode 100644 index 7ee86602e..000000000 --- a/src/Api/PubnubApi/Timer.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace System.Threading -{ -#if NETSTANDARD10 || NETSTANDARD11 - public delegate void TimerCallback(object state); - - public sealed class Timer : CancellationTokenSource, IDisposable - { - TimerCallback callback; - object state; - - public Timer(TimerCallback callback, object state, int dueTime, int period) - { - Init(callback, state, dueTime, period); - } - - public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period) - { - Init(callback, state, (long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds); - } - - public Timer(TimerCallback callback) - { - Init(callback, this, Timeout.Infinite, Timeout.Infinite); - } - - void Init(TimerCallback callback, object state, long dueTime, long period) - { - if (callback == null) - throw new ArgumentNullException("callback"); - - this.callback = callback; - this.state = state; - - Change(dueTime, period, true); - } - - - public new void Dispose() - { - base.Cancel(); - } - - public bool Change(int dueTime, int period) - { - return Change(dueTime, period, false); - } - - - public bool Change(TimeSpan dueTime, TimeSpan period) - { - return Change((long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds, false); - } - - - public bool Change(uint dueTime, uint period) - { - // convert all values to long - with a special case for -1 / 0xffffffff - long d = (dueTime == UInt32.MaxValue) ? Timeout.Infinite : (long)dueTime; - long p = (period == UInt32.MaxValue) ? Timeout.Infinite : (long)period; - return Change(d, p, false); - } - - public bool Change(long dueTime, long period) - { - return Change(dueTime, period, false); - } - - bool Change(long dueTime, long period, bool first) - { - bool status = false; - - if (dueTime < Timeout.Infinite) - throw new ArgumentOutOfRangeException("dueTime"); - - - if (period < Timeout.Infinite) - throw new ArgumentOutOfRangeException("period"); - - - Task.Delay((int)dueTime, Token).ContinueWith(async (t, s) => - { - var tuple = (Tuple)s; - - while (true) - { - if (IsCancellationRequested) - { - status = false; - break; - } - await Task.Run(() => tuple.Item1(tuple.Item2)).ConfigureAwait(false); - await Task.Delay((int)period).ConfigureAwait(false); - - status = true; - } - - }, Tuple.Create(callback, state), CancellationToken.None, - TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, - TaskScheduler.Default).ConfigureAwait(false); - - return status; - } - - - } - -#endif -} - diff --git a/src/Api/PubnubApi/Transport/HttpClientService.cs b/src/Api/PubnubApi/Transport/HttpClientService.cs new file mode 100644 index 000000000..d48e0f1b5 --- /dev/null +++ b/src/Api/PubnubApi/Transport/HttpClientService.cs @@ -0,0 +1,226 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; + +namespace PubnubApi +{ + public class HttpClientService : IHttpClientService + { + private readonly HttpClient httpClient; + public HttpClientService(IWebProxy proxy = default) + { + httpClient = new HttpClient() + { + Timeout = Timeout.InfiniteTimeSpan + }; + if (proxy == null) return; + httpClient = new HttpClient(new HttpClientHandler() + { + Proxy = proxy, + UseProxy = true + }); + httpClient.Timeout = Timeout.InfiniteTimeSpan; + } + + public async Task GetRequest(TransportRequest transportRequest) + { + TransportResponse response; + try { + HttpRequestMessage requestMessage = new HttpRequestMessage(method: HttpMethod.Get, requestUri: transportRequest.RequestUrl); + if (transportRequest.Headers.Keys.Count > 0) { + foreach (var kvp in transportRequest.Headers) { + requestMessage.Headers.Add(kvp.Key, kvp.Value); + } + } + var httpResult = await httpClient.SendAsync(request: requestMessage, cancellationToken: transportRequest.CancellationToken).ConfigureAwait(false); + var responseContent = await httpResult.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + response = new TransportResponse() { + StatusCode = (int)httpResult.StatusCode, + Content = responseContent, + Headers = httpResult.Headers.ToDictionary(h => h.Key, h => h.Value), + RequestUrl = httpResult.RequestMessage?.RequestUri?.AbsolutePath + }; + } catch (Exception ex) { + response = new TransportResponse() { + RequestUrl = transportRequest.RequestUrl, + Error = ex + }; + } + return response; + } + + public async Task PostRequest(TransportRequest transportRequest) + { + TransportResponse transportResponse; + try + { + HttpContent postData = null; + if (!string.IsNullOrEmpty(transportRequest.BodyContentString)) { + postData = new StringContent(transportRequest.BodyContentString, Encoding.UTF8, "application/json"); + } else if (transportRequest.BodyContentBytes != null) + { + postData = new ByteArrayContent(transportRequest.BodyContentBytes); + foreach (var transportRequestHeader in transportRequest.Headers) + { + postData.Headers.Add(transportRequestHeader.Key, transportRequestHeader.Value); + } + } + HttpRequestMessage requestMessage = new HttpRequestMessage(method: HttpMethod.Post, requestUri: transportRequest.RequestUrl) { Content = postData }; + + var httpResult = await httpClient.SendAsync(request: requestMessage, cancellationToken: transportRequest.CancellationToken).ConfigureAwait(false); + var responseContent = await httpResult.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + transportResponse= new TransportResponse() { + StatusCode = (int)httpResult.StatusCode, + Content = responseContent, + Headers = httpResult.Headers.ToDictionary(h => h.Key, h => h.Value), + RequestUrl = httpResult.RequestMessage?.RequestUri?.AbsolutePath + }; + } catch (Exception e) { + transportResponse = new TransportResponse() { + RequestUrl = transportRequest.RequestUrl, + Error = e + }; + } + return transportResponse; + } + + public async Task PutRequest(TransportRequest transportRequest) + { + TransportResponse transportResponse; + try + { + HttpContent putData = null; + + if (!string.IsNullOrEmpty(transportRequest.BodyContentString)) + { + putData = new StringContent(transportRequest.BodyContentString, Encoding.UTF8, "application/json"); + } + else if (transportRequest.BodyContentBytes != null) + { + putData = new ByteArrayContent(transportRequest.FormData); + foreach (var transportRequestHeader in transportRequest.Headers) + { + putData.Headers.Add(transportRequestHeader.Key, transportRequestHeader.Value); + } + } + + HttpRequestMessage requestMessage = + new HttpRequestMessage(method: HttpMethod.Put, requestUri: transportRequest.RequestUrl) + { Content = putData }; + if (transportRequest.Headers.Keys.Count > 0) + { + foreach (var kvp in transportRequest.Headers) + { + requestMessage.Headers.Add(kvp.Key, kvp.Value); + } + } + + var httpResult = await httpClient.SendAsync(request: requestMessage, + cancellationToken: transportRequest.CancellationToken).ConfigureAwait(false); + var responseContent = await httpResult.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + transportResponse = new TransportResponse() + { + StatusCode = (int)httpResult.StatusCode, + Content = responseContent, + Headers = httpResult.Headers.ToDictionary(h => h.Key, h => h.Value), + RequestUrl = httpResult.RequestMessage?.RequestUri?.AbsolutePath + }; + } + catch (Exception e) + { + transportResponse = new TransportResponse() { + RequestUrl = transportRequest.RequestUrl, + Error = e + }; + } + return transportResponse; + } + + public async Task DeleteRequest(TransportRequest transportRequest) + { + TransportResponse response; + try { + if (transportRequest.Timeout.HasValue) httpClient.Timeout = (TimeSpan)transportRequest.Timeout; + HttpRequestMessage requestMessage = new HttpRequestMessage(method: HttpMethod.Delete, requestUri: transportRequest.RequestUrl); + if (transportRequest.Headers.Keys.Count > 0) { + foreach (var kvp in transportRequest.Headers) { + requestMessage.Headers.Add(kvp.Key, kvp.Value); + } + } + var httpResult = await httpClient.SendAsync(request: requestMessage, cancellationToken: transportRequest.CancellationToken).ConfigureAwait(false); + var responseContent = await httpResult.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + response = new TransportResponse() { + StatusCode = (int)httpResult.StatusCode, + Content = responseContent, + Headers = httpResult.Headers.ToDictionary(h => h.Key, h => h.Value), + RequestUrl = httpResult.RequestMessage?.RequestUri?.AbsolutePath + }; + } catch (Exception ex) { + response = new TransportResponse() { + RequestUrl = transportRequest.RequestUrl, + Error = ex + }; + } + return response; + } + + public async Task PatchRequest(TransportRequest transportRequest) + { + TransportResponse transportResponse; + try + { + HttpContent patchData = null; + + if (!string.IsNullOrEmpty(transportRequest.BodyContentString)) + { + patchData = new StringContent(transportRequest.BodyContentString, Encoding.UTF8, + "application/json"); + } + else if (transportRequest.BodyContentBytes != null) + { + patchData = new ByteArrayContent(transportRequest.FormData); + foreach (var transportRequestHeader in transportRequest.Headers) + { + patchData.Headers.Add(transportRequestHeader.Key, transportRequestHeader.Value); + } + } + + HttpRequestMessage requestMessage = + new HttpRequestMessage(new HttpMethod("PATCH"), requestUri: transportRequest.RequestUrl) + { Content = patchData }; + if (transportRequest.Headers.Keys.Count > 0) + { + foreach (var kvp in transportRequest.Headers) + { + requestMessage.Headers.Add(kvp.Key, kvp.Value); + } + } + + var httpResult = await httpClient.SendAsync(request: requestMessage, + cancellationToken: transportRequest.CancellationToken).ConfigureAwait(false); + var responseContent = await httpResult.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + transportResponse = new TransportResponse() + { + StatusCode = (int)httpResult.StatusCode, + Content = responseContent, + Headers = httpResult.Headers.ToDictionary(h => h.Key, h => h.Value), + RequestUrl = httpResult.RequestMessage?.RequestUri?.AbsolutePath + }; + } + catch (Exception e) + { + transportResponse = new TransportResponse() { + RequestUrl = transportRequest.RequestUrl, + Error = e + }; + } + + return transportResponse; + } + } +} + diff --git a/src/Api/PubnubApi/Transport/Middleware.cs b/src/Api/PubnubApi/Transport/Middleware.cs new file mode 100644 index 000000000..f83b12cb2 --- /dev/null +++ b/src/Api/PubnubApi/Transport/Middleware.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using PubnubApi.EndPoint; +using PubnubApi.Security.Crypto.Common; + +namespace PubnubApi +{ + public class Middleware : ITransportMiddleware + { + private PNConfiguration configuration; + private Pubnub pnInstance; + private TokenManager tokenManager; + private IHttpClientService httpClientService; + + public Middleware(IHttpClientService httpClientService, PNConfiguration configuration, Pubnub pnInstance, TokenManager tokenManager) + { + this.configuration = configuration; + this.pnInstance = pnInstance; + this.tokenManager = tokenManager; + this.httpClientService = httpClientService; + } + + public TransportRequest PreapareTransportRequest(RequestParameter requestParameter, PNOperationType operationType) + { + long timeStamp = TranslateUtcDateTimeToSeconds(DateTime.UtcNow); + string requestid = Guid.NewGuid().ToString(); + string instanceId = pnInstance.InstanceId; + + Dictionary commonQueryParameters = new Dictionary + { + { "uuid",UriUtil.EncodeUriComponent(configuration.UserId.ToString(),PNOperationType.PNSubscribeOperation, false, false, true)}, + { "pnsdk", UriUtil.EncodeUriComponent(Pubnub.Version, PNOperationType.PNSubscribeOperation, false, false, true) } + }; + + if (configuration.IncludeInstanceIdentifier) + { + commonQueryParameters.Add("requestid", requestid); + } + if (configuration.IncludeInstanceIdentifier && !string.IsNullOrEmpty(instanceId) && instanceId.Trim().Length > 0) + { + commonQueryParameters.Add("instanceid", instanceId); + } + if (!string.IsNullOrEmpty(configuration.SecretKey)) + { + commonQueryParameters.Add("timestamp", timeStamp.ToString(CultureInfo.InvariantCulture)); + } + + var excludedAuthOperationTypes = new[] { + PNOperationType.PNTimeOperation, + PNOperationType.PNAccessManagerGrant, + PNOperationType.PNAccessManagerGrantToken, + PNOperationType.PNAccessManagerRevokeToken, + PNOperationType.ChannelGroupGrantAccess, + PNOperationType.PNAccessManagerAudit, + PNOperationType.ChannelGroupAuditAccess + }; + if (!excludedAuthOperationTypes.Contains(operationType)) + { + string authToken = tokenManager?.AuthToken?.Trim(); + string authKey = configuration.AuthKey?.Trim(); + + if (!string.IsNullOrEmpty(authToken)) + { + commonQueryParameters.Add("auth", UriUtil.EncodeUriComponent(authToken, operationType, false, false, false)); + } + else if (!string.IsNullOrEmpty(authKey)) + { + commonQueryParameters.Add("auth", UriUtil.EncodeUriComponent(authKey, operationType, false, false, false)); + } + } + requestParameter.Query = requestParameter.Query.Union(commonQueryParameters).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + var queryString = UriUtil.BuildQueryString(requestParameter.Query); + var pathString = GeneratePathString(requestParameter.PathSegment, operationType); + if (!string.IsNullOrEmpty(configuration.SecretKey)) + { + string signature = string.Empty; + StringBuilder stringToSign = new StringBuilder(); + stringToSign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", requestParameter.RequestType); + stringToSign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", configuration.PublishKey); + stringToSign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", pathString); + stringToSign.AppendFormat(CultureInfo.InvariantCulture, "{0}\n", queryString); + if (!string.IsNullOrEmpty(requestParameter.BodyContentString)) stringToSign.Append(requestParameter.BodyContentString); + signature = Util.PubnubAccessManagerSign(configuration.SecretKey, stringToSign.ToString()); + signature = string.Format(CultureInfo.InvariantCulture, "v2.{0}", signature.TrimEnd(new[] { '=' })); + requestParameter.Query.Add("signature", signature); + } + var urlString = $"{(configuration.Secure ? "https://" : "http://")}{configuration.Origin}{pathString}?{UriUtil.BuildQueryString(requestParameter.Query)}"; + + var cts = new CancellationTokenSource(); + cts.CancelAfter(operationType == PNOperationType.PNSubscribeOperation ? configuration.SubscribeTimeout * 1000 : configuration.NonSubscribeRequestTimeout* 1000); + var transportRequest = new TransportRequest() + { + RequestType = requestParameter.RequestType, + RequestUrl = urlString, + BodyContentString = requestParameter.BodyContentString, + FormData = requestParameter.FormData, + CancellationToken = cts.Token + }; + return transportRequest; + } + + public Task Send(TransportRequest transportRequest) + { + switch (transportRequest.RequestType) + { + case Constants.GET: + return httpClientService.GetRequest(transportRequest); + case Constants.POST: + return httpClientService.PostRequest(transportRequest); + case Constants.PATCH: + return httpClientService.PatchRequest(transportRequest); + case Constants.PUT: + return httpClientService.PutRequest(transportRequest); + case Constants.DELETE: + return httpClientService.DeleteRequest(transportRequest); + default: + return httpClientService.GetRequest(transportRequest); + } + } + + private string GeneratePathString(List pathSegments, PNOperationType operationType) + { + StringBuilder pathString = new StringBuilder(); + foreach (var component in pathSegments) + { + pathString.Append('/'); + + if ((operationType == PNOperationType.PNPublishOperation || operationType == PNOperationType.PNPublishFileMessageOperation) && component == pathSegments.Last()) + { + pathString.Append(UriUtil.EncodeUriComponent(component, operationType, false, true, false)); + } + else if (operationType == PNOperationType.PNAccessManagerRevokeToken) + { + pathString.Append(UriUtil.EncodeUriComponent(component, operationType, false, false, false)); + } + else + { + pathString.Append(UriUtil.EncodeUriComponent(component, operationType, true, false, false)); + } + } + return pathString.ToString(); + } + + private long TranslateUtcDateTimeToSeconds(DateTime dotNetUTCDateTime) + { + TimeSpan timeSpan = dotNetUTCDateTime - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + long timeStamp = Convert.ToInt64(timeSpan.TotalSeconds); + return timeStamp; + } + } +} diff --git a/src/Api/PubnubApi/Transport/RequestParameter.cs b/src/Api/PubnubApi/Transport/RequestParameter.cs new file mode 100644 index 000000000..1602fa800 --- /dev/null +++ b/src/Api/PubnubApi/Transport/RequestParameter.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace PubnubApi +{ + public class RequestParameter + { + public string RequestType { get; set; } + public List PathSegment { get; set; } + public Dictionary Query { get; set; } = new Dictionary(); + public string BodyContentString { get; set; } + public byte[] FormData { get; set; } + } +} diff --git a/src/Api/PubnubApi/TransportContract/IHttpClientService.cs b/src/Api/PubnubApi/TransportContract/IHttpClientService.cs new file mode 100644 index 000000000..a86a2c01e --- /dev/null +++ b/src/Api/PubnubApi/TransportContract/IHttpClientService.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; + +namespace PubnubApi +{ + public interface IHttpClientService + { + Task DeleteRequest(TransportRequest transportRequest); + Task GetRequest(TransportRequest transportRequest); + Task PostRequest(TransportRequest transportRequest); + Task PatchRequest(TransportRequest transportRequest); + Task PutRequest(TransportRequest transportRequest); + } +} \ No newline at end of file diff --git a/src/Api/PubnubApi/TransportContract/IMiddleware.cs b/src/Api/PubnubApi/TransportContract/IMiddleware.cs new file mode 100644 index 000000000..a1305473d --- /dev/null +++ b/src/Api/PubnubApi/TransportContract/IMiddleware.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace PubnubApi +{ + public interface ITransportMiddleware + { + TransportRequest PreapareTransportRequest(RequestParameter requestParameter, PNOperationType operationType); + Task Send(TransportRequest transportRequest); + } +} \ No newline at end of file diff --git a/src/Api/PubnubApi/TransportContract/TransportRequest.cs b/src/Api/PubnubApi/TransportContract/TransportRequest.cs new file mode 100644 index 000000000..882764815 --- /dev/null +++ b/src/Api/PubnubApi/TransportContract/TransportRequest.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +namespace PubnubApi +{ + public class TransportRequest + { + public string RequestType { get; set; } + public Dictionary Headers { get; set; } = new Dictionary(); + public string RequestUrl { get; set; } + public byte[] FormData { get; set; } = default; + public string BodyContentString { get; set; } + public byte[] BodyContentBytes { get; set; } + public CancellationToken CancellationToken { get; set; } = default; + public TimeSpan? Timeout { get; set; } = null; + } +} \ No newline at end of file diff --git a/src/Api/PubnubApi/TransportContract/TransportResponse.cs b/src/Api/PubnubApi/TransportContract/TransportResponse.cs new file mode 100644 index 000000000..ae106ec0b --- /dev/null +++ b/src/Api/PubnubApi/TransportContract/TransportResponse.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace PubnubApi +{ + public class TransportResponse + { + public int StatusCode { get; set; } + public byte[] Content { get; set; } + public Dictionary> Headers { get; set; } + public string RequestUrl { get; set; } + public Exception Error { get; set; } + } +} \ No newline at end of file diff --git a/src/Api/PubnubApi/Tuple.cs b/src/Api/PubnubApi/Tuple.cs deleted file mode 100644 index eed3fca84..000000000 --- a/src/Api/PubnubApi/Tuple.cs +++ /dev/null @@ -1,53 +0,0 @@ -#if NET35 || NET40 -namespace System -{ //THIS IS ADDED TO SUPPORT .NET 3.5 and .NET 4.0 BASED SDKs. IF THIS DOES NOT WORK, NEED TO REVIEW NetLegacySupport.Tuple NUGET PACKAGE, TO SEE IF IT CAN WORK - // CS0436,0436 warnings were disabled in project file - public class Tuple - { - public Tuple(T1 item1) - { - Item1 = item1; - } - - public T1 Item1 { get; set; } - } - - public class Tuple : Tuple - { - public Tuple(T1 item1, T2 item2) : base(item1) - { - Item2 = item2; - } - - public T2 Item2 { get; set; } - } - - public class Tuple : Tuple - { - public Tuple(T1 item1, T2 item2, T3 item3) : base(item1, item2) - { - Item3 = item3; - } - - public T3 Item3 { get; set; } - } - - public static class Tuple - { - public static Tuple Create(T1 item1) - { - return new Tuple(item1); - } - - public static Tuple Create(T1 item1, T2 item2) - { - return new Tuple(item1, item2); - } - - public static Tuple Create(T1 item1, T2 item2, T3 item3) - { - return new Tuple(item1, item2, item3); - } - } -} -#endif diff --git a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj index aae15f3e8..8a5b0d112 100644 --- a/src/Api/PubnubApiPCL/PubnubApiPCL.csproj +++ b/src/Api/PubnubApiPCL/PubnubApiPCL.csproj @@ -1,7 +1,7 @@  - netstandard1.0;netstandard1.3;netstandard1.4;netstandard1.1;netstandard2.0;net6.0 + netstandard1.3;netstandard1.4;netstandard2.0;net6.0 latest true True @@ -29,9 +29,6 @@ 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 PubNub 2012-2021 - $(PackageTargetFallback);dnxcore50 - - $(PackageTargetFallback);dnxcore50 @@ -56,8 +53,8 @@ Builder\UriUtil.cs - - Builder\UrlRequestBuilder.cs + + Builder\UrlParameterConverter.cs Callbacks\PNCallback.cs @@ -187,7 +184,6 @@ - EndPoint\TimeOperation.cs @@ -293,9 +289,6 @@ Interface\IJsonPluggableLibrary.cs - - Interface\IPubnubHttp.cs - Interface\IPubnubLog.cs @@ -304,9 +297,6 @@ - - Interface\IUrlRequestBuilder.cs - JsonDataParse\DeserializeToInternalObjectUtility.cs @@ -592,10 +582,6 @@ RetryConfiguration.cs - - PubnubHttp.cs - - Push\Mpns\MpnsCycleTileNotification.cs @@ -619,6 +605,13 @@ + + + + + + + Security\MD5.cs @@ -634,9 +627,6 @@ Security\SecureMessage.cs - - Timer.cs - diff --git a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj index 4c9355528..d10af0c14 100644 --- a/src/Api/PubnubApiUWP/PubnubApiUWP.csproj +++ b/src/Api/PubnubApiUWP/PubnubApiUWP.csproj @@ -29,9 +29,6 @@ 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 PubNub 2012-2021 - - - false @@ -165,8 +162,8 @@ Builder\UriUtil.cs - - Builder\UrlRequestBuilder.cs + + Builder\UrlParameterConverter.cs Callbacks\PNCallback.cs @@ -302,7 +299,6 @@ - EndPoint\TimeOperation.cs @@ -349,11 +345,9 @@ - - @@ -409,9 +403,6 @@ Interface\IJsonPluggableLibrary.cs - - Interface\IPubnubHttp.cs - Interface\ISubscribeOperation.cs @@ -422,9 +413,6 @@ Interface\IPubnubUnitTest.cs - - Interface\IUrlRequestBuilder.cs - JsonDataParse\DeserializeToInternalObjectUtility.cs @@ -629,6 +617,13 @@ + + + + + + + Model\Derived\PNTimeResultExt.cs @@ -711,10 +706,6 @@ RetryConfiguration.cs - - PubnubHttp.cs - - Push\Mpns\MpnsCycleTileNotification.cs @@ -769,9 +760,6 @@ Security\SecureMessage.cs - - Timer.cs - diff --git a/src/Api/PubnubApiUnity/PubnubApiUnity.csproj b/src/Api/PubnubApiUnity/PubnubApiUnity.csproj index ce6284f87..14f3c45c6 100644 --- a/src/Api/PubnubApiUnity/PubnubApiUnity.csproj +++ b/src/Api/PubnubApiUnity/PubnubApiUnity.csproj @@ -1,8 +1,8 @@  - netstandard1.0;netstandard1.3;netstandard1.4;netstandard1.1;netstandard2.0;net6.0 - 9.0 + net6.0;netstandard1.3;netstandard1.4;netstandard2.0 + default true True pubnub.snk @@ -29,9 +29,6 @@ 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 PubNub 2012-2021 - $(PackageTargetFallback);dnxcore50 - - $(PackageTargetFallback);dnxcore50 @@ -56,8 +53,8 @@ Builder\UriUtil.cs - - Builder\UrlRequestBuilder.cs + + Builder\UrlParameterConverter.cs Callbacks\PNCallback.cs @@ -249,7 +246,6 @@ - EndPoint\TimeOperation.cs @@ -301,18 +297,12 @@ Interface\IJsonPluggableLibrary.cs - - Interface\IPubnubHttp.cs - Interface\IPubnubLog.cs Interface\IPubnubUnitTest.cs - - Interface\IUrlRequestBuilder.cs - @@ -592,10 +582,6 @@ PubnubCoreBase.cs - - PubnubHttp.cs - - Push\Mpns\MpnsCycleTileNotification.cs @@ -619,6 +605,13 @@ + + + + + + + Security\MD5.cs @@ -634,9 +627,6 @@ Security\SecureMessage.cs - - Timer.cs - diff --git a/src/UnitTests/PubnubApi.Tests/CleanupGrant.cs b/src/UnitTests/PubnubApi.Tests/CleanupGrant.cs index 43b1103a0..b31781258 100644 --- a/src/UnitTests/PubnubApi.Tests/CleanupGrant.cs +++ b/src/UnitTests/PubnubApi.Tests/CleanupGrant.cs @@ -14,6 +14,17 @@ public class CleanupGrant : TestHarness private static Pubnub pubnub; private static int manualResetEventWaitTimeout = 20 * 1000; + [TearDown] + public static void Exit() + { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } + } + [Test] public static void AtUserLevel() { diff --git a/src/UnitTests/PubnubApi.Tests/EncryptionTests.cs b/src/UnitTests/PubnubApi.Tests/EncryptionTests.cs index 28f73e23d..539012f1e 100644 --- a/src/UnitTests/PubnubApi.Tests/EncryptionTests.cs +++ b/src/UnitTests/PubnubApi.Tests/EncryptionTests.cs @@ -3,17 +3,12 @@ using System.Collections.Generic; using NUnit.Framework; using PubnubApi; -using System.Text.RegularExpressions; -using System.Globalization; using Newtonsoft.Json; using System.Diagnostics; -using System.Linq; -using PeterO.Cbor; using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; using PubnubApi.Security.Crypto.Common; using System.Threading; -using System.Security.Policy; using MockServer; namespace PubNubMessaging.Tests @@ -190,6 +185,8 @@ public void ParseGrantTokenTest() { actual = Newtonsoft.Json.JsonConvert.SerializeObject(pnGrant); } + + pubnub.Destroy(); } catch (Exception ex) { @@ -840,13 +837,17 @@ public void TestPAMv3Signature() public void TestSubscribeDecryption() { server.ClearRequests(); - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } ManualResetEvent done = new ManualResetEvent(false); PNConfiguration config = new PNConfiguration(new UserId("test")) { SubscribeKey = PubnubCommon.SubscribeKey, PublishKey = PubnubCommon.PublishKey, + SecretKey = PubnubCommon.SecretKey, Secure = false }; config.LogVerbosity = PNLogVerbosity.BODY; @@ -909,21 +910,33 @@ public void TestSubscribeDecryption() pn.Subscribe().Channels(new[] { "test" }).Execute(); + Thread.Sleep(1000); + + // Rust generated encrypted message + CreateTestSender().Publish() + .Channel("test") + .Message("UE5FRAFBQ1JIEALf+E65kseYJwTw2J6BUk9MePHiCcBCS+8ykXLkBIOA") + .Execute(new PNPublishResultExt((r,s)=>{})); + bool passed = done.WaitOne(5000); Assert.True(passed); } - + [Test] public void TestSubscribeDecryptionOnNonEncryptedMessage() { server.ClearRequests(); - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } ManualResetEvent done = new ManualResetEvent(false); PNConfiguration config = new PNConfiguration(new UserId("test")) { SubscribeKey = PubnubCommon.SubscribeKey, PublishKey = PubnubCommon.PublishKey, + SecretKey = PubnubCommon.SecretKey }; config.LogVerbosity = PNLogVerbosity.BODY; config.CryptoModule = new CryptoModule(new AesCbcCryptor("enigma"), @@ -982,6 +995,13 @@ public void TestSubscribeDecryptionOnNonEncryptedMessage() pn.Subscribe().Channels(new[] { "test" }).Execute(); + Thread.Sleep(1000); + + CreateTestSender().Publish() + .Channel("test") + .Message("test") + .Execute(new PNPublishResultExt((r,s)=>{})); + bool passed = done.WaitOne(5000); Assert.True(passed); } @@ -1048,7 +1068,7 @@ public void TestHistoryDecryptionOnNonEncryptedMessage() done.Set(); })); - bool passed = done.WaitOne(5000); + bool passed = done.WaitOne(500000); Assert.True(passed); } @@ -1060,5 +1080,18 @@ private PNConfiguration CreateTestConfig() return config; } + + private Pubnub CreateTestSender() + { + var senderConfig = new PNConfiguration(new UserId("test_sender")) + { + SubscribeKey = PubnubCommon.SubscribeKey, + PublishKey = PubnubCommon.PublishKey, + SecretKey = PubnubCommon.SecretKey, + Secure = false, + LogVerbosity = PNLogVerbosity.BODY + }; + return new Pubnub(senderConfig); + } } } \ No newline at end of file diff --git a/src/UnitTests/PubnubApi.Tests/GenerateSampleGrant.cs b/src/UnitTests/PubnubApi.Tests/GenerateSampleGrant.cs index 8d751c3f9..16eeab386 100644 --- a/src/UnitTests/PubnubApi.Tests/GenerateSampleGrant.cs +++ b/src/UnitTests/PubnubApi.Tests/GenerateSampleGrant.cs @@ -26,12 +26,21 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/PubnubCommon.cs b/src/UnitTests/PubnubApi.Tests/PubnubCommon.cs index 40cf67177..ab13c9d53 100644 --- a/src/UnitTests/PubnubApi.Tests/PubnubCommon.cs +++ b/src/UnitTests/PubnubApi.Tests/PubnubCommon.cs @@ -5,14 +5,14 @@ namespace PubNubMessaging.Tests public static class PubnubCommon { private static readonly string EnvPAMServerSideRun = Environment.GetEnvironmentVariable("PN_PAM_SERVER_SIDE"); - private static readonly string EnvPublishKey = Environment.GetEnvironmentVariable("PN_PUB_KEY"); - private static readonly string EnvSubscribeKey = Environment.GetEnvironmentVariable("PN_SUB_KEY"); - private static readonly string EnvSecretKey = Environment.GetEnvironmentVariable("PN_SEC_KEY"); + private static readonly string EnvPublishKey = Environment.GetEnvironmentVariable("PN_PAM_PUB_KEY"); + private static readonly string EnvSubscribeKey = Environment.GetEnvironmentVariable("PN_PAM_SUB_KEY"); + private static readonly string EnvSecretKey = Environment.GetEnvironmentVariable("PN_PAM_SEC_KEY"); public static readonly bool PAMServerSideRun = (!string.IsNullOrEmpty(EnvPAMServerSideRun) && EnvPAMServerSideRun == "1"); public static readonly bool PAMServerSideGrant = !PAMServerSideRun; public static readonly bool SuppressAuthKey = PAMServerSideRun; - public static readonly bool EnableStubTest = true; + public static readonly bool EnableStubTest = false; //USE demo-36 keys for unit tests public static readonly string PublishKey = string.IsNullOrEmpty(EnvPublishKey) ? "demo-36" : EnvPublishKey; diff --git a/src/UnitTests/PubnubApi.Tests/TestHarness.cs b/src/UnitTests/PubnubApi.Tests/TestHarness.cs index 1d3f3642d..8e6d90185 100644 --- a/src/UnitTests/PubnubApi.Tests/TestHarness.cs +++ b/src/UnitTests/PubnubApi.Tests/TestHarness.cs @@ -5,7 +5,7 @@ namespace PubNubMessaging.Tests { public class TestHarness { - protected static Pubnub createPubNubInstance(PNConfiguration pnConfiguration) + protected static Pubnub createPubNubInstance(PNConfiguration pnConfiguration, string authToken = "") { Pubnub pubnub = null; if (PubnubCommon.EnableStubTest) @@ -29,8 +29,13 @@ protected static Pubnub createPubNubInstance(PNConfiguration pnConfiguration) else { pnConfiguration.Origin = "ps.pndsn.com"; + pnConfiguration.EnableEventEngine = false; pubnub = new Pubnub(pnConfiguration); } + if (!string.IsNullOrEmpty(authToken)) + { + pubnub.SetAuthToken(authToken); + } return pubnub; } } diff --git a/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs b/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs index c5f43d8f8..3635f6b5f 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAClientIsPresented.cs @@ -21,7 +21,7 @@ public class WhenAClientIsPresented : TestHarness private static int manualResetEventWaitTimeout = 310 * 1000; private static Pubnub pubnub; private static Server server; - private static string authKey = "myauth"; + private static string authToken; public class TestLog : IPubnubLog { @@ -32,25 +32,32 @@ void IPubnubLog.WriteToLog(string logText) } [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } - - bool receivedGrantMessage = false; + string channel = "hello_my_channel"; + string channel1 = "hello_my_channel_1"; + string channel2 = "hello_my_channel_2"; + string channel3 = "hello_my_channel_3"; + string channel4 = "hello_my_channel_4"; PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - Secure = false + Secure = false, + EnableEventEngine = false }; server.RunOnHttps(false); @@ -63,46 +70,76 @@ public static void Init() .WithPath(string.Format("/v2/auth/grant/sub-key/{0}", PubnubCommon.SubscribeKey)) .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); + + var fullAccess = new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + }; + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() + { + { + channel, fullAccess + }, + { + channel+"-pnpres", fullAccess + }, + { + channel1, fullAccess + }, + { + channel1+"-pnpres", fullAccess + }, + { + channel2, fullAccess + }, + { + channel2+"-pnpres", fullAccess + }, + { + channel3, fullAccess + }, + { + channel3+"-pnpres", fullAccess + }, + { + channel4, fullAccess + }, + { + channel4+"-pnpres", fullAccess + } + } + }).ExecuteAsync(); - ManualResetEvent grantManualEvent = new ManualResetEvent(false); - pubnub.Grant().Channels(new [] { channel, channel+"-pnpres" }).AuthKeys(new [] { authKey }).Read(true).Write(true).Manage(true).TTL(20) - .Execute(new PNAccessManagerGrantResultExt( - (r, s) => - { - try - { - Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(s)); - if (r != null) - { - Debug.WriteLine("PNAccessManagerGrantResult={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(r)); - if (r.Channels != null && r.Channels.Count > 0) - { - var read = r.Channels[channel][authKey].ReadEnabled; - var write = r.Channels[channel][authKey].WriteEnabled; - if (read && write) { receivedGrantMessage = true; } - } - } - } - catch { /* ignore */ } - finally - { - grantManualEvent.Set(); - } - })); - - Thread.Sleep(100); + await Task.Delay(4000); - grantManualEvent.WaitOne(manualResetEventWaitTimeout); + authToken = grantResult.Result?.Token; pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenAClientIsPresent Grant access failed."); + Assert.IsTrue(grantResult.Status.Error == false && grantResult.Result != null, + "WhenAClientIsPresent Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -145,10 +182,7 @@ public static void ThenPresenceShouldReturnReceivedMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + server.RunOnHttps(false); ManualResetEvent presenceManualEvent = new ManualResetEvent(false); @@ -169,13 +203,13 @@ public static void ThenPresenceShouldReturnReceivedMessage() } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); } - string channel = "hello_my_channel"; + string channel = "hello_my_channel_3"; manualResetEventWaitTimeout = 310 * 1000; string expected = "{\"t\":{\"t\":\"14833694874957031\",\"r\":7},\"m\":[{\"a\":\"4\",\"f\":512,\"p\":{\"t\":\"14833694873794045\",\"r\":2},\"k\":\"demo-36\",\"c\":\"hello_my_channel-pnpres\",\"d\":{\"action\": \"join\", \"timestamp\": 1483369487, \"uuid\": \"mylocalmachine.mydomain.com\", \"occupancy\": 1},\"b\":\"hello_my_channel-pnpres\"}]}"; @@ -241,10 +275,6 @@ public static void ThenPresenceShouldReturnReceivedMessageSSL() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(true); @@ -264,14 +294,14 @@ public static void ThenPresenceShouldReturnReceivedMessageSSL() presenceManualEvent.Set(); } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); } - string channel = "hello_my_channel"; + string channel = "hello_my_channel_4"; manualResetEventWaitTimeout = 310 * 1000; string expected = "{\"t\":{\"t\":\"14833694874957031\",\"r\":7},\"m\":[{\"a\":\"4\",\"f\":512,\"p\":{\"t\":\"14833694873794045\",\"r\":2},\"k\":\"demo-36\",\"c\":\"hello_my_channel-pnpres\",\"d\":{\"action\": \"join\", \"timestamp\": 1483369487, \"uuid\": \"mylocalmachine.mydomain.com\", \"occupancy\": 1},\"b\":\"hello_my_channel-pnpres\"}]}"; @@ -300,12 +330,12 @@ public static void ThenPresenceShouldReturnReceivedMessageSSL() pubnub.Subscribe().Channels(new [] { channel }).WithPresence().Execute(); presenceManualEvent.WaitOne(manualResetEventWaitTimeout); - if (!PubnubCommon.EnableStubTest) { Thread.Sleep(1000); } + if (!PubnubCommon.EnableStubTest) { Thread.Sleep(4000); } else { Thread.Sleep(100); } pubnub.Unsubscribe().Channels(new [] { channel }).Execute(); - Thread.Sleep(100); + Thread.Sleep(4000); if (!pubnub.RemoveListener(listenerSubCallack)) { @@ -321,8 +351,7 @@ public static void ThenPresenceShouldReturnReceivedMessageSSL() public static void ThenPresenceShouldReturnCustomUserId() { server.ClearRequests(); - - UserId customUserId = new UserId("mylocalmachine.mydomain.com"); + bool receivedCustomUUID = false; PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) @@ -335,10 +364,6 @@ public static void ThenPresenceShouldReturnCustomUserId() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -358,17 +383,15 @@ public static void ThenPresenceShouldReturnCustomUserId() presenceManualEvent.Set(); } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); } - string channel = "hello_my_channel"; + string channel = "hello_my_channel_2"; manualResetEventWaitTimeout = 310 * 1000; - pubnub.ChangeUserId(customUserId); - string expected = "{\"t\":{\"t\":\"14833694874957031\",\"r\":7},\"m\":[{\"a\":\"4\",\"f\":512,\"p\":{\"t\":\"14833694873794045\",\"r\":2},\"k\":\"demo-36\",\"c\":\"hello_my_channel-pnpres\",\"d\":{\"action\": \"join\", \"timestamp\": 1483369487, \"uuid\": \"mylocalmachine.mydomain.com\", \"occupancy\": 1},\"b\":\"hello_my_channel-pnpres\"}]}"; server.AddRequest(new Request() @@ -379,7 +402,7 @@ public static void ThenPresenceShouldReturnCustomUserId() .WithParameter("requestid", "myRequestId") .WithParameter("timestamp", "1356998400") .WithParameter("tt", "0") - .WithParameter("uuid", customUserId.ToString()) + //.WithParameter("uuid", customUserId.ToString()) .WithParameter("signature", "D7lw9Np5UU_xUTUAe0Sc0L0eSP9aTQljeith_M_rXzI=") .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); @@ -431,10 +454,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); ManualResetEvent subscribeManualEvent = new ManualResetEvent(false); @@ -452,7 +471,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfo() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -555,10 +574,6 @@ public static async Task IfWithAsyncHereNowIsCalledThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); ManualResetEvent subscribeManualEvent = new ManualResetEvent(false); @@ -576,7 +591,7 @@ public static async Task IfWithAsyncHereNowIsCalledThenItShouldReturnInfo() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -678,10 +693,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipher() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -701,7 +712,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipher() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -799,10 +810,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipherSecret() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(true); @@ -820,7 +827,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipherSecret() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -918,10 +925,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipherSecretSSL() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(true); @@ -939,7 +942,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipherSecretSSL() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1038,10 +1041,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipherSSL() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(true); @@ -1060,7 +1059,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoCipherSSL() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1157,10 +1156,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoSecret() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -1178,7 +1173,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoSecret() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1275,10 +1270,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoSecretSSL() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(true); @@ -1296,7 +1287,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoSecretSSL() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1394,10 +1385,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoSSL() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(true); @@ -1416,7 +1403,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoSSL() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1515,10 +1502,6 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoWithUserState() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -1537,7 +1520,7 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoWithUserState() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1655,7 +1638,8 @@ public static void IfHereNowIsCalledThenItShouldReturnInfoWithUserState() Assert.IsTrue(receivedHereNowMessage, "here_now message not received with user state"); } - [Test] + //TODO: CLEN-2044 + //[Test] public static void IfGlobalHereNowIsCalledThenItShouldReturnInfo() { server.ClearRequests(); @@ -1673,10 +1657,6 @@ public static void IfGlobalHereNowIsCalledThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); ManualResetEvent subscribeManualEvent = new ManualResetEvent(false); @@ -1693,7 +1673,7 @@ public static void IfGlobalHereNowIsCalledThenItShouldReturnInfo() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1790,7 +1770,8 @@ public static void IfGlobalHereNowIsCalledThenItShouldReturnInfo() Assert.IsTrue(receivedHereNowMessage, "global_here_now message not received"); } - [Test] + //TODO: CLEN-2044 + //[Test] public static void IfGlobalHereNowIsCalledThenItShouldReturnInfoWithUserState() { server.ClearRequests(); @@ -1807,10 +1788,6 @@ public static void IfGlobalHereNowIsCalledThenItShouldReturnInfoWithUserState() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -1828,7 +1805,7 @@ public static void IfGlobalHereNowIsCalledThenItShouldReturnInfoWithUserState() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -1958,10 +1935,6 @@ public static void IfWhereNowIsCalledThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -1979,7 +1952,7 @@ public static void IfWhereNowIsCalledThenItShouldReturnInfo() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -2080,10 +2053,6 @@ public static async Task IfWithAsyncWhereNowIsCalledThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -2101,7 +2070,7 @@ public static async Task IfWithAsyncWhereNowIsCalledThenItShouldReturnInfo() } subscribeManualEvent.Set(); }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); @@ -2188,8 +2157,7 @@ public static async Task IfWithAsyncWhereNowIsCalledThenItShouldReturnInfo() public static void IfSetAndGetUserStateThenItShouldReturnInfo() { server.ClearRequests(); - - UserId customUserId = new UserId("mylocalmachine.mydomain.com"); + bool receivedUserStateMessage = false; PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) @@ -2202,15 +2170,10 @@ public static void IfSetAndGetUserStateThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); - pubnub.ChangeUserId(customUserId); + pubnub = createPubNubInstance(config, authToken); manualResetEventWaitTimeout = 310 * 1000; string channel = "hello_my_channel"; @@ -2221,7 +2184,7 @@ public static void IfSetAndGetUserStateThenItShouldReturnInfo() string expected = "{\"status\": 200, \"message\": \"OK\", \"payload\": {\"testkey\": \"testval\"}, \"service\": \"Presence\"}"; server.AddRequest(new Request() .WithMethod("GET") - .WithPath(String.Format("/v2/presence/sub_key/{0}/channel/{1}/uuid/{2}/data", PubnubCommon.SubscribeKey, channel, customUserId.ToString())) + //.WithPath(String.Format("/v2/presence/sub_key/{0}/channel/{1}/uuid/{2}/data", PubnubCommon.SubscribeKey, channel, customUserId.ToString())) .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); @@ -2249,7 +2212,7 @@ public static void IfSetAndGetUserStateThenItShouldReturnInfo() expected = "{\"status\": 200, \"uuid\": \"mylocalmachine.mydomain.com\", \"service\": \"Presence\", \"message\": \"OK\", \"payload\": {\"testkey\": \"testval\"}, \"channel\": \"hello_my_channel\"}"; server.AddRequest(new Request() .WithMethod("GET") - .WithPath(String.Format("/v2/presence/sub_key/{0}/channel/{1}/uuid/{2}", PubnubCommon.SubscribeKey, channel, customUserId.ToString())) + //.WithPath(String.Format("/v2/presence/sub_key/{0}/channel/{1}/uuid/{2}", PubnubCommon.SubscribeKey, channel, customUserId.ToString())) .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); @@ -2287,14 +2250,10 @@ public static void IfSetAndDeleteUserStateThenItShouldReturnInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); manualResetEventWaitTimeout = 310 * 1000; string channel = "hello_my_channel"; @@ -2442,10 +2401,6 @@ public static void ThenPresenceHeartbeatShouldReturnMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -2465,14 +2420,14 @@ public static void ThenPresenceHeartbeatShouldReturnMessage() presenceManualEvent.Set(); } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); if (!pubnub.AddListener(listenerSubCallack)) { System.Diagnostics.Debug.WriteLine("ATTENTION: AddListener failed"); } - string channel = "hello_my_channel"; + string channel = "hello_my_channel_1"; manualResetEventWaitTimeout = 310 * 1000; string expected = "{\"t\":{\"t\":\"14828440156769626\",\"r\":7},\"m\":[{\"a\":\"4\",\"f\":512,\"p\":{\"t\":\"14828440155770431\",\"r\":2},\"k\":\"demo-36\",\"c\":\"hello_my_channel-pnpres\",\"d\":{\"action\": \"join\", \"timestamp\": 1482844015, \"uuid\": \"mytestuuid\", \"occupancy\": 1},\"b\":\"hello_my_channel-pnpres\"}]}"; diff --git a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs index da6619b8e..93e9a6367 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsPublished.cs @@ -35,7 +35,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -112,6 +115,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs index 4c1e2b22a..e46ca84ff 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAMessageIsSignaled.cs @@ -29,7 +29,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -106,6 +109,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenAuditIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenAuditIsRequested.cs index 05a3ea686..83e267a48 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenAuditIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenAuditIsRequested.cs @@ -25,12 +25,21 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -80,6 +89,9 @@ public static void ThenSubKeyLevelShouldReturnSuccess() } else { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.Ignore("PAM Not Enabled for WhenAuditIsRequested -> ThenSubKeyLevelShouldReturnSuccess"); } @@ -135,6 +147,9 @@ public static void ThenChannelLevelShouldReturnSuccess() } else { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.Ignore("PAM Not Enabled for WhenAuditIsRequested -> ThenChannelLevelShouldReturnSuccess"); } } @@ -187,6 +202,9 @@ public static void ThenChannelGroupLevelShouldReturnSuccess() } else { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; Assert.Ignore("PAM Not Enabled for WhenAuditIsRequested -> ThenChannelGroupLevelShouldReturnSuccess"); } } diff --git a/src/UnitTests/PubnubApi.Tests/WhenChannelGroupIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenChannelGroupIsRequested.cs index 87f4233b6..75eac890c 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenChannelGroupIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenChannelGroupIsRequested.cs @@ -33,7 +33,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { @@ -73,7 +76,7 @@ public static void Init() pubnub.Grant().ChannelGroups(new [] { channelGroupName }).AuthKeys(new [] { authKey }).Read(true).Write(true).Manage(true).TTL(20).Execute(new GrantResult()); - Thread.Sleep(1000); + Thread.Sleep(3000); grantManualEvent.WaitOne(); @@ -86,6 +89,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -182,12 +191,8 @@ public static async Task ThenWithAsyncAddChannelShouldReturnSuccess() .WithStatusCode(System.Net.HttpStatusCode.OK)); channelGroupManualEvent = new ManualResetEvent(false); - -#if NET40 - PNResult cgAddResult = Task.Factory.StartNew(async () => await pubnub.AddChannelsToChannelGroup().Channels(new[] { channelName }).ChannelGroup(channelGroupName).ExecuteAsync()).Result.Result; -#else + PNResult cgAddResult = await pubnub.AddChannelsToChannelGroup().Channels(new[] { channelName }).ChannelGroup(channelGroupName).ExecuteAsync(); -#endif Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(cgAddResult.Status)); if (cgAddResult.Result != null) diff --git a/src/UnitTests/PubnubApi.Tests/WhenDetailedHistoryIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenDetailedHistoryIsRequested.cs index 97b6e4c5d..b01089d3b 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenDetailedHistoryIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenDetailedHistoryIsRequested.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using MockServer; using System.Diagnostics; +using System.Threading.Tasks; using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; @@ -19,20 +20,22 @@ public class WhenDetailedHistoryIsRequested : TestHarness private static int manualResetEventWaitTimeout = 310 * 1000; private static Pubnub pubnub; private static Server server; - private static string authKey = "myauth"; + private static string authToken; [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } - - bool receivedGrantMessage = false; + string channel = "hello_my_channel"; PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) @@ -40,7 +43,6 @@ public static void Init() PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - AuthKey = authKey, Secure = false }; server.RunOnHttps(false); @@ -54,7 +56,7 @@ public static void Init() server.AddRequest(new Request() .WithMethod("GET") .WithPath(string.Format("/v2/auth/grant/sub-key/{0}", PubnubCommon.SubscribeKey)) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel", grantChannel) .WithParameter("m", "1") .WithParameter("pnsdk", PubnubCommon.EncodedSDK) @@ -68,43 +70,49 @@ public static void Init() .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); - ManualResetEvent grantManualEvent = new ManualResetEvent(false); - pubnub.Grant().Channels(new [] { grantChannel }).AuthKeys(new [] { authKey }).Read(true).Write(true).Manage(true).TTL(20) - .Execute(new PNAccessManagerGrantResultExt((r,s)=> { - try + var fullAccess = new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + }; + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() { - Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(s)); - - if (r != null) { - Debug.WriteLine("PNAccessManagerGrantResult={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(r)); - if (r.Channels != null && r.Channels.Count > 0) - { - var read = r.Channels[channel][authKey].ReadEnabled; - var write = r.Channels[channel][authKey].WriteEnabled; - if (read && write) - { - receivedGrantMessage = true; - } - } + grantChannel, fullAccess } } - catch { /* ignore */ } - finally { grantManualEvent.Set(); } - })); - Thread.Sleep(1000); - grantManualEvent.WaitOne(); + }).ExecuteAsync(); + + await Task.Delay(4000); + + authToken = grantResult.Result?.Token; pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenDetailedHistoryIsRequested Grant access failed."); + Assert.IsTrue(grantResult.Result != null && grantResult.Status.Error == false, + "WhenDetailedHistoryIsRequested Grant access failed."); } [TearDown] public static void Exit() { server.Stop(); + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } } [Test] @@ -125,14 +133,10 @@ public static void DetailHistoryNoStoreShouldNotGetMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; string message = messageForNoStorePublish; @@ -233,10 +237,6 @@ public static void DetailHistoryShouldReturnDecryptMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -244,7 +244,7 @@ public static void DetailHistoryShouldReturnDecryptMessage() config.AuthKey = "myAuth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; string message = messageForPublish; @@ -346,10 +346,6 @@ public static void DetailHistoryCount10ReturnsRecords() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -357,7 +353,7 @@ public static void DetailHistoryCount10ReturnsRecords() config.AuthKey = "myAuth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; manualResetEventWaitTimeout = (PubnubCommon.EnableStubTest) ? 1000 : 310 * 1000; @@ -410,10 +406,6 @@ public static void DetailHistoryCount10ReverseTrueReturnsRecords() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -421,7 +413,7 @@ public static void DetailHistoryCount10ReverseTrueReturnsRecords() config.AuthKey = "myAuth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; @@ -476,10 +468,6 @@ public static void DetailedHistoryStartWithReverseTrue() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -487,7 +475,7 @@ public static void DetailedHistoryStartWithReverseTrue() config.AuthKey = "myAuth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; @@ -728,14 +716,10 @@ private static void CommonDetailedHistoryShouldReturnEncryptedMessageBasedOnPara { config.SecretKey = secretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(ssl); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; @@ -1069,14 +1053,10 @@ private static void CommonDetailedHistoryShouldReturnUnencryptedMessageBasedOnPa { config.SecretKey = secretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(ssl); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; diff --git a/src/UnitTests/PubnubApi.Tests/WhenFetchHistoryIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenFetchHistoryIsRequested.cs index e813d5659..af4725cee 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenFetchHistoryIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenFetchHistoryIsRequested.cs @@ -29,7 +29,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -105,6 +108,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs index b6e4e5d68..b91a8cd98 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenFileIsRequested.cs @@ -1,4 +1,5 @@ -using NUnit.Framework; +using System; +using NUnit.Framework; using System.Threading; using PubnubApi; using System.Collections.Generic; @@ -12,94 +13,102 @@ namespace PubNubMessaging.Tests [TestFixture] public class WhenFileIsRequested : TestHarness { - private static ManualResetEvent mre = new ManualResetEvent(false); - private static ManualResetEvent grantManualEvent = new ManualResetEvent(false); - - private static bool receivedMessage = false; - private static bool receivedGrantMessage = false; - - private static string currentUnitTestCase = ""; - //private static string channelGroupName = "hello_my_group"; private static string channelName = "hello_my_channel"; - private static string authKey = "myauth"; + private static string token; private static Pubnub pubnub; private static Server server; [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } - receivedGrantMessage = false; - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - AuthKey = authKey, Secure = false }; pubnub = createPubNubInstance(config); - 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)=> - { - if (r != null) + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() { - receivedGrantMessage = true; + { + channelName, new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + } + } } - grantManualEvent.Set(); - })); - - Thread.Sleep(1000); - - grantManualEvent.WaitOne(2000); + }).ExecuteAsync(); + + await Task.Delay(3000); + token = grantResult.Result?.Token; + pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenFileUploadIsRequested Grant access failed."); + Assert.IsTrue(grantResult.Status.Error == false && grantResult.Result != null, + "WhenFileUploadIsRequested Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } + server.Stop(); } [Test] - public static void ThenSendFileShouldReturnSuccess() + public static void ThenSendAndDeleteFileShouldReturnSuccess() { server.ClearRequests(); - receivedMessage = false; - bool receivedEvent = false; + var eventReset = new ManualResetEvent(false); SubscribeCallbackExt eventListener = new SubscribeCallbackExt( - delegate (Pubnub pnObj, PNFileEventResult eventResult) + delegate(Pubnub pnObj, PNFileEventResult eventResult) { - receivedEvent = true; - System.Diagnostics.Debug.WriteLine("FILE EVENT: " + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); + eventReset.Set(); + System.Diagnostics.Debug.WriteLine("FILE EVENT: " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); }, - delegate (Pubnub pnObj, PNStatus status) - { - - } - ); + delegate(Pubnub pnObj, PNStatus status) { } + ); - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, @@ -109,100 +118,112 @@ public static void ThenSendFileShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); + pubnub.AddListener(eventListener); - mre = new ManualResetEvent(false); + pubnub.Subscribe().Channels(new string[] { channelName }).Execute(); - mre.WaitOne(2000); - mre = new ManualResetEvent(false); + var messageReset = new ManualResetEvent(false); string fileId = ""; string fileName = ""; - receivedMessage = false; + string targetFileUpload = @"fileupload.txt"; - pubnub.SendFile().Channel(channelName).File(targetFileUpload).CipherKey("enigma").Message("This is my sample file") + pubnub.SendFile().Channel(channelName).File(targetFileUpload).CipherKey("enigma") + .Message("This is my sample file") .Execute(new PNFileUploadResultExt((result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("SendFile result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); + System.Diagnostics.Debug.WriteLine("SendFile result = " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); fileId = result.FileId; fileName = result.FileName; - receivedMessage = true; + messageReset.Set(); } else { - System.Diagnostics.Debug.WriteLine("SendFile failed = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(status)); + System.Diagnostics.Debug.WriteLine("SendFile failed = " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(status)); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(3 * 1000 * 60); + var receivedMessage = messageReset.WaitOne(3 * 1000 * 60); + Assert.IsTrue(receivedMessage, "Send File Failed"); + if (receivedMessage) { - receivedMessage = false; - mre = new ManualResetEvent(false); + messageReset = new ManualResetEvent(false); pubnub.ListFiles().Channel(channelName) .Execute(new PNListFilesResultExt((result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("ListFiles result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine("ListFiles result = " + + pubnub.JsonPluggableLibrary + .SerializeToJsonString(result)); + messageReset.Set(); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(2 * 1000 * 60); + receivedMessage = messageReset.WaitOne(2 * 1000 * 60); } + + Assert.IsTrue(receivedMessage, "List Files Failed"); if (receivedMessage) { - System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072; //Need this line for .net 3.5/4.0/4.5 - receivedMessage = false; - mre = new ManualResetEvent(false); - pubnub.DownloadFile().Channel(channelName).FileId(fileId).FileName(fileName).Execute(new PNDownloadFileResultExt((result, status) => - { - if (result != null && result.FileBytes != null && result.FileBytes.Length > 0) + System.Net.ServicePointManager.SecurityProtocol = + (System.Net.SecurityProtocolType)3072; //Need this line for .net 3.5/4.0/4.5 + messageReset = new ManualResetEvent(false); + pubnub.DownloadFile().Channel(channelName).FileId(fileId).FileName(fileName).Execute( + new PNDownloadFileResultExt((result, status) => { - System.Diagnostics.Debug.WriteLine("DownloadFile result = " + result.FileBytes.Length); - receivedMessage = true; - } - mre.Set(); - })); - mre.WaitOne(2 * 1000 * 60); + if (result != null && result.FileBytes != null && result.FileBytes.Length > 0) + { + System.Diagnostics.Debug.WriteLine( + "DownloadFile result = " + result.FileBytes.Length); + messageReset.Set(); + } + })); + receivedMessage = messageReset.WaitOne(2 * 1000 * 60); } + + Assert.IsTrue(receivedMessage, "Download File Failed"); if (receivedMessage) { - receivedMessage = false; - mre = new ManualResetEvent(false); + messageReset = new ManualResetEvent(false); pubnub.DeleteFile().Channel(channelName).FileId(fileId).FileName(fileName) .Execute(new PNDeleteFileResultExt((result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("DeleteFile result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine("DeleteFile result = " + + pubnub.JsonPluggableLibrary + .SerializeToJsonString(result)); + messageReset.Set(); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(2 * 1000 * 60); + receivedMessage = messageReset.WaitOne(2 * 1000 * 60); + } + + Assert.IsTrue(receivedMessage, "Delete File Failed"); + var receivedEvent = false; + if (receivedMessage) + { + receivedEvent = eventReset.WaitOne(2 * 1000 * 60); } pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedMessage && receivedEvent, "WhenFileIsRequested -> TheSendFileShouldReturnSuccess failed."); + Assert.IsTrue(receivedEvent, "Receiving file event failed."); + Assert.IsTrue(receivedMessage, "WhenFileIsRequested -> TheSendFileShouldReturnSuccess failed."); } [Test] @@ -214,22 +235,19 @@ public static async Task ThenWithAsyncSendFileShouldReturnSuccess() { server.ClearRequests(); - receivedMessage = false; - bool receivedEvent = false; + var eventReset = new ManualResetEvent(false); SubscribeCallbackExt eventListener = new SubscribeCallbackExt( - delegate (Pubnub pnObj, PNFileEventResult eventResult) + delegate(Pubnub pnObj, PNFileEventResult eventResult) { - receivedEvent = true; - System.Diagnostics.Debug.WriteLine("FILE EVENT: " + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); + eventReset.Set(); + System.Diagnostics.Debug.WriteLine("FILE EVENT: " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); }, - delegate (Pubnub pnObj, PNStatus status) - { + delegate(Pubnub pnObj, PNStatus status) { } + ); - } - ); - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, @@ -239,95 +257,95 @@ public static async Task ThenWithAsyncSendFileShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); pubnub.AddListener(eventListener); - mre = new ManualResetEvent(false); pubnub.Subscribe().Channels(new string[] { channelName }).Execute(); - mre.WaitOne(2000); - - mre = new ManualResetEvent(false); string fileId = ""; string fileName = ""; - receivedMessage = false; string targetFileUpload = @"fileupload.txt"; Dictionary myInternalMsg = new Dictionary(); myInternalMsg.Add("color", "red"); myInternalMsg.Add("name", "John Doe"); #if NET40 - PNResult sendFileResult = Task.Factory.StartNew(async () => await pubnub.SendFile().Channel(channelName).File(targetFileUpload).Message(myInternalMsg).ExecuteAsync()).Result.Result; + PNResult sendFileResult = + Task.Factory.StartNew(async () => await pubnub.SendFile().Channel(channelName).File(targetFileUpload).Message(myInternalMsg).ExecuteAsync()).Result.Result; #else - PNResult sendFileResult = await pubnub.SendFile().Channel(channelName).File(targetFileUpload).Message(myInternalMsg).ExecuteAsync(); + PNResult sendFileResult = await pubnub.SendFile().Channel(channelName) + .File(targetFileUpload).Message(myInternalMsg).ExecuteAsync(); #endif - if (sendFileResult.Result != null && !string.IsNullOrEmpty(sendFileResult.Result.FileId) && sendFileResult.Result.Timetoken > 0) + if (sendFileResult.Result != null && !string.IsNullOrEmpty(sendFileResult.Result.FileId) && + sendFileResult.Result.Timetoken > 0) { - System.Diagnostics.Debug.WriteLine("SendFile result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(sendFileResult.Result)); + System.Diagnostics.Debug.WriteLine("SendFile result = " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(sendFileResult + .Result)); fileId = sendFileResult.Result.FileId; fileName = sendFileResult.Result.FileName; - receivedMessage = true; } - receivedMessage = false; - mre = new ManualResetEvent(false); + var messageReset = new ManualResetEvent(false); pubnub.ListFiles().Channel(channelName) .Execute(new PNListFilesResultExt((result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("ListFiles result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine("ListFiles result = " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); + messageReset.Set(); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(2 * 1000 * 60); - + var receivedMessage = messageReset.WaitOne(2 * 1000 * 60); if (receivedMessage) { - System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072; //Need this line for .net 3.5/4.0/4.5 + System.Net.ServicePointManager.SecurityProtocol = + (System.Net.SecurityProtocolType)3072; //Need this line for .net 3.5/4.0/4.5 receivedMessage = false; - mre = new ManualResetEvent(false); - pubnub.DownloadFile().Channel(channelName).FileId(fileId).FileName(fileName).Execute(new PNDownloadFileResultExt((result, status) => - { - if (result != null && result.FileBytes != null && result.FileBytes.Length > 0) + messageReset = new ManualResetEvent(false); + pubnub.DownloadFile().Channel(channelName).FileId(fileId).FileName(fileName).Execute( + new PNDownloadFileResultExt((result, status) => { - System.Diagnostics.Debug.WriteLine("DownloadFile result = " + result.FileBytes.Length); - receivedMessage = true; - } - mre.Set(); - })); - mre.WaitOne(2 * 1000 * 60); + if (result != null && result.FileBytes != null && result.FileBytes.Length > 0) + { + System.Diagnostics.Debug.WriteLine("DownloadFile result = " + result.FileBytes.Length); + messageReset.Set(); + } + })); + receivedMessage = messageReset.WaitOne(2 * 1000 * 60); } if (receivedMessage) { - receivedMessage = false; - mre = new ManualResetEvent(false); + messageReset = new ManualResetEvent(false); pubnub.DeleteFile().Channel(channelName).FileId(fileId).FileName(fileName) .Execute(new PNDeleteFileResultExt((result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("DeleteFile result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine("DeleteFile result = " + + pubnub.JsonPluggableLibrary + .SerializeToJsonString(result)); + messageReset.Set(); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(2 * 1000 * 60); + receivedMessage = messageReset.WaitOne(2 * 1000 * 60); + } + var receivedEvent = false; + if (receivedMessage) + { + receivedEvent = eventReset.WaitOne(10000); } pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedMessage && receivedEvent, "WhenFileIsRequested -> ThenWithAsyncSendFileShouldReturnSuccess failed."); + Assert.IsTrue(receivedMessage && receivedEvent, + "WhenFileIsRequested -> ThenWithAsyncSendFileShouldReturnSuccess failed."); } //[Test] @@ -335,9 +353,7 @@ public static void ThenDownloadFileShouldReturnSuccess() { server.ClearRequests(); - receivedMessage = false; - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, @@ -347,36 +363,31 @@ public static void ThenDownloadFileShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); - mre = new ManualResetEvent(false); + var messageReset = new ManualResetEvent(false); string fileId = "b0a5c0df-7523-432e-8ea9-01567c93da7d"; string fileName = "pandu_test.gif"; - receivedMessage = false; - pubnub.DownloadFile().Channel(channelName).FileId(fileId).FileName(fileName).CipherKey("enigma").Execute(new PNDownloadFileResultExt((result, status) => - { - if (result != null) + pubnub.DownloadFile().Channel(channelName).FileId(fileId).FileName(fileName).CipherKey("enigma").Execute( + new PNDownloadFileResultExt((result, status) => { - //result.SaveToLocal(@"C:\Pandu\temp\new\output\hi_file.gif"); - //result.SaveToLocal(@"C:\Pandu\temp\new\"); - result.SaveFileToLocal("what_is_hi_file.gif"); - receivedMessage = true; - } - mre.Set(); - })); - Thread.Sleep(1000); - mre.WaitOne(); + if (result != null) + { + //result.SaveToLocal(@"C:\Pandu\temp\new\output\hi_file.gif"); + //result.SaveToLocal(@"C:\Pandu\temp\new\"); + result.SaveFileToLocal("what_is_hi_file.gif"); + messageReset.Set(); + } + })); + var receivedMessage = messageReset.WaitOne(4000); pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; Assert.IsTrue(receivedMessage, "WhenFileIsRequested -> ThenListFilesShouldReturnSuccess failed."); - } [Test] @@ -384,9 +395,7 @@ public static void ThenGetFileUrlShouldReturnSuccess() { server.ClearRequests(); - receivedMessage = false; - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, @@ -396,92 +405,37 @@ public static void ThenGetFileUrlShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); - mre = new ManualResetEvent(false); + var messageReset = new ManualResetEvent(false); string fileId = "bc03db55-6345-4a0f-aa58-beac970b2c5b"; string fileName = "whoami.txt"; - receivedMessage = false; - pubnub.GetFileUrl().Channel(channelName).FileId(fileId).FileName(fileName).Execute(new PNFileUrlResultExt((result, status) => - { - if (result != null) - { - System.Diagnostics.Debug.WriteLine(result.Url); - receivedMessage = true; - } - mre.Set(); - })); - Thread.Sleep(1000); - mre.WaitOne(); - - pubnub.Destroy(); - pubnub.PubnubUnitTest = null; - pubnub = null; - Assert.IsTrue(receivedMessage, "WhenFileIsRequested -> ThenListFilesShouldReturnSuccess failed."); - - } - - - [Test] - public static void ThenListFilesShouldReturnSuccess() - { - server.ClearRequests(); - - receivedMessage = false; - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) - { - PublishKey = PubnubCommon.PublishKey, - SubscribeKey = PubnubCommon.SubscribeKey, - CryptoModule = new CryptoModule(new LegacyCryptor("enigma"), null), - Secure = false - }; - if (PubnubCommon.PAMServerSideRun) - { - config.SecretKey = PubnubCommon.SecretKey; - } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } - pubnub = createPubNubInstance(config); - - receivedMessage = false; - mre = new ManualResetEvent(false); - pubnub.ListFiles().Channel(channelName) - .Execute(new PNListFilesResultExt((result, status) => + pubnub.GetFileUrl().Channel(channelName).FileId(fileId).FileName(fileName).Execute(new PNFileUrlResultExt( + (result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine(result.Url); + messageReset.Set(); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(); + var receivedMessage = messageReset.WaitOne(5000); pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; Assert.IsTrue(receivedMessage, "WhenFileIsRequested -> ThenListFilesShouldReturnSuccess failed."); - } - [Test] - public static void ThenDeleteFileShouldReturnSuccess() + public static void ThenListFilesShouldReturnSuccess() { server.ClearRequests(); - receivedMessage = false; - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, @@ -492,60 +446,27 @@ public static void ThenDeleteFileShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } - pubnub = createPubNubInstance(config); - - 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) - { - List filesList = listFilesResponse.Result.FilesList; - foreach (var file in filesList) - { - PNResult deleteFileResponse = pubnub.DeleteFile().Channel(channelName).FileId(file.Id).FileName(file.Name).ExecuteAsync().Result; - PNDeleteFileResult deleteFileResult = deleteFileResponse.Result; - if (deleteFileResult != null) - { - System.Diagnostics.Debug.WriteLine(string.Format("File Id={0}, Name={1} => deleted successfully", file.Id, file.Name)); - } - } - receivedMessage = true; - } - else - { - PNResult deleteFileResponse = pubnub.DeleteFile().Channel(channelName).FileId("test_file_id").FileName("test_file_name.test").ExecuteAsync().Result; - PNDeleteFileResult deleteFileResult = deleteFileResponse.Result; - if (deleteFileResult != null) - { - System.Diagnostics.Debug.WriteLine("File Id=test_file_id, Name=test_file_name.test => deleted successfully"); - receivedMessage = true; - } - } + pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); - mre = new ManualResetEvent(false); - receivedMessage = false; - pubnub.DeleteFile().Channel(channelName).FileId("8f83d951-7850-40fb-9688-d2d825b14722").FileName("word_test.txt") - .Execute(new PNDeleteFileResultExt((result, status) => + var messageReset = new ManualResetEvent(false); + pubnub.ListFiles().Channel(channelName) + .Execute(new PNListFilesResultExt((result, status) => { if (result != null) { - System.Diagnostics.Debug.WriteLine("result = " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine("result = " + + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); + messageReset.Set(); } - mre.Set(); })); - Thread.Sleep(1000); - mre.WaitOne(); + var receivedMessage = messageReset.WaitOne(5000); pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedMessage, "WhenFileIsRequested -> ThenListFilesShouldReturnSuccess failed."); - + Assert.IsTrue(receivedMessage, $"WhenFileIsRequested -> ThenListFilesShouldReturnSuccess failed."); } [Test] @@ -557,9 +478,7 @@ public static async Task ThenWithAsyncDeleteFileShouldReturnSuccess() { server.ClearRequests(); - receivedMessage = false; - - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) + PNConfiguration config = new PNConfiguration(new UserId("mytestuuid_file_tests")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, @@ -570,56 +489,65 @@ public static async Task ThenWithAsyncDeleteFileShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); - receivedMessage = false; + var messageReset = new ManualResetEvent(false); #if NET40 - PNResult listFilesResponse = Task.Factory.StartNew(async () => await pubnub.ListFiles().Channel(channelName).ExecuteAsync()).Result.Result; + PNResult listFilesResponse = + Task.Factory.StartNew(async () => await pubnub.ListFiles().Channel(channelName).ExecuteAsync()).Result.Result; #else - PNResult listFilesResponse = await pubnub.ListFiles().Channel(channelName).ExecuteAsync(); + PNResult listFilesResponse = + await pubnub.ListFiles().Channel(channelName).ExecuteAsync(); #endif - if (listFilesResponse.Result != null && listFilesResponse.Result.FilesList != null && listFilesResponse.Result.FilesList.Count > 0 && !listFilesResponse.Status.Error) + if (listFilesResponse.Result != null && listFilesResponse.Result.FilesList != null && + listFilesResponse.Result.FilesList.Count > 0 && !listFilesResponse.Status.Error) { List filesList = listFilesResponse.Result.FilesList; foreach (var file in filesList) { #if NET40 - PNResult deleteFileResponse = Task.Factory.StartNew(async () => await pubnub.DeleteFile().Channel(channelName).FileId(file.Id).FileName(file.Name).ExecuteAsync()).Result.Result; + PNResult deleteFileResponse = + Task.Factory.StartNew(async () => await pubnub.DeleteFile().Channel(channelName).FileId(file.Id).FileName(file.Name).ExecuteAsync()).Result.Result; #else - PNResult deleteFileResponse = await pubnub.DeleteFile().Channel(channelName).FileId(file.Id).FileName(file.Name).ExecuteAsync(); + PNResult deleteFileResponse = await pubnub.DeleteFile().Channel(channelName) + .FileId(file.Id).FileName(file.Name).ExecuteAsync(); #endif PNDeleteFileResult deleteFileResult = deleteFileResponse.Result; if (deleteFileResult != null) { - System.Diagnostics.Debug.WriteLine(string.Format("File Id={0}, Name={1} => deleted successfully", file.Id, file.Name)); + System.Diagnostics.Debug.WriteLine( + string.Format("File Id={0}, Name={1} => deleted successfully", file.Id, file.Name)); } } - receivedMessage = true; + + messageReset.Set(); } else { #if NET40 - PNResult deleteFileResponse = Task.Factory.StartNew(async () => await pubnub.DeleteFile().Channel(channelName).FileId("test_file_id").FileName("test_file_name.test").ExecuteAsync()).Result.Result; + PNResult deleteFileResponse = + Task.Factory.StartNew(async () => await pubnub.DeleteFile().Channel(channelName).FileId("test_file_id").FileName("test_file_name.test").ExecuteAsync()).Result.Result; #else - PNResult deleteFileResponse = await pubnub.DeleteFile().Channel(channelName).FileId("test_file_id").FileName("test_file_name.test").ExecuteAsync(); + PNResult deleteFileResponse = await pubnub.DeleteFile().Channel(channelName) + .FileId("test_file_id").FileName("test_file_name.test").ExecuteAsync(); #endif PNDeleteFileResult deleteFileResult = deleteFileResponse.Result; if (deleteFileResult != null) { - System.Diagnostics.Debug.WriteLine("File Id=test_file_id, Name=test_file_name.test => deleted successfully"); - receivedMessage = true; + System.Diagnostics.Debug.WriteLine( + "File Id=test_file_id, Name=test_file_name.test => deleted successfully"); + messageReset.Set(); } } + var receivedMessage = messageReset.WaitOne(7000); + pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; Assert.IsTrue(receivedMessage, "WhenFileIsRequested -> ThenWithAsyncDeleteFileShouldReturnSuccess failed."); - } } -} +} \ No newline at end of file diff --git a/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTime.cs b/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTime.cs index f08bf94ec..5a8617af0 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTime.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTime.cs @@ -26,12 +26,21 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTimeMultiInstance.cs b/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTimeMultiInstance.cs index 78ca6484f..baade6b47 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTimeMultiInstance.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenGetRequestServerTimeMultiInstance.cs @@ -23,12 +23,27 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } } [TearDown] - public void Exit() + public static void Exit() { + if (pubnub1 != null) + { + pubnub1.Destroy(); + pubnub1.PubnubUnitTest = null; + pubnub1 = null; + } + if (pubnub2 != null) + { + pubnub2.Destroy(); + pubnub2.PubnubUnitTest = null; + pubnub2 = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenGrantIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenGrantIsRequested.cs index 7efd34f16..f9d245b69 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenGrantIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenGrantIsRequested.cs @@ -55,12 +55,21 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -1023,7 +1032,8 @@ public static async Task ThenWithAsyncGrantTokenShouldReturnSuccess() } - [Test] + //TODO: CLEN-2039 + //[Test] public static void ThenRevokeTokenShouldReturnSuccess() { server.ClearRequests(); diff --git a/src/UnitTests/PubnubApi.Tests/WhenMessageAction.cs b/src/UnitTests/PubnubApi.Tests/WhenMessageAction.cs index 78bfb58cf..d50b8a6f2 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenMessageAction.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenMessageAction.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using NUnit.Framework; using System.Threading; using PubnubApi; @@ -14,16 +15,19 @@ public class WhenMessageAction : TestHarness private static int manualResetEventWaitTimeout = 310 * 1000; private static Pubnub pubnub; private static Server server; - private static string authKey = "myauth"; + private static string authToken; [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -35,7 +39,6 @@ public static void Init() PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - AuthKey = authKey, Secure = false }; server.RunOnHttps(false); @@ -49,7 +52,7 @@ public static void Init() server.AddRequest(new Request() .WithMethod("GET") .WithPath(string.Format("/v2/auth/grant/sub-key/{0}", PubnubCommon.SubscribeKey)) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel", grantChannel) .WithParameter("m", "1") .WithParameter("pnsdk", PubnubCommon.EncodedSDK) @@ -63,42 +66,48 @@ public static void Init() .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); - ManualResetEvent grantManualEvent = new ManualResetEvent(false); - pubnub.Grant().Channels(new[] { grantChannel }).AuthKeys(new[] { authKey }).Read(true).Write(true).Manage(true).TTL(20) - .Execute(new PNAccessManagerGrantResultExt((r, s) => { - try + var fullAccess = new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + }; + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() { - Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(s)); - - if (r != null) { - Debug.WriteLine("PNAccessManagerGrantResult={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(r)); - if (r.Channels != null && r.Channels.Count > 0) - { - var read = r.Channels[channel][authKey].ReadEnabled; - var write = r.Channels[channel][authKey].WriteEnabled; - if (read && write) - { - receivedGrantMessage = true; - } - } + grantChannel, fullAccess } } - catch { /* ignore */ } - finally { grantManualEvent.Set(); } - })); - Thread.Sleep(1000); - grantManualEvent.WaitOne(); + }).ExecuteAsync(); + + await Task.Delay(4000); + + authToken = grantResult.Result?.Token; pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenDetailedHistoryIsRequested Grant access failed."); + Assert.IsTrue(grantResult.Result != null && grantResult.Status.Error == false, + "WhenDetailedHistoryIsRequested Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -119,14 +128,10 @@ public static void ThenAddMessageActionReturnsSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; manualResetEventWaitTimeout = (PubnubCommon.EnableStubTest) ? 1000 : 310 * 1000; @@ -222,14 +227,10 @@ public static async Task ThenWithAsyncAddMessageActionReturnsSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; manualResetEventWaitTimeout = (PubnubCommon.EnableStubTest) ? 1000 : 310 * 1000; @@ -328,10 +329,6 @@ public static void ThenRemoveMessageActionReturnsSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -339,7 +336,7 @@ public static void ThenRemoveMessageActionReturnsSuccess() config.AuthKey = "myauth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; long currentMessageTimetoken = 0; @@ -420,10 +417,6 @@ public static async Task ThenWithAsyncRemoveMessageActionReturnsSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -431,7 +424,7 @@ public static async Task ThenWithAsyncRemoveMessageActionReturnsSuccess() config.AuthKey = "myauth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; long currentMessageTimetoken = 0; @@ -503,10 +496,6 @@ public static void ThenGetMessageActionsReturnsSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -514,7 +503,7 @@ public static void ThenGetMessageActionsReturnsSuccess() config.AuthKey = "myauth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; manualResetEventWaitTimeout = (PubnubCommon.EnableStubTest) ? 1000 : 310 * 1000; @@ -561,10 +550,6 @@ public static async Task ThenWithAsyncGetMessageActionsReturnsSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); if (PubnubCommon.PAMServerSideRun) @@ -572,7 +557,7 @@ public static async Task ThenWithAsyncGetMessageActionsReturnsSuccess() config.AuthKey = "myauth"; } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string channel = "hello_my_channel"; manualResetEventWaitTimeout = (PubnubCommon.EnableStubTest) ? 1000 : 310 * 1000; @@ -638,14 +623,10 @@ public static void ThenAddRemoveMessageActionReturnEventInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); pubnub.AddListener(eventListener); string channel = "hello_my_channel"; @@ -804,14 +785,10 @@ public static async Task ThenWithAsyncAddRemoveMessageActionReturnEventInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); pubnub.AddListener(eventListener); string channel = "hello_my_channel"; diff --git a/src/UnitTests/PubnubApi.Tests/WhenMessageCountIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenMessageCountIsRequested.cs index 9979f1ec2..063aa260a 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenMessageCountIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenMessageCountIsRequested.cs @@ -22,30 +22,30 @@ public class WhenMessageCountIsRequested : TestHarness private static string channelGroupName = "hello_my_group"; private static string channelName1 = "hello_my_channel1"; private static string channelName2 = "hello_my_channel2"; - private static string authKey = "myauth"; + private static string authToken; private static Pubnub pubnub; private static Server server; [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } - receivedGrantMessage = false; - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - AuthKey = authKey, }; pubnub = createPubNubInstance(config); @@ -55,7 +55,7 @@ public static void Init() server.AddRequest(new Request() .WithMethod("GET") .WithPath(string.Format("/v2/auth/grant/sub-key/{0}", PubnubCommon.SubscribeKey)) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel", string.Format("{0},{1}",channelName1, channelName2)) .WithParameter("m", "1") .WithParameter("pnsdk", PubnubCommon.EncodedSDK) @@ -69,29 +69,51 @@ public static void Init() .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); - pubnub.Grant().Channels(new[] { channelName1, channelName2 }).AuthKeys(new[] { authKey }).Read(true).Write(true).Manage(true).TTL(20) - .Execute(new PNAccessManagerGrantResultExt((r,s)=> + var fullAccess = new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + }; + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() { - if (r != null) + Channels = new Dictionary() { - receivedGrantMessage = true; + { + channelName1, fullAccess + }, + { + channelName2, fullAccess + } } - grantManualEvent.Set(); - })); + }).ExecuteAsync(); - Thread.Sleep(1000); + await Task.Delay(4000); - grantManualEvent.WaitOne(); + authToken = grantResult.Result?.Token; pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenMessageCountIsRequested Grant access failed."); + Assert.IsTrue(grantResult.Result != null && grantResult.Status.Error == false, + "WhenMessageCountIsRequested Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -113,12 +135,8 @@ public static void ThenChannel1Timetoken1ShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; @@ -180,12 +198,8 @@ public static async Task ThenWithAsyncChannel1Timetoken1ShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; @@ -244,12 +258,8 @@ public static void ThenChannel2Timetoken2ShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; @@ -311,12 +321,8 @@ public static async Task ThenWithAsyncChannel2Timetoken2ShouldReturnSuccess() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; diff --git a/src/UnitTests/PubnubApi.Tests/WhenMessageDeletedFromChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenMessageDeletedFromChannel.cs index 6cf9478ec..d661d071a 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenMessageDeletedFromChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenMessageDeletedFromChannel.cs @@ -20,7 +20,7 @@ public class WhenMessageDeletedFromChannel : TestHarness private static int manualResetEventWaitTimeout = 310 * 1000; private static string channel = "hello_my_channel"; - private static string authKey = "myauth"; + private static string token; private static string currentTestCase = ""; private static Pubnub pubnub; @@ -28,15 +28,21 @@ public class WhenMessageDeletedFromChannel : TestHarness private static Server server; [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } - if (!PubnubCommon.PAMServerSideGrant) { return; } + if (!PubnubCommon.PAMServerSideGrant) + { + return; + } receivedGrantMessage = false; @@ -45,7 +51,6 @@ public static void Init() PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - AuthKey = authKey, Secure = false }; server.RunOnHttps(false); @@ -59,7 +64,7 @@ public static void Init() server.AddRequest(new Request() .WithMethod("GET") .WithPath(string.Format("/v2/auth/grant/sub-key/{0}", PubnubCommon.SubscribeKey)) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel", channel) .WithParameter("m", "1") .WithParameter("pnsdk", PubnubCommon.EncodedSDK) @@ -73,22 +78,48 @@ public static void Init() .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); - pubnub.Grant().Channels(new [] { channel }).AuthKeys(new [] { authKey }).Read(true).Write(true).Manage(true).Delete(true).Manage(true).Update(true).TTL(20).Execute(new UTGrantResult()); - - Thread.Sleep(1000); + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() + { + { + channel, new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + } + } + } + }).ExecuteAsync(); - grantManualEvent.WaitOne(); + await Task.Delay(3000); + token = grantResult.Result?.Token; + pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenUnsubscribedToAChannelGroup Grant access failed."); + Assert.IsTrue(grantResult.Status.Error == false && grantResult.Result != null, + "WhenUnsubscribedToAChannelGroup Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -110,11 +141,8 @@ public static void ThenDeleteMessageShouldReturnSuccessMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); string expected = "{\"status\": 200, \"error\": false, \"error_message\": \"\"}"; @@ -172,11 +200,8 @@ public static async Task ThenWithAsyncDeleteMessageShouldReturnSuccessMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(token); string expected = "{\"status\": 200, \"error\": false, \"error_message\": \"\"}"; @@ -207,62 +232,5 @@ public static async Task ThenWithAsyncDeleteMessageShouldReturnSuccessMessage() Assert.IsTrue(receivedMessage, "ThenWithAsyncDeleteMessageShouldReturnSuccessMessage - DeleteMessages Result not expected"); } - - private class UTGrantResult : PNCallback - { - public override void OnResponse(PNAccessManagerGrantResult result, PNStatus status) - { - try - { - Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(status)); - - if (result != null) - { - Debug.WriteLine("PNAccessManagerGrantResult={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - if (result.Channels != null && result.Channels.Count > 0) - { - var read = result.Channels[channel][authKey].ReadEnabled; - var write = result.Channels[channel][authKey].WriteEnabled; - if (read && write) - { - receivedGrantMessage = true; - } - } - } - } - catch - { - } - finally - { - grantManualEvent.Set(); - } - } - } - - public class UTDeleteMessagaeResult : PNCallback - { - public override void OnResponse(PNDeleteMessageResult result, PNStatus status) - { - Debug.WriteLine("DeleteMessage Response: " + pubnub.JsonPluggableLibrary.SerializeToJsonString(result)); - Debug.WriteLine("DeleteMessage PNStatus => Status = : " + status.StatusCode.ToString()); - if (status != null && status.Error) - { - deleteMessageManualEvent.Set(); - } - else if (result != null && status.StatusCode == 200 && !status.Error) - { - switch (currentTestCase) - { - case "DeleteMessageShouldReturnSuccessMessage": - receivedMessage = true; - deleteMessageManualEvent.Set(); - break; - default: - break; - } - } - } - }; } } diff --git a/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMember.cs b/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMember.cs index 1c959b246..b95eed161 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMember.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMember.cs @@ -23,7 +23,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -92,6 +95,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -278,7 +287,6 @@ public static void ThenSetRemoveUuidMetadataWithManageMemberShouldReturnSuccessC #endregion manualEvent.WaitOne(manualResetEventWaitTimeout); } - if (receivedMessage) { receivedMessage = false; @@ -1121,7 +1129,7 @@ public static async Task ThenWithAsyncSetRemoveUuidMetadataWithSetRemoveMemberSh [Test] - public static void ThenManageChannelMembersShouldReturnEventInfo() + public async Task ThenManageChannelMembersShouldReturnEventInfo() { server.ClearRequests(); @@ -1179,32 +1187,28 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() } pubnub.AddListener(eventListener); - ManualResetEvent manualEvent = new ManualResetEvent(false); + pubnub.Subscribe().Channels(new string[] { uuidMetadataId1, uuidMetadataId2, channelMetadataId }).Execute(); - manualEvent.WaitOne(2000); - + await Task.Delay(3000); - manualResetEventWaitTimeout = 310 * 1000; + System.Diagnostics.Debug.WriteLine("pubnub.RemoveUuidMetadata() 1 STARTED"); - manualEvent = new ManualResetEvent(false); pubnub.RemoveUuidMetadata().Uuid(uuidMetadataId1).Execute(new PNRemoveUuidMetadataResultExt( delegate (PNRemoveUuidMetadataResult result, PNStatus status) { })); - manualEvent.WaitOne(2000); + await Task.Delay(3000); System.Diagnostics.Debug.WriteLine("pubnub.RemoveUuidMetadata() 2 STARTED"); - manualEvent = new ManualResetEvent(false); pubnub.RemoveUuidMetadata().Uuid(uuidMetadataId2).Execute(new PNRemoveUuidMetadataResultExt( delegate (PNRemoveUuidMetadataResult result, PNStatus status) { })); - manualEvent.WaitOne(2000); + await Task.Delay(3000); System.Diagnostics.Debug.WriteLine("pubnub.RemoveChannelMetadata() STARTED"); - manualEvent = new ManualResetEvent(false); pubnub.RemoveChannelMetadata().Channel(channelMetadataId).Execute(new PNRemoveChannelMetadataResultExt( delegate (PNRemoveChannelMetadataResult result, PNStatus status) { })); - manualEvent.WaitOne(2000); - - manualEvent = new ManualResetEvent(false); - receivedMessage = false; + await Task.Delay(3000); + + manualResetEventWaitTimeout = 310 * 1000; + var manualEvent = new ManualResetEvent(false); #region "SetUuidMetadata 1" System.Diagnostics.Debug.WriteLine("pubnub.SetUuidMetadata() 1 STARTED"); pubnub.SetUuidMetadata().Uuid(uuidMetadataId1).Name("pandu-ut-un1") @@ -1215,17 +1219,15 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() pubnub.JsonPluggableLibrary.SerializeToJsonString(r); if (uuidMetadataId1 == r.Uuid) { - receivedMessage = true; + manualEvent.Set(); } } - manualEvent.Set(); })); #endregion - manualEvent.WaitOne(manualResetEventWaitTimeout); + receivedMessage = manualEvent.WaitOne(manualResetEventWaitTimeout); if (receivedMessage) { - receivedMessage = false; manualEvent = new ManualResetEvent(false); #region "SetUuidMetadata 2" System.Diagnostics.Debug.WriteLine("pubnub.SetUuidMetadata() 2 STARTED"); @@ -1237,17 +1239,15 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() pubnub.JsonPluggableLibrary.SerializeToJsonString(r); if (uuidMetadataId2 == r.Uuid) { - receivedMessage = true; + manualEvent.Set(); } } - manualEvent.Set(); })); #endregion - manualEvent.WaitOne(manualResetEventWaitTimeout); + receivedMessage = manualEvent.WaitOne(manualResetEventWaitTimeout); } if (receivedMessage) { - receivedMessage = false; manualEvent = new ManualResetEvent(false); #region "SetChannelMetadata" System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); @@ -1259,18 +1259,16 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() pubnub.JsonPluggableLibrary.SerializeToJsonString(r); if (channelMetadataId == r.Channel) { - receivedMessage = true; + manualEvent.Set(); } } - manualEvent.Set(); })); #endregion - manualEvent.WaitOne(manualResetEventWaitTimeout); + receivedMessage = manualEvent.WaitOne(manualResetEventWaitTimeout); } if (receivedMessage) { - receivedMessage = false; manualEvent = new ManualResetEvent(false); #region "ManageChannelMembers Add" System.Diagnostics.Debug.WriteLine("pubnub.ManageChannelMembers() ADD STARTED"); @@ -1289,18 +1287,16 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() && r.ChannelMembers.Find(x => x.UuidMetadata.Uuid == uuidMetadataId1) != null && r.ChannelMembers.Find(x => x.UuidMetadata.Uuid == uuidMetadataId2) != null) { - receivedMessage = true; + manualEvent.Set(); } } - manualEvent.Set(); })); #endregion - manualEvent.WaitOne(manualResetEventWaitTimeout); + receivedMessage = manualEvent.WaitOne(manualResetEventWaitTimeout); } if (receivedMessage) { - receivedMessage = false; manualEvent = new ManualResetEvent(false); #region "ManageChannelMembers Update" if (!string.IsNullOrEmpty(config.SecretKey)) @@ -1320,10 +1316,9 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() if (r.ChannelMembers != null && r.ChannelMembers.Find(x => x.UuidMetadata.Uuid == uuidMetadataId1) != null) { - receivedMessage = true; + manualEvent.Set(); } } - manualEvent.Set(); })); } else @@ -1336,16 +1331,15 @@ public static void ThenManageChannelMembersShouldReturnEventInfo() if (r != null && s.StatusCode == 200 && !s.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(r); - receivedMessage = true; + manualEvent.Set(); } - manualEvent.Set(); })); } #endregion - manualEvent.WaitOne(manualResetEventWaitTimeout); + receivedMessage = manualEvent.WaitOne(manualResetEventWaitTimeout); } - Thread.Sleep(2000); + await Task.Delay(3000); pubnub.Unsubscribe().Channels(new string[] { uuidMetadataId1, uuidMetadataId2, channelMetadataId }).Execute(); pubnub.RemoveListener(eventListener); @@ -1422,7 +1416,7 @@ public static async Task ThenWithAsyncManageChannelMembersShouldReturnEventInfo( ManualResetEvent manualEvent = new ManualResetEvent(false); pubnub.Subscribe().Channels(new string[] { uuidMetadataId1, uuidMetadataId2, channelMetadataId }).Execute(); - manualEvent.WaitOne(2000); + manualEvent.WaitOne(4000); System.Diagnostics.Debug.WriteLine("pubnub.RemoveUuidMetadata() 1 STARTED"); #if NET40 @@ -1540,7 +1534,7 @@ public static async Task ThenWithAsyncManageChannelMembersShouldReturnEventInfo( #endregion } - Thread.Sleep(2000); + await Task.Delay(4000); if (receivedMessage) { @@ -1597,10 +1591,10 @@ public static async Task ThenWithAsyncManageChannelMembersShouldReturnEventInfo( #endregion } - Thread.Sleep(4000); + await Task.Delay(4000); /* */ pubnub.Unsubscribe().Channels(new string[] { uuidMetadataId1, uuidMetadataId2, channelMetadataId }).Execute(); - Thread.Sleep(1000); + await Task.Delay(4000); pubnub.RemoveListener(eventListener); Assert.IsTrue(receivedDeleteEvent && receivedSetEvent, "Async ManageMembers events Failed"); diff --git a/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMetadata.cs b/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMetadata.cs index 1efa55fb2..257b6f706 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMetadata.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenObjectChannelMetadata.cs @@ -14,73 +14,81 @@ public class WhenObjectChannelMetadata : TestHarness private static int manualResetEventWaitTimeout = 310 * 1000; private static Pubnub pubnub; private static Server server; - private static string authKey = "myauth"; - private static string authToken = ""; + private static string authToken; + private static string channelMetadataId = "pandu-ut-sid"; [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); - - if (!PubnubCommon.PAMServerSideGrant) { return; } + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } - bool receivedGrantMessage = false; - string channelMetadataId = "pandu-ut-sid"; + if (!PubnubCommon.PAMServerSideGrant) + { + return; + } PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, - AuthKey = authKey, Secure = false }; server.RunOnHttps(false); pubnub = createPubNubInstance(config); - ManualResetEvent grantManualEvent = new ManualResetEvent(false); - pubnub.Grant().Channels(new[] { channelMetadataId }).AuthKeys(new[] { authKey }).Read(true).Write(true).Manage(true).Update(true).Delete(true).Get(true).TTL(20) - .Execute(new PNAccessManagerGrantResultExt( - (r, s) => - { - try - { - Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(s)); - if (r != null) - { - Debug.WriteLine("PNAccessManagerGrantResult={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(r)); - if (r.Channels != null && r.Channels.Count > 0) - { - var read = r.Channels[channelMetadataId][authKey].ReadEnabled; - var write = r.Channels[channelMetadataId][authKey].WriteEnabled; - if (read && write) { receivedGrantMessage = true; } - } - } - } - catch { /* ignore */ } - finally - { - grantManualEvent.Set(); - } - })); - if (!PubnubCommon.EnableStubTest) Thread.Sleep(1000); - - grantManualEvent.WaitOne(); + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() + { + { + channelMetadataId, new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + } + } + } + }).ExecuteAsync(); + if (!PubnubCommon.EnableStubTest) + { + await Task.Delay(3000); + } + + authToken = grantResult.Result?.Token; pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenObjectChannelMetadata Grant access failed."); + Assert.IsTrue(grantResult.Result != null && grantResult.Status.Error == false, + "WhenObjectChannelMetadata Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } + server.Stop(); } @@ -97,8 +105,6 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() bool receivedMessage = false; - string channelMetadataId = "pandu-ut-sid"; - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, @@ -109,61 +115,69 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + server.RunOnHttps(false); pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(authToken); ManualResetEvent manualEvent = new ManualResetEvent(false); manualResetEventWaitTimeout = 310 * 1000; System.Diagnostics.Debug.WriteLine("pubnub.DeleteSpace() STARTED"); pubnub.RemoveChannelMetadata().Channel(channelMetadataId).Execute(new PNRemoveChannelMetadataResultExt( - delegate (PNRemoveChannelMetadataResult result, PNStatus status) { })); + delegate(PNRemoveChannelMetadataResult result, PNStatus status) { })); manualEvent.WaitOne(2000); manualEvent = new ManualResetEvent(false); + #region "CreateSpace" + System.Diagnostics.Debug.WriteLine("pubnub.CreateSpace() STARTED"); pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname") - .Execute(new PNSetChannelMetadataResultExt((r, s) => + .Execute(new PNSetChannelMetadataResultExt((r, s) => + { + if (r != null && s.StatusCode == 200 && !s.Error) { - if (r != null && s.StatusCode == 200 && !s.Error) + pubnub.JsonPluggableLibrary.SerializeToJsonString(r); + if (channelMetadataId == r.Channel) { - pubnub.JsonPluggableLibrary.SerializeToJsonString(r); - if (channelMetadataId == r.Channel) - { - receivedMessage = true; - } + receivedMessage = true; } - manualEvent.Set(); - })); + } + + manualEvent.Set(); + })); + #endregion + manualEvent.WaitOne(manualResetEventWaitTimeout); if (receivedMessage) { receivedMessage = false; manualEvent = new ManualResetEvent(false); + #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") .Description("pandu-ut-spdesc") .Custom(new Dictionary() { { "color", "red" } }) - .Execute(new PNSetChannelMetadataResultExt((r, s) => + .Execute(new PNSetChannelMetadataResultExt((r, s) => + { + if (r != null && s.StatusCode == 200 && !s.Error) { - if (r != null && s.StatusCode == 200 && !s.Error) + pubnub.JsonPluggableLibrary.SerializeToJsonString(r); + if (channelMetadataId == r.Channel) { - pubnub.JsonPluggableLibrary.SerializeToJsonString(r); - if (channelMetadataId == r.Channel) - { - receivedMessage = true; - } + receivedMessage = true; } - manualEvent.Set(); - })); + } + + manualEvent.Set(); + })); + #endregion + manualEvent.WaitOne(manualResetEventWaitTimeout); } @@ -171,7 +185,9 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() { receivedMessage = false; manualEvent = new ManualResetEvent(false); + #region "GetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.GetChannelMetadata() STARTED"); pubnub.GetChannelMetadata().Channel(channelMetadataId).IncludeCustom(true) .Execute(new PNGetChannelMetadataResultExt((r, s) => @@ -184,9 +200,12 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() receivedMessage = true; } } + manualEvent.Set(); })); + #endregion + manualEvent.WaitOne(manualResetEventWaitTimeout); } @@ -194,7 +213,9 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() { receivedMessage = false; manualEvent = new ManualResetEvent(false); + #region "GetAllChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.GetAllChannelMetadata() STARTED"); pubnub.GetAllChannelMetadata().IncludeCount(true) .Execute(new PNGetAllChannelMetadataResultExt((r, s) => @@ -203,20 +224,24 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() { pubnub.JsonPluggableLibrary.SerializeToJsonString(r); List spaceList = r.Channels; - if (spaceList != null && spaceList.Count > 0 && spaceList.Find(x => x.Channel == channelMetadataId) != null) + if (spaceList != null && spaceList.Count > 0 && + spaceList.Find(x => x.Channel == channelMetadataId) != null) { receivedMessage = true; } } + manualEvent.Set(); })); + #endregion + manualEvent.WaitOne(manualResetEventWaitTimeout); } if (!receivedMessage) { - Assert.IsTrue(receivedMessage, "SetChannelMetadata/DeleteChannelMetadataId Failed"); + Assert.IsTrue(receivedMessage, $"SetChannelMetadata/DeleteChannelMetadataId Failed."); } pubnub.Destroy(); @@ -229,7 +254,7 @@ public static void ThenChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() public static void ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() #else public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCodeAndInfo() -#endif +#endif { server.ClearRequests(); @@ -241,8 +266,6 @@ public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCode bool receivedMessage = false; - string channelMetadataId = "pandu-ut-sid"; - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, @@ -253,12 +276,10 @@ public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCode { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + server.RunOnHttps(false); pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(authToken); System.Diagnostics.Debug.WriteLine("pubnub.RemoveChannelMetadata() STARTED"); #if NET40 @@ -268,13 +289,17 @@ public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCode #endif #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); #if NET40 - PNResult createSpaceResult = Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync()).Result.Result; + PNResult createSpaceResult = + Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync()).Result.Result; #else - PNResult createSpaceResult = await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync(); + PNResult createSpaceResult = await pubnub.SetChannelMetadata() + .Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync(); #endif - if (createSpaceResult.Result != null && createSpaceResult.Status.StatusCode == 200 && !createSpaceResult.Status.Error) + if (createSpaceResult.Result != null && createSpaceResult.Status.StatusCode == 200 && + !createSpaceResult.Status.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(createSpaceResult.Result); if (channelMetadataId == createSpaceResult.Result.Channel) @@ -282,25 +307,31 @@ public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCode receivedMessage = true; } } + #endregion if (receivedMessage) { receivedMessage = false; + #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); #if NET40 - PNResult updateSpaceResult = Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") + PNResult updateSpaceResult = + Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") .Description("pandu-ut-spdesc") .Custom(new Dictionary() { { "color", "red" } }) .ExecuteAsync()).Result.Result; #else - PNResult updateSpaceResult = await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") + PNResult updateSpaceResult = await pubnub.SetChannelMetadata() + .Channel(channelMetadataId).Name("pandu-ut-spname-upd") .Description("pandu-ut-spdesc") .Custom(new Dictionary() { { "color", "red" } }) .ExecuteAsync(); #endif - if (updateSpaceResult.Result != null && updateSpaceResult.Status.StatusCode == 200 && !updateSpaceResult.Status.Error) + if (updateSpaceResult.Result != null && updateSpaceResult.Status.StatusCode == 200 && + !updateSpaceResult.Status.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(updateSpaceResult.Result); if (channelMetadataId == updateSpaceResult.Result.Channel) @@ -308,22 +339,28 @@ public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCode receivedMessage = true; } } + #endregion } if (receivedMessage) { receivedMessage = false; + #region "GetSpace" + System.Diagnostics.Debug.WriteLine("pubnub.GetChannelMetadata() STARTED"); #if NET40 - PNResult getSpaceResult = Task.Factory.StartNew(async () => await pubnub.GetChannelMetadata().Channel(channelMetadataId).IncludeCustom(true) + PNResult getSpaceResult = + Task.Factory.StartNew(async () => await pubnub.GetChannelMetadata().Channel(channelMetadataId).IncludeCustom(true) .ExecuteAsync()).Result.Result; #else - PNResult getSpaceResult = await pubnub.GetChannelMetadata().Channel(channelMetadataId).IncludeCustom(true) + PNResult getSpaceResult = await pubnub.GetChannelMetadata() + .Channel(channelMetadataId).IncludeCustom(true) .ExecuteAsync(); #endif - if (getSpaceResult.Result != null && getSpaceResult.Status.StatusCode == 200 && !getSpaceResult.Status.Error) + if (getSpaceResult.Result != null && getSpaceResult.Status.StatusCode == 200 && + !getSpaceResult.Status.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(getSpaceResult.Result); if (channelMetadataId == getSpaceResult.Result.Channel) @@ -331,28 +368,36 @@ public static async Task ThenWithAsyncChannelMetadataCRUDShouldReturnSuccessCode receivedMessage = true; } } + #endregion } if (receivedMessage) { receivedMessage = false; + #region "GetSpaces" + System.Diagnostics.Debug.WriteLine("pubnub.GetAllChannelMetadata() STARTED"); #if NET40 - PNResult getSpacesResult = Task.Factory.StartNew(async () => await pubnub.GetAllChannelMetadata().IncludeCount(true).ExecuteAsync()).Result.Result; + PNResult getSpacesResult = + Task.Factory.StartNew(async () => await pubnub.GetAllChannelMetadata().IncludeCount(true).ExecuteAsync()).Result.Result; #else - PNResult getSpacesResult = await pubnub.GetAllChannelMetadata().IncludeCount(true).ExecuteAsync(); + PNResult getSpacesResult = + await pubnub.GetAllChannelMetadata().IncludeCount(true).ExecuteAsync(); #endif - if (getSpacesResult.Result != null && getSpacesResult.Status.StatusCode == 200 && !getSpacesResult.Status.Error) + if (getSpacesResult.Result != null && getSpacesResult.Status.StatusCode == 200 && + !getSpacesResult.Status.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(getSpacesResult.Result); List spaceList = getSpacesResult.Result.Channels; - if (spaceList != null && spaceList.Count > 0 && spaceList.Find(x => x.Channel == channelMetadataId) != null) + if (spaceList != null && spaceList.Count > 0 && + spaceList.Find(x => x.Channel == channelMetadataId) != null) { receivedMessage = true; } } + #endregion } @@ -380,14 +425,14 @@ public static void ThenChannelMetadataSetDeleteShouldReturnEventInfo() bool receivedMessage = false; bool receivedDeleteEvent = false; bool receivedUpdateEvent = false; - - string channelMetadataId = "pandu-ut-sid"; + manualResetEventWaitTimeout = 310 * 1000; SubscribeCallbackExt eventListener = new SubscribeCallbackExt( - delegate (Pubnub pnObj, PNObjectEventResult eventResult) + delegate(Pubnub pnObj, PNObjectEventResult eventResult) { - System.Diagnostics.Debug.WriteLine("EVENT:" + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); + System.Diagnostics.Debug.WriteLine("EVENT:" + + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); if (eventResult.Type.ToLowerInvariant() == "channel") { if (eventResult.Event.ToLowerInvariant() == "set") @@ -400,29 +445,23 @@ public static void ThenChannelMetadataSetDeleteShouldReturnEventInfo() } } }, - delegate (Pubnub pnObj, PNStatus status) - { - - } - ); + delegate(Pubnub pnObj, PNStatus status) { } + ); PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, Secure = false, - AuthKey = "myauth" }; if (PubnubCommon.PAMServerSideRun) { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + server.RunOnHttps(false); pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(authToken); pubnub.AddListener(eventListener); ManualResetEvent manualEvent = new ManualResetEvent(false); @@ -432,50 +471,60 @@ public static void ThenChannelMetadataSetDeleteShouldReturnEventInfo() manualEvent = new ManualResetEvent(false); System.Diagnostics.Debug.WriteLine("pubnub.RemoveChannelMetadata() STARTED"); pubnub.RemoveChannelMetadata().Channel(channelMetadataId).Execute(new PNRemoveChannelMetadataResultExt( - delegate (PNRemoveChannelMetadataResult result, PNStatus status) { })); + delegate(PNRemoveChannelMetadataResult result, PNStatus status) { })); manualEvent.WaitOne(2000); manualEvent = new ManualResetEvent(false); + #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname") - .Execute(new PNSetChannelMetadataResultExt((r, s) => + .Execute(new PNSetChannelMetadataResultExt((r, s) => + { + if (r != null && s.StatusCode == 200 && !s.Error) { - if (r != null && s.StatusCode == 200 && !s.Error) + pubnub.JsonPluggableLibrary.SerializeToJsonString(r); + if (channelMetadataId == r.Channel) { - pubnub.JsonPluggableLibrary.SerializeToJsonString(r); - if (channelMetadataId == r.Channel) - { - receivedMessage = true; - } + receivedMessage = true; } - manualEvent.Set(); - })); + } + + manualEvent.Set(); + })); + #endregion + manualEvent.WaitOne(manualResetEventWaitTimeout); if (receivedMessage) { receivedMessage = false; manualEvent = new ManualResetEvent(false); + #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") .Description("pandu-ut-spdesc") .Custom(new Dictionary() { { "color", "red" } }) - .Execute(new PNSetChannelMetadataResultExt((r, s) => + .Execute(new PNSetChannelMetadataResultExt((r, s) => + { + if (r != null && s.StatusCode == 200 && !s.Error) { - if (r != null && s.StatusCode == 200 && !s.Error) + pubnub.JsonPluggableLibrary.SerializeToJsonString(r); + if (channelMetadataId == r.Channel) { - pubnub.JsonPluggableLibrary.SerializeToJsonString(r); - if (channelMetadataId == r.Channel) - { - receivedMessage = true; - } + receivedMessage = true; } - manualEvent.Set(); - })); + } + + manualEvent.Set(); + })); + #endregion + manualEvent.WaitOne(manualResetEventWaitTimeout); } @@ -484,7 +533,7 @@ public static void ThenChannelMetadataSetDeleteShouldReturnEventInfo() manualEvent = new ManualResetEvent(false); System.Diagnostics.Debug.WriteLine("pubnub.RemoveChannelMetadata() 2 STARTED"); pubnub.RemoveChannelMetadata().Channel(channelMetadataId).Execute(new PNRemoveChannelMetadataResultExt( - delegate (PNRemoveChannelMetadataResult result, PNStatus status) { })); + delegate(PNRemoveChannelMetadataResult result, PNStatus status) { })); manualEvent.WaitOne(2000); } @@ -498,7 +547,6 @@ public static void ThenChannelMetadataSetDeleteShouldReturnEventInfo() pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - } [Test] @@ -506,7 +554,7 @@ public static void ThenChannelMetadataSetDeleteShouldReturnEventInfo() public static void ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEventInfo() #else public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEventInfo() -#endif +#endif { server.ClearRequests(); @@ -519,14 +567,14 @@ public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEve bool receivedMessage = false; bool receivedDeleteEvent = false; bool receivedUpdateEvent = false; - - string channelMetadataId = "pandu-ut-sid"; + manualResetEventWaitTimeout = 310 * 1000; SubscribeCallbackExt eventListener = new SubscribeCallbackExt( - delegate (Pubnub pnObj, PNObjectEventResult eventResult) + delegate(Pubnub pnObj, PNObjectEventResult eventResult) { - System.Diagnostics.Debug.WriteLine("EVENT:" + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); + System.Diagnostics.Debug.WriteLine("EVENT:" + + pubnub.JsonPluggableLibrary.SerializeToJsonString(eventResult)); if (eventResult.Type.ToLowerInvariant() == "channel") { if (eventResult.Event.ToLowerInvariant() == "set") @@ -539,29 +587,23 @@ public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEve } } }, - delegate (Pubnub pnObj, PNStatus status) - { - - } - ); + delegate(Pubnub pnObj, PNStatus status) { } + ); PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, Secure = false, - AuthKey = "myauth" }; if (PubnubCommon.PAMServerSideRun) { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } + server.RunOnHttps(false); pubnub = createPubNubInstance(config); + pubnub.SetAuthToken(authToken); pubnub.AddListener(eventListener); ManualResetEvent manualEvent = new ManualResetEvent(false); @@ -576,13 +618,17 @@ public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEve #endif #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); #if NET40 - PNResult createSpaceResult = Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync()).Result.Result; + PNResult createSpaceResult = + Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync()).Result.Result; #else - PNResult createSpaceResult = await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync(); + PNResult createSpaceResult = await pubnub.SetChannelMetadata() + .Channel(channelMetadataId).Name("pandu-ut-spname").ExecuteAsync(); #endif - if (createSpaceResult.Result != null && createSpaceResult.Status.StatusCode == 200 && !createSpaceResult.Status.Error) + if (createSpaceResult.Result != null && createSpaceResult.Status.StatusCode == 200 && + !createSpaceResult.Status.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(createSpaceResult.Result); if (channelMetadataId == createSpaceResult.Result.Channel) @@ -590,25 +636,31 @@ public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEve receivedMessage = true; } } + #endregion if (receivedMessage) { receivedMessage = false; + #region "SetChannelMetadata" + System.Diagnostics.Debug.WriteLine("pubnub.SetChannelMetadata() STARTED"); #if NET40 - PNResult updateSpaceResult = Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") + PNResult updateSpaceResult = + Task.Factory.StartNew(async () => await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") .Description("pandu-ut-spdesc") .Custom(new Dictionary() { { "color", "red" } }) .ExecuteAsync()).Result.Result; #else - PNResult updateSpaceResult = await pubnub.SetChannelMetadata().Channel(channelMetadataId).Name("pandu-ut-spname-upd") + PNResult updateSpaceResult = await pubnub.SetChannelMetadata() + .Channel(channelMetadataId).Name("pandu-ut-spname-upd") .Description("pandu-ut-spdesc") .Custom(new Dictionary() { { "color", "red" } }) .ExecuteAsync(); #endif - if (updateSpaceResult.Result != null && updateSpaceResult.Status.StatusCode == 200 && !updateSpaceResult.Status.Error) + if (updateSpaceResult.Result != null && updateSpaceResult.Status.StatusCode == 200 && + !updateSpaceResult.Status.Error) { pubnub.JsonPluggableLibrary.SerializeToJsonString(updateSpaceResult.Result); if (channelMetadataId == updateSpaceResult.Result.Channel) @@ -616,6 +668,7 @@ public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEve receivedMessage = true; } } + #endregion } @@ -639,7 +692,6 @@ public static async Task ThenWithAsyncChannelMetadataUpdateDeleteShouldReturnEve pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - } } -} +} \ No newline at end of file diff --git a/src/UnitTests/PubnubApi.Tests/WhenObjectMembership.cs b/src/UnitTests/PubnubApi.Tests/WhenObjectMembership.cs index b01d354d6..e3f1913b3 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenObjectMembership.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenObjectMembership.cs @@ -23,7 +23,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -91,10 +94,17 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } - [Test] + //TODO: CLEN-2039 + //[Test] public static void ThenSetRemoveChannelMetadataWithManageMembershipShouldReturnSuccessCodeAndInfo() { server.ClearRequests(); @@ -1056,7 +1066,8 @@ public static async Task ThenWithAsyncSetRemoveChannelMetadataWithSetRemoveMembe } - [Test] + //TODO: CLEN-2037 + //[Test] public static void ThenManageMembershipShouldReturnEventInfo() { server.ClearRequests(); diff --git a/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs b/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs index 0c959bb2b..75a50643c 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenObjectUuidMetadata.cs @@ -23,7 +23,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -89,6 +92,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenPushIsRequested.cs b/src/UnitTests/PubnubApi.Tests/WhenPushIsRequested.cs index f6ca660d5..64952a258 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenPushIsRequested.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenPushIsRequested.cs @@ -41,7 +41,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { @@ -114,6 +117,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs index af97dca53..4687bb96d 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel.cs @@ -35,7 +35,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -133,6 +136,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -504,7 +513,8 @@ public static void ThenMultiSubscribeShouldReturnConnectStatus() { PublishKey = PubnubCommon.PublishKey, SubscribeKey = PubnubCommon.SubscribeKey, - Secure = false + Secure = false, + EnableEventEngine = false }; if (PubnubCommon.PAMServerSideRun) { diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel2.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel2.cs index 2a90faefe..7c137e2ac 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel2.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel2.cs @@ -47,7 +47,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { @@ -62,7 +65,8 @@ public static void Init() SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, AuthKey = authKey, - Secure = false + Secure = false, + EnableEventEngine = false }; server.RunOnHttps(false); @@ -89,7 +93,7 @@ public static void Init() pubnub.Grant().Channels(channelsGrant).AuthKeys(new [] { authKey }).Read(true).Write(true).Manage(true).TTL(20).Execute(new UTGrantResult()); - Thread.Sleep(1000); + Thread.Sleep(3000); grantManualEvent.WaitOne(); @@ -103,6 +107,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs index ffcd5a7e5..76d3e6e0b 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannel3.cs @@ -40,7 +40,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -52,7 +55,8 @@ public static void Init() SubscribeKey = PubnubCommon.SubscribeKey, SecretKey = PubnubCommon.SecretKey, AuthKey = authKey, - Secure = false + Secure = false, + EnableEventEngine = false }; server.RunOnHttps(false); @@ -93,6 +97,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannelGroup.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannelGroup.cs index 6659da4a2..9a0c47e00 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannelGroup.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToAChannelGroup.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using MockServer; using System.Diagnostics; +using System.Threading.Tasks; namespace PubNubMessaging.Tests { @@ -17,10 +18,9 @@ public class WhenSubscribedToAChannelGroup : TestHarness private static string channelName = "hello_my_channel"; private static object publishedMessage; - private static long publishTimetoken = 0; static int manualResetEventWaitTimeout = 310 * 1000; - private static string authKey = "myauth"; + private static string authToken; private static Pubnub pubnub; private static Server server; @@ -34,18 +34,19 @@ void IPubnubLog.WriteToLog(string logText) } [SetUp] - public static void Init() + public static async Task Init() { UnitTestLog unitLog = new Tests.UnitTestLog(); unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } - bool receivedGrantMessage = false; - PNConfiguration config = new PNConfiguration(new UserId("mytestuuid")) { PublishKey = PubnubCommon.PublishKey, @@ -57,15 +58,13 @@ public static void Init() pubnub = createPubNubInstance(config); manualResetEventWaitTimeout = (PubnubCommon.EnableStubTest) ? 1000 : 310 * 1000; - - ManualResetEvent grantManualEvent = new ManualResetEvent(false); - + string expected = "{\"message\":\"Success\",\"payload\":{\"level\":\"user\",\"subscribe_key\":\"demo-36\",\"ttl\":20,\"channel\":\"hello_my_channel\",\"auths\":{\"myAuth\":{\"r\":1,\"w\":1,\"m\":1}}},\"service\":\"Access Manager\",\"status\":200}"; server.AddRequest(new Request() .WithMethod("GET") .WithPath(string.Format("/v2/auth/grant/sub-key/{0}", PubnubCommon.SubscribeKey)) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel", "hello_my_channel") .WithParameter("channel-group", "hello_my_group%2Chello_my_group1%2Chello_my_group2") .WithParameter("m", "1") @@ -80,86 +79,61 @@ public static void Init() .WithResponse(expected) .WithStatusCode(System.Net.HttpStatusCode.OK)); - pubnub.Grant().AuthKeys(new [] { authKey }).ChannelGroups(new [] { channelGroupName, channelGroupName1, channelGroupName2 }).Channels(new [] { channelName }).Read(true).Write(true).Manage(true).TTL(20) - .Execute(new PNAccessManagerGrantResultExt( - (r, s) => - { - try - { - if (r != null && s.StatusCode == 200 && !s.Error) - { - Debug.WriteLine("PNAccessManagerGrantResult={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(r)); - - if (r.ChannelGroups != null && r.ChannelGroups.Count > 0) - { - foreach (KeyValuePair> channelGroupKP in r.ChannelGroups) - { - receivedGrantMessage = false; - - string channelGroup = channelGroupKP.Key; - var read = r.ChannelGroups[channelGroup][authKey].ReadEnabled; - var write = r.ChannelGroups[channelGroup][authKey].WriteEnabled; - var manage = r.ChannelGroups[channelGroup][authKey].ManageEnabled; - - if (read && write && manage) - { - receivedGrantMessage = true; - } - else - { - receivedGrantMessage = false; - break; - } - } - } - if (r.Channels != null && r.Channels.Count > 0) - { - foreach (KeyValuePair> channelKP in r.Channels) - { - receivedGrantMessage = false; - - string channel = channelKP.Key; - var read = r.Channels[channel][authKey].ReadEnabled; - var write = r.Channels[channel][authKey].WriteEnabled; - var manage = r.Channels[channel][authKey].ManageEnabled; - - if (read && write && manage) - { - receivedGrantMessage = true; - } - else - { - receivedGrantMessage = false; - break; - } - } - } - - } - else - { - Debug.WriteLine("PNStatus={0}", pubnub.JsonPluggableLibrary.SerializeToJsonString(s)); - } - } - catch { /* ignore */ } - finally - { - grantManualEvent.Set(); - } - })); - Thread.Sleep(1000); - grantManualEvent.WaitOne(manualResetEventWaitTimeout); + var fullAccess = new PNTokenAuthValues() + { + Read = true, + Write = true, + Create = true, + Get = true, + Delete = true, + Join = true, + Update = true, + Manage = true + }; + var grantResult = await pubnub.GrantToken().TTL(20).AuthorizedUuid(config.UserId).Resources( + new PNTokenResources() + { + Channels = new Dictionary() + { + { + channelName, fullAccess + } + }, + ChannelGroups = new Dictionary() + { + { + channelGroupName, fullAccess + }, + { + channelGroupName1, fullAccess + }, + { + channelGroupName2, fullAccess + } + } + }).ExecuteAsync(); + + await Task.Delay(4000); + authToken = grantResult.Result?.Token; + pubnub.Destroy(); pubnub.PubnubUnitTest = null; pubnub = null; - Assert.IsTrue(receivedGrantMessage, "WhenSubscribedToAChannelGroup Grant access failed."); + Assert.IsTrue(grantResult.Status.Error == false && grantResult.Result != null, + "WhenSubscribedToAChannelGroup Grant access failed."); } [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } @@ -184,10 +158,6 @@ public static void ThenSubscribeShouldReturnReceivedMessage() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -219,7 +189,7 @@ public static void ThenSubscribeShouldReturnReceivedMessage() subscribeManualEvent.Set(); } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); pubnub.AddListener(listenerSubCallack); string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; @@ -264,7 +234,7 @@ public static void ThenSubscribeShouldReturnReceivedMessage() server.AddRequest(new Request() .WithMethod("GET") .WithPath(String.Format("/v2/subscribe/{0}/{1}/0", PubnubCommon.SubscribeKey, ",")) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel-group", "hello_my_group") .WithParameter("heartbeat", "300") .WithParameter("pnsdk", PubnubCommon.EncodedSDK) @@ -307,7 +277,6 @@ public static void ThenSubscribeShouldReturnReceivedMessage() if (r != null && s.StatusCode == 200 && !s.Error) { Debug.WriteLine("Publish Response: " + pubnub.JsonPluggableLibrary.SerializeToJsonString(r)); - publishTimetoken = r.Timetoken; receivedMessage = true; } @@ -349,10 +318,6 @@ public static void ThenSubscribeShouldReturnConnectStatus() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -376,7 +341,7 @@ public static void ThenSubscribeShouldReturnConnectStatus() subscribeManualEvent.Set(); } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); pubnub.AddListener(listenerSubCallack); string expected = "{\"status\": 200, \"message\": \"OK\", \"service\": \"channel-registry\", \"error\": false}"; @@ -421,7 +386,7 @@ public static void ThenSubscribeShouldReturnConnectStatus() server.AddRequest(new Request() .WithMethod("GET") .WithPath(String.Format("/v2/subscribe/{0}/{1}/0", PubnubCommon.SubscribeKey, ",")) - .WithParameter("auth", authKey) + //.WithParameter("auth", authKey) .WithParameter("channel-group", "hello_my_group") .WithParameter("heartbeat", "300") .WithParameter("pnsdk", PubnubCommon.EncodedSDK) @@ -474,10 +439,6 @@ public static void ThenMultiSubscribeShouldReturnConnectStatus() { config.SecretKey = PubnubCommon.SecretKey; } - else if (!string.IsNullOrEmpty(authKey) && !PubnubCommon.SuppressAuthKey) - { - config.AuthKey = authKey; - } server.RunOnHttps(false); @@ -502,7 +463,7 @@ public static void ThenMultiSubscribeShouldReturnConnectStatus() subscribeManualEvent.Set(); } }); - pubnub = createPubNubInstance(config); + pubnub = createPubNubInstance(config, authToken); pubnub.AddListener(listenerSubCallack); manualResetEventWaitTimeout = 310 * 1000; diff --git a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs index 29b37443e..49d5915f6 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenSubscribedToWildcardChannel.cs @@ -37,7 +37,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -51,7 +54,8 @@ public static void Init() AuthKey = authKey, Secure = false, LogVerbosity = PNLogVerbosity.BODY, - PubnubLog = new TestLog() + PubnubLog = new TestLog(), + EnableEventEngine = false }; server.RunOnHttps(false); @@ -420,6 +424,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs index d7fb05348..9e04290f3 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannel.cs @@ -35,7 +35,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -87,6 +90,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs index 7dc626876..ed13eeae6 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenUnsubscribedToAChannelGroup.cs @@ -23,7 +23,10 @@ public static void Init() unitLog.LogLevel = MockServer.LoggingMethod.Level.Verbose; server = Server.Instance(); MockServer.LoggingMethod.MockServerLog = unitLog; - server.Start(); + if (PubnubCommon.EnableStubTest) + { + server.Start(); + } if (!PubnubCommon.PAMServerSideGrant) { return; } @@ -109,6 +112,12 @@ public static void Init() [TearDown] public static void Exit() { + if (pubnub != null) + { + pubnub.Destroy(); + pubnub.PubnubUnitTest = null; + pubnub = null; + } server.Stop(); } diff --git a/src/UnitTests/PubnubApi.Tests/WhenUserIdInPNConfig.cs b/src/UnitTests/PubnubApi.Tests/WhenUserIdInPNConfig.cs index 8ada91bc7..dd1c8d98e 100644 --- a/src/UnitTests/PubnubApi.Tests/WhenUserIdInPNConfig.cs +++ b/src/UnitTests/PubnubApi.Tests/WhenUserIdInPNConfig.cs @@ -11,17 +11,6 @@ namespace PubNubMessaging.Tests [TestFixture] public class WhenUserIdInPNConfig : TestHarness { - [SetUp] - public static void Init() - { - } - - [TearDown] - public static void Exit() - { - - } - [Test] public static void ThenUuidSetShouldFailWithUserIdConstructorValue() { diff --git a/src/UnitTests/PubnubApiPCL.Tests/SetupTrace.cs b/src/UnitTests/PubnubApiPCL.Tests/SetupTrace.cs new file mode 100644 index 000000000..ca03716ab --- /dev/null +++ b/src/UnitTests/PubnubApiPCL.Tests/SetupTrace.cs @@ -0,0 +1,20 @@ +using System.Diagnostics; +using NUnit.Framework; + +namespace PubnubApiPCL.Tests; + +[SetUpFixture] +public class SetupTrace +{ + [OneTimeSetUp] + public void StartTest() + { + Trace.Listeners.Add(new ConsoleTraceListener()); + } + + [OneTimeTearDown] + public void EndTest() + { + Trace.Flush(); + } +} \ No newline at end of file