Arduino  1.8.10
CoapMessageLayer クラス

#include <CoapMessageLayer.h>

公開型

enum  State { STATE_CLOSED, STATE_RELIABLE_TX, STATE_ACK_PENDING, STATE_WAITING_FOR_CON }
 
enum  Result {
  NO_ERROR = 0, CON_RECEIVED, NON_RECEIVED, ACK_RECEIVED,
  RESET_RECEIVED, ERROR_IMPROPER_STATE, ERROR_NULL_MESSAGE, ERROR_SENDING_PACKET,
  ERROR_RECEIVING_PACKET, ERROR_RETRANSMIT_COUNT_EXCEEDED, ERROR_TX_SPAN_TIME_EXCEEDED
}
 

公開メンバ関数

 CoapMessageLayer (uint8_t *rxBuffer, uint16_t rxLen, TembooCoAPIPStack &ipStack)
 
Result reliableSend (CoapMsg &msg, IPAddress destAddr, uint16_t destPort)
 
Result cancelReliableSend ()
 
Result acceptMsg (CoapMsg &msg)
 
Result acceptMsg (CoapMsg &msg, IPAddress addr, uint16_t port)
 
Result rejectMsg (CoapMsg &msg)
 
Result rejectMsg (CoapMsg &msg, IPAddress addr, uint16_t port)
 
Result loop ()
 
Result getLastResult ()
 
uint16_t getRXByteCount ()
 
void setState (State state)
 

静的公開変数類

static const uint32_t ACK_TIMEOUT = 2000
 
static const uint32_t MAX_ACK_TIMEOUT = 3000
 
static const uint8_t MAX_RETRANSMIT = 4
 
static const uint32_t MAX_TRANSMIT_SPAN = 45000
 
static const uint32_t MAX_TRANSMIT_WAIT = 93000
 

詳解

CoapMessageLayer is the lowest layer of the CoAP stack. It is responsible for transmitting and receiving messages. Specifically, this implementation is responsible for handling confirmable (CON) messages and their ACKs. It is intended to implement the Message Layer FSM described by Kovatsch et al. in https://tools.ietf.org/html/draft-kovatsch-lwig-coap-01

It can send reliable (confirmable or CON) messages and will maintain the necessary state information to wait for an acknowledgement. It will handle any necessary retransmissions and timeouts until a CON message has been ACK'd (or rejected.)

It can not send unreliable (non-confirmable or NON) messages as currently designed because our application does not use NON messages.

It can receive CON and NON messages and will send ACKs or RESETs as required.

Any non-rejected CON or NON messages received are passed up to the Request/Response layer (CoapRRLayer) for processing.

Be sure to note the difference between ACK's and Responses. This layer handles ACK's, it does not handle Responses. (Responses are handled by the CoapRRLayer class.)

CoapMessageLayer.h54 行目に定義があります。

列挙型メンバ詳解

◆ Result

◆ State

列挙値
STATE_CLOSED 
STATE_RELIABLE_TX 
STATE_ACK_PENDING 
STATE_WAITING_FOR_CON 

CoapMessageLayer.h57 行目に定義があります。

構築子と解体子

◆ CoapMessageLayer()

CoapMessageLayer::CoapMessageLayer ( uint8_t *  rxBuffer,
uint16_t  rxLen,
TembooCoAPIPStack ipStack 
)

CoapMessageLayer.cpp25 行目に定義があります。

25  :
26  m_rxBuffer(rxBuffer),
27  m_rxLen(rxLen),
28  m_ipStack(ipStack),
29  m_state(STATE_CLOSED),
30  m_prevState(STATE_CLOSED),
31  m_retransmitCount(0),
32  m_lastResult(NO_ERROR),
33  m_msgID(0) {
34 }

関数詳解

◆ acceptMsg() [1/2]

CoapMessageLayer::Result CoapMessageLayer::acceptMsg ( CoapMsg msg)

CoapMessageLayer.cpp59 行目に定義があります。

59  {
60  return acceptMsg(msg, m_ipStack.getRemoteAddress(), m_ipStack.getRemotePort());
61 }
Result acceptMsg(CoapMsg &msg)
IPAddress getRemoteAddress()
uint16_t getRemotePort()

◆ acceptMsg() [2/2]

CoapMessageLayer::Result CoapMessageLayer::acceptMsg ( CoapMsg msg,
IPAddress  addr,
uint16_t  port 
)

CoapMessageLayer.cpp65 行目に定義があります。

65  {
66  if (m_state != STATE_ACK_PENDING) {
67  m_lastResult = ERROR_IMPROPER_STATE;
68  } else {
69  msg.convertToEmptyAck();
70  TEMBOO_TRACE("DBG: ");
71  TEMBOO_TRACELN("Sending ACK");
72  if (m_ipStack.sendDatagram(addr, port, msg.getMsgBytes(), msg.getMsgLen())) {
73  m_lastResult = ERROR_SENDING_PACKET;
74  } else {
75  m_state = STATE_CLOSED;
76  m_lastResult = NO_ERROR;
77  }
78  }
79  return m_lastResult;
80 }
int sendDatagram(IPAddress address, uint16_t port, uint8_t *data, size_t len)
void convertToEmptyAck()
Definition: CoapMsg.cpp:663
#define TEMBOO_TRACELN(x)
Definition: TembooGlobal.h:37
uint8_t * getMsgBytes()
Definition: CoapMsg.cpp:421
#define TEMBOO_TRACE(x)
Definition: TembooGlobal.h:35
uint16_t getMsgLen()
Definition: CoapMsg.cpp:427

◆ cancelReliableSend()

CoapMessageLayer::Result CoapMessageLayer::cancelReliableSend ( )

CoapMessageLayer.cpp116 行目に定義があります。

116  {
117  if (m_state != STATE_RELIABLE_TX) {
118  m_lastResult = ERROR_IMPROPER_STATE;
119  return m_lastResult;
120  }
121 
122  m_state = STATE_CLOSED;
123  m_lastResult = NO_ERROR;
124  return m_lastResult;
125 }

◆ getLastResult()

Result CoapMessageLayer::getLastResult ( )
inline

CoapMessageLayer.h100 行目に定義があります。

100 {return m_lastResult;}

◆ getRXByteCount()

uint16_t CoapMessageLayer::getRXByteCount ( )
inline

CoapMessageLayer.h101 行目に定義があります。

101 {return m_rxByteCount;}

◆ loop()

CoapMessageLayer::Result CoapMessageLayer::loop ( )

CoapMessageLayer.cpp129 行目に定義があります。

129  {
130 
131  m_lastResult = NO_ERROR;
132 
133  switch(m_state) {
134  case STATE_RELIABLE_TX:
135  // We have sent a CON request.
136  // We're expecting an ACK or a response.
137 
138  // See if it's time to give up all hope of getting an ACK.
139  if (m_txSpanTimer.expired()) {
140  m_lastResult = ERROR_TX_SPAN_TIME_EXCEEDED;
141  m_state = STATE_CLOSED;
142  TEMBOO_TRACE("ERROR: ");
143  TEMBOO_TRACELN("ACK not received within timeout");
144  break;
145  }
146 
147  // See if any messages have come in.
148  if (m_ipStack.recvDatagram(m_rxBuffer, m_rxLen, m_rxByteCount)) {
149  m_lastResult = ERROR_RECEIVING_PACKET;
150  m_state = STATE_CLOSED;
151  break;
152  }
153 
154  // We've received something. See if it's relevant.
155  if (m_rxByteCount > 0) {
156  CoapMsg msg(m_rxBuffer, m_rxLen, m_rxByteCount);
157 
158  // Make sure the message is valid
159  if (!msg.isValid()) {
160  rejectMsg(msg);
161 
162  // We're only interested in messages coming from the host
163  // we sent the original request to.
164  } else if (m_ipStack.getRemoteAddress() == m_destAddr) {
165  switch (msg.getType()) {
166  case CoapMsg::COAP_ACK:
167  TEMBOO_TRACE("DBG: ");
168  TEMBOO_TRACELN("ACK Received");
169  // Is it ACK'ing the last request we sent?
170  if (msg.getId() == m_msgID) {
171  m_state = STATE_CLOSED;
172  m_lastResult = ACK_RECEIVED;
173  } else {
174  // if not, just ignore it.
175  TEMBOO_TRACE("ERROR: ");
176  TEMBOO_TRACELN("MID did not match");
177  }
178 
179  break;
180 
181  case CoapMsg::COAP_RESET:
182  // Is it rejecting the last request we sent?
183  TEMBOO_TRACE("DBG: ");
184  TEMBOO_TRACELN("RST Received");
185  if (msg.getId() == m_msgID) {
186  m_state = STATE_CLOSED;
187  m_lastResult = RESET_RECEIVED;
188  } else {
189  // if not, just ignore it.
190  TEMBOO_TRACE("ERROR: ");
191  TEMBOO_TRACELN("MID did not match");
192  }
193  break;
194 
196  // It COULD be the response to our request, or
197  // just some unexpected message.
198  // We'll let the upper layers decide.
199  m_prevState = m_state;
200  m_state = STATE_ACK_PENDING;
201  m_lastResult = CON_RECEIVED;
202  TEMBOO_TRACE("DBG: ");
203  TEMBOO_TRACELN("CON Received");
204  break;
205 
207  // It COULD be the response to our request, or
208  // just some unexpected message.
209  // We'll let the upper layers decide.
210 
211  // That's what Kovatsch et al. show in their FSM.
212  m_state = STATE_CLOSED;
213  m_lastResult = NON_RECEIVED;
214  TEMBOO_TRACE("DBG: ");
215  TEMBOO_TRACELN("NON Received");
216  break;
217  }
218  if (msg.getPayloadLen() > 0) {
219  TEMBOO_TRACE("DBG: ");
220  TEMBOO_TRACELN("Payload data:");
221  uint8_t *payload = msg.getPayload();
222  uint16_t len = msg.getPayloadLen();
223  for (uint16_t i = 0; i < len; i++) {
224  TEMBOO_TRACE((char)payload[i]);
225  }
226  TEMBOO_TRACELN();
227  }
228  } else if (msg.getType() == CoapMsg::COAP_CONFIRMABLE) {
229  // It's not from the host we sent the request to, but
230  // the sending host expects a reply, so explicitly reject it.
231  rejectMsg(msg);
232  }
233 
234  break;
235  }
236 
237  // Nothing was received. See if it's time to retransmit.
238  if (m_retransmitTimer.expired()) {
239  if (m_retransmitCount >= MAX_RETRANSMIT) {
240  // We've retried enough. Give up.
241  TEMBOO_TRACE("ERROR: ");
242  TEMBOO_TRACELN("Maximum retransmit reached");
243  m_lastResult = ERROR_RETRANSMIT_COUNT_EXCEEDED;
244  m_state = STATE_CLOSED;
245  } else {
246  TEMBOO_TRACE("DBG: ");
247  TEMBOO_TRACELN("Retransmit message");
248  m_retransmitCount++;
249  m_retransmitTimeoutMillis *= 2;
250  if (m_ipStack.sendDatagram(m_destAddr, m_destPort, m_msgBytes, m_msgLen)) {
251  m_state = STATE_CLOSED;
252  m_lastResult = ERROR_SENDING_PACKET;
253  } else {
254  m_retransmitTimer.start(m_retransmitTimeoutMillis);
255  m_state = STATE_RELIABLE_TX;
256  m_lastResult = NO_ERROR;
257  }
258  }
259  }
260  break;
261 
262  case STATE_ACK_PENDING:
263  // Nothing to do here but wait for
264  // the higher layer to accept or reject.
265  break;
266 
268  // See if any messages have come in.
269  if (m_ipStack.recvDatagram(m_rxBuffer, m_rxLen, m_rxByteCount)) {
270  m_lastResult = ERROR_RECEIVING_PACKET;
271  m_state = STATE_CLOSED;
272  break;
273  }
274 
275  // We've received something. See if it's relevant.
276  if (m_rxByteCount > 0) {
277  CoapMsg msg(m_rxBuffer, m_rxLen, m_rxByteCount);
278 
279  // Make sure the message is valid
280  if (!msg.isValid()) {
281  rejectMsg(msg);
282 
283  // We're only interested in messages coming from the host
284  // we sent the original request to.
285  } else if (m_ipStack.getRemoteAddress() == m_destAddr) {
286  switch (msg.getType()) {
287  case CoapMsg::COAP_ACK:
288  TEMBOO_TRACE("DBG: ");
289  TEMBOO_TRACELN("ACK Received");
290  // Is it ACK'ing the last request we sent?
291  if (msg.getId() == m_msgID) {
292  m_state = STATE_CLOSED;
293  m_lastResult = ACK_RECEIVED;
294  } else {
295  // if not, just ignore it.
296  TEMBOO_TRACE("ERROR: ");
297  TEMBOO_TRACELN("MID did not match");
298  }
299  break;
300 
301  case CoapMsg::COAP_RESET:
302  // Is it rejecting the last request we sent?
303  TEMBOO_TRACE("DBG: ");
304  TEMBOO_TRACELN("RST Received");
305  if (msg.getId() == m_msgID) {
306  m_state = STATE_CLOSED;
307  m_lastResult = RESET_RECEIVED;
308  } else {
309  // if not, just ignore it.
310  TEMBOO_TRACE("ERROR: ");
311  TEMBOO_TRACELN("MID did not match");
312  }
313  break;
314 
316  // It COULD be the response to our request, or
317  // just some unexpected message.
318  // We'll let the upper layers decide.
319  m_prevState = m_state;
320  m_state = STATE_ACK_PENDING;
321  m_lastResult = CON_RECEIVED;
322  TEMBOO_TRACE("DBG: ");
323  TEMBOO_TRACELN("CON Received");
324  break;
325 
327  // It COULD be the response to our request, or
328  // just some unexpected message.
329  // We'll let the upper layers decide.
330 
331  // That's what Kovatsch et al. show in their FSM.
332  m_state = STATE_CLOSED;
333  m_lastResult = NON_RECEIVED;
334  TEMBOO_TRACE("DBG: ");
335  TEMBOO_TRACELN("NON Received");
336  break;
337  }
338  if (msg.getPayloadLen() > 0) {
339  TEMBOO_TRACE("DBG: ");
340  TEMBOO_TRACELN("Payload data:");
341  uint8_t *payload = msg.getPayload();
342  uint16_t len = msg.getPayloadLen();
343  for (uint16_t i = 0; i < len; i++) {
344  TEMBOO_TRACE((char)payload[i]);
345  }
346  TEMBOO_TRACELN();
347  }
348  } else if (msg.getType() == CoapMsg::COAP_CONFIRMABLE) {
349  // It's not from the host we sent the request to, but
350  // the sending host expects a reply, so explicitly reject it.
351  rejectMsg(msg);
352  }
353 
354  break;
355  }
356  break;
357 
358 
359  case STATE_CLOSED:
360 
361  // We haven't sent anything that we're expecting an answer to.
362  // We haven't received anything that requires an answer.
363  // Just pump the receiver.
364  if (m_ipStack.recvDatagram(m_rxBuffer, m_rxLen, m_rxByteCount)) {
365  m_lastResult = ERROR_RECEIVING_PACKET;
366  break;
367  }
368 
369  // If we received something, handle it.
370  if (m_rxByteCount > 0) {
371  CoapMsg msg(m_rxBuffer, m_rxLen, m_rxByteCount);
372  switch (msg.getType()) {
373  case CoapMsg::COAP_ACK:
374  // Not expecting any ACKS, ignore it.
375  break;
376 
377  case CoapMsg::COAP_RESET:
378  // Haven't sent any CONs and we don't send NONs, ignore it.
379  break;
380 
382  // Let the higher layers deal with this.
383  m_prevState = m_state;
384  m_state = STATE_ACK_PENDING;
385  m_lastResult = CON_RECEIVED;
386  break;
387 
389  // Let the higher layers deal with this.
390  m_lastResult = NON_RECEIVED;
391  break;
392  }
393  }
394 
395  break;
396 
397  }
398  return m_lastResult;
399 }
void start(uint32_t m_durationMillis)
Definition: TembooTimer.h:41
int sendDatagram(IPAddress address, uint16_t port, uint8_t *data, size_t len)
uint8_t i
#define TEMBOO_TRACELN(x)
Definition: TembooGlobal.h:37
IPAddress getRemoteAddress()
bool expired()
Definition: TembooTimer.h:37
static const uint8_t MAX_RETRANSMIT
#define TEMBOO_TRACE(x)
Definition: TembooGlobal.h:35
int recvDatagram(uint8_t *buffer, size_t maxLen, int32_t &count)
Result rejectMsg(CoapMsg &msg)

◆ rejectMsg() [1/2]

CoapMessageLayer::Result CoapMessageLayer::rejectMsg ( CoapMsg msg)

CoapMessageLayer.cpp37 行目に定義があります。

37  {
38  return rejectMsg(msg, m_ipStack.getRemoteAddress(), m_ipStack.getRemotePort());
39 }
IPAddress getRemoteAddress()
uint16_t getRemotePort()
Result rejectMsg(CoapMsg &msg)

◆ rejectMsg() [2/2]

CoapMessageLayer::Result CoapMessageLayer::rejectMsg ( CoapMsg msg,
IPAddress  addr,
uint16_t  port 
)

CoapMessageLayer.cpp41 行目に定義があります。

41  {
42  msg.convertToReset();
43  TEMBOO_TRACE("DBG: ");
44  TEMBOO_TRACELN("Sending RST");
45  if (m_ipStack.sendDatagram(addr, port, msg.getMsgBytes(), msg.getMsgLen())) {
46  m_lastResult = ERROR_SENDING_PACKET;
47  } else {
48  m_lastResult = NO_ERROR;
49  if (STATE_ACK_PENDING == m_state) {
50  // go back to previous state since the
51  // message recv'd wasn't what we're expecting
52  m_state = m_prevState;
53  }
54  }
55  return m_lastResult;
56 }
int sendDatagram(IPAddress address, uint16_t port, uint8_t *data, size_t len)
#define TEMBOO_TRACELN(x)
Definition: TembooGlobal.h:37
uint8_t * getMsgBytes()
Definition: CoapMsg.cpp:421
#define TEMBOO_TRACE(x)
Definition: TembooGlobal.h:35
void convertToReset()
Definition: CoapMsg.cpp:653
uint16_t getMsgLen()
Definition: CoapMsg.cpp:427

◆ reliableSend()

CoapMessageLayer::Result CoapMessageLayer::reliableSend ( CoapMsg msg,
IPAddress  destAddr,
uint16_t  destPort 
)

CoapMessageLayer.cpp84 行目に定義があります。

84  {
85 
86  if (m_state != STATE_CLOSED) {
87  m_lastResult = ERROR_IMPROPER_STATE;
88  return m_lastResult;
89  }
90 
91  m_rxByteCount = 0;
92  m_msgID = msg.getId();
93  m_msgBytes = msg.getMsgBytes();
94  m_msgLen = msg.getMsgLen();
95  m_destAddr = destAddr;
96  m_destPort = destPort;
98  m_retransmitCount = 0;
99  m_retransmitTimeoutMillis = random(ACK_TIMEOUT, MAX_ACK_TIMEOUT);
100  TEMBOO_TRACE("DBG: ");
101  TEMBOO_TRACELN("Sending message");
102  if (m_ipStack.sendDatagram(m_destAddr, m_destPort, msg.getMsgBytes(), msg.getMsgLen())) {
103  m_state = STATE_CLOSED;
104  m_lastResult = ERROR_SENDING_PACKET;
105  } else {
106  m_txSpanTimer.start(MAX_TRANSMIT_WAIT);
107  m_retransmitTimer.start(m_retransmitTimeoutMillis);
108  m_state = STATE_RELIABLE_TX;
109  m_lastResult = NO_ERROR;
110  }
111 
112  return m_lastResult;
113 }
void start(uint32_t m_durationMillis)
Definition: TembooTimer.h:41
int sendDatagram(IPAddress address, uint16_t port, uint8_t *data, size_t len)
#define TEMBOO_TRACELN(x)
Definition: TembooGlobal.h:37
void setType(CoapMsg::Type msgType)
Definition: CoapMsg.cpp:52
uint8_t * getMsgBytes()
Definition: CoapMsg.cpp:421
uint16_t getId()
Definition: CoapMsg.cpp:72
long random(long howbig)
Definition: WMath.cpp:35
static const uint32_t MAX_ACK_TIMEOUT
#define TEMBOO_TRACE(x)
Definition: TembooGlobal.h:35
static const uint32_t MAX_TRANSMIT_WAIT
static const uint32_t ACK_TIMEOUT
uint16_t getMsgLen()
Definition: CoapMsg.cpp:427

◆ setState()

void CoapMessageLayer::setState ( State  state)
inline

CoapMessageLayer.h102 行目に定義があります。

102 {m_state = state;}

メンバ詳解

◆ ACK_TIMEOUT

const uint32_t CoapMessageLayer::ACK_TIMEOUT = 2000
static

CoapMessageLayer.h78 行目に定義があります。

◆ MAX_ACK_TIMEOUT

const uint32_t CoapMessageLayer::MAX_ACK_TIMEOUT = 3000
static

CoapMessageLayer.h82 行目に定義があります。

◆ MAX_RETRANSMIT

const uint8_t CoapMessageLayer::MAX_RETRANSMIT = 4
static

CoapMessageLayer.h83 行目に定義があります。

◆ MAX_TRANSMIT_SPAN

const uint32_t CoapMessageLayer::MAX_TRANSMIT_SPAN = 45000
static

CoapMessageLayer.h86 行目に定義があります。

◆ MAX_TRANSMIT_WAIT

const uint32_t CoapMessageLayer::MAX_TRANSMIT_WAIT = 93000
static

CoapMessageLayer.h89 行目に定義があります。


このクラス詳解は次のファイルから抽出されました: