-
Notifications
You must be signed in to change notification settings - Fork 76
/
Copy pathCoapMessageEventArgs.cs
156 lines (136 loc) · 5.1 KB
/
CoapMessageEventArgs.cs
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
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Waher.Networking.CoAP.Options;
using Waher.Networking.CoAP.Transport;
namespace Waher.Networking.CoAP
{
/// <summary>
/// Event arguments for CoAP message callbacks.
/// </summary>
public class CoapMessageEventArgs : EventArgs
{
private readonly ClientBase client;
private readonly CoapEndpoint endpoint;
private readonly CoapMessage message;
private readonly CoapResource resource;
private bool responded = false;
/// <summary>
/// Event arguments for CoAP response callbacks.
/// </summary>
/// <param name="Client">UDP Client.</param>
/// <param name="Endpoint">CoAP Endpoint.</param>
/// <param name="Message">CoAP message.</param>
/// <param name="Resource">CoAP resource if relevant.</param>
internal CoapMessageEventArgs(ClientBase Client, CoapEndpoint Endpoint, CoapMessage Message,
CoapResource Resource)
{
this.client = Client;
this.endpoint = Endpoint;
this.message = Message;
this.resource = Resource;
}
/// <summary>
/// UDP Client through which the message was received.
/// </summary>
internal ClientBase Client => this.client;
/// <summary>
/// CoAP resource, if relevant.
/// </summary>
internal CoapResource Resource => this.resource;
/// <summary>
/// CoAP Endpoint.
/// </summary>
public CoapEndpoint Endpoint => this.endpoint;
/// <summary>
/// CoAP message received.
/// </summary>
public CoapMessage Message => this.message;
/// <summary>
/// If a response has been returned.
/// </summary>
public bool Responded => this.responded;
/// <summary>
/// Returns a response to the caller.
/// </summary>
/// <param name="Code">CoAP message code.</param>
/// <param name="Options">Optional options.</param>
public Task RespondAsync(CoapCode Code, params CoapOption[] Options)
{
return this.RespondAsync(Code, null, 64, Options);
}
/// <summary>
/// Returns a response to the caller.
/// </summary>
/// <param name="Code">CoAP message code.</param>
/// <param name="Payload">Optional payload to be encoded.</param>
/// <param name="BlockSize">Block size, in case the <paramref name="Payload"/> needs to be divided into blocks.</param>
/// <param name="Options">Optional options.</param>
public async Task RespondAsync(CoapCode Code, object Payload, int BlockSize, params CoapOption[] Options)
{
KeyValuePair<byte[], int> P = await CoapEndpoint.EncodeAsync(Payload);
byte[] Data = P.Key;
int ContentFormat = P.Value;
if (!CoapEndpoint.HasOption(Options, 12))
Options = CoapEndpoint.Merge(Options, new CoapOptionContentFormat((ulong)ContentFormat));
await this.RespondAsync(Code, Data, BlockSize, Options);
}
/// <summary>
/// Returns a response to the caller.
/// </summary>
/// <param name="Code">CoAP message code.</param>
/// <param name="Payload">Optional payload.</param>
/// <param name="BlockSize">Block size, in case the <paramref name="Payload"/> needs to be divided into blocks.</param>
/// <param name="Options">Optional options.</param>
public async Task Respond(CoapCode Code, byte[] Payload, int BlockSize, params CoapOption[] Options)
{
if (this.message.Type == CoapMessageType.ACK || this.message.Type == CoapMessageType.RST)
throw new IOException("You cannot respond to ACK or RST messages.");
int BlockNr = !(this.message.Block2 is null) ? this.message.Block2.Number : 0;
await this.endpoint.Transmit(this.client, this.message.From, this.client.IsEncrypted,
this.responded ? (ushort?)null : this.message.MessageId,
this.responded ? this.message.Type : CoapMessageType.ACK, Code,
this.message.Token, false, Payload, BlockNr, BlockSize, this.resource, null, null, null, null, Options);
this.responded = true;
}
/// <summary>
/// Returns an acknowledgement.
/// </summary>
public Task ACK()
{
return this.ACK(CoapCode.EmptyMessage);
}
/// <summary>
/// Returns an acknowledgement.
/// </summary>
/// <param name="Code">CoAP message code.</param>
public Task ACK(CoapCode Code)
{
this.responded = true;
return this.endpoint.Transmit(this.client, this.message.From, this.client.IsEncrypted,
this.message.MessageId, CoapMessageType.ACK, Code,
Code == CoapCode.EmptyMessage ? (ulong?)null : this.message.Token, false, null, 0, 64, this.resource, null, null, null, null);
}
/// <summary>
/// Returns a reset message.
/// </summary>
public Task RST()
{
return this.RST(CoapCode.EmptyMessage);
}
/// <summary>
/// Returns a reset message.
/// </summary>
/// <param name="Code">CoAP message code.</param>
public Task RST(CoapCode Code)
{
if (this.message.Type == CoapMessageType.ACK || this.message.Type == CoapMessageType.RST)
throw new IOException("You cannot respond to ACK or RST messages.");
this.responded = true;
return this.endpoint.Transmit(this.client, this.message.From, this.client.IsEncrypted,
this.message.MessageId, CoapMessageType.RST, Code,
Code == CoapCode.EmptyMessage ? (ulong?)null : this.message.Token, false, null, 0, 64, this.resource, null, null, null, null);
}
}
}