/mono-for-mac/3.3.0.1/PubNub-Messaging/PubNub-Console/PubnubBase.cs
C# | 2925 lines | 2303 code | 308 blank | 314 comment | 408 complexity | 5cc62c7e952711fdebf1d493cd848207 MD5 | raw file
Possible License(s): Apache-2.0
Large files files are truncated, but you can click here to view the full file
- using System;
- using System.IO;
- using System.Text;
- using System.Net;
- using System.Collections;
- using System.Collections.Generic;
- using System.Security.Cryptography;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Json;
- using System.ComponentModel;
- using System.Reflection;
- using System.Web.Script.Serialization;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Diagnostics;
- using System.Collections.Concurrent;
- using System.Net.NetworkInformation;
- using System.Net.Sockets;
- using System.Configuration;
- using Microsoft.Win32;
- using System.Linq;
- using System.Text.RegularExpressions;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- namespace PubNub_Messaging2
- {
- // INotifyPropertyChanged provides a standard event for objects to notify clients that one of its properties has changed
- public class PubnubBase : INotifyPropertyChanged
- {
- const int PUBNUB_WEBREQUEST_CALLBACK_INTERVAL_IN_SEC = 310;
- const int PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC = 15;
- const int PUBNUB_NETWORK_CHECK_RETRIES = 50;
- const int PUBNUB_WEBREQUEST_RETRY_INTERVAL_IN_SEC = 10;
- // Common property changed event
- public event PropertyChangedEventHandler PropertyChanged;
- public void RaisePropertyChanged(string propertyName)
- {
- var handler = PropertyChanged;
- if (handler != null)
- {
- handler(this, new PropertyChangedEventArgs(propertyName));
- }
- }
- ConcurrentDictionary<string, long> _channelSubscription = new ConcurrentDictionary<string, long>();
- ConcurrentDictionary<string, long> _channelPresence = new ConcurrentDictionary<string, long>();
- ConcurrentDictionary<string, RequestState> _channelRequest = new ConcurrentDictionary<string, RequestState>();
- ConcurrentDictionary<string, bool> _channelInternetStatus = new ConcurrentDictionary<string, bool>();
- ConcurrentDictionary<string, int> _channelInternetRetry = new ConcurrentDictionary<string, int>();
- ConcurrentDictionary<string, Timer> _channelReconnectTimer = new ConcurrentDictionary<string, Timer>();
- System.Threading.Timer heartBeatTimer;
- private static bool _pubnetSystemActive = true;
- private static TraceSwitch appSwitch = new TraceSwitch("PubnubTraceSwitch", "Pubnub Trace Switch in config file");
- // Publish
- private ConcurrentDictionary<string, object> _publishMsg = new ConcurrentDictionary<string, object>();
- // History of Messages
- private List<object> _History = new List<object>();
- public List<object> History { get { return _History; } set { _History = value; RaisePropertyChanged("History"); } }
- // Subscribe
- private ConcurrentDictionary<string, object> _subscribeMsg = new ConcurrentDictionary<string, object>();
- // Presence
- private ConcurrentDictionary<string, object> _presenceMsg = new ConcurrentDictionary<string, object>();
- // Timestamp
- private List<object> _Time = new List<object>();
- private bool _overrideTcpKeepAlive = false;
- // Pubnub Core API implementation
- private string ORIGIN = "pubsub.pubnub.com";
- private int LIMIT = 1800; // Temporary setup, remove limit as server will handle this.
- private string PUBLISH_KEY = "";
- private string SUBSCRIBE_KEY = "";
- private string SECRET_KEY = "";
- private string CIPHER_KEY = "";
- private bool SSL = false;
- private string sessionUUID = "";
- private string parameters = "";
- /**
- * Pubnub instance initialization function
- *
- * @param string pubish_key.
- * @param string subscribe_key.
- * @param string secret_key.
- * @param bool ssl_on
- */
- private void init(string publish_key, string subscribe_key, string secret_key, string cipher_key, bool ssl_on)
- {
- this.PUBLISH_KEY = publish_key;
- this.SUBSCRIBE_KEY = subscribe_key;
- this.SECRET_KEY = secret_key;
- this.CIPHER_KEY = cipher_key;
- this.SSL = ssl_on;
- if (this.sessionUUID == "")
- this.sessionUUID = Guid.NewGuid().ToString();
- // SSL is ON?
- if (this.SSL)
- this.ORIGIN = "https://" + this.ORIGIN;
- else
- this.ORIGIN = "http://" + this.ORIGIN;
- _overrideTcpKeepAlive = Boolean.Parse(ConfigurationManager.AppSettings["OverrideTcpKeepAlive"].ToString());
- //Initiate System Events for PowerModeChanged - to monitor suspend/resume
- initiatePowerModeCheck();
- }
- private void reconnectNetwork<T>(ReconnectState<T> netState)
- {
- System.Threading.Timer timer = new Timer(new TimerCallback(reconnectNetworkCallback<T>), netState, 0, PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000);
- _channelReconnectTimer.AddOrUpdate(netState.channel, timer, (key, oldState) => timer);
- }
- void reconnectNetworkCallback<T>(Object reconnectState)
- {
- try
- {
- ReconnectState<T> netState = reconnectState as ReconnectState<T>;
- if (netState != null)
- {
- if (_channelInternetStatus.ContainsKey(netState.channel)
- && (netState.type == ResponseType.Subscribe || netState.type == ResponseType.Presence))
- {
- if (_channelInternetStatus[netState.channel])
- {
- //Reset Retry if previous state is true
- _channelInternetRetry.AddOrUpdate(netState.channel, 0, (key, oldValue) => 0);
- }
- else
- {
- _channelInternetRetry.AddOrUpdate(netState.channel, 1, (key, oldValue) => oldValue + 1);
- Trace.WriteLine(string.Format("DateTime {0}, {1} {2} reconnectNetworkCallback. Retry {3} of {4}", DateTime.Now.ToString(), netState.channel, netState.type, _channelInternetRetry[netState.channel], PUBNUB_NETWORK_CHECK_RETRIES));
- }
- }
-
- if (_channelInternetStatus[netState.channel])
- {
- if (_channelReconnectTimer.ContainsKey(netState.channel))
- {
- _channelReconnectTimer[netState.channel].Change(Timeout.Infinite, Timeout.Infinite);
- _channelReconnectTimer[netState.channel].Dispose();
- }
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, {1} {2} reconnectNetworkCallback. Internet Available : {3}", DateTime.Now.ToString(), netState.channel, netState.type, _channelInternetStatus[netState.channel]));
- }
- switch (netState.type)
- {
- case ResponseType.Subscribe:
- _subscribe(netState.channel, netState.timetoken, netState.callback, false);
- break;
- case ResponseType.Presence:
- _presence(netState.channel, netState.timetoken, netState.callback, false);
- break;
- default:
- break;
- }
- }
- else if (_channelInternetRetry[netState.channel] >= PUBNUB_NETWORK_CHECK_RETRIES)
- {
- if (_channelReconnectTimer.ContainsKey(netState.channel))
- {
- _channelReconnectTimer[netState.channel].Change(Timeout.Infinite, Timeout.Infinite);
- _channelReconnectTimer[netState.channel].Dispose();
- }
- switch (netState.type)
- {
- case ResponseType.Subscribe:
- subscribeExceptionHandler(netState.channel, netState.callback, true);
- break;
- case ResponseType.Presence:
- presenceExceptionHandler(netState.channel, netState.callback, true);
- break;
- default:
- break;
- }
- }
- }
- else
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Unknown request state in reconnectNetworkCallback", DateTime.Now.ToString()));
- }
- }
- }
- catch (Exception ex)
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0} method:reconnectNetworkCallback \n Exception Details={1}", DateTime.Now.ToString(), ex.ToString()));
- }
- }
- }
- private void initiatePowerModeCheck()
- {
- try
- {
- SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Initiated System Event - PowerModeChanged.", DateTime.Now.ToString()));
- }
- }
- catch(Exception ex)
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0} No support for System Event - PowerModeChanged.", DateTime.Now.ToString()));
- Trace.WriteLine(string.Format("DateTime {0} {1}", DateTime.Now.ToString(),ex.ToString()));
- }
- }
- }
- void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
- {
- if (e.Mode == PowerModes.Suspend)
- {
- _pubnetSystemActive = false;
- TerminatePendingWebRequest();
- if (_overrideTcpKeepAlive)
- {
- heartBeatTimer.Change(Timeout.Infinite, Timeout.Infinite);
- }
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, System entered into Suspend Mode.", DateTime.Now.ToString()));
- if (_overrideTcpKeepAlive)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Disabled Timer for heartbeat ", DateTime.Now.ToString()));
- }
- }
- }
- else if (e.Mode == PowerModes.Resume)
- {
- _pubnetSystemActive = true;
- if (_overrideTcpKeepAlive)
- {
- heartBeatTimer.Change(
- (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000,
- (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000);
- }
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, System entered into Resume/Awake Mode.", DateTime.Now.ToString()));
- if (_overrideTcpKeepAlive)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Enabled Timer for heartbeat ", DateTime.Now.ToString()));
- }
- }
- }
- }
- private void TerminatePendingWebRequest()
- {
- TerminatePendingWebRequest(null);
- }
- private void TerminatePendingWebRequest(RequestState state)
- {
- if (state != null && state.request != null)
- {
- state.request.Abort();
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0} TerminatePendingWebRequest {1}", DateTime.Now.ToString(), state.request.RequestUri.ToString()));
- }
- RequestState removedReq;
- bool removeKey = _channelRequest.TryRemove(state.channel, out removedReq);
- if (!removeKey && appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0} Unable to remove web request from dictionary in TerminatePendingWebRequest for channel= {1}", DateTime.Now.ToString(), state.channel));
- }
- }
- else
- {
- ConcurrentDictionary<string, RequestState> webReq = _channelRequest;
- ICollection<string> keyCol = _channelRequest.Keys;
- foreach (string key in keyCol)
- {
- RequestState currReq = _channelRequest[key];
- if (currReq.request != null)
- {
- currReq.request.Abort();
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0} TerminatePendingWebRequest {1}", DateTime.Now.ToString(), currReq.request.RequestUri.ToString()));
- }
- bool removeKey = _channelRequest.TryRemove(key, out currReq);
- if (!removeKey && appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0} Unable to remove web request from dictionary in TerminatePendingWebRequest for channel= {1}", DateTime.Now.ToString(), key));
- }
- }
- }
- }
- }
- ~PubnubBase()
- {
- //detach
- SystemEvents.PowerModeChanged -= new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
- }
- /**
- * PubNub 3.0 API
- *
- * Prepare Pubnub messaging class initial state
- *
- * @param string pubish_key.
- * @param string subscribe_key.
- * @param string secret_key.
- * @param bool ssl_on
- */
- public PubnubBase(string publish_key, string subscribe_key, string secret_key, string cipher_key, bool ssl_on)
- {
- this.init(publish_key, subscribe_key, secret_key, cipher_key, ssl_on);
- }
- /**
- * PubNub 2.0 Compatibility
- *
- * Prepare Pubnub messaging class initial state
- *
- * @param string pubish_key.
- * @param string subscribe_key.
- */
- public PubnubBase(string publish_key, string subscribe_key)
- {
- this.init(publish_key, subscribe_key, "", "", false);
- }
- /**
- * PubNub 3.0 without SSL
- *
- * Prepare Pubnub messaging class initial state
- *
- * @param string pubish_key.
- * @param string subscribe_key.
- * @param string secret_key.
- */
- public PubnubBase(string publish_key, string subscribe_key, string secret_key)
- {
- this.init(publish_key, subscribe_key, secret_key, "", false);
- }
- /**
- * History
- *
- * Load history from a channel
- *
- * @param String channel name.
- * @param int limit history count response
- * @return ListArray of history
- */
- [Obsolete("This method should no longer be used, please use detailedHistory() instead.")]
- public bool history(string channel, int limit)
- {
- List<string> url = new List<string>();
- url.Add("history");
- url.Add(this.SUBSCRIBE_KEY);
- url.Add(channel);
- url.Add("0");
- url.Add(limit.ToString());
- return _request(url, ResponseType.History);
- }
- /**
- * Detailed History
- */
- public bool detailedHistory(string channel, long start, long end, int count, bool reverse, Action<object> usercallback)
- {
- return detailedHistory<object>(channel, start, end, count, reverse, usercallback);
- }
- public bool detailedHistory<T>(string channel, long start, long end, int count, bool reverse, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel))
- {
- throw new ArgumentException("Missing Channel");
- }
- parameters = "";
- if (count <= -1) count = 100;
- parameters = "?count=" + count;
- if (reverse)
- parameters = parameters + "&" + "reverse=" + reverse.ToString().ToLower();
- if (start != -1)
- parameters = parameters + "&" + "start=" + start.ToString().ToLower();
- if (end != -1)
- parameters = parameters + "&" + "end=" + end.ToString().ToLower();
- List<string> url = new List<string>();
- url.Add("v2");
- url.Add("history");
- url.Add("sub-key");
- url.Add(this.SUBSCRIBE_KEY);
- url.Add("channel");
- url.Add(channel);
- return _urlRequest<T>(url, ResponseType.DetailedHistory, usercallback, false);
- }
- public bool detailedHistory(string channel, long start, Action<object> usercallback, bool reverse)
- {
- return detailedHistory<object>(channel, start, -1, -1, reverse, usercallback);
- }
- public bool detailedHistory<T>(string channel, long start, Action<T> usercallback, bool reverse)
- {
- return detailedHistory<T>(channel, start, -1, -1, reverse, usercallback);
- }
- public bool detailedHistory(string channel, int count, Action<object> usercallback)
- {
- return detailedHistory<object>(channel, -1, -1, count, false, usercallback);
- }
- public bool detailedHistory<T>(string channel, int count, Action<T> usercallback)
- {
- return detailedHistory<T>(channel, -1, -1, count, false, usercallback);
- }
-
- /**
- * Publish
- *
- * Send a message to a channel
- *
- * @param String channel name.
- * @param List<object> info.
- * @return bool false on fail
- */
- public bool publish(string channel, object message, Action<object> usercallback)
- {
- return publish<object>(channel, message, usercallback);
- }
- public bool publish<T>(string channel, object message, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel) || message == null)
- {
- throw new ArgumentException("Missing Channel or Message");
- }
- if (string.IsNullOrWhiteSpace(this.PUBLISH_KEY) || this.PUBLISH_KEY.Length <= 0)
- {
- throw new MissingFieldException("Invalid publish key");
- }
- if (usercallback == null)
- {
- throw new ArgumentException("Missing Callback");
- }
- string msg = jsonEncodePublishMsg(message);
- // Generate String to Sign
- string signature = "0";
- if (this.SECRET_KEY.Length > 0)
- {
- StringBuilder string_to_sign = new StringBuilder();
- string_to_sign
- .Append(this.PUBLISH_KEY)
- .Append('/')
- .Append(this.SUBSCRIBE_KEY)
- .Append('/')
- .Append(this.SECRET_KEY)
- .Append('/')
- .Append(channel)
- .Append('/')
- .Append(msg); // 1
- // Sign Message
- signature = md5(string_to_sign.ToString());
- }
- // Build URL
- List<string> url = new List<string>();
- url.Add("publish");
- url.Add(this.PUBLISH_KEY);
- url.Add(this.SUBSCRIBE_KEY);
- url.Add(signature);
- url.Add(channel);
- url.Add("0");
- url.Add(msg);
- return _urlRequest<T>(url, ResponseType.Publish, usercallback, false);
- }
- private string jsonEncodePublishMsg(object originalMsg)
- {
- string msg = SerializeToJsonString(originalMsg);
- if (this.CIPHER_KEY.Length > 0)
- {
- PubnubCrypto aes = new PubnubCrypto(this.CIPHER_KEY);
- string encryptMsg = aes.encrypt(msg);
- msg = SerializeToJsonString(encryptMsg);
- }
- return msg;
- }
- private List<object> decodeMsg(List<object> message, ResponseType type)
- {
- List<object> receivedMsg = new List<object>();
- if (type == ResponseType.Presence || type == ResponseType.Publish || type == ResponseType.Time || type == ResponseType.Here_Now || type == ResponseType.Leave)
- {
- return message;
- }
- else if (type == ResponseType.DetailedHistory)
- {
- receivedMsg = decodeDecryptLoop(message);
- }
- else
- {
- receivedMsg = decodeDecryptLoop(message);
- }
- return receivedMsg;
- }
- private List<object> decodeDecryptLoop(List<object> message)
- {
- List<object> returnMsg = new List<object>();
- if (this.CIPHER_KEY.Length > 0)
- {
- PubnubCrypto aes = new PubnubCrypto(this.CIPHER_KEY);
- var myObjectArray = (from item in message select item as object).ToArray();
- IEnumerable enumerable = myObjectArray[0] as IEnumerable;
- if (enumerable != null)
- {
- List<object> receivedMsg = new List<object>();
- foreach (object element in enumerable)
- {
- string decryptMsg = aes.decrypt(element.ToString());
- object decodeMsg = JsonConvert.DeserializeObject<object>(decryptMsg);
- receivedMsg.Add(decodeMsg);
- }
- returnMsg.Add(receivedMsg);
- }
- for (int index = 1; index < myObjectArray.Length; index++)
- {
- returnMsg.Add(myObjectArray[index]);
- }
- return returnMsg;
- }
- else
- {
- var myObjectArray = (from item in message select item as object).ToArray();
- IEnumerable enumerable = myObjectArray[0] as IEnumerable;
- if (enumerable != null)
- {
- List<object> receivedMsg = new List<object>();
- foreach (object element in enumerable)
- {
- receivedMsg.Add(element);
- }
- returnMsg.Add(receivedMsg);
- }
- for (int index = 1; index < myObjectArray.Length; index++)
- {
- returnMsg.Add(myObjectArray[index]);
- }
- return returnMsg;
- }
- }
- /**
- * Subscribe
- *
- * Listen for a message on a channel (BLOCKING)
- *
- * @param String channel name.
- * @param Procedure function callback
- */
- public void subscribe(string channel, Action<object> usercallback)
- {
- subscribe<object>(channel, usercallback);
- }
- public void subscribe<T>(string channel, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel))
- {
- throw new ArgumentException("Missing Channel");
- }
- if (usercallback == null)
- {
- throw new ArgumentException("Missing Callback");
- }
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, requested subscribe for channel={1}", DateTime.Now.ToString(), channel));
- }
- if (_channelSubscription.ContainsKey(channel))
- {
- List<object> result = new List<object>();
- string jsonString = "[0, \"Already subscribed\"]";
- result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
- result.Add(channel);
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, JSON subscribe response={1}", DateTime.Now.ToString(), jsonString));
- }
- goToUserCallback<T>(result, usercallback);
- }
- else
- {
- _channelSubscription.GetOrAdd(channel, 0);
- resetInternetCheckSettings(channel);
- _subscribe<T>(channel, 0, usercallback, false);
- }
- }
- private void resetInternetCheckSettings(string channel)
- {
- if (_channelInternetStatus.ContainsKey(channel))
- {
- _channelInternetStatus.AddOrUpdate(channel, true, (key, oldValue) => true);
- }
- else
- {
- _channelInternetStatus.GetOrAdd(channel, true); //Set to true for internet connection
- }
- if (_channelInternetRetry.ContainsKey(channel))
- {
- _channelInternetRetry.AddOrUpdate(channel, 0, (key, oldValue) => 0);
- }
- else
- {
- _channelInternetRetry.GetOrAdd(channel, 0); //Initialize the internet retry count
- }
- }
- void OnPubnubWebRequestTimeout(object state, bool timeout)
- {
- if (timeout)
- {
- RequestState currentState = state as RequestState;
- if (currentState != null)
- {
- HttpWebRequest request = currentState.request;
- if (request != null)
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubWebRequestTimeout: client request timeout reached.Request aborted for channel = {1}", DateTime.Now.ToString(), currentState.channel));
- }
- request.Abort();
- }
- }
- else
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubWebRequestTimeout: client request timeout reached. However state is unknown", DateTime.Now.ToString()));
- }
- }
- if (_overrideTcpKeepAlive)
- {
- //reset heart beat time because http request already timedout
- heartBeatTimer.Change(
- (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000,
- (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000);
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubWebRequestTimeout: resetting the heartbeat timeout", DateTime.Now.ToString()));
- }
- }
- }
- }
- void OnPubnubHeartBeatTimeoutCallback(Object heartbeatState)
- {
- if (appSwitch.TraceVerbose)
- {
- Trace.WriteLine(string.Format("DateTime: {0}, **OnPubnubHeartBeatTimeoutCallback**", DateTime.Now.ToString()));
- }
- RequestState currentState = heartbeatState as RequestState;
- if (currentState != null)
- {
- bool networkConnection = ClientNetworkStatus.checkInternetStatus(_pubnetSystemActive);
- if (_channelInternetStatus.ContainsKey(currentState.channel)
- && (currentState.type == ResponseType.Subscribe || currentState.type == ResponseType.Presence)
- && _overrideTcpKeepAlive)
- {
- _channelInternetStatus[currentState.channel] = networkConnection;
- if (appSwitch.TraceVerbose)
- {
- Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubHeartBeatTimeoutCallback - Internet connection = {1}", DateTime.Now.ToString(), networkConnection));
- }
- if (!networkConnection)
- {
- TerminatePendingWebRequest(currentState);
- }
- }
- }
- }
- /// <summary>
- /// Check the response of the REST API and call for re-subscribe
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="subscribeResult"></param>
- /// <param name="usercallback"></param>
- private void subscribeInternalCallback<T>(object subscribeResult, Action<T> usercallback)
- {
- List<object> message = subscribeResult as List<object>;
- string channelName = "";
- if (message != null && message.Count >= 3)
- {
- channelName = message[2].ToString();
- }
- else
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Lost Channel Name for resubscribe", DateTime.Now.ToString()));
- }
- return;
- }
- if (!_channelSubscription.ContainsKey(channelName))
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Due to Unsubscribe, further re-subscription was stopped for channel {1}", DateTime.Now.ToString(), channelName.ToString()));
- }
- return;
- }
- if (message != null && message.Count >= 3)
- {
- _subscribe<T>(channelName, (object)message[1], usercallback, false);
- }
- }
- private void presenceInternalCallback<T>(object presenceResult, Action<T> usercallback)
- {
- List<object> message = presenceResult as List<object>;
- string channelName = "";
- if (message != null && message.Count >= 3)
- {
- channelName = message[2].ToString();
- }
- else
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Lost Channel Name for re-presence", DateTime.Now.ToString()));
- }
- return;
- }
- if (message != null && message.Count >= 3)
- {
- _presence<T>(channelName, (object)message[1], usercallback, false);
- }
- }
- /// <summary>
- /// To unsubscribe a channel
- /// </summary>
- /// <param name="channel"></param>
- /// <param name="usercallback"></param>
- public void unsubscribe(string channel, Action<object> usercallback)
- {
- unsubscribe<object>(channel, usercallback);
- }
- /// <summary>
- /// To unsubscribe a channel
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="channel"></param>
- /// <param name="usercallback"></param>
- public void unsubscribe<T>(string channel, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel))
- {
- throw new ArgumentException("Missing Channel");
- }
- bool unsubStatus = false;
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, requested unsubscribe for channel={1}", DateTime.Now.ToString(), channel));
- }
-
- string jsonString = "";
- List<object> result = new List<object>();
- if (_channelSubscription.ContainsKey(channel))
- {
- if (_channelRequest.ContainsKey(channel))
- {
- long unsubValue;
- unsubStatus = _channelSubscription.TryRemove(channel, out unsubValue);
- if (unsubStatus)
- {
- jsonString = string.Format("[1, \"Unsubscribed from {0}\"]", channel);
- }
- else
- {
- jsonString = string.Format("[1, \"Error unsubscribing from {0}\"]", channel);
- }
- HttpWebRequest storedRequest = _channelRequest[channel].request;
- storedRequest.Abort();
- }
-
- result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
- result.Add(channel);
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, JSON unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
- }
- goToUserCallback<T>(result, usercallback);
- //just fire leave() event to REST API for safeguard
- List<string> url = new List<string>();
- url.Add("v2");
- url.Add("presence");
- url.Add("sub_key");
- url.Add(this.SUBSCRIBE_KEY);
- url.Add("channel");
- url.Add(channel);
- url.Add("leave");
- _urlRequest<T>(url, ResponseType.Leave, null, false);
- }
- else
- {
- result = new List<object>();
- jsonString = "[0, \"Channel Not Subscribed\"]";
- result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
- result.Add(channel);
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, JSON unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
- }
- goToUserCallback<T>(result, usercallback);
- }
- }
- /**
- * Subscribe - Private Interface
- *
- * @param String channel name.
- * @param Procedure function callback
- * @param String timetoken.
- */
- private void _subscribe<T>(string channel, object timetoken, Action<T> usercallback, bool reconnect)
- {
- //Exit if the channel is unsubscribed
- if (!_channelSubscription.ContainsKey(channel))
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Due to Unsubscribe, further subscription was stopped for channel {1}", DateTime.Now.ToString(), channel.ToString()));
- }
- return;
- }
- _channelSubscription.AddOrUpdate(channel, Convert.ToInt64(timetoken.ToString()), (key, oldValue) => Convert.ToInt64(timetoken.ToString())); //Store the timetoken
- if (_channelInternetStatus.ContainsKey(channel) && (!_channelInternetStatus[channel]) && _pubnetSystemActive)
- {
- if (_channelInternetRetry.ContainsKey(channel) && (_channelInternetRetry[channel] >= PUBNUB_NETWORK_CHECK_RETRIES))
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Subscribe channel={1} - No internet connection. MAXed retries for internet ", DateTime.Now.ToString(), channel));
- }
- subscribeExceptionHandler<T>(channel, usercallback, true);
- return;
- }
- if (_overrideTcpKeepAlive)
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Subscribe - No internet connection for {1}", DateTime.Now.ToString(), channel));
- }
- ReconnectState<T> netState = new ReconnectState<T>();
- netState.channel = channel;
- netState.type = ResponseType.Subscribe;
- netState.callback = usercallback;
- netState.timetoken = timetoken;
- reconnectNetwork<T>(netState);
- return;
- }
- }
- // Begin recursive subscribe
- try
- {
- // Build URL
- List<string> url = new List<string>();
- url.Add("subscribe");
- url.Add(this.SUBSCRIBE_KEY);
- url.Add(channel);
- url.Add("0");
- url.Add(timetoken.ToString());
- // Wait for message
- _urlRequest<T>(url, ResponseType.Subscribe, usercallback, reconnect);
- }
- catch (Exception ex)
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("DateTime {0} method:_subscribe \n channel={1} \n timetoken={2} \n Exception Details={3}", DateTime.Now.ToString(), channel, timetoken.ToString(), ex.ToString()));
- }
- this._subscribe<T>(channel, timetoken, usercallback, false);
- }
- }
- /**
- * Presence feature
- *
- * Listen for a presence message on a channel (BLOCKING)
- *
- * @param String channel name. (+"pnpres")
- * @param Procedure function callback
- */
- public void presence(string channel, Action<object> usercallback)
- {
- presence<object>(channel, usercallback);
- }
- public void presence<T>(string channel, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel))
- {
- throw new ArgumentException("Missing Channel");
- }
- if (usercallback == null)
- {
- throw new ArgumentException("Missing Callback");
- }
- channel = string.Format("{0}-pnpres", channel);
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, requested presence for channel={1}", DateTime.Now.ToString(), channel));
- }
- if (_channelPresence.ContainsKey(channel))
- {
- List<object> result = new List<object>();
- string jsonString = "[0, \"Presence Already subscribed\"]";
- result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
- result.Add(channel.Replace("-pnpres", ""));
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, JSON presence response={1}", DateTime.Now.ToString(), jsonString));
- }
- goToUserCallback<T>(result, usercallback);
- }
- else
- {
- _channelPresence.GetOrAdd(channel, 0);
- resetInternetCheckSettings(channel);
- this._presence<T>(channel, 0, usercallback, false);
- }
- }
- /**
- * Presence feature - Private Interface
- *
- * @param String channel name.
- * @param Procedure function callback
- * @param String timetoken.
- */
- private void _presence<T>(string channel, object timetoken, Action<T> usercallback, bool reconnect)
- {
- //Exit if the channel is unsubscribed
- if (!_channelPresence.ContainsKey(channel))
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Due to Presence-unsubscribe, further presence was stopped for channel {1}", DateTime.Now.ToString(), channel.ToString()));
- }
- return;
- }
- _channelPresence.AddOrUpdate(channel, Convert.ToInt64(timetoken.ToString()), (key, oldValue) => Convert.ToInt64(timetoken.ToString())); //Store the timetoken
- if (_channelInternetStatus.ContainsKey(channel) && (!_channelInternetStatus[channel]) && _pubnetSystemActive)
- {
- if (_channelInternetRetry.ContainsKey(channel) && (_channelInternetRetry[channel] >= PUBNUB_NETWORK_CHECK_RETRIES))
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Presence channel={1} - No internet connection. MAXed retries for internet ", DateTime.Now.ToString(), channel));
- }
- presenceExceptionHandler<T>(channel, usercallback, true);
- return;
- }
- if (_overrideTcpKeepAlive)
- {
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, Presence - No internet connection for {1}", DateTime.Now.ToString(), channel));
- }
- ReconnectState<T> netState = new ReconnectState<T>();
- netState.channel = channel;
- netState.type = ResponseType.Presence;
- netState.callback = usercallback;
- netState.timetoken = timetoken;
- reconnectNetwork<T>(netState);
- return;
- }
- }
- // Begin recursive subscribe
- try
- {
- // Build URL
- List<string> url = new List<string>();
- url.Add("subscribe");
- url.Add(this.SUBSCRIBE_KEY);
- url.Add(channel);
- url.Add("0");
- url.Add(timetoken.ToString());
- // Wait for message
- _urlRequest<T>(url, ResponseType.Presence, usercallback, reconnect);
- }
- catch (Exception ex)
- {
- if (appSwitch.TraceError)
- {
- Trace.WriteLine(string.Format("method:_presence \n channel={0} \n timetoken={1} \n Exception Details={2}", channel, timetoken.ToString(), ex.ToString()));
- }
- this._presence<T>(channel, timetoken, usercallback, false);
- }
- }
- public void presence_unsubscribe(string channel, Action<object> usercallback)
- {
- presence_unsubscribe<object>(channel, usercallback);
- }
- public void presence_unsubscribe<T>(string channel, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel))
- {
- throw new ArgumentException("Missing Channel");
- }
- channel = string.Format("{0}-pnpres", channel);
- bool unsubStatus = false;
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, requested presence-unsubscribe for channel={1}", DateTime.Now.ToString(), channel));
- }
- string jsonString = "";
- List<object> result = new List<object>();
- if (_channelPresence.ContainsKey(channel))
- {
- if (_channelRequest.ContainsKey(channel))
- {
- long unsubPreValue;
- unsubStatus = _channelPresence.TryRemove(channel, out unsubPreValue);
- if (unsubStatus)
- {
- jsonString = string.Format("[1, \"Presence-Unsubscribed from {0}\"]", channel.Replace("-pnpres", ""));
- }
- else
- {
- jsonString = string.Format("[1, \"Error presence-unsubscribing from {0}\"]", channel.Replace("-pnpres", ""));
- }
- HttpWebRequest storedRequest = _channelRequest[channel].request;
- storedRequest.Abort();
- }
- result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
- result.Add(channel.Replace("-pnpres", ""));
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, JSON presence-unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
- }
- goToUserCallback<T>(result, usercallback);
- }
- else
- {
- result = new List<object>();
- jsonString = "[0, \"Channel Not Subscribed\"]";
- result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
- result.Add(channel.Replace("-pnpres", ""));
- if (appSwitch.TraceInfo)
- {
- Trace.WriteLine(string.Format("DateTime {0}, JSON presence-unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
- }
- goToUserCallback<T>(result, usercallback);
- }
- }
- public bool here_now(string channel, Action<object> usercallback)
- {
- return here_now<object>(channel, usercallback);
- }
- public bool here_now<T>(string channel, Action<T> usercallback)
- {
- if (string.IsNullOrWhiteSpace(channel))
- {
- throw new ArgumentException("Missing Channel");
- }
- List<string> url = new List<string>();
- url.Add("v2");
- url.Add("presence");
- url.Add("sub_key");
- url.Add(this.SUBSCRIBE_KEY);
- url.Add("channel");
- url.Add(channel);
- return _urlRequest<T>(url, ResponseType.Here_Now, usercallback, false);
- }
- /**
- * Time
- *
- * Timestamp from PubNub Cloud
- *
- * @return object timestamp.
- */
- public bool time(Action<object> usercallback)
- {
- return time<object>(usercallback);
- }
- public bool time<T>(Action<T> usercallback)
- {
- List<string> url = new List<string>();
- url.Add("time");
- url.Add("0");
- return _urlRequest<T>(url, ResponseType.Time, usercallback, false);
- }
- /**
- * Http Get Request
- *
- * @param List<string> request of URL directories.
- * @return List<object> from JSON response.
- */
- private bool _request(List<string> url_components, ResponseType type)
- {
- List<object> result = new List<object>();
- StringBuilder url = new StringBuilder();
- // Add Origin To The Request
- url.Append(this.ORIGIN);
- // Generate URL with UTF-8 Encoding
- foreach (string url_bit in url_components)
- {
- url.Append("/");
- url.Append(_encodeURIcomponent(url_bit, type));
- }
- if (type == ResponseType.Presence || type == ResponseType.Subscribe)
- {
- url.Append("?uuid=");
- url.Append(this.sessionUUID);
- }
- if (type == ResponseType.DetailedHistory)
- url.Append(parameters);
- // Temporary fail if string too long
- if (url.Length > this.LIMIT)
- {
- result.Add(0);
- result.Add("Message Too Long.");
- // return result;
- }
- Uri requestUri = new Uri(url.ToString());
- // Force canonical path and query
- string paq = requestUri.PathAndQuery;
- FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
- ulong flags = (ulong)flagsFieldInfo.GetValue(requestUri);
- flags &= ~((ulong)0x30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
- flagsFieldInfo.SetValue(requestUri, flags);
- // Create Request
- HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
- try
- {
- // Make request with the following inline Asynchronous callback
- IAsyncResult asyncResult = request.BeginGetResponse(new AsyncCallback((asynchronousResult) =>
- {
- HttpWebRequest aRequest = (HttpWebRequest)asynchronousResult.AsyncState;
- HttpWebResponse aResponse = (HttpWebResponse)aRequest.EndGetResponse(asynchronousResult);
- using (StreamReader streamReader = new StreamReader(aResponse.GetResponseStream()))
- {
- // Deserialize the result
- string jsonString = streamReader.ReadToEnd();
- result = WrapResultBasedOnResponseType(type, jsonString, url_components, false);
- }
- }), request
- );
- return true;
- }
- catch (System.Exception ex)
- {
- Console.WriteLine(ex.ToString());
- …
Large files files are truncated, but you can click here to view the full file