diff --git a/command.c b/command.c index a3d5dd3663..da70fe0395 100644 --- a/command.c +++ b/command.c @@ -180,35 +180,21 @@ static void network_command_free(command_t *handle) static void command_network_poll(command_t *handle) { - fd_set fds; - struct timeval tmp_tv = {0}; - command_network_t *netcmd = (command_network_t*)handle->userptr; + ssize_t ret; + char buf[2048]; + command_network_t *netcmd = (command_network_t*)handle->userptr; if (netcmd->net_fd < 0) return; - FD_ZERO(&fds); - FD_SET(netcmd->net_fd, &fds); - - if (socket_select(netcmd->net_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0) - return; - - if (!FD_ISSET(netcmd->net_fd, &fds)) - return; - for (;;) { - ssize_t ret; - char buf[1024]; - - buf[0] = '\0'; - netcmd->cmd_source_len = sizeof(struct sockaddr_storage); - ret = recvfrom(netcmd->net_fd, buf, sizeof(buf) - 1, 0, - (struct sockaddr*)&netcmd->cmd_source, - &netcmd->cmd_source_len); + netcmd->cmd_source_len = sizeof(netcmd->cmd_source); + ret = recvfrom(netcmd->net_fd, buf, sizeof(buf) - 1, 0, + (struct sockaddr*)&netcmd->cmd_source, &netcmd->cmd_source_len); if (ret <= 0) - break; + return; buf[ret] = '\0'; @@ -431,71 +417,58 @@ static void uds_command_free(command_t *handle) static void command_uds_poll(command_t *handle) { int i; - fd_set fds; - command_uds_t *udscmd = (command_uds_t*)handle->userptr; - int maxfd = udscmd->sfd; - struct timeval tmp_tv = {0}; + int fd; + ssize_t ret; + char buf[2048]; + command_uds_t *udscmd = (command_uds_t*)handle->userptr; if (udscmd->sfd < 0) return; - FD_ZERO(&fds); - FD_SET(udscmd->sfd, &fds); - - for (i = 0; i < MAX_USER_CONNECTIONS; i++) - { - if (udscmd->userfd[i] >= 0) - { - maxfd = MAX(udscmd->userfd[i], maxfd); - FD_SET(udscmd->userfd[i], &fds); - } - } - - if (socket_select(maxfd + 1, &fds, NULL, NULL, &tmp_tv) <= 0) - return; - /* Read data from clients and process commands */ for (i = 0; i < MAX_USER_CONNECTIONS; i++) { - if (udscmd->userfd[i] >= 0 && FD_ISSET(udscmd->userfd[i], &fds)) + bool err = false; + + fd = udscmd->userfd[i]; + if (fd < 0) + continue; + + ret = socket_receive_all_nonblocking(fd, &err, buf, sizeof(buf) - 1); + if (!ret) + continue; + + if (!err) { - while (1) - { - char buf[2048]; - ssize_t ret = recv(udscmd->userfd[i], buf, sizeof(buf) - 1, 0); + buf[ret] = '\0'; + udscmd->last_fd = fd; - if (ret < 0) - break; /* no more data */ - if (!ret) - { - socket_close(udscmd->userfd[i]); - udscmd->userfd[i] = -1; - break; - } - - buf[ret] = 0; - udscmd->last_fd = udscmd->userfd[i]; - command_parse_msg(handle, buf); - } + command_parse_msg(handle, buf); + } + else + { + socket_close(fd); + udscmd->userfd[i] = -1; } } - if (FD_ISSET(udscmd->sfd, &fds)) + /* Accepts new connections from clients */ + fd = accept(udscmd->sfd, NULL, NULL); + if (fd >= 0) { - /* Accepts new connections from clients */ - int cfd = accept(udscmd->sfd, NULL, NULL); - if (cfd >= 0) { - if (!socket_nonblock(cfd)) - socket_close(cfd); - else { - for (i = 0; i < MAX_USER_CONNECTIONS; i++) - if (udscmd->userfd[i] < 0) - { - udscmd->userfd[i] = cfd; - break; - } + if (socket_nonblock(fd)) + { + for (i = 0; i < MAX_USER_CONNECTIONS; i++) + { + if (udscmd->userfd[i] < 0) + { + udscmd->userfd[i] = fd; + return; + } } } + + socket_close(fd); } } diff --git a/libretro-common/include/net/net_socket.h b/libretro-common/include/net/net_socket.h index 37b91d9b86..6df9a8bd6b 100644 --- a/libretro-common/include/net/net_socket.h +++ b/libretro-common/include/net/net_socket.h @@ -84,7 +84,7 @@ bool socket_send_all_blocking(int fd, const void *data_, size_t size, bool no_si bool socket_send_all_blocking_with_timeout(int fd, const void *data_, size_t size, - unsigned timeout, bool no_signal); + int timeout, bool no_signal); ssize_t socket_send_all_nonblocking(int fd, const void *data_, size_t size, bool no_signal); @@ -93,7 +93,7 @@ bool socket_receive_all_blocking(int fd, void *data_, size_t size); bool socket_receive_all_blocking_with_timeout(int fd, void *data_, size_t size, - unsigned timeout); + int timeout); ssize_t socket_receive_all_nonblocking(int fd, bool *error, void *data_, size_t size); @@ -102,7 +102,7 @@ bool socket_bind(int fd, void *data); int socket_connect(int fd, void *data, bool timeout_enable); -bool socket_connect_with_timeout(int fd, void *data, unsigned timeout); +bool socket_connect_with_timeout(int fd, void *data, int timeout); int socket_create( const char *name, diff --git a/libretro-common/net/net_compat.c b/libretro-common/net/net_compat.c index bce6d6c0c1..0b2f9f0f72 100644 --- a/libretro-common/net/net_compat.c +++ b/libretro-common/net/net_compat.c @@ -91,7 +91,6 @@ struct in_addr }; static void *_net_compat_net_memory = NULL; -int retro_epoll_fd = -1; char *inet_ntoa(struct SceNetInAddr in) { @@ -352,17 +351,15 @@ bool network_init(void) SceNetInitParam param; _net_compat_net_memory = malloc(COMPAT_NET_INIT_SIZE); + if (!_net_compat_net_memory) + goto failure; param.memory = _net_compat_net_memory; param.size = COMPAT_NET_INIT_SIZE; param.flags = 0; if (sceNetInit(¶m) < 0) goto failure; - - sceNetCtlInit(); - - retro_epoll_fd = sceNetEpollCreate("epoll", 0); - if (retro_epoll_fd < 0) + if (sceNetCtlInit() < 0) goto failure; } #elif defined(GEKKO) @@ -427,12 +424,6 @@ void network_deinit(void) netFinalizeNetwork(); sysModuleUnload(SYSMODULE_NET); #elif defined(VITA) - if (retro_epoll_fd >= 0) - { - sceNetEpollDestroy(retro_epoll_fd); - retro_epoll_fd = -1; - } - sceNetCtlTerm(); sceNetTerm(); diff --git a/libretro-common/net/net_socket.c b/libretro-common/net/net_socket.c index bba2013ab9..4aefda0c17 100644 --- a/libretro-common/net/net_socket.c +++ b/libretro-common/net/net_socket.c @@ -28,10 +28,6 @@ #include #endif -#ifdef GEKKO -#include -#endif - #include #include @@ -128,13 +124,13 @@ bool socket_receive_all_blocking(int fd, void *data_, size_t size) bool socket_receive_all_blocking_with_timeout(int fd, void *data_, size_t size, - unsigned timeout) + int timeout) { const uint8_t *data = (const uint8_t*)data_; retro_time_t deadline = cpu_features_get_time_usec(); - if (timeout) - deadline += (retro_time_t)timeout * 1000000; + if (timeout > 0) + deadline += (retro_time_t)timeout * 1000; else deadline += 5000000; @@ -147,23 +143,17 @@ bool socket_receive_all_blocking_with_timeout(int fd, if (ret < 0) { - retro_time_t time_delta; - fd_set fds; - struct timeval tv; + int _timeout; + bool ready = true; if (!isagain((int)ret)) return false; - time_delta = deadline - cpu_features_get_time_usec(); - - if (time_delta <= 0) + _timeout = (int)((deadline - cpu_features_get_time_usec()) / 1000); + if (_timeout <= 0) return false; - FD_ZERO(&fds); - FD_SET(fd, &fds); - tv.tv_sec = (unsigned)(time_delta / 1000000); - tv.tv_usec = (unsigned)(time_delta % 1000000); - if (socket_select(fd + 1, &fds, NULL, NULL, &tv) <= 0) + if (!socket_wait(fd, &ready, NULL, _timeout) || !ready) return false; } else @@ -568,14 +558,14 @@ bool socket_send_all_blocking(int fd, const void *data_, size_t size, bool socket_send_all_blocking_with_timeout(int fd, const void *data_, size_t size, - unsigned timeout, bool no_signal) + int timeout, bool no_signal) { const uint8_t *data = (const uint8_t*)data_; int flags = no_signal ? MSG_NOSIGNAL : 0; retro_time_t deadline = cpu_features_get_time_usec(); - if (timeout) - deadline += (retro_time_t)timeout * 1000000; + if (timeout > 0) + deadline += (retro_time_t)timeout * 1000; else deadline += 5000000; @@ -588,23 +578,17 @@ bool socket_send_all_blocking_with_timeout(int fd, if (ret < 0) { - retro_time_t time_delta; - fd_set fds; - struct timeval tv; + int _timeout; + bool ready = true; if (!isagain((int)ret)) return false; - time_delta = deadline - cpu_features_get_time_usec(); - - if (time_delta <= 0) + _timeout = (int)((deadline - cpu_features_get_time_usec()) / 1000); + if (_timeout <= 0) return false; - FD_ZERO(&fds); - FD_SET(fd, &fds); - tv.tv_sec = (unsigned)(time_delta / 1000000); - tv.tv_usec = (unsigned)(time_delta % 1000000); - if (socket_select(fd + 1, NULL, &fds, NULL, &tv) <= 0) + if (!socket_wait(fd, NULL, &ready, _timeout) || !ready) return false; } else @@ -698,7 +682,7 @@ int socket_connect(int fd, void *data, bool timeout_enable) return connect(fd, addr->ai_addr, addr->ai_addrlen); } -bool socket_connect_with_timeout(int fd, void *data, unsigned timeout) +bool socket_connect_with_timeout(int fd, void *data, int timeout) { int res; struct addrinfo *addr = (struct addrinfo*)data; @@ -728,20 +712,15 @@ bool socket_connect_with_timeout(int fd, void *data, unsigned timeout) res = connect(fd, addr->ai_addr, addr->ai_addrlen); if (res) { - fd_set wfd, efd; - struct timeval tv = {0}; + bool ready = true; if (!isinprogress(res) && !isagain(res)) return false; - FD_ZERO(&wfd); - FD_ZERO(&efd); - FD_SET(fd, &wfd); - FD_SET(fd, &efd); - tv.tv_sec = timeout ? timeout : 5; - if (socket_select(fd + 1, NULL, &wfd, &efd, &tv) <= 0) - return false; - if (FD_ISSET(fd, &efd)) + if (timeout <= 0) + timeout = 5000; + + if (!socket_wait(fd, NULL, &ready, timeout) || !ready) return false; } diff --git a/network/natt.c b/network/natt.c index 92736c6d3a..e0a51883b8 100644 --- a/network/natt.c +++ b/network/natt.c @@ -16,11 +16,11 @@ #include #include +#include #include #include -#include -#include +#include #ifndef HAVE_SOCKET_LEGACY #include @@ -161,12 +161,10 @@ done: bool natt_device_next(struct natt_discovery *discovery, struct natt_device *device) { - fd_set fds; char buf[2048]; ssize_t recvd; char *data; size_t remaining; - struct timeval tv = {0}; socklen_t addr_size = sizeof(device->addr); if (!discovery || !device) @@ -183,19 +181,16 @@ bool natt_device_next(struct natt_discovery *discovery, *device->service_type = '\0'; device->busy = false; - /* Check our file descriptor to see if a device sent data to it. */ - FD_ZERO(&fds); - FD_SET(discovery->fd, &fds); - if (socket_select(discovery->fd + 1, &fds, NULL, NULL, &tv) < 0) - return false; - /* If there was no data, check for timeout. */ - if (!FD_ISSET(discovery->fd, &fds)) - return cpu_features_get_time_usec() < discovery->timeout; - recvd = recvfrom(discovery->fd, buf, sizeof(buf), 0, - (struct sockaddr *) &device->addr, &addr_size); + (struct sockaddr*)&device->addr, &addr_size); if (recvd < 0) + { + /* If there was no data, check for timeout. */ + if (isagain((int)recvd)) + return cpu_features_get_time_usec() < discovery->timeout; + return false; + } /* Zero-length datagrams are valid, but we can't do anything with them. Don't treat them as an error. */ if (!recvd) @@ -204,12 +199,14 @@ bool natt_device_next(struct natt_discovery *discovery, /* Parse the data we received. We are only looking for the 'Location' HTTP header. */ data = buf; - remaining = (size_t) recvd; + remaining = (size_t)recvd; do { - char *lnbreak = (char *) memchr(data, '\n', remaining); + char *lnbreak = (char*)memchr(data, '\n', remaining); + if (!lnbreak) break; + *lnbreak++ = '\0'; /* This also gets rid of any trailing carriage return. */ @@ -230,7 +227,7 @@ bool natt_device_next(struct natt_discovery *discovery, } } - remaining -= (size_t) lnbreak - (size_t) data; + remaining -= (size_t)lnbreak - (size_t)data; data = lnbreak; } while (remaining); diff --git a/network/netplay/netplay.h b/network/netplay/netplay.h index 22438ccc90..46a0ad8897 100644 --- a/network/netplay/netplay.h +++ b/network/netplay/netplay.h @@ -26,12 +26,12 @@ #include #include -#include - #ifdef HAVE_CONFIG_H #include "../../config.h" #endif +#include + #include "../../retroarch_types.h" #include "../natt.h" diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 7f6155dc28..3714ec3d65 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -27,6 +27,10 @@ #include #include +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + #include #include #include @@ -303,24 +307,20 @@ static bool netplay_lan_ad_client_response(void) /* Check for any ad queries */ for (;;) { - fd_set fds; - struct timeval tv = {0}; + bool has_data = true; struct sockaddr_storage their_addr = {0}; socklen_t addr_size = sizeof(their_addr); - FD_ZERO(&fds); - FD_SET(net_st->lan_ad_client_fd, &fds); - tv.tv_usec = 500000; - if (socket_select(net_st->lan_ad_client_fd + 1, - &fds, NULL, NULL, &tv) <= 0) + if (!socket_wait(net_st->lan_ad_client_fd, &has_data, NULL, 500) || + !has_data) break; /* Somebody queried, so check that it's valid */ if (recvfrom(net_st->lan_ad_client_fd, - (char *) &net_st->ad_packet_buffer, - sizeof(net_st->ad_packet_buffer), 0, - (struct sockaddr *) &their_addr, - &addr_size) == sizeof(net_st->ad_packet_buffer)) + (char*)&net_st->ad_packet_buffer, sizeof(net_st->ad_packet_buffer), + 0, + (struct sockaddr*)&their_addr, &addr_size) == + sizeof(net_st->ad_packet_buffer)) { char address[256]; struct netplay_host *host = NULL; @@ -343,23 +343,20 @@ static bool netplay_lan_ad_client_response(void) continue; #endif - if (!netplay_is_lan_address( - (struct sockaddr_in *) &their_addr)) + if (!netplay_is_lan_address((struct sockaddr_in*)&their_addr)) continue; #ifndef HAVE_SOCKET_LEGACY - if (getnameinfo((struct sockaddr *) - &their_addr, sizeof(their_addr), + if (getnameinfo((struct sockaddr*)&their_addr, sizeof(their_addr), address, sizeof(address), NULL, 0, NI_NUMERICHOST)) continue; #else /* We need to convert the address manually */ { - uint8_t *addr8 = (uint8_t *) - &((struct sockaddr_in *) &their_addr)->sin_addr; - snprintf(address, sizeof(address), - "%d.%d.%d.%d", + uint8_t *addr8 = + (uint8_t*)&((struct sockaddr_in*)&their_addr)->sin_addr; + snprintf(address, sizeof(address), "%d.%d.%d.%d", (int)addr8[0], (int)addr8[1], (int)addr8[2], (int)addr8[3]); } @@ -377,14 +374,14 @@ static bool netplay_lan_ad_client_response(void) allocated *= 2; if (net_st->discovered_hosts.hosts) - new_hosts = (struct netplay_host *) - realloc(net_st->discovered_hosts.hosts, allocated * sizeof(struct - netplay_host)); + new_hosts = (struct netplay_host*)realloc( + net_st->discovered_hosts.hosts, + allocated * sizeof(struct netplay_host)); else /* Should be equivalent to realloc, * but I don't trust screwy libcs */ - new_hosts = (struct netplay_host *) - malloc(allocated * sizeof(struct netplay_host)); + new_hosts = (struct netplay_host*)malloc( + allocated * sizeof(struct netplay_host)); if (!new_hosts) return false; @@ -399,29 +396,21 @@ static bool netplay_lan_ad_client_response(void) /* Copy in the response */ host->content_crc = (int)ntohl(net_st->ad_packet_buffer.content_crc); host->port = (int)ntohl(net_st->ad_packet_buffer.port); - strlcpy(host->address, - address, - sizeof(host->address)); - strlcpy(host->nick, - net_st->ad_packet_buffer.nick, + strlcpy(host->address, address, sizeof(host->address)); + strlcpy(host->nick, net_st->ad_packet_buffer.nick, sizeof(host->nick)); - strlcpy(host->frontend, - net_st->ad_packet_buffer.frontend, + strlcpy(host->frontend, net_st->ad_packet_buffer.frontend, sizeof(host->frontend)); - strlcpy(host->core, - net_st->ad_packet_buffer.core, + strlcpy(host->core, net_st->ad_packet_buffer.core, sizeof(host->core)); - strlcpy(host->core_version, - net_st->ad_packet_buffer.core_version, + strlcpy(host->core_version, net_st->ad_packet_buffer.core_version, sizeof(host->core_version)); strlcpy(host->retroarch_version, net_st->ad_packet_buffer.retroarch_version, sizeof(host->retroarch_version)); - strlcpy(host->content, - net_st->ad_packet_buffer.content, + strlcpy(host->content, net_st->ad_packet_buffer.content, sizeof(host->content)); - strlcpy(host->subsystem_name, - net_st->ad_packet_buffer.subsystem_name, + strlcpy(host->subsystem_name, net_st->ad_packet_buffer.subsystem_name, sizeof(host->subsystem_name)); has_password = ntohl(net_st->ad_packet_buffer.has_password); host->has_password = (has_password & 1) ? true : false; @@ -513,30 +502,28 @@ static void deinit_lan_ad_server_socket(void) */ static bool netplay_lan_ad_server(netplay_t *netplay) { - fd_set fds; + ssize_t ret; uint32_t header; - struct timeval tv = {0}; struct sockaddr_storage their_addr = {0}; socklen_t addr_size = sizeof(their_addr); net_driver_state_t *net_st = &networking_driver_st; /* Check for any ad queries */ - FD_ZERO(&fds); - FD_SET(net_st->lan_ad_server_fd, &fds); - if (socket_select(net_st->lan_ad_server_fd + 1, - &fds, NULL, NULL, &tv) < 0) + ret = recvfrom(net_st->lan_ad_server_fd, + (char*)&header, sizeof(header), 0, + (struct sockaddr*)&their_addr, &addr_size); + if (ret < 0) { + if (isagain((int)ret)) + return true; + deinit_lan_ad_server_socket(); + return false; } - if (!FD_ISSET(net_st->lan_ad_server_fd, &fds)) - return true; /* Somebody queried, so check that it's valid */ - if (recvfrom(net_st->lan_ad_server_fd, - (char *) &header, sizeof(header), 0, - (struct sockaddr *) &their_addr, - &addr_size) == sizeof(header)) + if (ret == sizeof(header)) { const frontend_ctx_driver_t *frontend_drv; char frontend_architecture_tmp[24]; @@ -564,15 +551,13 @@ static bool netplay_lan_ad_server(netplay_t *netplay) return true; #endif - if (!netplay_is_lan_address( - (struct sockaddr_in *) &their_addr)) + if (!netplay_is_lan_address((struct sockaddr_in*)&their_addr)) return true; RARCH_LOG("[Discovery] Query received on LAN interface.\n"); /* Now build our response */ - memset(&net_st->ad_packet_buffer, 0, - sizeof(net_st->ad_packet_buffer)); + memset(&net_st->ad_packet_buffer, 0, sizeof(net_st->ad_packet_buffer)); net_st->ad_packet_buffer.header = htonl(DISCOVERY_RESPONSE_MAGIC); @@ -582,27 +567,22 @@ static bool netplay_lan_ad_server(netplay_t *netplay) sizeof(net_st->ad_packet_buffer.nick)); frontend_drv = - (const frontend_ctx_driver_t*) frontend_driver_get_cpu_architecture_str( + (const frontend_ctx_driver_t*)frontend_driver_get_cpu_architecture_str( frontend_architecture_tmp, sizeof(frontend_architecture_tmp)); if (frontend_drv) snprintf(net_st->ad_packet_buffer.frontend, sizeof(net_st->ad_packet_buffer.frontend), - "%s %s", - frontend_drv->ident, frontend_architecture_tmp); + "%s %s", frontend_drv->ident, frontend_architecture_tmp); else - strlcpy(net_st->ad_packet_buffer.frontend, - "N/A", + strlcpy(net_st->ad_packet_buffer.frontend, "N/A", sizeof(net_st->ad_packet_buffer.frontend)); - strlcpy(net_st->ad_packet_buffer.core, - system->library_name, + strlcpy(net_st->ad_packet_buffer.core, system->library_name, sizeof(net_st->ad_packet_buffer.core)); - strlcpy(net_st->ad_packet_buffer.core_version, - system->library_version, + strlcpy(net_st->ad_packet_buffer.core_version, system->library_version, sizeof(net_st->ad_packet_buffer.core_version)); - strlcpy(net_st->ad_packet_buffer.retroarch_version, - PACKAGE_VERSION, + strlcpy(net_st->ad_packet_buffer.retroarch_version, PACKAGE_VERSION, sizeof(net_st->ad_packet_buffer.retroarch_version)); if (subsystem && subsystem->size > 0) @@ -613,7 +593,8 @@ static bool netplay_lan_ad_server(netplay_t *netplay) buf[0] = '\0'; for (i = 0;;) { - strlcat(buf, path_basename(subsystem->elems[i++].data), sizeof(buf)); + strlcat(buf, path_basename(subsystem->elems[i++].data), + sizeof(buf)); if (i >= subsystem->size) break; strlcat(buf, "|", sizeof(buf)); @@ -650,9 +631,8 @@ static bool netplay_lan_ad_server(netplay_t *netplay) /* Send our response */ sendto(net_st->lan_ad_server_fd, - (char *) &net_st->ad_packet_buffer, - sizeof(net_st->ad_packet_buffer), - 0, (struct sockaddr *) &their_addr, sizeof(their_addr)); + (char*)&net_st->ad_packet_buffer, sizeof(net_st->ad_packet_buffer), + 0, (struct sockaddr*)&their_addr, sizeof(their_addr)); } return true; @@ -2525,34 +2505,33 @@ static bool netplay_full(netplay_t *netplay, int sockfd) unsigned max_connections = settings->uints.netplay_max_connections; unsigned total = 0; - if (max_connections) + if (!max_connections || max_connections >= MAX_CLIENTS) + max_connections = MAX_CLIENTS - 1; + + for (i = 0; i < netplay->connections_size; i++) + if (netplay->connections[i].active) total++; + + if (total >= max_connections) { - for (i = 0; i < netplay->connections_size; i++) - if (netplay->connections[i].active) total++; + /* We send a header to let the client + know we are full */ + uint32_t header[6]; - if (total >= max_connections) - { - /* We send a header to let the client - know we are full */ - uint32_t header[6]; + /* The only parameter that we need to set is + netplay magic; + we set the protocol version parameter + too for backwards compatibility */ + memset(header, 0, sizeof(header)); + header[0] = htonl(FULL_MAGIC); + header[4] = htonl(HIGH_NETPLAY_PROTOCOL_VERSION); - /* The only parameter that we need to set is - netplay magic; - we set the protocol version parameter - too for backwards compatibility */ - memset(header, 0, sizeof(header)); - header[0] = htonl(FULL_MAGIC); - header[4] = htonl(HIGH_NETPLAY_PROTOCOL_VERSION); + /* The kernel might close the socket before + sending our data. + This is fine; the header is just a warning + for the client. */ + socket_send_all_nonblocking(sockfd, header, sizeof(header), true); - /* The kernel might close the socket before - sending our data. - This is fine; the header is just a warning - for the client. */ - socket_send_all_nonblocking(sockfd, header, - sizeof(header), true); - - return true; - } + return true; } return false; @@ -3142,50 +3121,33 @@ static void netplay_handle_frame_hash(netplay_t *netplay, */ static int handle_connection(netplay_t *netplay, bool *error) { - fd_set fds; - int result; - struct timeval tv = {0}; - int new_fd = -1; + int new_fd; + struct sockaddr_storage their_addr; + socklen_t addr_size = sizeof(their_addr); - FD_ZERO(&fds); - FD_SET(netplay->listen_fd, &fds); - - /* Check for a connection */ - result = socket_select(netplay->listen_fd + 1, &fds, NULL, NULL, &tv); - - if (result < 0) - goto critical_failure; - - if (result) + new_fd = accept(netplay->listen_fd, + (struct sockaddr*)&their_addr, &addr_size); + if (new_fd < 0) { - struct sockaddr_storage their_addr; - socklen_t addr_size = sizeof(their_addr); + if (!isagain(new_fd)) + *error = true; - new_fd = accept(netplay->listen_fd, - (struct sockaddr*) &their_addr, &addr_size); - - if (new_fd >= 0) - { - /* Set the socket nonblocking */ - if (!socket_nonblock(new_fd)) - goto critical_failure; - - SET_TCP_NODELAY(new_fd) - SET_FD_CLOEXEC(new_fd) - } - else - goto critical_failure; + return -1; } - return new_fd; - -critical_failure: - if (new_fd >= 0) + /* Set the socket nonblocking */ + if (!socket_nonblock(new_fd)) + { socket_close(new_fd); + *error = true; - *error = true; + return -1; + } - return -1; + SET_TCP_NODELAY(new_fd) + SET_FD_CLOEXEC(new_fd) + + return new_fd; } static bool netplay_tunnel_connect(int fd, const struct addrinfo *addr) @@ -3198,7 +3160,7 @@ static bool netplay_tunnel_connect(int fd, const struct addrinfo *addr) SET_TCP_NODELAY(fd) SET_FD_CLOEXEC(fd) - result = socket_connect(fd, (void*) addr, false); + result = socket_connect(fd, (void*)addr, false); if (result && !isinprogress(result) && !isagain(result)) return false; @@ -3221,40 +3183,34 @@ static bool netplay_tunnel_connect(int fd, const struct addrinfo *addr) */ static int handle_mitm_connection(netplay_t *netplay, bool *error) { - size_t i; - void* recv_buf; - size_t recv_len; - ssize_t recvd; + size_t i; + void* recv_buf; + size_t recv_len; + ssize_t recvd; int new_fd = -1; retro_time_t ctime = cpu_features_get_time_usec(); - /* We want to call select individually in order to handle errors on a per - connection basis. */ for (i = 0; i < NETPLAY_MITM_MAX_PENDING; i++) { int fd = netplay->mitm_pending->fds[i]; + if (fd >= 0) { - fd_set wfd, efd; - struct timeval tv = {0}; + bool ready = true; - FD_ZERO(&wfd); - FD_ZERO(&efd); - FD_SET(fd, &wfd); - FD_SET(fd, &efd); - - if (socket_select(fd + 1, NULL, &wfd, &efd, &tv) < 0 || - FD_ISSET(fd, &efd)) + if (!socket_wait(fd, NULL, &ready, 0)) { /* Error */ RARCH_ERR("[Netplay] Tunnel link connection failed.\n"); } - else if (FD_ISSET(fd, &wfd)) + else if (ready) { /* Connection is ready. Send the linking id. */ mitm_id_t *lid = &netplay->mitm_pending->ids[i]; - if (socket_send_all_nonblocking(fd, lid, sizeof(*lid), true) == sizeof(*lid)) + + if (socket_send_all_nonblocking(fd, lid, sizeof(*lid), true) == + sizeof(*lid)) { new_fd = fd; RARCH_LOG("[Netplay] Tunnel link connection completed.\n"); @@ -3272,8 +3228,10 @@ static int handle_mitm_connection(netplay_t *netplay, bool *error) { /* Check if the connection timeouted. */ retro_time_t timeout = netplay->mitm_pending->timeouts[i]; + if (ctime < timeout) continue; + RARCH_ERR("[Netplay] Tunnel link connection timeout.\n"); } @@ -3282,9 +3240,10 @@ static int handle_mitm_connection(netplay_t *netplay, bool *error) } } - recv_buf = (void*) ((size_t) &netplay->mitm_pending->id_buf + - netplay->mitm_pending->id_recvd); - if (netplay->mitm_pending->id_recvd < sizeof(netplay->mitm_pending->id_buf.magic)) + recv_buf = ((uint8_t*)&netplay->mitm_pending->id_buf) + + netplay->mitm_pending->id_recvd; + if (netplay->mitm_pending->id_recvd < + sizeof(netplay->mitm_pending->id_buf.magic)) recv_len = sizeof(netplay->mitm_pending->id_buf.magic) - netplay->mitm_pending->id_recvd; else @@ -3301,55 +3260,59 @@ static int handle_mitm_connection(netplay_t *netplay, bool *error) } netplay->mitm_pending->id_recvd += recvd; - if (netplay->mitm_pending->id_recvd >= sizeof(netplay->mitm_pending->id_buf.magic)) + if (netplay->mitm_pending->id_recvd >= + sizeof(netplay->mitm_pending->id_buf.magic)) { switch (ntohl(netplay->mitm_pending->id_buf.magic)) { case MITM_LINK_MAGIC: { - if (netplay->mitm_pending->id_recvd == sizeof(netplay->mitm_pending->id_buf)) - { - netplay->mitm_pending->id_recvd = 0; + if (netplay->mitm_pending->id_recvd < + sizeof(netplay->mitm_pending->id_buf)) + break; - /* Find a free spot to allocate this connection. */ - for (i = 0; i < NETPLAY_MITM_MAX_PENDING; i++) - if (netplay->mitm_pending->fds[i] < 0) - break; - if (i < NETPLAY_MITM_MAX_PENDING) + netplay->mitm_pending->id_recvd = 0; + + /* Find a free spot to allocate this connection. */ + for (i = 0; i < NETPLAY_MITM_MAX_PENDING; i++) + if (netplay->mitm_pending->fds[i] < 0) + break; + if (i < NETPLAY_MITM_MAX_PENDING) + { + int fd = socket( + netplay->mitm_pending->addr->ai_family, + netplay->mitm_pending->addr->ai_socktype, + netplay->mitm_pending->addr->ai_protocol + ); + + if (fd >= 0) { - int fd = socket( - netplay->mitm_pending->addr->ai_family, - netplay->mitm_pending->addr->ai_socktype, - netplay->mitm_pending->addr->ai_protocol - ); - if (fd >= 0) + if (netplay_tunnel_connect(fd, netplay->mitm_pending->addr)) { - if (netplay_tunnel_connect(fd, netplay->mitm_pending->addr)) - { - netplay->mitm_pending->fds[i] = fd; - memcpy(&netplay->mitm_pending->ids[i], - &netplay->mitm_pending->id_buf, - sizeof(*netplay->mitm_pending->ids)); - /* 30 seconds */ - netplay->mitm_pending->timeouts[i] = ctime + 30000000; - RARCH_LOG("[Netplay] Queued tunnel link connection.\n"); - } - else - { - socket_close(fd); - RARCH_ERR("[Netplay] Failed to connect to tunnel server.\n"); - } + netplay->mitm_pending->fds[i] = fd; + memcpy(&netplay->mitm_pending->ids[i], + &netplay->mitm_pending->id_buf, + sizeof(*netplay->mitm_pending->ids)); + /* 30 seconds */ + netplay->mitm_pending->timeouts[i] = ctime + 30000000; + RARCH_LOG("[Netplay] Queued tunnel link connection.\n"); } else { - RARCH_ERR("[Netplay] Failed to create socket for tunnel link connection.\n"); + socket_close(fd); + RARCH_ERR("[Netplay] Failed to connect to tunnel server.\n"); } } else { - RARCH_WARN("[Netplay] Cannot create more tunnel link connections.\n"); + RARCH_ERR("[Netplay] Failed to create socket for tunnel link connection.\n"); } } + else + { + RARCH_WARN("[Netplay] Cannot create any more tunnel link connections.\n"); + } + break; } case MITM_PING_MAGIC: @@ -3369,10 +3332,10 @@ static int handle_mitm_connection(netplay_t *netplay, bool *error) } break; - } - default: - RARCH_ERR("[Netplay] Received unknown magic from tunnel server.\n"); - goto critical_failure; + } + default: + RARCH_ERR("[Netplay] Received unknown magic from tunnel server.\n"); + goto critical_failure; } } @@ -6095,19 +6058,8 @@ shrt: */ int netplay_poll_net_input(netplay_t *netplay, bool block) { - bool had_input = false; - int max_fd = 0; size_t i; - - for (i = 0; i < netplay->connections_size; i++) - { - struct netplay_connection *connection = &netplay->connections[i]; - if (connection->active && connection->fd >= max_fd) - max_fd = connection->fd + 1; - } - - if (max_fd == 0) - return 0; + bool had_input; netplay->timeout_cnt = 0; @@ -6115,14 +6067,14 @@ int netplay_poll_net_input(netplay_t *netplay, bool block) { had_input = false; - netplay->timeout_cnt++; - /* Read input from each connection */ for (i = 0; i < netplay->connections_size; i++) { struct netplay_connection *connection = &netplay->connections[i]; - if (connection->active && !netplay_get_cmd(netplay, connection, &had_input)) - netplay_hangup(netplay, connection); + + if (connection->active) + if (!netplay_get_cmd(netplay, connection, &had_input)) + netplay_hangup(netplay, connection); } if (block) @@ -6136,29 +6088,70 @@ int netplay_poll_net_input(netplay_t *netplay, bool block) /* If we're supposed to block but we didn't have enough input, wait for it */ if (!had_input) { +#ifdef NETWORK_HAVE_POLL + struct pollfd fds[MAX_CLIENTS]; + unsigned nfds = 0; +#else fd_set fds; + int max_fd = -1; struct timeval tv = {0}; - tv.tv_usec = RETRY_MS * 1000; +#endif - FD_ZERO(&fds); + if (netplay->timeout_cnt >= MAX_RETRIES && !netplay->remote_paused) + return -1; + +#ifdef NETWORK_HAVE_POLL for (i = 0; i < netplay->connections_size; i++) { struct netplay_connection *connection = &netplay->connections[i]; + if (connection->active) - FD_SET(connection->fd, &fds); + { + struct pollfd *fd = &fds[nfds++]; + + NET_POLL_FD(connection->fd, fd); + fd->events = POLLIN; + fd->revents = 0; + } } - if (socket_select(max_fd, &fds, NULL, NULL, &tv) < 0) - return -1; + if (!nfds) + break; +#else + FD_ZERO(&fds); + + for (i = 0; i < netplay->connections_size; i++) + { + struct netplay_connection *connection = &netplay->connections[i]; + + if (connection->active) + { + FD_SET(connection->fd, &fds); + + if (connection->fd > max_fd) + max_fd = connection->fd; + } + } + + if (max_fd < 0) + break; + + tv.tv_usec = RETRY_MS * 1000; +#endif + + netplay->timeout_cnt++; RARCH_LOG( - "[Netplay] Network is stalling at frame %u, count %u of %d ...\n", - netplay->run_frame_count, - netplay->timeout_cnt, - MAX_RETRIES); + "[Netplay] Network is stalling at frame %lu, count %u of %d ...\n", + (unsigned long)netplay->run_frame_count, + netplay->timeout_cnt, + MAX_RETRIES); - if ( netplay->timeout_cnt >= MAX_RETRIES - && !netplay->remote_paused) +#ifdef NETWORK_HAVE_POLL + if (socket_poll(fds, nfds, RETRY_MS) < 0) +#else + if (socket_select(max_fd + 1, &fds, NULL, NULL, &tv) < 0) +#endif return -1; } } @@ -6314,14 +6307,14 @@ static int init_tcp_connection(netplay_t *netplay, const struct addrinfo *addr, if (!is_server) { - if (socket_connect_with_timeout(fd, (void*)addr, 10)) + if (socket_connect_with_timeout(fd, (void*)addr, 10000)) { /* If we are connecting to a tunnel server, we must also send our session linking request. */ if (!netplay->mitm_session_id.magic || socket_send_all_blocking_with_timeout(fd, &netplay->mitm_session_id, sizeof(netplay->mitm_session_id), - 5, true)) + 5000, true)) return fd; } @@ -6341,7 +6334,7 @@ static int init_tcp_connection(netplay_t *netplay, const struct addrinfo *addr, } else if (is_mitm) { - if (socket_connect_with_timeout(fd, (void*)addr, 10)) + if (socket_connect_with_timeout(fd, (void*)addr, 10000)) { mitm_id_t new_session = {0}; @@ -6351,10 +6344,10 @@ static int init_tcp_connection(netplay_t *netplay, const struct addrinfo *addr, /* Tunnel server should provide us with our session ID. */ if (socket_send_all_blocking_with_timeout(fd, - &new_session, sizeof(new_session), 5, true) && + &new_session, sizeof(new_session), 5000, true) && socket_receive_all_blocking_with_timeout(fd, &netplay->mitm_session_id, sizeof(netplay->mitm_session_id), - 5)) + 5000)) { if (ntohl(netplay->mitm_session_id.magic) == MITM_SESSION_MAGIC && memcmp(netplay->mitm_session_id.unique, new_session.unique,