summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libwaitress/waitress.c114
-rw-r--r--src/libwaitress/waitress.h1
2 files changed, 61 insertions, 54 deletions
diff --git a/src/libwaitress/waitress.c b/src/libwaitress/waitress.c
index 8202a38..1697258 100644
--- a/src/libwaitress/waitress.c
+++ b/src/libwaitress/waitress.c
@@ -408,18 +408,16 @@ WaitressReturn_t WaitressFetchBuf (WaitressHandle_t *waith, char **retBuffer) {
/* poll wrapper that retries after signal interrupts, required for socksify
* wrapper
*/
-static int WaitressPollLoop (struct pollfd *fds, nfds_t nfds, int timeout) {
+static int WaitressPollLoop (int fd, short events, int timeout) {
int pollres = -1;
- int pollerr = 0;
+ struct pollfd sockpoll = {fd, events, 0};
- assert (fds != NULL);
- assert (nfds > 0);
+ assert (fd != -1);
do {
- pollres = poll (fds, nfds, timeout);
- pollerr = errno;
errno = 0;
- } while (pollerr == EINTR || pollerr == EINPROGRESS || pollerr == EAGAIN);
+ pollres = poll (&sockpoll, 1, timeout);
+ } while (errno == EINTR || errno == EINPROGRESS || errno == EAGAIN);
return pollres;
}
@@ -432,17 +430,15 @@ static int WaitressPollLoop (struct pollfd *fds, nfds_t nfds, int timeout) {
* @param timeout (microseconds)
* @return WAITRESS_RET_OK, WAITRESS_RET_TIMEOUT or WAITRESS_RET_ERR
*/
-static WaitressReturn_t WaitressPollWrite (int sockfd, const char *buf, size_t count,
- struct pollfd *sockpoll, int timeout) {
+static WaitressReturn_t WaitressPollWrite (int sockfd, const char *buf,
+ size_t count, int timeout) {
int pollres = -1;
assert (sockfd != -1);
assert (buf != NULL);
assert (count > 0);
- assert (sockpoll != NULL);
- sockpoll->events = POLLOUT;
- pollres = WaitressPollLoop (sockpoll, 1, timeout);
+ pollres = WaitressPollLoop (sockfd, POLLOUT, timeout);
if (pollres == 0) {
return WAITRESS_RET_TIMEOUT;
} else if (pollres == -1) {
@@ -464,17 +460,15 @@ static WaitressReturn_t WaitressPollWrite (int sockfd, const char *buf, size_t c
* @return WAITRESS_RET_OK, WAITRESS_RET_TIMEOUT, WAITRESS_RET_ERR
*/
static WaitressReturn_t WaitressPollRead (int sockfd, char *buf, size_t count,
- struct pollfd *sockpoll, int timeout, ssize_t *retSize) {
+ int timeout, ssize_t *retSize) {
int pollres = -1;
assert (sockfd != -1);
assert (buf != NULL);
assert (count > 0);
- assert (sockpoll != NULL);
assert (retSize != NULL);
- sockpoll->events = POLLIN;
- pollres = WaitressPollLoop (sockpoll, 1, timeout);
+ pollres = WaitressPollLoop (sockfd, POLLIN, timeout);
if (pollres == 0) {
return WAITRESS_RET_TIMEOUT;
} else if (pollres == -1) {
@@ -650,39 +644,12 @@ static int WaitressParseStatusline (const char * const line) {
return -1;
}
-/* Receive data from host and call *callback ()
- * @param waitress handle
- * @return WaitressReturn_t
+/* Connect to server
*/
-WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
-/* FIXME: compiler macros are ugly... */
-#define FINISH(ret) wRet = ret; goto finish;
-#define WRITE_RET(buf, count) \
- if ((wRet = WaitressPollWrite (sockfd, buf, count, \
- &sockpoll, waith->socktimeout)) != WAITRESS_RET_OK) { \
- FINISH (wRet); \
- }
-#define READ_RET(buf, count, size) \
- if ((wRet = WaitressPollRead (sockfd, buf, count, \
- &sockpoll, waith->socktimeout, size)) != WAITRESS_RET_OK) { \
- FINISH (wRet); \
- }
-
+static WaitressReturn_t WaitressConnect (WaitressHandle_t *waith) {
struct addrinfo hints, *res;
- int sockfd;
- char *buf = NULL;
- ssize_t recvSize = 0;
- WaitressReturn_t wRet = WAITRESS_RET_OK;
- struct pollfd sockpoll;
int pollres;
- /* header parser vars */
- char *nextLine = NULL, *thisLine = NULL;
- enum {HDRM_HEAD, HDRM_LINES, HDRM_FINISHED} hdrParseMode = HDRM_HEAD;
- unsigned int bufFilled = 0;
- /* initialize */
- memset (&waith->request, 0, sizeof (waith->request));
- waith->request.dataHandler = WaitressHandleIdentity;
memset (&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
@@ -701,24 +668,25 @@ WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
}
}
- if ((sockfd = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
+ if ((waith->request.sockfd = socket (res->ai_family, res->ai_socktype,
+ res->ai_protocol)) == -1) {
freeaddrinfo (res);
return WAITRESS_RET_SOCK_ERR;
}
- sockpoll.fd = sockfd;
/* we need shorter timeouts for connect() */
- fcntl (sockfd, F_SETFL, O_NONBLOCK);
+ fcntl (waith->request.sockfd, F_SETFL, O_NONBLOCK);
/* increase socket receive buffer */
const int sockopt = 256*1024;
- setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof (sockopt));
+ setsockopt (waith->request.sockfd, SOL_SOCKET, SO_RCVBUF, &sockopt,
+ sizeof (sockopt));
/* non-blocking connect will return immediately */
- connect (sockfd, res->ai_addr, res->ai_addrlen);
+ connect (waith->request.sockfd, res->ai_addr, res->ai_addrlen);
- sockpoll.events = POLLOUT;
- pollres = WaitressPollLoop (&sockpoll, 1, waith->socktimeout);
+ pollres = WaitressPollLoop (waith->request.sockfd, POLLOUT,
+ waith->socktimeout);
freeaddrinfo (res);
if (pollres == 0) {
return WAITRESS_RET_TIMEOUT;
@@ -727,11 +695,49 @@ WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
}
/* check connect () return value */
socklen_t pollresSize = sizeof (pollres);
- getsockopt (sockfd, SOL_SOCKET, SO_ERROR, &pollres, &pollresSize);
+ getsockopt (waith->request.sockfd, SOL_SOCKET, SO_ERROR, &pollres,
+ &pollresSize);
if (pollres != 0) {
return WAITRESS_RET_CONNECT_REFUSED;
}
+ return WAITRESS_RET_OK;
+}
+
+/* Receive data from host and call *callback ()
+ * @param waitress handle
+ * @return WaitressReturn_t
+ */
+WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
+/* FIXME: compiler macros are ugly... */
+#define FINISH(ret) wRet = ret; goto finish;
+#define WRITE_RET(buf, count) \
+ if ((wRet = WaitressPollWrite (waith->request.sockfd, buf, count, \
+ waith->socktimeout)) != WAITRESS_RET_OK) { \
+ FINISH (wRet); \
+ }
+#define READ_RET(buf, count, size) \
+ if ((wRet = WaitressPollRead (waith->request.sockfd, buf, count, \
+ waith->socktimeout, size)) != WAITRESS_RET_OK) { \
+ FINISH (wRet); \
+ }
+
+ char *buf = NULL;
+ ssize_t recvSize = 0;
+ WaitressReturn_t wRet = WAITRESS_RET_OK;
+ /* header parser vars */
+ char *nextLine = NULL, *thisLine = NULL;
+ enum {HDRM_HEAD, HDRM_LINES, HDRM_FINISHED} hdrParseMode = HDRM_HEAD;
+ unsigned int bufFilled = 0;
+
+ /* initialize */
+ memset (&waith->request, 0, sizeof (waith->request));
+ waith->request.dataHandler = WaitressHandleIdentity;
+
+ if ((wRet = WaitressConnect (waith)) != WAITRESS_RET_OK) {
+ return wRet;
+ }
+
const char *path = waith->url.path;
if (waith->url.path == NULL) {
/* avoid NULL pointer deref */
@@ -884,7 +890,7 @@ WaitressReturn_t WaitressFetchCall (WaitressHandle_t *waith) {
} while (recvSize > 0);
finish:
- close (sockfd);
+ close (waith->request.sockfd);
free (buf);
if (wRet == WAITRESS_RET_OK &&
diff --git a/src/libwaitress/waitress.h b/src/libwaitress/waitress.h
index 6f43ca2..ed7d4dc 100644
--- a/src/libwaitress/waitress.h
+++ b/src/libwaitress/waitress.h
@@ -70,6 +70,7 @@ typedef struct {
/* per-request data */
struct {
size_t contentLength, contentReceived, chunkSize;
+ int sockfd;
/* first argument is WaitressHandle_t, but that's not defined here */
WaitressHandlerReturn_t (*dataHandler) (void *, char *, const size_t);
} request;