forked from PeterWaher/IoTGateway
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCoapMessage.cs
More file actions
332 lines (298 loc) · 7.28 KB
/
CoapMessage.cs
File metadata and controls
332 lines (298 loc) · 7.28 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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Waher.Networking.CoAP.Options;
namespace Waher.Networking.CoAP
{
/// <summary>
/// Contains information about a CoAP message.
/// </summary>
public class CoapMessage
{
private Dictionary<string, string> uriQuery = null;
private Dictionary<string, string> locationQuery = null;
private CoapOption[] options;
private CoapMessageType type;
private CoapCode code;
private IPEndPoint from;
private Uri baseUri = null;
private byte[] payload;
private ushort messageId;
private ulong token;
private string host = null;
private string path = null;
private string subPath = null;
private string locationPath = null;
private ushort? contentFormat = null;
private ulong? accept = null;
private ushort? port = null;
private uint maxAge = 60;
private uint? size1 = null;
private uint? size2 = null;
private CoapOptionBlock1 block1 = null;
private CoapOptionBlock2 block2 = null;
private uint? observe = null;
internal CoapMessage(CoapMessageType Type, CoapCode Code, ushort MessageId, ulong Token, CoapOption[] Options, byte[] Payload,
IPEndPoint From)
{
this.type = Type;
this.code = Code;
this.messageId = MessageId;
this.token = Token;
this.options = Options;
this.payload = Payload;
this.from = From;
}
/// <summary>
/// Type of message.
/// </summary>
public CoapMessageType Type
{
get { return this.type; }
}
/// <summary>
/// Message code.
/// </summary>
public CoapCode Code
{
get { return this.code; }
}
/// <summary>
/// Message ID.
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
}
/// <summary>
/// Token
/// </summary>
public ulong Token
{
get { return this.token; }
}
/// <summary>
/// Available options.
/// </summary>
public CoapOption[] Options
{
get { return this.options; }
}
/// <summary>
/// Payload, if available, or null otherwise.
/// </summary>
public byte[] Payload
{
get { return this.payload; }
internal set { this.payload = value; }
}
/// <summary>
/// Base URI, if available, or null otherwise.
/// </summary>
public Uri BaseUri
{
get { return this.baseUri; }
internal set { this.baseUri = value; }
}
/// <summary>
/// From where the message came.
/// </summary>
public IPEndPoint From
{
get { return this.from; }
}
/// <summary>
/// Optional accept option.
/// </summary>
public ulong? Accept
{
get { return this.accept; }
internal set { this.accept = value; }
}
/// <summary>
/// Optional content format option.
/// </summary>
public ushort? ContentFormat
{
get { return this.contentFormat; }
internal set { this.contentFormat = value; }
}
/// <summary>
/// Optional URI query parameters.
/// </summary>
public Dictionary<string, string> UriQuery
{
get { return this.uriQuery; }
internal set { this.uriQuery = value; }
}
/// <summary>
/// Tries to get a URI query parameter value.
/// </summary>
/// <param name="Name">Parameter name.</param>
/// <param name="Value">Parameter value.</param>
/// <returns>If a parameter with the gíven name was found.</returns>
public bool TryGetUriQueryParameter(string Name, out string Value)
{
if (this.uriQuery is null)
{
Value = null;
return false;
}
else
return this.uriQuery.TryGetValue(Name, out Value);
}
/// <summary>
/// Optional URI Port number option.
/// </summary>
public ushort? Port
{
get { return this.port; }
internal set { this.port = value; }
}
/// <summary>
/// Optional URI Host option.
/// </summary>
public string Host
{
get { return this.host; }
internal set { this.host = value; }
}
/// <summary>
/// Optional URI Path options, appended into a path string.
/// </summary>
public string Path
{
get { return this.path; }
set { this.path = value; }
}
/// <summary>
/// Part of the <see cref="Path"/> not matched by the corresponding resource
/// processing the message, in case the resource supports subpaths.
/// </summary>
public string SubPath
{
get { return this.subPath; }
set { this.subPath = value; }
}
/// <summary>
/// Max Age option (number of seconds).
/// </summary>
public uint MaxAge
{
get { return this.maxAge; }
internal set { this.maxAge = value; }
}
/// <summary>
/// Optional Location Path options, appended into a path string.
/// </summary>
public string LocationPath
{
get { return this.locationPath; }
internal set { this.locationPath = value; }
}
/// <summary>
/// Optional Location Query parameters.
/// </summary>
public Dictionary<string, string> LocationQuery
{
get { return this.locationQuery; }
internal set { this.locationQuery = value; }
}
/// <summary>
/// Tries to get a Location query parameter value.
/// </summary>
/// <param name="Name">Parameter name.</param>
/// <param name="Value">Parameter value.</param>
/// <returns>If a location parameter was found with the given name.</returns>
public bool TryGetLocationQueryParameter(string Name, out string Value)
{
if (this.locationQuery is null)
{
Value = null;
return false;
}
else
return this.locationQuery.TryGetValue(Name, out Value);
}
/// <summary>
/// Optional Size1 option.
/// </summary>
public uint? Size1
{
get { return this.size1; }
internal set { this.size1 = value; }
}
/// <summary>
/// Optional Size2 option.
/// </summary>
public uint? Size2
{
get { return this.size2; }
internal set { this.size2 = value; }
}
/// <summary>
/// Optional Block1 option (request payload).
/// </summary>
public CoapOptionBlock1 Block1
{
get { return this.block1; }
internal set { this.block1 = value; }
}
/// <summary>
/// Optional Block2 option (response payload).
/// </summary>
public CoapOptionBlock2 Block2
{
get { return this.block2; }
internal set { this.block2 = value; }
}
/// <summary>
/// Optional Observe option.
/// </summary>
public uint? Observe
{
get { return this.observe; }
internal set { this.observe = value; }
}
/// <summary>
/// Generates an URI for the message.
/// </summary>
/// <returns>URI string.</returns>
public string GetUri()
{
return CoapEndpoint.GetUri(this.host, this.port, this.path, this.uriQuery);
}
/// <summary>
/// Decodes the payload of the message.
/// </summary>
/// <returns>Decoded payload.</returns>
public object Decode()
{
if (this.payload is null)
return null;
else if (!this.contentFormat.HasValue)
return this.payload;
else
return CoapEndpoint.Decode((int)this.contentFormat.Value, this.payload, this.baseUri);
}
/// <summary>
/// Checks if a given content format is acceptable to the client.
/// </summary>
/// <param name="ContentFormat">Content Format to check.</param>
/// <returns>If the content format is acceptable or not.</returns>
public bool IsAcceptable(int ContentFormat)
{
if (this.accept is null)
return true;
if (ContentFormat < 0)
return false;
foreach (CoapOption Option in this.options)
{
if (Option is CoapOptionAccept Accept && Accept.Value == (uint)ContentFormat)
return true;
}
return false;
}
}
}