1*657871a7Schristos /* $NetBSD: http-connect.c,v 1.1.1.2 2021/04/07 02:43:15 christos Exp $ */
2805a1ce9Schristos #include "event2/event-config.h"
3805a1ce9Schristos #include <sys/cdefs.h>
4*657871a7Schristos __RCSID("$NetBSD: http-connect.c,v 1.1.1.2 2021/04/07 02:43:15 christos Exp $");
5805a1ce9Schristos
6805a1ce9Schristos #include <event2/event.h>
7805a1ce9Schristos #include <event2/http.h>
8805a1ce9Schristos #include <event2/http_struct.h>
9805a1ce9Schristos #include <event2/buffer.h>
10805a1ce9Schristos #include <stdlib.h>
11805a1ce9Schristos #include <stdio.h>
12805a1ce9Schristos #include <limits.h>
13805a1ce9Schristos
14805a1ce9Schristos #define VERIFY(cond) do { \
15805a1ce9Schristos if (!(cond)) { \
16805a1ce9Schristos fprintf(stderr, "[error] %s\n", #cond); \
17*657871a7Schristos exit(EXIT_FAILURE); \
18805a1ce9Schristos } \
19805a1ce9Schristos } while (0); \
20805a1ce9Schristos
21805a1ce9Schristos #define URL_MAX 4096
22805a1ce9Schristos
23805a1ce9Schristos struct connect_base
24805a1ce9Schristos {
25805a1ce9Schristos struct evhttp_connection *evcon;
26805a1ce9Schristos struct evhttp_uri *location;
27805a1ce9Schristos };
28805a1ce9Schristos
uri_parse(const char * str)29*657871a7Schristos static struct evhttp_uri* uri_parse(const char *str)
30*657871a7Schristos {
31*657871a7Schristos struct evhttp_uri *uri;
32*657871a7Schristos VERIFY(uri = evhttp_uri_parse(str));
33*657871a7Schristos VERIFY(evhttp_uri_get_host(uri));
34*657871a7Schristos VERIFY(evhttp_uri_get_port(uri) > 0);
35*657871a7Schristos return uri;
36*657871a7Schristos }
uri_path(struct evhttp_uri * uri,char buffer[URL_MAX])37*657871a7Schristos static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX])
38*657871a7Schristos {
39*657871a7Schristos struct evhttp_uri *path;
40*657871a7Schristos
41*657871a7Schristos VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
42*657871a7Schristos
43*657871a7Schristos path = evhttp_uri_parse(buffer);
44*657871a7Schristos evhttp_uri_set_scheme(path, NULL);
45*657871a7Schristos evhttp_uri_set_userinfo(path, 0);
46*657871a7Schristos evhttp_uri_set_host(path, NULL);
47*657871a7Schristos evhttp_uri_set_port(path, -1);
48*657871a7Schristos VERIFY(evhttp_uri_join(path, buffer, URL_MAX));
49*657871a7Schristos return buffer;
50*657871a7Schristos }
uri_hostport(struct evhttp_uri * uri,char buffer[URL_MAX])51*657871a7Schristos static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX])
52*657871a7Schristos {
53*657871a7Schristos VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
54*657871a7Schristos VERIFY(evhttp_uri_get_host(uri));
55*657871a7Schristos VERIFY(evhttp_uri_get_port(uri) > 0);
56*657871a7Schristos evutil_snprintf(buffer, URL_MAX, "%s:%d",
57*657871a7Schristos evhttp_uri_get_host(uri), evhttp_uri_get_port(uri));
58*657871a7Schristos return buffer;
59*657871a7Schristos }
60*657871a7Schristos
get_cb(struct evhttp_request * req,void * arg)61805a1ce9Schristos static void get_cb(struct evhttp_request *req, void *arg)
62805a1ce9Schristos {
63805a1ce9Schristos ev_ssize_t len;
64805a1ce9Schristos struct evbuffer *evbuf;
65805a1ce9Schristos
66805a1ce9Schristos VERIFY(req);
67805a1ce9Schristos
68805a1ce9Schristos evbuf = evhttp_request_get_input_buffer(req);
69805a1ce9Schristos len = evbuffer_get_length(evbuf);
70805a1ce9Schristos fwrite(evbuffer_pullup(evbuf, len), len, 1, stdout);
71805a1ce9Schristos evbuffer_drain(evbuf, len);
72805a1ce9Schristos }
73805a1ce9Schristos
connect_cb(struct evhttp_request * proxy_req,void * arg)74805a1ce9Schristos static void connect_cb(struct evhttp_request *proxy_req, void *arg)
75805a1ce9Schristos {
76805a1ce9Schristos struct connect_base *base = arg;
77805a1ce9Schristos struct evhttp_connection *evcon = base->evcon;
78805a1ce9Schristos struct evhttp_uri *location = base->location;
79*657871a7Schristos struct evhttp_request *req;
80*657871a7Schristos char buffer[URL_MAX];
81805a1ce9Schristos
82805a1ce9Schristos VERIFY(proxy_req);
83*657871a7Schristos VERIFY(evcon);
84*657871a7Schristos
85*657871a7Schristos req = evhttp_request_new(get_cb, NULL);
86805a1ce9Schristos evhttp_add_header(req->output_headers, "Connection", "close");
87*657871a7Schristos evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location));
88805a1ce9Schristos VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
89*657871a7Schristos uri_path(location, buffer)));
90805a1ce9Schristos }
91805a1ce9Schristos
main(int argc,const char ** argv)92805a1ce9Schristos int main(int argc, const char **argv)
93805a1ce9Schristos {
94*657871a7Schristos char hostport[URL_MAX];
95805a1ce9Schristos
96805a1ce9Schristos struct evhttp_uri *location;
97805a1ce9Schristos struct evhttp_uri *proxy;
98805a1ce9Schristos
99805a1ce9Schristos struct event_base *base;
100805a1ce9Schristos struct evhttp_connection *evcon;
101805a1ce9Schristos struct evhttp_request *req;
102805a1ce9Schristos
103805a1ce9Schristos struct connect_base connect_base;
104805a1ce9Schristos
105805a1ce9Schristos if (argc != 3) {
106805a1ce9Schristos printf("Usage: %s proxy url\n", argv[0]);
107805a1ce9Schristos return 1;
108805a1ce9Schristos }
109805a1ce9Schristos
110*657871a7Schristos proxy = uri_parse(argv[1]);
111*657871a7Schristos location = uri_parse(argv[2]);
112805a1ce9Schristos
113805a1ce9Schristos VERIFY(base = event_base_new());
114805a1ce9Schristos VERIFY(evcon = evhttp_connection_base_new(base, NULL,
115805a1ce9Schristos evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy)));
116805a1ce9Schristos connect_base.evcon = evcon;
117805a1ce9Schristos connect_base.location = location;
118805a1ce9Schristos VERIFY(req = evhttp_request_new(connect_cb, &connect_base));
119805a1ce9Schristos
120*657871a7Schristos uri_hostport(location, hostport);
121805a1ce9Schristos evhttp_add_header(req->output_headers, "Connection", "keep-alive");
122805a1ce9Schristos evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive");
123*657871a7Schristos evhttp_add_header(req->output_headers, "Host", hostport);
124*657871a7Schristos evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport);
125805a1ce9Schristos
126805a1ce9Schristos event_base_dispatch(base);
127*657871a7Schristos
128805a1ce9Schristos evhttp_connection_free(evcon);
129805a1ce9Schristos event_base_free(base);
130805a1ce9Schristos evhttp_uri_free(proxy);
131805a1ce9Schristos evhttp_uri_free(location);
132*657871a7Schristos
133805a1ce9Schristos return 0;
134805a1ce9Schristos }
135