GUACAMOLE-325: Use select() if poll() is unavailable.

This commit is contained in:
Michael Jumper 2017-06-12 13:58:05 -07:00
parent 50d2dd51cb
commit 9dcddd1947
5 changed files with 127 additions and 39 deletions

View File

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

View File

@ -21,8 +21,8 @@
#include "error.h"
#include "socket.h"
#include "wait-fd.h"
#include <poll.h>
#include <pthread.h>
#include <stddef.h>
#include <stdio.h>
@ -31,6 +31,10 @@
#include <sys/time.h>
#include <unistd.h>
#ifdef __MINGW32__
#include <winsock2.h>
#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";
}

View File

@ -22,8 +22,8 @@
#include "error.h"
#include "socket-ssl.h"
#include "socket.h"
#include "wait-fd.h"
#include <poll.h>
#include <stdlib.h>
#include <openssl/ssl.h>
@ -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) {

72
src/libguac/wait-fd.c Normal file
View File

@ -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 <winsock2.h>
#else
# ifdef HAVE_POLL
# include <poll.h>
# else
# include <sys/select.h>
# 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

41
src/libguac/wait-fd.h Normal file
View File

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