summaryrefslogtreecommitdiff
path: root/src/ui.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui.c')
-rw-r--r--src/ui.c117
1 files changed, 64 insertions, 53 deletions
diff --git a/src/ui.c b/src/ui.c
index 779dbf8..92a91c2 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -158,6 +158,18 @@ static size_t httpFetchCb (char *ptr, size_t size, size_t nmemb,
return recvSize;
}
+/* libcurl progress callback. aborts the current request if user pressed ^C
+ */
+int progressCb (void * const data, double dltotal, double dlnow,
+ double ultotal, double ulnow) {
+ const sig_atomic_t lint = *((sig_atomic_t *) data);
+ if (lint) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
#define setAndCheck(k,v) \
httpret = curl_easy_setopt (http, k, v); \
assert (httpret == CURLE_OK);
@@ -165,6 +177,7 @@ static size_t httpFetchCb (char *ptr, size_t size, size_t nmemb,
static CURLcode BarPianoHttpRequest (CURL * const http,
const BarSettings_t * const settings, PianoRequest_t * const req) {
buffer buffer = {NULL, 0};
+ sig_atomic_t lint = 0, *prevint;
char url[2048];
int ret = snprintf (url, sizeof (url), "%s://%s:%s%s",
req->secure ? "https" : "http",
@@ -173,6 +186,10 @@ static CURLcode BarPianoHttpRequest (CURL * const http,
req->urlPath);
assert (ret >= 0 && ret <= (int) sizeof (url));
+ /* save the previous interrupt destination */
+ prevint = interrupted;
+ interrupted = &lint;
+
curl_easy_reset (http);
CURLcode httpret;
setAndCheck (CURLOPT_URL, url);
@@ -180,8 +197,10 @@ static CURLcode BarPianoHttpRequest (CURL * const http,
setAndCheck (CURLOPT_POSTFIELDS, req->postData);
setAndCheck (CURLOPT_WRITEFUNCTION, httpFetchCb);
setAndCheck (CURLOPT_WRITEDATA, &buffer);
+ setAndCheck (CURLOPT_PROGRESSFUNCTION, progressCb);
+ setAndCheck (CURLOPT_PROGRESSDATA, &lint);
+ setAndCheck (CURLOPT_NOPROGRESS, 0);
setAndCheck (CURLOPT_POST, 1);
- setAndCheck (CURLOPT_TIMEOUT, 30);
if (settings->caBundle != NULL) {
setAndCheck (CURLOPT_CAINFO, settings->caBundle);
}
@@ -215,90 +234,82 @@ static CURLcode BarPianoHttpRequest (CURL * const http,
req->responseData = buffer.data;
+ interrupted = prevint;
+
return httpret;
}
/* piano wrapper: prepare/execute http request and pass result back to
- * libpiano (updates data structures)
- * @return 1 on success, 0 otherwise
+ * libpiano
*/
-int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type,
- void *data, PianoReturn_t *pRet, CURLcode *wRet) {
- PianoRequest_t req;
-
- memset (&req, 0, sizeof (req));
+bool BarUiPianoCall (BarApp_t * const app, const PianoRequestType_t type,
+ void * const data, PianoReturn_t * const pRet, CURLcode * const wRet) {
+ PianoReturn_t pRetLocal = PIANO_RET_OK;
+ CURLcode wRetLocal = CURLE_OK;
+ bool ret = false;
/* repeat as long as there are http requests to do */
do {
- req.data = data;
+ PianoRequest_t req = { .data = data, .responseData = NULL };
- *pRet = PianoRequest (&app->ph, &req, type);
- if (*pRet != PIANO_RET_OK) {
- BarUiMsg (&app->settings, MSG_NONE, "Error: %s\n", PianoErrorToStr (*pRet));
- PianoDestroyRequest (&req);
- return 0;
+ pRetLocal = PianoRequest (&app->ph, &req, type);
+ if (pRetLocal != PIANO_RET_OK) {
+ BarUiMsg (&app->settings, MSG_NONE, "Error: %s\n",
+ PianoErrorToStr (pRetLocal));
+ goto cleanup;
}
- *wRet = BarPianoHttpRequest (app->http, &app->settings, &req);
- if (*wRet != CURLE_OK) {
+ wRetLocal = BarPianoHttpRequest (app->http, &app->settings, &req);
+ if (wRetLocal == CURLE_ABORTED_BY_CALLBACK) {
+ BarUiMsg (&app->settings, MSG_NONE, "Interrupted.\n");
+ goto cleanup;
+ } else if (wRetLocal != CURLE_OK) {
BarUiMsg (&app->settings, MSG_NONE, "Network error: %s\n",
- curl_easy_strerror (*wRet));
- if (req.responseData != NULL) {
- free (req.responseData);
- }
- PianoDestroyRequest (&req);
- return 0;
+ curl_easy_strerror (wRetLocal));
+ goto cleanup;
}
- *pRet = PianoResponse (&app->ph, &req);
- if (*pRet != PIANO_RET_CONTINUE_REQUEST) {
+ pRetLocal = PianoResponse (&app->ph, &req);
+ if (pRetLocal != PIANO_RET_CONTINUE_REQUEST) {
/* checking for request type avoids infinite loops */
- if (*pRet == PIANO_RET_P_INVALID_AUTH_TOKEN &&
+ if (pRetLocal == PIANO_RET_P_INVALID_AUTH_TOKEN &&
type != PIANO_REQUEST_LOGIN) {
/* reauthenticate */
- PianoReturn_t authpRet;
- CURLcode authwRet;
PianoRequestDataLogin_t reqData;
reqData.user = app->settings.username;
reqData.password = app->settings.password;
reqData.step = 0;
- BarUiMsg (&app->settings, MSG_NONE, "Reauthentication required... ");
- if (!BarUiPianoCall (app, PIANO_REQUEST_LOGIN, &reqData, &authpRet,
- &authwRet)) {
- *pRet = authpRet;
- *wRet = authwRet;
- if (req.responseData != NULL) {
- free (req.responseData);
- }
- PianoDestroyRequest (&req);
- return 0;
+ BarUiMsg (&app->settings, MSG_NONE,
+ "Reauthentication required... ");
+ if (!BarUiPianoCall (app, PIANO_REQUEST_LOGIN, &reqData,
+ &pRetLocal, &wRetLocal)) {
+ goto cleanup;
} else {
/* try again */
- *pRet = PIANO_RET_CONTINUE_REQUEST;
+ pRetLocal = PIANO_RET_CONTINUE_REQUEST;
BarUiMsg (&app->settings, MSG_INFO, "Trying again... ");
}
- } else if (*pRet != PIANO_RET_OK) {
- BarUiMsg (&app->settings, MSG_NONE, "Error: %s\n", PianoErrorToStr (*pRet));
- if (req.responseData != NULL) {
- free (req.responseData);
- }
- PianoDestroyRequest (&req);
- return 0;
+ } else if (pRetLocal != PIANO_RET_OK) {
+ BarUiMsg (&app->settings, MSG_NONE, "Error: %s\n",
+ PianoErrorToStr (pRetLocal));
+ goto cleanup;
} else {
BarUiMsg (&app->settings, MSG_NONE, "Ok.\n");
+ ret = true;
}
}
- /* we can destroy the request at this point, even when this call needs
- * more than one http request. persistent data (step counter, e.g.) is
- * stored in req.data */
- if (req.responseData != NULL) {
- free (req.responseData);
- }
+
+cleanup:
+ /* persistent data is stored in req.data */
+ free (req.responseData);
PianoDestroyRequest (&req);
- } while (*pRet == PIANO_RET_CONTINUE_REQUEST);
+ } while (pRetLocal == PIANO_RET_CONTINUE_REQUEST);
+
+ *pRet = pRetLocal;
+ *wRet = wRetLocal;
- return 1;
+ return ret;
}
/* Station sorting functions */