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