diff --git a/sys/net/application_layer/nanocoap/sock.c b/sys/net/application_layer/nanocoap/sock.c index 02ef3c28ef..d0b0cb9701 100644 --- a/sys/net/application_layer/nanocoap/sock.c +++ b/sys/net/application_layer/nanocoap/sock.c @@ -52,7 +52,7 @@ enum { STATE_REQUEST_SEND, /**< request was just sent or will be sent again */ - STATE_RESPONSE_RCVD, /**< response received but might be invalid */ + STATE_STOP_RETRANSMIT, /**< stop retransmissions due to a matching empty ACK */ STATE_RESPONSE_OK, /**< valid response was received */ }; @@ -212,10 +212,7 @@ ssize_t nanocoap_sock_request_cb(nanocoap_sock_t *sock, coap_pkt_t *pkt, while (1) { switch (state) { case STATE_REQUEST_SEND: - if (tries_left == 0) { - DEBUG("nanocoap: maximum retries reached\n"); - return -ETIMEDOUT; - } + assert(tries_left > 0); --tries_left; DEBUG("nanocoap: send %u bytes (%u tries left)\n", @@ -235,7 +232,7 @@ ssize_t nanocoap_sock_request_cb(nanocoap_sock_t *sock, coap_pkt_t *pkt, /* ctx must have been released at this point */ assert(ctx == NULL); /* fall-through */ - case STATE_RESPONSE_RCVD: + case STATE_STOP_RETRANSMIT: case STATE_RESPONSE_OK: if (ctx == NULL) { DEBUG("nanocoap: waiting for response (timeout: %"PRIu32" µs)\n", @@ -257,13 +254,17 @@ ssize_t nanocoap_sock_request_cb(nanocoap_sock_t *sock, coap_pkt_t *pkt, /* no more data */ /* sock_udp_recv_buf() needs to be called in a loop until ctx is NULL again * to release the buffer */ - if (state == STATE_RESPONSE_RCVD) { + if (state == STATE_STOP_RETRANSMIT) { continue; } return res; } res = tmp; if (res == -ETIMEDOUT) { + if (tries_left == 0) { + DEBUG("nanocoap: maximum retries reached\n"); + return -ETIMEDOUT; + } DEBUG("nanocoap: timeout waiting for response\n"); timeout *= 2; deadline = _deadline_from_interval(timeout); @@ -275,7 +276,6 @@ ssize_t nanocoap_sock_request_cb(nanocoap_sock_t *sock, coap_pkt_t *pkt, } /* parse response */ - state = STATE_RESPONSE_RCVD; if (coap_parse(pkt, payload, res) < 0) { DEBUG("nanocoap: error parsing packet\n"); continue; @@ -285,20 +285,16 @@ ssize_t nanocoap_sock_request_cb(nanocoap_sock_t *sock, coap_pkt_t *pkt, continue; } - state = STATE_RESPONSE_OK; DEBUG("nanocoap: response code=%i\n", coap_get_code_decimal(pkt)); switch (coap_get_type(pkt)) { case COAP_TYPE_RST: /* TODO: handle different? */ res = -EBADMSG; break; - case COAP_TYPE_CON: - _send_ack(sock, pkt); - /* fall-through */ case COAP_TYPE_ACK: if (coap_get_code_raw(pkt) == COAP_CODE_EMPTY) { /* empty ACK, wait for separate response */ - state = STATE_RESPONSE_RCVD; + state = STATE_STOP_RETRANSMIT; deadline = _deadline_from_interval(CONFIG_COAP_SEPARATE_RESPONSE_TIMEOUT_MS * US_PER_MS); tries_left = 0; /* stop retransmissions */ @@ -306,7 +302,13 @@ ssize_t nanocoap_sock_request_cb(nanocoap_sock_t *sock, coap_pkt_t *pkt, continue; } /* fall-through */ + case COAP_TYPE_CON: case COAP_TYPE_NON: + state = STATE_RESPONSE_OK; + if (coap_get_type(pkt) == COAP_TYPE_CON) { + /* send ACK */ + _send_ack(sock, pkt); + } /* call user callback */ if (cb) { res = cb(arg, pkt);