diff options
Diffstat (limited to 'apps')
34 files changed, 1156 insertions, 573 deletions
diff --git a/apps/.clang-format b/apps/.clang-format index cd21e2017..adc73c6fd 100644 --- a/apps/.clang-format +++ b/apps/.clang-format @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2021 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index df1b9fc7c..b06d7bcb4 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,37 +11,68 @@ # See the License for the specific language governing permissions and # limitations under the License. +############################################################## +# Project and cmake version +############################################################## cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 14) - project(apps) + +############################################################## +# C Standard +############################################################## +set(CMAKE_CXX_STANDARD 17) + + +############################################################## +# Cmake modules +############################################################## +include("${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules ) -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif () - -include(BuildMacros) -include(WindowsMacros) +############################################################## +# Libs and Bins names +############################################################## set(HICN_APPS hicn-apps CACHE INTERNAL "" FORCE) +set(HIGET higet) +set(HTTP_PROXY hicn-http-proxy) +set(LIBHTTP_PROXY hicnhttpproxy) +set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static) + +############################################################## +# Dependencies and third party libs +############################################################## find_package(Threads REQUIRED) -find_package(Libconfig++ REQUIRED) +find_package(Libconfig++ ${LIBCONFIG_DEFAULT_VERSION} REQUIRED) + +############################################################## +# Check if building as subproject or as root project +############################################################## if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - find_package(Libtransport REQUIRED) - find_package(Libhicn REQUIRED) - find_package(hicnctrl REQUIRED) + include(CommonSetup) + + find_package(Libhicn ${CURRENT_VERSION} REQUIRED NO_MODULE) + find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE) + find_package(Libhicntransport ${CURRENT_VERSION} REQUIRED NO_MODULE) + + if (DISABLE_SHARED_LIBRARIES) + set(LIBTYPE static) + else() + set(LIBTYPE shared) + endif() + + list(APPEND LIBHICN_LIBRARIES hicn::hicn.${LIBTYPE}) + list(APPEND LIBTRANSPORT_LIBRARIES hicn::hicntransport.${LIBTYPE}) + list(APPEND LIBHICNCTRL_LIBRARIES hicn::hicnctrl.${LIBTYPE}) else() if (DISABLE_SHARED_LIBRARIES) - find_package(OpenSSL REQUIRED) + find_package(OpenSSL ${OPENSSL_DEFAULT_VERSION} REQUIRED) set(LIBTRANSPORT_LIBRARIES ${LIBTRANSPORT_STATIC}) set(LIBHICN_LIBRARIES ${LIBHICN_STATIC}) set(LIBHICNCTRL_LIBRARIES ${LIBHICNCTRL_STATIC}) @@ -56,20 +87,18 @@ else() ) endif() -if (WIN32) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4200 /wd4996") -endif () -include(Packaging) +############################################################## +# Packaging and versioning +############################################################## +include(${CMAKE_CURRENT_SOURCE_DIR}/../versions.cmake) +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging.cmake) + +############################################################## +# Subdirectories +############################################################## add_subdirectory(ping) add_subdirectory(hiperf) - -set(HIGET higet) -set(HTTP_PROXY hicn-http-proxy) - -if (NOT WIN32) - add_subdirectory(http-proxy) -endif () - +add_subdirectory(http-proxy) add_subdirectory(higet) diff --git a/apps/cmake/Modules/Packaging.cmake b/apps/cmake/packaging.cmake index 981eb728e..9142598ad 100644 --- a/apps/cmake/Modules/Packaging.cmake +++ b/apps/cmake/packaging.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -18,21 +18,34 @@ useful for testing and debugging within a hicn network." ) set(${HICN_APPS}_DEB_DEPENDENCIES - "lib${LIBTRANSPORT} (>= stable_version), lib${LIBHICNCTRL} (>= stable_version)" + "lib${LIBTRANSPORT} (= stable_version), lib${LIBHICNCTRL} (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) set(${HICN_APPS}-dev_DEB_DEPENDENCIES - "${HICN_APPS} (>= stable_version), lib${LIBTRANSPORT}-dev (>= stable_version), lib${LIBHICNCTRL}-dev (>= stable_version)" + "${HICN_APPS} (= stable_version), lib${LIBTRANSPORT}-dev (= stable_version), lib${LIBHICNCTRL}-dev (= stable_version)" CACHE STRING "Dependencies for deb/rpm package." ) set(${HICN_APPS}_RPM_DEPENDENCIES - "lib${LIBTRANSPORT} >= stable_version, lib${LIBHICNCTRL} >= stable_version" + "lib${LIBTRANSPORT} = stable_version, lib${LIBHICNCTRL} = stable_version" CACHE STRING "Dependencies for deb/rpm package." ) set(${HICN_APPS}-dev_RPM_DEPENDENCIES - "${HICN_APPS} >= stable_version, lib${LIBTRANSPORT}-dev >= stable_version, lib${LIBHICNCTRL}-dev >= stable_version" + "${HICN_APPS} = stable_version, lib${LIBTRANSPORT}-dev = stable_version, lib${LIBHICNCTRL}-dev = stable_version" CACHE STRING "Dependencies for deb/rpm package." -)
\ No newline at end of file +) + +if (INTERNAL_ENVIRONMENT) + include(CheckSsl) + CheckSsl() + set(${HICN_APPS}_DEB_DEPENDENCIES + "${${HICN_APPS}_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY}" + CACHE STRING "Dependencies for deb/rpm package." + ) + set(${HICN_APPS}-dev_DEB_DEPENDENCIES + "${${HICN_APPS}-dev_DEB_DEPENDENCIES}, ${OPENSSL_DEPENDENCY_DEV}" + CACHE STRING "Dependencies for deb/rpm package." + ) +endif ()
\ No newline at end of file diff --git a/apps/higet/CMakeLists.txt b/apps/higet/CMakeLists.txt index 8d112d3a3..f4d2d4ec4 100644 --- a/apps/higet/CMakeLists.txt +++ b/apps/higet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,36 +11,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 14) - -project(utils) - -find_package(Threads REQUIRED) - -set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" -) - -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif () - +############################################################## +# Source files +############################################################## list(APPEND APPS_SRC higet.cc ) + +############################################################## +# Linker flags +############################################################## if (WIN32) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" ) + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:\"LIBCMT\"" + ) endif() + +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + + +############################################################## +# Build higet +############################################################## if (NOT DISABLE_EXECUTABLES) build_executable(${HIGET} SOURCES ${APPS_SRC} LINK_LIBRARIES + ${LIBHICN_LIBRARIES} ${LIBTRANSPORT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${WSOCK32_LIBRARY} @@ -49,5 +53,6 @@ if (NOT DISABLE_EXECUTABLES) COMPONENT ${HICN_APPS} DEFINITIONS ${COMPILER_DEFINITIONS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif () diff --git a/apps/higet/higet.cc b/apps/higet/higet.cc index 9ae869731..d72d7d74f 100644 --- a/apps/higet/higet.cc +++ b/apps/higet/higet.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -14,23 +14,20 @@ */ #include <hicn/transport/http/client_connection.h> +#include <hicn/transport/utils/chrono_typedefs.h> #include <algorithm> +#include <asio.hpp> #include <fstream> #include <functional> #include <map> +#ifndef ASIO_STANDALONE #define ASIO_STANDALONE +#endif #include <asio.hpp> -#undef ASIO_STANDALONE - #include <thread> -typedef std::chrono::time_point<std::chrono::system_clock> Time; -typedef std::chrono::milliseconds TimeDuration; - -Time t1; - #define DEFAULT_BETA 0.99 #define DEFAULT_GAMMA 0.07 @@ -181,7 +178,7 @@ class ReadBytesCallbackImplementation }); } - void onError(const std::error_code ec) { + void onError(const std::error_code &ec) { io_service_.post([this]() { of_.close(); delete out_; @@ -345,8 +342,6 @@ int main(int argc, char **argv) { connection.setVerifier(verifier); } - t1 = std::chrono::system_clock::now(); - http::ReadBytesCallbackImplementation readBytesCallback(conf.file_name, yetDownloaded); diff --git a/apps/hiperf/CMakeLists.txt b/apps/hiperf/CMakeLists.txt index 564525e67..6986c90aa 100644 --- a/apps/hiperf/CMakeLists.txt +++ b/apps/hiperf/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -12,6 +12,9 @@ # limitations under the License. if (NOT DISABLE_EXECUTABLES) +############################################################## +# Source files +############################################################## list(APPEND HIPERF_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/client.cc ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc @@ -19,26 +22,40 @@ if (NOT DISABLE_EXECUTABLES) ${CMAKE_CURRENT_SOURCE_DIR}/src/forwarder_interface.cc ) + +############################################################## +# Libraries +############################################################## list (APPEND HIPERF_LIBRARIES - ${LIBTRANSPORT_LIBRARIES} - ${LIBHICNCTRL_LIBRARIES} - ${LIBHICN_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${LIBCONFIG_CPP_LIBRARIES} - ${WSOCK32_LIBRARY} - ${WS2_32_LIBRARY} + PRIVATE ${LIBTRANSPORT_LIBRARIES} + PRIVATE ${LIBHICNCTRL_LIBRARIES} + PRIVATE ${LIBHICN_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} + PRIVATE ${LIBCONFIG_CPP_LIBRARIES} + PRIVATE ${WSOCK32_LIBRARY} + PRIVATE ${WS2_32_LIBRARY} + ) + +############################################################## +# Compiler options +############################################################## + set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} ) + +############################################################## +# Build hiperf +############################################################## build_executable(hiperf SOURCES ${HIPERF_SRC} LINK_LIBRARIES ${HIPERF_LIBRARIES} INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/src - ${LIBTRANSPORT_INCLUDE_DIRS} - ${LIBHICNCTRL_INCLUDE_DIRS} - ${LIBCONFIG_CPP_INCLUDE_DIRS} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src + PRIVATE ${LIBCONFIG_CPP_INCLUDE_DIRS} DEPENDS ${DEPENDENCIES} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif()
\ No newline at end of file diff --git a/apps/hiperf/src/client.cc b/apps/hiperf/src/client.cc index 820ebf0ce..319fa82ab 100644 --- a/apps/hiperf/src/client.cc +++ b/apps/hiperf/src/client.cc @@ -31,17 +31,12 @@ class Callback; * Hiperf client class: configure and setup an hicn consumer following the * ClientConfiguration. */ -class HIperfClient::Impl -#ifdef FORWARDER_INTERFACE - : ForwarderInterface::ICallback -#endif -{ - typedef std::chrono::time_point<std::chrono::steady_clock> Time; - typedef std::chrono::microseconds TimeDuration; - +class HIperfClient::Impl : ForwarderInterface::ICallback { friend class Callback; friend class RTCCallback; + static const constexpr uint16_t log2_header_counter = 4; + struct nack_packet_t { uint64_t timestamp; uint32_t prod_rate; @@ -76,21 +71,29 @@ class HIperfClient::Impl delay_sample_(0), received_bytes_(0), received_data_pkt_(0), + auth_alerts_(0), data_delays_(""), signals_(io_service_), rtc_callback_(*this), callback_(*this), socket_(io_service_), - done_(false), - switch_threshold_(~0) -#ifdef FORWARDER_INTERFACE - , - forwarder_interface_(io_service_, this) -#endif - { + // switch_threshold_(~0), + fwd_connected_(false), + use_bestpath_(false), + rtt_threshold_(~0), + loss_threshold_(~0), + prefix_name_(""), + prefix_len_(0), + // done_(false), + header_counter_mask_((1 << log2_header_counter) - 1), + header_counter_(0), + print_headers_(configuration_.print_headers_), + first_(true), + forwarder_interface_(io_service_) { + setForwarderConnection(conf.forwarder_type_); } - ~Impl() {} + virtual ~Impl() {} void checkReceivedRtcContent(ConsumerSocket &c, const ContentObject &contentObject) {} @@ -104,174 +107,187 @@ class HIperfClient::Impl void handleTimerExpiration(ConsumerSocket &c, const TransportStatistics &stats) { const char separator = ' '; - const int width = 15; + const int width = 18; - utils::TimePoint t2 = utils::SteadyClock::now(); - auto exact_duration = - std::chrono::duration_cast<utils::Milliseconds>(t2 - t_stats_); + utils::SteadyTime::TimePoint t2 = utils::SteadyTime::Clock::now(); + auto exact_duration = utils::SteadyTime::getDurationMs(t_stats_, t2); - std::stringstream interval; - interval << total_duration_milliseconds_ / 1000 << "-" - << total_duration_milliseconds_ / 1000 + - exact_duration.count() / 1000; + std::stringstream interval_ms; + interval_ms << total_duration_milliseconds_ << "-" + << total_duration_milliseconds_ + exact_duration.count(); std::stringstream bytes_transferred; bytes_transferred << std::fixed << std::setprecision(3) << (stats.getBytesRecv() - old_bytes_value_) / 1000000.0 - << std::setfill(separator) << "[MB]"; + << std::setfill(separator); std::stringstream bandwidth; bandwidth << ((stats.getBytesRecv() - old_bytes_value_) * 8) / (exact_duration.count()) / 1000.0 - << std::setfill(separator) << "[Mbps]"; + << std::setfill(separator); std::stringstream window; - window << stats.getAverageWindowSize() << std::setfill(separator) - << "[Int]"; + window << stats.getAverageWindowSize() << std::setfill(separator); std::stringstream avg_rtt; - avg_rtt << stats.getAverageRtt() << std::setfill(separator) << "[ms]"; + avg_rtt << stats.getAverageRtt() << std::setfill(separator); if (configuration_.rtc_) { - // we get rtc stats more often, thus we need ms in the interval - std::stringstream interval_ms; - interval_ms << total_duration_milliseconds_ << "-" - << total_duration_milliseconds_ + exact_duration.count(); - std::stringstream lost_data; lost_data << stats.getLostData() - old_lost_data_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream bytes_recovered_data; bytes_recovered_data << stats.getBytesRecoveredData() - old_bytes_recovered_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream definitely_lost_data; definitely_lost_data << stats.getDefinitelyLostData() - old_definitely_lost_data_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream data_delay; - data_delay << avg_data_delay_ << std::setfill(separator) << "[ms]"; + data_delay << std::fixed << std::setprecision(3) << avg_data_delay_ + << std::setfill(separator); std::stringstream received_data_pkt; - received_data_pkt << received_data_pkt_ << std::setfill(separator) - << "[pkt]"; + received_data_pkt << received_data_pkt_ << std::setfill(separator); std::stringstream goodput; - goodput << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0 - << std::setfill(separator) << "[Mbps]"; + goodput << std::fixed << std::setprecision(3) + << (received_bytes_ * 8.0) / (exact_duration.count()) / 1000.0 + << std::setfill(separator); std::stringstream loss_rate; loss_rate << std::fixed << std::setprecision(2) - << stats.getLossRatio() * 100.0 << std::setfill(separator) - << "[%]"; + << stats.getLossRatio() * 100.0 << std::setfill(separator); std::stringstream retx_sent; retx_sent << stats.getRetxCount() - old_retx_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream interest_sent; interest_sent << stats.getInterestTx() - old_sent_int_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream nacks; nacks << stats.getReceivedNacks() - old_received_nacks_value_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream fec_pkt; fec_pkt << stats.getReceivedFEC() - old_fec_pkt_ - << std::setfill(separator) << "[pkt]"; + << std::setfill(separator); std::stringstream queuing_delay; - queuing_delay << stats.getQueuingDelay() << std::setfill(separator) - << "[ms]"; + queuing_delay << std::fixed << std::setprecision(3) + << stats.getQueuingDelay() << std::setfill(separator); -#ifdef FORWARDER_INTERFACE - if (!done_ && stats.getQueuingDelay() >= switch_threshold_ && - total_duration_milliseconds_ > 1000) { - std::cout << "Switching due to queuing delay" << std::endl; - forwarder_interface_.createFaceAndRoutes(backup_routes_); - forwarder_interface_.deleteFaceAndRoutes(main_routes_); - std::swap(backup_routes_, main_routes_); - done_ = true; + std::stringstream residual_losses; + double rl_perc = stats.getResidualLossRate() * 100; + residual_losses << std::fixed << std::setprecision(2) << rl_perc + << std::setfill(separator); + + std::stringstream quality_score; + quality_score << std::fixed << (int)stats.getQualityScore() + << std::setfill(separator); + + std::stringstream alerts; + alerts << stats.getAlerts() << std::setfill(separator); + + std::stringstream auth_alerts; + auth_alerts << auth_alerts_ << std::setfill(separator); + + if (fwd_connected_ && use_bestpath_ && + ((stats.getAverageRtt() > rtt_threshold_) || + ((stats.getResidualLossRate() * 100) > loss_threshold_))) { + forwarder_interface_.setStrategy(prefix_name_, prefix_len_, "bestpath"); } -#endif - // statistics not yet available in the transport - // std::stringstream interest_fec_tx; - // interest_fec_tx << stats.getInterestFecTxCount() - - // old_fec_interest_tx_value_ << std::setfill(separator) << "[pkt]"; - // std::stringstream bytes_fec_recv; - // bytes_fec_recv << stats.getBytesFecRecv() - old_fec_data_rx_value_ - // << std::setfill(separator) << "[bytes]"; - std::cout << std::left << std::setw(width) << "Interval"; - std::cout << std::left << std::setw(width) << "RecvData"; - std::cout << std::left << std::setw(width) << "Bandwidth"; - std::cout << std::left << std::setw(width) << "Goodput"; - std::cout << std::left << std::setw(width) << "LossRate"; - std::cout << std::left << std::setw(width) << "Retr"; - std::cout << std::left << std::setw(width) << "InterestSent"; - std::cout << std::left << std::setw(width) << "ReceivedNacks"; - std::cout << std::left << std::setw(width) << "SyncWnd"; - std::cout << std::left << std::setw(width) << "MinRtt"; - std::cout << std::left << std::setw(width) << "QueuingDelay"; - std::cout << std::left << std::setw(width) << "LostData"; - std::cout << std::left << std::setw(width) << "RecoveredData"; - std::cout << std::left << std::setw(width) << "DefinitelyLost"; - std::cout << std::left << std::setw(width) << "State"; - std::cout << std::left << std::setw(width) << "DataDelay"; - std::cout << std::left << std::setw(width) << "FecPkt" << std::endl; - - std::cout << std::left << std::setw(width) << interval_ms.str(); - std::cout << std::left << std::setw(width) << received_data_pkt.str(); - std::cout << std::left << std::setw(width) << bandwidth.str(); - std::cout << std::left << std::setw(width) << goodput.str(); - std::cout << std::left << std::setw(width) << loss_rate.str(); - std::cout << std::left << std::setw(width) << retx_sent.str(); - std::cout << std::left << std::setw(width) << interest_sent.str(); - std::cout << std::left << std::setw(width) << nacks.str(); - std::cout << std::left << std::setw(width) << window.str(); - std::cout << std::left << std::setw(width) << avg_rtt.str(); - std::cout << std::left << std::setw(width) << queuing_delay.str(); - std::cout << std::left << std::setw(width) << lost_data.str(); - std::cout << std::left << std::setw(width) << bytes_recovered_data.str(); - std::cout << std::left << std::setw(width) << definitely_lost_data.str(); - std::cout << std::left << std::setw(width) << stats.getCCStatus(); - std::cout << std::left << std::setw(width) << data_delay.str(); - std::cout << std::left << std::setw(width) << fec_pkt.str(); + if ((header_counter_ == 0 && print_headers_) || first_) { + std::cout << std::right << std::setw(width) << "Interval[ms]"; + std::cout << std::right << std::setw(width) << "RecvData[pkt]"; + std::cout << std::right << std::setw(width) << "Bandwidth[Mbps]"; + std::cout << std::right << std::setw(width) << "Goodput[Mbps]"; + std::cout << std::right << std::setw(width) << "LossRate[%]"; + std::cout << std::right << std::setw(width) << "Retr[pkt]"; + std::cout << std::right << std::setw(width) << "InterestSent"; + std::cout << std::right << std::setw(width) << "ReceivedNacks"; + std::cout << std::right << std::setw(width) << "SyncWnd[pkt]"; + std::cout << std::right << std::setw(width) << "MinRtt[ms]"; + std::cout << std::right << std::setw(width) << "QueuingDelay[ms]"; + std::cout << std::right << std::setw(width) << "LostData[pkt]"; + std::cout << std::right << std::setw(width) << "RecoveredData"; + std::cout << std::right << std::setw(width) << "DefinitelyLost"; + std::cout << std::right << std::setw(width) << "State"; + std::cout << std::right << std::setw(width) << "DataDelay[ms]"; + std::cout << std::right << std::setw(width) << "FecPkt"; + std::cout << std::right << std::setw(width) << "Congestion"; + std::cout << std::right << std::setw(width) << "ResidualLosses"; + std::cout << std::right << std::setw(width) << "QualityScore"; + std::cout << std::right << std::setw(width) << "Alerts"; + std::cout << std::right << std::setw(width) << "AuthAlerts" + << std::endl; + + first_ = false; + } + + std::cout << std::right << std::setw(width) << interval_ms.str(); + std::cout << std::right << std::setw(width) << received_data_pkt.str(); + std::cout << std::right << std::setw(width) << bandwidth.str(); + std::cout << std::right << std::setw(width) << goodput.str(); + std::cout << std::right << std::setw(width) << loss_rate.str(); + std::cout << std::right << std::setw(width) << retx_sent.str(); + std::cout << std::right << std::setw(width) << interest_sent.str(); + std::cout << std::right << std::setw(width) << nacks.str(); + std::cout << std::right << std::setw(width) << window.str(); + std::cout << std::right << std::setw(width) << avg_rtt.str(); + std::cout << std::right << std::setw(width) << queuing_delay.str(); + std::cout << std::right << std::setw(width) << lost_data.str(); + std::cout << std::right << std::setw(width) << bytes_recovered_data.str(); + std::cout << std::right << std::setw(width) << definitely_lost_data.str(); + std::cout << std::right << std::setw(width) << stats.getCCStatus(); + std::cout << std::right << std::setw(width) << data_delay.str(); + std::cout << std::right << std::setw(width) << fec_pkt.str(); + std::cout << std::right << std::setw(width) << stats.isCongested(); + std::cout << std::right << std::setw(width) << residual_losses.str(); + std::cout << std::right << std::setw(width) << quality_score.str(); + std::cout << std::right << std::setw(width) << alerts.str(); + std::cout << std::right << std::setw(width) << auth_alerts.str(); std::cout << std::endl; if (configuration_.test_mode_) { if (data_delays_.size() > 0) data_delays_.pop_back(); - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - std::cout << now << " DATA-DELAYS:[" << data_delays_ << "]" - << std::endl; + auto now = utils::SteadyTime::nowMs(); + std::cout << std::fixed << std::setprecision(0) << now.count() + << " DATA-DELAYS:[" << data_delays_ << "]" << std::endl; } // statistics not yet available in the transport - // std::cout << std::left << std::setw(width) << interest_fec_tx.str(); - // std::cout << std::left << std::setw(width) << bytes_fec_recv.str(); + // std::cout << std::right << std::setw(width) << interest_fec_tx.str(); + // std::cout << std::right << std::setw(width) << bytes_fec_recv.str(); } else { - std::cout << std::left << std::setw(width) << "Interval"; - std::cout << std::left << std::setw(width) << "Transfer"; - std::cout << std::left << std::setw(width) << "Bandwidth"; - std::cout << std::left << std::setw(width) << "Retr"; - std::cout << std::left << std::setw(width) << "Cwnd"; - std::cout << std::left << std::setw(width) << "AvgRtt" << std::endl; - - std::cout << std::left << std::setw(width) << interval.str(); - std::cout << std::left << std::setw(width) << bytes_transferred.str(); - std::cout << std::left << std::setw(width) << bandwidth.str(); - std::cout << std::left << std::setw(width) << stats.getRetxCount(); - std::cout << std::left << std::setw(width) << window.str(); - std::cout << std::left << std::setw(width) << avg_rtt.str() << std::endl; - std::cout << std::endl; + if ((header_counter_ == 0 && print_headers_) || first_) { + std::cout << std::right << std::setw(width) << "Interval[ms]"; + std::cout << std::right << std::setw(width) << "Transfer[MB]"; + std::cout << std::right << std::setw(width) << "Bandwidth[Mbps]"; + std::cout << std::right << std::setw(width) << "Retr[pkt]"; + std::cout << std::right << std::setw(width) << "Cwnd[Int]"; + std::cout << std::right << std::setw(width) << "AvgRtt[ms]" + << std::endl; + + first_ = false; + } + + std::cout << std::right << std::setw(width) << interval_ms.str(); + std::cout << std::right << std::setw(width) << bytes_transferred.str(); + std::cout << std::right << std::setw(width) << bandwidth.str(); + std::cout << std::right << std::setw(width) << stats.getRetxCount(); + std::cout << std::right << std::setw(width) << window.str(); + std::cout << std::right << std::setw(width) << avg_rtt.str() << std::endl; } + total_duration_milliseconds_ += (uint32_t)exact_duration.count(); old_bytes_value_ = stats.getBytesRecv(); old_lost_data_value_ = stats.getLostData(); @@ -289,9 +305,95 @@ class HIperfClient::Impl received_data_pkt_ = 0; data_delays_ = ""; - t_stats_ = utils::SteadyClock::now(); + t_stats_ = utils::SteadyTime::Clock::now(); + + header_counter_ = (header_counter_ + 1) & header_counter_mask_; + + if (--configuration_.nb_iterations_ == 0) { + // We reached the maximum nb of runs. Stop now. + io_service_.stop(); + } } + bool setForwarderConnection(forwarder_type_t forwarder_type) { + using namespace libconfig; + Config cfg; + + const char *conf_file = getenv("FORWARDER_CONFIG"); + if (!conf_file) return false; + + if ((forwarder_type != HICNLIGHT) && (forwarder_type != HICNLIGHT_NG)) + return false; + + try { + cfg.readFile(conf_file); + } catch (const FileIOException &fioex) { + std::cerr << "I/O error while reading file." << std::endl; + return false; + } catch (const ParseException &pex) { + std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine() + << " - " << pex.getError() << std::endl; + return false; + } + + Setting &config = cfg.getRoot(); + + /* conf file example + * + * use_bestpath = "ON | OFF" + * rtt_threshold = 200 //ms + * loss_threshold = 20 //% + * name = "b001::/16" + */ + + if (config.exists("use_bestpath")) { + std::string val; + config.lookupValue("use_bestpath", val); + if (val.compare("ON") == 0) use_bestpath_ = true; + } + + if (config.exists("rtt_threshold")) { + unsigned val; + config.lookupValue("rtt_threshold", val); + rtt_threshold_ = val; + } + + if (config.exists("loss_threshold")) { + unsigned val; + config.lookupValue("loss_threshold", val); + loss_threshold_ = val; + } + + if (config.exists("name")) { + std::string route; + config.lookupValue("name", route); + + std::string delimiter = "/"; + size_t pos = 0; + + if ((pos = route.find(delimiter)) != std::string::npos) { + prefix_name_ = route.substr(0, pos); + route.erase(0, pos + delimiter.length()); + prefix_len_ = std::stoul(route.substr(0)); + } + } + + forwarder_interface_.initForwarderInterface(this, forwarder_type); + + return true; + } + + void onHicnServiceReady() override { + std::cout << "Successfully connected to local forwarder!" << std::endl; + fwd_connected_ = true; + } + + void onRouteConfigured( + std::vector<ForwarderInterface::RouteInfoPtr> &route_info) override { + std::cout << "Routes successfully configured!" << std::endl; + } + +#ifdef FORWARDER_INTERFACE bool parseConfig(const char *conf_file) { using namespace libconfig; Config cfg; @@ -439,7 +541,6 @@ class HIperfClient::Impl return true; } -#ifdef FORWARDER_INTERFACE void onHicnServiceReady() override { std::cout << "Successfully connected to local forwarder!" << std::endl; @@ -541,6 +642,13 @@ class HIperfClient::Impl } #endif + transport::auth::VerificationPolicy onAuthFailed( + transport::auth::Suffix suffix, + transport::auth::VerificationPolicy policy) { + auth_alerts_++; + return transport::auth::VerificationPolicy::ACCEPT; + } + int setup() { int ret; @@ -557,6 +665,7 @@ class HIperfClient::Impl producer_socket_ = std::make_unique<ProducerSocket>(production_protocol); producer_socket_->registerPrefix(configuration_.relay_name_); producer_socket_->connect(); + producer_socket_->start(); } if (configuration_.output_stream_mode_ && configuration_.rtc_) { @@ -586,6 +695,17 @@ class HIperfClient::Impl GeneralTransportOptions::INTEREST_LIFETIME, configuration_.interest_lifetime_); + consumer_socket_->setSocketOption( + GeneralTransportOptions::MAX_UNVERIFIED_TIME, + configuration_.unverified_delay_); + + if (consumer_socket_->setSocketOption( + GeneralTransportOptions::PACKET_FORMAT, + configuration_.packet_format_) == SOCKET_OPTION_NOT_SET) { + std::cerr << "ERROR -- Impossible to set the packet format." << std::endl; + return ERROR_SETUP; + } + #if defined(DEBUG) && defined(__linux__) std::shared_ptr<transport::BasePortal> portal; consumer_socket_->getSocketOption(GeneralTransportOptions::PORTAL, portal); @@ -623,20 +743,24 @@ class HIperfClient::Impl } } + std::shared_ptr<Verifier> verifier = std::make_shared<VoidVerifier>(); + if (!configuration_.producer_certificate.empty()) { - std::shared_ptr<Verifier> verifier = std::make_shared<AsymmetricVerifier>( + verifier = std::make_shared<AsymmetricVerifier>( configuration_.producer_certificate); - if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER, - verifier) == SOCKET_OPTION_NOT_SET) - return ERROR_SETUP; } if (!configuration_.passphrase.empty()) { - std::shared_ptr<Verifier> verifier = - std::make_shared<SymmetricVerifier>(configuration_.passphrase); - if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER, - verifier) == SOCKET_OPTION_NOT_SET) - return ERROR_SETUP; + verifier = std::make_shared<SymmetricVerifier>(configuration_.passphrase); + } + + verifier->setVerificationFailedCallback( + std::bind(&HIperfClient::Impl::onAuthFailed, this, + std::placeholders::_1, std::placeholders::_2)); + + if (consumer_socket_->setSocketOption(GeneralTransportOptions::VERIFIER, + verifier) == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; } ret = consumer_socket_->setSocketOption( @@ -662,6 +786,65 @@ class HIperfClient::Impl } if (configuration_.rtc_) { + if (configuration_.recovery_strategy_ == 1) { // unreliable + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::RECOVERY_OFF); + } else if (configuration_.recovery_strategy_ == 2) { // rtx only + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::RTX_ONLY); + } else if (configuration_.recovery_strategy_ == 3) { // fec only + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::FEC_ONLY); + } else if (configuration_.recovery_strategy_ == 4) { // delay based + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::DELAY_BASED); + } else if (configuration_.recovery_strategy_ == 5) { // low rate flow + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE); + } else if (configuration_.recovery_strategy_ == + 6) { // low rate + bestpath + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE_AND_BESTPATH); + } else if (configuration_.recovery_strategy_ == + 7) { // low rate + replication + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::LOW_RATE_AND_REPLICATION); + } else if (configuration_.recovery_strategy_ == + 8) { // low rate + bestpath or replication + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies:: + LOW_RATE_AND_ALL_FWD_STRATEGIES); + } else { + // default + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::RECOVERY_STRATEGY, + (uint32_t)RtcTransportRecoveryStrategies::RTX_ONLY); + } + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { + ret = consumer_socket_->setSocketOption( + RtcTransportOptions::AGGREGATED_DATA, + configuration_.aggregated_data_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { ret = consumer_socket_->setSocketOption( ConsumerCallbacksOptions::CONTENT_OBJECT_INPUT, (ConsumerContentObjectCallback)std::bind( @@ -673,6 +856,15 @@ class HIperfClient::Impl } if (configuration_.rtc_) { + ret = consumer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE, + configuration_.fec_type_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { std::shared_ptr<TransportStatistics> transport_stats; consumer_socket_->getSocketOption( OtherOptions::STATISTICS, (TransportStatistics **)&transport_stats); @@ -708,10 +900,10 @@ class HIperfClient::Impl signals_.async_wait( [this](const std::error_code &, const int &) { io_service_.stop(); }); - t_download_ = t_stats_ = std::chrono::steady_clock::now(); - consumer_socket_->asyncConsume(configuration_.name); - io_service_.run(); + t_download_ = t_stats_ = utils::SteadyTime::now(); + consumer_socket_->consume(configuration_.name); + io_service_.run(); consumer_socket_->stop(); return ERROR_SUCCESS; @@ -719,11 +911,15 @@ class HIperfClient::Impl private: class RTCCallback : public ConsumerSocket::ReadCallback { - static constexpr std::size_t mtu = 1500; + static constexpr std::size_t mtu = HIPERF_MTU; public: RTCCallback(Impl &hiperf_client) : client_(hiperf_client) { client_.configuration_.receive_buffer = utils::MemBuf::create(mtu); + Packet::Format format = + PayloadSize::getFormatFromName(client_.configuration_.name, false); + payload_size_max_ = + PayloadSize(format).getPayloadSizeMax(RTC_HEADER_SIZE); } bool isBufferMovable() noexcept override { return false; } @@ -743,9 +939,7 @@ class HIperfClient::Impl uint64_t *senderTimeStamp = (uint64_t *)client_.configuration_.receive_buffer->writableData(); - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + auto now = utils::SystemTime::nowMs().count(); double new_delay = (double)(now - *senderTimeStamp); if (*senderTimeStamp > now) @@ -765,7 +959,7 @@ class HIperfClient::Impl client_.producer_socket_->produceDatagram( client_.configuration_.relay_name_.getName(), client_.configuration_.receive_buffer->writableData(), - length < 1400 ? length : 1400); + length < payload_size_max_ ? length : payload_size_max_); } if (client_.configuration_.output_stream_mode_) { uint8_t *start = @@ -778,7 +972,7 @@ class HIperfClient::Impl size_t maxBufferSize() const override { return mtu; } - void readError(const std::error_code ec) noexcept override { + void readError(const std::error_code &ec) noexcept override { std::cerr << "Error while reading from RTC socket" << std::endl; client_.io_service_.stop(); } @@ -789,6 +983,7 @@ class HIperfClient::Impl private: Impl &client_; + std::size_t payload_size_max_; }; class Callback : public ConsumerSocket::ReadCallback { @@ -816,16 +1011,15 @@ class HIperfClient::Impl return client_.configuration_.receive_buffer_size_; } - void readError(const std::error_code ec) noexcept override { + void readError(const std::error_code &ec) noexcept override { std::cerr << "Error " << ec.message() << " while reading from socket" << std::endl; client_.io_service_.stop(); } void readSuccess(std::size_t total_size) noexcept override { - Time t2 = std::chrono::steady_clock::now(); - TimeDuration dt = - std::chrono::duration_cast<TimeDuration>(t2 - client_.t_download_); + auto t2 = utils::SteadyTime::now(); + auto dt = utils::SteadyTime::getDurationUs(client_.t_download_, t2); long usec = (long)dt.count(); std::cout << "Content retrieved. Size: " << total_size << " [Bytes]" @@ -843,8 +1037,8 @@ class HIperfClient::Impl }; hiperf::ClientConfiguration configuration_; - Time t_stats_; - Time t_download_; + utils::SteadyTime::TimePoint t_stats_; + utils::SteadyTime::TimePoint t_download_; uint32_t total_duration_milliseconds_; uint64_t old_bytes_value_; uint64_t old_interest_tx_value_; @@ -865,6 +1059,7 @@ class HIperfClient::Impl uint32_t received_bytes_; uint32_t received_data_pkt_; + uint32_t auth_alerts_; std::string data_delays_; @@ -878,19 +1073,44 @@ class HIperfClient::Impl asio::ip::udp::endpoint remote_; ForwarderConfiguration config_; - uint16_t switch_threshold_; /* ms */ - bool done_; + // uint16_t switch_threshold_; /* ms */ + bool fwd_connected_; + bool use_bestpath_; + uint32_t rtt_threshold_; /* ms */ + uint32_t loss_threshold_; /* ms */ + std::string prefix_name_; // bestpath route + uint32_t prefix_len_; + // bool done_; + std::vector<ForwarderInterface::RouteInfoPtr> main_routes_; std::vector<ForwarderInterface::RouteInfoPtr> backup_routes_; -#ifdef FORWARDER_INTERFACE + uint16_t header_counter_mask_; + uint16_t header_counter_; + + bool print_headers_; + bool first_; + ForwarderInterface forwarder_interface_; -#endif }; HIperfClient::HIperfClient(const ClientConfiguration &conf) { impl_ = new Impl(conf); } +HIperfClient::HIperfClient(HIperfClient &&other) { + impl_ = other.impl_; + other.impl_ = nullptr; +} + +HIperfClient &HIperfClient::operator=(HIperfClient &&other) { + if (this != &other) { + impl_ = other.impl_; + other.impl_ = nullptr; + } + + return *this; +} + HIperfClient::~HIperfClient() { delete impl_; } int HIperfClient::setup() { return impl_->setup(); } diff --git a/apps/hiperf/src/client.h b/apps/hiperf/src/client.h index f45b9af43..bc80c874c 100644 --- a/apps/hiperf/src/client.h +++ b/apps/hiperf/src/client.h @@ -16,12 +16,16 @@ #pragma once #include <common.h> +#include <hicn/transport/utils/noncopyable.h> namespace hiperf { -class HIperfClient { +class HIperfClient : ::utils::NonCopyable { public: HIperfClient(const ClientConfiguration &conf); + HIperfClient(HIperfClient &&other); + HIperfClient &operator=(HIperfClient &&other); + ~HIperfClient(); int setup(); void run(); diff --git a/apps/hiperf/src/common.h b/apps/hiperf/src/common.h index e6ba526f9..13c9dcc1d 100644 --- a/apps/hiperf/src/common.h +++ b/apps/hiperf/src/common.h @@ -15,7 +15,7 @@ #pragma once -#include <hicn/transport/auth/identity.h> +#include <forwarder_interface.h> #include <hicn/transport/auth/signer.h> #include <hicn/transport/config.h> #include <hicn/transport/core/content_object.h> @@ -45,6 +45,9 @@ #endif #define ERROR_SETUP -5 #define MIN_PROBE_SEQ 0xefffffff +#define RTC_HEADER_SIZE 12 +#define FEC_HEADER_MAX_SIZE 36 +#define HIPERF_MTU 1500 using namespace transport::interface; using namespace transport::auth; @@ -73,11 +76,51 @@ static inline uint64_t _htonll(const uint64_t *input) { namespace hiperf { /** + * Class to retrieve the maximum payload size given the MTU and packet headers. + */ +class PayloadSize { + public: + PayloadSize(Packet::Format format, std::size_t mtu = HIPERF_MTU) + : mtu_(mtu), format_(format) {} + + std::size_t getPayloadSizeMax(std::size_t transport_size = 0, + std::size_t fec_size = 0, + std::size_t signature_size = 0) { + return mtu_ - Packet::getHeaderSizeFromFormat(format_, signature_size) - + transport_size - fec_size; + } + + static Packet::Format getFormatFromName(Name name, bool ah = false) { + switch (name.getAddressFamily()) { + case AF_INET: + return ah ? HF_INET_TCP_AH : HF_INET_TCP; + case AF_INET6: + return ah ? HF_INET6_TCP_AH : HF_INET6_TCP; + default: + return HF_UNSPEC; + } + } + + private: + std::size_t mtu_; + Packet::Format format_; +}; + +/** * Class for handling the production rate for the RTC producer. */ class Rate { public: Rate() : rate_kbps_(0) {} + ~Rate() {} + + Rate &operator=(const Rate &other) { + if (this != &other) { + rate_kbps_ = other.rate_kbps_; + } + + return *this; + } Rate(const std::string &rate) { std::size_t found = rate.find("kbps"); @@ -137,9 +180,16 @@ struct ClientConfiguration { secure_(false), producer_prefix_(), interest_lifetime_(500), + unverified_delay_(2000), relay_name_("c001::abcd/64"), output_stream_mode_(false), - port_(0) {} + port_(0), + recovery_strategy_(4), + aggregated_data_(false), + fec_type_(""), + packet_format_(default_values::packet_format), + print_headers_(true), + nb_iterations_(std::numeric_limits<decltype(nb_iterations_)>::max()) {} Name name; double beta; @@ -158,9 +208,17 @@ struct ClientConfiguration { bool secure_; Prefix producer_prefix_; uint32_t interest_lifetime_; + uint32_t unverified_delay_; Prefix relay_name_; bool output_stream_mode_; uint16_t port_; + uint32_t recovery_strategy_; + bool aggregated_data_; + std::string fec_type_; + Packet::Format packet_format_; + bool print_headers_; + std::uint32_t nb_iterations_; + forwarder_type_t forwarder_type_; }; /** @@ -170,11 +228,11 @@ struct ServerConfiguration { ServerConfiguration() : name("b001::abcd/64"), virtual_producer(true), - manifest(false), + manifest(0), live_production(false), content_lifetime(600000000_U32), download_size(20 * 1024 * 1024), - hash_algorithm(CryptoHashType::SHA256), + hash_algorithm_(CryptoHashType::SHA256), keystore_name(""), passphrase(""), keystore_password("cisco"), @@ -185,18 +243,21 @@ struct ServerConfiguration { trace_index_(0), trace_file_(nullptr), production_rate_(std::string("2048kbps")), - payload_size_(1400), + payload_size_(1384), secure_(false), input_stream_mode_(false), - port_(0) {} + port_(0), + aggregated_data_(false), + fec_type_(""), + packet_format_(default_values::packet_format) {} Prefix name; bool virtual_producer; - bool manifest; + std::uint32_t manifest; bool live_production; std::uint32_t content_lifetime; std::uint32_t download_size; - CryptoHashType hash_algorithm; + CryptoHashType hash_algorithm_; std::string keystore_name; std::string passphrase; std::string keystore_password; @@ -212,6 +273,9 @@ struct ServerConfiguration { bool input_stream_mode_; uint16_t port_; std::vector<struct packet_t> trace_; + bool aggregated_data_; + std::string fec_type_; + Packet::Format packet_format_; }; } // namespace hiperf diff --git a/apps/hiperf/src/forwarder_config.h b/apps/hiperf/src/forwarder_config.h index 655ac3b66..aaac14839 100644 --- a/apps/hiperf/src/forwarder_config.h +++ b/apps/hiperf/src/forwarder_config.h @@ -94,4 +94,4 @@ class ForwarderConfiguration { std::size_t n_threads_; }; -}
\ No newline at end of file +} // namespace hiperf
\ No newline at end of file diff --git a/apps/hiperf/src/forwarder_interface.cc b/apps/hiperf/src/forwarder_interface.cc index 864208239..e87a5953d 100644 --- a/apps/hiperf/src/forwarder_interface.cc +++ b/apps/hiperf/src/forwarder_interface.cc @@ -25,6 +25,7 @@ extern "C" { #include <hicn/error.h> #include <hicn/util/ip_address.h> +#include <hicn/util/sstrncpy.h> } // XXX the main listener should be retrieve in this class at initialization, aka @@ -36,27 +37,14 @@ extern "C" { namespace hiperf { +ForwarderInterface::ForwarderInterface(asio::io_service &io_service) + : external_ioservice_(io_service), timer_(io_service) {} + ForwarderInterface::ForwarderInterface(asio::io_service &io_service, - ICallback *callback) - : external_ioservice_(io_service), - forwarder_interface_callback_(callback), - work_(std::make_unique<asio::io_service::work>(internal_ioservice_)), - sock_(nullptr), - thread_(std::make_unique<std::thread>([this]() { - std::cout << "Starting Forwarder Interface thread" << std::endl; - internal_ioservice_.run(); - std::cout << "Stopping Forwarder Interface thread" << std::endl; - })), - // set_route_callback_(std::forward<Callback &&>(setRouteCallback)), - check_routes_timer_(nullptr), - pending_add_route_counter_(0), - hicn_listen_port_(9695), - /* We start in disabled state even when a forwarder is always available */ - state_(State::Disabled), - timer_(io_service), - num_reattempts(0) { - std::cout << "Forwarder interface created... connecting to forwarder...\n"; - internal_ioservice_.post([this]() { onHicnServiceAvailable(true); }); + ICallback *callback, + forwarder_type_t fwd_type) + : external_ioservice_(io_service), timer_(io_service) { + initForwarderInterface(callback, fwd_type); } ForwarderInterface::~ForwarderInterface() { @@ -72,8 +60,27 @@ ForwarderInterface::~ForwarderInterface() { thread_->join(); } +} - std::cout << "ForwarderInterface::~ForwarderInterface" << std::endl; +void ForwarderInterface::initForwarderInterface(ICallback *callback, + forwarder_type_t fwd_type) { + forwarder_interface_callback_ = callback; + work_ = std::make_unique<asio::io_service::work>(internal_ioservice_); + sock_ = nullptr; + thread_ = std::make_unique<std::thread>([this]() { + std::cout << "Starting Forwarder Interface thread" << std::endl; + internal_ioservice_.run(); + std::cout << "Stopping Forwarder Interface thread" << std::endl; + }); + check_routes_timer_ = nullptr; + pending_add_route_counter_ = 0; + hicn_listen_port_ = 9695; + /* We start in disabled state even when a forwarder is always available */ + state_ = State::Disabled; + fwd_type_ = fwd_type; + num_reattempts = 0; + std::cout << "Forwarder interface created... connecting to forwarder...\n"; + internal_ioservice_.post([this]() { onHicnServiceAvailable(true); }); } void ForwarderInterface::onHicnServiceAvailable(bool flag) { @@ -93,26 +100,15 @@ void ForwarderInterface::onHicnServiceAvailable(bool flag) { std::cout << "Connected to forwarder... cancelling reconnection timer" << std::endl; + timer_.cancel(); num_reattempts = 0; - // case State::Connected: - // checkListener(); - - // if (state_ != State::Ready) { - // std::cout << "Listener not found" << std::endl; - // goto REATTEMPT; - // } - // state_ = State::Ready; - - // timer_.cancel(); - // num_reattempts = 0; - std::cout << "Forwarder interface is ready... communicate to controller" << std::endl; forwarder_interface_callback_->onHicnServiceReady(); - + case State::Connected: case State::Ready: break; } @@ -136,14 +132,14 @@ REATTEMPT: std::chrono::milliseconds(ForwarderInterface::REATTEMPT_DELAY_MS)); // timer_.async_wait(std::bind(&ForwarderInterface::onHicnServiceAvailable, // this, flag, std::placeholders::_1)); - timer_.async_wait([this, flag](std::error_code ec) { + timer_.async_wait([this, flag](const std::error_code &ec) { if (ec) return; onHicnServiceAvailable(flag); }); } int ForwarderInterface::connectToForwarder() { - sock_ = hc_sock_create(); + sock_ = hc_sock_create_forwarder(fwd_type_); if (!sock_) { std::cout << "Could not create socket" << std::endl; goto ERR_SOCK; @@ -256,6 +252,27 @@ void ForwarderInterface::deleteFaceAndRoutes( }); } +void ForwarderInterface::setStrategy(std::string prefix, uint32_t prefix_len, + std::string strategy) { + if (!sock_) return; + + ip_address_t ip_prefix; + if (ip_address_pton(prefix.c_str(), &ip_prefix) < 0) { + return; + } + + strategy_type_t strategy_type = strategy_type_from_str(strategy.c_str()); + if (strategy_type == STRATEGY_TYPE_UNDEFINED) return; + + hc_strategy_t strategy_conf; + strategy_conf.address = ip_prefix; + strategy_conf.len = prefix_len; + strategy_conf.family = AF_INET6; + strategy_conf.type = strategy_type; + + hc_strategy_set(sock_, &strategy_conf); +} + void ForwarderInterface::internalDeleteFaceAndRoute( const RouteInfoPtr &route_info) { if (!sock_) return; @@ -346,10 +363,11 @@ void ForwarderInterface::internalCreateFaceAndRoutes( } max_try--; timer->expires_from_now(std::chrono::milliseconds(500)); - timer->async_wait([this, failed, max_try, timer](std::error_code ec) { - if (ec) return; - internalCreateFaceAndRoutes(failed, max_try, timer); - }); + timer->async_wait( + [this, failed, max_try, timer](const std::error_code &ec) { + if (ec) return; + internalCreateFaceAndRoutes(failed, max_try, timer); + }); return; } @@ -422,16 +440,18 @@ int ForwarderInterface::tryToCreateFace(RouteInfo *route_info, std::string name = "l_" + route_info->name; listener.local_addr = local_address; - listener.type = CONNECTION_TYPE_UDP; + listener.type = FACE_TYPE_UDP; listener.family = AF_INET; listener.local_port = route_info->local_port; - strncpy(listener.name, name.c_str(), sizeof(listener.name)); - strncpy(listener.interface_name, route_info->interface.c_str(), - sizeof(listener.interface_name)); + int ret = strcpy_s(listener.name, SYMBOLIC_NAME_LEN - 1, name.c_str()); + if (ret < EOK) goto ERR; + ret = strcpy_s(listener.interface_name, INTERFACE_LEN - 1, + route_info->interface.c_str()); + if (ret < EOK) goto ERR; std::cout << "------------> " << route_info->interface << std::endl; - int ret = hc_listener_create(sock_, &listener); + ret = hc_listener_create(sock_, &listener); if (ret < 0) { std::cerr << "Error creating listener." << std::endl; @@ -520,7 +540,7 @@ int ForwarderInterface::tryToCreateRoute(RouteInfo *route_info, #if 0 // not used void ForwarderInterface::checkRoutesLoop() { check_routes_timer_->expires_from_now(std::chrono::milliseconds(1000)); - check_routes_timer_->async_wait([this](std::error_code ec) { + check_routes_timer_->async_wait([this](const std::error_code &ec) { if (ec) return; if (pending_add_route_counter_ == 0) checkRoutes(); }); @@ -580,7 +600,7 @@ void ForwarderInterface::checkRoutes() { } else { // XXX This should be moved somewhere else getMainListener( - [this](std::error_code ec, uint32_t hicn_listen_port) { + [this](const std::error_code &ec, uint32_t hicn_listen_port) { if (!ec) { hicn_listen_port_ = hicn_listen_port; @@ -597,7 +617,7 @@ void ForwarderInterface::checkRoutes() { tryToConnectToForwarder(); } private: - void doGetMainListener(std::error_code ec) + void doGetMainListener(const std::error_code &ec) { if (!ec) { @@ -607,7 +627,7 @@ void ForwarderInterface::checkRoutes() { { // Since without the main listener of the forwarder the proxy cannot // work, we can stop the program here until we get the listener port. - std::cout << + std::cout << "Could not retrieve main listener port from the forwarder. " "Retrying."; @@ -635,7 +655,7 @@ void ForwarderInterface::checkRoutes() { doTryToConnectToForwarder(std::make_error_code(std::errc(0))); } - void doTryToConnectToForwarder(std::error_code ec) + void doTryToConnectToForwarder(const std::error_code &ec) { if (!ec) { @@ -673,4 +693,4 @@ void ForwarderInterface::checkRoutes() { constexpr uint32_t ForwarderInterface::REATTEMPT_DELAY_MS; constexpr uint32_t ForwarderInterface::MAX_REATTEMPT; -} // namespace hiperf
\ No newline at end of file +} // namespace hiperf diff --git a/apps/hiperf/src/forwarder_interface.h b/apps/hiperf/src/forwarder_interface.h index 7591ea257..e58989295 100644 --- a/apps/hiperf/src/forwarder_interface.h +++ b/apps/hiperf/src/forwarder_interface.h @@ -15,6 +15,8 @@ #pragma once +#include <hicn/transport/utils/noncopyable.h> + extern "C" { #ifndef WITH_POLICY #define WITH_POLICY @@ -27,14 +29,13 @@ extern "C" { #define ASIO_STANDALONE #endif #include <asio.hpp> - #include <functional> #include <thread> #include <unordered_map> namespace hiperf { -class ForwarderInterface { +class ForwarderInterface : ::utils::NonCopyable { static const uint32_t REATTEMPT_DELAY_MS = 500; static const uint32_t MAX_REATTEMPT = 10; @@ -68,10 +69,14 @@ class ForwarderInterface { }; public: - ForwarderInterface(asio::io_service &io_service, ICallback *callback); + explicit ForwarderInterface(asio::io_service &io_service); + explicit ForwarderInterface(asio::io_service &io_service, ICallback *callback, + forwarder_type_t fwd_type); ~ForwarderInterface(); + void initForwarderInterface(ICallback *callback, forwarder_type_t fwd_type); + State getState(); void setState(State state); @@ -88,11 +93,16 @@ class ForwarderInterface { void deleteFaceAndRoute(const RouteInfoPtr &route_info); + void setStrategy(std::string prefix, uint32_t prefix_len, + std::string strategy); + void close(); uint16_t getHicnListenerPort() { return hicn_listen_port_; } private: + ForwarderInterface &operator=(const ForwarderInterface &other) = delete; + int connectToForwarder(); int checkListener(); @@ -123,6 +133,8 @@ class ForwarderInterface { State state_; + forwarder_type_t fwd_type_; + /* Reattempt timer */ asio::steady_timer timer_; unsigned num_reattempts; diff --git a/apps/hiperf/src/main.cc b/apps/hiperf/src/main.cc index b2d99c4a4..b69392de8 100644 --- a/apps/hiperf/src/main.cc +++ b/apps/hiperf/src/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -14,13 +14,13 @@ */ #include <client.h> -#include <server.h> #include <forwarder_interface.h> +#include <server.h> namespace hiperf { void usage() { - std::cerr << "HIPERF - A tool for performing network throughput " + std::cerr << "HIPERF - Instrumentation tool for performing active network" "measurements with hICN" << std::endl; std::cerr << "usage: hiperf [-S|-C] [options] [prefix|name]" << std::endl; @@ -34,19 +34,27 @@ void usage() { std::cerr << "-f\t<filename>\t\t\t" << "Log file" << std::endl; std::cerr << "-z\t<io_module>\t\t\t" - << "IO module to use. Default: hicnlight_module" << std::endl; + << "IO module to use. Default: hicnlightng_module" << std::endl; + std::cerr << "-F\t<conf_file>\t\t\t" + << "Path to optional configuration file for libtransport" + << std::endl; + std::cerr << "-a\t\t\t\t\t" + << "Enables data packet aggregation. " + << "Works only in RTC mode" << std::endl; + std::cerr << "-X\t<param>\t\t\t\t" + << "Set FEC params. Options are Rely_K#_N# or RS_K#_N#" + << std::endl; #endif std::cerr << std::endl; std::cerr << "SERVER SPECIFIC:" << std::endl; std::cerr << "-A\t<content_size>\t\t\t" - "Size of the content to publish. This " - "is not the size of the packet (see -s for it)." - << std::endl; - std::cerr << "-s\t<packet_size>\t\t\tSize of the payload of each data packet." + "Sends an application data unit in bytes that is published once " + "before exit" << std::endl; + std::cerr << "-s\t<packet_size>\t\t\tData packet payload size." << std::endl; std::cerr << "-r\t\t\t\t\t" << "Produce real content of <content_size> bytes" << std::endl; - std::cerr << "-m\t\t\t\t\t" + std::cerr << "-m\t<manifest_capacity>\t\t" << "Produce transport manifest" << std::endl; std::cerr << "-l\t\t\t\t\t" << "Start producing content upon the reception of the " @@ -60,20 +68,17 @@ void usage() { << "String from which a 128-bit symmetric key will be " "derived for signing packets" << std::endl; + std::cerr << "-p\t<password>\t\t\t" + << "Password for p12 keystore" << std::endl; std::cerr << "-y\t<hash_algorithm>\t\t" << "Use the selected hash algorithm for " - "calculating manifest digests" + "computing manifest digests (default: SHA256)" << std::endl; - std::cerr << "-p\t<password>\t\t\t" - << "Password for p12 keystore" << std::endl; std::cerr << "-x\t\t\t\t\t" - << "Produce a content of <content_size>, then after downloading " - "it produce a new content of" - << "\n\t\t\t\t\t<content_size> without resetting " - "the suffix to 0." - << std::endl; + << "Produces application data units of size <content_size> " + << "without resetting the name suffix to 0." << std::endl; std::cerr << "-B\t<bitrate>\t\t\t" - << "Bitrate for RTC producer, to be used with the -R option." + << "RTC producer data bitrate, to be used with the -R option." << std::endl; #ifndef _WIN32 std::cerr << "-I\t\t\t\t\t" @@ -92,8 +97,8 @@ void usage() { "file containing the " "crypto material used for the TLS handshake" << std::endl; - std::cerr << "-G\t<port>\t\t\t" - << "input stream from localhost at the specified port" << std::endl; + std::cerr << "-G\t<port>\t\t\t\t" + << "Input stream from localhost at the specified port" << std::endl; #endif std::cerr << std::endl; std::cerr << "CLIENT SPECIFIC:" << std::endl; @@ -105,6 +110,8 @@ void usage() { << std::endl; std::cerr << "-L\t<interest lifetime>\t\t" << "Set interest lifetime." << std::endl; + std::cerr << "-u\t<delay>\t\t\t\t" + << "Set max lifetime of unverified packets." << std::endl; std::cerr << "-M\t<input_buffer_size>\t\t" << "Size of consumer input buffer. If 0, reassembly of packets " "will be disabled." @@ -127,17 +134,31 @@ void usage() { std::cerr << "-t\t\t\t\t\t" "Test mode, check if the client is receiving the " "correct data. This is an RTC specific option, to be " - "used with the -R (default false)" + "used with the -R (default: false)" << std::endl; std::cerr << "-P\t\t\t\t\t" << "Prefix of the producer where to do the handshake" << std::endl; std::cerr << "-j\t<relay_name>\t\t\t" - << "Publish the received content under the name relay_name." + << "Publish received content under the name relay_name." "This is an RTC specific option, to be " - "used with the -R (default false)" + "used with the -R (default: false)" + << std::endl; + std::cerr << "-g\t<port>\t\t\t\t" + << "Output stream to localhost at the specified port" << std::endl; + std::cerr << "-e\t<strategy>\t\t\t" + << "Enance the network with a realiability strategy. Options 1:" + << " unreliable, 2: rtx only, 3: fec only, " + << "4: delay based, 5: low rate, 6: low rate and best path " + << "7: low rate and replication, 8: low rate and best" + << " path/replication" + << "(default: 2 = rtx only) " << std::endl; + std::cerr << "-H\t\t\t\t\t" + << "Disable periodic print headers in stats report." << std::endl; + std::cerr << "-n\t<nb_iterations>\t\t\t" + << "Print the stats report <nb_iterations> times and exit.\n" + << "\t\t\t\t\tThis option limits the duration of the run to " + "<nb_iterations> * <stats_interval> milliseconds." << std::endl; - std::cerr << "-g\t<port>\t\t\t" - << "output stream to localhost at the specified port" << std::endl; } int main(int argc, char *argv[]) { @@ -156,7 +177,7 @@ int main(int argc, char *argv[]) { char *log_file = nullptr; transport::interface::global_config::IoModuleConfiguration config; std::string conf_file; - config.name = "hicnlight_module"; + config.name = "hicnlightng_module"; // Consumer ClientConfiguration client_configuration; @@ -166,10 +187,9 @@ int main(int argc, char *argv[]) { int opt; #ifndef _WIN32 - while ((opt = getopt( - argc, argv, - "DSCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:g:G:")) != - -1) { + while ((opt = getopt(argc, argv, + "DSCf:b:d:W:RM:c:vA:s:rm:lK:k:y:p:hi:xE:P:B:ItL:z:T:F:j:" + "g:G:e:awHn:X:u:")) != -1) { switch (opt) { // Common case 'D': { @@ -202,9 +222,11 @@ int main(int argc, char *argv[]) { break; } #else - while ((opt = getopt(argc, argv, - "SCf:b:d:W:RM:c:vA:s:rmlK:k:y:p:hi:xB:E:P:tL:z:F:j:")) != - -1) { + while ( + (opt = getopt( + argc, argv, + "SCf:b:d:W:RM:c:vA:s:rm:lK:k:y:p:hi:xB:E:P:tL:z:F:j:e:awHn:X:u:")) != + -1) { switch (opt) { #endif case 'f': { @@ -216,6 +238,21 @@ int main(int argc, char *argv[]) { server_configuration.rtc_ = true; break; } + case 'a': { + client_configuration.aggregated_data_ = true; + server_configuration.aggregated_data_ = true; + break; + } + case 'X': { + client_configuration.fec_type_ = std::string(optarg); + server_configuration.fec_type_ = std::string(optarg); + break; + } + case 'w': { + client_configuration.packet_format_ = Packet::Format::HF_INET6_UDP; + server_configuration.packet_format_ = Packet::Format::HF_INET6_UDP; + break; + } case 'z': { config.name = optarg; break; @@ -286,12 +323,27 @@ int main(int argc, char *argv[]) { options = 1; break; } + case 'u': { + client_configuration.unverified_delay_ = std::stoul(optarg); + options = 1; + break; + } case 'j': { client_configuration.relay_ = true; client_configuration.relay_name_ = Prefix(optarg); options = 1; break; } + case 'H': { + client_configuration.print_headers_ = false; + options = 1; + break; + } + case 'n': { + client_configuration.nb_iterations_ = std::stoul(optarg); + options = 1; + break; + } // Server specific case 'A': { server_configuration.download_size = std::stoul(optarg); @@ -309,7 +361,7 @@ int main(int argc, char *argv[]) { break; } case 'm': { - server_configuration.manifest = true; + server_configuration.manifest = std::stoul(optarg); options = -1; break; } @@ -324,18 +376,19 @@ int main(int argc, char *argv[]) { break; } case 'y': { + CryptoHashType hash_algorithm = CryptoHashType::SHA256; if (strncasecmp(optarg, "sha256", 6) == 0) { - server_configuration.hash_algorithm = CryptoHashType::SHA256; + hash_algorithm = CryptoHashType::SHA256; } else if (strncasecmp(optarg, "sha512", 6) == 0) { - server_configuration.hash_algorithm = CryptoHashType::SHA512; + hash_algorithm = CryptoHashType::SHA512; } else if (strncasecmp(optarg, "blake2b512", 10) == 0) { - server_configuration.hash_algorithm = CryptoHashType::BLAKE2B512; + hash_algorithm = CryptoHashType::BLAKE2B512; } else if (strncasecmp(optarg, "blake2s256", 10) == 0) { - server_configuration.hash_algorithm = CryptoHashType::BLAKE2S256; + hash_algorithm = CryptoHashType::BLAKE2S256; } else { - std::cerr << "Ignored unknown hash algorithm. Using SHA 256." - << std::endl; + std::cerr << "Unknown hash algorithm. Using SHA 256." << std::endl; } + server_configuration.hash_algorithm_ = hash_algorithm; options = -1; break; } @@ -361,6 +414,11 @@ int main(int argc, char *argv[]) { server_configuration.secure_ = true; break; } + case 'e': { + client_configuration.recovery_strategy_ = std::stoul(optarg); + options = 1; + break; + } case 'h': default: usage(); @@ -430,6 +488,13 @@ int main(int argc, char *argv[]) { transport::interface::global_config::parseConfigurationFile(conf_file); if (role > 0) { + // set forwarder type + client_configuration.forwarder_type_ = UNDEFINED; + if (config.name.compare("hicnlightng_module") == 0) + client_configuration.forwarder_type_ = HICNLIGHT; + else if (config.name.compare("hicnlightng_module") == 0) + client_configuration.forwarder_type_ = HICNLIGHT_NG; + HIperfClient c(client_configuration); if (c.setup() != ERROR_SETUP) { c.run(); diff --git a/apps/hiperf/src/server.cc b/apps/hiperf/src/server.cc index 968d42e2c..7101e7a4a 100644 --- a/apps/hiperf/src/server.cc +++ b/apps/hiperf/src/server.cc @@ -21,7 +21,7 @@ namespace hiperf { * Hiperf server class: configure and setup an hicn producer following the * ServerConfiguration. */ -class HIperfServer::Impl { +class HIperfServer::Impl : public ProducerSocket::Callback { const std::size_t log2_content_object_buffer_size = 8; public: @@ -35,11 +35,8 @@ class HIperfServer::Impl { mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1), last_segment_(0), #ifndef _WIN32 - ptr_last_segment_(&last_segment_), input_(io_service_), rtc_running_(false), -#else - ptr_last_segment_(&last_segment_), #endif flow_name_(configuration_.name.getName()), socket_(io_service_), @@ -54,14 +51,16 @@ class HIperfServer::Impl { #endif for (int i = 0; i < (1 << log2_content_object_buffer_size); i++) { - content_objects_[i] = ContentObject::Ptr( - new ContentObject(conf.name.getName(), HF_INET6_TCP, 0, - (const uint8_t *)buffer.data(), buffer.size())); + content_objects_[i] = ContentObject::Ptr(new ContentObject( + configuration_.name.getName(), configuration_.packet_format_, 0, + (const uint8_t *)buffer.data(), buffer.size())); content_objects_[i]->setLifetime( default_values::content_object_expiry_time); } } + virtual ~Impl() {} + void virtualProcessInterest(ProducerSocket &p, const Interest &interest) { content_objects_[content_objects_index_ & mask_]->setName( interest.getName()); @@ -91,16 +90,14 @@ class HIperfServer::Impl { if (suffix == 0) { last_segment_ = 0; - ptr_last_segment_ = &last_segment_; unsatisfied_interests_.clear(); } - // The suffix will either be the one from the received interest or the - // smallest suffix of a previous interest not satisfed + // The suffix will either come from the received interest or will be set to + // the smallest suffix of a previous interest not satisfied if (!unsatisfied_interests_.empty()) { - auto it = - std::lower_bound(unsatisfied_interests_.begin(), - unsatisfied_interests_.end(), *ptr_last_segment_); + auto it = std::lower_bound(unsatisfied_interests_.begin(), + unsatisfied_interests_.end(), last_segment_); if (it != unsatisfied_interests_.end()) { suffix = *it; } @@ -121,27 +118,28 @@ class HIperfServer::Impl { b->append(configuration_.download_size); uint32_t total; - utils::TimePoint t0 = utils::SteadyClock::now(); + utils::SteadyTime::TimePoint t0 = utils::SteadyTime::Clock::now(); total = p.produceStream(content_name, std::move(b), !configuration_.multiphase_produce_, suffix); - utils::TimePoint t1 = utils::SteadyClock::now(); + utils::SteadyTime::TimePoint t1 = utils::SteadyTime::Clock::now(); - std::cout - << "Written " << total - << " data packets in output buffer (Segmentation time: " - << std::chrono::duration_cast<utils::Microseconds>(t1 - t0).count() - << " us)" << std::endl; + std::cout << "Written " << total + << " data packets in output buffer (Segmentation time: " + << utils::SteadyTime::getDurationUs(t0, t1).count() << " us)" + << std::endl; } void produceContentAsync(ProducerSocket &p, Name content_name, uint32_t suffix) { - auto b = utils::MemBuf::create(configuration_.download_size); - std::memset(b->writableData(), '?', configuration_.download_size); - b->append(configuration_.download_size); - - p.asyncProduce(content_name, std::move(b), - !configuration_.multiphase_produce_, suffix, - &ptr_last_segment_); + produce_thread_.add([this, suffix, content_name]() { + auto b = utils::MemBuf::create(configuration_.download_size); + std::memset(b->writableData(), '?', configuration_.download_size); + b->append(configuration_.download_size); + + last_segment_ = suffix + producer_socket_->produceStream( + content_name, std::move(b), + !configuration_.multiphase_produce_, suffix); + }); } void cacheMiss(ProducerSocket &p, const Interest &interest) { @@ -156,27 +154,22 @@ class HIperfServer::Impl { std::placeholders::_1, std::placeholders::_2)); } - std::shared_ptr<Identity> getProducerIdentity(std::string &keystore_path, - std::string &keystore_pwd, - CryptoHashType &hash_type) { - if (access(keystore_path.c_str(), F_OK) != -1) { - return std::make_shared<Identity>(keystore_path, keystore_pwd, hash_type); - } - return std::make_shared<Identity>(keystore_path, keystore_pwd, - CryptoSuite::RSA_SHA256, 1024, 365, - "producer-test"); + void produceError(const std::error_code &err) noexcept override { + std::cerr << "Error from producer transport: " << err.message() + << std::endl; + producer_socket_->stop(); + io_service_.stop(); } int setup() { int ret; int production_protocol; + std::shared_ptr<Signer> signer = std::make_shared<VoidSigner>(); if (configuration_.secure_) { - auto identity = getProducerIdentity(configuration_.keystore_name, - configuration_.keystore_password, - configuration_.hash_algorithm); producer_socket_ = std::make_unique<P2PSecureProducerSocket>( - configuration_.rtc_, identity); + configuration_.rtc_, configuration_.keystore_name, + configuration_.keystore_password); } else { if (!configuration_.rtc_) { production_protocol = ProductionProtocolAlgorithms::BYTE_STREAM; @@ -188,36 +181,79 @@ class HIperfServer::Impl { } if (producer_socket_->setSocketOption( + ProducerCallbacksOptions::PRODUCER_CALLBACK, this) == + SOCKET_OPTION_NOT_SET) { + std::cerr << "Failed to set producer callback." << std::endl; + return ERROR_SETUP; + } + + if (producer_socket_->setSocketOption( GeneralTransportOptions::MAKE_MANIFEST, configuration_.manifest) == SOCKET_OPTION_NOT_SET) { return ERROR_SETUP; } + if (producer_socket_->setSocketOption( + GeneralTransportOptions::HASH_ALGORITHM, + configuration_.hash_algorithm_) == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + + if (producer_socket_->setSocketOption(PACKET_FORMAT, + configuration_.packet_format_) == + SOCKET_OPTION_NOT_SET) { + std::cerr << "ERROR -- Impossible to set the packet format." << std::endl; + return ERROR_SETUP; + } + if (!configuration_.passphrase.empty()) { - std::shared_ptr<Signer> signer = std::make_shared<SymmetricSigner>( - CryptoSuite::HMAC_SHA256, configuration_.passphrase); - producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, - signer); + signer = std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, + configuration_.passphrase); } if (!configuration_.keystore_name.empty()) { - auto identity = getProducerIdentity(configuration_.keystore_name, - configuration_.keystore_password, - configuration_.hash_algorithm); - std::shared_ptr<Signer> signer = identity->getSigner(); - producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, - signer); + signer = std::make_shared<AsymmetricSigner>( + configuration_.keystore_name, configuration_.keystore_password); + } + + producer_socket_->setSocketOption(GeneralTransportOptions::SIGNER, signer); + + // Compute maximum payload size + Packet::Format format = PayloadSize::getFormatFromName( + configuration_.name.getName(), !configuration_.manifest); + payload_size_max_ = PayloadSize(format).getPayloadSizeMax( + configuration_.rtc_ ? RTC_HEADER_SIZE : 0, + configuration_.fec_type_.empty() ? 0 : FEC_HEADER_MAX_SIZE, + !configuration_.manifest ? signer->getSignatureFieldSize() : 0); + + if (configuration_.payload_size_ > payload_size_max_) { + std::cerr << "WARNING: Payload has size " << configuration_.payload_size_ + << ", maximum is " << payload_size_max_ + << ". Payload will be truncated to fit." << std::endl; + } + + if (configuration_.rtc_) { + ret = producer_socket_->setSocketOption( + RtcTransportOptions::AGGREGATED_DATA, + configuration_.aggregated_data_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + } + + if (configuration_.rtc_) { + ret = producer_socket_->setSocketOption(GeneralTransportOptions::FEC_TYPE, + configuration_.fec_type_); + + if (ret == SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } } - uint32_t rtc_header_size = 0; - if (configuration_.rtc_) rtc_header_size = 12; - producer_socket_->setSocketOption( - GeneralTransportOptions::DATA_PACKET_SIZE, - (uint32_t)( - configuration_.payload_size_ + rtc_header_size + - (configuration_.name.getAddressFamily() == AF_INET ? 40 : 60))); producer_socket_->registerPrefix(configuration_.name); producer_socket_->connect(); + producer_socket_->start(); if (configuration_.rtc_) { std::cout << "Running RTC producer: the prefix length will be ignored." @@ -239,6 +275,13 @@ class HIperfServer::Impl { return ERROR_SETUP; } + if (producer_socket_->setSocketOption( + GeneralTransportOptions::MAX_SEGMENT_SIZE, + static_cast<uint32_t>(configuration_.payload_size_)) == + SOCKET_OPTION_NOT_SET) { + return ERROR_SETUP; + } + if (!configuration_.live_production) { produceContent(*producer_socket_, configuration_.name.getName(), 0); } else { @@ -283,7 +326,7 @@ class HIperfServer::Impl { void receiveStream() { socket_.async_receive_from( asio::buffer(recv_buffer_.first, recv_buffer_.second), remote_, - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (ec) return; sendRTCContentFromStream(recv_buffer_.first, length); receiveStream(); @@ -296,9 +339,8 @@ class HIperfServer::Impl { // this is used to compute the data packet delay // Used only for performance evaluation // It requires clock synchronization between producer and consumer - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + uint64_t now = utils::SystemTime::nowMs().count(); + uint8_t *start = (uint8_t *)payload->writableData(); std::memcpy(start, &now, sizeof(uint64_t)); std::memcpy(start + sizeof(uint64_t), buff, len); @@ -306,7 +348,7 @@ class HIperfServer::Impl { len + sizeof(uint64_t)); } - void sendRTCContentObjectCallback(std::error_code ec) { + void sendRTCContentObjectCallback(const std::error_code &ec) { if (ec) return; rtc_timer_.expires_from_now( configuration_.production_rate_.getMicrosecondsForPacket( @@ -319,18 +361,17 @@ class HIperfServer::Impl { // this is used to compute the data packet delay // Used only for performance evaluation // It requires clock synchronization between producer and consumer - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); + uint64_t now = utils::SystemTime::nowMs().count(); std::memcpy(payload->writableData(), &now, sizeof(uint64_t)); - producer_socket_->produceDatagram( - flow_name_, payload->data(), - payload->length() < 1400 ? payload->length() : 1400); + producer_socket_->produceDatagram(flow_name_, payload->data(), + payload->length() < payload_size_max_ + ? payload->length() + : payload_size_max_); } - void sendRTCContentObjectCallbackWithTrace(std::error_code ec) { + void sendRTCContentObjectCallbackWithTrace(const std::error_code &ec) { if (ec) return; auto payload = @@ -342,14 +383,11 @@ class HIperfServer::Impl { // this is used to compute the data packet delay // used only for performance evaluation // it requires clock synchronization between producer and consumer - uint64_t now = std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::system_clock::now().time_since_epoch()) - .count(); - + uint64_t now = utils::SystemTime::nowMs().count(); std::memcpy(payload->writableData(), &now, sizeof(uint64_t)); if (packet_len > payload->length()) packet_len = payload->length(); - if (packet_len > 1400) packet_len = 1400; + if (packet_len > payload_size_max_) packet_len = payload_size_max_; producer_socket_->produceDatagram(flow_name_, payload->data(), packet_len); @@ -450,13 +488,13 @@ class HIperfServer::Impl { std::placeholders::_1)); } else if (configuration_.input_stream_mode_) { rtc_running_ = true; - // crate socket + // create socket remote_ = asio::ip::udp::endpoint( asio::ip::address::from_string("127.0.0.1"), configuration_.port_); socket_.open(asio::ip::udp::v4()); socket_.bind(remote_); - recv_buffer_.first = (uint8_t *)malloc(1500); - recv_buffer_.second = 1500; + recv_buffer_.first = (uint8_t *)malloc(HIPERF_MTU); + recv_buffer_.second = HIPERF_MTU; receiveStream(); } else { rtc_running_ = true; @@ -490,8 +528,9 @@ class HIperfServer::Impl { std::uint16_t content_objects_index_; std::uint16_t mask_; std::uint32_t last_segment_; - std::uint32_t *ptr_last_segment_; std::unique_ptr<ProducerSocket> producer_socket_; + ::utils::EventThread produce_thread_; + std::size_t payload_size_max_; #ifndef _WIN32 asio::posix::stream_descriptor input_; asio::streambuf input_buffer_; @@ -507,6 +546,20 @@ HIperfServer::HIperfServer(const ServerConfiguration &conf) { impl_ = new Impl(conf); } +HIperfServer::HIperfServer(HIperfServer &&other) { + impl_ = other.impl_; + other.impl_ = nullptr; +} + +HIperfServer &HIperfServer::operator=(HIperfServer &&other) { + if (this != &other) { + impl_ = other.impl_; + other.impl_ = nullptr; + } + + return *this; +} + HIperfServer::~HIperfServer() { delete impl_; } int HIperfServer::setup() { return impl_->setup(); } diff --git a/apps/hiperf/src/server.h b/apps/hiperf/src/server.h index 05407a807..73ac72123 100644 --- a/apps/hiperf/src/server.h +++ b/apps/hiperf/src/server.h @@ -22,6 +22,9 @@ namespace hiperf { class HIperfServer { public: HIperfServer(const ServerConfiguration &conf); + HIperfServer(HIperfServer &&other); + HIperfServer &operator=(HIperfServer &&other); + ~HIperfServer(); int setup(); void run(); diff --git a/apps/http-proxy/CMakeLists.txt b/apps/http-proxy/CMakeLists.txt index 66b9c1bab..dbe9bc51c 100644 --- a/apps/http-proxy/CMakeLists.txt +++ b/apps/http-proxy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,8 +11,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.10 FATAL_ERROR) -set(CMAKE_CXX_STANDARD 14) +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) # -Wno-c99-designator issue # @@ -22,20 +26,22 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string ) string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string}) if (CLANG_VERSION_STRING VERSION_GREATER_EQUAL 11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c99-designator") + list(APPEND COMPILER_OPTIONS + "-Wno-c99-designator" + ) endif() endif() -set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} - "${CMAKE_SOURCE_DIR}/cmake/Modules/" -) -if (NOT CMAKE_BUILD_TYPE) - message(STATUS "${PROJECT_NAME}: No build type selected, default to Release") - set(CMAKE_BUILD_TYPE "Release") -endif () +############################################################## +# Includes subdirectory +############################################################## +add_subdirectory(includes/hicn/http-proxy) + +############################################################## +# Source files +############################################################## set(LIB_SOURCE_FILES src/http_session.cc src/http_proxy.cc @@ -48,41 +54,45 @@ set(APP_SOURCE_FILES main.cc ) -add_subdirectory(includes/hicn/http-proxy) -set(LIBHTTP_PROXY hicnhttpproxy) -set(LIBHTTP_PROXY_STATIC ${LIBHTTP_PROXY}.static) - -list(APPEND COMPILER_DEFINITIONS - -DWITH_POLICY -) - +############################################################## +# Libraries to link +############################################################## list(APPEND HTTP_PROXY_LIBRARIES - ${LIBTRANSPORT_LIBRARIES} - ${LIBHICNCTRL_LIBRARIES} - ${LIBHICN_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} + PUBLIC ${LIBTRANSPORT_LIBRARIES} + PUBLIC ${LIBHICNCTRL_LIBRARIES} + PUBLIC ${LIBHICN_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} ) + +############################################################## +# Build http proxy library +############################################################## build_library(${LIBHTTP_PROXY} STATIC SOURCES ${LIB_SOURCE_FILES} LINK_LIBRARIES ${HTTP_PROXY_LIBRARIES} DEPENDS ${DEPENDENCIES} INSTALL_HEADERS ${LIBPROXY_TO_INSTALL_HEADER_FILES} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBHICNCTRL_INCLUDE_DIRS} ${LIBPROXY_INCLUDE_DIRS} + INCLUDE_DIRS + PUBLIC + $<BUILD_INTERFACE:${LIBPROXY_INCLUDE_DIRS}> + $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} - DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) + +############################################################## +# Build http proxy executable +############################################################## if (NOT DISABLE_EXECUTABLES) build_executable(${HTTP_PROXY} SOURCES ${APP_SOURCE_FILES} LINK_LIBRARIES ${LIBHTTP_PROXY_STATIC} DEPENDS ${LIBHTTP_PROXY_STATIC} COMPONENT ${HICN_APPS} - DEFINITIONS ${COMPILER_DEFINITIONS} LINK_FLAGS ${LINK_FLAGS} ) endif () diff --git a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt index 5cc80a168..18f5704d1 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt +++ b/apps/http-proxy/includes/hicn/http-proxy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -24,7 +24,7 @@ list(APPEND HEADER_FILES set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) set(LIBPROXY_INCLUDE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/../.. "" + ${CMAKE_CURRENT_SOURCE_DIR}/../.. CACHE INTERNAL "" FORCE ) @@ -34,4 +34,3 @@ set(LIBPROXY_TO_INSTALL_HEADER_FILES CACHE INTERNAL "" FORCE ) - diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h index e02b9d9a7..935b85e78 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h +++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -60,7 +60,7 @@ class ForwarderConfig { doTryToConnectToForwarder(std::make_error_code(std::errc(0))); } - void doTryToConnectToForwarder(std::error_code ec) { + void doTryToConnectToForwarder(const std::error_code& ec) { if (!ec) { // ec == 0 --> timer expired int ret = forwarder_interface_.connectToForwarder(); @@ -84,7 +84,7 @@ class ForwarderConfig { } } - void doGetMainListener(std::error_code ec) { + void doGetMainListener(const std::error_code& ec) { if (!ec) { // ec == 0 --> timer expired int ret = forwarder_interface_.getMainListenerPort(); @@ -114,7 +114,7 @@ class ForwarderConfig { TRANSPORT_ALWAYS_INLINE bool parseHicnHeader(std::string& header, Callback&& callback) { std::stringstream ss(header); - route_info_t* ret = new route_info_t(); + RouteInfoPtr ret = std::make_shared<route_info_t>(); std::string port_string; while (ss.good()) { @@ -174,9 +174,9 @@ class ForwarderConfig { ret->family = AF_INET; std::string _prefix = ret->route_addr; forwarder_interface_.createFaceAndRoute( - RouteInfoPtr(ret), [callback = std::forward<Callback>(callback), - configured_prefix = std::move(_prefix)]( - uint32_t route_id, bool result) { + std::move(ret), [callback = std::forward<Callback>(callback), + configured_prefix = std::move(_prefix)]( + uint32_t route_id, bool result) { callback(result, configured_prefix); }); diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h index 54941a4ba..1741aedc6 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h +++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h index 7c035c83b..87a5c7d4e 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_1x_message_fast_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h index a4139a620..efb9f850e 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,7 +22,9 @@ #include "http_session.h" #include "icn_receiver.h" +#ifndef ASIO_STANDALONE #define ASIO_STANDALONE +#endif #include <asio.hpp> #include <asio/version.hpp> #include <unordered_set> @@ -50,9 +52,9 @@ class TcpListener { void doAccept() { #if ((ASIO_VERSION / 100 % 1000) >= 12) acceptor_.async_accept( - [this](std::error_code ec, asio::ip::tcp::socket socket) { + [this](const std::error_code& ec, asio::ip::tcp::socket socket) { #else - acceptor_.async_accept(socket_, [this](std::error_code ec) { + acceptor_.async_accept(socket_, [this](const std::error_code& ec) { auto socket = std::move(socket_); #endif if (!ec) { diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_session.h b/apps/http-proxy/includes/hicn/http-proxy/http_session.h index f4a3dbdee..ee9380a8c 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_session.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_session.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -17,13 +17,12 @@ #include <hicn/transport/core/packet.h> -#include "http_1x_message_fast_parser.h" - -#define ASIO_STANDALONE #include <asio.hpp> #include <deque> #include <functional> +#include "http_1x_message_fast_parser.h" + namespace transport { using asio::ip::tcp; @@ -98,7 +97,7 @@ class HTTPSession { bool checkConnected(); private: - void handleRead(std::error_code ec, std::size_t length); + void handleRead(const std::error_code &ec, std::size_t length); void tryReconnection(); void startConnectionTimer(); void handleDeadline(const std::error_code &ec); diff --git a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h index 780037665..ab90fab07 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h +++ b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -13,6 +13,7 @@ * limitations under the License. */ +#include <hicn/http-proxy/http_session.h> #include <hicn/transport/core/prefix.h> #include <hicn/transport/interfaces/publication_options.h> #include <hicn/transport/interfaces/socket_producer.h> @@ -23,8 +24,6 @@ #include <cstring> #include <queue> #include <utility> - -#include <hicn/http-proxy/http_session.h> //#include "http_session.h" namespace transport { diff --git a/apps/http-proxy/includes/hicn/http-proxy/utils.h b/apps/http-proxy/includes/hicn/http-proxy/utils.h index d87c796d0..0df24dfd9 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/utils.h +++ b/apps/http-proxy/includes/hicn/http-proxy/utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -35,14 +35,13 @@ TRANSPORT_ALWAYS_INLINE std::string generatePrefix( str += pos; uint32_t locator_hash = utils::hash::fnv32_buf(str, strlen(str)); + uint16_t* word = (uint16_t*)&locator_hash; std::stringstream stream; stream << first_ipv6_word << ":0"; - for (uint16_t* word = (uint16_t*)&locator_hash; - std::size_t(word) < (std::size_t(&locator_hash) + sizeof(locator_hash)); - word++) { - stream << ":" << std::hex << *word; + for (std::size_t i = 0; i < sizeof(locator_hash) / 2; i++) { + stream << ":" << std::hex << word[i]; } stream << "::"; diff --git a/apps/http-proxy/main.cc b/apps/http-proxy/main.cc index d9c29ecde..9bd97e02e 100644 --- a/apps/http-proxy/main.cc +++ b/apps/http-proxy/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -139,7 +139,6 @@ int main(int argc, char** argv) { case 'h': default: return usage(argv[0]); - break; } } diff --git a/apps/http-proxy/src/forwarder_interface.cc b/apps/http-proxy/src/forwarder_interface.cc index c2448de9a..1c034f60f 100644 --- a/apps/http-proxy/src/forwarder_interface.cc +++ b/apps/http-proxy/src/forwarder_interface.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -163,7 +163,7 @@ void ForwarderInterface::internalCreateFaceAndRoute(RouteInfoPtr route_info, max_try--; timer->expires_from_now(std::chrono::milliseconds(500)); timer->async_wait([this, _route_info = std::move(route_info), max_try, - timer, callback](std::error_code ec) { + timer, callback](const std::error_code &ec) { if (ec) return; internalCreateFaceAndRoute(std::move(_route_info), max_try, timer, std::move(callback)); diff --git a/apps/http-proxy/src/http_1x_message_fast_parser.cc b/apps/http-proxy/src/http_1x_message_fast_parser.cc index 4b6b78d55..e97c33161 100644 --- a/apps/http-proxy/src/http_1x_message_fast_parser.cc +++ b/apps/http-proxy/src/http_1x_message_fast_parser.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: diff --git a/apps/http-proxy/src/http_proxy.cc b/apps/http-proxy/src/http_proxy.cc index 2040f7cfa..5abe8780f 100644 --- a/apps/http-proxy/src/http_proxy.cc +++ b/apps/http-proxy/src/http_proxy.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -36,7 +36,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback { : tcp_receiver_(tcp_receiver), thread_(thread), prefix_hash_(tcp_receiver_.prefix_hash_), - consumer_(TransportProtocolAlgorithms::RAAQM, thread_.getIoService()), + consumer_(TransportProtocolAlgorithms::RAAQM, thread_), session_(nullptr), current_size_(0) { consumer_.setSocketOption(ConsumerCallbacksOptions::READ_CALLBACK, this); @@ -69,8 +69,8 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback { std::uint16_t remote_port = socket.remote_endpoint().port(); TRANSPORT_LOG_INFO << "Client " << remote_address << ":" << remote_port << "disconnected."; - } catch (std::system_error& e) { - // Do nothing + } catch (asio::system_error& e) { + TRANSPORT_LOG_INFO << "Client disconnected."; } consumer_.stop(); @@ -191,7 +191,7 @@ class HTTPClientConnectionCallback : interface::ConsumerSocket::ReadCallback { session_->send(_buffer, []() {}); } - void readError(const std::error_code ec) noexcept { + void readError(const std::error_code& ec) noexcept { TRANSPORT_LOG_ERROR << "Error reading from hicn consumer socket. Closing session."; session_->close(); @@ -265,7 +265,7 @@ TcpReceiver::TcpReceiver(std::uint16_t port, const std::string& prefix, prefix_hash_(generatePrefix(prefix_, ipv6_first_word_)), forwarder_config_( thread_.getIoService(), - [this](std::error_code ec) { + [this](const std::error_code& ec) { if (!ec) { listener_.doAccept(); for (int i = 0; i < 10; i++) { diff --git a/apps/http-proxy/src/http_session.cc b/apps/http-proxy/src/http_session.cc index 84c814cbd..870f188cd 100644 --- a/apps/http-proxy/src/http_session.cc +++ b/apps/http-proxy/src/http_session.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -92,7 +92,7 @@ void HTTPSession::send(const uint8_t *packet, std::size_t len, io_service_.dispatch([this, packet, len, content_sent]() { asio::async_write(socket_, asio::buffer(packet, len), [content_sent = std::move(content_sent)]( - std::error_code ec, std::size_t /*length*/) { + const std::error_code &ec, std::size_t /*length*/) { if (!ec) { content_sent(); } @@ -131,7 +131,7 @@ void HTTPSession::doWrite() { auto &buffer = write_msgs_.front().first; asio::async_write(socket_, asio::buffer(buffer->data(), buffer->length()), - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_FALSE(!ec)) { write_msgs_.front().second(); write_msgs_.pop_front(); @@ -142,7 +142,7 @@ void HTTPSession::doWrite() { }); } // namespace transport -void HTTPSession::handleRead(std::error_code ec, std::size_t length) { +void HTTPSession::handleRead(const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_TRUE(!ec)) { content_length_ -= length; const uint8_t *buffer = @@ -207,7 +207,7 @@ void HTTPSession::doReadBody(std::size_t body_size, void HTTPSession::doReadChunkedHeader() { asio::async_read_until( socket_, input_buffer_, "\r\n", - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_TRUE(!ec)) { const uint8_t *buffer = asio::buffer_cast<const uint8_t *>(input_buffer_.data()); @@ -226,7 +226,7 @@ void HTTPSession::doReadChunkedHeader() { void HTTPSession::doReadHeader() { asio::async_read_until( socket_, input_buffer_, "\r\n\r\n", - [this](std::error_code ec, std::size_t length) { + [this](const std::error_code &ec, std::size_t length) { if (TRANSPORT_EXPECT_TRUE(!ec)) { const uint8_t *buffer = asio::buffer_cast<const uint8_t *>(input_buffer_.data()); @@ -287,7 +287,7 @@ void HTTPSession::tryReconnection() { void HTTPSession::doConnect() { asio::async_connect( socket_, endpoint_iterator_, - [this](std::error_code ec, tcp::resolver::iterator) { + [this](const std::error_code &ec, tcp::resolver::iterator) { if (!ec) { timer_.cancel(); state_ = ConnectorState::CONNECTED; diff --git a/apps/http-proxy/src/icn_receiver.cc b/apps/http-proxy/src/icn_receiver.cc index ea8ac7191..954861e3a 100644 --- a/apps/http-proxy/src/icn_receiver.cc +++ b/apps/http-proxy/src/icn_receiver.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -112,6 +112,7 @@ void AsyncConsumerProducer::doReceive() { }); producer_socket_.connect(); + producer_socket_.start(); } void AsyncConsumerProducer::manageIncomingInterest( @@ -128,9 +129,9 @@ void AsyncConsumerProducer::manageIncomingInterest( if (seg >= _it->second.first) { // TRANSPORT_LOGD( - // "Ignoring interest with name %s for a content object which does not " - // "exist. (Request: %u, max: %u)", - // name.toString().c_str(), (uint32_t)seg, (uint32_t)_it->second.first); + // "Ignoring interest with name %s for a content object which does not + // " "exist. (Request: %u, max: %u)", name.toString().c_str(), + // (uint32_t)seg, (uint32_t)_it->second.first); return; } } @@ -168,7 +169,8 @@ void AsyncConsumerProducer::publishContent(const uint8_t* data, options.getLifetime()); if (TRANSPORT_EXPECT_FALSE(ret != SOCKET_OPTION_SET)) { - TRANSPORT_LOG_WARNING << "Warning: content object lifetime has not been set."; + TRANSPORT_LOG_WARNING + << "Warning: content object lifetime has not been set."; } const interface::Name& name = options.getName(); diff --git a/apps/ping/.clang-format b/apps/ping/.clang-format index cd21e2017..adc73c6fd 100644 --- a/apps/ping/.clang-format +++ b/apps/ping/.clang-format @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2021 Cisco and/or its affiliates. +# Copyright (c) 2021 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: diff --git a/apps/ping/CMakeLists.txt b/apps/ping/CMakeLists.txt index 42f7f98c1..a094cebe3 100644 --- a/apps/ping/CMakeLists.txt +++ b/apps/ping/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -12,28 +12,45 @@ # limitations under the License. if (NOT DISABLE_EXECUTABLES) +############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + +############################################################## +# Libraries to link +############################################################## list (APPEND PING_LIBRARIES - ${LIBTRANSPORT_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ${WSOCK32_LIBRARY} - ${WS2_32_LIBRARY} + PRIVATE ${LIBHICN_LIBRARIES} + PRIVATE ${LIBTRANSPORT_LIBRARIES} + PRIVATE ${CMAKE_THREAD_LIBS_INIT} + PRIVATE ${WSOCK32_LIBRARY} + PRIVATE ${WS2_32_LIBRARY} ) +############################################################## +# Build ping server +############################################################## build_executable(hicn-ping-server SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_server.cc LINK_LIBRARIES ${PING_LIBRARIES} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} DEPENDS ${DEPENDENCIES} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) +############################################################## +# Build ping client +############################################################## build_executable(hicn-ping-client SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/ping_client.cc LINK_LIBRARIES ${PING_LIBRARIES} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} DEPENDS ${DEPENDENCIES} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif ()
\ No newline at end of file diff --git a/apps/ping/src/ping_client.cc b/apps/ping/src/ping_client.cc index 24e0bf3ed..0217f2f8c 100644 --- a/apps/ping/src/ping_client.cc +++ b/apps/ping/src/ping_client.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,7 +16,9 @@ #include <hicn/transport/auth/verifier.h> #include <hicn/transport/core/global_object_pool.h> #include <hicn/transport/core/interest.h> +#include <hicn/transport/interfaces/global_conf_interface.h> #include <hicn/transport/interfaces/portal.h> +#include <hicn/transport/utils/chrono_typedefs.h> #include <asio/signal_set.hpp> #include <asio/steady_timer.hpp> @@ -32,7 +34,7 @@ namespace core { namespace ping { -typedef std::map<uint64_t, uint64_t> SendTimeMap; +typedef std::map<uint64_t, utils::SteadyTime::TimePoint> SendTimeMap; typedef auth::AsymmetricVerifier Verifier; class Configuration { @@ -77,17 +79,12 @@ class Configuration { } }; -class Client : interface::Portal::ConsumerCallback { +class Client : interface::Portal::TransportCallback { public: - Client(Configuration *c) - : portal_(), signals_(portal_.getIoService(), SIGINT) { + Client(Configuration *c) : portal_(), signals_(io_service_, SIGINT) { // Let the main thread to catch SIGINT - portal_.connect(); - portal_.setConsumerCallback(this); - signals_.async_wait(std::bind(&Client::afterSignal, this)); - - timer_.reset(new asio::steady_timer(portal_.getIoService())); + timer_.reset(new asio::steady_timer(portal_.getThread().getIoService())); config_ = c; sequence_number_ = config_->first_suffix_; last_jump_ = 0; @@ -105,19 +102,28 @@ class Client : interface::Portal::ConsumerCallback { void ping() { std::cout << "start ping" << std::endl; - doPing(); - portal_.runEventsLoop(); + + portal_.getThread().add([this]() { + portal_.connect(); + portal_.registerTransportCallback(this); + doPing(); + }); + + io_service_.run(); + } + + void onInterest(Interest &interest) override { + throw errors::RuntimeException("Unexpected interest received."); } void onContentObject(Interest &interest, ContentObject &object) override { - uint64_t rtt = 0; + double rtt = 0; if (!config_->certificate_.empty()) { - auto t0 = std::chrono::steady_clock::now(); + auto t0 = utils::SteadyTime::now(); if (verifier_.verifyPacket(&object)) { - auto t1 = std::chrono::steady_clock::now(); - auto dt = - std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0); + auto t1 = utils::SteadyTime::now(); + auto dt = utils::SteadyTime::getDurationUs(t0, t1); std::cout << "Verification time: " << dt.count() << std::endl; std::cout << "<<< Signature Ok." << std::endl; } else { @@ -127,10 +133,9 @@ class Client : interface::Portal::ConsumerCallback { auto it = send_timestamps_.find(interest.getName().getSuffix()); if (it != send_timestamps_.end()) { - rtt = std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count() - - it->second; + rtt = + utils::SteadyTime::getDurationUs(it->second, utils::SteadyTime::now()) + .count(); send_timestamps_.erase(it); } @@ -206,7 +211,11 @@ class Client : interface::Portal::ConsumerCallback { } } - void onError(std::error_code ec) override {} + void onError(const std::error_code &ec) override { + std::cout << "Aborting ping due to internal error: " << ec.message() + << std::endl; + afterSignal(); + } void doPing() { const Name interest_name(config_->name_, (uint32_t)sequence_number_); @@ -254,10 +263,7 @@ class Client : interface::Portal::ConsumerCallback { if (!config_->quiet_) std::cout << std::endl; - send_timestamps_[sequence_number_] = - std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::steady_clock::now().time_since_epoch()) - .count(); + send_timestamps_[sequence_number_] = utils::SteadyTime::now(); portal_.sendInterest(std::move(interest)); @@ -267,7 +273,11 @@ class Client : interface::Portal::ConsumerCallback { if (sent_ < config_->maxPing_) { this->timer_->expires_from_now( std::chrono::microseconds(config_->pingInterval_)); - this->timer_->async_wait([this](const std::error_code e) { doPing(); }); + this->timer_->async_wait([this](const std::error_code e) { + if (!e) { + doPing(); + } + }); } } @@ -275,11 +285,11 @@ class Client : interface::Portal::ConsumerCallback { std::cout << "Stop ping" << std::endl; std::cout << "Sent: " << sent_ << " Received: " << received_ << " Timeouts: " << timedout_ << std::endl; - portal_.stopEventsLoop(); + io_service_.stop(); } void reset() { - timer_.reset(new asio::steady_timer(portal_.getIoService())); + timer_.reset(new asio::steady_timer(portal_.getThread().getIoService())); sequence_number_ = config_->first_suffix_; last_jump_ = 0; processed_ = 0; @@ -291,6 +301,7 @@ class Client : interface::Portal::ConsumerCallback { private: SendTimeMap send_timestamps_; + asio::io_service io_service_; interface::Portal portal_; asio::signal_set signals_; uint64_t sequence_number_; @@ -337,6 +348,11 @@ void help() { << std::endl; std::cout << "-q quiet, not prints (default false)" << std::endl; + std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module" + << std::endl; + std::cerr << "-F <conf_file> Path to optional configuration file for " + "libtransport" + << std::endl; std::cout << "-H prints this message" << std::endl; } @@ -350,7 +366,11 @@ int main(int argc, char *argv[]) { int opt; std::string producer_certificate = ""; - while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:f:c:SAOqVDH")) != -1) { + std::string conf_file; + transport::interface::global_config::IoModuleConfiguration io_config; + io_config.name = "hicnlightng_module"; + + while ((opt = getopt(argc, argv, "j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) != -1) { switch (opt) { case 't': c->ttl_ = (uint8_t)std::stoi(optarg); @@ -406,6 +426,12 @@ int main(int argc, char *argv[]) { case 'c': c->certificate_ = std::string(optarg); break; + case 'z': + io_config.name = optarg; + break; + case 'F': + conf_file = optarg; + break; case 'H': default: help(); @@ -413,16 +439,24 @@ int main(int argc, char *argv[]) { } } + /** + * IO module configuration + */ + io_config.set(); + + /** + * Parse config file + */ + transport::interface::global_config::parseConfigurationFile(conf_file); + auto ping = std::make_unique<Client>(c); auto t0 = std::chrono::steady_clock::now(); ping->ping(); auto t1 = std::chrono::steady_clock::now(); - std::cout - << "Elapsed time: " - << std::chrono::duration_cast<std::chrono::microseconds>(t1 - t0).count() - << std::endl; + std::cout << "Elapsed time: " + << utils::SteadyTime::getDurationUs(t0, t1).count() << std::endl; #ifdef _WIN32 WSACleanup(); diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc index baf9c6698..3ffbc7325 100644 --- a/apps/ping/src/ping_server.cc +++ b/apps/ping/src/ping_server.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -21,10 +21,10 @@ #include <openssl/applink.c> #endif -#include <hicn/transport/auth/identity.h> #include <hicn/transport/auth/signer.h> #include <hicn/transport/core/content_object.h> #include <hicn/transport/core/interest.h> +#include <hicn/transport/interfaces/global_conf_interface.h> #include <hicn/transport/utils/string_tokenizer.h> #include <asio.hpp> @@ -36,24 +36,13 @@ namespace interface { using HashAlgorithm = core::HashAlgorithm; using CryptoSuite = auth::CryptoSuite; -auth::Identity setProducerIdentity(std::string keystore_name, - std::string keystore_password, - auth::CryptoHashType hash_algorithm) { - if (access(keystore_name.c_str(), F_OK) != -1) { - return auth::Identity(keystore_name, keystore_password, hash_algorithm); - } else { - return auth::Identity(keystore_name, keystore_password, - CryptoSuite::RSA_SHA256, 1024, 365, "producer-test"); - } -} - class CallbackContainer { const std::size_t log2_content_object_buffer_size = 12; public: CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose, bool dump, bool quite, bool flags, bool reset, uint8_t ttl, - auth::Identity *identity, bool sign, uint32_t lifetime) + auth::Signer *signer, bool sign, uint32_t lifetime) : buffer_(object_size, 'X'), content_objects_((std::uint32_t)(1 << log2_content_object_buffer_size)), mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1), @@ -64,7 +53,7 @@ class CallbackContainer { flags_(flags), reset_(reset), ttl_(ttl), - identity_(identity), + signer_(signer), sign_(sign) { core::Packet::Format format; @@ -151,8 +140,8 @@ class CallbackContainer { if (!quite_) std::cout << std::endl; - if (sign_) { - identity_->getSigner()->signPacket(content_object.get()); + if (sign_ && signer_) { + signer_->signPacket(content_object.get()); } p.produce(*content_object); @@ -170,33 +159,43 @@ class CallbackContainer { bool flags_; bool reset_; uint8_t ttl_; - auth::Identity *identity_; + auth::Signer *signer_; bool sign_; }; void help() { std::cout << "usage: hicn-preoducer-ping [options]" << std::endl; std::cout << "PING options" << std::endl; - std::cout << "-s <val> object content size (default 1350B)" << std::endl; - std::cout << "-n <val> hicn name (default b001::/64)" << std::endl; - std::cout << "-f set tcp flags according to the flag received " - "(default false)" + std::cout << "-s <val> object content size (default 1350B)" << std::endl; - std::cout << "-l data lifetime" << std::endl; - std::cout << "-r always reply with a reset flag (default false)" + std::cout << "-n <val> hicn name (default b001::/64)" << std::endl; + std::cout << "-f set tcp flags according to the flag received " + " (default false)" << std::endl; - std::cout << "-t set ttl (default 64)" << std::endl; + std::cout << "-l data lifetime" << std::endl; + std::cout + << "-r always reply with a reset flag (default false)" + << std::endl; + std::cout << "-t set ttl (default 64)" << std::endl; std::cout << "OUTPUT options" << std::endl; - std::cout << "-V verbose, prints statistics about the messagges sent " - "and received (default false)" + std::cout << "-V verbose, prints statistics about the " + "messagges sent " + " and received (default false)" + << std::endl; + std::cout << "-D dump, dumps sent and received packets " + "(default false)" << std::endl; - std::cout << "-D dump, dumps sent and received packets (default false)" + std::cout << "-q quite, not prints (default false)" + << std::endl; + std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module" + << std::endl; + std::cerr << "-F <conf_file> Path to optional configuration file for " + "libtransport" << std::endl; - std::cout << "-q quite, not prints (default false)" << std::endl; #ifndef _WIN32 - std::cout << "-d daemon mode" << std::endl; + std::cout << "-d daemon mode" << std::endl; #endif - std::cout << "-H prints this message" << std::endl; + std::cout << "-H prints this message" << std::endl; } int main(int argc, char **argv) { @@ -220,11 +219,15 @@ int main(int argc, char **argv) { bool sign = false; uint32_t data_lifetime = default_values::content_object_expiry_time; + std::string conf_file; + transport::interface::global_config::IoModuleConfiguration io_config; + io_config.name = "hicnlightng_module"; + int opt; #ifndef _WIN32 - while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:")) != -1) { + while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDdHk:p:z:F:")) != -1) { #else - while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:")) != -1) { + while ((opt = getopt(argc, argv, "s:n:t:l:qfrVDHk:p:z:F:")) != -1) { #endif switch (opt) { case 's': @@ -268,6 +271,12 @@ int main(int argc, char **argv) { case 'p': keystore_password = optarg; break; + case 'z': + io_config.name = optarg; + break; + case 'F': + conf_file = optarg; + break; case 'H': default: help(); @@ -281,6 +290,16 @@ int main(int argc, char **argv) { } #endif + /** + * IO module configuration + */ + io_config.set(); + + /** + * Parse config file + */ + transport::interface::global_config::parseConfigurationFile(conf_file); + core::Prefix producer_namespace(name_prefix); utils::StringTokenizer tokenizer(name_prefix, delimiter); @@ -290,21 +309,24 @@ int main(int argc, char **argv) { if (object_size > 1350) object_size = 1350; CallbackContainer *stubs; - auth::Identity identity = setProducerIdentity( - keystore_path, keystore_password, auth::CryptoHashType::SHA256); + std::unique_ptr<auth::AsymmetricSigner> signer; if (sign) { - stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, &identity, sign, data_lifetime); + signer = std::make_unique<auth::AsymmetricSigner>(keystore_path, + keystore_password); + stubs = + new CallbackContainer(n, object_size, verbose, dump, quite, flags, + reset, ttl, signer.get(), sign, data_lifetime); } else { - auth::Identity *identity = nullptr; + auth::Signer *signer = nullptr; stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, identity, sign, data_lifetime); + reset, ttl, signer, sign, data_lifetime); } ProducerSocket p; p.registerPrefix(producer_namespace); + p.setSocketOption(GeneralTransportOptions::MAKE_MANIFEST, false); p.setSocketOption(GeneralTransportOptions::OUTPUT_BUFFER_SIZE, 0U); p.setSocketOption( ProducerCallbacksOptions::CACHE_MISS, @@ -313,6 +335,7 @@ int main(int argc, char **argv) { std::placeholders::_2, data_lifetime)); p.connect(); + p.start(); asio::io_service io_service; asio::signal_set signal_set(io_service, SIGINT); |