diff --git a/CMakeLists.txt b/CMakeLists.txt index 6465ffa..37cd4fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(sources include/ftp/detail/ascii_ostream.hpp include/ftp/detail/binary_istream.hpp include/ftp/detail/binary_ostream.hpp + include/ftp/detail/boost_utils.hpp include/ftp/detail/control_connection.hpp include/ftp/detail/data_connection.hpp include/ftp/detail/utils.hpp @@ -39,6 +40,7 @@ set(sources src/ascii_ostream.cpp src/binary_istream.cpp src/binary_ostream.cpp + src/boost_utils.cpp src/client.cpp src/control_connection.cpp src/data_connection.cpp diff --git a/include/ftp/client.hpp b/include/ftp/client.hpp index 5fe6e0d..14d2dd4 100644 --- a/include/ftp/client.hpp +++ b/include/ftp/client.hpp @@ -158,7 +158,7 @@ class client static std::string make_command(std::string_view command, const std::optional & argument = std::nullopt); - static std::string make_port_command(std::string_view ip, std::uint16_t port); + static std::string make_port_command(const boost::asio::ip::tcp::endpoint & endpoint); static std::string make_type_command(transfer_type type); diff --git a/include/ftp/detail/boost_utils.hpp b/include/ftp/detail/boost_utils.hpp new file mode 100644 index 0000000..bdd2719 --- /dev/null +++ b/include/ftp/detail/boost_utils.hpp @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (c) 2023 Denis Kovalchuk + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef LIBFTP_BOOST_UTILS_HPP +#define LIBFTP_BOOST_UTILS_HPP + +#include +#include + +namespace ftp::detail::boost_utils +{ + +std::string address_to_string(const boost::asio::ip::address & address); + +} // namespace ftp::detail::boost_utils +#endif //LIBFTP_BOOST_UTILS_HPP diff --git a/include/ftp/detail/control_connection.hpp b/include/ftp/detail/control_connection.hpp index d1163aa..b7d5fb1 100644 --- a/include/ftp/detail/control_connection.hpp +++ b/include/ftp/detail/control_connection.hpp @@ -46,7 +46,7 @@ class control_connection void close(); - [[nodiscard]] std::string get_local_ip() const; + [[nodiscard]] boost::asio::ip::tcp::endpoint get_local_endpoint() const; void send(std::string_view command); diff --git a/include/ftp/detail/data_connection.hpp b/include/ftp/detail/data_connection.hpp index c78f0ff..4716250 100644 --- a/include/ftp/detail/data_connection.hpp +++ b/include/ftp/detail/data_connection.hpp @@ -46,11 +46,11 @@ class data_connection void open(std::string_view ip, std::uint16_t port); - void listen(std::string_view ip, std::uint16_t port); + void listen(const boost::asio::ip::tcp::endpoint & endpoint); void accept(); - std::uint16_t get_listen_port(); + boost::asio::ip::tcp::endpoint get_listen_endpoint() const; void close(bool graceful = true); diff --git a/src/boost_utils.cpp b/src/boost_utils.cpp new file mode 100644 index 0000000..ace21d1 --- /dev/null +++ b/src/boost_utils.cpp @@ -0,0 +1,45 @@ +/* + * MIT License + * + * Copyright (c) 2023 Denis Kovalchuk + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include + +namespace ftp::detail::boost_utils +{ + +std::string address_to_string(const boost::asio::ip::address & address) +{ + boost::system::error_code ec; + + std::string string = address.to_string(ec); + + if (ec) + { + throw ftp_exception(ec, "Cannot get address string"); + } + + return string; +} + +} // namespace ftp::detail::boost_utils diff --git a/src/client.cpp b/src/client.cpp index 84314c4..f12ff67 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -602,13 +603,14 @@ data_connection_ptr client::process_pasv_command(std::string_view command, repli data_connection_ptr client::process_port_command(std::string_view command, replies & replies) { - data_connection_ptr connection = std::make_unique(); + boost::asio::ip::tcp::endpoint local_endpoint = control_connection_.get_local_endpoint(); + boost::asio::ip::tcp::endpoint listen_endpoint(local_endpoint.address(), 0); - std::string local_ip = control_connection_.get_local_ip(); - connection->listen(local_ip, 0); - std::uint16_t local_port = connection->get_listen_port(); + data_connection_ptr connection = std::make_unique(); + connection->listen(listen_endpoint); + listen_endpoint = connection->get_listen_endpoint(); - std::string port_command = make_port_command(local_ip, local_port); + std::string port_command = make_port_command(listen_endpoint); reply reply = process_command(port_command, replies); if (!reply.is_positive()) @@ -691,12 +693,14 @@ std::string client::make_command(std::string_view command, const std::optional