mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-29 16:31:18 +01:00
Merge pull request #7336 from kb2ma/gcoap/confirm_infrastructure
net/gcoap: Create confirm request infrastructure and adapt existing messaging
This commit is contained in:
commit
73d9c460d3
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Ken Bannister. All rights reserved.
|
||||
* Copyright (c) 2015-2017 Ken Bannister. All rights reserved.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -180,61 +180,80 @@ int gcoap_cli_cmd(int argc, char **argv)
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(method_codes) / sizeof(char*); i++) {
|
||||
if (strcmp(argv[1], method_codes[i]) == 0) {
|
||||
if (argc == 5 || argc == 6) {
|
||||
if (argc == 6) {
|
||||
gcoap_req_init(&pdu, &buf[0], GCOAP_PDU_BUF_SIZE, i+1, argv[4]);
|
||||
memcpy(pdu.payload, argv[5], strlen(argv[5]));
|
||||
len = gcoap_finish(&pdu, strlen(argv[5]), COAP_FORMAT_TEXT);
|
||||
}
|
||||
else {
|
||||
len = gcoap_request(&pdu, &buf[0], GCOAP_PDU_BUF_SIZE, i+1,
|
||||
argv[4]);
|
||||
}
|
||||
printf("gcoap_cli: sending msg ID %u, %u bytes\n", coap_get_id(&pdu),
|
||||
(unsigned) len);
|
||||
if (!_send(&buf[0], len, argv[2], argv[3])) {
|
||||
puts("gcoap_cli: msg send failed");
|
||||
}
|
||||
else {
|
||||
/* send Observe notification for /cli/stats */
|
||||
switch (gcoap_obs_init(&pdu, &buf[0], GCOAP_PDU_BUF_SIZE,
|
||||
&_resources[0])) {
|
||||
case GCOAP_OBS_INIT_OK:
|
||||
DEBUG("gcoap_cli: creating /cli/stats notification\n");
|
||||
size_t payload_len = fmt_u16_dec((char *)pdu.payload, req_count);
|
||||
len = gcoap_finish(&pdu, payload_len, COAP_FORMAT_TEXT);
|
||||
gcoap_obs_send(&buf[0], len, &_resources[0]);
|
||||
break;
|
||||
case GCOAP_OBS_INIT_UNUSED:
|
||||
DEBUG("gcoap_cli: no observer for /cli/stats\n");
|
||||
break;
|
||||
case GCOAP_OBS_INIT_ERR:
|
||||
DEBUG("gcoap_cli: error initializing /cli/stats notification\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("usage: %s <get|post|put> <addr> <port> <path> [data]\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strcmp(argv[1], "info") == 0) {
|
||||
uint8_t open_reqs = gcoap_op_state();
|
||||
|
||||
printf("CoAP server is listening on port %u\n", GCOAP_PORT);
|
||||
printf(" CLI requests sent: %u\n", req_count);
|
||||
printf("CoAP open requests: %u\n", open_reqs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "info") == 0) {
|
||||
if (argc == 2) {
|
||||
uint8_t open_reqs = gcoap_op_state();
|
||||
|
||||
printf("CoAP server is listening on port %u\n", GCOAP_PORT);
|
||||
printf(" CLI requests sent: %u\n", req_count);
|
||||
printf("CoAP open requests: %u\n", open_reqs);
|
||||
return 0;
|
||||
/* if not 'info', must be a method code */
|
||||
int code_pos = -1;
|
||||
for (size_t i = 0; i < sizeof(method_codes) / sizeof(char*); i++) {
|
||||
if (strcmp(argv[1], method_codes[i]) == 0) {
|
||||
code_pos = i;
|
||||
}
|
||||
}
|
||||
if (code_pos == -1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* parse options */
|
||||
int apos = 2; /* position of address argument */
|
||||
unsigned msg_type = COAP_TYPE_NON;
|
||||
if (argc > apos && strcmp(argv[apos], "-c") == 0) {
|
||||
msg_type = COAP_TYPE_CON;
|
||||
apos++;
|
||||
}
|
||||
|
||||
if (argc == apos + 3 || argc == apos + 4) {
|
||||
gcoap_req_init(&pdu, &buf[0], GCOAP_PDU_BUF_SIZE, code_pos+1, argv[apos+2]);
|
||||
if (argc == apos + 4) {
|
||||
memcpy(pdu.payload, argv[apos+3], strlen(argv[apos+3]));
|
||||
}
|
||||
coap_hdr_set_type(pdu.hdr, msg_type);
|
||||
|
||||
if (argc == apos + 4) {
|
||||
len = gcoap_finish(&pdu, strlen(argv[apos+3]), COAP_FORMAT_TEXT);
|
||||
}
|
||||
else {
|
||||
len = gcoap_finish(&pdu, 0, COAP_FORMAT_NONE);
|
||||
}
|
||||
|
||||
printf("gcoap_cli: sending msg ID %u, %u bytes\n", coap_get_id(&pdu),
|
||||
(unsigned) len);
|
||||
if (!_send(&buf[0], len, argv[apos], argv[apos+1])) {
|
||||
puts("gcoap_cli: msg send failed");
|
||||
}
|
||||
else {
|
||||
/* send Observe notification for /cli/stats */
|
||||
switch (gcoap_obs_init(&pdu, &buf[0], GCOAP_PDU_BUF_SIZE,
|
||||
&_resources[0])) {
|
||||
case GCOAP_OBS_INIT_OK:
|
||||
DEBUG("gcoap_cli: creating /cli/stats notification\n");
|
||||
size_t payload_len = fmt_u16_dec((char *)pdu.payload, req_count);
|
||||
len = gcoap_finish(&pdu, payload_len, COAP_FORMAT_TEXT);
|
||||
gcoap_obs_send(&buf[0], len, &_resources[0]);
|
||||
break;
|
||||
case GCOAP_OBS_INIT_UNUSED:
|
||||
DEBUG("gcoap_cli: no observer for /cli/stats\n");
|
||||
break;
|
||||
case GCOAP_OBS_INIT_ERR:
|
||||
DEBUG("gcoap_cli: error initializing /cli/stats notification\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
printf("usage: %s <get|post|put> [-c] <addr> <port> <path> [data]\n",
|
||||
argv[0]);
|
||||
printf("Options\n");
|
||||
printf(" -c Send confirmably (defaults to non-confirmable)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
end:
|
||||
printf("usage: %s <get|post|put|info>\n", argv[0]);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Ken Bannister. All rights reserved.
|
||||
* Copyright (c) 2015-2017 Ken Bannister. All rights reserved.
|
||||
* 2017 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
@ -302,6 +302,11 @@ extern "C" {
|
||||
#define GCOAP_MEMO_ERR (4) /**< Error processing response packet */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Value for send_limit in request memo when non-confirmable type
|
||||
*/
|
||||
#define GCOAP_SEND_LIMIT_NON (-1)
|
||||
|
||||
/**
|
||||
* @brief Time in usec that the event loop waits for an incoming CoAP message
|
||||
*/
|
||||
@ -424,13 +429,28 @@ typedef struct gcoap_listener {
|
||||
typedef void (*gcoap_resp_handler_t)(unsigned req_state, coap_pkt_t* pdu,
|
||||
sock_udp_ep_t *remote);
|
||||
|
||||
/**
|
||||
* @brief Extends request memo for resending a confirmable request.
|
||||
*/
|
||||
typedef struct {
|
||||
sock_udp_ep_t remote_ep; /**< Remote endpoint */
|
||||
uint8_t *pdu_buf; /**< Buffer containing the PDU */
|
||||
size_t pdu_len; /**< Length of pdu_buf */
|
||||
} gcoap_resend_t;
|
||||
|
||||
/**
|
||||
* @brief Memo to handle a response for a request
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned state; /**< State of this memo, a GCOAP_MEMO... */
|
||||
uint8_t hdr_buf[GCOAP_HEADER_MAXLEN];
|
||||
/**< Stores a copy of the request header */
|
||||
int send_limit; /**< Remaining resends, 0 if none;
|
||||
GCOAP_SEND_LIMIT_NON if non-confirmable */
|
||||
union {
|
||||
uint8_t hdr_buf[GCOAP_HEADER_MAXLEN];
|
||||
/**< Copy of PDU header, if no resends */
|
||||
gcoap_resend_t data; /**< Endpoint and PDU buffer, for resend */
|
||||
} msg; /**< Request message data; if confirmable,
|
||||
supports resending message */
|
||||
gcoap_resp_handler_t resp_handler; /**< Callback for the response */
|
||||
xtimer_t response_timer; /**< Limits wait for response */
|
||||
msg_t timeout_msg; /**< For response timer */
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Ken Bannister. All rights reserved.
|
||||
* Copyright (c) 2015-2017 Ken Bannister. All rights reserved.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -35,8 +35,7 @@ static size_t _handle_req(coap_pkt_t *pdu, uint8_t *buf, size_t len,
|
||||
sock_udp_ep_t *remote);
|
||||
static ssize_t _finish_pdu(coap_pkt_t *pdu, uint8_t *buf, size_t len);
|
||||
static void _expire_request(gcoap_request_memo_t *memo);
|
||||
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu,
|
||||
uint8_t *buf, size_t len);
|
||||
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *pdu);
|
||||
static void _find_resource(coap_pkt_t *pdu, coap_resource_t **resource_ptr,
|
||||
gcoap_listener_t **listener_ptr);
|
||||
static int _find_observer(sock_udp_ep_t **observer, sock_udp_ep_t *remote);
|
||||
@ -156,7 +155,7 @@ static void _listen(sock_udp_t *sock)
|
||||
|
||||
/* incoming response */
|
||||
else {
|
||||
_find_req_memo(&memo, &pdu, buf, sizeof(buf));
|
||||
_find_req_memo(&memo, &pdu);
|
||||
if (memo) {
|
||||
xtimer_remove(&memo->response_timer);
|
||||
memo->state = GCOAP_MEMO_RESP;
|
||||
@ -331,39 +330,34 @@ static ssize_t _finish_pdu(coap_pkt_t *pdu, uint8_t *buf, size_t len)
|
||||
* Finds the memo for an outstanding request within the _coap_state.open_reqs
|
||||
* array. Matches on token.
|
||||
*
|
||||
* src_pdu Source for the match token
|
||||
* memo_ptr[out] -- Registered request memo, or NULL if not found
|
||||
* src_pdu[in] -- PDU for token to match
|
||||
*/
|
||||
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *src_pdu,
|
||||
uint8_t *buf, size_t len)
|
||||
static void _find_req_memo(gcoap_request_memo_t **memo_ptr, coap_pkt_t *src_pdu)
|
||||
{
|
||||
gcoap_request_memo_t *memo;
|
||||
coap_pkt_t memo_pdu = { .token = NULL };
|
||||
(void) buf;
|
||||
(void) len;
|
||||
*memo_ptr = NULL;
|
||||
/* no need to initialize struct; we only care about buffer contents below */
|
||||
coap_pkt_t memo_pdu_data;
|
||||
coap_pkt_t *memo_pdu = &memo_pdu_data;
|
||||
unsigned cmplen = coap_get_token_len(src_pdu);
|
||||
|
||||
for (int i = 0; i < GCOAP_REQ_WAITING_MAX; i++) {
|
||||
if (_coap_state.open_reqs[i].state == GCOAP_MEMO_UNUSED)
|
||||
continue;
|
||||
|
||||
/* setup memo PDU from memo header */
|
||||
memo = &_coap_state.open_reqs[i];
|
||||
coap_hdr_t *memo_hdr = (coap_hdr_t *) &memo->hdr_buf[0];
|
||||
memo_pdu.hdr = memo_hdr;
|
||||
if (coap_get_token_len(&memo_pdu)) {
|
||||
memo_pdu.token = &memo_hdr->data[0];
|
||||
gcoap_request_memo_t *memo = &_coap_state.open_reqs[i];
|
||||
if (memo->send_limit == GCOAP_SEND_LIMIT_NON) {
|
||||
memo_pdu->hdr = (coap_hdr_t *) &memo->msg.hdr_buf[0];
|
||||
}
|
||||
/* match on token */
|
||||
if (coap_get_token_len(src_pdu) == coap_get_token_len(&memo_pdu)) {
|
||||
uint8_t *src_byte = src_pdu->token;
|
||||
uint8_t *memo_byte = memo_pdu.token;
|
||||
size_t j;
|
||||
for (j = 0; j < coap_get_token_len(src_pdu); j++) {
|
||||
if (*src_byte++ != *memo_byte++) {
|
||||
break; /* token mismatch */
|
||||
}
|
||||
}
|
||||
if (j == coap_get_token_len(src_pdu)) {
|
||||
else {
|
||||
memo_pdu->hdr = (coap_hdr_t *) memo->msg.data.pdu_buf;
|
||||
}
|
||||
|
||||
if (coap_get_token_len(memo_pdu) == cmplen) {
|
||||
memo_pdu->token = &memo_pdu->hdr->data[0];
|
||||
if (memcmp(src_pdu->token, memo_pdu->token, cmplen) == 0) {
|
||||
*memo_ptr = memo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -379,7 +373,7 @@ static void _expire_request(gcoap_request_memo_t *memo)
|
||||
memo->state = GCOAP_MEMO_TIMEOUT;
|
||||
/* Pass response to handler */
|
||||
if (memo->resp_handler) {
|
||||
req.hdr = (coap_hdr_t *)&memo->hdr_buf[0]; /* for reference */
|
||||
req.hdr = (coap_hdr_t *)&memo->msg.hdr_buf[0]; /* for reference */
|
||||
memo->resp_handler(memo->state, &req, NULL);
|
||||
}
|
||||
memo->state = GCOAP_MEMO_UNUSED;
|
||||
@ -692,7 +686,8 @@ size_t gcoap_req_send2(const uint8_t *buf, size_t len,
|
||||
mutex_unlock(&_coap_state.lock);
|
||||
|
||||
if (memo) {
|
||||
memcpy(&memo->hdr_buf[0], buf, GCOAP_HEADER_MAXLEN);
|
||||
memo->send_limit = GCOAP_SEND_LIMIT_NON;
|
||||
memcpy(&memo->msg.hdr_buf[0], buf, GCOAP_HEADER_MAXLEN);
|
||||
memo->resp_handler = resp_handler;
|
||||
|
||||
size_t res = sock_udp_send(&_sock, buf, len, remote);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user