diff options
author | Nick Mathewson <nickm@torproject.org> | 2009-08-26 11:55:36 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2010-09-27 12:31:14 -0400 |
commit | 9796b9bfa6a757780d6185547e4baf739c53cdac (patch) | |
tree | 8e4b805c838f42d8d99a3c662d75f6849b296f4f /src/or/buffers.c | |
parent | c74a4ab515990701800755b88c097f8239cc3811 (diff) | |
download | tor-9796b9bfa6a757780d6185547e4baf739c53cdac.tar tor-9796b9bfa6a757780d6185547e4baf739c53cdac.tar.gz |
Implement SOCKS-client support for bufferevents
Diffstat (limited to 'src/or/buffers.c')
-rw-r--r-- | src/or/buffers.c | 73 |
1 files changed, 58 insertions, 15 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index ffdbcd3b4..b9e1c5347 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -56,6 +56,9 @@ static int parse_socks(const char *data, size_t datalen, socks_request_t *req, int log_sockstype, int safe_socks, ssize_t *drain_out, size_t *want_length_out); +static int parse_socks_client(const uint8_t *data, size_t datalen, + int state, char **reason, + ssize_t *drain_out); /* Chunk manipulation functions */ @@ -1513,7 +1516,7 @@ fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req, want_length = evbuffer_get_contiguous_space(buf); n_drain = 0; i = evbuffer_peek(buf, want_length, NULL, &v, 1); - tor_assert(i == i); + tor_assert(i == 1); data = v.iov_base; datalen = v.iov_len; @@ -1900,21 +1903,61 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) { - unsigned char *data; - size_t addrlen; - + ssize_t drain = 0; + int r; if (buf->datalen < 2) return 0; buf_pullup(buf, 128, 0); tor_assert(buf->head && buf->head->datalen >= 2); - data = (unsigned char *) buf->head->data; + r = parse_socks_client((uint8_t*)buf->head->data, buf->head->datalen, + state, reason, &drain); + if (drain > 0) + buf_remove_from_front(buf, drain); + else if (drain < 0) + buf_clear(buf); + + return r; +} + +#ifdef USE_BUFFEREVENTS +/** As fetch_from_buf_socks_client, buf works on an evbuffer */ +int +fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state, + char **reason) +{ + ssize_t drain = 0; + uint8_t *data; + size_t datalen = evbuffer_get_contiguous_space(buf); + int r; + + data = evbuffer_pullup(buf, 128); + r = parse_socks_client(data, datalen, state, reason, &drain); + if (drain > 0) + evbuffer_drain(buf, drain); + else + evbuffer_drain(buf, evbuffer_get_length(buf)); + + return r; +} +#endif + +/** Implementation logic for fetch_from_*_socks_client. */ +static int +parse_socks_client(const uint8_t *data, size_t datalen, + int state, char **reason, + ssize_t *drain_out) +{ + unsigned int addrlen; + *drain_out = 0; + if (datalen < 2) + return 0; switch (state) { case PROXY_SOCKS4_WANT_CONNECT_OK: /* Wait for the complete response */ - if (buf->head->datalen < 8) + if (datalen < 8) return 0; if (data[1] != 0x5a) { @@ -1923,7 +1966,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) } /* Success */ - buf_remove_from_front(buf, 8); + *drain_out = 8; return 1; case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE: @@ -1935,7 +1978,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) } log_info(LD_NET, "SOCKS 5 client: continuing without authentication"); - buf_clear(buf); + *drain_out = -1; return 1; case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929: @@ -1945,11 +1988,11 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) case 0x00: log_info(LD_NET, "SOCKS 5 client: we have auth details but server " "doesn't require authentication."); - buf_clear(buf); + *drain_out = -1; return 1; case 0x02: log_info(LD_NET, "SOCKS 5 client: need authentication."); - buf_clear(buf); + *drain_out = -1; return 2; /* fall through */ } @@ -1966,7 +2009,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) } log_info(LD_NET, "SOCKS 5 client: authentication successful."); - buf_clear(buf); + *drain_out = -1; return 1; case PROXY_SOCKS5_WANT_CONNECT_OK: @@ -1975,7 +2018,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) * the data used */ /* wait for address type field to arrive */ - if (buf->datalen < 4) + if (datalen < 4) return 0; switch (data[3]) { @@ -1986,7 +2029,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) addrlen = 16; break; case 0x03: /* fqdn (can this happen here?) */ - if (buf->datalen < 5) + if (datalen < 5) return 0; addrlen = 1 + data[4]; break; @@ -1996,7 +2039,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) } /* wait for address and port */ - if (buf->datalen < 6 + addrlen) + if (datalen < 6 + addrlen) return 0; if (data[1] != 0x00) { @@ -2004,7 +2047,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason) return -1; } - buf_remove_from_front(buf, 6 + addrlen); + *drain_out = 6 + addrlen; return 1; } |