diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index a7cdaab80..8332e7383 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -38,6 +38,7 @@ #endif #include "http.h" +#include "../tcp.h" #define TAG FREERDP_TAG("core.gateway.http") @@ -1230,14 +1231,34 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength) response->ContentLength = 0; + const UINT32 timeout = freerdp_settings_get_uint32(tls->settings, FreeRDP_TcpConnectTimeout); while (payloadOffset == 0) { + int status = -1; size_t s = 0; char* end = NULL; /* Read until we encounter \r\n\r\n */ ERR_clear_error(); - int status = BIO_read(tls->bio, Stream_Pointer(response->data), 1); + const long wstatus = BIO_wait_read(tls->bio, timeout); + if (wstatus < 0) + { + if (!BIO_should_retry(tls->bio)) + { + WLog_ERR(TAG, "[BIO_wait_read] Retries exceeded"); + ERR_print_errors_cb(print_bio_error, NULL); + goto out_error; + } + USleep(100); + continue; + } + else if (wstatus == 0) + { + WLog_ERR(TAG, "[BIO_wait] timeout exceeded"); + ERR_print_errors_cb(print_bio_error, NULL); + goto out_error; + } + status = BIO_read(tls->bio, Stream_Pointer(response->data), 1); if (status <= 0) { if (!BIO_should_retry(tls->bio)) diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index f9e216fe2..f424cc048 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -263,8 +263,12 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2) } while ((status < 0) && (errno == EINTR)); #endif + /* Convert timeout to error return */ + if (status == 0) + errno = ETIMEDOUT; } break; + case BIO_C_WAIT_WRITE: { int timeout = (int)arg1; @@ -298,14 +302,12 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2) } while ((status < 0) && (errno == EINTR)); #endif + /* Convert timeout to error return */ + if (status == 0) + errno = ETIMEDOUT; } break; - default: - break; - } - switch (cmd) - { case BIO_C_SET_FD: if (arg2) { @@ -336,11 +338,8 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2) status = 1; break; - case BIO_CTRL_DUP: - status = 1; - break; - case BIO_CTRL_FLUSH: + case BIO_CTRL_DUP: status = 1; break; diff --git a/libfreerdp/core/tcp.h b/libfreerdp/core/tcp.h index 51f3e5420..7e9856a18 100644 --- a/libfreerdp/core/tcp.h +++ b/libfreerdp/core/tcp.h @@ -53,15 +53,43 @@ #define BIO_C_WAIT_WRITE 1108 #define BIO_C_SET_HANDLE 1109 -#define BIO_set_socket(b, s, c) BIO_ctrl(b, BIO_C_SET_SOCKET, c, s); -#define BIO_get_socket(b, c) BIO_ctrl(b, BIO_C_GET_SOCKET, 0, (char*)c) -#define BIO_get_event(b, c) BIO_ctrl(b, BIO_C_GET_EVENT, 0, (char*)c) -#define BIO_set_handle(b, h) BIO_ctrl(b, BIO_C_SET_HANDLE, 0, h) -#define BIO_set_nonblock(b, c) BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL) -#define BIO_read_blocked(b) BIO_ctrl(b, BIO_C_READ_BLOCKED, 0, NULL) -#define BIO_write_blocked(b) BIO_ctrl(b, BIO_C_WRITE_BLOCKED, 0, NULL) -#define BIO_wait_read(b, c) BIO_ctrl(b, BIO_C_WAIT_READ, c, NULL) -#define BIO_wait_write(b, c) BIO_ctrl(b, BIO_C_WAIT_WRITE, c, NULL) +static INLINE long BIO_set_socket(BIO* b, SOCKET* s, long c) +{ + return BIO_ctrl(b, BIO_C_SET_SOCKET, c, s); +} +static INLINE long BIO_get_socket(BIO* b, SOCKET* c) +{ + return BIO_ctrl(b, BIO_C_GET_SOCKET, 0, c); +} +static INLINE long BIO_get_event(BIO* b, HANDLE* c) +{ + return BIO_ctrl(b, BIO_C_GET_EVENT, 0, c); +} +static INLINE long BIO_set_handle(BIO* b, HANDLE* h) +{ + return BIO_ctrl(b, BIO_C_SET_HANDLE, 0, h); +} +static INLINE long BIO_set_nonblock(BIO* b, long c) +{ + return BIO_ctrl(b, BIO_C_SET_NONBLOCK, c, NULL); +} +static INLINE long BIO_read_blocked(BIO* b) +{ + return BIO_ctrl(b, BIO_C_READ_BLOCKED, 0, NULL); +} +static INLINE long BIO_write_blocked(BIO* b) +{ + return BIO_ctrl(b, BIO_C_WRITE_BLOCKED, 0, NULL); +} +static INLINE long BIO_wait_read(BIO* b, long c) +{ + return BIO_ctrl(b, BIO_C_WAIT_READ, c, NULL); +} + +static INLINE long BIO_wait_write(BIO* b, long c) +{ + return BIO_ctrl(b, BIO_C_WAIT_WRITE, c, NULL); +} FREERDP_LOCAL BIO_METHOD* BIO_s_simple_socket(void); FREERDP_LOCAL BIO_METHOD* BIO_s_buffered_socket(void);