PageRenderTime 63ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/mono-for-mac/3.3.0.1/PubNub-Messaging/PubNub-Console/PubnubBase.cs

https://github.com/jhey/pubnub-api
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

  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Net;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Security.Cryptography;
  8. using System.Runtime.Serialization;
  9. using System.Runtime.Serialization.Json;
  10. using System.ComponentModel;
  11. using System.Reflection;
  12. using System.Web.Script.Serialization;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using System.Diagnostics;
  16. using System.Collections.Concurrent;
  17. using System.Net.NetworkInformation;
  18. using System.Net.Sockets;
  19. using System.Configuration;
  20. using Microsoft.Win32;
  21. using System.Linq;
  22. using System.Text.RegularExpressions;
  23. using Newtonsoft.Json;
  24. using Newtonsoft.Json.Linq;
  25. namespace PubNub_Messaging2
  26. {
  27. // INotifyPropertyChanged provides a standard event for objects to notify clients that one of its properties has changed
  28. public class PubnubBase : INotifyPropertyChanged
  29. {
  30. const int PUBNUB_WEBREQUEST_CALLBACK_INTERVAL_IN_SEC = 310;
  31. const int PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC = 15;
  32. const int PUBNUB_NETWORK_CHECK_RETRIES = 50;
  33. const int PUBNUB_WEBREQUEST_RETRY_INTERVAL_IN_SEC = 10;
  34. // Common property changed event
  35. public event PropertyChangedEventHandler PropertyChanged;
  36. public void RaisePropertyChanged(string propertyName)
  37. {
  38. var handler = PropertyChanged;
  39. if (handler != null)
  40. {
  41. handler(this, new PropertyChangedEventArgs(propertyName));
  42. }
  43. }
  44. ConcurrentDictionary<string, long> _channelSubscription = new ConcurrentDictionary<string, long>();
  45. ConcurrentDictionary<string, long> _channelPresence = new ConcurrentDictionary<string, long>();
  46. ConcurrentDictionary<string, RequestState> _channelRequest = new ConcurrentDictionary<string, RequestState>();
  47. ConcurrentDictionary<string, bool> _channelInternetStatus = new ConcurrentDictionary<string, bool>();
  48. ConcurrentDictionary<string, int> _channelInternetRetry = new ConcurrentDictionary<string, int>();
  49. ConcurrentDictionary<string, Timer> _channelReconnectTimer = new ConcurrentDictionary<string, Timer>();
  50. System.Threading.Timer heartBeatTimer;
  51. private static bool _pubnetSystemActive = true;
  52. private static TraceSwitch appSwitch = new TraceSwitch("PubnubTraceSwitch", "Pubnub Trace Switch in config file");
  53. // Publish
  54. private ConcurrentDictionary<string, object> _publishMsg = new ConcurrentDictionary<string, object>();
  55. // History of Messages
  56. private List<object> _History = new List<object>();
  57. public List<object> History { get { return _History; } set { _History = value; RaisePropertyChanged("History"); } }
  58. // Subscribe
  59. private ConcurrentDictionary<string, object> _subscribeMsg = new ConcurrentDictionary<string, object>();
  60. // Presence
  61. private ConcurrentDictionary<string, object> _presenceMsg = new ConcurrentDictionary<string, object>();
  62. // Timestamp
  63. private List<object> _Time = new List<object>();
  64. private bool _overrideTcpKeepAlive = false;
  65. // Pubnub Core API implementation
  66. private string ORIGIN = "pubsub.pubnub.com";
  67. private int LIMIT = 1800; // Temporary setup, remove limit as server will handle this.
  68. private string PUBLISH_KEY = "";
  69. private string SUBSCRIBE_KEY = "";
  70. private string SECRET_KEY = "";
  71. private string CIPHER_KEY = "";
  72. private bool SSL = false;
  73. private string sessionUUID = "";
  74. private string parameters = "";
  75. /**
  76. * Pubnub instance initialization function
  77. *
  78. * @param string pubish_key.
  79. * @param string subscribe_key.
  80. * @param string secret_key.
  81. * @param bool ssl_on
  82. */
  83. private void init(string publish_key, string subscribe_key, string secret_key, string cipher_key, bool ssl_on)
  84. {
  85. this.PUBLISH_KEY = publish_key;
  86. this.SUBSCRIBE_KEY = subscribe_key;
  87. this.SECRET_KEY = secret_key;
  88. this.CIPHER_KEY = cipher_key;
  89. this.SSL = ssl_on;
  90. if (this.sessionUUID == "")
  91. this.sessionUUID = Guid.NewGuid().ToString();
  92. // SSL is ON?
  93. if (this.SSL)
  94. this.ORIGIN = "https://" + this.ORIGIN;
  95. else
  96. this.ORIGIN = "http://" + this.ORIGIN;
  97. _overrideTcpKeepAlive = Boolean.Parse(ConfigurationManager.AppSettings["OverrideTcpKeepAlive"].ToString());
  98. //Initiate System Events for PowerModeChanged - to monitor suspend/resume
  99. initiatePowerModeCheck();
  100. }
  101. private void reconnectNetwork<T>(ReconnectState<T> netState)
  102. {
  103. System.Threading.Timer timer = new Timer(new TimerCallback(reconnectNetworkCallback<T>), netState, 0, PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000);
  104. _channelReconnectTimer.AddOrUpdate(netState.channel, timer, (key, oldState) => timer);
  105. }
  106. void reconnectNetworkCallback<T>(Object reconnectState)
  107. {
  108. try
  109. {
  110. ReconnectState<T> netState = reconnectState as ReconnectState<T>;
  111. if (netState != null)
  112. {
  113. if (_channelInternetStatus.ContainsKey(netState.channel)
  114. && (netState.type == ResponseType.Subscribe || netState.type == ResponseType.Presence))
  115. {
  116. if (_channelInternetStatus[netState.channel])
  117. {
  118. //Reset Retry if previous state is true
  119. _channelInternetRetry.AddOrUpdate(netState.channel, 0, (key, oldValue) => 0);
  120. }
  121. else
  122. {
  123. _channelInternetRetry.AddOrUpdate(netState.channel, 1, (key, oldValue) => oldValue + 1);
  124. 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));
  125. }
  126. }
  127. if (_channelInternetStatus[netState.channel])
  128. {
  129. if (_channelReconnectTimer.ContainsKey(netState.channel))
  130. {
  131. _channelReconnectTimer[netState.channel].Change(Timeout.Infinite, Timeout.Infinite);
  132. _channelReconnectTimer[netState.channel].Dispose();
  133. }
  134. if (appSwitch.TraceInfo)
  135. {
  136. Trace.WriteLine(string.Format("DateTime {0}, {1} {2} reconnectNetworkCallback. Internet Available : {3}", DateTime.Now.ToString(), netState.channel, netState.type, _channelInternetStatus[netState.channel]));
  137. }
  138. switch (netState.type)
  139. {
  140. case ResponseType.Subscribe:
  141. _subscribe(netState.channel, netState.timetoken, netState.callback, false);
  142. break;
  143. case ResponseType.Presence:
  144. _presence(netState.channel, netState.timetoken, netState.callback, false);
  145. break;
  146. default:
  147. break;
  148. }
  149. }
  150. else if (_channelInternetRetry[netState.channel] >= PUBNUB_NETWORK_CHECK_RETRIES)
  151. {
  152. if (_channelReconnectTimer.ContainsKey(netState.channel))
  153. {
  154. _channelReconnectTimer[netState.channel].Change(Timeout.Infinite, Timeout.Infinite);
  155. _channelReconnectTimer[netState.channel].Dispose();
  156. }
  157. switch (netState.type)
  158. {
  159. case ResponseType.Subscribe:
  160. subscribeExceptionHandler(netState.channel, netState.callback, true);
  161. break;
  162. case ResponseType.Presence:
  163. presenceExceptionHandler(netState.channel, netState.callback, true);
  164. break;
  165. default:
  166. break;
  167. }
  168. }
  169. }
  170. else
  171. {
  172. if (appSwitch.TraceError)
  173. {
  174. Trace.WriteLine(string.Format("DateTime {0}, Unknown request state in reconnectNetworkCallback", DateTime.Now.ToString()));
  175. }
  176. }
  177. }
  178. catch (Exception ex)
  179. {
  180. if (appSwitch.TraceError)
  181. {
  182. Trace.WriteLine(string.Format("DateTime {0} method:reconnectNetworkCallback \n Exception Details={1}", DateTime.Now.ToString(), ex.ToString()));
  183. }
  184. }
  185. }
  186. private void initiatePowerModeCheck()
  187. {
  188. try
  189. {
  190. SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
  191. if (appSwitch.TraceInfo)
  192. {
  193. Trace.WriteLine(string.Format("DateTime {0}, Initiated System Event - PowerModeChanged.", DateTime.Now.ToString()));
  194. }
  195. }
  196. catch(Exception ex)
  197. {
  198. if (appSwitch.TraceError)
  199. {
  200. Trace.WriteLine(string.Format("DateTime {0} No support for System Event - PowerModeChanged.", DateTime.Now.ToString()));
  201. Trace.WriteLine(string.Format("DateTime {0} {1}", DateTime.Now.ToString(),ex.ToString()));
  202. }
  203. }
  204. }
  205. void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
  206. {
  207. if (e.Mode == PowerModes.Suspend)
  208. {
  209. _pubnetSystemActive = false;
  210. TerminatePendingWebRequest();
  211. if (_overrideTcpKeepAlive)
  212. {
  213. heartBeatTimer.Change(Timeout.Infinite, Timeout.Infinite);
  214. }
  215. if (appSwitch.TraceInfo)
  216. {
  217. Trace.WriteLine(string.Format("DateTime {0}, System entered into Suspend Mode.", DateTime.Now.ToString()));
  218. if (_overrideTcpKeepAlive)
  219. {
  220. Trace.WriteLine(string.Format("DateTime {0}, Disabled Timer for heartbeat ", DateTime.Now.ToString()));
  221. }
  222. }
  223. }
  224. else if (e.Mode == PowerModes.Resume)
  225. {
  226. _pubnetSystemActive = true;
  227. if (_overrideTcpKeepAlive)
  228. {
  229. heartBeatTimer.Change(
  230. (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000,
  231. (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000);
  232. }
  233. if (appSwitch.TraceInfo)
  234. {
  235. Trace.WriteLine(string.Format("DateTime {0}, System entered into Resume/Awake Mode.", DateTime.Now.ToString()));
  236. if (_overrideTcpKeepAlive)
  237. {
  238. Trace.WriteLine(string.Format("DateTime {0}, Enabled Timer for heartbeat ", DateTime.Now.ToString()));
  239. }
  240. }
  241. }
  242. }
  243. private void TerminatePendingWebRequest()
  244. {
  245. TerminatePendingWebRequest(null);
  246. }
  247. private void TerminatePendingWebRequest(RequestState state)
  248. {
  249. if (state != null && state.request != null)
  250. {
  251. state.request.Abort();
  252. if (appSwitch.TraceInfo)
  253. {
  254. Trace.WriteLine(string.Format("DateTime {0} TerminatePendingWebRequest {1}", DateTime.Now.ToString(), state.request.RequestUri.ToString()));
  255. }
  256. RequestState removedReq;
  257. bool removeKey = _channelRequest.TryRemove(state.channel, out removedReq);
  258. if (!removeKey && appSwitch.TraceError)
  259. {
  260. Trace.WriteLine(string.Format("DateTime {0} Unable to remove web request from dictionary in TerminatePendingWebRequest for channel= {1}", DateTime.Now.ToString(), state.channel));
  261. }
  262. }
  263. else
  264. {
  265. ConcurrentDictionary<string, RequestState> webReq = _channelRequest;
  266. ICollection<string> keyCol = _channelRequest.Keys;
  267. foreach (string key in keyCol)
  268. {
  269. RequestState currReq = _channelRequest[key];
  270. if (currReq.request != null)
  271. {
  272. currReq.request.Abort();
  273. if (appSwitch.TraceInfo)
  274. {
  275. Trace.WriteLine(string.Format("DateTime {0} TerminatePendingWebRequest {1}", DateTime.Now.ToString(), currReq.request.RequestUri.ToString()));
  276. }
  277. bool removeKey = _channelRequest.TryRemove(key, out currReq);
  278. if (!removeKey && appSwitch.TraceError)
  279. {
  280. Trace.WriteLine(string.Format("DateTime {0} Unable to remove web request from dictionary in TerminatePendingWebRequest for channel= {1}", DateTime.Now.ToString(), key));
  281. }
  282. }
  283. }
  284. }
  285. }
  286. ~PubnubBase()
  287. {
  288. //detach
  289. SystemEvents.PowerModeChanged -= new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);
  290. }
  291. /**
  292. * PubNub 3.0 API
  293. *
  294. * Prepare Pubnub messaging class initial state
  295. *
  296. * @param string pubish_key.
  297. * @param string subscribe_key.
  298. * @param string secret_key.
  299. * @param bool ssl_on
  300. */
  301. public PubnubBase(string publish_key, string subscribe_key, string secret_key, string cipher_key, bool ssl_on)
  302. {
  303. this.init(publish_key, subscribe_key, secret_key, cipher_key, ssl_on);
  304. }
  305. /**
  306. * PubNub 2.0 Compatibility
  307. *
  308. * Prepare Pubnub messaging class initial state
  309. *
  310. * @param string pubish_key.
  311. * @param string subscribe_key.
  312. */
  313. public PubnubBase(string publish_key, string subscribe_key)
  314. {
  315. this.init(publish_key, subscribe_key, "", "", false);
  316. }
  317. /**
  318. * PubNub 3.0 without SSL
  319. *
  320. * Prepare Pubnub messaging class initial state
  321. *
  322. * @param string pubish_key.
  323. * @param string subscribe_key.
  324. * @param string secret_key.
  325. */
  326. public PubnubBase(string publish_key, string subscribe_key, string secret_key)
  327. {
  328. this.init(publish_key, subscribe_key, secret_key, "", false);
  329. }
  330. /**
  331. * History
  332. *
  333. * Load history from a channel
  334. *
  335. * @param String channel name.
  336. * @param int limit history count response
  337. * @return ListArray of history
  338. */
  339. [Obsolete("This method should no longer be used, please use detailedHistory() instead.")]
  340. public bool history(string channel, int limit)
  341. {
  342. List<string> url = new List<string>();
  343. url.Add("history");
  344. url.Add(this.SUBSCRIBE_KEY);
  345. url.Add(channel);
  346. url.Add("0");
  347. url.Add(limit.ToString());
  348. return _request(url, ResponseType.History);
  349. }
  350. /**
  351. * Detailed History
  352. */
  353. public bool detailedHistory(string channel, long start, long end, int count, bool reverse, Action<object> usercallback)
  354. {
  355. return detailedHistory<object>(channel, start, end, count, reverse, usercallback);
  356. }
  357. public bool detailedHistory<T>(string channel, long start, long end, int count, bool reverse, Action<T> usercallback)
  358. {
  359. if (string.IsNullOrWhiteSpace(channel))
  360. {
  361. throw new ArgumentException("Missing Channel");
  362. }
  363. parameters = "";
  364. if (count <= -1) count = 100;
  365. parameters = "?count=" + count;
  366. if (reverse)
  367. parameters = parameters + "&" + "reverse=" + reverse.ToString().ToLower();
  368. if (start != -1)
  369. parameters = parameters + "&" + "start=" + start.ToString().ToLower();
  370. if (end != -1)
  371. parameters = parameters + "&" + "end=" + end.ToString().ToLower();
  372. List<string> url = new List<string>();
  373. url.Add("v2");
  374. url.Add("history");
  375. url.Add("sub-key");
  376. url.Add(this.SUBSCRIBE_KEY);
  377. url.Add("channel");
  378. url.Add(channel);
  379. return _urlRequest<T>(url, ResponseType.DetailedHistory, usercallback, false);
  380. }
  381. public bool detailedHistory(string channel, long start, Action<object> usercallback, bool reverse)
  382. {
  383. return detailedHistory<object>(channel, start, -1, -1, reverse, usercallback);
  384. }
  385. public bool detailedHistory<T>(string channel, long start, Action<T> usercallback, bool reverse)
  386. {
  387. return detailedHistory<T>(channel, start, -1, -1, reverse, usercallback);
  388. }
  389. public bool detailedHistory(string channel, int count, Action<object> usercallback)
  390. {
  391. return detailedHistory<object>(channel, -1, -1, count, false, usercallback);
  392. }
  393. public bool detailedHistory<T>(string channel, int count, Action<T> usercallback)
  394. {
  395. return detailedHistory<T>(channel, -1, -1, count, false, usercallback);
  396. }
  397. /**
  398. * Publish
  399. *
  400. * Send a message to a channel
  401. *
  402. * @param String channel name.
  403. * @param List<object> info.
  404. * @return bool false on fail
  405. */
  406. public bool publish(string channel, object message, Action<object> usercallback)
  407. {
  408. return publish<object>(channel, message, usercallback);
  409. }
  410. public bool publish<T>(string channel, object message, Action<T> usercallback)
  411. {
  412. if (string.IsNullOrWhiteSpace(channel) || message == null)
  413. {
  414. throw new ArgumentException("Missing Channel or Message");
  415. }
  416. if (string.IsNullOrWhiteSpace(this.PUBLISH_KEY) || this.PUBLISH_KEY.Length <= 0)
  417. {
  418. throw new MissingFieldException("Invalid publish key");
  419. }
  420. if (usercallback == null)
  421. {
  422. throw new ArgumentException("Missing Callback");
  423. }
  424. string msg = jsonEncodePublishMsg(message);
  425. // Generate String to Sign
  426. string signature = "0";
  427. if (this.SECRET_KEY.Length > 0)
  428. {
  429. StringBuilder string_to_sign = new StringBuilder();
  430. string_to_sign
  431. .Append(this.PUBLISH_KEY)
  432. .Append('/')
  433. .Append(this.SUBSCRIBE_KEY)
  434. .Append('/')
  435. .Append(this.SECRET_KEY)
  436. .Append('/')
  437. .Append(channel)
  438. .Append('/')
  439. .Append(msg); // 1
  440. // Sign Message
  441. signature = md5(string_to_sign.ToString());
  442. }
  443. // Build URL
  444. List<string> url = new List<string>();
  445. url.Add("publish");
  446. url.Add(this.PUBLISH_KEY);
  447. url.Add(this.SUBSCRIBE_KEY);
  448. url.Add(signature);
  449. url.Add(channel);
  450. url.Add("0");
  451. url.Add(msg);
  452. return _urlRequest<T>(url, ResponseType.Publish, usercallback, false);
  453. }
  454. private string jsonEncodePublishMsg(object originalMsg)
  455. {
  456. string msg = SerializeToJsonString(originalMsg);
  457. if (this.CIPHER_KEY.Length > 0)
  458. {
  459. PubnubCrypto aes = new PubnubCrypto(this.CIPHER_KEY);
  460. string encryptMsg = aes.encrypt(msg);
  461. msg = SerializeToJsonString(encryptMsg);
  462. }
  463. return msg;
  464. }
  465. private List<object> decodeMsg(List<object> message, ResponseType type)
  466. {
  467. List<object> receivedMsg = new List<object>();
  468. if (type == ResponseType.Presence || type == ResponseType.Publish || type == ResponseType.Time || type == ResponseType.Here_Now || type == ResponseType.Leave)
  469. {
  470. return message;
  471. }
  472. else if (type == ResponseType.DetailedHistory)
  473. {
  474. receivedMsg = decodeDecryptLoop(message);
  475. }
  476. else
  477. {
  478. receivedMsg = decodeDecryptLoop(message);
  479. }
  480. return receivedMsg;
  481. }
  482. private List<object> decodeDecryptLoop(List<object> message)
  483. {
  484. List<object> returnMsg = new List<object>();
  485. if (this.CIPHER_KEY.Length > 0)
  486. {
  487. PubnubCrypto aes = new PubnubCrypto(this.CIPHER_KEY);
  488. var myObjectArray = (from item in message select item as object).ToArray();
  489. IEnumerable enumerable = myObjectArray[0] as IEnumerable;
  490. if (enumerable != null)
  491. {
  492. List<object> receivedMsg = new List<object>();
  493. foreach (object element in enumerable)
  494. {
  495. string decryptMsg = aes.decrypt(element.ToString());
  496. object decodeMsg = JsonConvert.DeserializeObject<object>(decryptMsg);
  497. receivedMsg.Add(decodeMsg);
  498. }
  499. returnMsg.Add(receivedMsg);
  500. }
  501. for (int index = 1; index < myObjectArray.Length; index++)
  502. {
  503. returnMsg.Add(myObjectArray[index]);
  504. }
  505. return returnMsg;
  506. }
  507. else
  508. {
  509. var myObjectArray = (from item in message select item as object).ToArray();
  510. IEnumerable enumerable = myObjectArray[0] as IEnumerable;
  511. if (enumerable != null)
  512. {
  513. List<object> receivedMsg = new List<object>();
  514. foreach (object element in enumerable)
  515. {
  516. receivedMsg.Add(element);
  517. }
  518. returnMsg.Add(receivedMsg);
  519. }
  520. for (int index = 1; index < myObjectArray.Length; index++)
  521. {
  522. returnMsg.Add(myObjectArray[index]);
  523. }
  524. return returnMsg;
  525. }
  526. }
  527. /**
  528. * Subscribe
  529. *
  530. * Listen for a message on a channel (BLOCKING)
  531. *
  532. * @param String channel name.
  533. * @param Procedure function callback
  534. */
  535. public void subscribe(string channel, Action<object> usercallback)
  536. {
  537. subscribe<object>(channel, usercallback);
  538. }
  539. public void subscribe<T>(string channel, Action<T> usercallback)
  540. {
  541. if (string.IsNullOrWhiteSpace(channel))
  542. {
  543. throw new ArgumentException("Missing Channel");
  544. }
  545. if (usercallback == null)
  546. {
  547. throw new ArgumentException("Missing Callback");
  548. }
  549. if (appSwitch.TraceInfo)
  550. {
  551. Trace.WriteLine(string.Format("DateTime {0}, requested subscribe for channel={1}", DateTime.Now.ToString(), channel));
  552. }
  553. if (_channelSubscription.ContainsKey(channel))
  554. {
  555. List<object> result = new List<object>();
  556. string jsonString = "[0, \"Already subscribed\"]";
  557. result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
  558. result.Add(channel);
  559. if (appSwitch.TraceInfo)
  560. {
  561. Trace.WriteLine(string.Format("DateTime {0}, JSON subscribe response={1}", DateTime.Now.ToString(), jsonString));
  562. }
  563. goToUserCallback<T>(result, usercallback);
  564. }
  565. else
  566. {
  567. _channelSubscription.GetOrAdd(channel, 0);
  568. resetInternetCheckSettings(channel);
  569. _subscribe<T>(channel, 0, usercallback, false);
  570. }
  571. }
  572. private void resetInternetCheckSettings(string channel)
  573. {
  574. if (_channelInternetStatus.ContainsKey(channel))
  575. {
  576. _channelInternetStatus.AddOrUpdate(channel, true, (key, oldValue) => true);
  577. }
  578. else
  579. {
  580. _channelInternetStatus.GetOrAdd(channel, true); //Set to true for internet connection
  581. }
  582. if (_channelInternetRetry.ContainsKey(channel))
  583. {
  584. _channelInternetRetry.AddOrUpdate(channel, 0, (key, oldValue) => 0);
  585. }
  586. else
  587. {
  588. _channelInternetRetry.GetOrAdd(channel, 0); //Initialize the internet retry count
  589. }
  590. }
  591. void OnPubnubWebRequestTimeout(object state, bool timeout)
  592. {
  593. if (timeout)
  594. {
  595. RequestState currentState = state as RequestState;
  596. if (currentState != null)
  597. {
  598. HttpWebRequest request = currentState.request;
  599. if (request != null)
  600. {
  601. if (appSwitch.TraceInfo)
  602. {
  603. Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubWebRequestTimeout: client request timeout reached.Request aborted for channel = {1}", DateTime.Now.ToString(), currentState.channel));
  604. }
  605. request.Abort();
  606. }
  607. }
  608. else
  609. {
  610. if (appSwitch.TraceError)
  611. {
  612. Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubWebRequestTimeout: client request timeout reached. However state is unknown", DateTime.Now.ToString()));
  613. }
  614. }
  615. if (_overrideTcpKeepAlive)
  616. {
  617. //reset heart beat time because http request already timedout
  618. heartBeatTimer.Change(
  619. (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000,
  620. (-1 == PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC) ? -1 : PUBNUB_NETWORK_TCP_CHECK_INTERVAL_IN_SEC * 1000);
  621. if (appSwitch.TraceInfo)
  622. {
  623. Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubWebRequestTimeout: resetting the heartbeat timeout", DateTime.Now.ToString()));
  624. }
  625. }
  626. }
  627. }
  628. void OnPubnubHeartBeatTimeoutCallback(Object heartbeatState)
  629. {
  630. if (appSwitch.TraceVerbose)
  631. {
  632. Trace.WriteLine(string.Format("DateTime: {0}, **OnPubnubHeartBeatTimeoutCallback**", DateTime.Now.ToString()));
  633. }
  634. RequestState currentState = heartbeatState as RequestState;
  635. if (currentState != null)
  636. {
  637. bool networkConnection = ClientNetworkStatus.checkInternetStatus(_pubnetSystemActive);
  638. if (_channelInternetStatus.ContainsKey(currentState.channel)
  639. && (currentState.type == ResponseType.Subscribe || currentState.type == ResponseType.Presence)
  640. && _overrideTcpKeepAlive)
  641. {
  642. _channelInternetStatus[currentState.channel] = networkConnection;
  643. if (appSwitch.TraceVerbose)
  644. {
  645. Trace.WriteLine(string.Format("DateTime: {0}, OnPubnubHeartBeatTimeoutCallback - Internet connection = {1}", DateTime.Now.ToString(), networkConnection));
  646. }
  647. if (!networkConnection)
  648. {
  649. TerminatePendingWebRequest(currentState);
  650. }
  651. }
  652. }
  653. }
  654. /// <summary>
  655. /// Check the response of the REST API and call for re-subscribe
  656. /// </summary>
  657. /// <typeparam name="T"></typeparam>
  658. /// <param name="subscribeResult"></param>
  659. /// <param name="usercallback"></param>
  660. private void subscribeInternalCallback<T>(object subscribeResult, Action<T> usercallback)
  661. {
  662. List<object> message = subscribeResult as List<object>;
  663. string channelName = "";
  664. if (message != null && message.Count >= 3)
  665. {
  666. channelName = message[2].ToString();
  667. }
  668. else
  669. {
  670. if (appSwitch.TraceError)
  671. {
  672. Trace.WriteLine(string.Format("DateTime {0}, Lost Channel Name for resubscribe", DateTime.Now.ToString()));
  673. }
  674. return;
  675. }
  676. if (!_channelSubscription.ContainsKey(channelName))
  677. {
  678. if (appSwitch.TraceInfo)
  679. {
  680. Trace.WriteLine(string.Format("DateTime {0}, Due to Unsubscribe, further re-subscription was stopped for channel {1}", DateTime.Now.ToString(), channelName.ToString()));
  681. }
  682. return;
  683. }
  684. if (message != null && message.Count >= 3)
  685. {
  686. _subscribe<T>(channelName, (object)message[1], usercallback, false);
  687. }
  688. }
  689. private void presenceInternalCallback<T>(object presenceResult, Action<T> usercallback)
  690. {
  691. List<object> message = presenceResult as List<object>;
  692. string channelName = "";
  693. if (message != null && message.Count >= 3)
  694. {
  695. channelName = message[2].ToString();
  696. }
  697. else
  698. {
  699. if (appSwitch.TraceError)
  700. {
  701. Trace.WriteLine(string.Format("DateTime {0}, Lost Channel Name for re-presence", DateTime.Now.ToString()));
  702. }
  703. return;
  704. }
  705. if (message != null && message.Count >= 3)
  706. {
  707. _presence<T>(channelName, (object)message[1], usercallback, false);
  708. }
  709. }
  710. /// <summary>
  711. /// To unsubscribe a channel
  712. /// </summary>
  713. /// <param name="channel"></param>
  714. /// <param name="usercallback"></param>
  715. public void unsubscribe(string channel, Action<object> usercallback)
  716. {
  717. unsubscribe<object>(channel, usercallback);
  718. }
  719. /// <summary>
  720. /// To unsubscribe a channel
  721. /// </summary>
  722. /// <typeparam name="T"></typeparam>
  723. /// <param name="channel"></param>
  724. /// <param name="usercallback"></param>
  725. public void unsubscribe<T>(string channel, Action<T> usercallback)
  726. {
  727. if (string.IsNullOrWhiteSpace(channel))
  728. {
  729. throw new ArgumentException("Missing Channel");
  730. }
  731. bool unsubStatus = false;
  732. if (appSwitch.TraceInfo)
  733. {
  734. Trace.WriteLine(string.Format("DateTime {0}, requested unsubscribe for channel={1}", DateTime.Now.ToString(), channel));
  735. }
  736. string jsonString = "";
  737. List<object> result = new List<object>();
  738. if (_channelSubscription.ContainsKey(channel))
  739. {
  740. if (_channelRequest.ContainsKey(channel))
  741. {
  742. long unsubValue;
  743. unsubStatus = _channelSubscription.TryRemove(channel, out unsubValue);
  744. if (unsubStatus)
  745. {
  746. jsonString = string.Format("[1, \"Unsubscribed from {0}\"]", channel);
  747. }
  748. else
  749. {
  750. jsonString = string.Format("[1, \"Error unsubscribing from {0}\"]", channel);
  751. }
  752. HttpWebRequest storedRequest = _channelRequest[channel].request;
  753. storedRequest.Abort();
  754. }
  755. result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
  756. result.Add(channel);
  757. if (appSwitch.TraceInfo)
  758. {
  759. Trace.WriteLine(string.Format("DateTime {0}, JSON unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
  760. }
  761. goToUserCallback<T>(result, usercallback);
  762. //just fire leave() event to REST API for safeguard
  763. List<string> url = new List<string>();
  764. url.Add("v2");
  765. url.Add("presence");
  766. url.Add("sub_key");
  767. url.Add(this.SUBSCRIBE_KEY);
  768. url.Add("channel");
  769. url.Add(channel);
  770. url.Add("leave");
  771. _urlRequest<T>(url, ResponseType.Leave, null, false);
  772. }
  773. else
  774. {
  775. result = new List<object>();
  776. jsonString = "[0, \"Channel Not Subscribed\"]";
  777. result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
  778. result.Add(channel);
  779. if (appSwitch.TraceInfo)
  780. {
  781. Trace.WriteLine(string.Format("DateTime {0}, JSON unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
  782. }
  783. goToUserCallback<T>(result, usercallback);
  784. }
  785. }
  786. /**
  787. * Subscribe - Private Interface
  788. *
  789. * @param String channel name.
  790. * @param Procedure function callback
  791. * @param String timetoken.
  792. */
  793. private void _subscribe<T>(string channel, object timetoken, Action<T> usercallback, bool reconnect)
  794. {
  795. //Exit if the channel is unsubscribed
  796. if (!_channelSubscription.ContainsKey(channel))
  797. {
  798. if (appSwitch.TraceInfo)
  799. {
  800. Trace.WriteLine(string.Format("DateTime {0}, Due to Unsubscribe, further subscription was stopped for channel {1}", DateTime.Now.ToString(), channel.ToString()));
  801. }
  802. return;
  803. }
  804. _channelSubscription.AddOrUpdate(channel, Convert.ToInt64(timetoken.ToString()), (key, oldValue) => Convert.ToInt64(timetoken.ToString())); //Store the timetoken
  805. if (_channelInternetStatus.ContainsKey(channel) && (!_channelInternetStatus[channel]) && _pubnetSystemActive)
  806. {
  807. if (_channelInternetRetry.ContainsKey(channel) && (_channelInternetRetry[channel] >= PUBNUB_NETWORK_CHECK_RETRIES))
  808. {
  809. if (appSwitch.TraceInfo)
  810. {
  811. Trace.WriteLine(string.Format("DateTime {0}, Subscribe channel={1} - No internet connection. MAXed retries for internet ", DateTime.Now.ToString(), channel));
  812. }
  813. subscribeExceptionHandler<T>(channel, usercallback, true);
  814. return;
  815. }
  816. if (_overrideTcpKeepAlive)
  817. {
  818. if (appSwitch.TraceInfo)
  819. {
  820. Trace.WriteLine(string.Format("DateTime {0}, Subscribe - No internet connection for {1}", DateTime.Now.ToString(), channel));
  821. }
  822. ReconnectState<T> netState = new ReconnectState<T>();
  823. netState.channel = channel;
  824. netState.type = ResponseType.Subscribe;
  825. netState.callback = usercallback;
  826. netState.timetoken = timetoken;
  827. reconnectNetwork<T>(netState);
  828. return;
  829. }
  830. }
  831. // Begin recursive subscribe
  832. try
  833. {
  834. // Build URL
  835. List<string> url = new List<string>();
  836. url.Add("subscribe");
  837. url.Add(this.SUBSCRIBE_KEY);
  838. url.Add(channel);
  839. url.Add("0");
  840. url.Add(timetoken.ToString());
  841. // Wait for message
  842. _urlRequest<T>(url, ResponseType.Subscribe, usercallback, reconnect);
  843. }
  844. catch (Exception ex)
  845. {
  846. if (appSwitch.TraceError)
  847. {
  848. 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()));
  849. }
  850. this._subscribe<T>(channel, timetoken, usercallback, false);
  851. }
  852. }
  853. /**
  854. * Presence feature
  855. *
  856. * Listen for a presence message on a channel (BLOCKING)
  857. *
  858. * @param String channel name. (+"pnpres")
  859. * @param Procedure function callback
  860. */
  861. public void presence(string channel, Action<object> usercallback)
  862. {
  863. presence<object>(channel, usercallback);
  864. }
  865. public void presence<T>(string channel, Action<T> usercallback)
  866. {
  867. if (string.IsNullOrWhiteSpace(channel))
  868. {
  869. throw new ArgumentException("Missing Channel");
  870. }
  871. if (usercallback == null)
  872. {
  873. throw new ArgumentException("Missing Callback");
  874. }
  875. channel = string.Format("{0}-pnpres", channel);
  876. if (appSwitch.TraceInfo)
  877. {
  878. Trace.WriteLine(string.Format("DateTime {0}, requested presence for channel={1}", DateTime.Now.ToString(), channel));
  879. }
  880. if (_channelPresence.ContainsKey(channel))
  881. {
  882. List<object> result = new List<object>();
  883. string jsonString = "[0, \"Presence Already subscribed\"]";
  884. result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
  885. result.Add(channel.Replace("-pnpres", ""));
  886. if (appSwitch.TraceInfo)
  887. {
  888. Trace.WriteLine(string.Format("DateTime {0}, JSON presence response={1}", DateTime.Now.ToString(), jsonString));
  889. }
  890. goToUserCallback<T>(result, usercallback);
  891. }
  892. else
  893. {
  894. _channelPresence.GetOrAdd(channel, 0);
  895. resetInternetCheckSettings(channel);
  896. this._presence<T>(channel, 0, usercallback, false);
  897. }
  898. }
  899. /**
  900. * Presence feature - Private Interface
  901. *
  902. * @param String channel name.
  903. * @param Procedure function callback
  904. * @param String timetoken.
  905. */
  906. private void _presence<T>(string channel, object timetoken, Action<T> usercallback, bool reconnect)
  907. {
  908. //Exit if the channel is unsubscribed
  909. if (!_channelPresence.ContainsKey(channel))
  910. {
  911. if (appSwitch.TraceInfo)
  912. {
  913. Trace.WriteLine(string.Format("DateTime {0}, Due to Presence-unsubscribe, further presence was stopped for channel {1}", DateTime.Now.ToString(), channel.ToString()));
  914. }
  915. return;
  916. }
  917. _channelPresence.AddOrUpdate(channel, Convert.ToInt64(timetoken.ToString()), (key, oldValue) => Convert.ToInt64(timetoken.ToString())); //Store the timetoken
  918. if (_channelInternetStatus.ContainsKey(channel) && (!_channelInternetStatus[channel]) && _pubnetSystemActive)
  919. {
  920. if (_channelInternetRetry.ContainsKey(channel) && (_channelInternetRetry[channel] >= PUBNUB_NETWORK_CHECK_RETRIES))
  921. {
  922. if (appSwitch.TraceInfo)
  923. {
  924. Trace.WriteLine(string.Format("DateTime {0}, Presence channel={1} - No internet connection. MAXed retries for internet ", DateTime.Now.ToString(), channel));
  925. }
  926. presenceExceptionHandler<T>(channel, usercallback, true);
  927. return;
  928. }
  929. if (_overrideTcpKeepAlive)
  930. {
  931. if (appSwitch.TraceInfo)
  932. {
  933. Trace.WriteLine(string.Format("DateTime {0}, Presence - No internet connection for {1}", DateTime.Now.ToString(), channel));
  934. }
  935. ReconnectState<T> netState = new ReconnectState<T>();
  936. netState.channel = channel;
  937. netState.type = ResponseType.Presence;
  938. netState.callback = usercallback;
  939. netState.timetoken = timetoken;
  940. reconnectNetwork<T>(netState);
  941. return;
  942. }
  943. }
  944. // Begin recursive subscribe
  945. try
  946. {
  947. // Build URL
  948. List<string> url = new List<string>();
  949. url.Add("subscribe");
  950. url.Add(this.SUBSCRIBE_KEY);
  951. url.Add(channel);
  952. url.Add("0");
  953. url.Add(timetoken.ToString());
  954. // Wait for message
  955. _urlRequest<T>(url, ResponseType.Presence, usercallback, reconnect);
  956. }
  957. catch (Exception ex)
  958. {
  959. if (appSwitch.TraceError)
  960. {
  961. Trace.WriteLine(string.Format("method:_presence \n channel={0} \n timetoken={1} \n Exception Details={2}", channel, timetoken.ToString(), ex.ToString()));
  962. }
  963. this._presence<T>(channel, timetoken, usercallback, false);
  964. }
  965. }
  966. public void presence_unsubscribe(string channel, Action<object> usercallback)
  967. {
  968. presence_unsubscribe<object>(channel, usercallback);
  969. }
  970. public void presence_unsubscribe<T>(string channel, Action<T> usercallback)
  971. {
  972. if (string.IsNullOrWhiteSpace(channel))
  973. {
  974. throw new ArgumentException("Missing Channel");
  975. }
  976. channel = string.Format("{0}-pnpres", channel);
  977. bool unsubStatus = false;
  978. if (appSwitch.TraceInfo)
  979. {
  980. Trace.WriteLine(string.Format("DateTime {0}, requested presence-unsubscribe for channel={1}", DateTime.Now.ToString(), channel));
  981. }
  982. string jsonString = "";
  983. List<object> result = new List<object>();
  984. if (_channelPresence.ContainsKey(channel))
  985. {
  986. if (_channelRequest.ContainsKey(channel))
  987. {
  988. long unsubPreValue;
  989. unsubStatus = _channelPresence.TryRemove(channel, out unsubPreValue);
  990. if (unsubStatus)
  991. {
  992. jsonString = string.Format("[1, \"Presence-Unsubscribed from {0}\"]", channel.Replace("-pnpres", ""));
  993. }
  994. else
  995. {
  996. jsonString = string.Format("[1, \"Error presence-unsubscribing from {0}\"]", channel.Replace("-pnpres", ""));
  997. }
  998. HttpWebRequest storedRequest = _channelRequest[channel].request;
  999. storedRequest.Abort();
  1000. }
  1001. result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
  1002. result.Add(channel.Replace("-pnpres", ""));
  1003. if (appSwitch.TraceInfo)
  1004. {
  1005. Trace.WriteLine(string.Format("DateTime {0}, JSON presence-unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
  1006. }
  1007. goToUserCallback<T>(result, usercallback);
  1008. }
  1009. else
  1010. {
  1011. result = new List<object>();
  1012. jsonString = "[0, \"Channel Not Subscribed\"]";
  1013. result = (List<object>)JsonConvert.DeserializeObject<List<object>>(jsonString);
  1014. result.Add(channel.Replace("-pnpres", ""));
  1015. if (appSwitch.TraceInfo)
  1016. {
  1017. Trace.WriteLine(string.Format("DateTime {0}, JSON presence-unsubscribe response={1}", DateTime.Now.ToString(), jsonString));
  1018. }
  1019. goToUserCallback<T>(result, usercallback);
  1020. }
  1021. }
  1022. public bool here_now(string channel, Action<object> usercallback)
  1023. {
  1024. return here_now<object>(channel, usercallback);
  1025. }
  1026. public bool here_now<T>(string channel, Action<T> usercallback)
  1027. {
  1028. if (string.IsNullOrWhiteSpace(channel))
  1029. {
  1030. throw new ArgumentException("Missing Channel");
  1031. }
  1032. List<string> url = new List<string>();
  1033. url.Add("v2");
  1034. url.Add("presence");
  1035. url.Add("sub_key");
  1036. url.Add(this.SUBSCRIBE_KEY);
  1037. url.Add("channel");
  1038. url.Add(channel);
  1039. return _urlRequest<T>(url, ResponseType.Here_Now, usercallback, false);
  1040. }
  1041. /**
  1042. * Time
  1043. *
  1044. * Timestamp from PubNub Cloud
  1045. *
  1046. * @return object timestamp.
  1047. */
  1048. public bool time(Action<object> usercallback)
  1049. {
  1050. return time<object>(usercallback);
  1051. }
  1052. public bool time<T>(Action<T> usercallback)
  1053. {
  1054. List<string> url = new List<string>();
  1055. url.Add("time");
  1056. url.Add("0");
  1057. return _urlRequest<T>(url, ResponseType.Time, usercallback, false);
  1058. }
  1059. /**
  1060. * Http Get Request
  1061. *
  1062. * @param List<string> request of URL directories.
  1063. * @return List<object> from JSON response.
  1064. */
  1065. private bool _request(List<string> url_components, ResponseType type)
  1066. {
  1067. List<object> result = new List<object>();
  1068. StringBuilder url = new StringBuilder();
  1069. // Add Origin To The Request
  1070. url.Append(this.ORIGIN);
  1071. // Generate URL with UTF-8 Encoding
  1072. foreach (string url_bit in url_components)
  1073. {
  1074. url.Append("/");
  1075. url.Append(_encodeURIcomponent(url_bit, type));
  1076. }
  1077. if (type == ResponseType.Presence || type == ResponseType.Subscribe)
  1078. {
  1079. url.Append("?uuid=");
  1080. url.Append(this.sessionUUID);
  1081. }
  1082. if (type == ResponseType.DetailedHistory)
  1083. url.Append(parameters);
  1084. // Temporary fail if string too long
  1085. if (url.Length > this.LIMIT)
  1086. {
  1087. result.Add(0);
  1088. result.Add("Message Too Long.");
  1089. // return result;
  1090. }
  1091. Uri requestUri = new Uri(url.ToString());
  1092. // Force canonical path and query
  1093. string paq = requestUri.PathAndQuery;
  1094. FieldInfo flagsFieldInfo = typeof(Uri).GetField("m_Flags", BindingFlags.Instance | BindingFlags.NonPublic);
  1095. ulong flags = (ulong)flagsFieldInfo.GetValue(requestUri);
  1096. flags &= ~((ulong)0x30); // Flags.PathNotCanonical|Flags.QueryNotCanonical
  1097. flagsFieldInfo.SetValue(requestUri, flags);
  1098. // Create Request
  1099. HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
  1100. try
  1101. {
  1102. // Make request with the following inline Asynchronous callback
  1103. IAsyncResult asyncResult = request.BeginGetResponse(new AsyncCallback((asynchronousResult) =>
  1104. {
  1105. HttpWebRequest aRequest = (HttpWebRequest)asynchronousResult.AsyncState;
  1106. HttpWebResponse aResponse = (HttpWebResponse)aRequest.EndGetResponse(asynchronousResult);
  1107. using (StreamReader streamReader = new StreamReader(aResponse.GetResponseStream()))
  1108. {
  1109. // Deserialize the result
  1110. string jsonString = streamReader.ReadToEnd();
  1111. result = WrapResultBasedOnResponseType(type, jsonString, url_components, false);
  1112. }
  1113. }), request
  1114. );
  1115. return true;
  1116. }
  1117. catch (System.Exception ex)
  1118. {
  1119. Console.WriteLine(ex.ToString());

Large files files are truncated, but you can click here to view the full file