[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[Libevent-users] patch for https



In my project, a https server is needed. I added the https feature based on 2.0.10-stable release.

diff -ur libevent-2.0.10-stable-orig/http.c libevent-2.0.10-stable/http.c
--- libevent-2.0.10-stable-orig/http.c Â2010-12-15 14:02:25.000000000 -0500
+++ libevent-2.0.10-stable/http.c    2011-05-04 07:24:29.000000000 -0400
@@ -79,6 +79,7 @@
Â#ifdef _EVENT_HAVE_FCNTL_H
Â#include <fcntl.h>
Â#endif
+#include <openssl/ssl.h>

Â#undef timeout_pending
Â#undef timeout_initialized
@@ -93,6 +94,7 @@
Â#include "event2/http_compat.h"
Â#include "event2/util.h"
Â#include "event2/listener.h"
+#include "event2/bufferevent_ssl.h"
Â#include "log-internal.h"
Â#include "util-internal.h"
Â#include "http-internal.h"
@@ -1278,6 +1283,8 @@
        evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
    } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
        evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
+ Â Â Â } else if (what & BEV_EVENT_CONNECTED) {
+ Â Â Â Â Â Â Â return;
    } else {
        evhttp_connection_fail(evcon, EVCON_HTTP_BUFFER_ERROR);
    }
@@ -2018,6 +2025,65 @@
    return (NULL);
Â}

+struct evhttp_connection *
+evhttps_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
+ Â Âconst char *address, unsigned short port, void *ssl_ctx, evutil_socket_t fd)
+{
+ Â Â Â struct evhttp_connection *evcon = NULL;
+ Â Â Â SSL *ssl;
+
+ Â Â Â event_debug(("Attempting connection to %s:%d\n", address, port));
+
+ Â Â Â if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
+ Â Â Â Â Â Â Â event_warn("%s: calloc failed", __func__);
+ Â Â Â Â Â Â Â goto error;
+ Â Â Â }
+
+ Â Â Â evcon->fd = fd;
+ Â Â Â evcon->port = port;
+
+ Â Â Â evcon->max_headers_size = EV_SIZE_MAX;
+ Â Â Â evcon->max_body_size = EV_SIZE_MAX;
+
+ Â Â Â evcon->timeout = -1;
+ Â Â Â evcon->retry_cnt = evcon->retry_max = 0;
+
+ Â Â Â if ((evcon->address = mm_strdup(address)) == NULL) {
+ Â Â Â Â Â Â Â event_warn("%s: strdup failed", __func__);
+ Â Â Â Â Â Â Â goto error;
+ Â Â Â }
+
+ Â Â Â ssl = SSL_new(ssl_ctx);
+ Â Â Â evcon->bufev = bufferevent_openssl_socket_new(base, fd,
+ Â Â Â Â Â Â Â ssl, BUFFEREVENT_SSL_ACCEPTING,
+ Â Â Â Â Â Â Â BEV_OPT_CLOSE_ON_FREE|BEV_OPT_DEFER_CALLBACKS);
+ Â Â Â if (evcon->bufev == NULL) {
+ Â Â Â Â Â Â Â event_warn("%s: bufferevent_new failed", __func__);
+ Â Â Â Â Â Â Â goto error;
+ Â Â Â }
+
+ Â Â Â bufferevent_setcb(evcon->bufev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
+
+ Â Â Â evcon->state = EVCON_DISCONNECTED;
+ Â Â Â TAILQ_INIT(&evcon->requests);
+
+ Â Â Â if (base != NULL) {
+ Â Â Â Â Â Â Â evcon->base = base;
+ Â Â Â }
+
+ Â Â Â event_deferred_cb_init(&evcon->read_more_deferred_cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âevhttp_deferred_read_cb, evcon);
+
+ Â Â Â evcon->dns_base = dnsbase;
+
+ Â Â Â return (evcon);
+
+error:
+ Â Â Â if (evcon != NULL)
+ Â Â Â Â Â Â Â evhttp_connection_free(evcon);
+ Â Â Â return (NULL);
+}
+
Âvoid
Âevhttp_connection_set_base(struct evhttp_connection *evcon,
  Âstruct event_base *base)
@@ -2965,6 +3031,18 @@
    return (0);
Â}

+int
+evhttps_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port, void *ssl_ctx)
+{
+ Â Â Â struct evhttp_bound_socket *bound;
+
+ Â Â Â http->ssl_ctx = ssl_ctx;
+ Â Â Â bound = evhttp_bind_socket_with_handle(http, address, port);
+ Â Â Â if (bound == NULL)
+ Â Â Â Â Â Â Â return (-1);
+ Â Â Â return (0);
+}
+
Âstruct evhttp_bound_socket *
Âevhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
Â{
@@ -3160,6 +3238,9 @@
        mm_free(alias->alias);
        mm_free(alias);
    }
+
+ Â Â Â if (http->ssl_ctx != NULL)
+ Â Â Â Â Â Â Â SSL_CTX_free(http->ssl_ctx);

    mm_free(http);
Â}
@@ -3551,8 +3632,13 @@
            __func__, hostname, portname, fd));

    /* we need a connection object to put the http request on */
- Â Â Â evcon = evhttp_connection_base_new(
- Â Â Â Â Â Â Â http->base, NULL, hostname, atoi(portname));
+ Â Â Â if (http->ssl_ctx) {
+ Â Â Â Â Â Â Â evcon = evhttps_connection_base_new(
+ Â Â Â Â Â Â Â Â Â Â Â http->base, NULL, hostname, atoi(portname), http->ssl_ctx, fd);
+ Â Â Â } else {
+ Â Â Â Â Â Â Â evcon = evhttp_connection_base_new(
+ Â Â Â Â Â Â Â Â Â Â Â http->base, NULL, hostname, atoi(portname));
+ Â Â Â }
    mm_free(hostname);
    mm_free(portname);
    if (evcon == NULL)
@@ -3563,10 +3649,11 @@

    evcon->flags |= EVHTTP_CON_INCOMING;
    evcon->state = EVCON_READING_FIRSTLINE;
-
- Â Â Â evcon->fd = fd;
-
- Â Â Â bufferevent_setfd(evcon->bufev, fd);
+
+ Â Â Â if (NULL == http->ssl_ctx) {
+ Â Â Â Â Â Â Â evcon->fd = fd;
+ Â Â Â Â Â Â Â bufferevent_setfd(evcon->bufev, fd);
+ Â Â Â }

    return (evcon);
Â}
diff -ur libevent-2.0.10-stable-orig/http-internal.h libevent-2.0.10-stable/http-internal.h
--- libevent-2.0.10-stable-orig/http-internal.h 2010-11-29 19:55:48.000000000 -0500
+++ libevent-2.0.10-stable/http-internal.h   Â2011-05-04 07:25:56.000000000 -0400
@@ -21,6 +21,9 @@
Â#define HTTP_PREFIX Â Â Â Â Â Â"http://"
Â#define HTTP_DEFAULTPORT Â Â Â 80

+#define HTTPS_PREFIX Â Â Â Â Â Â"https://"
+#define HTTPS_DEFAULTPORT Â Â Â 443
+
Âenum message_read_status {
    ALL_DATA_READ = 1,
    MORE_DATA_EXPECTED = 0,
@@ -151,7 +154,7 @@

    /* NULL if this server is not a vhost */
    char *vhost_pattern;
-
+ Â Â Â void *ssl_ctx;
    int timeout;

    size_t default_max_headers_size;
diff -ur libevent-2.0.10-stable-orig/include/event2/http.h libevent-2.0.10-stable/include/event2/http.h
--- libevent-2.0.10-stable-orig/include/event2/http.h  2010-12-10 12:43:18.000000000 -0500
+++ libevent-2.0.10-stable/include/event2/http.h    Â2011-05-02 00:40:17.000000000 -0400
@@ -91,8 +91,8 @@
 * @return 0 on success, -1 on failure.
 * @see evhttp_accept_socket()
 */
-int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port);
-
+ int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port);
+ int evhttps_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port, void *ssl_ctx);
Â/**
 * Like evhttp_bind_socket(), but returns a handle for referencing the socket.
 *

If it's good, hope it can be added into future release.

Thanks,