From 2e6a373cdc6791d77d7c808c757b6892b6669c2c Mon Sep 17 00:00:00 2001 From: RogerZhongAWS <100961047+RogerZhongAWS@users.noreply.github.com> Date: Thu, 12 Sep 2024 18:20:48 +0000 Subject: [PATCH] Catch2 upgrade + Fix destination TCP retry loop + documentation updates (#161) * cap default retry count to 5 * remove connection_id field from stream_reset * accept both stream start and connection start messages upon startup in destination mode * update README and docker scripts * add static linking option to cmakelists * upgrade Catch 2 to V3 * update static linking documentation --- .../base-images/amazonlinux/Dockerfile | 2 +- .../base-images/debian-ubuntu/Dockerfile | 2 +- .../base-images/fedora/Dockerfile | 2 +- .../docker-images/base-images/ubi8/Dockerfile | 2 +- .github/workflows/ci.yml | 6 +- .travis.yml | 2 +- CMakeLists.txt | 34 +++-- Dockerfile | 2 +- README.md | 9 +- docker-build.sh | 2 + docker-run.sh | 2 + src/ProxySettings.cpp | 2 +- src/TcpAdapterProxy.cpp | 131 ++++++------------ src/TcpAdapterProxy.h | 2 +- test/AdapterTests.cpp | 4 +- test/Url.cpp | 3 +- test/WebProxyAdapterTests.cpp | 3 +- windows-localproxy-build.md | 2 +- 18 files changed, 95 insertions(+), 117 deletions(-) diff --git a/.github/docker-images/base-images/amazonlinux/Dockerfile b/.github/docker-images/base-images/amazonlinux/Dockerfile index 565e16a..cfb9702 100644 --- a/.github/docker-images/base-images/amazonlinux/Dockerfile +++ b/.github/docker-images/base-images/amazonlinux/Dockerfile @@ -44,7 +44,7 @@ RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/p make install WORKDIR /home/dependencies -RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ +RUN git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git && \ cd Catch2 && \ mkdir build && \ cd build && \ diff --git a/.github/docker-images/base-images/debian-ubuntu/Dockerfile b/.github/docker-images/base-images/debian-ubuntu/Dockerfile index 5df51cc..38020aa 100644 --- a/.github/docker-images/base-images/debian-ubuntu/Dockerfile +++ b/.github/docker-images/base-images/debian-ubuntu/Dockerfile @@ -44,7 +44,7 @@ RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/p make install WORKDIR /home/dependencies -RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ +RUN git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git && \ cd Catch2 && \ mkdir build && \ cd build && \ diff --git a/.github/docker-images/base-images/fedora/Dockerfile b/.github/docker-images/base-images/fedora/Dockerfile index 3c6e9ce..e226cd1 100644 --- a/.github/docker-images/base-images/fedora/Dockerfile +++ b/.github/docker-images/base-images/fedora/Dockerfile @@ -43,7 +43,7 @@ RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/p make install WORKDIR /home/dependencies -RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ +RUN git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git && \ cd Catch2 && \ mkdir build && \ cd build && \ diff --git a/.github/docker-images/base-images/ubi8/Dockerfile b/.github/docker-images/base-images/ubi8/Dockerfile index c93d1e3..9992fb4 100644 --- a/.github/docker-images/base-images/ubi8/Dockerfile +++ b/.github/docker-images/base-images/ubi8/Dockerfile @@ -42,7 +42,7 @@ RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.17.3/p make install WORKDIR /home/dependencies -RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ +RUN git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git && \ cd Catch2 && \ mkdir build && \ cd build && \ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5aaea4..25e90d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,7 +84,7 @@ jobs: - name: install Catch2 working-directory: ${{ github.workspace }} run: | - git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git + git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git cd Catch2 mkdir build cd build @@ -126,7 +126,7 @@ jobs: $env:Path += ";C:\Program Files\OpenSSL\bin" - name: Install Catch2 run: | - git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git + git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git cd Catch2 mkdir build cd build @@ -169,7 +169,7 @@ jobs: run: | mkdir build cd build - cmake -DBUILD_TESTS=OFF -DBOOST_PKG_VERSION=1.84.0 -DWIN32_WINNT=0x0601 -DBoost_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH="C:\Boost;C:\Program Files (x86)\Catch2;C:\Program Files (x86)\protobuf;C:\Program Files\OpenSSL" -G "Visual Studio 16 2019" -A x64 ..\ + cmake -DBUILD_TESTS=OFF -DLINK_STATIC_OPENSSL=OFF -DBOOST_PKG_VERSION=1.84.0 -DWIN32_WINNT=0x0601 -DBoost_USE_STATIC_LIBS=ON -DCMAKE_PREFIX_PATH="C:\Boost;C:\Program Files (x86)\Catch2;C:\Program Files (x86)\protobuf;C:\Program Files\OpenSSL" -G "Visual Studio 16 2019" -A x64 ..\ msbuild localproxy.vcxproj -p:Configuration=Release - name: Upload Artifact uses: actions/upload-artifact@v3 diff --git a/.travis.yml b/.travis.yml index 6fe5000..2097103 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ install: - make - sudo make install - cd $TRAVIS_BUILD_DIR - - git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git + - git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git - cd Catch2 - mkdir -p build - cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index f7fd445..79db672 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,8 @@ set(AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME localproxy) set(AWS_TUNNEL_LOCAL_PROXY_LIB_NAME lproxy) project(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} CXX) -option(BUILD_TESTS "Build tests" ON) +option(BUILD_TESTS "Build tests" OFF) +option(LINK_STATIC_OPENSSL "Use static openssl libs" ON) if(BUILD_TESTS) set(AWS_TUNNEL_LOCAL_PROXY_TEST_NAME localproxytest) project(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} CXX) @@ -62,16 +63,18 @@ protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${PROJECT_SOURCE_DIR}/resources/Mess set(OPENSSL_USE_STATIC_LIBS TRUE) find_package(OpenSSL REQUIRED) -include_directories(${OPENSSL_INCLUDE_DIR}) -string(REPLACE ${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_STATIC_LIBRARY_SUFFIX} OpenSSL_STATIC_SSL_LIBRARY ${OPENSSL_SSL_LIBRARY}) -string(REPLACE ${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_STATIC_LIBRARY_SUFFIX} OpenSSL_STATIC_CRYPTO_LIBRARY ${OPENSSL_CRYPTO_LIBRARY}) +if(LINK_STATIC_OPENSSL) + include_directories(${OPENSSL_INCLUDE_DIR}) + string(REPLACE ${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_STATIC_LIBRARY_SUFFIX} OpenSSL_STATIC_SSL_LIBRARY ${OPENSSL_SSL_LIBRARY}) + string(REPLACE ${CMAKE_SHARED_LIBRARY_SUFFIX} ${CMAKE_STATIC_LIBRARY_SUFFIX} OpenSSL_STATIC_CRYPTO_LIBRARY ${OPENSSL_CRYPTO_LIBRARY}) +endif() ######################################### # Test framework dependency # ######################################### #probably comment out for cross compiler as Catch2 is really just a header library if(BUILD_TESTS) - find_package(Catch2 REQUIRED) + find_package(Catch2 3 REQUIRED) endif(BUILD_TESTS) ######################################### @@ -102,6 +105,7 @@ if(BUILD_TESTS) file(GLOB TEST_CODE ${PROJECT_SOURCE_DIR}/test/*.cpp) set(TEST_SOURCES ${TEST_CODE} ${CORE_SOURCES} ${UTIL_SOURCE}) add_executable(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${TEST_SOURCES}) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} Catch2::Catch2WithMain) endif(BUILD_TESTS) #libatomic ensured for all platforms except OSX and WINDOWS @@ -115,9 +119,13 @@ endif() include_directories(${PROJECT_SOURCE_DIR}/src) target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT}) -# target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} OpenSSL::SSL) -# target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} OpenSSL::Crypto) -### uncomment above 2 lines and remove below 2 lines to link against OpenSSL shared libs +if(LINK_STATIC_OPENSSL) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} ${OpenSSL_STATIC_SSL_LIBRARY}) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} ${OpenSSL_STATIC_CRYPTO_LIBRARY}) +else() + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} OpenSSL::SSL) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} OpenSSL::Crypto) +endif() target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} ${OpenSSL_STATIC_SSL_LIBRARY}) target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} ${OpenSSL_STATIC_CRYPTO_LIBRARY}) target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} ${Boost_STATIC_LIBRARIES}) @@ -127,9 +135,13 @@ set_property(TARGET ${AWS_TUNNEL_LOCAL_PROXY_TARGET_NAME} APPEND_STRING PROPERTY if(BUILD_TESTS) target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${CMAKE_THREAD_LIBS_INIT}) - # target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} OpenSSL::SSL) - # target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} OpenSSL::Crypto) - ### uncomment above 2 lines and remove below 2 lines to link against OpenSSL shared libs + if(LINK_STATIC_OPENSSL) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${OpenSSL_STATIC_SSL_LIBRARY}) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${OpenSSL_STATIC_CRYPTO_LIBRARY}) + else() + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} OpenSSL::SSL) + target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} OpenSSL::Crypto) + endif() target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${OpenSSL_STATIC_SSL_LIBRARY}) target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${OpenSSL_STATIC_CRYPTO_LIBRARY}) target_link_libraries(${AWS_TUNNEL_LOCAL_PROXY_TEST_NAME} ${Boost_STATIC_LIBRARIES}) diff --git a/Dockerfile b/Dockerfile index 28bc37a..96a9d36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,7 +47,7 @@ RUN git clone https://github.com/openssl/openssl.git && \ make all && \ cd /home/dependencies -RUN git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git && \ +RUN git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git && \ cd Catch2 && \ mkdir build && \ cd build && \ diff --git a/README.md b/README.md index bef3344..876dba6 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,11 @@ This code enables tunneling of a single threaded TCP client / server socket inte --- +## Quick Start for x86 Linux platforms + +Install Docker https://docs.docker.com/get-started/get-docker/ +`docker run --rm -it --network=host public.ecr.aws/aws-iot-securetunneling-localproxy/ubuntu-bin:amd64-latest`, then populate the missing required parameters. + ## Building the local proxy via Docker ### Prerequisites @@ -173,11 +178,11 @@ Source install example: Run the ./Configure command without any arguments to check the available platform configuration options and the documentation here: https://wiki.openssl.org/index.php/Compilation_and_Installation ##### Static vs. Dynamic linking OpenSSL -In the `CMakeLists.txt`, there are marked sections with commented code that when uncommented, allow users to switch between using static vs shared OpenSSL libraries. Choosing to do so is completely optional depending on your own operational requirements. This is following guidance from https://github.com/aws-samples/aws-iot-securetunneling-localproxy/pull/145. The localproxy uses static libs by default +In the `CMakeLists.txt`, we provide a parameter -DLINK_STATIC_OPENSSL which by default is set to ON. You may link against shared libraries on your system by setting the value to OFF. Choosing to do so is completely optional depending on your own operational requirements. This is following guidance from https://github.com/aws-samples/aws-iot-securetunneling-localproxy/pull/145. #### 5. Download and install Catch2 test framework - git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git + git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git cd Catch2 mkdir build cd build diff --git a/docker-build.sh b/docker-build.sh index 15285b3..09496a9 100755 --- a/docker-build.sh +++ b/docker-build.sh @@ -1,5 +1,7 @@ #!/bin/bash +echo This script is deprecated, please refer to the Docker Images section of the README for the recommended method of pulling and running images from ECR. + architecture=$(uname -m) if [ "${architecture}" != aarch64 -a "${architecture}" != arm64 ]; then diff --git a/docker-run.sh b/docker-run.sh index 9ca00ff..0ef5870 100755 --- a/docker-run.sh +++ b/docker-run.sh @@ -1,5 +1,7 @@ #!/bin/bash +echo This script is deprecated, please refer to the Docker Images section of the README for the recommended method of pulling and running images from ECR. + while getopts p: flag do case "${flag}" in diff --git a/src/ProxySettings.cpp b/src/ProxySettings.cpp index 929af57..5dc2311 100644 --- a/src/ProxySettings.cpp +++ b/src/ProxySettings.cpp @@ -23,7 +23,7 @@ namespace aws { namespace iot { namespace securedtunneling { namespace settings std::size_t const DEFAULT_MAX_DATA_FRAME_SIZE = DEFAULT_MESSAGE_MAX_SIZE + DEFAULT_DATA_LENGTH_SIZE; char const * const KEY_TCP_CONNECTION_RETRY_COUNT = "tunneling.proxy.tcp.connection_retry_count"; - std::int32_t const DEFAULT_TCP_CONNECTION_RETRY_COUNT = -1; + std::int32_t const DEFAULT_TCP_CONNECTION_RETRY_COUNT = 5; char const * const KEY_TCP_CONNECTION_RETRY_DELAY_MS = "tunneling.proxy.tcp.connection_retry_delay_ms"; std::uint32_t const DEFAULT_TCP_CONNECTION_RETRY_DELAY_MS = 2500; diff --git a/src/TcpAdapterProxy.cpp b/src/TcpAdapterProxy.cpp index 75f1a7a..59a001d 100644 --- a/src/TcpAdapterProxy.cpp +++ b/src/TcpAdapterProxy.cpp @@ -523,15 +523,13 @@ namespace aws { namespace iot { namespace securedtunneling { { BOOST_LOG_SEV(this->log, info) << "Disconnecting... remote endpoint not found due to TCP connection already terminated"; } - connection->tcp_write_buffer_.consume(connection->tcp_write_buffer_.max_size()); // this works on Linux x86_64 but causes a bus error on Darwin arm64, commenting it out // connection->socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_receive); - connection->socket_.close(); - connection->on_web_socket_write_buffer_drain_complete = [&, service_id, connection_id]() { BOOST_LOG_SEV(this->log, trace) << "on_web_socket_write_buffer_drain_complete callback"; tcp_connection::pointer socket_connection = get_tcp_connection(tac, service_id, connection_id); + socket_connection->socket_.close(); // if simultaneous connections are not enabled, then send a stream reset if (tac.adapter_config.is_v2_message_format || tac.adapter_config.is_v1_message_format) @@ -539,7 +537,7 @@ namespace aws { namespace iot { namespace securedtunneling { BOOST_LOG_SEV(log, info) << "simultaneous connections are not enabled, sending stream reset"; socket_connection->after_send_message = std::bind(&tcp_adapter_proxy::setup_tcp_socket, this, std::ref(tac), service_id); tac.serviceId_to_control_message_handler_map[service_id] = std::bind(&tcp_adapter_proxy::ignore_message_and_stop, this, std::ref(tac), std::placeholders::_1); - async_send_stream_reset(tac, service_id, connection_id); + async_send_stream_reset(tac, service_id); } else { @@ -683,7 +681,7 @@ namespace aws { namespace iot { namespace securedtunneling { async_send_message(tac, outgoing_message); } - void tcp_adapter_proxy::async_send_stream_reset(tcp_adapter_context &tac, std::string const & service_id, uint32_t const & connection_id) + void tcp_adapter_proxy::async_send_stream_reset(tcp_adapter_context &tac, std::string const & service_id) { using namespace com::amazonaws::iot::securedtunneling; BOOST_LOG_SEV(log, trace) << "Send reset stream for service id: " << service_id; @@ -706,10 +704,9 @@ namespace aws { namespace iot { namespace securedtunneling { std::int32_t stream_id = tac.serviceId_to_streamId_map[service_id]; outgoing_message.set_type(Message_Type_STREAM_RESET); outgoing_message.set_streamid(stream_id); - outgoing_message.set_connectionid(connection_id); outgoing_message.set_ignorable(false); outgoing_message.clear_payload(); - async_send_message(tac, outgoing_message, service_id, connection_id); + async_send_message(tac, outgoing_message); } void tcp_adapter_proxy::async_send_connection_reset(tcp_adapter_context &tac, std::string const & service_id, uint32_t const & connection_id) @@ -769,9 +766,7 @@ namespace aws { namespace iot { namespace securedtunneling { void tcp_adapter_proxy::handle_web_socket_control_message(tcp_adapter_context &tac, boost::beast::websocket::frame_type ws_message_type, boost::beast::string_view payload) { -#ifdef DEBUG BOOST_LOG_SEV(log, debug) << "Control message received enum(close=0, ping=1, pong=2): " << static_cast(ws_message_type); -#endif boost::beast::websocket::ping_data pd{ payload }; long long now_millis = 0; long long pong_millis = 0; @@ -783,9 +778,7 @@ namespace aws { namespace iot { namespace securedtunneling { tcp_socket_reset_all(tac, std::bind(&tcp_adapter_proxy::web_socket_close_and_stop, this, std::ref(tac))); break; case boost::beast::websocket::frame_type::ping: -#ifdef DEBUG BOOST_LOG_SEV(log, debug) << "Websocket ping received: " << pd; -#endif tac.wss->async_pong(pd, [&](boost::system::error_code const &ec) { if (ec) @@ -814,12 +807,10 @@ namespace aws { namespace iot { namespace securedtunneling { { BOOST_LOG_SEV(log, error) << "Failed to send websocket ping: " << ping_ec.message(); } -#ifdef DEBUG else { BOOST_LOG_SEV(log, trace) << "Successfully sent websocket ping"; } -#endif ping_timer->expires_after(*ping_period); ping_timer->async_wait([this, &tac, ping_data, ping_period, ping_timer](boost::system::error_code const &wait_ec) { @@ -1083,25 +1074,19 @@ namespace aws { namespace iot { namespace securedtunneling { } else { - #ifdef DEBUG BOOST_LOG_SEV(log, debug) << "TCP socket read loop started while web socket write buffer is already full"; - #endif } } bool tcp_adapter_proxy::ignore_message(tcp_adapter_context &tac, message const &message) { - #ifdef DEBUG BOOST_LOG_SEV(log, trace) << "Ignoring data message"; - #endif return true; } bool tcp_adapter_proxy::ignore_message_and_stop(tcp_adapter_context &tac, message const &message) { - #ifdef DEBUG BOOST_LOG_SEV(log, trace) << "Ignoring data message and stopping web socket read loop"; - #endif return false; } @@ -1119,42 +1104,41 @@ namespace aws { namespace iot { namespace securedtunneling { bool tcp_adapter_proxy::async_wait_for_stream_start(tcp_adapter_context &tac, message const &message) { using namespace com::amazonaws::iot::securedtunneling; - BOOST_LOG_SEV(log, trace) << "Wait for control message stream start, receive message type:" << message.type(); + BOOST_LOG_SEV(log, trace) << "Wait for control message stream or connection start, receive message type:" << message.type(); std::int32_t stream_id = static_cast(message.streamid()); uint32_t connection_id = static_cast(message.connectionid()); - // backward compatibility: set is_v2_message_format to true if receives no connection id - if (!connection_id) - { - BOOST_LOG_SEV(log, debug) << "reverting to v2 message format"; - tac.adapter_config.is_v2_message_format = true; - } string service_id = message.serviceid(); + bool is_connection_start = false; switch (message.type()) { case Message_Type_SESSION_RESET: - #ifdef DEBUG BOOST_LOG_SEV(log, trace) << "Session reset received"; - #endif return true; case Message_Type_STREAM_RESET: - // while waiting for stream start (destination mode implied), no TCP socket is present so these - // messages are no-op - #ifdef DEBUG - BOOST_LOG_SEV(log, trace) << "Stream reset received"; - #endif + BOOST_LOG_SEV(log, trace) << "Stream reset received while waiting for stream start (destination mode implied), no TCP socket is present so these messages are no-op"; return true; case Message_Type_CONNECTION_RESET: - // while waiting for stream start (destination mode implied), no TCP socket is present so these - // messages are no-op - #ifdef DEBUG - BOOST_LOG_SEV(log, trace) << "Connection reset received"; - #endif + BOOST_LOG_SEV(log, trace) << "Connection reset received while waiting for stream start (destination mode implied), no TCP socket is present so these messages are no-op"; return true; + case Message_Type_CONNECTION_START: + is_connection_start = true; + case Message_Type_STREAM_START: - #ifdef DEBUG - BOOST_LOG_SEV(log, debug) << "Stream start received"; - #endif + // backward compatibility: set is_v2_message_format to true if receives no connection id + if (!connection_id) + { + BOOST_LOG_SEV(log, debug) << "reverting to v2 message format"; + tac.adapter_config.is_v2_message_format = true; + } + if (is_connection_start) + { + BOOST_LOG_SEV(log, trace) << "Connection Start received, processing message..."; + } + else + { + BOOST_LOG_SEV(log, trace) << "Stream Start received, processing message..."; + } if (!stream_id) { throw proxy_exception("No stream ID set for stream start message!"); @@ -1173,13 +1157,6 @@ namespace aws { namespace iot { namespace securedtunneling { tac.serviceId_to_streamId_map[service_id] = stream_id; async_setup_dest_tcp_socket(tac, service_id, connection_id, true); return false; - case Message_Type_CONNECTION_START: - // while waiting for stream start (destination mode implied), no TCP socket is present so these - // messages are no-op - #ifdef DEBUG - BOOST_LOG_SEV(log, trace) << "Connection start received"; - #endif - return true; case Message_Type_DATA: //handling the following cases alleviates clang compiler warnings throw std::logic_error("Data message received in control message handler"); case Message_Type_SERVICE_IDS: @@ -1371,12 +1348,6 @@ namespace aws { namespace iot { namespace securedtunneling { std::int32_t stream_id = static_cast(message.streamid()); uint32_t connection_id = static_cast(message.connectionid()); - // backward compatibility: set is_v2_message_format to true if receives no connection id - if (!connection_id) - { - BOOST_LOG_SEV(log, debug) << "reverting to v2 message format"; - tac.adapter_config.is_v2_message_format = true; - } string service_id = message.serviceid(); // v1 message format does not need to validate service id. Set to the one service id stored in memory. if (tac.adapter_config.is_v1_message_format) @@ -1386,9 +1357,7 @@ namespace aws { namespace iot { namespace securedtunneling { switch (message.type()) { case Message_Type_SESSION_RESET: - #ifdef DEBUG BOOST_LOG_SEV(log, trace) << "Session reset received"; - #endif //validation has already been done on stream_id before calling this, so we can just listen tcp_socket_reset_all(tac, std::bind(&tcp_adapter_proxy::setup_tcp_sockets, this, std::ref(tac))); return true; //indicates we should stop reading from the web socket after processing this message @@ -1406,6 +1375,12 @@ namespace aws { namespace iot { namespace securedtunneling { return true; case Message_Type_STREAM_START: //could verify that this is a destination mode local proxy. Source mode shouldn't receive stream start + // backward compatibility: set is_v2_message_format to true if receives no connection id + if (!connection_id) + { + BOOST_LOG_SEV(log, debug) << "reverting to v2 message format"; + tac.adapter_config.is_v2_message_format = true; + } if (!stream_id) { throw proxy_exception("No stream ID set for stream start message!"); @@ -1525,9 +1500,7 @@ namespace aws { namespace iot { namespace securedtunneling { { throw proxy_exception("Websocket read error", ec); } - #ifdef DEBUG BOOST_LOG_SEV(log, trace) << "Websocket read " << bytes_read << " bytes"; - #endif continue_reading = process_incoming_websocket_buffer(tac, incoming_message_buffer); @@ -1565,16 +1538,12 @@ namespace aws { namespace iot { namespace securedtunneling { //doesn't output actual error string unless debug protobuf library is linked to throw proxy_exception((boost::format("Could not parse web socket binary frame into message: %1%") % incoming_message.InitializationErrorString()).str()); } - #ifdef DEBUG //BOOST_LOG_SEV(log, trace) << "Message received:\n" << message.DebugString(); //re-add when linked to protobuf instead of protobuf-lite BOOST_LOG_SEV(log, trace) << "Message parsed successfully , type :" << incoming_message.type(); - #endif if (!is_valid_stream_id(tac, incoming_message)) { continue_reading = true; - #ifdef DEBUG BOOST_LOG_SEV(log, trace) << "Stale message received. Dropping"; - #endif } else { @@ -1657,9 +1626,6 @@ namespace aws { namespace iot { namespace securedtunneling { else if (tac.is_web_socket_reading) { BOOST_LOG_SEV(log, debug) << "Starting web socket read loop while web socket is already reading. Ignoring..."; - #ifdef DEBUG - BOOST_LOG_SEV(log, debug) << "Starting web socket read loop while web socket is already reading. Ignoring..."; - #endif } else { @@ -1686,9 +1652,7 @@ namespace aws { namespace iot { namespace securedtunneling { } if (tac.is_web_socket_reading) { -#ifdef DEBUG BOOST_LOG_SEV(log, debug) << "Starting web socket read loop while web socket is already reading. Ignoring..."; -#endif } else { @@ -1743,9 +1707,7 @@ namespace aws { namespace iot { namespace securedtunneling { bool has_space_after = tcp_has_enough_write_buffer_space(socket_write_connection); if (!had_space_before && has_space_after) { - #ifdef DEBUG BOOST_LOG_SEV(log, debug) << "Just cleared enough buffer space in tcp write buffer. Re-starting async web socket read loop"; - #endif async_web_socket_read_loop(tac); } if (socket_write_connection->tcp_write_buffer_.size() > 0) @@ -1761,9 +1723,6 @@ namespace aws { namespace iot { namespace securedtunneling { invoke_and_clear_handler(socket_write_connection->on_tcp_write_buffer_drain_complete); } BOOST_LOG_SEV(log, trace) << "TCP write buffer drain complete"; - #ifdef DEBUG - BOOST_LOG_SEV(log, trace) << "TCP write buffer drain complete"; - #endif } BOOST_LOG_SEV(log, trace) << "Done writing for: " << service_id << ", connection id: " << connection_id; } @@ -2089,12 +2048,11 @@ namespace aws { namespace iot { namespace securedtunneling { string endpoint = tac.adapter_config.serviceId_to_endpoint_map[service_id]; BOOST_LOG_SEV(log, error) << (boost::format("Could not resolve endpoint %1%. Error message: %2%") % endpoint % ec.message()).str(); basic_retry_execute(log, retry_config, - [this, &tac, service_id, connection_id]() + [this, &tac, service_id]() { - tcp_connection::pointer socket_connection = get_tcp_connection(tac, service_id, connection_id); - tac.serviceId_to_control_message_handler_map[service_id] = std::bind(&tcp_adapter_proxy::ignore_message, this, std::ref(tac), std::placeholders::_1); - socket_connection->after_send_message = std::bind(&tcp_adapter_proxy::setup_tcp_socket, this, std::ref(tac), service_id); - async_send_stream_reset(tac, service_id, connection_id); + BOOST_LOG_SEV(log, trace) << "resetting stream for service id:" << service_id << ", then listen for stream start"; + async_send_stream_reset(tac, service_id); + setup_tcp_socket(std::ref(tac), service_id); }); } else { @@ -2109,13 +2067,11 @@ namespace aws { namespace iot { namespace securedtunneling { { BOOST_LOG_SEV(log, error) << (boost::format("Could not connect to destination %1%:%2% -- %3%") % dst_host % dst_port % ec.message()).str(); basic_retry_execute(log, retry_config, - [this, &tac, service_id, connection_id]() + [this, &tac, service_id]() { - BOOST_LOG_SEV(log, trace) << "ignoring all messages: "; - tcp_connection::pointer socket_connection = get_tcp_connection(tac, service_id, connection_id); - tac.serviceId_to_control_message_handler_map[service_id] = std::bind(&tcp_adapter_proxy::ignore_message, this, std::ref(tac), std::placeholders::_1); - socket_connection->after_send_message = std::bind(&tcp_adapter_proxy::setup_tcp_socket, this, std::ref(tac), service_id); - async_send_stream_reset(tac, service_id, connection_id); + BOOST_LOG_SEV(log, trace) << "resetting stream for service id:" << service_id << ", then listen for stream start"; + async_send_stream_reset(tac, service_id); + setup_tcp_socket(std::ref(tac), service_id); }); } else @@ -2172,12 +2128,11 @@ namespace aws { namespace iot { namespace securedtunneling { { BOOST_LOG_SEV(log, error) << (boost::format("Could not resolve bind address: %1% -- %2%") % tac.adapter_config.bind_address.get() % ec.message()).str(); basic_retry_execute(log, retry_config, - [this, &tac, service_id, connection_id]() + [this, &tac, service_id]() { - tcp_connection::pointer socket_connection = get_tcp_connection(tac, service_id, connection_id); - tac.serviceId_to_control_message_handler_map[service_id] = std::bind(&tcp_adapter_proxy::ignore_message, this, std::ref(tac), std::placeholders::_1); - socket_connection->after_send_message = std::bind(&tcp_adapter_proxy::setup_tcp_socket, this, std::ref(tac), service_id); - async_send_stream_reset(tac, service_id, connection_id); + BOOST_LOG_SEV(log, trace) << "resetting stream for service id:" << service_id << ", then listen for stream start"; + async_send_stream_reset(tac, service_id); + setup_tcp_socket(std::ref(tac), service_id); }); } else diff --git a/src/TcpAdapterProxy.h b/src/TcpAdapterProxy.h index b99d4de..9bf13ef 100644 --- a/src/TcpAdapterProxy.h +++ b/src/TcpAdapterProxy.h @@ -238,7 +238,7 @@ namespace aws { namespace iot { namespace securedtunneling { void async_send_message(tcp_adapter_context &tac, message const &message); void async_send_message(tcp_adapter_context &tac, message const &message, std::string const & service_id, uint32_t const & connection_id); void async_send_stream_start(tcp_adapter_context &tac, std::string const & service_id, uint32_t const & connection_id); - void async_send_stream_reset(tcp_adapter_context &tac, std::string const & service_id, uint32_t const & connection_id); + void async_send_stream_reset(tcp_adapter_context &tac, std::string const & service_id); void async_send_connection_start(tcp_adapter_context &tac, std::string const & service_id, uint32_t const & connection_id); void async_send_connection_reset(tcp_adapter_context &tac, std::string const & service_id, uint32_t const & connection_id); diff --git a/test/AdapterTests.cpp b/test/AdapterTests.cpp index dcd14cc..db48190 100644 --- a/test/AdapterTests.cpp +++ b/test/AdapterTests.cpp @@ -1,12 +1,12 @@ // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#define CATCH_CONFIG_MAIN -#include +#include #include #include #include #include +#include #include #include #include diff --git a/test/Url.cpp b/test/Url.cpp index 04af151..43253c4 100644 --- a/test/Url.cpp +++ b/test/Url.cpp @@ -1,8 +1,9 @@ // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#include +#include #include +#include #include #include diff --git a/test/WebProxyAdapterTests.cpp b/test/WebProxyAdapterTests.cpp index 30d86ca..efa4acf 100644 --- a/test/WebProxyAdapterTests.cpp +++ b/test/WebProxyAdapterTests.cpp @@ -6,11 +6,12 @@ #include "WebProxyAdapter.h" #include "WebSocketStream.h" -#include +#include #include #include #include #include +#include #include #include diff --git a/windows-localproxy-build.md b/windows-localproxy-build.md index ddde043..1d89aec 100644 --- a/windows-localproxy-build.md +++ b/windows-localproxy-build.md @@ -28,7 +28,7 @@ * https://community.chocolatey.org/packages/openssl * Download and install catch2 * Use Visual Studio native tool command prompt in admin mode. - * `git clone --branch v2.13.6 https://github.com/catchorg/Catch2.git` + * `git clone --branch v3.7.0 https://github.com/catchorg/Catch2.git` * `cd Catch2` * `mkdir build` * `cd build`