[/
    Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

    Official repository: https://github.com/boostorg/beast
]

[section:detect_ssl 检测 SSL __示例__]

本示例将构建一个简单函数，用于检测输入缓冲区序列中是否存在 TLS 客户端握手协议。然后在该示例的基础上，添加一个同步流算法。最后，通过组合操作实现异步检测函数。该 SSL 检测器可用于让服务器在同一端口上同时接受 TLS 和明文（未加密）连接。

以下函数模板声明用于检测 SSL 客户端握手。该函数接受任何满足 __ConstBufferSequence__ 概念要求的对象，从而使调用方能够根据任务需要灵活选择合适的缓冲区对象。

[example_core_detect_ssl_1]

该算法从缓冲区开头开始检查，并按照 TLS 规范进行一系列验证。如果数据不足，无法确定结果，则返回 `boost::indeterminate`，通知调用方继续向缓冲区读入更多数据。上面声明的函数，其定义如下：

[example_core_detect_ssl_2]

上述检测函数足够通用，且目标明确，可以作为基础模块来构建更高级的抽象。接下来要创建一个流算法：该算法接收一个流作为参数，通过执行读写操作来达到特定目的，这里就是检测 TLS 客户端握手。流算法可以是同步的，也可以是异步的。同步算法更容易编写，因此先实现同步版本，再在此基础上构建异步版本，并尽量让两者风格相似，便于理解。

同步版本的实现如下：

[example_core_detect_ssl_3]

有了同步版本之后，可以尝试以类似方式构建异步版本。启动异步操作的函数称为发起函数。上述同步版本通过输出参数返回错误码，而异步版本则通过完成处理器或由完成令牌定义的其他自定义机制来传递错误码。发起函数的签名反映了这些差异。

首先声明发起函数，并说明其使用要求、参数、前置条件及功能效果：

[example_core_detect_ssl_4]

实现发起函数还需要以下两个额外组件：

* 一个中间完成处理器，称为“组合操作”
  object, which holds the state of the operation while it is in progress,
  and also holds the user's completion handler to be invoked when the
  opeartion completes, and

* 一个“发起”函数对象，当使用参数调用时
  captured at the call site of the initiating function, constructs the 
  composed operation with the captured arguments and launches it.

这里先对组合操作类型进行前置声明，然后给出发起函数对象的定义。因为这些组件属于内部实现细节，不对外公开，所以都放在 `detail` 命名空间中：

[example_core_detect_ssl_5]

发起函数的定义本身并不复杂：先对参数进行类型检查，再通过 `net::async_initiate` 捕获参数列表和发起函数对象的一个副本。根据 `CompletionToken` 类型对应的 `async_result` 特化版本，发起函数可以立即执行，也可以在发起函数返回之后再执行。后者称为“延迟执行”，这种机制便于编写高效且表达力强的抽象。

[example_core_detect_ssl_6]

接下来声明组合操作。虽然需要编写不少必要的样板代码，但最终效果是值得的。

[example_core_detect_ssl_7]

样板代码已经全部完成，接下来需要实现函数调用运算符，使该组合操作成为一个具有 `void(error_code, std::size_t)` 签名的完成处理器，而这正是执行异步读取时所需的签名。该函数是对上述同步版本 `detect_ssl` 的一种转换，但与同步版本不同，它采用了回调风格代码特有的控制流反转方式：

[example_core_detect_ssl_8]

示例 [path_link example/advanced/server/advanced_server.cpp advanced-server] 和 [path_link example/advanced/server-flex/advanced_server_flex.cpp advanced-server-flex] 使用了该 SSL 检测函数。

[endsect]
