PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/PushSharp.Android/C2dm/C2dmMessageTransportAsync.cs

https://github.com/mustafagenc/PushSharp
C# | 290 lines | 242 code | 39 blank | 9 comment | 26 complexity | 33e61714364bd6c60c80449b25171d52 MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.IO;
  7. using System.Security.Cryptography.X509Certificates;
  8. using System.Security;
  9. using System.Net.Security;
  10. namespace PushSharp.Android
  11. {
  12. internal class C2dmMessageTransportAsync
  13. {
  14. public event Action<string> UpdateGoogleClientAuthToken;
  15. public event Action<C2dmMessageTransportResponse> MessageResponseReceived;
  16. public event Action<C2dmNotification, Exception> UnhandledException;
  17. static C2dmMessageTransportAsync()
  18. {
  19. ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, policyErrs) => { return true; };
  20. }
  21. private const string C2DM_SEND_URL = "https://android.apis.google.com/c2dm/send";
  22. public void Send(C2dmNotification msg, string googleLoginAuthorizationToken, string senderID, string applicationID)
  23. {
  24. try
  25. {
  26. send(msg, googleLoginAuthorizationToken, senderID, applicationID);
  27. }
  28. catch (Exception ex)
  29. {
  30. if (UnhandledException != null)
  31. UnhandledException(msg, ex);
  32. else
  33. throw ex;
  34. }
  35. }
  36. void send(C2dmNotification msg, string googleLoginAuthorizationToken, string senderID, string applicationID)
  37. {
  38. C2dmMessageTransportResponse result = new C2dmMessageTransportResponse();
  39. result.Message = msg;
  40. var postData = msg.GetPostData();
  41. var webReq = (HttpWebRequest)WebRequest.Create(C2DM_SEND_URL);
  42. //webReq.ContentLength = postData.Length;
  43. webReq.Method = "POST";
  44. webReq.ContentType = "application/x-www-form-urlencoded";
  45. webReq.UserAgent = "PushSharp (version: 1.0)";
  46. webReq.Headers.Add("Authorization: GoogleLogin auth=" + googleLoginAuthorizationToken);
  47. webReq.BeginGetRequestStream(new AsyncCallback(requestStreamCallback), new C2dmAsyncParameters()
  48. {
  49. WebRequest = webReq,
  50. WebResponse = null,
  51. Message = msg,
  52. GoogleAuthToken = googleLoginAuthorizationToken,
  53. SenderId = senderID,
  54. ApplicationId = applicationID
  55. });
  56. }
  57. void requestStreamCallback(IAsyncResult result)
  58. {
  59. var msg = new C2dmNotification();
  60. try
  61. {
  62. var asyncParam = result.AsyncState as C2dmAsyncParameters;
  63. msg = asyncParam.Message;
  64. if (asyncParam != null)
  65. {
  66. var wrStream = asyncParam.WebRequest.EndGetRequestStream(result);
  67. using (var webReqStream = new StreamWriter(wrStream))
  68. {
  69. var data = asyncParam.Message.GetPostData();
  70. webReqStream.Write(data);
  71. webReqStream.Close();
  72. }
  73. try
  74. {
  75. asyncParam.WebRequest.BeginGetResponse(new AsyncCallback(responseCallback), asyncParam);
  76. }
  77. catch (WebException wex)
  78. {
  79. asyncParam.WebResponse = wex.Response as HttpWebResponse;
  80. processResponseError(asyncParam);
  81. }
  82. }
  83. }
  84. catch (Exception ex)
  85. {
  86. if (UnhandledException != null)
  87. UnhandledException(msg, ex);
  88. else
  89. throw ex;
  90. }
  91. }
  92. void responseCallback(IAsyncResult result)
  93. {
  94. var msg = new C2dmNotification();
  95. try
  96. {
  97. var asyncParam = result.AsyncState as C2dmAsyncParameters;
  98. msg = asyncParam.Message;
  99. try
  100. {
  101. asyncParam.WebResponse = asyncParam.WebRequest.EndGetResponse(result) as HttpWebResponse;
  102. processResponseOk(asyncParam);
  103. }
  104. catch (WebException wex)
  105. {
  106. asyncParam.WebResponse = wex.Response as HttpWebResponse;
  107. processResponseError(asyncParam);
  108. }
  109. }
  110. catch (Exception ex)
  111. {
  112. if (UnhandledException != null)
  113. UnhandledException(msg, ex);
  114. else
  115. throw ex;
  116. }
  117. }
  118. void processResponseOk(C2dmAsyncParameters asyncParam)
  119. {
  120. var result = new C2dmMessageTransportResponse()
  121. {
  122. ResponseCode = MessageTransportResponseCode.Ok,
  123. ResponseStatus = MessageTransportResponseStatus.Ok,
  124. Message = asyncParam.Message,
  125. MessageId = string.Empty
  126. };
  127. var updateClientAuth = asyncParam.WebResponse.GetResponseHeader("Update-Client-Auth");
  128. if (!string.IsNullOrEmpty(updateClientAuth) && UpdateGoogleClientAuthToken != null)
  129. UpdateGoogleClientAuthToken(updateClientAuth);
  130. //Get the response body
  131. var responseBody = "Error=";
  132. try { responseBody = (new StreamReader(asyncParam.WebResponse.GetResponseStream())).ReadToEnd(); }
  133. catch { }
  134. //Handle the type of error
  135. if (responseBody.StartsWith("Error="))
  136. {
  137. var wrErr = responseBody.Substring(responseBody.IndexOf("Error=") + 6);
  138. switch (wrErr.ToLower().Trim())
  139. {
  140. case "quotaexceeded":
  141. result.ResponseStatus = MessageTransportResponseStatus.QuotaExceeded;
  142. break;
  143. case "devicequotaexceeded":
  144. result.ResponseStatus = MessageTransportResponseStatus.DeviceQuotaExceeded;
  145. break;
  146. case "invalidregistration":
  147. result.ResponseStatus = MessageTransportResponseStatus.InvalidRegistration;
  148. break;
  149. case "notregistered":
  150. result.ResponseStatus = MessageTransportResponseStatus.NotRegistered;
  151. break;
  152. case "messagetoobig":
  153. result.ResponseStatus = MessageTransportResponseStatus.MessageTooBig;
  154. break;
  155. case "missingcollapsekey":
  156. result.ResponseStatus = MessageTransportResponseStatus.MissingCollapseKey;
  157. break;
  158. default:
  159. result.ResponseStatus = MessageTransportResponseStatus.Error;
  160. break;
  161. }
  162. result.ResponseCode = MessageTransportResponseCode.Error;
  163. //throw new MessageTransportException(wrErr, result);
  164. }
  165. else
  166. {
  167. //Get the message ID
  168. if (responseBody.StartsWith("id="))
  169. result.MessageId = responseBody.Substring(3).Trim();
  170. }
  171. asyncParam.WebResponse.Close();
  172. if (MessageResponseReceived != null)
  173. MessageResponseReceived(result);
  174. }
  175. void processResponseError(C2dmAsyncParameters asyncParam)
  176. {
  177. var result = new C2dmMessageTransportResponse()
  178. {
  179. ResponseCode = MessageTransportResponseCode.Error,
  180. ResponseStatus = MessageTransportResponseStatus.Error,
  181. Message = asyncParam.Message,
  182. MessageId = string.Empty
  183. };
  184. if (asyncParam.WebResponse.StatusCode == HttpStatusCode.Unauthorized)
  185. {
  186. //401 bad auth token
  187. result.ResponseCode = MessageTransportResponseCode.InvalidAuthToken;
  188. result.ResponseStatus = MessageTransportResponseStatus.Error;
  189. //throw new InvalidAuthenticationTokenTransportException(result);
  190. }
  191. else if (asyncParam.WebResponse.StatusCode == HttpStatusCode.ServiceUnavailable)
  192. {
  193. //First try grabbing the retry-after header and parsing it.
  194. TimeSpan retryAfter = new TimeSpan(0, 0, 120);
  195. var wrRetryAfter = asyncParam.WebResponse.GetResponseHeader("Retry-After");
  196. if (!string.IsNullOrEmpty(wrRetryAfter))
  197. {
  198. DateTime wrRetryAfterDate = DateTime.UtcNow;
  199. if (DateTime.TryParse(wrRetryAfter, out wrRetryAfterDate))
  200. retryAfter = wrRetryAfterDate - DateTime.UtcNow;
  201. else
  202. {
  203. int wrRetryAfterSeconds = 120;
  204. if (int.TryParse(wrRetryAfter, out wrRetryAfterSeconds))
  205. retryAfter = new TimeSpan(0, 0, wrRetryAfterSeconds);
  206. }
  207. }
  208. //503 exponential backoff, get retry-after header
  209. result.ResponseCode = MessageTransportResponseCode.ServiceUnavailable;
  210. result.ResponseStatus = MessageTransportResponseStatus.Error;
  211. throw new ServiceUnavailableTransportException(retryAfter, result);
  212. }
  213. asyncParam.WebResponse.Close();
  214. if (MessageResponseReceived != null)
  215. MessageResponseReceived(result);
  216. }
  217. class C2dmAsyncParameters
  218. {
  219. public C2dmNotification Message
  220. {
  221. get;
  222. set;
  223. }
  224. public HttpWebRequest WebRequest
  225. {
  226. get;
  227. set;
  228. }
  229. public HttpWebResponse WebResponse
  230. {
  231. get;
  232. set;
  233. }
  234. public string GoogleAuthToken
  235. {
  236. get;
  237. set;
  238. }
  239. public string SenderId
  240. {
  241. get;
  242. set;
  243. }
  244. public string ApplicationId
  245. {
  246. get;
  247. set;
  248. }
  249. }
  250. }
  251. }