diff --git a/src/libguac/Makefile.am b/src/libguac/Makefile.am index a1f47edc..35e8e6e5 100644 --- a/src/libguac/Makefile.am +++ b/src/libguac/Makefile.am @@ -68,7 +68,8 @@ noinst_HEADERS = \ encode-png.h \ palette.h \ user-handlers.h \ - raw_encoder.h + raw_encoder.h \ + wait-fd.h libguac_la_SOURCES = \ audio.c \ @@ -92,7 +93,8 @@ libguac_la_SOURCES = \ unicode.c \ user.c \ user-handlers.c \ - user-handshake.c + user-handshake.c \ + wait-fd.c # Compile WebP support if available if ENABLE_WEBP diff --git a/src/libguac/socket-fd.c b/src/libguac/socket-fd.c index 0ed57485..f806b87b 100644 --- a/src/libguac/socket-fd.c +++ b/src/libguac/socket-fd.c @@ -21,8 +21,8 @@ #include "error.h" #include "socket.h" +#include "wait-fd.h" -#include #include #include #include @@ -31,6 +31,10 @@ #include #include +#ifdef __MINGW32__ +#include +#endif + /** * Data associated with an open socket which writes to a file descriptor. */ @@ -330,24 +334,9 @@ static ssize_t guac_socket_fd_write_handler(guac_socket* socket, static int guac_socket_fd_select_handler(guac_socket* socket, int usec_timeout) { + /* Wait for data on socket */ guac_socket_fd_data* data = (guac_socket_fd_data*) socket->data; - - int retval; - - /* Initialize with single underlying file descriptor */ - struct pollfd fds[1] = {{ - .fd = data->fd, - .events = POLLIN, - .revents = 0, - }}; - - /* No timeout if usec_timeout is negative */ - if (usec_timeout < 0) - retval = poll(fds, 1, -1); - - /* Handle timeout if specified, rounding up to poll()'s granularity */ - else - retval = poll(fds, 1, (usec_timeout + 999) / 1000); + int retval = guac_wait_for_fd(data->fd, usec_timeout); /* Properly set guac_error */ if (retval < 0) { @@ -355,7 +344,7 @@ static int guac_socket_fd_select_handler(guac_socket* socket, guac_error_message = "Error while waiting for data on socket"; } - if (retval == 0) { + else if (retval == 0) { guac_error = GUAC_STATUS_TIMEOUT; guac_error_message = "Timeout while waiting for data on socket"; } diff --git a/src/libguac/socket-ssl.c b/src/libguac/socket-ssl.c index f8f3f87b..1a631fe1 100644 --- a/src/libguac/socket-ssl.c +++ b/src/libguac/socket-ssl.c @@ -22,8 +22,8 @@ #include "error.h" #include "socket-ssl.h" #include "socket.h" +#include "wait-fd.h" -#include #include #include @@ -69,23 +69,7 @@ static ssize_t __guac_socket_ssl_write_handler(guac_socket* socket, static int __guac_socket_ssl_select_handler(guac_socket* socket, int usec_timeout) { guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data; - - int retval; - - /* Initialize with single underlying file descriptor */ - struct pollfd fds[1] = {{ - .fd = data->fd, - .events = POLLIN, - .revents = 0, - }}; - - /* No timeout if usec_timeout is negative */ - if (usec_timeout < 0) - retval = poll(fds, 1, -1); - - /* Handle timeout if specified, rounding up to poll()'s granularity */ - else - retval = poll(fds, 1, (usec_timeout + 999) / 1000); + int retval = guac_wait_for_fd(data->fd, usec_timeout); /* Properly set guac_error */ if (retval < 0) { diff --git a/src/libguac/wait-fd.c b/src/libguac/wait-fd.c new file mode 100644 index 00000000..0523e624 --- /dev/null +++ b/src/libguac/wait-fd.c @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "config.h" + +#ifdef __MINGW32__ +# include +#else +# ifdef HAVE_POLL +# include +# else +# include +# endif +#endif + +#ifdef HAVE_POLL +int guac_wait_for_fd(int fd, int usec_timeout) { + + /* Initialize with single underlying file descriptor */ + struct pollfd fds[1] = {{ + .fd = fd, + .events = POLLIN, + .revents = 0 + }}; + + /* No timeout if usec_timeout is negative */ + if (usec_timeout < 0) + return poll(fds, 1, -1); + + /* Handle timeout if specified, rounding up to poll()'s granularity */ + return poll(fds, 1, (usec_timeout + 999) / 1000); + +} +#else +int guac_wait_for_fd(int fd, int usec_timeout) { + + fd_set fds; + + /* Initialize fd_set with single underlying file descriptor */ + FD_ZERO(&fds); + FD_SET(fd, &fds); + + /* No timeout if usec_timeout is negative */ + if (usec_timeout < 0) + return select(fd + 1, &fds, NULL, NULL, NULL); + + /* Handle timeout if specified */ + struct timeval timeout = { + .tv_sec = usec_timeout / 1000000, + .tv_usec = usec_timeout % 1000000 + }; + + return select(fd + 1, &fds, NULL, NULL, &timeout); + +} +#endif diff --git a/src/libguac/wait-fd.h b/src/libguac/wait-fd.h new file mode 100644 index 00000000..b5e2e5f2 --- /dev/null +++ b/src/libguac/wait-fd.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef GUAC_WAIT_FD_H +#define GUAC_WAIT_FD_H + +/** + * Waits for data to be available for reading on a given file descriptor, + * similar to the POSIX select() and poll() functions. + * + * @param fd + * The file descriptor to wait for. + * + * @param usec_timeout + * The maximum number of microseconds to wait for data, or -1 to + * potentially wait forever. + * + * @return + * Positive if data is available for reading, zero if the timeout elapsed + * and no data is available, negative if an error occurs, in which case + * errno will also be set. + */ +int guac_wait_for_fd(int fd, int usec_timeout); + +#endif