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