Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: lib: coap: Handle truncated messages in CoAP server #83758

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions subsys/net/lib/coap/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@ config COAP_SERVER_PENDING_ALLOCATOR_STATIC_BLOCKS
help
The number of data blocks to reserve for pending messages to retransmit.

config COAP_SERVER_TRUNCATE_MSGS
bool "Handle truncated messages"
default y
help
Include ZSOCK_MSG_TRUNC in flags passed to zsock_recvfrom() to
receive network stack notifications about block truncation.
Otherwise it happens silently.

config COAP_SERVER_SHELL
bool "CoAP service shell commands"
depends on SHELL
Expand Down
47 changes: 43 additions & 4 deletions subsys/net/lib/coap/coap_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,13 @@ static int coap_server_process(int sock_fd)
uint8_t type;
ssize_t received;
int ret;
int flags = ZSOCK_MSG_DONTWAIT;

received = zsock_recvfrom(sock_fd, buf, sizeof(buf), ZSOCK_MSG_DONTWAIT, &client_addr,
&client_addr_len);
__ASSERT_NO_MSG(received <= sizeof(buf));
if (IS_ENABLED(CONFIG_COAP_SERVER_TRUNCATE_MSGS)) {
flags |= ZSOCK_MSG_TRUNC;
}

received = zsock_recvfrom(sock_fd, buf, sizeof(buf), flags, &client_addr, &client_addr_len);

if (received < 0) {
if (errno == EWOULDBLOCK) {
Expand All @@ -149,7 +152,7 @@ static int coap_server_process(int sock_fd)
return -errno;
}

ret = coap_packet_parse(&request, buf, received, options, opt_num);
ret = coap_packet_parse(&request, buf, MIN(received, sizeof(buf)), options, opt_num);
martinjaeger marked this conversation as resolved.
Show resolved Hide resolved
if (ret < 0) {
LOG_ERR("Failed To parse coap message (%d)", ret);
return ret;
Expand All @@ -170,6 +173,42 @@ static int coap_server_process(int sock_fd)

type = coap_header_get_type(&request);

if (received > sizeof(buf)) {
/* The message was truncated and can't be processed further */
struct coap_packet response;
uint8_t token[COAP_TOKEN_MAX_LEN];
uint8_t tkl = coap_header_get_token(&request, token);
uint16_t id = coap_header_get_id(&request);

if (type == COAP_TYPE_CON) {
type = COAP_TYPE_ACK;
} else {
type = COAP_TYPE_NON_CON;
}

ret = coap_packet_init(&response, buf, sizeof(buf), COAP_VERSION_1, type, tkl,
token, COAP_RESPONSE_CODE_REQUEST_TOO_LARGE, id);
if (ret < 0) {
LOG_ERR("Failed to init response (%d)", ret);
goto unlock;
}

ret = coap_append_option_int(&response, COAP_OPTION_SIZE1,
CONFIG_COAP_SERVER_MESSAGE_SIZE);
if (ret < 0) {
LOG_ERR("Failed to add SIZE1 option (%d)", ret);
goto unlock;
}

ret = coap_service_send(service, &response, &client_addr, client_addr_len, NULL);
if (ret < 0) {
LOG_ERR("Failed to reply \"Request Entity Too Large\" (%d)", ret);
goto unlock;
}

goto unlock;
}

pending = coap_pending_received(&request, service->data->pending, MAX_PENDINGS);
if (pending) {
uint8_t token[COAP_TOKEN_MAX_LEN];
Expand Down
Loading