diff options
-rw-r--r-- | src/libwaitress/waitress.c | 114 | ||||
-rw-r--r-- | src/libwaitress/waitress.h | 1 |
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; |