aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/buffers.c70
-rw-r--r--src/or/buffers.h4
2 files changed, 74 insertions, 0 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 6ba2f1f65..374c37c86 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1347,6 +1347,76 @@ fetch_from_buf_http(buf_t *buf,
return 1;
}
+#ifdef USE_BUFFEREVENTS
+int
+fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete)
+{
+ struct evbuffer_ptr crlf;
+ unsigned char *headers;
+ size_t headerlen, bodylen, contentlen;
+ char *p;
+
+ crlf = evbuffer_search(buf, "\r\n\r\n", 4, NULL);
+ if (crlf.pos < 0) {
+ if (evbuffer_get_length(buf) > max_headerlen)
+ return -1; /* Headers too long. */
+ return 0; /* Headers not here yet. */
+ } else if (crlf.pos > (int)max_headerlen)
+ return -1; /* Headers too long. */
+
+ /* Okay, we've found the end of the headers. Pull them into the first
+ * chunk. */
+ /* XXXX Or don't! It would be better to scan for the Content-Length as-is.*/
+ headerlen = crlf.pos + 4;
+ bodylen = evbuffer_get_length(buf) - headerlen;
+ if (bodylen > max_bodylen)
+ return -1; /* body too long */
+
+ headers = evbuffer_pullup(buf, headerlen);
+ tor_assert(headers && evbuffer_get_contiguous_space(buf) >= headerlen);
+ p = (char*) tor_memstr(headers, headerlen, CONTENT_LENGTH);
+ if (p) {
+ int i = atoi(p+strlen(CONTENT_LENGTH));
+ if (i < 0) {
+ log_warn(LD_PROTOCOL, "Content-Length is less than zero; it looks like "
+ "someone is trying to crash us.");
+ return -1;
+ }
+ contentlen = i;
+ /* if content-length is malformed, then our body length is 0. fine. */
+ log_debug(LD_HTTP,"Got a contentlen of %d.",(int)contentlen);
+ if (bodylen < contentlen) {
+ if (!force_complete) {
+ log_debug(LD_HTTP,"body not all here yet.");
+ return 0; /* not all there yet */
+ }
+ }
+ if (bodylen > contentlen) {
+ bodylen = contentlen;
+ log_debug(LD_HTTP,"bodylen reduced to %d.",(int)bodylen);
+ }
+ }
+
+ if (headers_out) {
+ *headers_out = tor_malloc(headerlen+1);
+ evbuffer_remove(buf, *headers_out, headerlen);
+ (*headers_out)[headerlen] = '\0';
+ }
+ if (body_out) {
+ tor_assert(headers_out);
+ tor_assert(body_used);
+ *body_used = bodylen;
+ *body_out = tor_malloc(bodylen+1);
+ evbuffer_remove(buf, *body_out, bodylen);
+ (*body_out)[bodylen] = '\0';
+ }
+ return 1;
+}
+#endif
+
/** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
* of the forms
* - socks4: "socksheader username\\0"
diff --git a/src/or/buffers.h b/src/or/buffers.h
index d6ff79e93..ca01dc807 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -53,6 +53,10 @@ int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
int linkproto);
int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
int log_sockstype, int safe_socks);
+int fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete);
#endif
void assert_buf_ok(buf_t *buf);