Edit

kc3-lang/libevent/sample/http-connect.c

Branch :

  • Show log

    Commit

  • Author : Azat Khuzhin
    Date : 2020-01-12 15:31:50
    Hash : 9c91fe14
    Message : http-connect: do not check connection on GET cb

  • sample/http-connect.c
  • #include "event2/event-config.h"
    
    #include <event2/event.h>
    #include <event2/http.h>
    #include <event2/http_struct.h>
    #include <event2/buffer.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <limits.h>
    
    #define VERIFY(cond) do {                       \
    	if (!(cond)) {                              \
    		fprintf(stderr, "[error] %s\n", #cond); \
    		exit(EXIT_FAILURE);                     \
    	}                                           \
    } while (0);                                    \
    
    #define URL_MAX 4096
    
    struct connect_base
    {
    	struct evhttp_connection *evcon;
    	struct evhttp_uri *location;
    };
    
    static struct evhttp_uri* uri_parse(const char *str)
    {
    	struct evhttp_uri *uri;
    	VERIFY(uri = evhttp_uri_parse(str));
    	VERIFY(evhttp_uri_get_host(uri));
    	VERIFY(evhttp_uri_get_port(uri) > 0);
    	return uri;
    }
    static char* uri_path(struct evhttp_uri *uri, char buffer[URL_MAX])
    {
    	struct evhttp_uri *path;
    
    	VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
    
    	path = evhttp_uri_parse(buffer);
    	evhttp_uri_set_scheme(path, NULL);
    	evhttp_uri_set_userinfo(path, 0);
    	evhttp_uri_set_host(path, NULL);
    	evhttp_uri_set_port(path, -1);
    	VERIFY(evhttp_uri_join(path, buffer, URL_MAX));
    	return buffer;
    }
    static char* uri_hostport(struct evhttp_uri *uri, char buffer[URL_MAX])
    {
    	VERIFY(evhttp_uri_join(uri, buffer, URL_MAX));
    	VERIFY(evhttp_uri_get_host(uri));
    	VERIFY(evhttp_uri_get_port(uri) > 0);
    	evutil_snprintf(buffer, URL_MAX, "%s:%d",
    		evhttp_uri_get_host(uri), evhttp_uri_get_port(uri));
    	return buffer;
    }
    
    static void get_cb(struct evhttp_request *req, void *arg)
    {
    	ev_ssize_t len;
    	struct evbuffer *evbuf;
    
    	VERIFY(req);
    
    	evbuf = evhttp_request_get_input_buffer(req);
    	len = evbuffer_get_length(evbuf);
    	fwrite(evbuffer_pullup(evbuf, len), len, 1, stdout);
    	evbuffer_drain(evbuf, len);
    }
    
    static void connect_cb(struct evhttp_request *proxy_req, void *arg)
    {
    	struct connect_base *base = arg;
    	struct evhttp_connection *evcon = base->evcon;
    	struct evhttp_uri *location = base->location;
    	struct evhttp_request *req;
    	char buffer[URL_MAX];
    
    	VERIFY(proxy_req);
    	VERIFY(evcon);
    
    	req = evhttp_request_new(get_cb, NULL);
    	evhttp_add_header(req->output_headers, "Connection", "close");
    	evhttp_add_header(req->output_headers, "Host", evhttp_uri_get_host(location));
    	VERIFY(!evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
    		uri_path(location, buffer)));
    }
    
    int main(int argc, const char **argv)
    {
    	char hostport[URL_MAX];
    
    	struct evhttp_uri *location;
    	struct evhttp_uri *proxy;
    
    	struct event_base *base;
    	struct evhttp_connection *evcon;
    	struct evhttp_request *req;
    
    	struct connect_base connect_base;
    
    	if (argc != 3) {
    		printf("Usage: %s proxy url\n", argv[0]);
    		return 1;
    	}
    
    	proxy    = uri_parse(argv[1]);
    	location = uri_parse(argv[2]);
    
    	VERIFY(base = event_base_new());
    	VERIFY(evcon = evhttp_connection_base_new(base, NULL,
    		evhttp_uri_get_host(proxy), evhttp_uri_get_port(proxy)));
    	connect_base.evcon = evcon;
    	connect_base.location = location;
    	VERIFY(req = evhttp_request_new(connect_cb, &connect_base));
    
    	uri_hostport(location, hostport);
    	evhttp_add_header(req->output_headers, "Connection", "keep-alive");
    	evhttp_add_header(req->output_headers, "Proxy-Connection", "keep-alive");
    	evhttp_add_header(req->output_headers, "Host", hostport);
    	evhttp_make_request(evcon, req, EVHTTP_REQ_CONNECT, hostport);
    
    	event_base_dispatch(base);
    
    	evhttp_connection_free(evcon);
    	event_base_free(base);
    	evhttp_uri_free(proxy);
    	evhttp_uri_free(location);
    
    	return 0;
    }