static int poll_input(netplay_t *netplay, bool block) { bool had_input = false; int max_fd = netplay->fd + 1; struct timeval tv = {0}; tv.tv_sec = 0; tv.tv_usec = block ? (RETRY_MS * 1000) : 0; do { fd_set fds; /* select() does not take pointer to const struct timeval. * Technically possible for select() to modify tmp_tv, so * we go paranoia mode. */ struct timeval tmp_tv = tv; had_input = false; netplay->timeout_cnt++; FD_ZERO(&fds); FD_SET(netplay->fd, &fds); if (socket_select(max_fd, &fds, NULL, NULL, &tmp_tv) < 0) return -1; if (FD_ISSET(netplay->fd, &fds)) { /* If we're not ready for input, wait until we are. * Could fill the TCP buffer, stalling the other side. */ if (netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->read_ptr], netplay->read_frame_count)) { had_input = true; if (!netplay_get_cmd(netplay)) return -1; } } /* If we were blocked for input, pass if we have this frame's input */ if (block && netplay->read_frame_count > netplay->self_frame_count) break; /* If we had input, we might have more */ if (had_input || !block) continue; RARCH_LOG("Network is stalling at frame %u, count %u of %d ...\n", netplay->self_frame_count, netplay->timeout_cnt, MAX_RETRIES); if (netplay->timeout_cnt >= MAX_RETRIES && !netplay->remote_paused) return -1; } while (had_input || block); return 0; }
static int poll_input(netplay_t *netplay, bool block) { int max_fd = (netplay->fd > netplay->udp_fd ? netplay->fd : netplay->udp_fd) + 1; struct timeval tv = {0}; tv.tv_sec = 0; tv.tv_usec = block ? (RETRY_MS * 1000) : 0; do { fd_set fds; /* select() does not take pointer to const struct timeval. * Technically possible for select() to modify tmp_tv, so * we go paranoia mode. */ struct timeval tmp_tv = tv; netplay->timeout_cnt++; FD_ZERO(&fds); FD_SET(netplay->udp_fd, &fds); FD_SET(netplay->fd, &fds); if (socket_select(max_fd, &fds, NULL, NULL, &tmp_tv) < 0) return -1; /* Somewhat hacky, * but we aren't using the TCP connection for anything useful atm. */ if (FD_ISSET(netplay->fd, &fds) && !netplay_get_cmd(netplay)) return -1; if (FD_ISSET(netplay->udp_fd, &fds)) return 1; if (!block) continue; if (!send_chunk(netplay)) { warn_hangup(); netplay->has_connection = false; return -1; } RARCH_LOG("Network is stalling, resending packet... Count %u of %d ...\n", netplay->timeout_cnt, MAX_RETRIES); } while ((netplay->timeout_cnt < MAX_RETRIES) && block); if (block) return -1; return 0; }
static int poll_input(netplay_t *handle, bool block) { int max_fd = (handle->fd > handle->udp_fd ? handle->fd : handle->udp_fd) + 1; struct timeval tv = {0}; tv.tv_sec = 0; tv.tv_usec = block ? (RETRY_MS * 1000) : 0; do { handle->timeout_cnt++; // select() does not take pointer to const struct timeval. // Technically possible for select() to modify tmp_tv, so we go paranoia mode. struct timeval tmp_tv = tv; fd_set fds; FD_ZERO(&fds); FD_SET(handle->udp_fd, &fds); FD_SET(handle->fd, &fds); if (select(max_fd, &fds, NULL, NULL, &tmp_tv) < 0) return -1; // Somewhat hacky, // but we aren't using the TCP connection for anything useful atm. if (FD_ISSET(handle->fd, &fds) && !netplay_get_cmd(handle)) return -1; if (FD_ISSET(handle->udp_fd, &fds)) return 1; if (block && !send_chunk(handle)) { warn_hangup(); handle->has_connection = false; return -1; } if (block) { RARCH_LOG("Network is stalling, resending packet... Count %u of %d ...\n", handle->timeout_cnt, MAX_RETRIES); } } while ((handle->timeout_cnt < MAX_RETRIES) && block); if (block) return -1; return 0; }