diff options
Diffstat (limited to 'lib/libshout-idjc/src/shout.c')
-rw-r--r-- | lib/libshout-idjc/src/shout.c | 1756 |
1 files changed, 942 insertions, 814 deletions
diff --git a/lib/libshout-idjc/src/shout.c b/lib/libshout-idjc/src/shout.c index d296ff3321..9cc169909e 100644 --- a/lib/libshout-idjc/src/shout.c +++ b/lib/libshout-idjc/src/shout.c @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +# include <config.h> #endif #include <stdarg.h> @@ -32,27 +32,28 @@ #include <strings.h> #include <errno.h> -#include <shout/shout.h> +#include <shoutidjc/shout.h> + #include <common/net/sock.h> -#include "common/timing/timing.h" -#include "common/httpp/httpp.h" +#include <common/timing/timing.h> +#include <common/httpp/httpp.h> #include "shout_private.h" #include "util.h" #ifdef _MSC_VER -# ifndef va_copy -# define va_copy(ap1, ap2) memcpy(&ap1, &ap2, sizeof(va_list)) -# endif -# define vsnprintf _vsnprintf -# define inline _inline +# ifndef va_copy +# define va_copy(ap1, ap2) memcpy(&ap1, &ap2, sizeof(va_list)) +# endif +# define vsnprintf _vsnprintf +# define inline _inline #endif /* -- local prototypes -- */ static int send_queue(shout_t *self); static int get_response(shout_t *self); -static int try_connect (shout_t *self); -static int try_write (shout_t *self, const void *data, size_t len); +static int try_connect(shout_t *self); +static int try_write(shout_t *self, const void *data, size_t len); static int create_request(shout_t *self); static int parse_response(shout_t *self); @@ -64,474 +65,504 @@ static int _initialized = 0; void shout_init(void) { - if (_initialized) - return; + if (_initialized) + return; - sock_initialize(); - _initialized = 1; + sock_initialize(); + _initialized = 1; } void shout_shutdown(void) { - if (!_initialized) - return; + if (!_initialized) + return; - sock_shutdown(); - _initialized = 0; + sock_shutdown(); + _initialized = 0; } shout_t *shout_new(void) { - shout_t *self; + shout_t *self; - /* in case users haven't done this explicitly. Should we error - * if not initialized instead? */ - shout_init(); - - if (!(self = (shout_t *)calloc(1, sizeof(shout_t)))) { - return NULL; - } + /* in case users haven't done this explicitly. Should we error + * if not initialized instead? */ + shout_init(); - if (shout_set_host(self, LIBSHOUT_DEFAULT_HOST) != SHOUTERR_SUCCESS) { - shout_free(self); + if (!(self = (shout_t*)calloc(1, sizeof(shout_t)))) { + return NULL; + } - return NULL; - } - if (shout_set_user(self, LIBSHOUT_DEFAULT_USER) != SHOUTERR_SUCCESS) { - shout_free(self); + if (shout_set_host(self, LIBSHOUT_DEFAULT_HOST) != SHOUTERR_SUCCESS) { + shout_free(self); + return NULL; + } - return NULL; - } - if (shout_set_agent(self, LIBSHOUT_DEFAULT_USERAGENT) != SHOUTERR_SUCCESS) { - shout_free(self); + if (shout_set_user(self, LIBSHOUT_DEFAULT_USER) != SHOUTERR_SUCCESS) { + shout_free(self); + return NULL; + } - return NULL; - } - if (!(self->audio_info = _shout_util_dict_new())) { - shout_free(self); + if (shout_set_agent(self, LIBSHOUT_DEFAULT_USERAGENT) != SHOUTERR_SUCCESS) { + shout_free(self); + return NULL; + } - return NULL; - } - if (!(self->meta = _shout_util_dict_new())) { - shout_free(self); + if (!(self->audio_info = _shout_util_dict_new())) { + shout_free(self); + return NULL; + } - return NULL; - } - if (shout_set_meta(self, "name", "no name") != SHOUTERR_SUCCESS) { - shout_free(self); + if (!(self->meta = _shout_util_dict_new())) { + shout_free(self); + return NULL; + } - return NULL; - } + if (shout_set_meta(self, "name", "no name") != SHOUTERR_SUCCESS) { + shout_free(self); + return NULL; + } #ifdef HAVE_OPENSSL - if (shout_set_allowed_ciphers(self, LIBSHOUT_DEFAULT_ALLOWED_CIPHERS) != SHOUTERR_SUCCESS) { - shout_free(self); + if (shout_set_allowed_ciphers(self, LIBSHOUT_DEFAULT_ALLOWED_CIPHERS) != SHOUTERR_SUCCESS) { + shout_free(self); + return NULL; + } - return NULL; - } - self->tls_mode = SHOUT_TLS_AUTO; + self->tls_mode = SHOUT_TLS_AUTO; + self->tls_mode_used = SHOUTERR_NOTLS; #endif - self->port = LIBSHOUT_DEFAULT_PORT; - self->format = LIBSHOUT_DEFAULT_FORMAT; - self->protocol = LIBSHOUT_DEFAULT_PROTOCOL; + self->port = LIBSHOUT_DEFAULT_PORT; + self->format = LIBSHOUT_DEFAULT_FORMAT; + self->protocol = LIBSHOUT_DEFAULT_PROTOCOL; - return self; + return self; } void shout_free(shout_t *self) { - if (!self) return; - - if (self->state != SHOUT_STATE_UNCONNECTED) return; - - if (self->host) free(self->host); - if (self->password) free(self->password); - if (self->mount) free(self->mount); - if (self->user) free(self->user); - if (self->useragent) free(self->useragent); - if (self->audio_info) _shout_util_dict_free (self->audio_info); - if (self->meta) _shout_util_dict_free (self->meta); + if (!self) + return; + + if (self->state != SHOUT_STATE_UNCONNECTED) + return; + + if (self->host) + free(self->host); + if (self->password) + free(self->password); + if (self->mount) + free(self->mount); + if (self->user) + free(self->user); + if (self->useragent) + free(self->useragent); + if (self->audio_info) + _shout_util_dict_free (self->audio_info); + if (self->meta) + _shout_util_dict_free (self->meta); #ifdef HAVE_OPENSSL - if (self->ca_directory) free(self->ca_directory); - if (self->ca_file) free(self->ca_file); - if (self->allowed_ciphers) free(self->allowed_ciphers); - if (self->client_certificate) free(self->client_certificate); + if (self->ca_directory) + free(self->ca_directory); + if (self->ca_file) + free(self->ca_file); + if (self->allowed_ciphers) + free(self->allowed_ciphers); + if (self->client_certificate) + free(self->client_certificate); #endif - free(self); + free(self); } int shout_open(shout_t *self) { - /* sanity check */ - if (!self) - return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return SHOUTERR_CONNECTED; - if (!self->host || !self->password || !self->port) - return self->error = SHOUTERR_INSANE; - if (self->format == SHOUT_FORMAT_OGG && (self->protocol != SHOUT_PROTOCOL_HTTP && self->protocol != SHOUT_PROTOCOL_ROARAUDIO)) - return self->error = SHOUTERR_UNSUPPORTED; + /* sanity check */ + if (!self) + return SHOUTERR_INSANE; + if (self->state != SHOUT_STATE_UNCONNECTED) + return SHOUTERR_CONNECTED; + if (!self->host || !self->password || !self->port) + return self->error = SHOUTERR_INSANE; + if (self->format == SHOUT_FORMAT_OGG && (self->protocol != SHOUT_PROTOCOL_HTTP && self->protocol != SHOUT_PROTOCOL_ROARAUDIO)) + return self->error = SHOUTERR_UNSUPPORTED; - return self->error = try_connect(self); + return self->error = try_connect(self); } int shout_close(shout_t *self) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state == SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_UNCONNECTED; + if (self->state == SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_UNCONNECTED; - if (self->state == SHOUT_STATE_CONNECTED && self->close) - self->close(self); + if (self->state == SHOUT_STATE_CONNECTED && self->close) + self->close(self); #ifdef HAVE_OPENSSL - if (self->tls) - shout_tls_close(self->tls); - self->tls = NULL; + if (self->tls) + shout_tls_close(self->tls); + self->tls = NULL; #endif - sock_close(self->socket); - self->state = SHOUT_STATE_UNCONNECTED; - self->starttime = 0; - self->senttime = 0; - shout_queue_free(&self->rqueue); - shout_queue_free(&self->wqueue); + sock_close(self->socket); + self->state = SHOUT_STATE_UNCONNECTED; + self->starttime = 0; + self->senttime = 0; + shout_queue_free(&self->rqueue); + shout_queue_free(&self->wqueue); - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } int shout_send(shout_t *self, const unsigned char *data, size_t len) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_CONNECTED) - return self->error = SHOUTERR_UNCONNECTED; + if (self->state != SHOUT_STATE_CONNECTED) + return self->error = SHOUTERR_UNCONNECTED; - if (self->starttime <= 0) - self->starttime = timing_get_time(); + if (self->starttime <= 0) + self->starttime = timing_get_time(); - if (!len) - return send_queue(self); + if (!len) + return send_queue(self); - return self->send(self, data, len); + return self->send(self, data, len); } ssize_t shout_send_raw(shout_t *self, const unsigned char *data, size_t len) { - ssize_t ret; - - if (!self) - return SHOUTERR_INSANE; + ssize_t ret; - if (self->state != SHOUT_STATE_CONNECTED) - return SHOUTERR_UNCONNECTED; + if (!self) + return SHOUTERR_INSANE; - self->error = SHOUTERR_SUCCESS; + if (self->state != SHOUT_STATE_CONNECTED) + return SHOUTERR_UNCONNECTED; - /* send immediately if possible (should be the common case) */ - if (len && ! self->wqueue.len) { - if ((ret = try_write(self, data, len)) < 0) - return self->error; - if (ret < (ssize_t)len) { - self->error = shout_queue_data(&self->wqueue, data + ret, len - ret); - if (self->error != SHOUTERR_SUCCESS) - return self->error; - } + self->error = SHOUTERR_SUCCESS; - return len; - } + /* send immediately if possible (should be the common case) */ + if (len && !self->wqueue.len) { + if ((ret = try_write(self, data, len)) < 0) + return self->error; + if (ret < (ssize_t)len) { + self->error = shout_queue_data(&self->wqueue, data + ret, len - ret); + if (self->error != SHOUTERR_SUCCESS) + return self->error; + } + return len; + } - self->error = shout_queue_data(&self->wqueue, data, len); - if (self->error != SHOUTERR_SUCCESS) - return self->error; + self->error = shout_queue_data(&self->wqueue, data, len); + if (self->error != SHOUTERR_SUCCESS) + return self->error; - ret = send_queue(self); - if (ret == SHOUTERR_SUCCESS || (len && ret == SHOUTERR_BUSY)) - return len; + ret = send_queue(self); + if (ret == SHOUTERR_SUCCESS || (len && ret == SHOUTERR_BUSY)) + return len; - return ret; + return ret; } ssize_t shout_queuelen(shout_t *self) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - return (ssize_t)self->wqueue.len; + return (ssize_t)self->wqueue.len; } void shout_sync(shout_t *self) { - int64_t sleep; + int64_t sleep; + + if (!self) + return; - if (!self) - return; + if (self->senttime == 0) + return; - if (self->senttime == 0) - return; + sleep = self->senttime / 1000 - (timing_get_time() - self->starttime); + if (sleep > 0) + timing_sleep((uint64_t)sleep); - sleep = self->senttime / 1000 - (timing_get_time() - self->starttime); - if (sleep > 0) - timing_sleep((uint64_t)sleep); - } int shout_delay(shout_t *self) { - if (!self) - return 0; + if (!self) + return 0; - if (self->senttime == 0) - return 0; + if (self->senttime == 0) + return 0; - return self->senttime / 1000 - (timing_get_time() - self->starttime); + return self->senttime / 1000 - (timing_get_time() - self->starttime); } - + shout_metadata_t *shout_metadata_new(void) { - return _shout_util_dict_new(); + return _shout_util_dict_new(); } void shout_metadata_free(shout_metadata_t *self) { - if (!self) - return; + if (!self) + return; - _shout_util_dict_free(self); + _shout_util_dict_free(self); } int shout_metadata_add(shout_metadata_t *self, const char *name, const char *value) { - if (!self || !name) - return SHOUTERR_INSANE; + if (!self || !name) + return SHOUTERR_INSANE; - return _shout_util_dict_set(self, name, value); + return _shout_util_dict_set(self, name, value); } /* open second socket to server, send HTTP request to change metadata. - * TODO: prettier error-handling. */ + * TODO: prettier error-handling. + */ int shout_set_metadata(shout_t *self, shout_metadata_t *metadata) { - int error; - sock_t socket = -1; - int rv; - char *encvalue = NULL; - const char *request_template; - char *request = NULL; - size_t request_len; - char *auth = NULL; + int error; + sock_t socket = -1; + int rv; + char *encvalue = NULL; + const char *request_template; + char *request = NULL; + size_t request_len; + char *auth = NULL; + char *mount = NULL; #ifdef HAVE_OPENSSL - shout_tls_t *tls = NULL; + shout_tls_t *tls = NULL; #endif - if (!self || !metadata) - return SHOUTERR_INSANE; - - if (!(encvalue = _shout_util_dict_urlencode(metadata, '&'))) - goto error_malloc; - - switch (self->protocol) { - case SHOUT_PROTOCOL_ICY: - request_template = "GET /admin.cgi?mode=updinfo&pass=%s&%s HTTP/1.0\r\nUser-Agent: %s (Mozilla compatible)\r\n\r\n"; - request_len = strlen(request_template) + strlen(self->password) + strlen(encvalue) + strlen(shout_get_agent(self)) + 1; - if (!(request = malloc(request_len))) - goto error_malloc; - snprintf(request, request_len, request_template, self->password, encvalue, shout_get_agent(self)); - break; - case SHOUT_PROTOCOL_HTTP: - auth = shout_http_basic_authorization(self); - - request_template = "GET /admin/metadata?mode=updinfo&mount=%s&%s HTTP/1.0\r\nUser-Agent: %s\r\n%s\r\n"; - request_len = strlen(request_template) + strlen(self->mount) + strlen(encvalue) + strlen(shout_get_agent(self)) + 1; - if (auth) - request_len += strlen(auth); - if (!(request = malloc(request_len))) - goto error_malloc; - snprintf(request, request_len, request_template, self->mount, encvalue, shout_get_agent(self), auth ? auth : ""); - break; - default: - request_template = "GET /admin.cgi?mode=updinfo&pass=%s&mount=%s&%s HTTP/1.0\r\nUser-Agent: %s\r\n\r\n"; - request_len = strlen(request_template) + strlen(self->password) + strlen(self->mount) + strlen(encvalue) + strlen(shout_get_agent(self)) + 1; - if (!(request = malloc(request_len))) - goto error_malloc; - snprintf(request, request_len, request_template, self->password, self->mount, encvalue, shout_get_agent(self)); - break; - } + if (!self || !metadata) + return SHOUTERR_INSANE; + + if (!(encvalue = _shout_util_dict_urlencode(metadata, '&'))) + goto error_malloc; + + if (!(mount = _shout_util_url_encode(self->mount))) + goto error_malloc; + + switch (self->protocol) { + case SHOUT_PROTOCOL_ICY: + request_template = "GET /admin.cgi?mode=updinfo&pass=%s&%s HTTP/1.0\r\nUser-Agent: %s (Mozilla compatible)\r\n\r\n"; + request_len = strlen(request_template) + strlen(self->password) + strlen(encvalue) + strlen(shout_get_agent(self)) + 1; + if (!(request = malloc(request_len))) + goto error_malloc; + snprintf(request, request_len, request_template, self->password, encvalue, shout_get_agent(self)); + break; + case SHOUT_PROTOCOL_HTTP: + auth = shout_http_basic_authorization(self); + + request_template = "GET /admin/metadata?mode=updinfo&mount=%s&%s HTTP/1.0\r\nUser-Agent: %s\r\n%s\r\n"; + request_len = strlen(request_template) + strlen(mount) + strlen(encvalue) + strlen(shout_get_agent(self)) + 1; + if (auth) + request_len += strlen(auth); + if (!(request = malloc(request_len))) + goto error_malloc; + snprintf(request, request_len, request_template, mount, encvalue, shout_get_agent(self), auth ? auth : ""); + break; + default: + request_template = "GET /admin.cgi?mode=updinfo&pass=%s&mount=%s&%s HTTP/1.0\r\nUser-Agent: %s\r\n\r\n"; + request_len = strlen(request_template) + strlen(self->password) + strlen(mount) + strlen(encvalue) + strlen(shout_get_agent(self)) + 1; + if (!(request = malloc(request_len))) + goto error_malloc; + snprintf(request, request_len, request_template, self->password, mount, encvalue, shout_get_agent(self)); + break; + } + + free(encvalue); + encvalue = NULL; - free(encvalue); - encvalue = NULL; + free(mount); + mount = NULL; - if (auth) - free(auth); - auth = NULL; + if (auth) + free(auth); + auth = NULL; - if ((socket = sock_connect(self->host, self->port)) <= 0) - return SHOUTERR_NOCONNECT; + if ((socket = sock_connect(self->host, self->port)) <= 0) + return SHOUTERR_NOCONNECT; #ifdef HAVE_OPENSSL - switch (self->tls_mode) { - case SHOUT_TLS_DISABLED: - /* nothing to do */ - break; - case SHOUT_TLS_RFC2817: /* Use TLS via HTTP Upgrade:-header [RFC2817]. */ - do { /* use a subscope to avoid more function level variables */ - char upgrade[512]; - size_t len; - - /* send upgrade request */ - snprintf(upgrade, sizeof(upgrade), - "GET / HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: TLS/1.0\r\nHost: %s:%i\r\n\r\n", - self->host, self->port); - upgrade[sizeof(upgrade)-1] = 0; - len = strlen(upgrade); - if (len == (sizeof(upgrade) - 1)) - goto error_malloc; - rv = sock_write_bytes(socket, upgrade, len); - if (len != (size_t)rv) - goto error_socket; - - /* read status line */ - if (!sock_read_line(socket, upgrade, sizeof(upgrade))) - goto error_socket; - if (strncmp(upgrade, "HTTP/1.1 101 ", 13) != 0) - goto error_socket; - - /* read headers */ - len = 0; - do { - if (!sock_read_line(socket, upgrade, sizeof(upgrade))) - goto error_socket; - if (upgrade[0] == 0) - break; - if (!strncasecmp(upgrade, "Content-Length: ", 16) == 0) - len = atoi(upgrade + 16); - } while (1); - - /* read body */ - while (len) { - rv = sock_read_bytes(socket, upgrade, len > sizeof(upgrade) ? sizeof(upgrade) : len); - if (rv < 1) - goto error_socket; - len -= rv; - } - } while (0); - /* fall thru */ - case SHOUT_TLS_RFC2818: /* Use TLS for transport layer like HTTPS [RFC2818] does. */ - tls = shout_tls_new(self, socket); - if (!tls) - goto error_malloc; - error = shout_tls_try_connect(tls); - if (error != SHOUTERR_SUCCESS) - goto error; - break; - default: - /* Bad mode or auto detection not completed. */ - error = SHOUTERR_INSANE; - goto error; - break; - } + switch (self->tls_mode_used) { + case SHOUT_TLS_DISABLED: + /* nothing to do */ + break; + + case SHOUT_TLS_RFC2817: + /* Use TLS via HTTP Upgrade:-header [RFC2817]. */ + do { + /* use a subscope to avoid more function level variables */ + char upgrade[512]; + size_t len; + + /* send upgrade request */ + snprintf(upgrade, sizeof(upgrade), + "GET / HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: TLS/1.0\r\nHost: %s:%i\r\n\r\n", + self->host, self->port); + + upgrade[sizeof(upgrade) - 1] = 0; + len = strlen(upgrade); + if (len == (sizeof(upgrade) - 1)) + goto error_malloc; + + rv = sock_write_bytes(socket, upgrade, len); + if (len != (size_t)rv) + goto error_socket; + + /* read status line */ + if (!sock_read_line(socket, upgrade, sizeof(upgrade))) + goto error_socket; + if (strncmp(upgrade, "HTTP/1.1 101 ", 13) != 0) + goto error_socket; + + /* read headers */ + len = 0; + do { + if (!sock_read_line(socket, upgrade, sizeof(upgrade))) + goto error_socket; + if (upgrade[0] == 0) + break; + if (!strncasecmp(upgrade, "Content-Length: ", 16) == 0) + len = atoi(upgrade + 16); + } while (1); + + /* read body */ + while (len) { + rv = sock_read_bytes(socket, upgrade, len > sizeof(upgrade) ? sizeof(upgrade) : len); + if (rv < 1) + goto error_socket; + len -= rv; + } + } while (0); + /* fall thru */ + + case SHOUT_TLS_RFC2818: + /* Use TLS for transport layer like HTTPS [RFC2818] does. */ + tls = shout_tls_new(self, socket); + if (!tls) + goto error_malloc; + error = shout_tls_try_connect(tls); + if (error != SHOUTERR_SUCCESS) + goto error; + break; + + default: + /* Bad mode or auto detection not completed. */ + error = SHOUTERR_INSANE; + goto error; + break; + } #endif #ifdef HAVE_OPENSSL - if (tls) { - rv = shout_tls_write(tls, request, strlen(request)); - } else { - rv = sock_write(socket, "%s", request); - } + if (tls) { + rv = shout_tls_write(tls, request, strlen(request)); + } else { + rv = sock_write(socket, "%s", request); + } #else - rv = sock_write(socket, "%s", request); + rv = sock_write(socket, "%s", request); #endif - if (!rv) - goto error_socket; + if (!rv) + goto error_socket; - error = SHOUTERR_SUCCESS; - goto error; + error = SHOUTERR_SUCCESS; + goto error; error_socket: - error = SHOUTERR_SOCKET; - goto error; + error = SHOUTERR_SOCKET; + goto error; error_malloc: - error = SHOUTERR_MALLOC; - goto error; + error = SHOUTERR_MALLOC; + goto error; error: #ifdef HAVE_OPENSSL - if (tls) - shout_tls_close(tls); + if (tls) + shout_tls_close(tls); #endif - if (socket != -1) - sock_close(socket); - if (encvalue) - free(encvalue); - if (request) - free(request); - if (auth) - free(auth); - return error; + if (socket != -1) + sock_close(socket); + if (encvalue) + free(encvalue); + if (request) + free(request); + if (auth) + free(auth); + if (mount) + free(mount); + return error; } /* getters/setters */ const char *shout_version(int *major, int *minor, int *patch) { - if (major) - *major = LIBSHOUT_MAJOR; - if (minor) - *minor = LIBSHOUT_MINOR; - if (patch) - *patch = LIBSHOUT_MICRO; + if (major) + *major = LIBSHOUT_MAJOR; + if (minor) + *minor = LIBSHOUT_MINOR; + if (patch) + *patch = LIBSHOUT_MICRO; - return VERSION; + return VERSION; } int shout_get_errno(shout_t *self) { - return self->error; + return self->error; } const char *shout_get_error(shout_t *self) { - if (!self) - return "Invalid shout_t"; - - switch (self->error) { - case SHOUTERR_SUCCESS: - return "No error"; - case SHOUTERR_INSANE: - return "Nonsensical arguments"; - case SHOUTERR_NOCONNECT: - return "Couldn't connect"; - case SHOUTERR_NOLOGIN: - return "Login failed"; - case SHOUTERR_SOCKET: - return "Socket error"; - case SHOUTERR_MALLOC: - return "Out of memory"; - case SHOUTERR_CONNECTED: - return "Cannot set parameter while connected"; - case SHOUTERR_UNCONNECTED: - return "Not connected"; - case SHOUTERR_BUSY: - return "Socket is busy"; - case SHOUTERR_UNSUPPORTED: - return "This libshout doesn't support the requested option"; - case SHOUTERR_NOTLS: - return "TLS requested but not supported by peer"; - case SHOUTERR_TLSBADCERT: - return "TLS connection can not be established because of bad certificate"; - case SHOUTERR_RETRY: - return "Please retry current operation."; - default: - return "Unknown error"; - } + if (!self) + return "Invalid shout_t"; + + switch (self->error) { + case SHOUTERR_SUCCESS: + return "No error"; + case SHOUTERR_INSANE: + return "Nonsensical arguments"; + case SHOUTERR_NOCONNECT: + return "Couldn't connect"; + case SHOUTERR_NOLOGIN: + return "Login failed"; + case SHOUTERR_SOCKET: + return "Socket error"; + case SHOUTERR_MALLOC: + return "Out of memory"; + case SHOUTERR_CONNECTED: + return "Cannot set parameter while connected"; + case SHOUTERR_UNCONNECTED: + return "Not connected"; + case SHOUTERR_BUSY: + return "Socket is busy"; + case SHOUTERR_UNSUPPORTED: + return "This libshout doesn't support the requested option"; + case SHOUTERR_NOTLS: + return "TLS requested but not supported by peer"; + case SHOUTERR_TLSBADCERT: + return "TLS connection can not be established because of bad certificate"; + case SHOUTERR_RETRY: + return "Please retry current operation."; + default: + return "Unknown error"; + } } /* Returns: @@ -541,759 +572,855 @@ const char *shout_get_error(shout_t *self) */ int shout_get_connected(shout_t *self) { - int rc; + int rc; - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state == SHOUT_STATE_CONNECTED) - return SHOUTERR_CONNECTED; - if (self->state != SHOUT_STATE_UNCONNECTED) { - if ((rc = try_connect(self)) == SHOUTERR_SUCCESS) - return SHOUTERR_CONNECTED; - return rc; - } + if (self->state == SHOUT_STATE_CONNECTED) + return SHOUTERR_CONNECTED; + if (self->state != SHOUT_STATE_UNCONNECTED) { + if ((rc = try_connect(self)) == SHOUTERR_SUCCESS) + return SHOUTERR_CONNECTED; + return rc; + } - return SHOUTERR_UNCONNECTED; + return SHOUTERR_UNCONNECTED; } int shout_set_host(shout_t *self, const char *host) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_CONNECTED; + if (self->state != SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_CONNECTED; - if (self->host) - free(self->host); + if (self->host) + free(self->host); - if (!(self->host = _shout_util_strdup(host))) - return self->error = SHOUTERR_MALLOC; + if ( !(self->host = _shout_util_strdup(host)) ) + return self->error = SHOUTERR_MALLOC; - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } const char *shout_get_host(shout_t *self) { - if (!self) - return NULL; + if (!self) + return NULL; - return self->host; + return self->host; } int shout_set_port(shout_t *self, unsigned short port) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_CONNECTED; + if (self->state != SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_CONNECTED; - self->port = port; + self->port = port; - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } unsigned short shout_get_port(shout_t *self) { - if (!self) - return 0; + if (!self) + return 0; - return self->port; + return self->port; } int shout_set_password(shout_t *self, const char *password) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_CONNECTED; + if (self->state != SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_CONNECTED; - if (self->password) - free (self->password); + if (self->password) + free(self->password); - if (!(self->password = _shout_util_strdup(password))) - return self->error = SHOUTERR_MALLOC; + if ( !(self->password = _shout_util_strdup(password)) ) + return self->error = SHOUTERR_MALLOC; - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } const char* shout_get_password(shout_t *self) { - if (!self) - return NULL; + if (!self) + return NULL; - return self->password; + return self->password; } int shout_set_mount(shout_t *self, const char *mount) { - size_t len; + size_t len; - if (!self || !mount) - return SHOUTERR_INSANE; + if (!self || !mount) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_CONNECTED; - - if (self->mount) - free(self->mount); + if (self->state != SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_CONNECTED; + + if (self->mount) + free(self->mount); - len = strlen (mount) + 1; - if (mount[0] != '/') - len++; + len = strlen(mount) + 1; + if (mount[0] != '/') + len++; - if (!(self->mount = malloc(len))) - return self->error = SHOUTERR_MALLOC; + if ( !(self->mount = malloc(len)) ) + return self->error = SHOUTERR_MALLOC; - snprintf (self->mount, len, "%s%s", mount[0] == '/' ? "" : "/", mount); + snprintf(self->mount, len, "%s%s", mount[0] == '/' ? "" : "/", mount); - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } const char *shout_get_mount(shout_t *self) { - if (!self) - return NULL; + if (!self) + return NULL; - return self->mount; + return self->mount; } int shout_set_name(shout_t *self, const char *name) { - return shout_set_meta(self, "name", name); + return shout_set_meta(self, "name", name); } const char *shout_get_name(shout_t *self) { - return shout_get_meta(self, "name"); + return shout_get_meta(self, "name"); } int shout_set_url(shout_t *self, const char *url) { - return shout_set_meta(self, "url", url); + return shout_set_meta(self, "url", url); } const char *shout_get_url(shout_t *self) { - return shout_get_meta(self, "url"); + return shout_get_meta(self, "url"); } int shout_set_genre(shout_t *self, const char *genre) { - return shout_set_meta(self, "genre", genre); + return shout_set_meta(self, "genre", genre); } const char *shout_get_genre(shout_t *self) { - return shout_get_meta(self, "genre"); + return shout_get_meta(self, "genre"); } int shout_set_agent(shout_t *self, const char *agent) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_CONNECTED; + if (self->state != SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_CONNECTED; - if (self->useragent) - free(self->useragent); + if (self->useragent) + free(self->useragent); - if (! (self->useragent = _shout_util_strdup (agent))) - return self->error = SHOUTERR_MALLOC; + if ( !(self->useragent = _shout_util_strdup(agent)) ) + return self->error = SHOUTERR_MALLOC; - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } const char *shout_get_agent(shout_t *self) { - if (!self) - return NULL; + if (!self) + return NULL; - return self->useragent; + return self->useragent; } int shout_set_user(shout_t *self, const char *username) { - if (!self) - return SHOUTERR_INSANE; + if (!self) + return SHOUTERR_INSANE; - if (self->state != SHOUT_STATE_UNCONNECTED) - return self->error = SHOUTERR_CONNECTED; + if (self->state != SHOUT_STATE_UNCONNECTED) + return self->error = SHOUTERR_CONNECTED; - if (self->user) - free(self->user); + if (self->user) + free(self->user); - if (! (self->user = _shout_util_strdup (username))) - return self->error = SHOUTERR_MALLOC; + if ( !(self->user = _shout_util_strdup(username)) ) + return self->error = SHOUTERR_MALLOC; - return self->error = SHOUTERR_SUCCESS; + return self->error = SHOUTERR_SUCCESS; } |