summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2018-04-07 20:17:23 +0200
committerLars-Dominik Braun <lars@6xq.net>2018-04-07 20:18:47 +0200
commitff4f15214100d209f39e4ed85f47e572c8fe9289 (patch)
tree1cea789efe2396b1855f5f65fbb79244cb0cf8f1
parent3c4d8f65896253a82e19adcbe2808a863a99f74f (diff)
downloadpianobar-ff4f15214100d209f39e4ed85f47e572c8fe9289.tar.gz
pianobar-ff4f15214100d209f39e4ed85f47e572c8fe9289.tar.bz2
pianobar-ff4f15214100d209f39e4ed85f47e572c8fe9289.zip
Add network timeouts and retries
All network operations can time out now. API requests are retried up to three times (default). Replaces setting max_player_errors with max_retries, which is used for player and API. Adds timeout setting. Partially reverts 436a1d4012553a2f33d0e3a5180b3b5ae0378bdd and fixes (at least) issue #657. Thanks to @exarkun for testing.
-rw-r--r--contrib/pianobar.18
-rw-r--r--src/main.c2
-rw-r--r--src/player.c10
-rw-r--r--src/settings.c9
-rw-r--r--src/settings.h2
-rw-r--r--src/ui.c17
6 files changed, 39 insertions, 9 deletions
diff --git a/contrib/pianobar.1 b/contrib/pianobar.1
index 98e67be..b6c743a 100644
--- a/contrib/pianobar.1
+++ b/contrib/pianobar.1
@@ -333,8 +333,8 @@ Keep a history of the last n songs (5, by default). You can rate these songs.
Icon for loved songs.
.TP
-.B max_player_errors = 5
-Amount of song download errors in a row after pianobar stops playback.
+.B max_retry = 3
+Max failures for several actions before giving up.
.TP
.B partner_password = AC7IBG09A3DTSYM4R41UJWL07VLN8JI7
@@ -370,6 +370,10 @@ sorts by name from a to z, quickmix_01_name_za by type (quickmix at the
bottom) and name from z to a.
.TP
+.B timeout = 30
+Network operation timeout.
+
+.TP
.B tired_icon = zZ
Icon for temporarily suspended songs.
diff --git a/src/main.c b/src/main.c
index 2a0e3f7..6388cde 100644
--- a/src/main.c
+++ b/src/main.c
@@ -293,7 +293,7 @@ static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) {
app->playerErrors = 0;
} else if (threadRet == (void *) PLAYER_RET_SOFTFAIL) {
++app->playerErrors;
- if (app->playerErrors >= app->settings.maxPlayerErrors) {
+ if (app->playerErrors >= app->settings.maxRetry) {
/* don't continue playback if thread reports too many error */
app->nextStation = NULL;
}
diff --git a/src/player.c b/src/player.c
index 977007d..df962fa 100644
--- a/src/player.c
+++ b/src/player.c
@@ -174,8 +174,16 @@ static bool openStream (player_t * const player) {
player->fctx->interrupt_callback.callback = intCb;
player->fctx->interrupt_callback.opaque = player;
+ /* in microseconds */
+ unsigned long int timeout = player->settings->timeout*1000000;
+ char timeoutStr[16];
+ ret = snprintf (timeoutStr, sizeof (timeoutStr), "%lu", timeout);
+ assert (ret < sizeof (timeoutStr));
+ AVDictionary *options = NULL;
+ av_dict_set (&options, "timeout", timeoutStr, 0);
+
assert (player->url != NULL);
- if ((ret = avformat_open_input (&player->fctx, player->url, NULL, NULL)) < 0) {
+ if ((ret = avformat_open_input (&player->fctx, player->url, NULL, &options)) < 0) {
softfail ("Unable to open audio file");
}
diff --git a/src/settings.c b/src/settings.c
index 9f05adc..06ad818 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -161,8 +161,9 @@ void BarSettingsRead (BarSettings_t *settings) {
settings->autoselect = true;
settings->history = 5;
settings->volume = 0;
+ settings->timeout = 30; /* seconds */
settings->gainMul = 1.0;
- settings->maxPlayerErrors = 5;
+ settings->maxRetry = 3;
settings->sortOrder = BAR_SORT_NAME_AZ;
settings->loveIcon = strdup (" <3");
settings->banIcon = strdup (" </3");
@@ -337,8 +338,10 @@ void BarSettingsRead (BarSettings_t *settings) {
settings->eventCmd = BarSettingsExpandTilde (val, userhome);
} else if (streq ("history", key)) {
settings->history = atoi (val);
- } else if (streq ("max_player_errors", key)) {
- settings->maxPlayerErrors = atoi (val);
+ } else if (streq ("max_retry", key)) {
+ settings->maxRetry = atoi (val);
+ } else if (streq ("timeout", key)) {
+ settings->timeout = atoi (val);
} else if (streq ("sort", key)) {
size_t i;
static const char *mapping[] = {"name_az",
diff --git a/src/settings.h b/src/settings.h
index b70e4f9..9b74602 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -84,7 +84,7 @@ typedef struct {
typedef struct {
bool autoselect;
- unsigned int history, maxPlayerErrors;
+ unsigned int history, maxRetry, timeout;
int volume;
float gainMul;
BarStationSorting_t sortOrder;
diff --git a/src/ui.c b/src/ui.c
index 5c4e42d..689ad1e 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -205,6 +205,7 @@ static CURLcode BarPianoHttpRequest (CURL * const http,
setAndCheck (CURLOPT_PROGRESSDATA, &lint);
setAndCheck (CURLOPT_NOPROGRESS, 0);
setAndCheck (CURLOPT_POST, 1);
+ setAndCheck (CURLOPT_TIMEOUT, settings->timeout);
if (settings->caBundle != NULL) {
setAndCheck (CURLOPT_CAINFO, settings->caBundle);
}
@@ -241,7 +242,21 @@ static CURLcode BarPianoHttpRequest (CURL * const http,
list = curl_slist_append (list, "Content-Type: text/plain");
setAndCheck (CURLOPT_HTTPHEADER, list);
- httpret = curl_easy_perform (http);
+ unsigned int retry = 0;
+ do {
+ httpret = curl_easy_perform (http);
+ ++retry;
+ if (httpret == CURLE_OPERATION_TIMEDOUT) {
+ free (buffer.data);
+ buffer.data = NULL;
+ buffer.pos = 0;
+ if (retry > settings->maxRetry) {
+ break;
+ }
+ } else {
+ break;
+ }
+ } while (true);
curl_slist_free_all (list);