mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-04 00:45:40 +03:00
Limit outstanding CON requests to NSTART per session for congestion control
https://tools.ietf.org/html/rfc7641#section-4.5 In order not to cause congestion, servers MUST strictly limit the number of simultaneous outstanding notifications/responses that they transmit to a given client to NSTART (1 by default; see Section 4.7 of RFC 7252 [RFC7252]). An outstanding notification/response is either a confirmable message for which an acknowledgement has not yet been received and whose last retransmission attempt has not yet timed out or a non-confirmable message for which the waiting time that results from the following rate-limiting rules has not yet elapsed. Delay sending of PDUs if active CON request waiting for ACK. Do not start of another Observer unsolicited response if active CON waiting waiting for ACK. Display outgoing PDU if log level DEBUG or higher to help troubleshooting. This does not fix the ratelimiting of non-confirmable messages, which should be handled by the application.
This commit is contained in:
1 parent
92994031ea
commit
ea72c3d770
3 files changed
+23
-2
No files matched your search
@@ -68,6 +68,7 @@ typedef struct coap_session_t {
|
||||
struct coap_context_t *context; /**< session's context */
|
||||
void *tls; /**< security parameters */
|
||||
uint16_t tx_mid; /**< the last message id that was used in this session */
|
||||
uint8_t con_active; /**< Active CON request sent */
|
||||
struct coap_queue_t *sendqueue; /**< list of messages waiting to be sent */
|
||||
size_t partial_write; /**< if > 0 indicates number of bytes already written from the pdu at the head of sendqueue */
|
||||
uint8_t read_header[8]; /**< storage space for header of incoming message header */
|
||||
|
||||
@@ -617,6 +617,9 @@ coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (LOG_DEBUG <= coap_get_log_level()) {
|
||||
coap_show_pdu(pdu);
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
@@ -631,7 +634,12 @@ coap_send_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node) {
|
||||
assert(session->endpoint != NULL);
|
||||
sock = &session->endpoint->sock;
|
||||
}
|
||||
if (pdu->type == COAP_MESSAGE_CON)
|
||||
session->con_active++;
|
||||
bytes_written = coap_socket_send_pdu(sock, session, pdu);
|
||||
if (LOG_DEBUG <= coap_get_log_level()) {
|
||||
coap_show_pdu(pdu);
|
||||
}
|
||||
coap_ticks(&session->last_rx_tx);
|
||||
|
||||
#else
|
||||
@@ -682,13 +690,17 @@ coap_send_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (session->state != COAP_SESSION_STATE_ESTABLISHED)
|
||||
if (session->state != COAP_SESSION_STATE_ESTABLISHED ||
|
||||
(pdu->type == COAP_MESSAGE_CON && session->con_active >= COAP_DEFAULT_NSTART)) {
|
||||
return coap_session_delay_pdu(session, pdu, node);
|
||||
}
|
||||
|
||||
if ((session->sock.flags & COAP_SOCKET_NOT_EMPTY) &&
|
||||
(session->sock.flags & COAP_SOCKET_WANT_WRITE))
|
||||
return coap_session_delay_pdu(session, pdu, node);
|
||||
|
||||
if (pdu->type == COAP_MESSAGE_CON)
|
||||
session->con_active++;
|
||||
bytes_written = coap_session_send_pdu(session, pdu);
|
||||
|
||||
#endif /* WITH_LWIP */
|
||||
@@ -901,6 +913,8 @@ coap_retransmit(coap_context_t *context, coap_queue_t *node) {
|
||||
debug("** %s tid=%d: retransmission #%d\n",
|
||||
coap_session_str(node->session), node->id, node->retransmit_cnt);
|
||||
|
||||
if (node->session->con_active)
|
||||
node->session->con_active--;
|
||||
bytes_written = coap_send_pdu(node->session, node->pdu, node);
|
||||
|
||||
if (bytes_written == COAP_PDU_DELAYED) {
|
||||
@@ -934,6 +948,8 @@ coap_retransmit(coap_context_t *context, coap_queue_t *node) {
|
||||
coap_handle_failed_notify(context, node->session, &token);
|
||||
}
|
||||
#endif /* WITHOUT_OBSERVE */
|
||||
if (node->session->con_active)
|
||||
node->session->con_active--;
|
||||
|
||||
/* And finally delete the node */
|
||||
if (node->pdu->type == COAP_MESSAGE_CON && context->nack_handler)
|
||||
@@ -2070,8 +2086,10 @@ coap_dispatch(coap_context_t *context, coap_session_t *session,
|
||||
/* find transaction in sendqueue to stop retransmission */
|
||||
coap_remove_from_queue(&context->sendqueue, session, pdu->tid, &sent);
|
||||
|
||||
if (session->con_active)
|
||||
session->con_active--;
|
||||
if (pdu->code == 0)
|
||||
goto cleanup;
|
||||
goto cleanup;
|
||||
|
||||
/* if sent code was >= 64 the message might have been a
|
||||
* notification. Then, we must flag the observer to be alive
|
||||
|
||||
@@ -712,6 +712,8 @@ coap_notify_observers(coap_context_t *context, coap_resource_t *r) {
|
||||
if (r->dirty == 0 && obs->dirty == 0)
|
||||
/* running this resource due to partiallydirty, but this observation's notification was already enqueued */
|
||||
continue;
|
||||
if (obs->session->con_active >= COAP_DEFAULT_NSTART)
|
||||
continue;
|
||||
|
||||
coap_tid_t tid = COAP_INVALID_TID;
|
||||
obs->dirty = 0;
|
||||
|
||||
Reference in new issue
Block a user