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