summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2011-11-13 16:58:31 +0100
committerLars-Dominik Braun <lars@6xq.net>2011-11-13 17:16:17 +0100
commitcc4fe9fe07a7bee817be8402cfbd3b082360b9f9 (patch)
tree89ccff4964e6b92064e2e307c3a2b0684f216738
parent340ada63936ed3164cd82fb989b7797210179cc6 (diff)
downloadpianobar-cc4fe9fe07a7bee817be8402cfbd3b082360b9f9.tar.gz
pianobar-cc4fe9fe07a7bee817be8402cfbd3b082360b9f9.tar.bz2
pianobar-cc4fe9fe07a7bee817be8402cfbd3b082360b9f9.zip
waitress: Use HTTP parser for proxy response parsing
-rw-r--r--src/libwaitress/waitress.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c
index 13388c4..1aeea90 100644
--- a/src/libwaitress/waitress.c
+++ b/src/libwaitress/waitress.c
@@ -53,6 +53,8 @@ typedef struct {
size_t pos;
} WaitressFetchBufCbBuffer_t;
+static WaitressReturn_t WaitressReceiveHeaders (WaitressHandle_t *, size_t *);
+
void WaitressInit (WaitressHandle_t *waith) {
assert (waith != NULL);
@@ -803,6 +805,8 @@ static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) {
if (WaitressProxyEnabled (waith)) {
char buf[256];
ssize_t size;
+ WaitressReturn_t wRet;
+
snprintf (buf, sizeof (buf), "CONNECT %s:%s HTTP/"
WAITRESS_HTTP_VERSION "\r\n",
waith->url.host, WaitressDefaultPort (&waith->url));
@@ -816,10 +820,9 @@ static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) {
waith->request.write (waith, "\r\n", 2);
- waith->request.read (waith, buf, sizeof (buf)-1, &size);
- buf[size] = 0;
- if (WaitressParseStatusline (buf) != 200) {
- return WAITRESS_RET_CONNECT_REFUSED;
+ if ((wRet = WaitressReceiveHeaders (waith, &size)) !=
+ WAITRESS_RET_OK) {
+ return wRet;
}
}
@@ -914,23 +917,22 @@ static WaitressReturn_t WaitressSendRequest (WaitressHandle_t *waith) {
#undef WRITE_RET
}
-/* read response header and data
- */
-static WaitressReturn_t WaitressReceiveResponse (WaitressHandle_t *waith) {
#define READ_RET(buf, count, size) \
if ((wRet = waith->request.read (waith, buf, count, size)) != \
WAITRESS_RET_OK) { \
return wRet; \
}
-
- assert (waith != NULL);
- assert (waith->request.buf != NULL);
-
+/* 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;
+ ssize_t recvSize = 0;
char *nextLine = NULL, *thisLine = NULL;
enum {HDRM_HEAD, HDRM_LINES, HDRM_FINISHED} hdrParseMode = HDRM_HEAD;
- ssize_t recvSize = 0;
- size_t bufFilled = 0;
WaitressReturn_t wRet = WAITRESS_RET_OK;
/* receive answer */
@@ -1004,7 +1006,25 @@ static WaitressReturn_t WaitressReceiveResponse (WaitressHandle_t *waith) {
bufFilled -= (thisLine-buf);
} /* end while hdrParseMode */
- recvSize = bufFilled;
+ *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;
+ ssize_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';
@@ -1066,16 +1086,15 @@ WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
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) {
- waith->request.buf = malloc (WAITRESS_BUFFER_SIZE *
- sizeof (*waith->request.buf));
-
if ((wRet = WaitressSendRequest (waith)) == WAITRESS_RET_OK) {
wRet = WaitressReceiveResponse (waith);
}
-
- free (waith->request.buf);
}
/* cleanup */
@@ -1085,6 +1104,7 @@ WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
gnutls_certificate_free_credentials (waith->tlsCred);
}
close (waith->request.sockfd);
+ free (waith->request.buf);
if (wRet == WAITRESS_RET_OK &&
waith->request.contentReceived < waith->request.contentLength) {