///////////////////////////////////////////////////////
| 560 | |
| 561 | //////////////////////////////////////////////////////////// |
| 562 | Sftp::Result Sftp::connect(IpAddress server, unsigned short port, const TimeoutWithPredicate& timeout) |
| 563 | { |
| 564 | (void)disconnect(timeout); |
| 565 | |
| 566 | if (const auto status = m_impl->socket.connect(server, port); |
| 567 | (status == Socket::Status::Error) || (status == Socket::Status::Disconnected)) |
| 568 | return Result(Result::Value::Disconnected); |
| 569 | |
| 570 | m_impl->selectorRecv.clear(); |
| 571 | m_impl->selectorSend.clear(); |
| 572 | m_impl->selectorEither.clear(); |
| 573 | m_impl->selectorRecv.add(m_impl->socket, sf::SocketSelector::Receive); |
| 574 | m_impl->selectorSend.add(m_impl->socket, sf::SocketSelector::Send); |
| 575 | m_impl->selectorEither.add(m_impl->socket, sf::SocketSelector::Receive | sf::SocketSelector::Send); |
| 576 | |
| 577 | // Wait for the socket to become connected |
| 578 | while (true) |
| 579 | { |
| 580 | if (m_impl->selectorSend.wait(timeout.getPeriod())) |
| 581 | break; |
| 582 | |
| 583 | if (!timeout.getPredicate()()) |
| 584 | { |
| 585 | m_impl->selectorRecv.clear(); |
| 586 | m_impl->selectorSend.clear(); |
| 587 | m_impl->selectorEither.clear(); |
| 588 | m_impl->socket.disconnect(); |
| 589 | return Result(Result::Value::Timeout); |
| 590 | } |
| 591 | } |
| 592 | |
| 593 | // Check if our connection was actually accepted or refused |
| 594 | if (!m_impl->socket.getRemoteAddress().has_value()) |
| 595 | { |
| 596 | m_impl->selectorRecv.clear(); |
| 597 | m_impl->selectorSend.clear(); |
| 598 | m_impl->selectorEither.clear(); |
| 599 | m_impl->socket.disconnect(); |
| 600 | return Result(Result::Value::Refused); |
| 601 | } |
| 602 | |
| 603 | // At this point the TCP connection is established |
| 604 | |
| 605 | // Reset POSIX rename supported flag to assume true for new connections |
| 606 | m_impl->posixRenameSupported = true; |
| 607 | |
| 608 | // Set up SSH session |
| 609 | m_impl->ssh2Session.reset(libssh2_session_init_ex(nullptr, nullptr, nullptr, m_impl.get())); |
| 610 | assert(m_impl->ssh2Session); |
| 611 | |
| 612 | // Tell libssh2 we will take care of waiting on socket readiness ourselves |
| 613 | libssh2_session_set_blocking(m_impl->ssh2Session.get(), 0); |
| 614 | |
| 615 | // Set send and receive callbacks to make use of TcpSocket as the underlying transport |
| 616 | #if (LIBSSH2_VERSION_NUM >= 0x010b01) |
| 617 | libssh2_session_callback_set2(m_impl->ssh2Session.get(), |
| 618 | LIBSSH2_CALLBACK_SEND, |
| 619 | reinterpret_cast<libssh2_cb_generic*>(Impl::handleSend)); |
nothing calls this directly
no test coverage detected