1 #include "event2/event-config.h" 2 3 #include <event2/event.h> 4 #include <event2/http.h> 5 #include <event2/http_struct.h> 6 #include <event2/buffer.h> 7 #include <stdlib.h> 8 #include <stdio.h> 9 #include <limits.h> 10 11 #define VERIFY(cond) do { \ 12 if (!(cond)) { \ 13 fprintf(stderr, "[error] %s\n", #cond); \ 14 } \ 15 } while (0); \ 16 17 #define URL_MAX 4096 18 19 struct connect_base 20 { 21 struct evhttp_connection *evcon; 22 struct evhttp_uri *location; 23 }; 24 25 static void get_cb(struct evhttp_request *req, void *arg) 26 { 27 ev_ssize_t len; 28 struct evbuffer *evbuf; 29 30 VERIFY(req); 31 32 evbuf = evhttp_request_get_input_buffer(req); 33 len = evbuffer_get_length(evbuf); 34 fwrite(evbuffer_pullup(evbuf, len), len, 1, stdout); 35 evbuffer_drain(evbuf, len); 36 } 37 38 static void connect_cb(struct evhttp_request *proxy_req, void *arg) 39 { 40 char buffer[URL_MAX]; 41 42 struct connect_base *base = arg; 43 struct evhttp_connection *evcon = base->evcon; 44 struct evhttp_uri *location = base->location; 45 46 VERIFY(proxy_req); 47 if (evcon) { 48 struct evhttp_request *req = evhttp_request_new(get_cb, NULL); 49 evhttp_add_header(req->output_headers, "Connection", "close"); 50 VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET, 51 evhttp_uri_join(location, buffer, URL_MAX))); 52 } 53 } 54 55 int main(int argc, const char **argv) 56 { 57 char buffer[URL_MAX]; 58 59 struct evhttp_uri *host_port; 60 struct evhttp_uri *location; 61 struct evhttp_uri *proxy; 62 63 struct event_base *base; 64 struct evhttp_connection *evcon; 65 struct evhttp_request *req; 66 67 struct connect_base connect_base; 68 69 if (argc != 3) { 70 printf("Usage: %s proxy url\n", argv[0]); 71 return 1; 72 } 73 74 { 75 proxy = evhttp_uri_parse(argv[1]); 76 VERIFY(evhttp_uri_get_host(proxy)); 77 VERIFY(evhttp_uri_get_port(proxy) > 0); 78 } 79 { 80 host_port = evhttp_uri_parse(argv[2]); 81 evhttp_uri_set_scheme(host_port, NULL); 82 evhttp_uri_set_userinfo(host_port, NULL); 83 evhttp_uri_set_path(host_port, NULL); 84 evhttp_uri_set_query(host_port, NULL); 85 evhttp_uri_set_fragment(host_port, NULL); 86 VERIFY(evhttp_uri_get_host(host_port)); 87 VERIFY(evhttp_uri_get_port(host_port) > 0); 88 } 89 { 90 location = evhttp_uri_parse(argv[2]); 91 evhttp_uri_set_scheme(location, NULL); 92 evhttp_uri_set_userinfo(location, 0); 93 evhttp_uri_set_host(location, NULL); 94 evhttp_uri_set_port(location, -1); 95 } 96 97 VERIFY(base = event_base_new()); 98 VERIFY(evcon = evhttp_connection_base_new(base, NULL, 99 evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy))); 100 connect_base.evcon = evcon; 101 connect_base.location = location; 102 VERIFY(req = evhttp_request_new(connect_cb, &connect_base)); 103 104 evhttp_add_header(req->output_headers, "Connection", "keep-alive"); 105 evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive"); 106 evutil_snprintf(buffer, URL_MAX, "%s:%d", 107 evhttp_uri_get_host(host_port), evhttp_uri_get_port(host_port)); 108 evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, buffer); 109 110 event_base_dispatch(base); 111 evhttp_connection_free(evcon); 112 event_base_free(base); 113 evhttp_uri_free(proxy); 114 evhttp_uri_free(host_port); 115 evhttp_uri_free(location); 116 return 0; 117 } 118