Fix multicast receiver shutdown by using non-blocking sockets and select(). Use the same port number 4532 for both state snapshots and commands -- it is enough to have different multicast groups for them. Publish multicast state snapshots more often (change detection interval now set to 50ms), but at least at interval defined by poll_interval.

pull/1413/head
Mikael Nousiainen 2023-11-03 17:18:49 +02:00
rodzic 5b86d4efff
commit 41c891251f
4 zmienionych plików z 93 dodań i 13 usunięć

Wyświetl plik

@ -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, }

Wyświetl plik

@ -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",

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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;