c - 在同一套接字中使用 libevent 处理 HTTP 和 HTTPS 请求

标签 c http https libevent

https://github.com/ppelleti/https-example 上绘图,我尝试定义以下代码来处理(服务器端)https 和 http 请求。有没有更简单的方法在单个监听套接字中处理 https 和 http 请求?提前致谢

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/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b4dbc4d1dac7c7d899d0d1c2f4dbc4d1dac7c7d89adbc6d3" rel="noreferrer noopener nofollow">[email protected]</a>/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;
}

最佳答案

不,您不能从同一个端口提供 HTTPS 和 HTTP,并且 libevent 需要两个 struct http 实例来处理这两者。

关于c - 在同一套接字中使用 libevent 处理 HTTP 和 HTTPS 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17558804/

相关文章:

javascript - 如何在 chrome 上更改不安全(http)网站的站点设置?

.net - IIS 503 "Service Unavailable"通过 HTTPS,HTTP 工作正常

c - C中的计数器数组

c - JPEG类别编码按位运算

image - 通过 http 加载的图像的大小(宽度、高度)

c# - 带有客户端证书的 Xamarin Forms https 抛出 WebException

https - NSIS inetc - HTTPS 给出 SendRequest 错误

javascript - 随机混合内容问题

c - C 中两个长整型相加

c - 如何使用 MPI_Gather 函数从变量中获取数据