xref: /netbsd-src/external/bsd/ntp/dist/sntp/libevent/sample/http-connect.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: http-connect.c,v 1.2 2024/08/18 20:47:23 christos Exp $	*/
2897be3a4Schristos 
3897be3a4Schristos #include "event2/event-config.h"
4897be3a4Schristos 
5897be3a4Schristos #include <event2/event.h>
6897be3a4Schristos #include <event2/http.h>
7897be3a4Schristos #include <event2/http_struct.h>
8897be3a4Schristos #include <event2/buffer.h>
9897be3a4Schristos #include <stdlib.h>
10897be3a4Schristos #include <stdio.h>
11897be3a4Schristos #include <limits.h>
12897be3a4Schristos 
13897be3a4Schristos #define VERIFY(cond) do {                       \
14897be3a4Schristos 	if (!(cond)) {                              \
15897be3a4Schristos 		fprintf(stderr, "[error] %s\n", #cond); \
16897be3a4Schristos 		exit(EXIT_FAILURE);                     \
17897be3a4Schristos 	}                                           \
18897be3a4Schristos } while (0);                                    \
19897be3a4Schristos 
20897be3a4Schristos #define URL_MAX 4096
21897be3a4Schristos 
22897be3a4Schristos struct connect_base
23897be3a4Schristos {
24897be3a4Schristos 	struct evhttp_connection *evcon;
25897be3a4Schristos 	struct evhttp_uri *location;
26897be3a4Schristos };
27897be3a4Schristos 
28897be3a4Schristos static struct evhttp_uri* uri_parse(const char *str)
29897be3a4Schristos {
30897be3a4Schristos 	struct evhttp_uri *uri;
31897be3a4Schristos 	VERIFY(uri = evhttp_uri_parse(str));
32897be3a4Schristos 	VERIFY(evhttp_uri_get_host(uri));
33897be3a4Schristos 	VERIFY(evhttp_uri_get_port(uri) > 0);
34897be3a4Schristos 	return uri;
35897be3a4Schristos }
36897be3a4Schristos static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX])
37897be3a4Schristos {
38897be3a4Schristos 	struct evhttp_uri *path;
39897be3a4Schristos 
40897be3a4Schristos 	VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
41897be3a4Schristos 
42897be3a4Schristos 	path = evhttp_uri_parse(buffer);
43897be3a4Schristos 	evhttp_uri_set_scheme(path, NULL);
44897be3a4Schristos 	evhttp_uri_set_userinfo(path, 0);
45897be3a4Schristos 	evhttp_uri_set_host(path, NULL);
46897be3a4Schristos 	evhttp_uri_set_port(path, -1);
47897be3a4Schristos 	VERIFY(evhttp_uri_join(path, buffer, URL_MAX));
48897be3a4Schristos 	return buffer;
49897be3a4Schristos }
50897be3a4Schristos static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX])
51897be3a4Schristos {
52897be3a4Schristos 	VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
53897be3a4Schristos 	VERIFY(evhttp_uri_get_host(uri));
54897be3a4Schristos 	VERIFY(evhttp_uri_get_port(uri) > 0);
55897be3a4Schristos 	evutil_snprintf(buffer, URL_MAX, "%s:%d",
56897be3a4Schristos 		evhttp_uri_get_host(uri), evhttp_uri_get_port(uri));
57897be3a4Schristos 	return buffer;
58897be3a4Schristos }
59897be3a4Schristos 
60897be3a4Schristos static void get_cb(struct evhttp_request *req, void *arg)
61897be3a4Schristos {
62897be3a4Schristos 	ev_ssize_t len;
63897be3a4Schristos 	struct evbuffer *evbuf;
64897be3a4Schristos 
65897be3a4Schristos 	VERIFY(req);
66897be3a4Schristos 
67897be3a4Schristos 	evbuf = evhttp_request_get_input_buffer(req);
68897be3a4Schristos 	len = evbuffer_get_length(evbuf);
69897be3a4Schristos 	fwrite(evbuffer_pullup(evbuf, len), len, 1, stdout);
70897be3a4Schristos 	evbuffer_drain(evbuf, len);
71897be3a4Schristos }
72897be3a4Schristos 
73897be3a4Schristos static void connect_cb(struct evhttp_request *proxy_req, void *arg)
74897be3a4Schristos {
75897be3a4Schristos 	struct connect_base *base = arg;
76897be3a4Schristos 	struct evhttp_connection *evcon = base->evcon;
77897be3a4Schristos 	struct evhttp_uri *location = base->location;
78897be3a4Schristos 	struct evhttp_request *req;
79897be3a4Schristos 	char buffer[URL_MAX];
80897be3a4Schristos 
81897be3a4Schristos 	VERIFY(proxy_req);
82897be3a4Schristos 	VERIFY(evcon);
83897be3a4Schristos 
84897be3a4Schristos 	req = evhttp_request_new(get_cb, NULL);
85897be3a4Schristos 	evhttp_add_header(req->output_headers, "Connection", "close");
86897be3a4Schristos 	evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location));
87897be3a4Schristos 	VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
88897be3a4Schristos 		uri_path(location, buffer)));
89897be3a4Schristos }
90897be3a4Schristos 
91897be3a4Schristos int main(int argc, const char **argv)
92897be3a4Schristos {
93897be3a4Schristos 	char hostport[URL_MAX];
94897be3a4Schristos 
95897be3a4Schristos 	struct evhttp_uri *location;
96897be3a4Schristos 	struct evhttp_uri *proxy;
97897be3a4Schristos 
98897be3a4Schristos 	struct event_base *base;
99897be3a4Schristos 	struct evhttp_connection *evcon;
100897be3a4Schristos 	struct evhttp_request *req;
101897be3a4Schristos 
102897be3a4Schristos 	struct connect_base connect_base;
103897be3a4Schristos 
104897be3a4Schristos 	if (argc != 3) {
105897be3a4Schristos 		printf("Usage: %s proxy url\n", argv[0]);
106897be3a4Schristos 		return 1;
107897be3a4Schristos 	}
108897be3a4Schristos 
109897be3a4Schristos 	proxy    = uri_parse(argv[1]);
110897be3a4Schristos 	location = uri_parse(argv[2]);
111897be3a4Schristos 
112897be3a4Schristos 	VERIFY(base = event_base_new());
113897be3a4Schristos 	VERIFY(evcon = evhttp_connection_base_new(base, NULL,
114897be3a4Schristos 		evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy)));
115897be3a4Schristos 	connect_base.evcon = evcon;
116897be3a4Schristos 	connect_base.location = location;
117897be3a4Schristos 	VERIFY(req = evhttp_request_new(connect_cb, &connect_base));
118897be3a4Schristos 
119897be3a4Schristos 	uri_hostport(location, hostport);
120897be3a4Schristos 	evhttp_add_header(req->output_headers, "Connection", "keep-alive");
121897be3a4Schristos 	evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive");
122897be3a4Schristos 	evhttp_add_header(req->output_headers, "Host", hostport);
123897be3a4Schristos 	evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport);
124897be3a4Schristos 
125897be3a4Schristos 	event_base_dispatch(base);
126897be3a4Schristos 
127897be3a4Schristos 	evhttp_connection_free(evcon);
128897be3a4Schristos 	event_base_free(base);
129897be3a4Schristos 	evhttp_uri_free(proxy);
130897be3a4Schristos 	evhttp_uri_free(location);
131897be3a4Schristos 
132897be3a4Schristos 	return 0;
133897be3a4Schristos }
134