2013-07-09 4 views
1

Рисунок на https://github.com/ppelleti/https-example. Я попытался определить следующий код для обработки (серверной) https и http-запросов. Есть ли более простой способ обработки https и http-запросов в одном гнезде для прослушивания? Заранее спасибоОбработка запросов HTTP и HTTPS с помощью libevent в одном и том же сокете

static int serve_some_http (void) 
{ struct event_base *base; 
    struct evhttp *https, *http; 
    struct evhttp_bound_socket *https_handle, *http_handle; 

    unsigned short port = COMMON_HTTPS_PORT; 
#ifdef _WIN32 
    WSADATA WSAData; 
    WSAStartup (0x101, &WSAData); 
#endif 

    base = event_base_new(); 
    if (! base) 
    { fprintf (stderr, "Couldn't create an event_base: exiting\n"); 
     return 1; 
    } 

    /* Create a new evhttp object to handle requests. */ 
    https = evhttp_new (base); 
    http = evhttp_new (base); 
    if ((! https)||(! http)) 
    { fprintf (stderr, "couldn't create evhttp. Exiting.\n"); 
     return 1; 
    } 

    SSL_CTX *ctx = SSL_CTX_new (SSLv23_server_method()); 
    SSL_CTX_set_options (ctx, 
        SSL_OP_SINGLE_DH_USE | 
        SSL_OP_SINGLE_ECDH_USE | 
        SSL_OP_NO_SSLv2); 

    /* Cheesily pick an elliptic curve to use with elliptic curve ciphersuites. 
    * We just hardcode a single curve which is reasonably decent. 
    * See http://www.mail-archive.com/[email protected]/msg30957.html */ 
    EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1); 
    if (! ecdh) 
    die_most_horribly_from_openssl_error ("EC_KEY_new_by_curve_name"); 
    if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) 
    die_most_horribly_from_openssl_error ("SSL_CTX_set_tmp_ecdh"); 

    /* Find and set up our server certificate. */ 
    const char *certificate_chain = SERVER_CERT_PEM; 
    const char *private_key = SERVER_PRIV_PEM; 
    server_setup_certs (ctx, certificate_chain, private_key); 

    /* This is the magic that lets evhttp use SSL. */ 
    evhttp_set_bevcb (https, bevcb, ctx); 

    /* This is the callback that gets called when a request comes in. */ 
    evhttp_set_gencb (https, https_document_cb, NULL); 
    evhttp_set_gencb (http, http_document_cb, NULL); 

    /* Now we tell the evhttp what port to listen on */ 
    https_handle = evhttp_bind_socket_with_handle (https, "127.0.0.1", port); 
    http_handle = evhttp_bind_socket_with_handle (http, "127.0.0.1", port+1); 
    if ((! https_handle)||(! http_handle)) 
    { fprintf (stderr, "couldn't bind to port %d. Exiting.\n", (int) port); 
     return 1; 
    } 

    { /* Extract and display the address we're listening on. */ 
    sock_hop ss, sss; 
    evutil_socket_t fds,fd; 
    ev_socklen_t socklen = sizeof (ss); 
    ev_socklen_t s_socklen = sizeof (ss); 
    char addrbuf[128]; 
    char s_addrbuf[128]; 
    void *inaddr, *s_inaddr; 
    const char *addr, *s_addr; 
    int got_port = -1; 
    int s_got_port = -1; 


    fds = evhttp_bound_socket_get_fd (https_handle); 
    memset (&sss, 0, sizeof(sss)); 
    if (getsockname (fds, &sss.sa, &s_socklen)) 
     { perror ("getsockname() failed"); 
    return 1; 
     } 
    if (sss.ss.ss_family == AF_INET) 
     { s_got_port = ntohs (sss.in.sin_port); 
    s_inaddr = &sss.in.sin_addr; 
     } 
    else if (sss.ss.ss_family == AF_INET6) 
     { s_got_port = ntohs (sss.i6.sin6_port); 
    s_inaddr = &sss.i6.sin6_addr; 
     } 
    else 
     { fprintf (stderr, "Weird address family %d\n", sss.ss.ss_family); 
    return 1; 
     } 
    s_addr = evutil_inet_ntop (sss.ss.ss_family, s_inaddr, s_addrbuf, 
         sizeof (s_addrbuf)); 
    if (s_addr) 
     printf ("Listening HTTPS on %s:%d\n", s_addr, s_got_port); 
    else 
     { fprintf (stderr, "evutil_inet_ntop failed\n"); 
    return 1; 
     } 





    fd = evhttp_bound_socket_get_fd (http_handle); 
    memset (&ss, 0, sizeof(ss)); 
    if (getsockname (fd, &ss.sa, &socklen)) 
     { perror ("getsockname() failed"); 
    return 1; 
     } 
    if (ss.ss.ss_family == AF_INET) 
     { got_port = ntohs (ss.in.sin_port); 
    inaddr = &ss.in.sin_addr; 
     } 
    else if (ss.ss.ss_family == AF_INET6) 
     { got_port = ntohs (ss.i6.sin6_port); 
    inaddr = &ss.i6.sin6_addr; 
     } 
    else 
     { fprintf (stderr, "Weird address family %d\n", ss.ss.ss_family); 
    return 1; 
     } 
    addr = evutil_inet_ntop (ss.ss.ss_family, inaddr, addrbuf, 
         sizeof (addrbuf)); 
    if (addr) 
     printf ("Listening HTTP on %s:%d\n", addr, got_port); 
    else 
     { fprintf (stderr, "evutil_inet_ntop failed\n"); 
    return 1; 
     } 

    } 

    event_base_dispatch (base); 

    /* not reached; runs forever */ 

    return 0; 
} 

ответ

1

Нет, вы не можете служить HTTPS и HTTP из одного порта и Libevent требует два экземпляра struct http для обработки обоих.

Смежные вопросы