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