# HTTPS 服务器

[English]

## 概述

HTTPS 服务器组件建立在 HTTP 服务器 组件的基础上。该服务器借助常规 HTTP 服务器中的钩子注册函数，注册 SSL 会话回调处理函数。

HTTP 服务器 组件的所有文档同样适用于用户按照本文档搭建的服务器。

## API 说明

下列 HTTP 服务器 的 API 已不适用于 HTTPS 服务器。这些 API 仅限内部使用，用于处理安全会话和维护内部状态。

- "send"、"receive" 和 "pending" 回调注册函数——处理安全套接字

  - `httpd_sess_set_send_override()`

  - `httpd_sess_set_recv_override()`

  - `httpd_sess_set_pending_override()`

- "transport context"——传输层上下文

  - `httpd_sess_get_transport_ctx()`：返回会话使用的 SSL

  - `httpd_sess_set_transport_ctx()`

  - `httpd_get_global_transport_ctx()`：返回共享的 SSL 上下文

  - `httpd_config::global_transport_ctx`

  - `httpd_config::global_transport_ctx_free_fn`

  - `httpd_config::open_fn`：用于设置安全套接字

其他 API 均可使用，没有其他限制。

## 如何使用

请参考示例 protocols/https_server 来学习如何搭建安全的服务器。

总体而言，只需生成证书，将其嵌入到固件中，并且在初始化结构体中配置好正确的证书地址和长度后，将其传入服务器启动函数。

通过改变初始化配置结构体中的标志 `httpd_ssl_config::transport_mode`，可以选择是否需要 SSL 连接来启动服务器。在测试时或在速度比安全性更重要的可信环境中，可以使用此功能。

## 性能

建立起始会话大约需要两秒，在时钟速度较慢或日志记录冗余信息较多的情况下，可能需要花费更多时间。后续通过已打开的安全套接字建立请求的速度会更快，最快只需不到 100 ms。

## 事件处理

ESP HTTPS 服务器在特定事件发生时，可以通过 事件循环库 触发事件处理程序。处理程序必须使用 `esp_event_handler_register()` 进行注册，以帮助 ESP HTTPS 服务器处理事件。

`esp_https_server_event_id_t` 包含了 ESP HTTPS 服务器可能发生的所有事件。

事件循环中不同 ESP HTTPS 服务器事件的预期数据类型如下所示：

> - HTTPS_SERVER_EVENT_ERROR : `esp_https_server_last_error_t`

> - HTTPS_SERVER_EVENT_START : `NULL`

> - HTTPS_SERVER_EVENT_ON_CONNECTED : `NULL`

> - HTTPS_SERVER_EVENT_ON_DATA : `int`

> - HTTPS_SERVER_EVENT_SENT_DATA : `NULL`

> - HTTPS_SERVER_EVENT_DISCONNECTED : `NULL`

> - HTTPS_SERVER_EVENT_STOP : `NULL`

## 应用示例

- protocols/https_server/simple 演示了如何创建一个 HTTPS 服务器，当访问时返回一个简单的 HTML 页面。

- protocols/https_server/wss_server 演示了如何创建一个支持多客户端的 SSL 服务器，具备简单的 WebSocket 请求处理器、PING-PONG 机制，并能够向所有客户端发送异步消息。

## HTTPS 服务器证书选择钩子

ESP HTTPS 服务器组件提供了设置服务器证书选择钩子的选项。启用此功能后，在服务器握手过程中，可以配置并使用证书选择回调函数。该回调函数会根据客户端 hello 消息中提供的 TLS 扩展（如 ALPN 和 SNI），动态选择合适的证书发送给客户端。

要启用此功能，请先在 ESP HTTPS 服务器的 menuconfig 中启用 CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK。请注意，只有当 Mbedtls 被用作 ESP-TLS 的 TLS 协议栈（默认行为）时，ESP-TLS 选项才可使用。

启用此功能后，请使用 `httpd_ssl_config_t` 结构体中的 `httpd_ssl_config::cert_select_cb` 成员，设置证书选择回调函数。

    int cert_selection_callback(mbedtls_ssl_context *ssl)
      {
          /* 回调函数应执行的代码 */
          return 0;
      }

      httpd_ssl_config_t cfg = {
          cert_select_cb = cert_section_callback,
      };

## API 参考

### Header File

- components/esp_https_server/include/esp_https_server.h

- This header file can be included with:

  >     #include "esp_https_server.h"

- This header file is a part of the API provided by the `esp_https_server` component. To declare that your component depends on `esp_https_server`, add the following to your CMakeLists.txt:

  >     REQUIRES esp_https_server

  > or

  >     PRIV_REQUIRES esp_https_server

### Functions

esp_err_t httpd_ssl_start(httpd_handle_t *handle, httpd_ssl_config_t *config)

  Create a SSL capable HTTP server (secure mode may be disabled in config)

  参数:

    - config -- [inout] - server config, must not be const. Does not have to stay valid after calling this function.

    - handle -- [out] - storage for the server handle, must be a valid pointer

  返回:

    success

esp_err_t httpd_ssl_stop(httpd_handle_t handle)

  Stop the server. Blocks until the server is shut down.

  参数:

    handle -- [in]

  返回:

    - ESP_OK: Server stopped successfully

    - ESP_ERR_INVALID_ARG: Invalid argument

    - ESP_FAIL: Failure to shut down server

### Structures

struct esp_https_server_user_cb_arg

  Callback data struct, contains the ESP-TLS connection handle and the connection state at which the callback is executed.

  Public Members

  httpd_ssl_user_cb_state_t user_cb_state

    State of user callback

  esp_tls_t *tls

    ESP-TLS connection handle

struct httpd_ssl_config

  HTTPS server config struct

  Please use HTTPD_SSL_CONFIG_DEFAULT() to initialize it.

  Public Members

  httpd_config_t httpd

    Underlying HTTPD server config

    Parameters like task stack size and priority can be adjusted here.

  const uint8_t *servercert

    Server certificate

  size_t servercert_len

    Server certificate byte length

  const uint8_t *cacert_pem

    CA certificate ((CA used to sign clients, or client cert itself)

  size_t cacert_len

    CA certificate byte length

  const uint8_t *prvtkey_pem

    Private key

  size_t prvtkey_len

    Private key byte length

  bool use_ecdsa_peripheral

    Use ECDSA peripheral to use private key

  uint8_t ecdsa_key_efuse_blk

    The efuse block where ECDSA key is stored. For SECP384R1 curve, if two blocks are used, set this to the low block and use ecdsa_key_efuse_blk_high for the high block.

  uint8_t ecdsa_key_efuse_blk_high

    The high efuse block for ECDSA key (used only for SECP384R1 curve). If not set (0), only ecdsa_key_efuse_blk is used.

  esp_tls_ecdsa_curve_t ecdsa_curve

    ECDSA curve to use (SECP256R1 or SECP384R1)

  httpd_ssl_transport_mode_t transport_mode

    Transport Mode (default secure)

  uint16_t port_secure

    Port used when transport mode is secure (default 443)

  uint16_t port_insecure

    Port used when transport mode is insecure (default 80)

  bool session_tickets

    Enable tls session tickets

  bool use_secure_element

    Enable secure element for server session

  esp_https_server_user_cb *user_cb

    User callback for esp_https_server

  void *ssl_userdata

    User data to add to the ssl context

  esp_https_server_cert_select_cb cert_select_cb

    Certificate selection callback to use. The callback is only applicable when CONFIG_ESP_HTTPS_SERVER_CERT_SELECT_HOOK is enabled in menuconfig

  const char **alpn_protos

    Application protocols the server supports in order of preference. Used for negotiating during the TLS handshake, first one the client supports is selected. The data structure must live as long as the https server itself

  uint32_t tls_handshake_timeout_ms

    TLS handshake timeout in milliseconds, default timeout is 10 seconds if not set

### Macros

HTTPD_SSL_CONFIG_DEFAULT()

  Default config struct init Notes:

  - port is set when starting the server, according to 'transport_mode'

  - one socket uses ~ 40kB RAM with SSL, we reduce the default socket count to 4

  - SSL sockets are usually long-lived, closing LRU prevents pool exhaustion DOS

  - Stack size may need adjustments depending on the user application

### Type Definitions

typedef esp_tls_handshake_callback esp_https_server_cert_select_cb

typedef struct esp_https_server_user_cb_arg esp_https_server_user_cb_arg_t

  Callback data struct, contains the ESP-TLS connection handle and the connection state at which the callback is executed.

typedef esp_tls_last_error_t esp_https_server_last_error_t

typedef void esp_https_server_user_cb(esp_https_server_user_cb_arg_t *user_cb)

  Callback function prototype Can be used to get connection or client information (SSL context) E.g. Client certificate, Socket FD, Connection state, etc.

  Param user_cb:

    Callback data struct

typedef struct httpd_ssl_config httpd_ssl_config_t

### Enumerations

enum esp_https_server_event_id_t

  Values:

  enumerator HTTPS_SERVER_EVENT_ERROR

    This event occurs when there are any errors during execution

  enumerator HTTPS_SERVER_EVENT_START

    This event occurs when HTTPS Server is started

  enumerator HTTPS_SERVER_EVENT_ON_CONNECTED

    Once the HTTPS Server has been connected to the client

  enumerator HTTPS_SERVER_EVENT_ON_DATA

    Occurs when receiving data from the client

  enumerator HTTPS_SERVER_EVENT_SENT_DATA

    Occurs when an ESP HTTPS server sends data to the client

  enumerator HTTPS_SERVER_EVENT_DISCONNECTED

    The connection has been disconnected

  enumerator HTTPS_SERVER_EVENT_STOP

    This event occurs when HTTPS Server is stopped

enum httpd_ssl_transport_mode_t

  Values:

  enumerator HTTPD_SSL_TRANSPORT_SECURE
  enumerator HTTPD_SSL_TRANSPORT_INSECURE

enum httpd_ssl_user_cb_state_t

  Indicates the state at which the user callback is executed, i.e at session creation or session close.

  Values:

  enumerator HTTPD_SSL_USER_CB_SESS_CREATE
  enumerator HTTPD_SSL_USER_CB_SESS_CLOSE

此文档对您有帮助吗？

- 反馈已收到，谢谢！
- 如果您有其他意见，欢迎填写乐鑫文档反馈表。

- 我们重视您的反馈。
- 您可以填写乐鑫文档反馈表告诉我们如何改进该文档。