} \
} while (0)
-#define HTTP_RECVLEN 1024
+#define HTTP_RECVLEN 4096
#define HTTP_SENDGROW 1024
#define HTTP_SEND_MAXLEN 10240
* the backing store.
* The third buffer is compbuffer, managed by us, that contains the
* compressed HTTP data, if compression is used.
- *
*/
isc_buffer_t headerbuffer;
isc_buffer_t compbuffer;
httpd_response(isc_httpd_t *);
static isc_result_t
-process_request(isc_httpd_t *, isc_region_t *);
+process_request(isc_httpd_t *, isc_region_t *, size_t *);
static isc_result_t
grow_headerspace(isc_httpd_t *);
isc_region_t r;
isc_buffer_region(buffer, &r);
- if (r.length > 0) {
+ if (r.base != NULL) {
isc_mem_put(mctx, r.base, r.length);
}
}
}
static isc_result_t
-process_request(isc_httpd_t *httpd, isc_region_t *region) {
- char *s = NULL, *p = NULL;
+process_request(isc_httpd_t *httpd, isc_region_t *region, size_t *buflen) {
+ char *s = NULL, *p = NULL, *urlend = NULL;
+ size_t limit = sizeof(httpd->recvbuf) - httpd->recvlen - 1;
+ size_t len = region->length;
int delim;
- memmove(httpd->recvbuf + httpd->recvlen, region->base, region->length);
- httpd->recvlen += region->length;
+ if (len > limit) {
+ len = limit;
+ }
+
+ memmove(httpd->recvbuf + httpd->recvlen, region->base, len);
+ httpd->recvlen += len;
httpd->recvbuf[httpd->recvlen] = 0;
+ *buflen = httpd->recvlen;
httpd->headers = NULL;
/*
}
/*
- * NUL terminate request at the blank line.
+ * NULL terminate the request at the blank line.
*/
s[delim] = 0;
if (!BUFLENOK(s)) {
return (ISC_R_NOMEMORY);
}
- *s = 0;
+ urlend = s;
/*
* Make the URL relative.
*/
- if ((strncmp(p, "http:/", 6) == 0) || (strncmp(p, "https:/", 7) == 0)) {
- /* Skip first / */
+ if (strncmp(p, "http://", 7) == 0 || strncmp(p, "https://", 8) == 0) {
+ /* Skip first '/' */
while (*p != '/' && *p != 0) {
p++;
}
return (ISC_R_RANGE);
}
p++;
- /* Skip second / */
+ /* Skip second '/' */
while (*p != '/' && *p != 0) {
p++;
}
return (ISC_R_RANGE);
}
p++;
- /* Find third / */
+ /* Find third '/' */
while (*p != '/' && *p != 0) {
p++;
}
s = p;
/*
- * Now, see if there is a ? mark in the URL. If so, this is
+ * Now, see if there is a question mark in the URL. If so, this is
* part of the query string, and we will split it from the URL.
*/
httpd->querystring = strchr(httpd->url, '?');
return (ISC_R_RANGE);
}
+ /*
+ * Looks like a a valid request, so now we know we won't have
+ * to process this buffer again. We can NULL-terminate the
+ * URL for the caller's benefit, and set recvlen to 0 so
+ * the next read will overwrite this one instead of appending
+ * to the buffer.
+ */
+ *urlend = 0;
+ httpd->recvlen = 0;
+
return (ISC_R_SUCCESS);
}
isc_buffer_clear(&httpd->headerbuffer);
isc_buffer_clear(&httpd->compbuffer);
isc_buffer_invalidate(&httpd->bodybuffer);
-
- httpdmgr_detach(&httpdmgr);
}
static void
httpd_put(void *arg) {
isc_httpd_t *httpd = (isc_httpd_t *)arg;
- isc_httpdmgr_t *httpdmgr = NULL;
+ isc_httpdmgr_t *mgr = NULL;
REQUIRE(VALID_HTTPD(httpd));
- httpdmgr = httpd->mgr;
- REQUIRE(VALID_HTTPDMGR(httpdmgr));
+ mgr = httpd->mgr;
+ REQUIRE(VALID_HTTPDMGR(mgr));
httpd->magic = 0;
+ httpd->mgr = NULL;
- free_buffer(httpdmgr->mctx, &httpd->headerbuffer);
- free_buffer(httpdmgr->mctx, &httpd->compbuffer);
+ free_buffer(mgr->mctx, &httpd->headerbuffer);
+ free_buffer(mgr->mctx, &httpd->compbuffer);
+ httpdmgr_detach(&mgr);
#if ENABLE_AFL
if (finishhook != NULL) {
if (httpd == NULL) {
httpd = isc_nmhandle_getextra(handle);
*httpd = (isc_httpd_t){ .handle = NULL };
+ httpdmgr_attach(httpdmgr, &httpd->mgr);
}
if (httpd->handle == NULL) {
INSIST(httpd->handle == handle);
}
- httpdmgr_attach(httpdmgr, &httpd->mgr);
-
/*
* Initialize the buffer for our headers.
*/
/*%<
* Reallocates compbuffer to size, does nothing if compbuffer is already
* larger than size.
- *
- * Requires:
- *\li httpd a valid isc_httpd_t object
- *
- * Returns:
- *\li #ISC_R_SUCCESS -- all is well.
- *\li #ISC_R_NOMEMORY -- not enough memory to extend buffer
*/
-static isc_result_t
+static void
alloc_compspace(isc_httpd_t *httpd, unsigned int size) {
- char *newspace;
+ char *newspace = NULL;
isc_region_t r;
isc_buffer_region(&httpd->compbuffer, &r);
if (size < r.length) {
- return (ISC_R_SUCCESS);
+ return;
}
newspace = isc_mem_get(httpd->mgr->mctx, size);
if (r.base != NULL) {
isc_mem_put(httpd->mgr->mctx, r.base, r.length);
}
-
- return (ISC_R_SUCCESS);
}
/*%<
httpd_compress(isc_httpd_t *httpd) {
z_stream zstr;
isc_region_t r;
- isc_result_t result;
int ret;
int inputlen;
inputlen = isc_buffer_usedlength(&httpd->bodybuffer);
- result = alloc_compspace(httpd, inputlen);
- if (result != ISC_R_SUCCESS) {
- return (result);
- }
+ alloc_compspace(httpd, inputlen);
isc_buffer_region(&httpd->compbuffer, &r);
/*
isc_region_t r;
bool is_compressed = false;
char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
+ size_t buflen = 0;
httpd = isc_nmhandle_getdata(handle);
goto cleanup_readhandle;
}
- result = process_request(httpd, region);
+ result = process_request(httpd, region, &buflen);
if (result == ISC_R_NOTFOUND) {
- if (httpd->recvlen < HTTP_RECVLEN - 1) {
- /* don't unref, continue reading */
+ if (buflen < HTTP_RECVLEN - 1) {
+ /* don't unref, keep reading */
return;
}
goto cleanup_readhandle;
isc_nmhandle_attach(handle, &httpd->sendhandle);
isc_nm_send(handle, &r, httpd_senddone, httpd);
- return;
cleanup_readhandle:
isc_nmhandle_detach(&httpd->readhandle);
}