延迟协程产量

时间:2015-10-22 16:30:52

标签: c++ ssl lambda boost-asio boost-coroutine

我的问题似乎源于这样一个事实,即openssl没有像服务器名称指示(SNI)那样的回调传递样式但是我试图强制进入它。

我想避免在读取客户端SSL hello时阻止工作线程,并且在我等待服务器ssl握手完成时拒绝返回SNI回调时避免阻塞工作线程(因此我可以重新签名服务器证书)。

对于使用asio openssl包装器的boost::asio::ssl::stream bsaed重新签名SSL代理。

我使用SSL_CTX_set_tlsext_servername_*帮助程序在与客户端进行SSL协商期间获得回调。

目前确保我在boost::asio::spawnstrand的lambda中使用协程和握手。我使用服务器名称指示回调(适当包装),以便我可以在服务器握手期间阻止客户端握手但不阻塞工作线程(协同例程将暂停。

boost::asio::spawn(strand_, [=](boost::asio::yield_context yield){
  boost::system::error_code ec;
  boost::system::error_code ec_server;

  sni_callback = [=,&ec](std::string server_name) {
    server_->ssl_connection->ssl_socket.async_handshake(boost::asio::ssl::stream_base::client, yield[ec_server]);
    /* Todo: sign the server certificate and replace the ssl_socket SSL_CTX here */
  };

  ssl_connection->ssl_socket.handshake(boost::asio::ssl:stream_base::server, ec);

  if (! ec) ec = ec_server;

  handler(ec);
});

但我意识到与客户端的ssl握手将阻止它完成的工作线程。

我尝试与客户进行asyc握手:

  ssl_connection->ssl_socket.async_handshake(boost::asio::ssl:stream_base::server, yield[ec]);

但是在SNI处理程序包装器中,程序会在yield中产生段错误。

毫无疑问,这是因为非阻塞握手不会在协同例程上调用SNI处理程序 - 并且它能够做到这一点的唯一方法(不阻塞工作线程)就是如果它的所有内部处理程序都被调用了coroutine,但我知道它使用内部链来完成它自己的工作。

加载了所有共享库符号(即使对于libstdc ++等),堆栈跟踪是:

.#0  0x000000000000000c in ?? ()
.#1  0x00007f8200000000 in ?? ()
.#2  0x00007f829e15043d in CRYPTO_free (str=0x7f828c054640) at mem.c:401
.#3  0x00007f829e1faba5 in ASN1_primitive_free (pval=<optimized out>, it=<optimized out>) at tasn_fre.c:261
.#4  0x00007f828c052250 in ?? ()
.#5  0x0000000000000005 in ?? ()
.#6  0x00007f828c0524f0 in ?? ()
.#7  0x0000000000000005 in ?? ()
.#8  0x00007f829d30c560 in ?? ()
.#9  0x00007f829d30c710 in ?? ()
.#10 0x000000000000000c in ?? ()
.#11 0x00007f828c0180b4 in ?? ()
.#12 0x00007f829e15043d in CRYPTO_free (str=0x7f828c052250) at mem.c:401
.#13 0x00007f829e1eb2cf in EVP_PKEY_CTX_free (ctx=<optimized out>) at pmeth_lib.c:381
.#14 0x00007f829e1de1e2 in EVP_MD_CTX_cleanup (ctx=0x7f829d30c590) at digest.c:394
.#15 0x00007f829e5041c1 in tls1_PRF (digest_mask=262400, seed1=0x7f829e5213fb, seed1_len=15, seed2=0x7f829d30c720, seed2_len=-1639094656, seed3=0x0, 
seed3_len=-1657747584, seed4=0x23635fe, seed4_len=-1657747600, sec=0x7f82a0035df0 "\321\365M\236\202\177", slen=<optimized out>, out1=0x7f82a0035178 "d\356@", 
out2=0x7f82a0038508 "", olen=4247053, seed5_len=0, seed5=0x0) at t1_enc.c:272
.#16 0x00007f829e4dbb18 in ?? () from /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
.#17 0x00007f829d30c780 in ?? ()
.#18 0x00000000023635fe in ?? ()
.#19 0x00007f829d30c770 in ?? ()
.#20 0x00007f82a0035df0 in ?? ()
.#21 0x0000000000000000 in ?? ()

我希望在清除故障时这是一个堆栈跟踪。

要在同一个协同程序上调用SNI处理程序,我认为我需要在该协同程序上进行所有ssl :: stream中间回调。 有没有直接的方法呢?

我想知道boost :: ssl是否可以在它自己的链中调用它的处理程序,但仍然在coroutine堆栈上,这是唯一的修复,但我不知道asio_handler_invoke业务与处理程序是否有足够的魔力导致它即使有可能也会发生。如何嵌套asio_handler_invoke来运行协程(strand-y本身)和通过内部链。

我也应该在我的示例的最后一行使用asio_invoke_handler吗?

0 个答案:

没有答案