Skip to content

Commit

Permalink
perf: use Boost.Asio endpoints where is possible
Browse files Browse the repository at this point in the history
Get rid of extra address construction from strings.
  • Loading branch information
deniskovalchuk committed Sep 28, 2023
1 parent 7b61465 commit 01c46c7
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 34 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion include/ftp/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class client

static std::string make_command(std::string_view command, const std::optional<std::string_view> & 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);

Expand Down
37 changes: 37 additions & 0 deletions include/ftp/detail/boost_utils.hpp
Original file line number Diff line number Diff line change
@@ -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 <boost/asio/ip/address.hpp>
#include <string>

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
2 changes: 1 addition & 1 deletion include/ftp/detail/control_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions include/ftp/detail/data_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
45 changes: 45 additions & 0 deletions src/boost_utils.cpp
Original file line number Diff line number Diff line change
@@ -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 <ftp/detail/boost_utils.hpp>
#include <ftp/ftp_exception.hpp>

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
20 changes: 13 additions & 7 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#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/stream/ostream_adapter.hpp>
#include <sstream>

Expand Down Expand Up @@ -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<data_connection>();
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<data_connection>();
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())
Expand Down Expand Up @@ -691,19 +693,23 @@ std::string client::make_command(std::string_view command, const std::optional<s
return result;
}

std::string client::make_port_command(std::string_view ip, std::uint16_t port)
std::string client::make_port_command(const boost::asio::ip::tcp::endpoint & endpoint)
{
std::string command = "PORT";
command.append(" ");

for (char ch : ip)
std::string address_string = boost_utils::address_to_string(endpoint.address());

for (char ch : address_string)
{
if (ch == '.')
command.push_back(',');
else
command.push_back(ch);
}

boost::asio::ip::port_type port = endpoint.port();

command.append(",");
command.append(std::to_string(port / 256));
command.append(",");
Expand Down
13 changes: 3 additions & 10 deletions src/control_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,25 +109,18 @@ void control_connection::close()
}
}

std::string control_connection::get_local_ip() const
boost::asio::ip::tcp::endpoint control_connection::get_local_endpoint() const
{
boost::system::error_code ec;

boost::asio::ip::tcp::endpoint local_endpoint = socket_.local_endpoint(ec);

if (ec)
{
throw ftp_exception(ec, "Cannot get IP address");
throw ftp_exception(ec, "Cannot get local endpoint");
}

std::string ip = local_endpoint.address().to_string(ec);

if (ec)
{
throw ftp_exception(ec, "Cannot get IP address");
}

return ip;
return local_endpoint;
}

reply control_connection::recv()
Expand Down
17 changes: 4 additions & 13 deletions src/data_connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,10 @@ void data_connection::open(std::string_view ip, std::uint16_t port)
}
}

void data_connection::listen(std::string_view ip, std::uint16_t port)
void data_connection::listen(const boost::asio::ip::tcp::endpoint & endpoint)
{
boost::system::error_code ec;

boost::asio::ip::address address = boost::asio::ip::make_address(ip, ec);

if (ec)
{
throw ftp_exception(ec, "Cannot get IP address");
}

boost::asio::ip::tcp::endpoint endpoint(address, port);

acceptor_.open(endpoint.protocol(), ec);

if (ec)
Expand Down Expand Up @@ -114,18 +105,18 @@ void data_connection::accept()
}
}

std::uint16_t data_connection::get_listen_port()
boost::asio::ip::tcp::endpoint data_connection::get_listen_endpoint() const
{
boost::system::error_code ec;

boost::asio::ip::tcp::endpoint endpoint = acceptor_.local_endpoint(ec);

if (ec)
{
throw ftp_exception(ec, "Cannot get listen port");
throw ftp_exception(ec, "Cannot get listen endpoint");
}

return endpoint.port();
return endpoint;
}

void data_connection::close(bool graceful)
Expand Down

0 comments on commit 01c46c7

Please sign in to comment.