diff --git a/include/ftp/detail/socket.hpp b/include/ftp/detail/socket.hpp index 03e7e49..1eb616e 100644 --- a/include/ftp/detail/socket.hpp +++ b/include/ftp/detail/socket.hpp @@ -49,6 +49,8 @@ class socket : public socket_base void ssl_handshake(boost::asio::ssl::stream_base::handshake_type type, boost::system::error_code & ec) override; + void ssl_shutdown(boost::system::error_code & ec) override; + std::size_t write(const char *buf, std::size_t size, boost::system::error_code & ec) override; std::size_t write(std::string_view buf, boost::system::error_code & ec) override; diff --git a/include/ftp/detail/socket_base.hpp b/include/ftp/detail/socket_base.hpp index ddd5f9b..6c9d476 100644 --- a/include/ftp/detail/socket_base.hpp +++ b/include/ftp/detail/socket_base.hpp @@ -47,6 +47,8 @@ class socket_base virtual void ssl_handshake(boost::asio::ssl::stream_base::handshake_type type, boost::system::error_code & ec) = 0; + virtual void ssl_shutdown(boost::system::error_code & ec) = 0; + virtual std::size_t write(const char *buf, std::size_t size, boost::system::error_code & ec) = 0; virtual std::size_t write(std::string_view buf, boost::system::error_code & ec) = 0; diff --git a/include/ftp/detail/ssl_socket.hpp b/include/ftp/detail/ssl_socket.hpp index b3b83b7..ea417a5 100644 --- a/include/ftp/detail/ssl_socket.hpp +++ b/include/ftp/detail/ssl_socket.hpp @@ -49,6 +49,8 @@ class ssl_socket : public socket_base void ssl_handshake(boost::asio::ssl::stream_base::handshake_type type, boost::system::error_code & ec) override; + void ssl_shutdown(boost::system::error_code & ec) override; + std::size_t write(const char *buf, std::size_t size, boost::system::error_code & ec) override; std::size_t write(std::string_view buf, boost::system::error_code & ec) override; diff --git a/src/control_connection.cpp b/src/control_connection.cpp index e566bd9..68170e4 100644 --- a/src/control_connection.cpp +++ b/src/control_connection.cpp @@ -114,14 +114,9 @@ void control_connection::ssl_handshake() void control_connection::ssl_shutdown() { - if (socket_->has_ssl_support()) - { - return; - } - boost::system::error_code ec; - socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + socket_->ssl_shutdown(ec); if (ec) { @@ -266,7 +261,14 @@ void control_connection::disconnect() { boost::system::error_code ec; - socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + if (socket_->has_ssl_support()) + { + socket_->ssl_shutdown(ec); + } + else + { + socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + } if (ec == boost::asio::error::not_connected) { diff --git a/src/data_connection.cpp b/src/data_connection.cpp index 26363c9..1b9b03b 100644 --- a/src/data_connection.cpp +++ b/src/data_connection.cpp @@ -247,27 +247,31 @@ void data_connection::disconnect(bool graceful) { boost::system::error_code ec; - if (graceful) + if (socket_->has_ssl_support()) + { + socket_->ssl_shutdown(ec); + } + else if (graceful) { socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + } - if (ec == boost::asio::error::not_connected) - { - /* Ignore 'not_connected' error. We could get ENOTCONN if a server side - * has already closed the data connection. This suits us, just close - * the socket. - */ - } - else if (ec == boost::asio::error::eof) - { - /* Rationale: - * http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error - */ - } - else if (ec) - { - throw ftp_exception(ec, "Cannot close data connection"); - } + if (ec == boost::asio::error::not_connected) + { + /* Ignore 'not_connected' error. We could get ENOTCONN if a server side + * has already closed the data connection. This suits us, just close + * the socket. + */ + } + else if (ec == boost::asio::error::eof) + { + /* Rationale: + * http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error + */ + } + else if (ec) + { + throw ftp_exception(ec, "Cannot close data connection"); } socket_->close(ec); diff --git a/src/socket.cpp b/src/socket.cpp index 6c26127..5514aee 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -58,7 +58,12 @@ bool socket::has_ssl_support() const void socket::ssl_handshake(boost::asio::ssl::stream_base::handshake_type type, boost::system::error_code & ec) { - /* Handshake makes sense only for SSL-sockets. */ + /* Make sense only for SSL-sockets. */ +} + +void socket::ssl_shutdown(boost::system::error_code & ec) +{ + /* Make sense only for SSL-sockets. */ } std::size_t socket::write(const char *buf, std::size_t size, boost::system::error_code & ec) diff --git a/src/ssl_socket.cpp b/src/ssl_socket.cpp index f990625..d4a80f5 100644 --- a/src/ssl_socket.cpp +++ b/src/ssl_socket.cpp @@ -57,6 +57,11 @@ void ssl_socket::ssl_handshake(boost::asio::ssl::stream_base::handshake_type typ socket_.handshake(type, ec); } +void ssl_socket::ssl_shutdown(boost::system::error_code & ec) +{ + socket_.shutdown(ec); +} + std::size_t ssl_socket::write(const char *buf, std::size_t size, boost::system::error_code & ec) { return socket_base::write(socket_, buf, size, ec); @@ -79,8 +84,7 @@ std::size_t ssl_socket::read_line(std::string & buf, std::size_t max_size, boost void ssl_socket::shutdown(boost::asio::ip::tcp::socket::shutdown_type type, boost::system::error_code & ec) { - /* Perform SSL shutdown, ignore the 'type' param. */ - socket_.shutdown(ec); + socket_.lowest_layer().shutdown(type, ec); } void ssl_socket::close(boost::system::error_code & ec)