From 0ac7ed9e84c3871d4427acc1ce59dca5e4af21ef Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Wed, 26 Jun 2019 18:58:44 +0000 Subject: [PATCH] Fix: Corrected blocking state of connections Thanks to Bernd Geiser for initial report. Fixes: #2309 --- include/shout/shout.h.in | 8 +++++++- src/connection.c | 13 +++++++------ src/shout.c | 7 +++++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/shout/shout.h.in b/include/shout/shout.h.in index 6fda58b..297ff17 100644 --- a/include/shout/shout.h.in +++ b/include/shout/shout.h.in @@ -85,6 +85,11 @@ extern "C" { #define SHOUT_TLS_RFC2818 ( 11) /* Use TLS for transport layer like HTTPS [RFC2818] does. */ #define SHOUT_TLS_RFC2817 ( 12) /* Use TLS via HTTP Upgrade:-header [RFC2817]. */ +/* Possible values for blocking */ +#define SHOUT_BLOCKING_DEFAULT (255) /* Use the default blocking setting. */ +#define SHOUT_BLOCKING_FULL ( 0) /* Block in all I/O related functions */ +#define SHOUT_BLOCKING_NONE ( 1) /* Do not block in I/O related functions */ + #define SHOUT_AI_BITRATE "bitrate" #define SHOUT_AI_SAMPLERATE "samplerate" #define SHOUT_AI_CHANNELS "channels" @@ -244,7 +249,8 @@ int shout_set_protocol(shout_t *self, unsigned int protocol); unsigned int shout_get_protocol(shout_t *self); /* Instructs libshout to use nonblocking I/O. Must be called before - * shout_open (no switching back and forth midstream at the moment). */ + * shout_open (no switching back and forth midstream at the moment). + * nonblocking is one of SHOUT_BLOCKING_xxx. */ int shout_set_nonblocking(shout_t* self, unsigned int nonblocking); unsigned int shout_get_nonblocking(shout_t *self); diff --git a/src/connection.c b/src/connection.c index 07fc587..01b15ba 100644 --- a/src/connection.c +++ b/src/connection.c @@ -118,7 +118,7 @@ static struct timeval shout_connection_iter__wait_for_io__get_timeout(shout_conn .tv_usec = (timeout % 1000) * 1000 }; return tv; - } else if (con->nonblocking) { + } else if (con->nonblocking == SHOUT_BLOCKING_NONE) { return tv_nonblocking; } else { return tv_blocking; @@ -167,7 +167,7 @@ static shout_connection_return_state_t shout_connection_iter__socket(shout_conne } break; case SHOUT_SOCKSTATE_CONNECTING: - if (con->nonblocking) { + if (con->nonblocking == SHOUT_BLOCKING_NONE) { ret = shout_connection_iter__wait_for_io(con, shout, 1, 1, 0); if (ret != SHOUT_RS_DONE) { return ret; @@ -460,7 +460,7 @@ int shout_connection_iter(shout_connection_t *con, shout_t *shou break; \ case SHOUT_RS_TIMEOUT: \ case SHOUT_RS_NOTNOW: \ - if (con->nonblocking) \ + if (con->nonblocking == SHOUT_BLOCKING_NONE) \ return SHOUTERR_RETRY; \ retry = 1; \ break; \ @@ -518,7 +518,7 @@ int shout_connection_select_tlsmode(shout_connection_t *con, int } int shout_connection_set_nonblocking(shout_connection_t *con, unsigned int nonblocking) { - if (!con) + if (!con || (nonblocking != SHOUT_BLOCKING_DEFAULT && nonblocking != SHOUT_BLOCKING_FULL && nonblocking != SHOUT_BLOCKING_NONE)) return SHOUTERR_INSANE; if (con->socket != SOCK_ERROR) @@ -563,13 +563,14 @@ int shout_connection_connect(shout_connection_t *con, shout_t *s if (con->socket != SOCK_ERROR || con->current_socket_state != SHOUT_SOCKSTATE_UNCONNECTED) return SHOUTERR_BUSY; - shout_connection_set_nonblocking(con, shout_get_nonblocking(shout)); + if (con->nonblocking == SHOUT_BLOCKING_DEFAULT) + shout_connection_set_nonblocking(con, shout_get_nonblocking(shout)); port = shout->port; if (shout_get_protocol(shout) == SHOUT_PROTOCOL_ICY) port++; - if (con->nonblocking) { + if (con->nonblocking == SHOUT_BLOCKING_NONE) { con->socket = sock_connect_non_blocking(shout->host, port); } else { con->socket = sock_connect(shout->host, port); diff --git a/src/shout.c b/src/shout.c index 1439c14..9845d13 100644 --- a/src/shout.c +++ b/src/shout.c @@ -417,7 +417,7 @@ int shout_set_metadata(shout_t *self, shout_metadata_t *metadata) #ifdef HAVE_OPENSSL shout_connection_select_tlsmode(connection, self->tls_mode); #endif - shout_connection_set_nonblocking(connection, 0); + shout_connection_set_nonblocking(connection, SHOUT_BLOCKING_FULL); connection->target_message_state = SHOUT_MSGSTATE_PARSED_FINAL; @@ -989,7 +989,10 @@ unsigned int shout_get_protocol(shout_t *self) int shout_set_nonblocking(shout_t *self, unsigned int nonblocking) { - if (!self || (nonblocking != 0 && nonblocking != 1)) + if (nonblocking == SHOUT_BLOCKING_DEFAULT) + nonblocking = SHOUT_BLOCKING_FULL; + + if (!self || (nonblocking != SHOUT_BLOCKING_FULL && nonblocking != SHOUT_BLOCKING_NONE)) return SHOUTERR_INSANE; if (self->connection) -- 2.22.0