diff --git a/src/conf.c b/src/conf.c index 349456d35..3c17ecb11 100644 --- a/src/conf.c +++ b/src/conf.c @@ -208,7 +208,7 @@ static const struct confparams frontend_cfg_params[] = { TOK_MULTICAST_CMD_PORT, "multicast_cmd_port", "Multicast command server UDP port", "Multicast data UDP port for sending commands to rig", - "4531", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } } + "4532", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } } }, { RIG_CONF_END, NULL, } diff --git a/src/event.c b/src/event.c index 5cdedc43c..c9f6ca9de 100644 --- a/src/event.c +++ b/src/event.c @@ -87,6 +87,10 @@ void *rig_poll_routine(void *arg) // Rig cache time should be equal to rig poll interval (should be set automatically by rigctld at least) rig_set_cache_timeout_ms(rig, HAMLIB_CACHE_ALL, rs->poll_interval); + // Attempt to detect changes with the interval below (in milliseconds) + int change_detection_interval = 50; + int interval_count = 0; + update_occurred = 0; while (rs->poll_routine_thread_run) @@ -333,9 +337,18 @@ void *rig_poll_routine(void *arg) { network_publish_rig_poll_data(rig); update_occurred = 0; + interval_count = 0; } - hl_usleep(rs->poll_interval * 1000); + hl_usleep(change_detection_interval * 1000); + interval_count++; + + // Publish updates every poll_interval if no changes have been detected + if (interval_count >= (rs->poll_interval / change_detection_interval)) + { + interval_count = 0; + network_publish_rig_poll_data(rig); + } } rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping rig poll routine thread\n", diff --git a/src/network.c b/src/network.c index 877ab510a..4d34527a9 100644 --- a/src/network.c +++ b/src/network.c @@ -1047,9 +1047,43 @@ void *multicast_receiver(void *arg) while (rs->multicast_receiver_run == 1) { - ssize_t result; struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); + fd_set rfds, efds; + struct timeval timeout; + int select_result; + ssize_t result; + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + FD_ZERO(&rfds); + FD_SET(socket_fd, &rfds); + efds = rfds; + + select_result = select(socket_fd + 1, &rfds, NULL, &efds, &timeout); + if (select_result == 0) + { + // Select timed out + continue; + } + + if (select_result < 0) + { + rig_debug(RIG_DEBUG_ERR, + "%s(): select() failed when reading UDP multicast socket data: %s\n", + __func__, + strerror(errno)); + + break; + } + + if (FD_ISSET(socket_fd, &efds)) + { + rig_debug(RIG_DEBUG_ERR, + "%s(): fd error when reading UDP multicast socket data\n", __func__); + break; + } result = recvfrom(socket_fd, data, sizeof(data), 0, (struct sockaddr *) &client_addr, &client_len); @@ -1057,9 +1091,8 @@ void *multicast_receiver(void *arg) { if (result < 0) { - if (errno == EAGAIN) + if (errno == 0 || errno == EAGAIN || errno == EWOULDBLOCK) { - hl_usleep(100 * 1000); continue; } rig_debug(RIG_DEBUG_ERR, "%s: error receiving from UDP socket %s:%d: %s\n", __func__, @@ -1128,13 +1161,6 @@ int network_multicast_publisher_start(RIG *rig, const char *multicast_addr, } socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - u_long mode = 1; // Enable non-blocking mode -#ifdef __MINGW32__ - ioctlsocket(socket_fd, FIONBIO, &mode); -#else - ioctl(socket_fd, FIONBIO, &mode); -#endif - if (socket_fd < 0) { @@ -1143,6 +1169,24 @@ int network_multicast_publisher_start(RIG *rig, const char *multicast_addr, RETURNFUNC(-RIG_EIO); } + // Enable non-blocking mode + u_long mode = 1; +#ifdef __MINGW32__ + if (ioctlsocket(socket_fd, FIONBIO, &mode) == SOCKET_ERROR) + { + rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__, + strerror(errno)); + RETURNFUNC(-RIG_EIO); + } +#else + if (ioctl(socket_fd, FIONBIO, &mode) < 0) + { + rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__, + strerror(errno)); + RETURNFUNC(-RIG_EIO); + } +#endif + if (items & RIG_MULTICAST_TRANSCEIVE) { rig_debug(RIG_DEBUG_VERBOSE, "%s(%d) MULTICAST_TRANSCEIVE enabled\n", __FILE__, @@ -1310,6 +1354,24 @@ int network_multicast_receiver_start(RIG *rig, const char *multicast_addr, int m RETURNFUNC(-RIG_EIO); } + // Enable non-blocking mode + u_long mode = 1; +#ifdef __MINGW32__ + if (ioctlsocket(socket_fd, FIONBIO, &mode) == SOCKET_ERROR) + { + rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__, + strerror(errno)); + RETURNFUNC(-RIG_EIO); + } +#else + if (ioctl(socket_fd, FIONBIO, &mode) < 0) + { + rig_debug(RIG_DEBUG_ERR, "%s: error enabling non-blocking mode for socket: %s", __func__, + strerror(errno)); + RETURNFUNC(-RIG_EIO); + } +#endif + rs->multicast_receiver_run = 1; rs->multicast_receiver_priv_data = calloc(1, sizeof(multicast_receiver_priv_data)); @@ -1371,6 +1433,11 @@ int network_multicast_receiver_stop(RIG *rig) // Close the socket first to stop the routine if (mcast_receiver_priv->args.socket_fd >= 0) { +#ifdef __MINGW32__ + shutdown(mcast_receiver_priv->args.socket_fd, SD_BOTH); +#else + shutdown(mcast_receiver_priv->args.socket_fd, SHUT_RDWR); +#endif close(mcast_receiver_priv->args.socket_fd); } diff --git a/src/rig.c b/src/rig.c index 1998ddfc6..1165c8c70 100644 --- a/src/rig.c +++ b/src/rig.c @@ -674,7 +674,7 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model) rs->multicast_data_addr = "224.0.0.1"; // enable multicast data publishing by default rs->multicast_data_port = 4532; rs->multicast_cmd_addr = "224.0.0.2"; // enable multicast command server by default - rs->multicast_cmd_port = 4531; + rs->multicast_cmd_port = 4532; rs->lo_freq = 0; rs->cache.timeout_ms = 500; // 500ms cache timeout by default rs->cache.ptt = 0;