Hi,
What cellular connectivity, the provider's DNS, and backend cloud services, invariably connecting over MQTT is transient and the internal blocking timeout of mqtt_client_tls_connect is inordinately long which can cause significant loss of battery life. We're perfectly fine modifying mqtt_client_tls_connect in mqtt_transport_socket_tls.c to make it a non-blocking socket connect() with our own timeout value but I'm observing the following:
- When calling fcntl(client->transport.tls.sock, F_SETFL, O_NONBLOCK); the flags parameter get unpacked in nrf91_socket_offload_fcntl, but flags = va_arg(args, int) is returning 0 instead of 0x4000 (O_NONBLOCK) even though I can see 0x4000 is being passed down before it becomes a va-arg.
- To eliminate va_arg as an issue we brought up the direct call to nrf_fcntl with NRF_O_NONBLOCK into mqtt_client_tls_connect and verified it is being set properly by calling nrf_fcntl(.. NRF_F_GETFL..) which returns NRF_O_NONBLOCK. However the subsequent socket connect(...) behaves as still blocking and doesn't return EINPROGRESS.
Full code below, any ideas?
Thanks!
// Set to non blocking
int flags = nrf_fcntl(client->transport.tls.sock, NRF_F_GETFL, 0);
ret = nrf_fcntl(client->transport.tls.sock, NRF_F_SETFL, flags | NRF_O_NONBLOCK);
int rflags = nrf_fcntl(client->transport.tls.sock, NRF_F_GETFL, 0);
printk(">>>>>>>> nrf_fcntl verified value set to %d\n", rflags);
ret = connect(client->transport.tls.sock, client->broker, peer_addr_size);
if (ret == EINPROGRESS) {
printk(">>>>>>>> connect EINPROGRESS\n");
fd_set wait_set;
struct timeval tv;
// make file descriptor set with socket
FD_ZERO(&wait_set);
FD_SET(client->transport.tls.sock, &wait_set);
// wait for socket to be writable; return after given timeout
tv.tv_sec = 30; // 30 seconds
tv.tv_usec = 0;
ret = select(client->transport.tls.sock + 1, NULL, &wait_set, NULL, &tv);
} else if (ret < 0) {
goto error;
}
ret = nrf_fcntl(client->transport.tls.sock, NRF_F_SETFL, flags); // restore to blocking socket calls