Commit 3110fe32 authored by Philipp Schafft's avatar Philipp Schafft 🦁

Feature: Allow sending a stream with the new statemachine for the first time

parent 68ef5223
......@@ -71,13 +71,8 @@ int shout_connection_unref(shout_connection_t *con)
if (con->destory)
con->destory(con);
#ifdef HAVE_OPENSSL
if (con->tls)
shout_tls_close(con->tls);
con->tls = NULL;
#endif
shout_connection_disconnect(con);
sock_close(con->socket);
free(con);
return SHOUTERR_SUCCESS;
......@@ -96,15 +91,21 @@ static struct timeval shout_connection_iter__wait_for_io__get_timeout(shout_conn
static shout_connection_return_state_t shout_connection_iter__wait_for_io(shout_connection_t *con, shout_t *shout, int for_read, int for_write)
{
struct timeval tv = shout_connection_iter__wait_for_io__get_timeout(con, shout);
fd_set fhset;
fd_set fhset_r;
fd_set fhset_w;
fd_set fhset_e;
int ret;
FD_ZERO(&fhset);
FD_SET(con->socket, &fhset);
FD_ZERO(&fhset_r);
FD_ZERO(&fhset_w);
FD_ZERO(&fhset_e);
FD_SET(con->socket, &fhset_r);
FD_SET(con->socket, &fhset_w);
FD_SET(con->socket, &fhset_e);
ret = select(con->socket + 1, (for_read) ? &fhset : NULL, (for_write) ? &fhset : NULL, &fhset, &tv);
ret = select(con->socket + 1, (for_read) ? &fhset_r : NULL, (for_write) ? &fhset_w : NULL, &fhset_e, &tv);
if (ret > 0 && FD_ISSET(con->socket, &fhset)) {
if (ret > 0 && (FD_ISSET(con->socket, &fhset_r) || FD_ISSET(con->socket, &fhset_w) || FD_ISSET(con->socket, &fhset_e))) {
return SHOUT_RS_DONE;
} else if (ret == 0) {
shout->error = SHOUTERR_RETRY;
......@@ -133,7 +134,7 @@ static shout_connection_return_state_t shout_connection_iter__socket(shout_conne
return ret;
}
if (sock_connected(con->socket, 0) == 0) {
if (sock_connected(con->socket, 0) == 1) {
con->current_socket_state = SHOUT_SOCKSTATE_CONNECTED;
return SHOUT_RS_DONE;
}
......@@ -273,17 +274,19 @@ static shout_connection_return_state_t shout_connection_iter__message(shout_conn
return ret;
break;
case SHOUT_MSGSTATE_SENDING0:
case SHOUT_MSGSTATE_SENDING1:
ret = shout_connection_iter__message__send_queue(con, shout);
if (ret == SHOUT_RS_DONE) {
if (con->current_message_state == SHOUT_MSGSTATE_SENDING0) {
con->current_message_state = SHOUT_MSGSTATE_WAITING0;
} else {
con->current_message_state = SHOUT_MSGSTATE_WAITING1;
}
con->current_message_state = SHOUT_MSGSTATE_WAITING0;
}
return ret;
break;
case SHOUT_MSGSTATE_SENDING1:
if (con->wqueue.len) {
return shout_connection_iter__message__send_queue(con, shout);
} else {
return SHOUT_RS_ERROR;
}
break;
case SHOUT_MSGSTATE_WAITING0:
case SHOUT_MSGSTATE_WAITING1:
ret = shout_connection_iter__wait_for_io(con, shout, 1, 0);
......@@ -354,6 +357,8 @@ static shout_connection_return_state_t shout_connection_iter__protocol(shout_con
int shout_connection_iter(shout_connection_t *con, shout_t *shout)
{
int found;
if (!con || !shout)
return SHOUTERR_INSANE;
......@@ -363,6 +368,7 @@ int shout_connection_iter(shout_connection_t *con, shout_t *shou
#define __iter(what) \
while (con->target_ ## what ## _state != con->current_ ## what ## _state) { \
found = 1; \
shout_connection_return_state_t ret = shout_connection_iter__ ## what (con, shout); \
switch (ret) { \
case SHOUT_RS_DONE: \
......@@ -370,7 +376,7 @@ int shout_connection_iter(shout_connection_t *con, shout_t *shou
break; \
case SHOUT_RS_TIMEOUT: \
case SHOUT_RS_NOTNOW: \
return SHOUTERR_RETRY; \
goto retry; \
return SHOUTERR_RETRY; \
break; \
case SHOUT_RS_ERROR: \
......@@ -379,9 +385,13 @@ int shout_connection_iter(shout_connection_t *con, shout_t *shou
} \
}
__iter(socket)
__iter(message)
__iter(protocol)
retry:
do {
found = 0;
__iter(socket)
__iter(message)
__iter(protocol)
} while (found);
return SHOUTERR_SUCCESS;
}
......@@ -443,5 +453,44 @@ int shout_connection_connect(shout_connection_t *con, shout_t *s
}
con->current_socket_state = SHOUT_SOCKSTATE_CONNECTING;
con->target_socket_state = SHOUT_SOCKSTATE_CONNECTED;
return SHOUTERR_SUCCESS;
}
int shout_connection_disconnect(shout_connection_t *con)
{
if (!con)
return SHOUTERR_INSANE;
#ifdef HAVE_OPENSSL
if (con->tls)
shout_tls_close(con->tls);
con->tls = NULL;
#endif
if (con->socket != SOCK_ERROR)
sock_close(con->socket);
con->socket = SOCK_ERROR;
con->target_socket_state = SHOUT_SOCKSTATE_UNCONNECTED;
con->current_socket_state = SHOUT_SOCKSTATE_UNCONNECTED;
return SHOUTERR_SUCCESS;
}
ssize_t shout_connection_send(shout_connection_t *con, shout_t *shout, const void *buf, size_t len)
{
int ret;
if (!con || !shout)
return -1;
if (con->current_message_state != SHOUT_MSGSTATE_SENDING1)
return -1;
ret = shout_queue_data(&(con->wqueue), buf, len);
if (ret != SHOUTERR_SUCCESS)
return -1;
shout_connection_iter(con, shout);
return len;
}
......@@ -34,6 +34,11 @@
#include "shout_private.h"
#include "common/httpp/httpp.h"
typedef enum {
STATE_CHALLENGE = 0,
STATE_SOURCE,
} shout_http_protocol_state_t;
char *shout_http_basic_authorization(shout_t *self)
{
char *out, *in;
......@@ -60,7 +65,7 @@ char *shout_http_basic_authorization(shout_t *self)
return in;
}
int shout_create_http_request(shout_t *self)
shout_connection_return_state_t shout_create_http_request(shout_t *self, shout_connection_t *connection)
{
char *auth;
char *ai;
......@@ -88,7 +93,8 @@ int shout_create_http_request(shout_t *self)
break;
default:
return SHOUTERR_INSANE;
self->error = SHOUTERR_INSANE;
return SHOUT_RS_ERROR;
break;
}
......@@ -98,39 +104,39 @@ int shout_create_http_request(shout_t *self)
do {
if (!(mount = _shout_util_url_encode_resource(self->mount)))
break;
if (shout_queue_printf(self, "SOURCE %s HTTP/1.0\r\n", mount))
if (shout_queue_printf(self->connection, "SOURCE %s HTTP/1.0\r\n", mount))
break;
if (self->password && (self->server_caps & LIBSHOUT_CAP_GOTCAPS)) {
if (! (auth = shout_http_basic_authorization(self)))
break;
if (shout_queue_str(self, auth)) {
if (shout_queue_str(self->connection, auth)) {
free(auth);
break;
}
free(auth);
}
if (self->useragent && shout_queue_printf(self, "Host: %s:%i\r\n", self->host, self->port))
if (shout_queue_printf(self->connection, "Host: %s:%i\r\n", self->host, self->port))
break;
if (self->useragent && shout_queue_printf(self, "User-Agent: %s\r\n", self->useragent))
if (self->useragent && shout_queue_printf(self->connection, "User-Agent: %s\r\n", self->useragent))
break;
if (shout_queue_printf(self, "Content-Type: %s\r\n", mimetype))
if (shout_queue_printf(self->connection, "Content-Type: %s\r\n", mimetype))
break;
if (shout_queue_printf(self, "ice-public: %d\r\n", self->public))
if (shout_queue_printf(self->connection, "ice-public: %d\r\n", self->public))
break;
_SHOUT_DICT_FOREACH(self->meta, dict, key, val) {
if (val && shout_queue_printf(self, "ice-%s: %s\r\n", key, val))
if (val && shout_queue_printf(self->connection, "ice-%s: %s\r\n", key, val))
break;
}
if ((ai = _shout_util_dict_urlencode(self->audio_info, ';'))) {
if (shout_queue_printf(self, "ice-audio-info: %s\r\n", ai)) {
if (shout_queue_printf(self->connection, "ice-audio-info: %s\r\n", ai)) {
free(ai);
break;
}
free(ai);
}
if (shout_queue_str(self, "\r\n"))
if (shout_queue_str(self->connection, "\r\n"))
break;
ret = SHOUTERR_SUCCESS;
......@@ -139,20 +145,21 @@ int shout_create_http_request(shout_t *self)
if (mount)
free(mount);
return ret;
self->error = ret;
return ret == SHOUTERR_SUCCESS ? SHOUT_RS_DONE : SHOUT_RS_ERROR;
}
int shout_create_http_request_upgrade(shout_t *self, const char *proto)
{
do {
if (shout_queue_str(self, "OPTIONS * HTTP/1.1\r\nConnection: Upgrade\r\n"))
if (shout_queue_str(self->connection, "OPTIONS * HTTP/1.1\r\nConnection: Upgrade\r\n"))
break;
if (shout_queue_printf(self, "Upgrade: %s\r\n", proto))
if (shout_queue_printf(self->connection, "Upgrade: %s\r\n", proto))
break;
/* Send Host:-header as this one may be used to select cert! */
if (shout_queue_printf(self, "Host: %s:%i\r\n", self->host, self->port))
if (shout_queue_printf(self->connection, "Host: %s:%i\r\n", self->host, self->port))
break;
if (shout_queue_str(self, "\r\n"))
if (shout_queue_str(self->connection, "\r\n"))
break;
return SHOUTERR_SUCCESS;
} while (0);
......@@ -160,7 +167,7 @@ int shout_create_http_request_upgrade(shout_t *self, const char *proto)
return SHOUTERR_MALLOC;
}
int shout_get_http_response(shout_t *self)
shout_connection_return_state_t shout_get_http_response(shout_t *self, shout_connection_t *connection)
{
int blen;
char *pc;
......@@ -170,7 +177,7 @@ int shout_get_http_response(shout_t *self)
/* work from the back looking for \r?\n\r?\n. Anything else means more
* is coming.
*/
for (queue = self->rqueue.head; queue->next; queue = queue->next) ;
for (queue = connection->rqueue.head; queue->next; queue = queue->next) ;
pc = (char*)queue->data + queue->len - 1;
blen = queue->len;
while (blen) {
......@@ -183,8 +190,9 @@ int shout_get_http_response(shout_t *self)
newlines = 0;
}
if (newlines == 2)
return SHOUTERR_SUCCESS;
if (newlines == 2) {
return SHOUT_RS_DONE;
}
blen--;
pc--;
......@@ -196,7 +204,7 @@ int shout_get_http_response(shout_t *self)
}
}
return SHOUTERR_BUSY;
return SHOUT_RS_NOTNOW;
}
static inline void parse_http_response_caps(shout_t *self, const char *header, const char *str) {
......@@ -295,7 +303,7 @@ static inline int eat_body(shout_t *self, size_t len, const char *buf, size_t bu
return 0;
}
int shout_parse_http_response(shout_t *self)
shout_connection_return_state_t shout_parse_http_response(shout_t *self, shout_connection_t *connection)
{
http_parser_t *parser;
char *header = NULL;
......@@ -304,12 +312,15 @@ int shout_parse_http_response(shout_t *self)
const char *retcode;
int ret;
char *mount;
int consider_retry = 0;
/* all this copying! */
hlen = shout_queue_collect(self->rqueue.head, &header);
if (hlen <= 0)
return SHOUTERR_MALLOC;
shout_queue_free(&self->rqueue);
hlen = shout_queue_collect(self->connection->rqueue.head, &header);
if (hlen <= 0) {
self->error = SHOUTERR_MALLOC;
return SHOUT_RS_ERROR;
}
shout_queue_free(&self->connection->rqueue);
parser = httpp_create_parser();
httpp_initialize(parser, NULL);
......@@ -317,7 +328,8 @@ int shout_parse_http_response(shout_t *self)
if (!(mount = _shout_util_url_encode(self->mount))) {
httpp_destroy(parser);
free(header);
return SHOUTERR_MALLOC;
self->error = SHOUTERR_MALLOC;
return SHOUT_RS_ERROR;
}
ret = httpp_parse_response(parser, header, hlen, mount);
......@@ -340,7 +352,9 @@ int shout_parse_http_response(shout_t *self)
#endif
httpp_destroy(parser);
free(header);
return SHOUTERR_SUCCESS;
connection->current_message_state = SHOUT_MSGSTATE_SENDING1;
connection->target_message_state = SHOUT_MSGSTATE_WAITING1;
return SHOUT_RS_DONE;
} else if ((code >= 200 && code < 300) || code == 401 || code == 405 || code == 426 || code == 101) {
const char *content_length = httpp_getvar(parser, "content-length");
if (content_length) {
......@@ -359,20 +373,32 @@ int shout_parse_http_response(shout_t *self)
break;
}
#endif
self->retry++;
if (self->retry > LIBSHOUT_MAX_RETRY)
self->retry = 0;
goto retry;
} else {
self->retry = 0;
consider_retry = 1;
}
}
failure:
self->retry = 0;
retry:
free(header);
httpp_destroy(parser);
return self->error = SHOUTERR_NOLOGIN;
switch ((shout_http_protocol_state_t)connection->current_protocol_state) {
case STATE_CHALLENGE:
if (consider_retry) {
shout_connection_disconnect(connection);
shout_connection_connect(connection, self);
connection->current_message_state = SHOUT_MSGSTATE_CREATING0;
connection->target_message_state = SHOUT_MSGSTATE_SENDING1;
connection->target_protocol_state = STATE_SOURCE;
return SHOUT_RS_NOTNOW;
} else {
self->error = SHOUTERR_NOLOGIN;
return SHOUT_RS_ERROR;
}
break;
case STATE_SOURCE:
default:
self->error = SHOUTERR_NOLOGIN;
return SHOUT_RS_ERROR;
break;
}
}
......@@ -30,7 +30,7 @@
static int shout_create_icy_request_poke(shout_t *self)
{
if (shout_queue_printf(self, "!POKE\nicy-name:libshout server poke request\n\n")) {
if (shout_queue_printf(self->connection, "!POKE\nicy-name:libshout server poke request\n\n")) {
return SHOUTERR_MALLOC;
} else {
return SHOUTERR_SUCCESS;
......@@ -49,28 +49,28 @@ static int shout_create_icy_request_real(shout_t *self)
ret = SHOUTERR_MALLOC;
do {
if (shout_queue_printf(self, "%s\n", self->password))
if (shout_queue_printf(self->connection, "%s\n", self->password))
break;
if (shout_queue_printf(self, "icy-name:%s\n", shout_get_meta(self, "name")))
if (shout_queue_printf(self->connection, "icy-name:%s\n", shout_get_meta(self, "name")))
break;
val = shout_get_meta(self, "url");
if (shout_queue_printf(self, "icy-url:%s\n", val ? val : "http://www.icecast.org/"))
if (shout_queue_printf(self->connection, "icy-url:%s\n", val ? val : "http://www.icecast.org/"))
break;
val = shout_get_meta(self, "irc");
if (shout_queue_printf(self, "icy-irc:%s\n", val ? val : ""))
if (shout_queue_printf(self->connection, "icy-irc:%s\n", val ? val : ""))
break;
val = shout_get_meta(self, "aim");
if (shout_queue_printf(self, "icy-aim:%s\n", val ? val : ""))
if (shout_queue_printf(self->connection, "icy-aim:%s\n", val ? val : ""))
break;
val = shout_get_meta(self, "icq");
if (shout_queue_printf(self, "icy-icq:%s\n", val ? val : ""))
if (shout_queue_printf(self->connection, "icy-icq:%s\n", val ? val : ""))
break;
if (shout_queue_printf(self, "icy-pub:%i\n", self->public))
if (shout_queue_printf(self->connection, "icy-pub:%i\n", self->public))
break;
val = shout_get_meta(self, "genre");
if (shout_queue_printf(self, "icy-genre:%s\n", val ? val : "icecast"))
if (shout_queue_printf(self->connection, "icy-genre:%s\n", val ? val : "icecast"))
break;
if (shout_queue_printf(self, "icy-br:%s\n\n", bitrate))
if (shout_queue_printf(self->connection, "icy-br:%s\n\n", bitrate))
break;
ret = SHOUTERR_SUCCESS;
......@@ -79,11 +79,16 @@ static int shout_create_icy_request_real(shout_t *self)
return ret;
}
int shout_create_icy_request(shout_t *self)
shout_connection_return_state_t shout_create_icy_request(shout_t *self, shout_connection_t *connection)
{
int ret;
if (self->server_caps & LIBSHOUT_CAP_GOTCAPS) {
return shout_create_icy_request_real(self);
ret = shout_create_icy_request_real(self);
} else {
return shout_create_icy_request_poke(self);
ret = shout_create_icy_request_poke(self);
}
self->error = ret;
return ret == SHOUTERR_SUCCESS ? SHOUT_RS_DONE : SHOUT_RS_ERROR;
}
......@@ -97,9 +97,9 @@ static int command_send(shout_t *self,
header[8] = (datalen & 0xFF00) >> 8;
header[9] = (datalen & 0x00FF);
shout_queue_data(&self->wqueue, header, HEADER_SIZE);
shout_queue_data(&self->connection->wqueue, header, HEADER_SIZE);
if (datalen)
shout_queue_data(&self->wqueue, data, datalen);
shout_queue_data(&self->connection->wqueue, data, datalen);
return SHOUTERR_SUCCESS;
}
......@@ -196,27 +196,33 @@ static int shout_create_roaraudio_request_exec(shout_t *self)
* after that. This very much like with SOURCE requests.
* so no hard deal to intigrate.
*/
return command_send(self, CMD_EXEC_STREAM, self->protocol_extra, NULL, 0);
return command_send(self, CMD_EXEC_STREAM, self->connection->protocol_extra.si, NULL, 0);
}
int shout_create_roaraudio_request(shout_t *self)
shout_connection_return_state_t shout_create_roaraudio_request(shout_t *self, shout_connection_t *connection)
{
switch ((shout_roar_protocol_state_t)self->protocol_state) {
int ret;
switch ((shout_roar_protocol_state_t)self->connection->current_protocol_state) {
case STATE_IDENT:
return shout_create_roaraudio_request_ident(self);
ret = shout_create_roaraudio_request_ident(self);
break;
case STATE_AUTH:
return shout_create_roaraudio_request_auth(self);
ret = shout_create_roaraudio_request_auth(self);
break;
case STATE_NEW_STREAM:
return shout_create_roaraudio_request_new_stream(self);
ret = shout_create_roaraudio_request_new_stream(self);
break;
case STATE_EXEC:
return shout_create_roaraudio_request_exec(self);
ret = shout_create_roaraudio_request_exec(self);
break;
default:
ret = SHOUTERR_INSANE;
break;
}
return SHOUTERR_INSANE;
self->error = ret;
return ret == SHOUTERR_SUCCESS ? SHOUT_RS_DONE : SHOUT_RS_ERROR;
}
int shout_get_roaraudio_response(shout_t *self)
......@@ -225,7 +231,7 @@ int shout_get_roaraudio_response(shout_t *self)
size_t total_len = 0;
uint8_t header[HEADER_SIZE];
for (queue = self->rqueue.head; queue; queue = queue->next) {
for (queue = self->connection->rqueue.head; queue; queue = queue->next) {
if (total_len < 10)
memcpy(header + total_len, queue->data, queue->len > (HEADER_SIZE - total_len) ? (HEADER_SIZE - total_len) : queue->len);
total_len += queue->len;
......@@ -262,11 +268,11 @@ int shout_parse_roaraudio_response(shout_t *self)
* "data length" is already checked by shout_get_roaraudio_response().
*/
if (shout_queue_collect(self->rqueue.head, &data) != HEADER_SIZE) {
if (shout_queue_collect(self->connection->rqueue.head, &data) != HEADER_SIZE) {
free(data);
return SHOUTERR_INSANE;
}
shout_queue_free(&self->rqueue);
shout_queue_free(&self->connection->rqueue);
memcpy(header, data, HEADER_SIZE);
free(data);
......@@ -278,19 +284,19 @@ int shout_parse_roaraudio_response(shout_t *self)
if (header[1] != CMD_OK)
return SHOUTERR_NOLOGIN;
switch ((shout_roar_protocol_state_t)self->protocol_state) {
switch ((shout_roar_protocol_state_t)self->connection->current_protocol_state) {
case STATE_IDENT:
self->protocol_state = STATE_AUTH;
self->connection->current_protocol_state = STATE_AUTH;
self->server_caps |= LIBSHOUT_CAP_GOTCAPS;
break;
case STATE_AUTH:
self->protocol_state = STATE_NEW_STREAM;
self->connection->current_protocol_state = STATE_NEW_STREAM;
break;
case STATE_NEW_STREAM:
self->protocol_extra = (((unsigned int)header[2]) << 8) | (unsigned int)header[3];
self->protocol_state = STATE_EXEC;
self->connection->protocol_extra.si = (((unsigned int)header[2]) << 8) | (unsigned int)header[3];
self->connection->current_protocol_state = STATE_EXEC;
break;
case STATE_EXEC:
......@@ -303,6 +309,6 @@ int shout_parse_roaraudio_response(shout_t *self)
break;
}
self->state = SHOUT_STATE_REQ_CREATION;
self->connection->current_message_state = SHOUT_MSGSTATE_CREATING0;
return SHOUTERR_RETRY;
}
......@@ -31,7 +31,7 @@
#include <shout/shout.h>
#include "shout_private.h"
int shout_create_xaudiocast_request(shout_t *self)
shout_connection_return_state_t shout_create_xaudiocast_request(shout_t *self, shout_connection_t *connection)
{
const char *bitrate;
const char *val;
......@@ -46,26 +46,26 @@ int shout_create_xaudiocast_request(shout_t *self)
do {
if (!(mount = _shout_util_url_encode_resource(self->mount)))
break;
if (shout_queue_printf(self, "SOURCE %s %s\n", self->password, mount))
if (shout_queue_printf(self->connection, "SOURCE %s %s\n", self->password, mount))
break;
if (shout_queue_printf(self, "x-audiocast-name: %s\n", shout_get_meta(self, "name")))
if (shout_queue_printf(self->connection, "x-audiocast-name: %s\n", shout_get_meta(self, "name")))
break;
val = shout_get_meta(self, "url");
if (shout_queue_printf(self, "x-audiocast-url: %s\n", val ? val : "http://www.icecast.org/"))
if (shout_queue_printf(self->connection, "x-audiocast-url: %s\n", val ? val : "http://www.icecast.org/"))
break;
val = shout_get_meta(self, "genre");
if (shout_queue_printf(self, "x-audiocast-genre: %s\n", val ? val : "icecast"))
if (shout_queue_printf(self->connection, "x-audiocast-genre: %s\n", val ? val : "icecast"))
break;
if (shout_queue_printf(self, "x-audiocast-bitrate: %s\n", bitrate))
if (shout_queue_printf(self->connection, "x-audiocast-bitrate: %s\n", bitrate))
break;
if (shout_queue_printf(self, "x-audiocast-public: %i\n", self->public))
if (shout_queue_printf(self->connection, "x-audiocast-public: %i\n", self->public))
break;
val = shout_get_meta(self, "description");
if (shout_queue_printf(self, "x-audiocast-description: %s\n", val ? val : "Broadcasting with the icecast streaming media server!"))
if (shout_queue_printf(self->connection, "x-audiocast-description: %s\n", val ? val : "Broadcasting with the icecast streaming media server!"))
break;
if (self->dumpfile && shout_queue_printf(self, "x-audiocast-dumpfile: %s\n", self->dumpfile))
if (self->dumpfile && shout_queue_printf(self->connection, "x-audiocast-dumpfile: %s\n", self->dumpfile))
break;
if (shout_queue_str(self, "\n"))
if (shout_queue_str(self->connection, "\n"))
break;
ret = SHOUTERR_SUCCESS;
......@@ -74,12 +74,13 @@ int shout_create_xaudiocast_request(shout_t *self)
if (mount)
free(mount);
return ret;
self->error = ret;
return ret == SHOUTERR_SUCCESS ? SHOUT_RS_DONE : SHOUT_RS_ERROR;
}
int shout_get_xaudiocast_response(shout_t *self)
{
shout_buf_t *queue = self->rqueue.head;
shout_buf_t *queue = self->connection->rqueue.head;
unsigned int i;
do {
......@@ -99,9 +100,9 @@ int shout_parse_xaudiocast_response(shout_t *self)
{
char *response;
if (shout_queue_collect(self->rqueue.head, &response) <= 0)
if (shout_queue_collect(self->connection->rqueue.head, &response) <= 0)
return SHOUTERR_MALLOC;
shout_queue_free(&self->rqueue);
shout_queue_free(&self->connection->rqueue);
if (!strstr(response, "OK")) {
free(response);
......@@ -109,10 +110,9 @@ int shout_parse_xaudiocast_response(shout_t *self)
/* check to see if that is a response to a POKE. */
if (!(self->server_caps & LIBSHOUT_CAP_GOTCAPS)) {
self->server_caps |= LIBSHOUT_CAP_GOTCAPS;
self->retry++;
if (self->retry > LIBSHOUT_MAX_RETRY)
self->retry = 0;
return SHOUTERR_SOCKET;
shout_connection_disconnect(self->connection);
shout_connection_connect(self->connection, self);
return SHOUTERR_BUSY;
} else {
return SHOUTERR_NOLOGIN;
}
......
......@@ -71,18 +71,19 @@ int shout_queue_data(shout_queue_t *queue, const unsigned char *data, size_t len
return SHOUTERR_SUCCESS;
}
int shout_queue_str(shout_t *self, const char *str)
int shout_queue_str(shout_connection_t *self, const char *str)
{
return shout_queue_data(&self->wqueue, (const unsigned char*)str, strlen(str));
}
/* this should be shared with sock_write. Create libicecommon. */
int shout_queue_printf(shout_t *self, const char *fmt, ...)
int shout_queue_printf(shout_connection_t *self, const char *fmt, ...)
{
char buffer[1024];
char *buf;
va_list ap, ap_retry;
int len;
int ret = SHOUTERR_SUCCESS;
buf = buffer;
......@@ -91,7 +92,6 @@ int shout_queue_printf(shout_t *self, const char *fmt, ...)
len = vsnprintf(buf, sizeof(buffer), fmt, ap);
self->error = SHOUTERR_SUCCESS;
if (len > 0) {
if ((size_t)len < sizeof(buffer)) {
shout_queue_data(&self->wqueue, (unsigned char*)buf, len);
......@@ -102,7 +102,7 @@ int shout_queue_printf(shout_t *self, const char *fmt, ...)
shout_queue_data(&self->wqueue, (unsigned char*)buf, len);
free(buf);
} else {
self->error = SHOUTERR_MALLOC;
ret = SHOUTERR_MALLOC;
}
}
}
......@@ -110,7 +110,7 @@ int shout_queue_printf(shout_t *self, const char *fmt, ...)
va_end(ap_retry);
va_end(ap);
return self->error;
return ret;
}
void shout_queue_free(shout_queue_t *queue)
......
This diff is collapsed.
......@@ -90,6 +90,7 @@ typedef struct {
size_t len;
} shout_queue_t;
/*
typedef enum {
SHOUT_STATE_UNCONNECTED = 0,
SHOUT_STATE_CONNECT_PENDING,
......@@ -100,6 +101,7 @@ typedef enum {
SHOUT_STATE_CONNECTED,
SHOUT_STATE_RECONNECT
} shout_state_e;
*/
typedef enum {
SHOUT_SOCKSTATE_UNCONNECTED = 0,
......@@ -204,29 +206,19 @@ struct shout {
char *ca_file;
char *allowed_ciphers;
char *client_certificate;
shout_tls_t *tls;
#endif
/* server capabilities (LIBSHOUT_CAP_*) */
uint32_t server_caps;
/* Should we retry on error? */
int retry;
/* socket the connection is on */