diff options
Diffstat (limited to 'libevent/sample/http-connect.c')
-rw-r--r-- | libevent/sample/http-connect.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/libevent/sample/http-connect.c b/libevent/sample/http-connect.c new file mode 100644 index 0000000..53f816d --- /dev/null +++ b/libevent/sample/http-connect.c @@ -0,0 +1,131 @@ +#include "event2/event-config.h" + +#include <event2/event.h> +#include <event2/http.h> +#include <event2/http_struct.h> +#include <event2/buffer.h> +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> + +#define VERIFY(cond) do { \ + if (!(cond)) { \ + fprintf(stderr, "[error] %s\n", #cond); \ + exit(EXIT_FAILURE); \ + } \ +} while (0); \ + +#define URL_MAX 4096 + +struct connect_base +{ + struct evhttp_connection *evcon; + struct evhttp_uri *location; +}; + +static struct evhttp_uri* uri_parse(const char *str) +{ + struct evhttp_uri *uri; + VERIFY(uri = evhttp_uri_parse(str)); + VERIFY(evhttp_uri_get_host(uri)); + VERIFY(evhttp_uri_get_port(uri) > 0); + return uri; +} +static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX]) +{ + struct evhttp_uri *path; + + VERIFY(evhttp_uri_join(uri, buffer, URL_MAX)); + + path = evhttp_uri_parse(buffer); + evhttp_uri_set_scheme(path, NULL); + evhttp_uri_set_userinfo(path, 0); + evhttp_uri_set_host(path, NULL); + evhttp_uri_set_port(path, -1); + VERIFY(evhttp_uri_join(path, buffer, URL_MAX)); + return buffer; +} +static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX]) +{ + VERIFY(evhttp_uri_join(uri, buffer, URL_MAX)); + VERIFY(evhttp_uri_get_host(uri)); + VERIFY(evhttp_uri_get_port(uri) > 0); + evutil_snprintf(buffer, URL_MAX, "%s:%d", + evhttp_uri_get_host(uri), evhttp_uri_get_port(uri)); + return buffer; +} + +static void get_cb(struct evhttp_request *req, void *arg) +{ + ev_ssize_t len; + struct evbuffer *evbuf; + + VERIFY(req); + + evbuf = evhttp_request_get_input_buffer(req); + len = evbuffer_get_length(evbuf); + fwrite(evbuffer_pullup(evbuf, len), len, 1, stdout); + evbuffer_drain(evbuf, len); +} + +static void connect_cb(struct evhttp_request *proxy_req, void *arg) +{ + struct connect_base *base = arg; + struct evhttp_connection *evcon = base->evcon; + struct evhttp_uri *location = base->location; + struct evhttp_request *req; + char buffer[URL_MAX]; + + VERIFY(proxy_req); + VERIFY(evcon); + + req = evhttp_request_new(get_cb, NULL); + evhttp_add_header(req->output_headers, "Connection", "close"); + evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location)); + VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + uri_path(location, buffer))); +} + +int main(int argc, const char **argv) +{ + char hostport[URL_MAX]; + + struct evhttp_uri *location; + struct evhttp_uri *proxy; + + struct event_base *base; + struct evhttp_connection *evcon; + struct evhttp_request *req; + + struct connect_base connect_base; + + if (argc != 3) { + printf("Usage: %s proxy url\n", argv[0]); + return 1; + } + + proxy = uri_parse(argv[1]); + location = uri_parse(argv[2]); + + VERIFY(base = event_base_new()); + VERIFY(evcon = evhttp_connection_base_new(base, NULL, + evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy))); + connect_base.evcon = evcon; + connect_base.location = location; + VERIFY(req = evhttp_request_new(connect_cb, &connect_base)); + + uri_hostport(location, hostport); + evhttp_add_header(req->output_headers, "Connection", "keep-alive"); + evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive"); + evhttp_add_header(req->output_headers, "Host", hostport); + evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport); + + event_base_dispatch(base); + + evhttp_connection_free(evcon); + event_base_free(base); + evhttp_uri_free(proxy); + evhttp_uri_free(location); + + return 0; +} |