Calling zsock_poll() with TCP and UDP sockets

Hi,

I have faced dificulties calling zsock_poll for ZSOCK_POLLIN with multiple opened sockets, expecially when conbined TCP and UDP at the same time. My goal is it poll for incoming data on these sockets.

I tried following scenarious:

  1. zsock_poll() is seperate thread, polling TCP socket + eventfd file descriptor - no issues 
  2. zsock_poll() is seperate thread, polling UTP socket + eventfd file descriptor - no issues 
  3. zsock_poll() is seperate thread, polling TCP socket + UDP socket + eventfd file descriptor - zsock_poll returns error, errno operation not permitted

After that I tried to create seperate thread, one for TCP socket, the second one for UDP socket. This works only partially, zsock_poll() does not return error, but the issue is that call in not canceled immediately after data is receieved, but after timeout expires - ZSOCK_POLLIN is detected. For example if I set timeout to 10 seconds and modem receives data during this period, function detects ZSOCK_POLLIN after 10 seconds, not immidietly.

My setup:

  • nRF9151DK
  • nrf-sdk version 3.0.2
  • modem FW version 2.0.2

static void recv_proxy_thread_func(void *p1, void *p2, void *p3)
{
	enum {
		SOCK = 0,
		EVENT_FD = SLM_MAX_SOCKET_COUNT,
		FD_COUNT
	};

	int ret, err;
	struct zsock_pollfd poll_fds[FD_COUNT];

	enum recv_proxy_type recv_proxy_type = (enum recv_proxy_type) p1;
	int *efd = (int*) p2;
	int timeout = MSEC_PER_SEC * (recv_proxy_type == TCP_RECV_PROXY ? CONFIG_SLM_TCP_POLL_TIME : CONFIG_SLM_UDP_POLL_TIME);

	ARG_UNUSED(p3);

	poll_fds[EVENT_FD].fd = *efd;
	poll_fds[EVENT_FD].events = ZSOCK_POLLIN;

	do {
		// Create list of sockets which should be polled
		err = k_mutex_lock(&recv_proxy_buffer_mtx, K_FOREVER);
		if (err) {
			LOG_ERR("Unable to lock recv_proxy_buffer_mtx");
			continue;
		}
		for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) {
			if (recv_proxy_type == TCP_RECV_PROXY && socks[i].fd != INVALID_SOCKET && socks[i].type == SOCK_STREAM) {
				poll_fds[i].fd = socks[i].fd;
				poll_fds[i].events = ZSOCK_POLLIN;
			} else if (recv_proxy_type == UDP_RECV_PROXY && socks[i].fd != INVALID_SOCKET && socks[i].type == SOCK_DGRAM) {
				poll_fds[i].fd = socks[i].fd;
				poll_fds[i].events = ZSOCK_POLLIN;
			} else {
				poll_fds[i].fd = INVALID_SOCKET;
				poll_fds[i].events = 0;
			}
		}
		err = k_mutex_unlock(&recv_proxy_buffer_mtx);
		if (err) {
			LOG_ERR("Unable to unlock recv_proxy_buffer_mtx");
		}
		
		ret = zsock_poll(poll_fds, ARRAY_SIZE(poll_fds), timeout);
		if (ret < 0) {  /* IO error */
			LOG_WRN("poll() error: %d, errno %d", ret, errno);
			continue;
		}
		if (ret == 0) {  /* timeout */
			continue;
		}
		for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) {
			LOG_DBG("sock %d events 0x%08x", poll_fds[i].fd, poll_fds[i].revents);
		}
		LOG_DBG("efd events 0x%08x", poll_fds[EVENT_FD].revents);
		// Check for POLLIN on all available sockets
		for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) {
			if ((poll_fds[i].revents & ZSOCK_POLLIN) != 0) {
				do_recv_proxy_recv_packet(i);
			}
			else if ((poll_fds[i].revents & ZSOCK_POLLERR) != 0) {
				int value;
				socklen_t len = sizeof(int);

				ret = zsock_getsockopt(poll_fds[i].fd, SOL_SOCKET, SO_ERROR, &value, &len);
				if (ret) {
					LOG_ERR("%d : getsockopt(SO_ERROR) error: %d", poll_fds[i].fd, -errno);
					ret = -EIO;
				} else {
					LOG_WRN("%d : POLLERR", poll_fds[i].fd);
					ret = -EIO;
				}
			}
			else if ((poll_fds[i].revents & ZSOCK_POLLHUP) != 0) {
				/* Lose LTE connection / remote end close */
				LOG_WRN("%d : POLLHUP", poll_fds[i].fd);
				ret = -ECONNRESET;
			}
		}
		/* Events from commands. */
		if ((poll_fds[EVENT_FD].revents & ZSOCK_POLLIN) != 0) {
			LOG_DBG("Terminate thread");
			ret = 0;
			break;
		}
	} while(1);

	safe_close_proxy_efd(efd);
	LOG_INF("Thread terminated");
}

Parents Reply Children
No Data
Related