Commit 5719c513 authored by Philipp Schafft's avatar Philipp Schafft
Browse files

Feature: Added support for timeouts

parent 9b0e7964
......@@ -101,7 +101,7 @@ int shout_connection_unref(shout_connection_t *con)
return SHOUTERR_SUCCESS;
}
static struct timeval shout_connection_iter__wait_for_io__get_timeout(shout_connection_t *con, shout_t *shout)
static struct timeval shout_connection_iter__wait_for_io__get_timeout(shout_connection_t *con, shout_t *shout, uint64_t timeout)
{
static const struct timeval tv_blocking = {
.tv_sec = 8,
......@@ -112,16 +112,22 @@ static struct timeval shout_connection_iter__wait_for_io__get_timeout(shout_conn
.tv_usec = 1000
};
if (con->nonblocking) {
if (timeout) {
struct timeval tv = {
.tv_sec = timeout / 1000,
.tv_usec = (timeout % 1000) * 1000
};
return tv;
} else if (con->nonblocking) {
return tv_nonblocking;
} else {
return tv_blocking;
}
}
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)
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, uint64_t timeout)
{
struct timeval tv = shout_connection_iter__wait_for_io__get_timeout(con, shout);
struct timeval tv = shout_connection_iter__wait_for_io__get_timeout(con, shout, timeout);
fd_set fhset_r;
fd_set fhset_w;
fd_set fhset_e;
......@@ -162,7 +168,7 @@ static shout_connection_return_state_t shout_connection_iter__socket(shout_conne
break;
case SHOUT_SOCKSTATE_CONNECTING:
if (con->nonblocking) {
ret = shout_connection_iter__wait_for_io(con, shout, 1, 1);
ret = shout_connection_iter__wait_for_io(con, shout, 1, 1, 0);
if (ret != SHOUT_RS_DONE) {
return ret;
}
......@@ -349,7 +355,22 @@ static shout_connection_return_state_t shout_connection_iter__message(shout_conn
break;
case SHOUT_MSGSTATE_WAITING0:
case SHOUT_MSGSTATE_WAITING1:
ret = shout_connection_iter__wait_for_io(con, shout, 1, 0);
if (con->wait_timeout) {
uint64_t now = timing_get_time();
if (now > con->wait_timeout) {
if (con->current_message_state == SHOUT_MSGSTATE_WAITING0) {
con->current_message_state = SHOUT_MSGSTATE_RECEIVED0;
} else {
con->current_message_state = SHOUT_MSGSTATE_RECEIVING1;
}
con->wait_timeout_happened = 1;
return SHOUT_RS_DONE;
} else {
ret = shout_connection_iter__wait_for_io(con, shout, 1, 0, con->wait_timeout - now);
}
} else {
ret = shout_connection_iter__wait_for_io(con, shout, 1, 0, 0);
}
if (ret == SHOUT_RS_DONE) {
if (con->current_message_state == SHOUT_MSGSTATE_WAITING0) {
con->current_message_state = SHOUT_MSGSTATE_RECEIVING0;
......@@ -375,6 +396,7 @@ static shout_connection_return_state_t shout_connection_iter__message(shout_conn
case SHOUT_MSGSTATE_RECEIVED1:
if (con->impl->msg_parse)
ret = con->impl->msg_parse(shout, con);
shout_connection_set_wait_timeout(con, shout, 0);
return ret;
break;
case SHOUT_MSGSTATE_PARSED_INFORMATIONAL0:
......@@ -506,7 +528,30 @@ int shout_connection_set_nonblocking(shout_connection_t *con, un
return SHOUTERR_SUCCESS;
}
int shout_connection_set_next_timeout(shout_connection_t *con, shout_t *shout, uint32_t timeout /* [ms] */);
int shout_connection_set_wait_timeout(shout_connection_t *con, shout_t *shout, uint64_t timeout /* [ms] */)
{
if (!con || !shout)
return SHOUTERR_INSANE;
if (timeout) {
con->wait_timeout = timing_get_time() + timeout;
} else {
con->wait_timeout = 0;
}
con->wait_timeout_happened = 0;
return SHOUTERR_SUCCESS;
}
int shout_connection_get_wait_timeout_happened(shout_connection_t *con, shout_t *shout) /* returns SHOUTERR_* or > 0 for true */
{
if (!con || !shout)
return SHOUTERR_INSANE;
return con->wait_timeout_happened;
}
int shout_connection_connect(shout_connection_t *con, shout_t *shout)
{
int port;
......
......@@ -193,6 +193,10 @@ struct shout_connection_tag {
shout_queue_t rqueue;
shout_queue_t wqueue;
uint64_t wait_timeout;
/* maybe we want to convert this to general flag vector later */
int wait_timeout_happened;
/* server capabilities (LIBSHOUT_CAP_*) */
uint32_t server_caps;
......@@ -279,7 +283,8 @@ int shout_connection_unref(shout_connection_t *con);
int shout_connection_iter(shout_connection_t *con, shout_t *shout);
int shout_connection_select_tlsmode(shout_connection_t *con, int tlsmode);
int shout_connection_set_nonblocking(shout_connection_t *con, unsigned int nonblocking);
int shout_connection_set_next_timeout(shout_connection_t *con, shout_t *shout, uint32_t timeout /* [ms] */);
int shout_connection_set_wait_timeout(shout_connection_t *con, shout_t *shout, uint64_t timeout /* [ms] */);
int shout_connection_get_wait_timeout_happened(shout_connection_t *con, shout_t *shout); /* returns SHOUTERR_* or > 0 for true */
int shout_connection_connect(shout_connection_t *con, shout_t *shout);
int shout_connection_disconnect(shout_connection_t *con);
ssize_t shout_connection_send(shout_connection_t *con, shout_t *shout, const void *buf, size_t len);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment