summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2015-04-06 12:25:13 +0200
committerLars-Dominik Braun <lars@6xq.net>2015-04-06 12:25:13 +0200
commit4458cbab76fd98989fa2d4260dd20bbbd66297a4 (patch)
tree832c7230129b50c278044cb9f4aabe711697ee69
parentb13b61b77b6d58c8b541bc4628b998681e94875f (diff)
downloadpianobar-4458cbab76fd98989fa2d4260dd20bbbd66297a4.tar.gz
pianobar-4458cbab76fd98989fa2d4260dd20bbbd66297a4.tar.bz2
pianobar-4458cbab76fd98989fa2d4260dd20bbbd66297a4.zip
Switch back to libcurl
Drops libwaitress. Adds the new dependency libcurl and drops gnutls. I wouldn’t say writing my own HTTP library was a mistake – it was not and the experience gained was worth it. Instead I have to acknowledge that libcurl is just better than my own implementation. Sure, it does a lot more than HTTP – one could call that bloat. Yet if you just want to get the job done™ reusing code is the way to go. See #512 and #513.
-rw-r--r--INSTALL2
-rw-r--r--Makefile46
-rw-r--r--src/libpiano/request.c17
-rw-r--r--src/libwaitress/config.h1
-rw-r--r--src/libwaitress/waitress-test.c143
-rw-r--r--src/libwaitress/waitress.c1240
-rw-r--r--src/libwaitress/waitress.h136
-rw-r--r--src/main.c46
-rw-r--r--src/main.h5
-rw-r--r--src/player.h1
-rw-r--r--src/settings.h1
-rw-r--r--src/ui.c122
-rw-r--r--src/ui.h5
-rw-r--r--src/ui_act.c30
14 files changed, 150 insertions, 1645 deletions
diff --git a/INSTALL b/INSTALL
index 0406c7c..b0db803 100644
--- a/INSTALL
+++ b/INSTALL
@@ -7,7 +7,7 @@ Dependencies
- gmake
- pthreads
- libao
-- gnutls
+- libcurl
- gcrypt[1]
- json-c
- libav/ffmpeg[2]
diff --git a/Makefile b/Makefile
index 289b1e6..1667277 100644
--- a/Makefile
+++ b/Makefile
@@ -61,21 +61,12 @@ LIBPIANO_OBJ:=${LIBPIANO_SRC:.c=.o}
LIBPIANO_RELOBJ:=${LIBPIANO_SRC:.c=.lo}
LIBPIANO_INCLUDE:=${LIBPIANO_DIR}
-LIBWAITRESS_DIR:=src/libwaitress
-LIBWAITRESS_SRC:=${LIBWAITRESS_DIR}/waitress.c
-LIBWAITRESS_HDR:=\
- ${LIBWAITRESS_DIR}/config.h \
- ${LIBWAITRESS_DIR}/waitress.h
-LIBWAITRESS_OBJ:=${LIBWAITRESS_SRC:.c=.o}
-LIBWAITRESS_RELOBJ:=${LIBWAITRESS_SRC:.c=.lo}
-LIBWAITRESS_INCLUDE:=${LIBWAITRESS_DIR}
-
-LIBWAITRESS_TEST_SRC=${LIBWAITRESS_DIR}/waitress-test.c
-LIBWAITRESS_TEST_OBJ:=${LIBWAITRESS_TEST_SRC:.c=.o}
-
LIBAV_CFLAGS=$(shell pkg-config --cflags libavcodec libavformat libavutil libavfilter)
LIBAV_LDFLAGS=$(shell pkg-config --libs libavcodec libavformat libavutil libavfilter)
+LIBCURL_CFLAGS=$(shell pkg-config --cflags libcurl)
+LIBCURL_LDFLAGS=$(shell pkg-config --libs libcurl)
+
LIBGNUTLS_CFLAGS:=$(shell pkg-config --cflags gnutls)
LIBGNUTLS_LDFLAGS:=$(shell pkg-config --libs gnutls)
@@ -86,12 +77,12 @@ LIBJSONC_CFLAGS:=$(shell pkg-config --cflags json-c 2>/dev/null || pkg-config --
LIBJSONC_LDFLAGS:=$(shell pkg-config --libs json-c 2>/dev/null || pkg-config --libs json)
# combine all flags
-ALL_CFLAGS:=${CFLAGS} -I ${LIBPIANO_INCLUDE} -I ${LIBWAITRESS_INCLUDE} \
+ALL_CFLAGS:=${CFLAGS} -I ${LIBPIANO_INCLUDE} \
${LIBAV_CFLAGS} ${LIBGNUTLS_CFLAGS} \
${LIBGCRYPT_CFLAGS} ${LIBJSONC_CFLAGS}
ALL_LDFLAGS:=${LDFLAGS} -lao -lpthread -lm \
${LIBAV_LDFLAGS} ${LIBGNUTLS_LDFLAGS} \
- ${LIBGCRYPT_LDFLAGS} ${LIBJSONC_LDFLAGS}
+ ${LIBGCRYPT_LDFLAGS} ${LIBJSONC_LDFLAGS} ${LIBCURL_LDFLAGS}
# build pianobar
ifeq (${DYNLINK},1)
@@ -99,28 +90,24 @@ pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} libpiano.so.0
@echo " LINK $@"
@${CC} -o $@ ${PIANOBAR_OBJ} -L. -lpiano ${ALL_LDFLAGS}
else
-pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} \
- ${LIBWAITRESS_HDR}
+pianobar: ${PIANOBAR_OBJ} ${PIANOBAR_HDR} ${LIBPIANO_OBJ}
@echo " LINK $@"
- @${CC} -o $@ ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} \
- ${ALL_LDFLAGS}
+ @${CC} -o $@ ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${ALL_LDFLAGS}
endif
# build shared and static libpiano
-libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \
- ${LIBWAITRESS_HDR} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ}
+libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBPIANO_OBJ}
@echo " LINK $@"
@${CC} -shared -Wl,-soname,libpiano.so.0 -o libpiano.so.0.0.0 \
- ${LIBPIANO_RELOBJ} ${LIBWAITRESS_RELOBJ} ${ALL_LDFLAGS}
+ ${LIBPIANO_RELOBJ} ${ALL_LDFLAGS}
@ln -s libpiano.so.0.0.0 libpiano.so.0
@ln -s libpiano.so.0 libpiano.so
@echo " AR libpiano.a"
- @${AR} rcs libpiano.a ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ}
+ @${AR} rcs libpiano.a ${LIBPIANO_OBJ}
-include $(PIANOBAR_SRC:.c=.d)
-include $(LIBPIANO_SRC:.c=.d)
--include $(LIBWAITRESS_SRC:.c=.d)
# build standard object files
%.o: %.c
@@ -134,19 +121,12 @@ libpiano.so.0: ${LIBPIANO_RELOBJ} ${LIBPIANO_HDR} ${LIBWAITRESS_RELOBJ} \
clean:
@echo " CLEAN"
- @${RM} ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} ${LIBWAITRESS_OBJ} ${LIBWAITRESS_OBJ}/test.o \
- ${LIBPIANO_RELOBJ} ${LIBWAITRESS_RELOBJ} pianobar libpiano.so* \
- libpiano.a waitress-test $(PIANOBAR_SRC:.c=.d) $(LIBPIANO_SRC:.c=.d) \
- $(LIBWAITRESS_SRC:.c=.d)
+ @${RM} ${PIANOBAR_OBJ} ${LIBPIANO_OBJ} \
+ ${LIBPIANO_RELOBJ} pianobar libpiano.so* \
+ libpiano.a $(PIANOBAR_SRC:.c=.d) $(LIBPIANO_SRC:.c=.d)
all: pianobar
-waitress-test: ${LIBWAITRESS_TEST_OBJ}
- ${CC} ${LDFLAGS} ${LIBWAITRESS_TEST_OBJ} ${LIBGNUTLS_LDFLAGS} -o waitress-test
-
-test: waitress-test
- ./waitress-test
-
ifeq (${DYNLINK},1)
install: pianobar install-libpiano
else
diff --git a/src/libpiano/request.c b/src/libpiano/request.c
index 6d0c8e5..cad0907 100644
--- a/src/libpiano/request.c
+++ b/src/libpiano/request.c
@@ -26,12 +26,11 @@ THE SOFTWARE.
#define _DARWIN_C_SOURCE /* strdup() on OS X */
#endif
+#include <curl/curl.h>
#include <json.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
-/* needed for urlencode */
-#include <waitress.h>
#include "piano.h"
#include "crypt.h"
@@ -100,13 +99,16 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,
json_object_object_add (j, "syncTime",
json_object_new_int (timestamp));
- urlencAuthToken = WaitressUrlEncode (ph->partner.authToken);
+ CURL * const curl = curl_easy_init ();
+ urlencAuthToken = curl_easy_escape (curl,
+ ph->partner.authToken, 0);
assert (urlencAuthToken != NULL);
snprintf (req->urlPath, sizeof (req->urlPath),
PIANO_RPC_PATH "method=auth.userLogin&"
"auth_token=%s&partner_id=%i", urlencAuthToken,
ph->partner.id);
- free (urlencAuthToken);
+ curl_free (urlencAuthToken);
+ curl_easy_cleanup (curl);
break;
}
@@ -432,14 +434,17 @@ PianoReturn_t PianoRequest (PianoHandle_t *ph, PianoRequest_t *req,
assert (ph->user.authToken != NULL);
- urlencAuthToken = WaitressUrlEncode (ph->user.authToken);
+ CURL * const curl = curl_easy_init ();
+ urlencAuthToken = curl_easy_escape (curl,
+ ph->user.authToken, 0);
assert (urlencAuthToken != NULL);
snprintf (req->urlPath, sizeof (req->urlPath), PIANO_RPC_PATH
"method=%s&auth_token=%s&partner_id=%i&user_id=%s", method,
urlencAuthToken, ph->partner.id, ph->user.listenerId);
- free (urlencAuthToken);
+ curl_free (urlencAuthToken);
+ curl_easy_cleanup (curl);
json_object_object_add (j, "userAuthToken",
json_object_new_string (ph->user.authToken));
diff --git a/src/libwaitress/config.h b/src/libwaitress/config.h
deleted file mode 100644
index e13fe40..0000000
--- a/src/libwaitress/config.h
+++ /dev/null
@@ -1 +0,0 @@
-#define PACKAGE "libwaitress"
diff --git a/src/libwaitress/waitress-test.c b/src/libwaitress/waitress-test.c
deleted file mode 100644
index 8cc3e3a..0000000
--- a/src/libwaitress/waitress-test.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-Copyright (c) 2009-2013
- Lars-Dominik Braun <lars@6xq.net>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-/* test cases for libwaitress */
-
-/* we are testing static methods and therefore have to include the .c */
-#include "waitress.c"
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-
-#define streq(a,b) (strcmp(a,b) == 0)
-
-/* string equality test (memory location or content)
- */
-static bool streqtest (const char *x, const char *y) {
- return (x == y) || (x != NULL && y != NULL && streq (x, y));
-}
-
-/* test WaitressSplitUrl
- * @param tested url
- * @param expected user
- * @param expected password
- * @param expected host
- * @param expected port
- * @param expected path
- */
-static void compareUrl (const char *url, const char *user,
- const char *password, const char *host, const char *port,
- const char *path) {
- WaitressUrl_t splitUrl;
-
- memset (&splitUrl, 0, sizeof (splitUrl));
-
- WaitressSplitUrl (url, &splitUrl);
-
- bool userTest, passwordTest, hostTest, portTest, pathTest, overallTest;
-
- userTest = streqtest (splitUrl.user, user);
- passwordTest = streqtest (splitUrl.password, password);
- hostTest = streqtest (splitUrl.host, host);
- portTest = streqtest (splitUrl.port, port);
- pathTest = streqtest (splitUrl.path, path);
-
- overallTest = userTest && passwordTest && hostTest && portTest && pathTest;
-
- if (!overallTest) {
- printf ("FAILED test(s) for %s\n", url);
- if (!userTest) {
- printf ("user: %s vs %s\n", splitUrl.user, user);
- }
- if (!passwordTest) {
- printf ("password: %s vs %s\n", splitUrl.password, password);
- }
- if (!hostTest) {
- printf ("host: %s vs %s\n", splitUrl.host, host);
- }
- if (!portTest) {
- printf ("port: %s vs %s\n", splitUrl.port, port);
- }
- if (!pathTest) {
- printf ("path: %s vs %s\n", splitUrl.path, path);
- }
- } else {
- printf ("OK for %s\n", url);
- }
-}
-
-/* compare two strings
- */
-void compareStr (const char *result, const char *expected) {
- if (!streq (result, expected)) {
- printf ("FAIL for %s, result was %s\n", expected, result);
- } else {
- printf ("OK for %s\n", expected);
- }
-}
-
-/* test entry point
- */
-int main () {
- /* WaitressSplitUrl tests */
- compareUrl ("http://www.example.com/", NULL, NULL, "www.example.com", NULL,
- "");
- compareUrl ("http://www.example.com", NULL, NULL, "www.example.com", NULL,
- NULL);
- compareUrl ("http://www.example.com:80/", NULL, NULL, "www.example.com",
- "80", "");
- compareUrl ("http://www.example.com:/", NULL, NULL, "www.example.com", "",
- "");
- compareUrl ("http://:80/", NULL, NULL, "", "80", "");
- compareUrl ("http://www.example.com/foobar/barbaz", NULL, NULL,
- "www.example.com", NULL, "foobar/barbaz");
- compareUrl ("http://www.example.com:80/foobar/barbaz", NULL, NULL,
- "www.example.com", "80", "foobar/barbaz");
- compareUrl ("http://foo:bar@www.example.com:80/foobar/barbaz", "foo", "bar",
- "www.example.com", "80", "foobar/barbaz");
- compareUrl ("http://foo:@www.example.com:80/foobar/barbaz", "foo", "",
- "www.example.com", "80", "foobar/barbaz");
- compareUrl ("http://foo@www.example.com:80/foobar/barbaz", "foo", NULL,
- "www.example.com", "80", "foobar/barbaz");
- compareUrl ("http://:foo@www.example.com:80/foobar/barbaz", "", "foo",
- "www.example.com", "80", "foobar/barbaz");
- compareUrl ("http://:@:80", "", "", "", "80", NULL);
- compareUrl ("http://", NULL, NULL, NULL, NULL, NULL);
- compareUrl ("http:///", NULL, NULL, "", NULL, "");
- compareUrl ("http://foo:bar@", "foo", "bar", "", NULL, NULL);
-
- /* WaitressBase64Encode tests */
- compareStr (WaitressBase64Encode ("M"), "TQ==");
- compareStr (WaitressBase64Encode ("Ma"), "TWE=");
- compareStr (WaitressBase64Encode ("Man"), "TWFu");
- compareStr (WaitressBase64Encode ("The quick brown fox jumped over the lazy dog."),
- "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2cu");
- compareStr (WaitressBase64Encode ("The quick brown fox jumped over the lazy dog"),
- "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2c=");
- compareStr (WaitressBase64Encode ("The quick brown fox jumped over the lazy do"),
- "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkbw==");
-
- return EXIT_SUCCESS;
-}
-
diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c
deleted file mode 100644
index 62e06a0..0000000
--- a/src/libwaitress/waitress.c
+++ /dev/null
@@ -1,1240 +0,0 @@
-/*
-Copyright (c) 2009-2013
- Lars-Dominik Braun <lars@6xq.net>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#ifndef __FreeBSD__
-#define _POSIX_C_SOURCE 1 /* required by getaddrinfo() */
-#define _BSD_SOURCE /* snprintf() */
-#define _DARWIN_C_SOURCE /* snprintf() on OS X */
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <errno.h>
-#include <assert.h>
-#include <stdint.h>
-
-#include <gnutls/x509.h>
-
-#include "config.h"
-#include "waitress.h"
-
-#define strcaseeq(a,b) (strcasecmp(a,b) == 0)
-#define WAITRESS_HTTP_VERSION "1.1"
-
-typedef struct {
- char *data;
- size_t pos;
-} WaitressFetchBufCbBuffer_t;
-
-static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *, size_t *);
-
-#define READ_RET(buf, count, size) \
- if ((wRet = waith->request.read (waith, buf, count, size)) != \
- WAITRESS_RET_OK) { \
- return wRet; \
- }
-
-#define WRITE_RET(buf, count) \
- if ((wRet = waith->request.write (waith, buf, count)) != WAITRESS_RET_OK) { \
- return wRet; \
- }
-
-void WaitressInit (WaitressHandle_t *waith) {
- assert (waith != NULL);
-
- memset (waith, 0, sizeof (*waith));
- waith->timeout = 30000;
-}
-
-void WaitressFree (WaitressHandle_t *waith) {
- assert (waith != NULL);
-
- free (waith->url.url);
- free (waith->proxy.url);
- memset (waith, 0, sizeof (*waith));
-}
-
-/* Proxy set up?
- * @param Waitress handle
- * @return true|false
- */
-static bool WaitressProxyEnabled (const WaitressHandle_t *waith) {
- assert (waith != NULL);
-
- return waith->proxy.host != NULL;
-}
-
-/* urlencode post-data
- * @param encode this
- * @return malloc'ed encoded string, don't forget to free it
- */
-char *WaitressUrlEncode (const char *in) {
- assert (in != NULL);
-
- size_t inLen = strlen (in);
- /* worst case: encode all characters */
- char *out = calloc (inLen * 3 + 1, sizeof (*in));
- const char *inPos = in;
- char *outPos = out;
-
- while (inPos - in < inLen) {
- if (!isalnum (*inPos) && *inPos != '_' && *inPos != '-' && *inPos != '.') {
- *outPos++ = '%';
- snprintf (outPos, 3, "%02x", *inPos & 0xff);
- outPos += 2;
- } else {
- /* copy character */
- *outPos++ = *inPos;
- }
- ++inPos;
- }
-
- return out;
-}
-
-/* base64 encode data
- * @param encode this
- * @return malloc'ed string
- */
-static char *WaitressBase64Encode (const char *in) {
- assert (in != NULL);
-
- size_t inLen = strlen (in);
- char *out, *outPos;
- const char *inPos;
- static const char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz0123456789+/";
- const size_t alphabetLen = strlen (alphabet);
-
- /* worst case is 1.333 */
- out = malloc ((inLen * 2 + 1) * sizeof (*out));
- if (out == NULL) {
- return NULL;
- }
- outPos = out;
- inPos = in;
-
- while (inLen >= 3) {
- uint8_t idx;
-
- idx = ((*inPos) >> 2) & 0x3f;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- idx = ((*inPos) & 0x3) << 4;
- ++inPos;
- idx |= ((*inPos) >> 4) & 0xf;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- idx = ((*inPos) & 0xf) << 2;
- ++inPos;
- idx |= ((*inPos) >> 6) & 0x3;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- idx = (*inPos) & 0x3f;
- ++inPos;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- inLen -= 3;
- }
-
- switch (inLen) {
- case 2: {
- uint8_t idx;
-
- idx = ((*inPos) >> 2) & 0x3f;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- idx = ((*inPos) & 0x3) << 4;
- ++inPos;
- idx |= ((*inPos) >> 4) & 0xf;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- idx = ((*inPos) & 0xf) << 2;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- *outPos = '=';
- ++outPos;
- break;
- }
-
- case 1: {
- uint8_t idx;
-
- idx = ((*inPos) >> 2) & 0x3f;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- idx = ((*inPos) & 0x3) << 4;
- assert (idx < alphabetLen);
- *outPos = alphabet[idx];
- ++outPos;
-
- *outPos = '=';
- ++outPos;
-
- *outPos = '=';
- ++outPos;
- break;
- }
- }
- *outPos = '\0';
-
- return out;
-}
-
-/* Split http url into host, port and path
- * @param url
- * @param returned url struct
- * @return url is a http url? does not say anything about its validity!
- */
-static bool WaitressSplitUrl (const char *inurl, WaitressUrl_t *retUrl) {
- assert (inurl != NULL);
- assert (retUrl != NULL);
-
- static const char *httpPrefix = "http://";
-
- /* is http url? */
- if (strncmp (httpPrefix, inurl, strlen (httpPrefix)) == 0) {
- enum {FIND_USER, FIND_PASS, FIND_HOST, FIND_PORT, FIND_PATH, DONE}
- state = FIND_USER, newState = FIND_USER;
- char *url, *urlPos, *assignStart;
- const char **assign = NULL;
-
- url = strdup (inurl);
- retUrl->url = url;
-
- urlPos = url + strlen (httpPrefix);
- assignStart = urlPos;
-
- if (*urlPos == '\0') {
- state = DONE;
- }
-
- while (state != DONE) {
- const char c = *urlPos;
-
- switch (state) {
- case FIND_USER: {
- if (c == ':') {
- assign = &retUrl->user;
- newState = FIND_PASS;
- } else if (c == '@') {
- assign = &retUrl->user;
- newState = FIND_HOST;
- } else if (c == '/') {
- /* not a user */
- assign = &retUrl->host;
- newState = FIND_PATH;
- } else if (c == '\0') {
- assign = &retUrl->host;
- newState = DONE;
- }
- break;
- }
-
- case FIND_PASS: {
- if (c == '@') {
- assign = &retUrl->password;
- newState = FIND_HOST;
- } else if (c == '/') {
- /* not a password */
- assign = &retUrl->port;
- newState = FIND_PATH;
- } else if (c == '\0') {
- assign = &retUrl->port;
- newState = DONE;
- }
- break;
- }
-
- case FIND_HOST: {
- if (c == ':') {
- assign = &retUrl->host;
- newState = FIND_PORT;
- } else if (c == '/') {
- assign = &retUrl->host;
- newState = FIND_PATH;
- } else if (c == '\0') {
- assign = &retUrl->host;
- newState = DONE;
- }
- break;
- }
-
- case FIND_PORT: {
- if (c == '/') {
- assign = &retUrl->port;
- newState = FIND_PATH;
- } else if (c == '\0') {
- assign = &retUrl->port;
- newState = DONE;
- }
- break;
- }
-
- case FIND_PATH: {
- if (c == '\0') {
- assign = &retUrl->path;
- newState = DONE;
- }
- break;
- }
-
- case DONE:
- break;
- } /* end switch */
-
- if (assign != NULL) {
- *assign = assignStart;
- *urlPos = '\0';
- assignStart = urlPos+1;
-
- state = newState;
- assign = NULL;
- }
-
- ++urlPos;
- } /* end while */
-
- /* fixes for our state machine logic */
- if (retUrl->user != NULL && retUrl->host == NULL && retUrl->port != NULL) {
- retUrl->host = retUrl->user;
- retUrl->user = NULL;
- }
- return true;
- } /* end if strncmp */
-
- return false;
-}
-
-/* Parse url and set host, port, path
- * @param Waitress handle
- * @param url: protocol://host:port/path
- */
-bool WaitressSetUrl (WaitressHandle_t *waith, const char *url) {
- return WaitressSplitUrl (url, &waith->url);
-}
-
-/* Set http proxy
- * @param waitress handle
- * @param url, e.g. http://proxy:80/
- */
-bool WaitressSetProxy (WaitressHandle_t *waith, const char *url) {
- return WaitressSplitUrl (url, &waith->proxy);
-}
-
-/* Callback for WaitressFetchBuf, appends received data to \0-terminated
- * buffer
- * @param received data
- * @param data size
- * @param buffer structure
- */
-static WaitressCbReturn_t WaitressFetchBufCb (void *recvData, size_t recvDataSize,
- void *extraData) {
- char *recvBytes = recvData;
- WaitressFetchBufCbBuffer_t *buffer = extraData;
-
- if (buffer->data == NULL) {
- if ((buffer->data = malloc (sizeof (*buffer->data) *
- (recvDataSize + 1))) == NULL) {
- return WAITRESS_CB_RET_ERR;
- }
- } else {
- char *newbuf;
- if ((newbuf = realloc (buffer->data,
- sizeof (*buffer->data) *
- (buffer->pos + recvDataSize + 1))) == NULL) {
- free (buffer->data);
- return WAITRESS_CB_RET_ERR;
- }
- buffer->data = newbuf;
- }
- memcpy (buffer->data + buffer->pos, recvBytes, recvDataSize);
- buffer->pos += recvDataSize;
- buffer->data[buffer->pos] = '\0';
-
- return WAITRESS_CB_RET_OK;
-}
-
-/* Fetch string. Beware! This overwrites your waith->data pointer
- * @param waitress handle
- * @param \0-terminated result buffer, malloced (don't forget to free it
- * yourself)
- */
-WaitressReturn_t WaitressFetchBuf (WaitressHandle_t *waith, char **retBuffer) {
- WaitressFetchBufCbBuffer_t buffer;
- WaitressReturn_t wRet;
-
- assert (waith != NULL);
- assert (retBuffer != NULL);
-
- memset (&buffer, 0, sizeof (buffer));
-
- waith->data = &buffer;
- waith->callback = WaitressFetchBufCb;
-
- wRet = WaitressFetchCall (waith);
- *retBuffer = buffer.data;
- return wRet;
-}
-
-/* poll wrapper that retries after signal interrupts, required for socksify
- * wrapper
- */
-static int WaitressPollLoop (int fd, short events, int timeout) {
- int pollres = -1;
- struct pollfd sockpoll = {fd, events, 0};
-
- assert (fd != -1);
-
- do {
- errno = 0;
- pollres = poll (&sockpoll, 1, timeout);
- } while (errno == EINTR || errno == EINPROGRESS || errno == EAGAIN);
-
- return pollres;
-}
-
-/* write () wrapper with poll () timeout
- * @param waitress handle
- * @param write buffer
- * @param write count bytes
- * @return number of written bytes or -1 on error
- */
-static ssize_t WaitressPollWrite (void *data, const void *buf, size_t count) {
- int pollres = -1;
- ssize_t retSize;
- WaitressHandle_t *waith = data;
-
- assert (waith != NULL);
- assert (buf != NULL);
-
- /* FIXME: simplify logic */
- pollres = WaitressPollLoop (waith->request.sockfd, POLLOUT,
- waith->timeout);
- if (pollres == 0) {
- waith->request.readWriteRet = WAITRESS_RET_TIMEOUT;
- return -1;
- } else if (pollres == -1) {
- waith->request.readWriteRet = WAITRESS_RET_ERR;
- return -1;
- }
- if ((retSize = write (waith->request.sockfd, buf, count)) == -1) {
- waith->request.readWriteRet = WAITRESS_RET_ERR;
- return -1;
- }
- waith->request.readWriteRet = WAITRESS_RET_OK;
- return retSize;
-}
-
-static WaitressReturn_t WaitressOrdinaryWrite (void *data, const char *buf,
- const size_t size) {
- WaitressHandle_t *waith = data;
-
- WaitressPollWrite (waith, buf, size);
- return waith->request.readWriteRet;
-}
-
-static WaitressReturn_t WaitressGnutlsWrite (void *data, const char *buf,
- const size_t size) {
- WaitressHandle_t *waith = data;
-
- if (gnutls_record_send (waith->request.tlsSession, buf, size) < 0) {
- return WAITRESS_RET_TLS_WRITE_ERR;
- }
- return waith->request.readWriteRet;
-}
-
-/* read () wrapper with poll () timeout
- * @param waitress handle
- * @param write to this buf, not NULL terminated
- * @param buffer size
- * @return number of read bytes or -1 on error
- */
-static ssize_t WaitressPollRead (void *data, void *buf, size_t count) {
- int pollres = -1;
- ssize_t retSize;
- WaitressHandle_t *waith = data;
-
- assert (waith != NULL);
- assert (buf != NULL);
-
- /* FIXME: simplify logic */
- pollres = WaitressPollLoop (waith->request.sockfd, POLLIN, waith->timeout);
- if (pollres == 0) {
- waith->request.readWriteRet = WAITRESS_RET_TIMEOUT;
- return -1;
- } else if (pollres == -1) {
- waith->request.readWriteRet = WAITRESS_RET_ERR;
- return -1;
- }
- if ((retSize = read (waith->request.sockfd, buf, count)) == -1) {
- waith->request.readWriteRet = WAITRESS_RET_READ_ERR;
- return -1;
- }
- waith->request.readWriteRet = WAITRESS_RET_OK;
- return retSize;
-}
-
-static WaitressReturn_t WaitressOrdinaryRead (void *data, char *buf,
- const size_t size, size_t *retSize) {
- WaitressHandle_t *waith = data;
-
- const ssize_t ret = WaitressPollRead (waith, buf, size);
- if (ret != -1) {
- assert (ret >= 0);
- *retSize = (size_t) ret;
- }
- return waith->request.readWriteRet;
-}
-
-static WaitressReturn_t WaitressGnutlsRead (void *data, char *buf,
- const size_t size, size_t *retSize) {
- WaitressHandle_t *waith = data;
-
- ssize_t ret = gnutls_record_recv (waith->request.tlsSession, buf, size);
- if (ret < 0) {
- return WAITRESS_RET_TLS_READ_ERR;
- } else {
- *retSize = ret;
- }
- return waith->request.readWriteRet;
-}
-
-/* send basic http authorization
- * @param waitress handle
- * @param url containing user/password
- * @param header name prefix
- */
-static bool WaitressFormatAuthorization (WaitressHandle_t *waith,
- WaitressUrl_t *url, const char *prefix, char *writeBuf,
- const size_t writeBufSize) {
- assert (waith != NULL);
- assert (url != NULL);
- assert (prefix != NULL);
- assert (writeBuf != NULL);
- assert (writeBufSize > 0);
-
- if (url->user != NULL) {
- char userPass[1024], *encodedUserPass;
- snprintf (userPass, sizeof (userPass), "%s:%s", url->user,
- (url->password != NULL) ? url->password : "");
- encodedUserPass = WaitressBase64Encode (userPass);
- assert (encodedUserPass != NULL);
- snprintf (writeBuf, writeBufSize, "%sAuthorization: Basic %s\r\n",
- prefix, encodedUserPass);
- free (encodedUserPass);
- return true;
- }
- return false;
-}
-
-/* get default http port if none was given
- */
-static const char *WaitressDefaultPort (const WaitressUrl_t * const url) {
- assert (url != NULL);
-
- if (url->tls) {
- return url->tlsPort == NULL ? "443" : url->tlsPort;
- } else {
- return url->port == NULL ? "80" : url->port;
- }
-}
-
-/* get line from string
- * @param string beginning/return value of last call
- * @return start of _next_ line or NULL if there is no next line
- */
-static char *WaitressGetline (char * const str) {
- char *eol;
-
- assert (str != NULL);
-
- eol = strchr (str, '\n');
- if (eol == NULL) {
- return NULL;
- }
-
- /* make lines parseable by string routines */
- *eol = '\0';
- if (eol-1 >= str && *(eol-1) == '\r') {
- *(eol-1) = '\0';
- }
- /* skip \0 */
- ++eol;
-
- assert (eol >= str);
-
- return eol;
-}
-
-/* identity encoding handler
- */
-static WaitressHandlerReturn_t WaitressHandleIdentity (void *data, char *buf,
- const size_t size) {
- assert (data != NULL);
- assert (buf != NULL);
-
- WaitressHandle_t *waith = data;
-
- waith->request.contentReceived += size;
- if (waith->callback (buf, size, waith->data) == WAITRESS_CB_RET_ERR) {
- return WAITRESS_HANDLER_ABORTED;
- } else {
- return WAITRESS_HANDLER_CONTINUE;
- }
-}
-
-/* chunked encoding handler
- */
-static WaitressHandlerReturn_t WaitressHandleChunked (void *data, char *buf,
- const size_t size) {
- assert (data != NULL);
- assert (buf != NULL);
-
- WaitressHandle_t * const waith = data;
- size_t pos = 0;
-
- while (pos < size) {
- switch (waith->request.chunkedState) {
- case CHUNKSIZE:
- /* Poor man’s hex to integer. This avoids another buffer that
- * fills until the terminating \r\n is received. */
- if (buf[pos] >= '0' && buf[pos] <= '9') {
- waith->request.chunkSize <<= 4;
- waith->request.chunkSize |= buf[pos] & 0xf;
- } else if (buf[pos] >= 'a' && buf[pos] <= 'f') {
- waith->request.chunkSize <<= 4;
- waith->request.chunkSize |= (buf[pos]+9) & 0xf;
- } else if (buf[pos] == '\r') {
- /* ignore */
- } else if (buf[pos] == '\n') {
- waith->request.chunkedState = DATA;
- /* last chunk has size 0 */
- if (waith->request.chunkSize == 0) {
- return WAITRESS_HANDLER_DONE;
- }
- } else {
- /* everything else is a protocol violation */
- return WAITRESS_HANDLER_ERR;
- }
- ++pos;
- break;
-
- case DATA:
- if (waith->request.chunkSize > 0) {
- assert (size >= pos);
- size_t payloadSize = size - pos;
-
- if (payloadSize > waith->request.chunkSize) {
- payloadSize = waith->request.chunkSize;
- }
- if (WaitressHandleIdentity (waith, &buf[pos],
- payloadSize) == WAITRESS_HANDLER_ABORTED) {
- return WAITRESS_HANDLER_ABORTED;
- }
- pos += payloadSize;
- assert (waith->request.chunkSize >= payloadSize);
- waith->request.chunkSize -= payloadSize;
- } else {
- /* next chunk size starts in the next line */
- if (buf[pos] == '\n') {
- waith->request.chunkedState = CHUNKSIZE;
- }
- ++pos;
- }
- break;
- }
- }
-
- return WAITRESS_HANDLER_CONTINUE;
-}
-
-/* handle http header
- */
-static void WaitressHandleHeader (WaitressHandle_t *waith, const char * const key,
- const char * const value) {
- assert (waith != NULL);
- assert (key != NULL);
- assert (value != NULL);
-
- if (strcaseeq (key, "Content-Length")) {
- waith->request.contentLength = atol (value);
- waith->request.contentLengthKnown = true;
- } else if (strcaseeq (key, "Transfer-Encoding")) {
- if (strcaseeq (value, "chunked")) {
- waith->request.dataHandler = WaitressHandleChunked;
- }
- }
-}
-
-/* parse http status line and return status code
- */
-static int WaitressParseStatusline (const char * const line) {
- char status[4] = "000";
-
- assert (line != NULL);
-
- if (sscanf (line, "HTTP/1.%*1[0-9] %3[0-9] ", status) == 1) {
- return atoi (status);
- }
- return -1;
-}
-
-/* verify server certificate
- */
-static WaitressReturn_t WaitressTlsVerify (const WaitressHandle_t *waith) {
- gnutls_session_t session = waith->request.tlsSession;
- unsigned int certListSize;
- const gnutls_datum_t *certList;
- gnutls_x509_crt_t cert;
-
- if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) {
- return WAITRESS_RET_TLS_HANDSHAKE_ERR;
- }
-
- if ((certList = gnutls_certificate_get_peers (session,
- &certListSize)) == NULL) {
- return WAITRESS_RET_TLS_HANDSHAKE_ERR;
- }
-
- if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
- return WAITRESS_RET_TLS_HANDSHAKE_ERR;
- }
-
- if (gnutls_x509_crt_import (cert, &certList[0],
- GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
- return WAITRESS_RET_TLS_HANDSHAKE_ERR;
- }
-
- char fingerprint[20];
- size_t fingerprintSize = sizeof (fingerprint);
- if (gnutls_x509_crt_get_fingerprint (cert, GNUTLS_DIG_SHA1, fingerprint,
- &fingerprintSize) != 0) {
- return WAITRESS_RET_TLS_HANDSHAKE_ERR;
- }
-
- assert (waith->tlsFingerprint != NULL);
- if (memcmp (fingerprint, waith->tlsFingerprint, sizeof (fingerprint)) != 0) {
- return WAITRESS_RET_TLS_FINGERPRINT_MISMATCH;
- }
-
- gnutls_x509_crt_deinit (cert);
-
- return WAITRESS_RET_OK;
-}
-
-/* Connect to server
- */
-static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) {
- WaitressReturn_t ret;
- struct addrinfo hints, *gares;
-
- memset (&hints, 0, sizeof hints);
-
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
-
- /* Use proxy? */
- if (WaitressProxyEnabled (waith)) {
- if (getaddrinfo (waith->proxy.host,
- WaitressDefaultPort (&waith->proxy), &hints, &gares) != 0) {
- return WAITRESS_RET_GETADDR_ERR;
- }
- } else {
- if (getaddrinfo (waith->url.host,
- WaitressDefaultPort (&waith->url), &hints, &gares) != 0) {
- return WAITRESS_RET_GETADDR_ERR;
- }
- }
-
- /* try all addresses */
- for (struct addrinfo *gacurr = gares; gacurr != NULL;
- gacurr = gacurr->ai_next) {
- int sock = -1;
-
- ret = WAITRESS_RET_OK;
-
- if ((sock = socket (gacurr->ai_family, gacurr->ai_socktype,
- gacurr->ai_protocol)) == -1) {
- ret = WAITRESS_RET_SOCK_ERR;
- } else {
- int pollres;
-
- /* we need shorter timeouts for connect() */
- fcntl (sock, F_SETFL, O_NONBLOCK);
-
- /* non-blocking connect will return immediately */
- connect (sock, gacurr->ai_addr, gacurr->ai_addrlen);
-
- pollres = WaitressPollLoop (sock, POLLOUT, waith->timeout);
- if (pollres == 0) {
- ret = WAITRESS_RET_TIMEOUT;
- } else if (pollres == -1) {
- ret = WAITRESS_RET_ERR;
- } else {
- /* check connect () return value */
- socklen_t pollresSize = sizeof (pollres);
- getsockopt (sock, SOL_SOCKET, SO_ERROR, &pollres,
- &pollresSize);
- if (pollres != 0) {
- ret = WAITRESS_RET_CONNECT_REFUSED;
- } else {
- /* this one is working */
- waith->request.sockfd = sock;
- break;
- }
- }
- close (sock);
- }
- }
-
- freeaddrinfo (gares);
- /* could not connect to any of the addresses */
- if (ret != WAITRESS_RET_OK) {
- return ret;
- }
-
- if (waith->url.tls) {
- WaitressReturn_t wRet;
-
- /* set up proxy tunnel */
- if (WaitressProxyEnabled (waith)) {
- char buf[256];
- size_t size;
-
- snprintf (buf, sizeof (buf), "CONNECT %s:%s HTTP/"
- WAITRESS_HTTP_VERSION "\r\n"
- "Host: %s:%s\r\n"
- "Proxy-Connection: close\r\n",
- waith->url.host, WaitressDefaultPort (&waith->url),
- waith->url.host, WaitressDefaultPort (&waith->url));
- WRITE_RET (buf, strlen (buf));
-
- /* write authorization headers */
- if (WaitressFormatAuthorization (waith, &waith->proxy, "Proxy-",
- buf, WAITRESS_BUFFER_SIZE)) {
- WRITE_RET (buf, strlen (buf));
- }
-
- WRITE_RET ("\r\n", 2);
-
- if ((wRet = WaitressReceiveHeaders (waith, &size)) !=
- WAITRESS_RET_OK) {
- return wRet;
- }
- }
-
- /* Ignore return code as connection will likely still succeed */
- gnutls_server_name_set (waith->request.tlsSession, GNUTLS_NAME_DNS,
- waith->url.host, strlen (waith->url.host));
-
- if (gnutls_handshake (waith->request.tlsSession) != GNUTLS_E_SUCCESS) {
- return WAITRESS_RET_TLS_HANDSHAKE_ERR;
- }
-
- if ((wRet = WaitressTlsVerify (waith)) != WAITRESS_RET_OK) {
- return wRet;
- }
-
- /* now we can talk encrypted */
- waith->request.read = WaitressGnutlsRead;
- waith->request.write = WaitressGnutlsWrite;
- }
-
- return WAITRESS_RET_OK;
-}
-
-/* Write http header/post data to socket
- */
-static WaitressReturn_t WaitressSendRequest (WaitressHandle_t *waith) {
- assert (waith != NULL);
- assert (waith->request.buf != NULL);
-
- const char *path = waith->url.path;
- char * const buf = waith->request.buf;
- WaitressReturn_t wRet = WAITRESS_RET_OK;
-
- if (waith->url.path == NULL) {
- /* avoid NULL pointer deref */
- path = "";
- } else if (waith->url.path[0] == '/') {
- /* most servers don't like "//" */
- ++path;
- }
-
- /* send request */
- if (WaitressProxyEnabled (waith) && !waith->url.tls) {
- snprintf (buf, WAITRESS_BUFFER_SIZE,
- "%s http://%s:%s/%s HTTP/" WAITRESS_HTTP_VERSION "\r\n"
- "Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n",
- (waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"),
- waith->url.host,
- WaitressDefaultPort (&waith->url), path, waith->url.host);
- } else {
- snprintf (buf, WAITRESS_BUFFER_SIZE,
- "%s /%s HTTP/" WAITRESS_HTTP_VERSION "\r\n"
- "Host: %s\r\nUser-Agent: " PACKAGE "\r\nConnection: Close\r\n",
- (waith->method == WAITRESS_METHOD_GET ? "GET" : "POST"),
- path, waith->url.host);
- }
- WRITE_RET (buf, strlen (buf));
-
- if (waith->method == WAITRESS_METHOD_POST && waith->postData != NULL) {
- snprintf (buf, WAITRESS_BUFFER_SIZE, "Content-Length: %zu\r\n",
- strlen (waith->postData));
- WRITE_RET (buf, strlen (buf));
- }
-
- /* write authorization headers */
- if (WaitressFormatAuthorization (waith, &waith->url, "", buf,
- WAITRESS_BUFFER_SIZE)) {
- WRITE_RET (buf, strlen (buf));
- }
- /* don't leak proxy credentials to destination server if tls is used */
- if (!waith->url.tls &&
- WaitressFormatAuthorization (waith, &waith->proxy, "Proxy-",
- buf, WAITRESS_BUFFER_SIZE)) {
- WRITE_RET (buf, strlen (buf));
- }
-
- if (waith->extraHeaders != NULL) {
- WRITE_RET (waith->extraHeaders, strlen (waith->extraHeaders));
- }
-
- WRITE_RET ("\r\n", 2);
-
- if (waith->method == WAITRESS_METHOD_POST && waith->postData != NULL) {
- WRITE_RET (waith->postData, strlen (waith->postData));
- }
-
- return WAITRESS_RET_OK;
-}
-
-/* receive response headers
- * @param Waitress handle
- * @param return unhandled bytes count in buf
- */
-static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *waith,
- size_t *retRemaining) {
- char * const buf = waith->request.buf;
- size_t bufFilled = 0, recvSize = 0;
- char *nextLine = NULL, *thisLine = NULL;
- enum {HDRM_HEAD, HDRM_LINES, HDRM_FINISHED} hdrParseMode = HDRM_HEAD;
- WaitressReturn_t wRet = WAITRESS_RET_OK;
-
- /* receive answer */
- nextLine = buf;
- while (hdrParseMode != HDRM_FINISHED) {
- READ_RET (buf+bufFilled, WAITRESS_BUFFER_SIZE-1 - bufFilled, &recvSize);
- if (recvSize == 0) {
- /* connection closed too early */
- return WAITRESS_RET_CONNECTION_CLOSED;
- }
- bufFilled += recvSize;
- buf[bufFilled] = '\0';
- thisLine = buf;
-
- /* split */
- while (hdrParseMode != HDRM_FINISHED &&
- (nextLine = WaitressGetline (thisLine)) != NULL) {
- switch (hdrParseMode) {
- /* Status code */
- case HDRM_HEAD:
- switch (WaitressParseStatusline (thisLine)) {
- case 200:
- case 206:
- hdrParseMode = HDRM_LINES;
- break;
-
- case 400:
- return WAITRESS_RET_BAD_REQUEST;
- break;
-
- case 403:
- return WAITRESS_RET_FORBIDDEN;
- break;
-
- case 404:
- return WAITRESS_RET_NOTFOUND;
- break;
-
- case -1:
- /* ignore invalid line */
- break;
-
- default:
- return WAITRESS_RET_STATUS_UNKNOWN;
- break;
- }
- break;
-
- /* Everything else, except status code */
- case HDRM_LINES:
- /* empty line => content starts here */
- if (*thisLine == '\0') {
- hdrParseMode = HDRM_FINISHED;
- } else {
- /* parse header: "key: value", ignore invalid lines */
- char *key = thisLine, *val;
-
- val = strchr (thisLine, ':');
- if (val != NULL) {
- *val++ = '\0';
- while (*val != '\0' && isspace ((unsigned char) *val)) {
- ++val;
- }
- WaitressHandleHeader (waith, key, val);
- }
- }
- break;
-
- default:
- break;
- } /* end switch */
- thisLine = nextLine;
- } /* end while strchr */
- memmove (buf, thisLine, bufFilled-(thisLine-buf));
- bufFilled -= (thisLine-buf);
- } /* end while hdrParseMode */
-
- *retRemaining = bufFilled;
-
- return wRet;
-}
-
-/* read response header and data
- */
-static WaitressReturn_t WaitressReceiveResponse (WaitressHandle_t *waith) {
- assert (waith != NULL);
- assert (waith->request.buf != NULL);
-
- char * const buf = waith->request.buf;
- size_t recvSize = 0;
- WaitressReturn_t wRet = WAITRESS_RET_OK;
-
- if ((wRet = WaitressReceiveHeaders (waith, &recvSize)) != WAITRESS_RET_OK) {
- return wRet;
- }
-
- do {
- /* data must be \0-terminated for chunked handler */
- buf[recvSize] = '\0';
- switch (waith->request.dataHandler (waith, buf, recvSize)) {
- case WAITRESS_HANDLER_DONE:
- return WAITRESS_RET_OK;
- break;
-
- case WAITRESS_HANDLER_ERR:
- return WAITRESS_RET_DECODING_ERR;
- break;
-
- case WAITRESS_HANDLER_ABORTED:
- return WAITRESS_RET_CB_ABORT;
- break;
-
- case WAITRESS_HANDLER_CONTINUE:
- /* go on */
- break;
- }
- if (waith->request.contentLengthKnown &&
- waith->request.contentReceived >= waith->request.contentLength) {
- /* don’t call read() again if we know the body’s size and have all
- * of it already */
- break;
- }
- READ_RET (buf, WAITRESS_BUFFER_SIZE-1, &recvSize);
- } while (recvSize > 0);
-
- return WAITRESS_RET_OK;
-}
-
-/* Receive data from host and call *callback ()
- * @param waitress handle
- * @return WaitressReturn_t
- */
-WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
- WaitressReturn_t wRet = WAITRESS_RET_OK;
-
- /* initialize */
- memset (&waith->request, 0, sizeof (waith->request));
- waith->request.sockfd = -1;
- waith->request.dataHandler = WaitressHandleIdentity;
- waith->request.read = WaitressOrdinaryRead;
- waith->request.write = WaitressOrdinaryWrite;
- waith->request.contentLengthKnown = false;
-
- if (waith->url.tls) {
- gnutls_init (&waith->request.tlsSession, GNUTLS_CLIENT);
- gnutls_set_default_priority (waith->request.tlsSession);
-
- gnutls_certificate_allocate_credentials (&waith->tlsCred);
- if (gnutls_credentials_set (waith->request.tlsSession,
- GNUTLS_CRD_CERTIFICATE,
- waith->tlsCred) != GNUTLS_E_SUCCESS) {
- return WAITRESS_RET_ERR;
- }
-
- /* set up custom read/write functions */
- gnutls_transport_set_ptr (waith->request.tlsSession,
- (gnutls_transport_ptr_t) waith);
- gnutls_transport_set_pull_function (waith->request.tlsSession,
- WaitressPollRead);
- gnutls_transport_set_push_function (waith->request.tlsSession,
- WaitressPollWrite);
- }
-
- /* buffer is required for connect already */
- waith->request.buf = malloc (WAITRESS_BUFFER_SIZE *
- sizeof (*waith->request.buf));
-
- /* request */
- if ((wRet = WaitressConnect (waith)) == WAITRESS_RET_OK) {
- if ((wRet = WaitressSendRequest (waith)) == WAITRESS_RET_OK) {
- wRet = WaitressReceiveResponse (waith);
- }
- if (waith->url.tls) {
- gnutls_bye (waith->request.tlsSession, GNUTLS_SHUT_RDWR);
- }
- }
-
- /* cleanup */
- if (waith->url.tls) {
- gnutls_deinit (waith->request.tlsSession);
- gnutls_certificate_free_credentials (waith->tlsCred);
- }
- if (waith->request.sockfd != -1) {
- close (waith->request.sockfd);
- }
- free (waith->request.buf);
-
- if (wRet == WAITRESS_RET_OK &&
- waith->request.contentReceived < waith->request.contentLength) {
- return WAITRESS_RET_PARTIAL_FILE;
- }
- return wRet;
-}
-
-const char *WaitressErrorToStr (WaitressReturn_t wRet) {
- switch (wRet) {
- case WAITRESS_RET_OK:
- return "Everything's fine :)";
- break;
-
- case WAITRESS_RET_ERR:
- return "Unknown.";
- break;
-
- case WAITRESS_RET_STATUS_UNKNOWN:
- return "Unknown HTTP status code.";
- break;
-
- case WAITRESS_RET_NOTFOUND:
- return "File not found.";
- break;
-
- case WAITRESS_RET_FORBIDDEN:
- return "Forbidden.";
- break;
-
- case WAITRESS_RET_CONNECT_REFUSED:
- return "Connection refused.";
- break;
-
- case WAITRESS_RET_SOCK_ERR:
- return "Socket error.";
- break;
-
- case WAITRESS_RET_GETADDR_ERR:
- return "DNS lookup failed.";
- break;
-
- case WAITRESS_RET_CB_ABORT:
- return "Callback aborted request.";
- break;
-
- case WAITRESS_RET_PARTIAL_FILE:
- return "Partial file.";
- break;
-
- case WAITRESS_RET_TIMEOUT:
- return "Timeout.";
- break;
-
- case WAITRESS_RET_READ_ERR:
- return "Read error.";
- break;
-
- case WAITRESS_RET_CONNECTION_CLOSED:
- return "Connection closed by remote host.";
- break;
-
- case WAITRESS_RET_DECODING_ERR:
- return "Invalid encoded data.";
- break;
-
- case WAITRESS_RET_TLS_WRITE_ERR:
- return "TLS write failed.";
- break;
-
- case WAITRESS_RET_TLS_READ_ERR:
- return "TLS read failed.";
- break;
-
- case WAITRESS_RET_TLS_HANDSHAKE_ERR:
- return "TLS handshake failed.";
- break;
-
- case WAITRESS_RET_TLS_FINGERPRINT_MISMATCH:
- return "TLS fingerprint mismatch.";
- break;
-
- default:
- return "No error message available.";
- break;
- }
-}
-
diff --git a/src/libwaitress/waitress.h b/src/libwaitress/waitress.h
deleted file mode 100644
index b17d3c1..0000000
--- a/src/libwaitress/waitress.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
-Copyright (c) 2009-2013
- Lars-Dominik Braun <lars@6xq.net>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#ifndef SRC_LIBWAITRESS_WAITRESS_H_ZE5NT8JI
-#define SRC_LIBWAITRESS_WAITRESS_H_ZE5NT8JI
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <gnutls/gnutls.h>
-
-#define WAITRESS_BUFFER_SIZE 10*1024
-
-typedef enum {
- WAITRESS_METHOD_GET = 0,
- WAITRESS_METHOD_POST,
-} WaitressMethod_t;
-
-typedef enum {
- WAITRESS_CB_RET_ERR,
- WAITRESS_CB_RET_OK,
-} WaitressCbReturn_t;
-
-typedef enum {
- WAITRESS_HANDLER_CONTINUE,
- WAITRESS_HANDLER_DONE,
- WAITRESS_HANDLER_ERR,
- WAITRESS_HANDLER_ABORTED,
-} WaitressHandlerReturn_t;
-
-typedef struct {
- char *url; /* splitted url, unusable */
- bool tls;
- const char *user;
- const char *password;
- const char *host;
- const char *port;
- const char *tlsPort;
- const char *path; /* without leading '/' */
-} WaitressUrl_t;
-
-typedef enum {
- WAITRESS_RET_ERR = 0,
- WAITRESS_RET_OK,
- WAITRESS_RET_CB_ABORT,
- /* http error codes */
- WAITRESS_RET_STATUS_UNKNOWN,
- WAITRESS_RET_NOTFOUND,
- WAITRESS_RET_FORBIDDEN,
- WAITRESS_RET_BAD_REQUEST,
- /* socket errors */
- WAITRESS_RET_CONNECT_REFUSED,
- WAITRESS_RET_SOCK_ERR,
- WAITRESS_RET_GETADDR_ERR,
- WAITRESS_RET_TIMEOUT,
- WAITRESS_RET_READ_ERR,
- WAITRESS_RET_CONNECTION_CLOSED,
- WAITRESS_RET_TLS_WRITE_ERR,
- WAITRESS_RET_TLS_READ_ERR,
- /* protocol errors */
- WAITRESS_RET_PARTIAL_FILE,
- WAITRESS_RET_DECODING_ERR,
- WAITRESS_RET_TLS_HANDSHAKE_ERR,
- WAITRESS_RET_TLS_FINGERPRINT_MISMATCH,
-} WaitressReturn_t;
-
-/* reusable handle
- */
-typedef struct {
- int timeout;
- WaitressMethod_t method;
-
- const char *extraHeaders;
- const char *postData;
- /* extra data handed over to callback function */
- void *data;
- WaitressCbReturn_t (*callback) (void *, size_t, void *);
- const char *tlsFingerprint;
-
- WaitressUrl_t url;
- WaitressUrl_t proxy;
-
- gnutls_certificate_credentials_t tlsCred;
-
- /* per-request data */
- struct {
- int sockfd;
-
- /* temporary return value storage */
- WaitressReturn_t readWriteRet;
-
- size_t contentLength, contentReceived, chunkSize;
- bool contentLengthKnown;
- enum {CHUNKSIZE = 0, DATA = 1} chunkedState;
-
- char *buf;
- /* first argument is WaitressHandle_t, but that's not defined yet */
- WaitressHandlerReturn_t (*dataHandler) (void *, char *, const size_t);
- WaitressReturn_t (*read) (void *, char *, const size_t, size_t *);
- WaitressReturn_t (*write) (void *, const char *, const size_t);
-
- gnutls_session_t tlsSession;
- } request;
-} WaitressHandle_t;
-
-void WaitressInit (WaitressHandle_t *);
-void WaitressFree (WaitressHandle_t *);
-bool WaitressSetProxy (WaitressHandle_t *, const char *);
-char *WaitressUrlEncode (const char *);
-bool WaitressSetUrl (WaitressHandle_t *, const char *);
-WaitressReturn_t WaitressFetchBuf (WaitressHandle_t *, char **);
-WaitressReturn_t WaitressFetchCall (WaitressHandle_t *);
-const char *WaitressErrorToStr (WaitressReturn_t);
-
-#endif /* SRC_LIBWAITRESS_WAITRESS_H_ZE5NT8JI */
-
diff --git a/src/main.c b/src/main.c
index 21d833f..dcf5eaf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -61,33 +61,11 @@ THE SOFTWARE.
#include "ui_dispatch.h"
#include "ui_readline.h"
-/* copy proxy settings to waitress handle
- */
-static void BarMainLoadProxy (const BarSettings_t *settings,
- WaitressHandle_t *waith) {
- /* set up proxy (control proxy for non-us citizen or global proxy for poor
- * firewalled fellows) */
- if (settings->controlProxy != NULL) {
- /* control proxy overrides global proxy */
- if (!WaitressSetProxy (waith, settings->controlProxy)) {
- /* if setting proxy fails, url is invalid */
- BarUiMsg (settings, MSG_ERR, "Control proxy (%s) is invalid!\n",
- settings->controlProxy);
- }
- } else if (settings->proxy != NULL && strlen (settings->proxy) > 0) {
- if (!WaitressSetProxy (waith, settings->proxy)) {
- /* if setting proxy fails, url is invalid */
- BarUiMsg (settings, MSG_ERR, "Proxy (%s) is invalid!\n",
- settings->proxy);
- }
- }
-}
-
/* authenticate user
*/
static bool BarMainLoginUser (BarApp_t *app) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataLogin_t reqData;
bool ret;
@@ -188,7 +166,7 @@ static bool BarMainGetLoginCredentials (BarSettings_t *settings,
*/
static bool BarMainGetStations (BarApp_t *app) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
bool ret;
BarUiMsg (&app->settings, MSG_INFO, "Get stations... ");
@@ -235,7 +213,7 @@ static void BarMainHandleUserInput (BarApp_t *app) {
*/
static void BarMainGetPlaylist (BarApp_t *app) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataGetPlaylist_t reqData;
reqData.station = app->curStation;
reqData.quality = app->settings.audioQuality;
@@ -288,7 +266,7 @@ static void BarMainStartPlayback (BarApp_t *app, pthread_t *playerThread) {
/* throw event */
BarUiStartEventCmd (&app->settings, "songstart",
app->curStation, curSong, &app->player, app->ph.stations,
- PIANO_RET_OK, WAITRESS_RET_OK);
+ PIANO_RET_OK, CURLE_OK);
/* prevent race condition, mode must _not_ be DEAD if
* thread has been started */
@@ -306,7 +284,7 @@ static void BarMainPlayerCleanup (BarApp_t *app, pthread_t *playerThread) {
BarUiStartEventCmd (&app->settings, "songfinish", app->curStation,
app->playlist, &app->player, app->ph.stations, PIANO_RET_OK,
- WAITRESS_RET_OK);
+ CURLE_OK);
/* FIXME: pthread_join blocks everything if network connection
* is hung up e.g. */
@@ -358,8 +336,6 @@ static void BarMainLoop (BarApp_t *app) {
return;
}
- BarMainLoadProxy (&app->settings, &app->waith);
-
if (!BarMainLoginUser (app)) {
return;
}
@@ -427,7 +403,6 @@ int main (int argc, char **argv) {
gcry_check_version (NULL);
gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
- gnutls_global_init ();
BarPlayerInit ();
BarSettingsInit (&app.settings);
@@ -452,10 +427,9 @@ int main (int argc, char **argv) {
app.settings.keys[BAR_KS_HELP]);
}
- WaitressInit (&app.waith);
- app.waith.url.host = app.settings.rpcHost;
- app.waith.url.tlsPort = app.settings.rpcTlsPort;
- app.waith.tlsFingerprint = app.settings.tlsFingerprint;
+ curl_global_init (CURL_GLOBAL_DEFAULT);
+ app.http = curl_easy_init ();
+ assert (app.http != NULL);
/* init fds */
FD_ZERO(&app.input.set);
@@ -496,9 +470,9 @@ int main (int argc, char **argv) {
PianoDestroy (&app.ph);
PianoDestroyPlaylist (app.songHistory);
PianoDestroyPlaylist (app.playlist);
- WaitressFree (&app.waith);
+ curl_easy_cleanup (app.http);
+ curl_global_cleanup ();
BarPlayerDestroy ();
- gnutls_global_deinit ();
BarSettingsDestroy (&app.settings);
/* restore terminal attributes, zsh doesn't need this, bash does... */
diff --git a/src/main.h b/src/main.h
index 12887ea..c8134ae 100644
--- a/src/main.h
+++ b/src/main.h
@@ -24,8 +24,9 @@ THE SOFTWARE.
#ifndef SRC_MAIN_H_4ZGSCG6X
#define SRC_MAIN_H_4ZGSCG6X
+#include <curl/curl.h>
+
#include <piano.h>
-#include <waitress.h>
#include "player.h"
#include "settings.h"
@@ -33,7 +34,7 @@ THE SOFTWARE.
typedef struct {
PianoHandle_t ph;
- WaitressHandle_t waith;
+ CURL *http;
player_t player;
BarSettings_t settings;
/* first item is current song */
diff --git a/src/player.h b/src/player.h
index 5c60e59..b97f5b2 100644
--- a/src/player.h
+++ b/src/player.h
@@ -36,7 +36,6 @@ THE SOFTWARE.
#include <libavfilter/avfilter.h>
#include <libavfilter/avfiltergraph.h>
#include <piano.h>
-#include <waitress.h>
#include "settings.h"
#include "config.h"
diff --git a/src/settings.h b/src/settings.h
index b56351e..ae22111 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -27,7 +27,6 @@ THE SOFTWARE.
#include <stdbool.h>
#include <piano.h>
-#include <waitress.h>
/* update structure in ui_dispatch.h if you add shortcuts here */
typedef enum {
diff --git a/src/ui.c b/src/ui.c
index 6259ba1..5dd5d79 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -131,32 +131,100 @@ void BarUiMsg (const BarSettings_t *settings, const BarUiMsg_t type,
fflush (stdout);
}
-/* fetch http resource (post request)
- * @param waitress handle
- * @param piano request (initialized by PianoRequest())
- */
-static WaitressReturn_t BarPianoHttpRequest (WaitressHandle_t *waith,
- PianoRequest_t *req) {
- waith->extraHeaders = "Content-Type: text/plain\r\n";
- waith->postData = req->postData;
- waith->method = WAITRESS_METHOD_POST;
- waith->url.path = req->urlPath;
- waith->url.tls = req->secure;
-
- return WaitressFetchBuf (waith, &req->responseData);
+typedef struct {
+ char *data;
+ size_t pos;
+} buffer;
+
+static size_t httpFetchCb (char *ptr, size_t size, size_t nmemb,
+ void *userdata) {
+ buffer * const buffer = userdata;
+ size_t recvSize = size * nmemb;
+
+ if (buffer->data == NULL) {
+ if ((buffer->data = malloc (sizeof (*buffer->data) *
+ (recvSize + 1))) == NULL) {
+ return 0;
+ }
+ } else {
+ char *newbuf;
+ if ((newbuf = realloc (buffer->data, sizeof (*buffer->data) *
+ (buffer->pos + recvSize + 1))) == NULL) {
+ free (buffer->data);
+ return 0;
+ }
+ buffer->data = newbuf;
+ }
+ memcpy (buffer->data + buffer->pos, ptr, recvSize);
+ buffer->pos += recvSize;
+ buffer->data[buffer->pos] = '\0';
+
+ return recvSize;
+}
+
+#define setAndCheck(k,v) \
+ httpret = curl_easy_setopt (http, k, v); \
+ assert (httpret == CURLE_OK);
+
+static CURLcode BarPianoHttpRequest (CURL * const http,
+ const BarSettings_t * const settings, PianoRequest_t * const req) {
+ buffer buffer = {NULL, 0};
+ char url[2048];
+ int ret = snprintf (url, sizeof (url), "%s://%s:%s%s",
+ req->secure ? "https" : "http",
+ settings->rpcHost,
+ req->secure ? settings->rpcTlsPort : "80",
+ req->urlPath);
+ assert (ret >= 0 && ret <= (int) sizeof (url));
+
+ curl_easy_reset (http);
+ CURLcode httpret;
+ setAndCheck (CURLOPT_URL, url);
+ setAndCheck (CURLOPT_USERAGENT, PACKAGE "-" VERSION);
+ setAndCheck (CURLOPT_POSTFIELDS, req->postData);
+ setAndCheck (CURLOPT_WRITEFUNCTION, httpFetchCb);
+ setAndCheck (CURLOPT_WRITEDATA, &buffer);
+ setAndCheck (CURLOPT_POST, 1);
+ setAndCheck (CURLOPT_TIMEOUT, 30);
+
+ /* set up proxy (control proxy for non-us citizen or global proxy for poor
+ * firewalled fellows) */
+ if (settings->controlProxy != NULL) {
+ /* control proxy overrides global proxy */
+ if (curl_easy_setopt (http, CURLOPT_PROXY,
+ settings->controlProxy) != CURLE_OK) {
+ /* if setting proxy fails, url is invalid */
+ BarUiMsg (settings, MSG_ERR, "Control proxy (%s) is invalid!\n",
+ settings->controlProxy);
+ }
+ } else if (settings->proxy != NULL && strlen (settings->proxy) > 0) {
+ if (curl_easy_setopt (http, CURLOPT_PROXY,
+ settings->proxy) != CURLE_OK) {
+ /* if setting proxy fails, url is invalid */
+ BarUiMsg (settings, MSG_ERR, "Proxy (%s) is invalid!\n",
+ settings->proxy);
+ }
+ }
+
+ struct curl_slist *list = NULL;
+ list = curl_slist_append (list, "Content-Type: text/plain");
+ setAndCheck (CURLOPT_HTTPHEADER, list);
+
+ httpret = curl_easy_perform (http);
+
+ curl_slist_free_all (list);
+
+ req->responseData = buffer.data;
+
+ return httpret;
}
/* piano wrapper: prepare/execute http request and pass result back to
* libpiano (updates data structures)
- * @param app handle
- * @param request type
- * @param request data
- * @param stores piano return code
- * @param stores waitress return code
* @return 1 on success, 0 otherwise
*/
int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type,
- void *data, PianoReturn_t *pRet, WaitressReturn_t *wRet) {
+ void *data, PianoReturn_t *pRet, CURLcode *wRet) {
PianoRequest_t req;
memset (&req, 0, sizeof (req));
@@ -172,9 +240,10 @@ int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type,
return 0;
}
- *wRet = BarPianoHttpRequest (&app->waith, &req);
- if (*wRet != WAITRESS_RET_OK) {
- BarUiMsg (&app->settings, MSG_NONE, "Network error: %s\n", WaitressErrorToStr (*wRet));
+ *wRet = BarPianoHttpRequest (app->http, &app->settings, &req);
+ if (*wRet != CURLE_OK) {
+ BarUiMsg (&app->settings, MSG_NONE, "Network error: %s\n",
+ curl_easy_strerror (*wRet));
if (req.responseData != NULL) {
free (req.responseData);
}
@@ -189,7 +258,7 @@ int BarUiPianoCall (BarApp_t * const app, PianoRequestType_t type,
type != PIANO_REQUEST_LOGIN) {
/* reauthenticate */
PianoReturn_t authpRet;
- WaitressReturn_t authwRet;
+ CURLcode authwRet;
PianoRequestDataLogin_t reqData;
reqData.user = app->settings.username;
reqData.password = app->settings.password;
@@ -481,7 +550,7 @@ char *BarUiSelectMusicId (BarApp_t *app, PianoStation_t *station,
if (BarReadlineStr (lineBuf, sizeof (lineBuf), &app->input,
BAR_RL_DEFAULT) > 0) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataSearch_t reqData;
reqData.searchStr = lineBuf;
@@ -680,12 +749,11 @@ size_t BarUiListSongs (const BarSettings_t *settings,
* @param current station
* @param current song
* @param piano error-code (PIANO_RET_OK if not applicable)
- * @param waitress error-code (WAITRESS_RET_OK if not applicable)
*/
void BarUiStartEventCmd (const BarSettings_t *settings, const char *type,
const PianoStation_t *curStation, const PianoSong_t *curSong,
const player_t * const player, PianoStation_t *stations,
- PianoReturn_t pRet, WaitressReturn_t wRet) {
+ PianoReturn_t pRet, CURLcode wRet) {
pid_t chld;
int pipeFd[2];
@@ -748,7 +816,7 @@ void BarUiStartEventCmd (const BarSettings_t *settings, const char *type,
pRet,
PianoErrorToStr (pRet),
wRet,
- WaitressErrorToStr (wRet),
+ curl_easy_strerror (wRet),
player->songDuration,
player->songPlayed,
curSong == NULL ? PIANO_RATE_NONE : curSong->rating,
diff --git a/src/ui.h b/src/ui.h
index 60262f8..f49ec62 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -27,7 +27,6 @@ THE SOFTWARE.
#include <stdbool.h>
#include <piano.h>
-#include <waitress.h>
#include "settings.h"
#include "player.h"
@@ -50,9 +49,9 @@ void BarUiPrintSong (const BarSettings_t *, const PianoSong_t *,
size_t BarUiListSongs (const BarSettings_t *, const PianoSong_t *, const char *);
void BarUiStartEventCmd (const BarSettings_t *, const char *,
const PianoStation_t *, const PianoSong_t *, const player_t *,
- PianoStation_t *, PianoReturn_t, WaitressReturn_t);
+ PianoStation_t *, PianoReturn_t, CURLcode);
int BarUiPianoCall (BarApp_t * const, PianoRequestType_t,
- void *, PianoReturn_t *, WaitressReturn_t *);
+ void *, PianoReturn_t *, CURLcode *);
void BarUiHistoryPrepend (BarApp_t *app, PianoSong_t *song);
#endif /* SRC_UI_H_46P20TS0 */
diff --git a/src/ui_act.c b/src/ui_act.c
index c39f98b..adb2f87 100644
--- a/src/ui_act.c
+++ b/src/ui_act.c
@@ -63,7 +63,7 @@ static inline void BarUiDoSkipSong (player_t * const player) {
*/
static int BarTransformIfShared (BarApp_t *app, PianoStation_t *station) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
assert (station != NULL);
@@ -96,7 +96,7 @@ BarUiActCallback(BarUiActHelp) {
*/
BarUiActCallback(BarUiActAddMusic) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataAddSeed_t reqData;
assert (selStation != NULL);
@@ -122,7 +122,7 @@ BarUiActCallback(BarUiActAddMusic) {
*/
BarUiActCallback(BarUiActBanSong) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoStation_t *realStation;
assert (selStation != NULL);
@@ -154,7 +154,7 @@ BarUiActCallback(BarUiActBanSong) {
*/
BarUiActCallback(BarUiActCreateStation) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataCreateStation_t reqData;
reqData.type = PIANO_MUSICTYPE_INVALID;
@@ -172,7 +172,7 @@ BarUiActCallback(BarUiActCreateStation) {
*/
BarUiActCallback(BarUiActCreateStationFromSong) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataCreateStation_t reqData;
char selectBuf[2];
@@ -202,7 +202,7 @@ BarUiActCallback(BarUiActCreateStationFromSong) {
*/
BarUiActCallback(BarUiActAddSharedStation) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
char stationId[50];
PianoRequestDataCreateStation_t reqData;
@@ -222,7 +222,7 @@ BarUiActCallback(BarUiActAddSharedStation) {
*/
BarUiActCallback(BarUiActDeleteStation) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
assert (selStation != NULL);
@@ -247,7 +247,7 @@ BarUiActCallback(BarUiActDeleteStation) {
*/
BarUiActCallback(BarUiActExplain) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataExplain_t reqData;
assert (selSong != NULL);
@@ -266,7 +266,7 @@ BarUiActCallback(BarUiActExplain) {
*/
BarUiActCallback(BarUiActStationFromGenre) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
const PianoGenreCategory_t *curCat;
const PianoGenre_t *curGenre;
int i;
@@ -376,7 +376,7 @@ BarUiActCallback(BarUiActDebug) {
*/
BarUiActCallback(BarUiActLoveSong) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoStation_t *realStation;
assert (selStation != NULL);
@@ -438,7 +438,7 @@ BarUiActCallback(BarUiActTogglePause) {
*/
BarUiActCallback(BarUiActRenameStation) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
char lineBuf[100];
assert (selStation != NULL);
@@ -481,7 +481,7 @@ BarUiActCallback(BarUiActSelectStation) {
*/
BarUiActCallback(BarUiActTempBanSong) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
assert (selSong != NULL);
@@ -547,7 +547,7 @@ static void BarUiActQuickmixCallback (BarApp_t *app, char *buf) {
*/
BarUiActCallback(BarUiActSelectQuickMix) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
assert (selStation != NULL);
@@ -616,7 +616,7 @@ BarUiActCallback(BarUiActHistory) {
*/
BarUiActCallback(BarUiActBookmark) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
char selectBuf[2];
assert (selSong != NULL);
@@ -660,7 +660,7 @@ BarUiActCallback(BarUiActVolReset) {
*/
BarUiActCallback(BarUiActManageStation) {
PianoReturn_t pRet;
- WaitressReturn_t wRet;
+ CURLcode wRet;
PianoRequestDataGetStationInfo_t reqData;
char selectBuf[2], allowedActions[6], *allowedPos = allowedActions;
char question[64];