| 543 | |
| 544 | |
| 545 | Future<std::shared_ptr<SocketImpl>> OpenSSLSocketImpl::accept() |
| 546 | { |
| 547 | if (!accept_loop_started.once()) { |
| 548 | // Hold a weak pointer since we do not want this accept loop to extend |
| 549 | // the lifetime of `this` unnecessarily. |
| 550 | std::weak_ptr<OpenSSLSocketImpl> weak_self(shared(this)); |
| 551 | |
| 552 | // We start accepting incoming connections in a loop here because a socket |
| 553 | // must complete the SSL handshake (or be downgraded) before the socket is |
| 554 | // considered ready. In case the incoming socket never writes any data, |
| 555 | // we do not wait for the accept logic to complete before accepting a |
| 556 | // new socket. |
| 557 | process::loop( |
| 558 | compute_thread, |
| 559 | [weak_self]() -> Future<std::shared_ptr<SocketImpl>> { |
| 560 | std::shared_ptr<OpenSSLSocketImpl> self(weak_self.lock()); |
| 561 | |
| 562 | if (self == nullptr) { |
| 563 | return Failure("Socket destructed"); |
| 564 | } |
| 565 | |
| 566 | return self->PollSocketImpl::accept(); |
| 567 | }, |
| 568 | [weak_self](const std::shared_ptr<SocketImpl>& socket) |
| 569 | -> Future<ControlFlow<Nothing>> { |
| 570 | std::shared_ptr<OpenSSLSocketImpl> self(weak_self.lock()); |
| 571 | |
| 572 | if (self == nullptr) { |
| 573 | return Break(); |
| 574 | } |
| 575 | |
| 576 | // If we support downgrading the connection, first wait for this |
| 577 | // socket to become readable. We will then MSG_PEEK it to test |
| 578 | // whether we want to dispatch as SSL or non-SSL. |
| 579 | if (openssl::flags().support_downgrade) { |
| 580 | io::poll(socket->get(), process::io::READ) |
| 581 | .onReady([weak_self, socket]() { |
| 582 | std::shared_ptr<OpenSSLSocketImpl> self(weak_self.lock()); |
| 583 | |
| 584 | if (self == nullptr) { |
| 585 | return; |
| 586 | } |
| 587 | |
| 588 | char data[6]; |
| 589 | |
| 590 | // Try to peek the first 6 bytes of the message. |
| 591 | ssize_t size = ::recv(socket->get(), data, 6, MSG_PEEK); |
| 592 | |
| 593 | // Based on the function 'ssl23_get_client_hello' in openssl, we |
| 594 | // test whether to dispatch to the SSL or non-SSL based accept |
| 595 | // based on the following rules: |
| 596 | // 1. If there are fewer than 3 bytes: non-SSL. |
| 597 | // 2. If the 1st bit of the 1st byte is set AND the 3rd byte |
| 598 | // is equal to SSL2_MT_CLIENT_HELLO: SSL. |
| 599 | // 3. If the 1st byte is equal to SSL3_RT_HANDSHAKE AND the |
| 600 | // 2nd byte is equal to SSL3_VERSION_MAJOR and the 6th byte |
| 601 | // is equal to SSL3_MT_CLIENT_HELLO: SSL. |
| 602 | // 4. Otherwise: non-SSL. |
nothing calls this directly
no test coverage detected