aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-12-29 17:36:03 +0000
committerNick Mathewson <nickm@torproject.org>2007-12-29 17:36:03 +0000
commitcd85eac0d3324555480b373df0e4051856a89f5e (patch)
treefc3d27be1e5e723bd217f3f4721251e18ebab8a3 /src
parentf4f5dc4aca76537258789f36a116f3abf0a07f70 (diff)
downloadtor-cd85eac0d3324555480b373df0e4051856a89f5e.tar
tor-cd85eac0d3324555480b373df0e4051856a89f5e.tar.gz
r17433@catbus: nickm | 2007-12-29 12:35:57 -0500
Incomplete code to avoid doing needless pull-ups on HTTP. Also, use memstr instead of strstr to find the content-length header. svn:r13005
Diffstat (limited to 'src')
-rw-r--r--src/or/buffers.c112
1 files changed, 110 insertions, 2 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index ea9ff3a2a..729b987b4 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -943,6 +943,93 @@ move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
return cp;
}
+// #define BUFPOS
+#ifdef BUFPOS
+typedef struct buf_pos_t {
+ chunk_t *chunk;
+ int pos;
+ int pos_absolute;
+};
+
+static void
+buf_pos_init(buf_t *buf, buf_pos_t *out)
+{
+ out->chunk = buf->head;
+ out->pos = 0;
+ out->pos_absolute = 0;
+}
+
+static int
+buf_find_pos_of_char(const buf_t *buf, char ch, buf_pos_t *out)
+{
+ chunk_t *chunk;
+ int offset = 0;
+ int pos = chunk->pos;
+ for (chunk = out->chunk; chunk; chunk = chunk->next) {
+ char *cp = memchr(chunk->data+pos, ch, chunk->datalen-pos);
+ if (cp) {
+ out->chunk = chunk;
+ out->pos = cp - chunk->data;
+ out->pos_absolute = offset + (cp - chunk->data);
+ return out->pos_absolute;
+ } else {
+ offset += chunk->datalen;
+ pos = 0;
+ }
+ }
+ return -1;
+}
+
+static INLINE int
+buf_pos_inc(buf_pos_t *pos)
+{
+ if (pos->pos == pos->chunk->datalen) {
+ if (!pos->chunk->next)
+ return -1;
+ pos->chunk = pos->chunk->next;
+ pos->pos = 0;
+ } else {
+ ++pos->pos;
+ }
+ ++pos->pos_absolute;
+}
+
+static int
+buf_matches_at_pos(const buf_t *buf, const buf_pos_t *pos, const char *s,
+ int n)
+{
+ buf_pos_t p;
+ memcpy(p, pos, sizeof(p));
+
+ while (n) {
+ char ch = p->chunk->data[p->pos];
+ if (ch != *s)
+ return 0;
+ ++s;
+ --n;
+ if (buf_pos_inc(p)<0)
+ return 0;
+ }
+ return 1;
+}
+
+static int
+buf_find_string_offset(const char *buf, const char *s, int n)
+{
+ buf_pos_t pos;
+ buf_pos_init(buf, &pos);
+ while (buf_find_pos_of_char(buf, *s, &pos) >= 0) {
+ if (buf_matches_at_pos(buf, pos, s, n)) {
+ return pos->pos_absolute;
+ } else {
+ if (buf_pos_inc(pos)<0)
+ return -1;
+ }
+ }
+ return -1;
+}
+#endif
+
/** There is a (possibly incomplete) http statement on <b>buf</b>, of the
* form "\%s\\r\\n\\r\\n\%s", headers, body. (body may contain nuls.)
* If a) the headers include a Content-Length field and all bytes in
@@ -968,14 +1055,33 @@ fetch_from_buf_http(buf_t *buf,
char **body_out, size_t *body_used, size_t max_bodylen,
int force_complete)
{
- char *headers, *body, *p;
+ char *headers, *p, *body;
size_t headerlen, bodylen, contentlen;
+#ifdef BUFPOS
+ int crlf_offset;
+#endif
check();
if (!buf->head)
return 0;
headers = buf->head->data;
+
+#ifdef BUFPOS
+ crlf_offset = buf_find_string_offset(buf, "\r\n\r\n", 4);
+ if (crlf_offset > max_headerlen ||
+ (crlf_offset < 0 && buf->datalen > max_headerlen)) {
+ log_debug(LD_HTTP,"headers too long.");
+ return -1;
+ } else if (crlf_offset < 0) {
+ log_debug(LD_HTTP,"headers not all here yet.");
+ return 0;
+ }
+ if (buf->head->datalen < crlf_offset + 4)
+ buf_pullup(buf, crlf_offset+4, 0);
+ headerlen = crlf_offset + 4;
+ body = buf->data + headerlen; /*XXX020 unused. */
+#else
/* See if CRLFCRLF is already in the head chunk. If it is, we don't need
* to move or resize anything. */
body = (char*) tor_memmem(buf->head->data, buf->head->datalen,
@@ -1001,6 +1107,8 @@ fetch_from_buf_http(buf_t *buf,
}
body += 4; /* Skip the the CRLFCRLF */
headerlen = body-headers; /* includes the CRLFCRLF */
+#endif
+
bodylen = buf->datalen - headerlen;
log_debug(LD_HTTP,"headerlen %d, bodylen %d.", (int)headerlen, (int)bodylen);
@@ -1016,7 +1124,7 @@ fetch_from_buf_http(buf_t *buf,
}
#define CONTENT_LENGTH "\r\nContent-Length: "
- p = strstr(headers, CONTENT_LENGTH);
+ p = (char*) tor_memstr(headers, headerlen, CONTENT_LENGTH);
if (p) {
int i;
i = atoi(p+strlen(CONTENT_LENGTH));