I'm trying to download a largish file (~167KB) via HTTP/TCP/IPv6 but the modem crashes every time around the same point during the download. It's spits out error 122, which I believe is EMSGSIZE. That would imply that the supplied buffer is too small or NULL. This happens regardless of the size of the buffer I give it. Sockets are offloaded to the modem and net native is set to no. I've tried to increase the size for just about every related Kconfig setting I can find with no change. Maybe it's MTU related?
I am writing the `recv()` bytes directly to flash, but I don't see any errors there.
Error log:
D: addrinfo @0x200302e0: ai_family=2, ai_socktype=1, ai_protocol=6, sa_family=2, sin_port=bb01 D: Total: 49176 I: lib free 0x200187dc, size 20 I: lib alloc 0x200187dc, size 20 I: lib alloc 0x2001883c, size 20 I: lib free 0x200187f4, size 20 I: lib free 0x2001880c, size 20 I: lib free 0x20018824, size 20 I: lib free 0x200187dc, size 20 D: recv bytes: 4096 D: Total: 50545 I: lib free 0x2001883c, size 20 D: recv bytes: 11 D: Total: 54641 E: recv() body failed, err 122 E: EOF or error in response headers. I: Closing socket 0 D: (main): close: ctx=0x200136b0, fd=0 I: lib free 0x200187c4, size 20
Testing conf:
# General CONFIG_STACK_SENTINEL=y # NRF Modem CONFIG_MODEM_INFO=y CONFIG_NRF_MODEM_LIB=y CONFIG_MODEM_KEY_MGMT=y CONFIG_PDN=y CONFIG_NRF_MODEM_LIB_ON_FAULT_DO_NOTHING=y # CONFIG_NRF_MODEM_LIB_SHMEM_RX_SIZE=8192 # CONFIG_NRF_MODEM_LIB_HEAP_SIZE=1024 CONFIG_NRF_MODEM_LIB_SHMEM_RX_SIZE=32768 CONFIG_NRF_MODEM_LIB_HEAP_SIZE=4096 CONFIG_NRF_MODEM_LIB_SENDMSG_BUF_SIZE=256 # Align the max FD entry to NRF_MODEM_MAX_SOCKET_COUNT(8) CONFIG_POSIX_MAX_FDS=8 # NRF net options CONFIG_NET_NATIVE=n CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_NET_SOCKETS_OFFLOAD=y CONFIG_NET_IPV4=y CONFIG_NET_IPV6=y CONFIG_NET_BUF_RX_COUNT=56 # Disable Duplicate Address Detection (DAD) # due to not being properly implemented for offloaded interfaces. CONFIG_NET_IPV6_NBR_CACHE=n CONFIG_NET_IPV6_MLD=n # Setup LTE CONFIG_LTE_LINK_CONTROL=y CONFIG_LTE_PSM_REQ=y # Active time set to 0 so we can go right to PSM CONFIG_LTE_PSM_REQ_RAT="00000000" CONFIG_LTE_EDRX_REQ=y # PTW set to the minimum value, 1.27s, to conserve power CONFIG_LTE_PTW_VALUE_LTE_M="0000" # RAI is only supported for NBIoT currently # CONFIG_LTE_RAI_REQ=y # Allow writing to the flash at runtime CONFIG_MPU_ALLOW_FLASH_WRITE=y # Debugging CONFIG_NRF_MODEM_LIB_LOG_LEVEL_DBG=y CONFIG_NRF_MODEM_LIB_MEM_DIAG=y CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=y CONFIG_NVS_LOG_LEVEL_DBG=y CONFIG_NRF_MODEM_LIB_FAULT_STRERROR=y CONFIG_NRF_MODEM_LIB_MEM_DIAG_ALLOC=y # Set Stack Size CONFIG_MAIN_STACK_SIZE=82432 # Increase heap size for networking operations CONFIG_HEAP_MEM_POOL_SIZE=8192 # Compiler size optimizations CONFIG_SIZE_OPTIMIZATIONS=n # Some MCUmgr command handlers require a large stack. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304 # Networking Logging CONFIG_NET_LOG=y CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y CONFIG_NET_HTTP_LOG_LEVEL_DBG=y # Debugging CONFIG_DEBUG=y CONFIG_DEBUG_OPTIMIZATIONS=n # CONFIG_DEBUG_INFO=n CONFIG_RESET_ON_FATAL_ERROR=n CONFIG_THREAD_NAME=y
Relevant code:
/***** Out of file *****/
char write_buf[4096];
int write_buffer_to_flash(char *data, size_t len, size_t offset) {
if (len % write_block_size == 0) {
// LOG_DBG("Writing to flash");
if (flash_write(external_flash, offset, data, len)) {
return -1;
}
} else {
return len;
}
return 0;
}
/***********************/
static int parse_response(
int *sock, char *recv_body_buf, int recv_body_buf_size, _Bool write_nvs
) {
int rc = 0;
int state = 0;
int bytes;
size_t offset = 0;
bool headers = true;
int status;
size_t headers_size = 0;
do {
if (headers) {
bytes = recv(*sock, &headers_buf[offset], 1, 0);
if (bytes < 0) {
LOG_ERR("recv() headers failed, err %d\n", errno);
return bytes;
}
if ((state == 0 || state == 2) && headers_buf[offset] == '\r') {
state++;
} else if (state == 1 && headers_buf[offset] == '\n') {
state++;
} else if (state == 3) {
headers_size = offset;
LOG_INF("Received Headers. Size: %d bytes", offset);
headers = false;
headers_buf[offset + 1] = '\0';
offset = 0;
status = parse_status();
switch (status) {
case HTTP_REDIRECT:
return 1;
case HTTP_CLIENT_ERROR:
return -1;
case HTTP_SERVER_ERROR:
return -1;
case HTTP_NULL:
return -1;
default:
break;
}
continue;
} else {
state = 0;
}
} else {
if (write_nvs) {
if (rc > 0) {
bytes =
recv(*sock, (recv_body_buf + rc), (recv_body_buf_size - rc), 0);
if (bytes < 0) {
LOG_ERR("recv() body failed, err %d\n", errno);
return bytes;
}
bytes += rc;
LOG_DBG("recv + rc bytes: %d", bytes);
} else {
bytes = recv(*sock, recv_body_buf, recv_body_buf_size, 0);
if (bytes < 0) {
LOG_ERR("recv() body failed, err %d\n", errno);
return bytes;
}
LOG_DBG("recv bytes: %d", bytes);
}
rc = write_buffer_to_flash(recv_body_buf, bytes, offset);
LOG_DBG("Total: %d", offset);
if (rc < 0) {
LOG_DBG("rc: %d, error: %d", rc, errno);
return -1;
}
} else {
bytes = recv(
*sock, (recv_body_buf + offset), (recv_body_buf_size - offset), 0
);
}
}
offset += bytes;
} while (bytes != 0); /* peer closed connection */