-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathAdmConnection.cs
More file actions
151 lines (119 loc) · 5.77 KB
/
AdmConnection.cs
File metadata and controls
151 lines (119 loc) · 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using PushSharp.Common;
namespace PushSharp.Amazon
{
public class AdmServiceConnectionFactory : IServiceConnectionFactory<AdmNotification>
{
public AdmServiceConnectionFactory (AdmConfiguration configuration)
{
Configuration = configuration;
}
public AdmConfiguration Configuration { get; private set; }
public IServiceConnection<AdmNotification> Create()
{
return new AdmServiceConnection (Configuration);
}
}
public class AdmServiceBroker : ServiceBroker<AdmNotification>
{
public AdmServiceBroker (AdmConfiguration configuration) : base (new AdmServiceConnectionFactory (configuration))
{
}
}
public class AdmServiceConnection : IServiceConnection<AdmNotification>
{
public AdmServiceConnection (AdmConfiguration configuration)
{
Configuration = configuration;
Expires = DateTime.UtcNow.AddYears(-1);
http.DefaultRequestHeaders.Add ("X-Amzn-Type-Version", "com.amazon.device.messaging.ADMMessage@1.0");
http.DefaultRequestHeaders.Add ("X-Amzn-Accept-Type", "com.amazon.device.messaging.ADMSendResult@1.0");
http.DefaultRequestHeaders.Add ("Accept", "application/json");
http.DefaultRequestHeaders.ConnectionClose = true;
http.DefaultRequestHeaders.Remove("connection");
}
public AdmConfiguration Configuration { get; private set; }
public DateTime Expires { get; set; }
public DateTime LastRequest { get; private set; }
public string LastAmazonRequestId { get; private set; }
public string AccessToken { get; private set; }
readonly HttpClient http = new HttpClient ();
public async Task Send (AdmNotification notification)
{
try
{
if (string.IsNullOrEmpty(AccessToken) || Expires <= DateTime.UtcNow) {
await UpdateAccessToken ();
http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + AccessToken);
//http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
}
var sc = new StringContent(notification.ToJson ());
sc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await http.PostAsync (string.Format(Configuration.AdmSendUrl, notification.RegistrationId), sc);
// We're done here if it was a success
if (response.IsSuccessStatusCode) {
return;
}
var data = await response.Content.ReadAsStringAsync();
var json = JObject.Parse (data);
var reason = json ["reason"].ToString ();
var regId = notification.RegistrationId;
if (json["registrationID"] != null)
regId = json["registrationID"].ToString();
switch (response.StatusCode)
{
case HttpStatusCode.BadGateway: //400
case HttpStatusCode.BadRequest: //
if ("InvalidRegistrationId".Equals (reason, StringComparison.InvariantCultureIgnoreCase)) {
throw new DeviceSubscriptionExpiredException (notification) {
OldSubscriptionId = regId,
ExpiredAt = DateTime.UtcNow
};
}
throw new NotificationException ("Notification Failed: " + reason, notification);
case HttpStatusCode.Unauthorized: //401
//Access token expired
AccessToken = null;
throw new UnauthorizedAccessException ("Access token failed authorization");
case HttpStatusCode.Forbidden: //403
throw new AdmRateLimitExceededException (reason, notification);
case HttpStatusCode.RequestEntityTooLarge: //413
throw new AdmMessageTooLargeException (notification);
default:
throw new NotificationException ("Unknown ADM Failure", notification);
}
}
catch (Exception ex)
{
throw new NotificationException ("Unknown ADM Failure", notification, ex);
}
}
async Task UpdateAccessToken()
{
var http = new HttpClient ();
var param = new Dictionary<string, string> ();
param.Add ("grant_type", "client_credentials");
param.Add ("scope", "messaging:push");
param.Add ("client_id", Configuration.ClientId);
param.Add ("client_secret", Configuration.ClientSecret);
var result = await http.PostAsync (Configuration.AdmAuthUrl, new FormUrlEncodedContent (param));
var data = await result.Content.ReadAsStringAsync();
var json = JObject.Parse (data);
AccessToken = json ["access_token"].ToString ();
JToken expiresJson = new JValue(3540);
if (json.TryGetValue("expires_in", out expiresJson))
Expires = DateTime.UtcNow.AddSeconds(expiresJson.ToObject<int>() - 60);
else
Expires = DateTime.UtcNow.AddSeconds(3540);
if (result.Headers.Contains ("X-Amzn-RequestId"))
this.LastAmazonRequestId = string.Join("; ", result.Headers.GetValues("X-Amzn-RequestId"));
LastRequest = DateTime.UtcNow;
}
}
}