summaryrefslogtreecommitdiff
path: root/src/or/buffers.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-06-17 18:49:55 +0000
committerNick Mathewson <nickm@torproject.org>2005-06-17 18:49:55 +0000
commitf9f09f1c5e69fcbd9a1c840c1b86854dfee3af6a (patch)
treebe08d99134fa5d6e5c61db0eea34a479ba7db470 /src/or/buffers.c
parent946892ab68bfeab4aa503d673adaa8374f778c55 (diff)
downloadtor-f9f09f1c5e69fcbd9a1c840c1b86854dfee3af6a.tar.gz
tor-f9f09f1c5e69fcbd9a1c840c1b86854dfee3af6a.zip
Start implementing framework for revised control spec.
svn:r4447
Diffstat (limited to 'src/or/buffers.c')
-rw-r--r--src/or/buffers.c78
1 files changed, 72 insertions, 6 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index b0c3d912ab..4c813eb2ef 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -108,10 +108,22 @@ _buf_end(buf_t *buf)
/** If the pointer <b>cp</b> has passed beyond the end of the buffer, wrap it
* around. */
static INLINE char *
-_wrap_ptr(buf_t *buf, char *cp) {
+_wrap_ptr(buf_t *buf, char *cp)
+{
return (cp >= buf->mem + buf->len) ? (cp - buf->len) : cp;
}
+/** Return the offset of <b>cp</b> within the buffer. */
+static INLINE int
+_buf_offset(buf_t *buf, char *cp)
+{
+ if (cp >= buf->cur)
+ return cp - buf->cur;
+ else
+ /* return (cp - buf->mem) + buf->mem+buf->len - buf->cur */
+ return cp + buf->len - buf->cur;
+}
+
/** If the range of *<b>len</b> bytes starting at <b>at</b> wraps around the
* end of the buffer, then set *<b>len</b> to the number of bytes starting
* at <b>at</b>, and set *<b>more_len</b> to the number of bytes starting
@@ -1099,7 +1111,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req)
#define CONTROL_CMD_FRAGMENTHEADER 0x0010
#define CONTROL_CMD_FRAGMENT 0x0011
-/** If there is a complete control message waiting on buf, then store
+/** If there is a complete version 0control message waiting on buf, then store
* its contents into *<b>type_out</b>, store its body's length into
* *<b>len_out</b>, allocate and store a string for its body into
* *<b>body_out</b>, and return 1. (body_out will always be NUL-terminated,
@@ -1107,11 +1119,11 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req)
*
* If there is not a complete control message waiting, return 0.
*
- * Return -1 on error.
+ * Return -1 on error; return -2 on "seems to be control protocol v1."
*/
int
-fetch_from_buf_control(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
- char **body_out)
+fetch_from_buf_control0(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
+ char **body_out, int check_for_v1)
{
uint32_t msglen;
uint16_t type;
@@ -1128,10 +1140,13 @@ fetch_from_buf_control(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
peek_from_buf(tmp, 4, buf);
msglen = ntohs(get_uint16(tmp));
+ type = ntohs(get_uint16(tmp+2));
+ if (type > 255 && check_for_v1)
+ return -2;
+
if (buf->datalen < 4 + (unsigned)msglen)
return 0;
- type = ntohs(get_uint16(tmp+2));
*len_out = msglen;
*type_out = type;
buf_remove_from_front(buf, 4);
@@ -1145,6 +1160,57 @@ fetch_from_buf_control(buf_t *buf, uint32_t *len_out, uint16_t *type_out,
return 1;
}
+/** DOCDOC */
+static char *
+find_char_on_buf(buf_t *buf, char *start, size_t len, char c)
+{
+ size_t len_rest;
+ char *cp;
+ _split_range(buf, start, &len, &len_rest);
+ cp = memchr(buf->cur, c, len);
+ if (cp || !len_rest)
+ return cp;
+ return memchr(buf->mem, c, len_rest);
+}
+
+static char *
+find_crlf_on_buf(buf_t *buf, char *cp)
+{
+ char *next;
+ while (1) {
+ size_t remaining = buf->datalen - _buf_offset(buf,cp);
+ cp = find_char_on_buf(buf, cp, remaining, '\r');
+ if (!cp)
+ return NULL;
+ next = _wrap_ptr(buf, cp+1);
+ if (next == _buf_end(buf))
+ return NULL;
+ if (*next == '\n')
+ return cp;
+ cp = next;
+ }
+}
+
+/* DOCDOC : 0 means 'need to read more'. means done, -1 means "grow buffer." */
+int
+fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
+{
+ char *eol;
+ size_t sz;
+ /* Look for a CRLF. */
+ if (!(eol = find_crlf_on_buf(buf, buf->cur)))
+ return 0;
+ sz = _buf_offset(buf, eol);
+ if (sz+2 > *data_len) {
+ *data_len = sz+2;
+ return -1;
+ }
+ fetch_from_buf(data_out, sz+2, buf);
+ *data_len = sz+2;
+ return 1;
+}
+
+
/** Log an error and exit if <b>buf</b> is corrupted.
*/
void assert_buf_ok(buf_t *buf)