tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

http-connect.c (3479B)


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