From 45a1eae91bf444ac400b9a673c9575f5ed8c99b8 Mon Sep 17 00:00:00 2001 From: fmichaut Date: Sat, 2 Dec 2023 17:25:03 -0500 Subject: [PATCH] Add CI scripts (#1) --- .github/workflows/cmake-multi-platform.yml | 93 +++++++++++++++ .github/workflows/code_scanning.yml | 125 +++++++++++++++++++++ CMakeLists.txt | 19 +--- include/CppSockets/Address.hpp | 3 +- source/IPv4.cpp | 12 +- source/Socket.cpp | 18 +-- source/TlsSocket.cpp | 3 +- tests/CMakeLists.txt | 18 +-- tests/TestSockets.cpp | 8 +- vcpkg.json | 6 + 10 files changed, 257 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/cmake-multi-platform.yml create mode 100644 .github/workflows/code_scanning.yml create mode 100644 vcpkg.json diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml new file mode 100644 index 0000000..0a80f8b --- /dev/null +++ b/.github/workflows/cmake-multi-platform.yml @@ -0,0 +1,93 @@ +name: CMake on multiple platforms + +on: + push: + branches: [ "master" ] + pull_request: + types: [ "opened", "reopened", "synchronize", "ready_for_review" ] + +jobs: + build: + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false # ensure we don't stop after 1 failure to always have a complete picture of what is failing + + # Set up a matrix to run the following configurations: + # - ubuntu Debug/Release clang/gcc + # - windows Debug/Release cl + # - macos Debug/Release clang + matrix: + os: [ubuntu-latest, macos-latest] # , windows-latest + build_type: [Release, Debug] + c_compiler: [gcc, clang, cl] + include: + # - os: windows-latest + # c_compiler: cl + # cpp_compiler: cl + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + - os: ubuntu-latest + c_compiler: clang + cpp_compiler: clang++ + - os: macos-latest + c_compiler: clang + cpp_compiler: clang++ + exclude: + - os: windows-latest + c_compiler: gcc + - os: windows-latest + c_compiler: clang + - os: ubuntu-latest + c_compiler: cl + - os: macos-latest + c_compiler: cl + - os: macos-latest + c_compiler: gcc + + steps: + - uses: actions/checkout@v3 + + - name: Set reusable strings + # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. + id: strings + shell: bash + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + - name: Cache VCPKG (Windows) + if: runner.os == 'Windows' + uses: actions/cache@v3 + with: + path: ${{ env.VCPKG_ROOT }} + key: ${{ runner.os }}-${{ matrix.build_type }}-${{ hashFiles('vcpkg.json') }} + + - name: Install OpenSSL (Windows) + if: runner.os == 'Windows' + shell: powershell + run: | + echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "CMAKE_TOOLCHAIN_FILE=${env:VCPKG_INSTALLATION_ROOT}\scripts\buildsystems\vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append + vcpkg install + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: > + cmake -B ${{ steps.strings.outputs.build-output-dir }} + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -DCPPSOCKETS_TESTS=TRUE + -S ${{ github.workspace }} + + - name: Build + # Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + + - name: Test + working-directory: ${{ steps.strings.outputs.build-output-dir }} + # Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest --build-config ${{ matrix.build_type }} --test-dir tests diff --git a/.github/workflows/code_scanning.yml b/.github/workflows/code_scanning.yml new file mode 100644 index 0000000..7c3199a --- /dev/null +++ b/.github/workflows/code_scanning.yml @@ -0,0 +1,125 @@ +name: "Code Scanning" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '20 3 * * 0' + +jobs: + codeql: + name: CodeQL + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ubuntu-latest + timeout-minutes: 360 + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: 'c-cpp' + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:c-cpp" + + flawfinder: + name: Flawfinder + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: flawfinder_scan + uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c + with: + arguments: '--sarif ./' + output: 'flawfinder_results.sarif' + + - name: Upload analysis results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{github.workspace}}/flawfinder_results.sarif + + # microsoft-analyze: + # permissions: + # contents: read # for actions/checkout to fetch code + # security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + # actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + # name: Microsoft Analyze + # runs-on: windows-latest + + # steps: + # - name: Checkout repository + # uses: actions/checkout@v3 + + # - name: Configure CMake + # run: cmake -B ./build + + # # Build is not required unless generated source files are used + # # - name: Build CMake + # # run: cmake --build ./build + + # - name: Initialize MSVC Code Analysis + # uses: microsoft/msvc-code-analysis-action@04825f6d9e00f87422d6bf04e1a38b1f3ed60d99 + # # Provide a unique ID to access the sarif output path + # id: run-analysis + # with: + # cmakeBuildDirectory: ${{ env.build }} + # # Ruleset file that will determine what checks will be run + # ruleset: NativeRecommendedRules.ruleset + + # # Upload SARIF file to GitHub Code Scanning Alerts + # - name: Upload SARIF to GitHub + # uses: github/codeql-action/upload-sarif@v2 + # with: + # sarif_file: ${{ steps.run-analysis.outputs.sarif }} + + # # Upload SARIF file as an Artifact to download and view + # # - name: Upload SARIF as an Artifact + # # uses: actions/upload-artifact@v3 + # # with: + # # name: sarif-file + # # path: ${{ steps.run-analysis.outputs.sarif }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 18db1b4..c4a96c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ ## Author Francois Michaut ## ## Started on Sun Aug 28 19:26:51 2022 Francois Michaut -## Last update Sat Dec 2 10:33:43 2023 Francois Michaut +## Last update Sat Dec 2 17:45:28 2023 Francois Michaut ## ## CMakeLists.txt : CMake to build the CppSockets library ## @@ -26,20 +26,11 @@ add_library(cppsockets source/TlsSocket.cpp ) target_include_directories(cppsockets PUBLIC $ $) -# target_include_directories(cppsockets INTERFACE $) find_package(OpenSSL 3.0 COMPONENTS SSL) target_link_libraries(cppsockets OpenSSL::SSL) -add_custom_target(test - COMMAND ${CMAKE_COMMAND} --log-level=WARNING - -B "${CMAKE_CURRENT_BINARY_DIR}/tests" - -S "${CMAKE_CURRENT_SOURCE_DIR}/tests" - -G ${CMAKE_GENERATOR} - COMMAND ${CMAKE_COMMAND} -E cmake_echo_color - --switch=$(COLOR) --cyan "Building tests..." - COMMAND ${CMAKE_COMMAND} - --build "${CMAKE_CURRENT_BINARY_DIR}/tests" -- --quiet - COMMAND ${CMAKE_MAKE_PROGRAM} - -C "${CMAKE_CURRENT_BINARY_DIR}/tests" test ARGS=--output-on-failure - ) +option(CPPSOCKETS_TESTS "TRUE to build the libcppsockets tests" FALSE) +if(CPPSOCKETS_TESTS) + add_subdirectory(tests) +endif() diff --git a/include/CppSockets/Address.hpp b/include/CppSockets/Address.hpp index 25021b4..6a09f37 100644 --- a/include/CppSockets/Address.hpp +++ b/include/CppSockets/Address.hpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Sun Feb 13 17:09:05 2022 Francois Michaut -** Last update Sat Nov 11 16:57:43 2023 Francois Michaut +** Last update Sat Dec 9 08:51:11 2023 Francois Michaut ** ** Address.hpp : Interface to represent network addresses */ @@ -44,6 +44,7 @@ namespace CppSockets { Endpoint(T addr, std::uint16_t port) : addr(std::move(addr)), port(port), str(makeString()) {}; + virtual ~Endpoint() = default; [[nodiscard]] std::uint16_t getPort() const override { return port; diff --git a/source/IPv4.cpp b/source/IPv4.cpp index 27fe679..6a80e2c 100644 --- a/source/IPv4.cpp +++ b/source/IPv4.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Sun Feb 13 18:52:28 2022 Francois Michaut -** Last update Thu Jul 20 23:08:49 2023 Francois Michaut +** Last update Sat Dec 2 16:17:43 2023 Francois Michaut ** ** IPv4.cpp : Implementation of IPv4 class */ @@ -14,13 +14,17 @@ #include -#include +#ifdef OS_WINDOWS + #include +#else + #include +#endif namespace CppSockets { IPv4::IPv4(std::uint32_t addr) : addr(htonl(addr)) { - struct in_addr tmp {this->addr}; + struct in_addr tmp {.s_addr = this->addr}; str = inet_ntoa(tmp); } @@ -30,7 +34,7 @@ namespace CppSockets { { struct in_addr in; - if (inet_aton(addr, &in) == 0) + if (inet_pton(AF_INET, addr, &in) != 1) throw std::runtime_error("Invalid IPv4 address"); this->addr = in.s_addr; } diff --git a/source/Socket.cpp b/source/Socket.cpp index 95906e9..f2e933f 100644 --- a/source/Socket.cpp +++ b/source/Socket.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Sat Jan 15 01:27:40 2022 Francois Michaut -** Last update Thu Nov 23 23:13:35 2023 Francois Michaut +** Last update Sat Dec 2 17:11:28 2023 Francois Michaut ** ** Socket.cpp : Protable C++ socket class implementation */ @@ -15,10 +15,14 @@ #ifdef OS_WINDOWS #include + #include #else #include #include - // To match windows's constants + #include + #include + + // To match windows's constants static constexpr int INVALID_SOCKET = -1; static constexpr int SOCKET_ERROR = -1; #endif @@ -31,8 +35,6 @@ static constexpr int BUFF_SIZE = 4096; #include #include -#include -#include // TODO add exceptions on error retunrs // TODO throw custom exceptions on invalid status (eg: socket already connected) @@ -43,7 +45,7 @@ namespace CppSockets { socklen_t len = sizeof(int); Socket::getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &m_type, &len); -#ifndef OS_APPLE +#if !defined (OS_APPLE) && !defined (OS_WINDOWS) Socket::getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, &m_domain, &len); Socket::getsockopt(sockfd, SOL_SOCKET, SO_PROTOCOL, &m_protocol, &len); #endif @@ -82,7 +84,7 @@ namespace CppSockets { void Socket::close() { if (m_sockfd != INVALID_SOCKET) { #ifdef OS_WINDOWS - closesocket(raw_socket); + closesocket(m_sockfd); #else ::close(m_sockfd); #endif @@ -193,12 +195,12 @@ namespace CppSockets { return this->bind(endpoint.getAddr().getAddress(), endpoint.getPort()); } - int Socket::bind(std::uint32_t s_addr, uint16_t port) { + int Socket::bind(std::uint32_t source_addr, uint16_t port) { struct sockaddr_in addr = {}; int ret = 0; addr.sin_family = m_domain; - addr.sin_addr.s_addr = s_addr; + addr.sin_addr.s_addr = source_addr; addr.sin_port = htons(port); ret = ::bind(m_sockfd, (struct sockaddr *)&addr, sizeof(addr)); if (ret < 0) { diff --git a/source/TlsSocket.cpp b/source/TlsSocket.cpp index 12b15ae..265109c 100644 --- a/source/TlsSocket.cpp +++ b/source/TlsSocket.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Wed Sep 14 21:04:42 2022 Francois Michaut -** Last update Tue Nov 14 21:15:11 2023 Francois Michaut +** Last update Sat Dec 2 11:33:00 2023 Francois Michaut ** ** SecureSocket.cpp : TLS socket wrapper implementation */ @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2924515..a236832 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,17 +4,11 @@ ## Author Francois Michaut ## ## Started on Mon Feb 14 19:35:41 2022 Francois Michaut -## Last update Wed May 10 09:47:41 2023 Francois Michaut +## Last update Sat Dec 2 17:46:03 2023 Francois Michaut ## ## CMakeLists.txt : CMake building and running tests for CppSockets ## -cmake_minimum_required (VERSION 3.15) -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED True) - -project(CppSockets-Tests VERSION 0.1.0 LANGUAGES C CXX) - include(CTest) create_test_sourcelist(TestFiles test_driver.cpp @@ -22,13 +16,11 @@ create_test_sourcelist(TestFiles test_driver.cpp ) add_executable(unit_tests - ../source/Address.cpp - ../source/Socket.cpp - ../source/IPv4.cpp ${TestFiles} ) target_compile_definitions(unit_tests PRIVATE DEBUG) +target_link_libraries(unit_tests cppsockets) foreach (test ${TestFiles}) if (NOT ${test} STREQUAL test_driver.cpp) @@ -41,9 +33,3 @@ foreach (test ${TestFiles}) endif() endif() endforeach () - -include_directories( - "${CMAKE_CURRENT_BINARY_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/../include" -) diff --git a/tests/TestSockets.cpp b/tests/TestSockets.cpp index d67f59d..316f966 100644 --- a/tests/TestSockets.cpp +++ b/tests/TestSockets.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Mon Feb 14 21:17:55 2022 Francois Michaut -** Last update Wed Oct 12 21:33:22 2022 Francois Michaut +** Last update Wed Dec 6 01:34:58 2023 Francois Michaut ** ** TestSockets.cpp : Socket tests */ @@ -25,8 +25,8 @@ int TestSockets(int, char **) std::string test = "Hello Network !"; int port = 44444; - alarm(10); - if (child == 0) { + alarm(2); + if (child != 0) { Socket soc(AF_INET, SOCK_STREAM, 0); int ret = 0; @@ -49,7 +49,7 @@ int TestSockets(int, char **) try { soc.connect("127.0.0.1", port); } catch (std::exception &e) { - std::cerr << e.what() << std::endl; + std::cerr << "Got error: " << e.what() << std::endl; } } std::cout << "Connected !" << std::endl; diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000..3c7da8a --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "openssl" + ] +}