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