From ff4f15214100d209f39e4ed85f47e572c8fe9289 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sat, 7 Apr 2018 20:17:23 +0200 Subject: 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. --- contrib/pianobar.1 | 8 ++++++-- src/main.c | 2 +- src/player.c | 10 +++++++++- src/settings.c | 9 ++++++--- src/settings.h | 2 +- src/ui.c | 17 ++++++++++++++++- 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 @@ -369,6 +369,10 @@ Sort station list by name or type (is quickmix) and name. name_az for example 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 (" 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); -- cgit v1.2.3