From 1d34498ea31134bd7a8fcadcb95910b30a479e19 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Tue, 18 Aug 2015 12:18:31 +0300 Subject: [PATCH] sample: add HTTP CONNECT tunnelling example using libevent http layer --- .gitignore | 1 + CMakeLists.txt | 1 + sample/http-connect.c | 102 ++++++++++++++++++++++++++++++++++++++++++ sample/include.am | 6 +-- 4 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 sample/http-connect.c diff --git a/.gitignore b/.gitignore index 9c61aaa6..75e2f718 100644 --- a/.gitignore +++ b/.gitignore @@ -84,6 +84,7 @@ libevent_openssl.pc /sample/event-read-fifo /sample/hello-world /sample/http-server +/sample/http-connect /sample/le-proxy /sample/https-client /sample/signal-test diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e76b3e6..6fff4dc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -770,6 +770,7 @@ if (NOT EVENT__DISABLE_SAMPLES) hello-world signal-test http-server + http-connect time-test) if (NOT EVENT__DISABLE_OPENSSL AND OPENSSL_LIBRARIES) diff --git a/sample/http-connect.c b/sample/http-connect.c new file mode 100644 index 00000000..ca29260a --- /dev/null +++ b/sample/http-connect.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct connect_base +{ + struct evhttp_connection *evcon; + struct evhttp_uri *location; +}; + +void get_cb(struct evhttp_request *req, void *arg) +{ + assert(req); + evbuffer_write(req->input_buffer, STDOUT_FILENO); +} + +void connect_cb(struct evhttp_request *proxy_req, void *arg) +{ + char buffer[PATH_MAX]; + + struct connect_base *base = arg; + struct evhttp_connection *evcon = base->evcon; + struct evhttp_uri *location = base->location; + + assert(proxy_req); + if (evcon) { + struct evhttp_request *req = evhttp_request_new(get_cb, NULL); + evhttp_add_header(req->output_headers, "Connection", "close"); + assert(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET, + evhttp_uri_join(location, buffer, PATH_MAX))); + } +} + +int main(int argc, const char **argv) +{ + char buffer[PATH_MAX]; + + struct evhttp_uri *host_port; + struct evhttp_uri *location; + struct evhttp_uri *proxy; + + struct event_base *base; + struct evhttp_connection *evcon; + struct evhttp_request *req; + + if (argc != 3) { + printf("Usage: %s proxy url\n", argv[0]); + return 1; + } + + { + proxy = evhttp_uri_parse(argv[1]); + assert(evhttp_uri_get_host(proxy)); + assert(evhttp_uri_get_port(proxy) > 0); + } + { + host_port = evhttp_uri_parse(argv[2]); + evhttp_uri_set_scheme(host_port, NULL); + evhttp_uri_set_userinfo(host_port, NULL); + evhttp_uri_set_path(host_port, NULL); + evhttp_uri_set_query(host_port, NULL); + evhttp_uri_set_fragment(host_port, NULL); + assert(evhttp_uri_get_host(host_port)); + assert(evhttp_uri_get_port(host_port) > 0); + } + { + location = evhttp_uri_parse(argv[2]); + evhttp_uri_set_scheme(location, NULL); + evhttp_uri_set_userinfo(location, 0); + evhttp_uri_set_host(location, NULL); + evhttp_uri_set_port(location, -1); + } + + assert(base = event_base_new()); + assert(evcon = evhttp_connection_base_new(base, NULL, + evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy))); + struct connect_base connect_base = { + .evcon = evcon, + .location = location, + }; + assert(req = evhttp_request_new(connect_cb, &connect_base)); + + evhttp_add_header(req->output_headers, "Connection", "keep-alive"); + evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive"); + evutil_snprintf(buffer, PATH_MAX, "%s:%d", + evhttp_uri_get_host(host_port), evhttp_uri_get_port(host_port)); + evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, buffer); + + event_base_dispatch(base); + evhttp_connection_free(evcon); + event_base_free(base); + evhttp_uri_free(proxy); + evhttp_uri_free(host_port); + evhttp_uri_free(location); + return 0; +} diff --git a/sample/include.am b/sample/include.am index 75f87c70..d1a7242f 100644 --- a/sample/include.am +++ b/sample/include.am @@ -9,6 +9,7 @@ SAMPLES = \ sample/event-read-fifo \ sample/hello-world \ sample/http-server \ + sample/http-connect \ sample/signal-test \ sample/time-test @@ -48,6 +49,5 @@ sample_hello_world_SOURCES = sample/hello-world.c sample_hello_world_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la sample_http_server_SOURCES = sample/http-server.c sample_http_server_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la - - - +sample_http_connect_SOURCES = sample/http-connect.c +sample_http_connect_LDADD = $(LIBEVENT_GC_SECTIONS) libevent.la -- 2.50.1