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 */