diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6195b77..0000000 --- a/.travis.yml +++ /dev/null @@ -1,153 +0,0 @@ - -dist: bionic -language: cpp -cache: ccache - -common_sources: &all_sources -- ubuntu-toolchain-r-test -- llvm-toolchain-trusty -- llvm-toolchain-trusty-3.9 -- llvm-toolchain-trusty-4.0 -- llvm-toolchain-xenial-5.0 -- llvm-toolchain-xenial-6.0 - -matrix: - include: - - # 1/ Linux Clang Builds - - - os: linux - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-3.9'] - env: COMPILER='clang++-3.9' - - - os: linux - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-4.0'] - env: COMPILER='clang++-4.0' - - - os: linux - dist: bionic - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-5.0'] - env: COMPILER='clang++-5.0' - - - os: linux - dist: bionic - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-6.0'] - env: COMPILER='clang++-6.0' - - # 2/ Linux GCC Builds - - os: linux - compiler: gcc - addons: - apt: - sources: *all_sources - packages: ['g++-5'] - env: COMPILER='g++-5' - - - os: linux - compiler: gcc - addons: &gcc6 - apt: - sources: *all_sources - packages: ['g++-6'] - env: COMPILER='g++-6' - - - os: linux - compiler: gcc - addons: &gcc7 - apt: - sources: *all_sources - packages: ['g++-7'] - env: COMPILER='g++-7' - - - os: linux - compiler: gcc - addons: &gcc8 - apt: - sources: *all_sources - packages: ['g++-8'] - env: COMPILER='g++-8' - - # 3b/ Linux C++14 Clang builds - # Note that we need newer libstdc++ for C++14 support - - os: linux - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-3.9', 'libstdc++-6-dev'] - env: COMPILER='clang++-3.9' CPP17=1 - - - os: linux - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-4.0', 'libstdc++-6-dev'] - env: COMPILER='clang++-4.0' CPP17=1 - - - os: linux - dist: bionic - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-5.0', 'libstdc++-6-dev'] - env: COMPILER='clang++-5.0' CPP17=1 - - - os: linux - dist: bionic - compiler: clang - addons: - apt: - sources: *all_sources - packages: ['clang-6.0', 'libstdc++-6-dev'] - env: COMPILER='clang++-6.0' CPP17=1 - - - # 4a/ Linux C++14 GCC builds - - os: linux - compiler: gcc - addons: *gcc6 - env: COMPILER='g++-6' - - - os: linux - compiler: gcc - addons: *gcc7 - env: COMPILER='g++-7' - - - os: linux - compiler: gcc - addons: *gcc8 - env: COMPILER='g++-8' - -before install: - -install: - -before_script: -- cd .. -- wget https://github.com/connectivecpp/utility-rack/archive/develop.tar.gz && mkdir utility-rack && tar -zxvf develop.tar.gz -C utility-rack --strip-components=1 -- wget https://github.com/chriskohlhoff/asio/archive/asio-1-14-0.tar.gz && mkdir asio && tar -zxvf asio-1-14-0.tar.gz -C asio --strip-components=1 -- wget https://github.com/catchorg/Catch2/archive/v2.10.2.tar.gz && mkdir Catch2 && tar -zxvf v2.10.2.tar.gz -C Catch2 --strip-components=1 -- mkdir build && cd build -- cmake ../chops-net-ip/ - -script: -- make all -j2 -- make test diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a159d3..5a0b432 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,53 +1,57 @@ -# Copyright 2019-2020 by Cliff Green +# Copyright (c) 2019-2024 by Cliff Green # # https://github.com/connectivecpp/chops-net-ip # +# I'm still learning CMake, so improvement suggestions are always welcome. +# +# The Asio CMake code is taken from CPM.cmake examples/asio-standalone. +# # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -# CMake 3.8 required for cxx_std_17 target_compile_features - -cmake_minimum_required ( VERSION 3.12 ) - -option ( CHOPS_NET_IP_OPT_BUILD_TESTS "Build and perform chops-net-ip tests" ON ) -option ( CHOPS_NET_IP_OPT_BUILD_EXAMPLES "Build and perform chops-net-ip examples" ON ) -option ( CHOPS_NET_IP_OPT_BUILD_DOCS "Build doxygen documentation" OFF ) +cmake_minimum_required ( VERSION 3.14 FATAL_ERROR ) -set ( OPTIONS "" ) -set ( DEFINITIONS "" ) +project ( chops_net_ip + LANGUAGES CXX + DESCRIPTION "An asynchronous networking library based on Asio" + HOMEPAGE_URL "https://github.com/connectivecpp/chops-net-ip/" ) -project ( chops-net-ip VERSION 1.0 LANGUAGES CXX ) +option ( CHOPS_NET_IP_BUILD_TESTS "Build unit tests" OFF ) +option ( CHOPS_NET_IP_BUILD_EXAMPLES "Build examples" OFF ) +option ( CHOPS_NET_IP_INSTALL "Install header only library" OFF ) -set ( package_name "chops-net-ip" ) +# add library targets -set ( include_source_dir "${CMAKE_SOURCE_DIR}/include" ) -set ( utility_rack_dir "${CMAKE_SOURCE_DIR}/../utility-rack" ) -set ( utility_rack_include_source_dir "${utility_rack_dir}/include" ) -set ( third_party_include_source_dir "${utility_rack_dir}/third_party" ) -set ( cmake_include_dir "${CMAKE_SOURCE_DIR}/cmake" ) -set ( cmake_all_repos_include_dir "${utility_rack_dir}/cmake/all_repos" ) +add_library ( chops_net_ip INTERFACE ) +add_library ( chops::chops_net_ip ALIAS chops_net_ip ) +# thread support specified in Asio download -# Interface library: +include ( cmake/download_asio_cpm.cmake ) -add_library ( ${package_name} INTERFACE ) +# configure library target -target_include_directories ( ${package_name} INTERFACE ${include_source_dir} ) -target_include_directories ( ${package_name} INTERFACE ${third_party_include_source_dir} ) -target_compile_features ( ${package_name} INTERFACE cxx_std_17) +target_include_directories ( chops_net_ip INTERFACE + $ + $ ) +target_compile_features ( chops_net_ip INTERFACE cxx_std_20 ) -if ( CHOPS_NET_IP_OPT_BUILD_TESTS ) +# check to build unit tests +if ( ${CHOPS_NET_IP_BUILD_TESTS} ) enable_testing() add_subdirectory ( test ) -endif() +endif () -if ( CHOPS_NET_IP_OPT_BUILD_EXAMPLES ) +# check to build example code +if ( ${CHOPS_NET_IP_BUILD_EXAMPLES} ) add_subdirectory ( example ) -endif() +endif () -if ( CHOPS_NET_IP_OPT_BUILD_DOCS ) - add_subdirectory ( doc ) -endif() +# check to install +if ( ${CHOPS_NET_IP_INSTALL} ) + set ( CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt ) + include ( CPack ) +endif () # end of file diff --git a/README.md b/README.md index 7870261..11bf150 100644 --- a/README.md +++ b/README.md @@ -1,124 +1,70 @@ # Chops Net IP - Connective Handcrafted Openwork Software for Asynchronous IP Networking -Chops Net IP is a C++ library that makes asynchronous networking programming fun. Or at least if not fun, it makes network programming easier and safer, without significantly sacrificing performance. Chops Net IP handles Internet Protocol (IP) communications including TCP, UDP, and UDP multicast. It is written using modern C++ design idioms and the latest (2017) C++ standard. +Chops Net IP is a C++ library that makes asynchronous networking programming fun. Or at least if not fun, it makes network programming easier and safer, without significantly sacrificing performance. Chops Net IP handles Internet Protocol (IP) communications including TCP, UDP, and UDP multicast. It is written using modern C++ design idioms and a recent (2020) C++ standard. Chops Net IP is not like any other high-level, general purpose C++ socket library. Chops Net IP is layered on top of the Asio asynchronous networking library, taking advantage of the portability and functionality that Asio provides. However, it simplifies network programming compared to coding against the Asio API, while providing easy scalability through the asynchronous facilities. -# Build and Release Status, License Info +#### Unit Test and Documentation Generation Workflow Status -**Travis CI Build Status:** +![GH Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/connectivecpp/chops-net-ip/build_run_unit_test_cmake.yml?branch=main&label=GH%20Actions%20build,%20unit%20tests%20on%20main) -*Master Branch* | [![Build Status](https://travis-ci.org/connectivecpp/chops-net-ip.svg?branch=master)](https://travis-ci.org/connectivecpp/chops-net-ip) -*Develop Branch* | [![Build Status](https://travis-ci.org/connectivecpp/chops-net-ip.svg?branch=develop)](https://travis-ci.org/connectivecpp/chops-net-ip) +![GH Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/connectivecpp/chops-net-ip/build_run_unit_test_cmake.yml?branch=develop&label=GH%20Actions%20build,%20unit%20tests%20on%20develop) -**GitHub Actions CI Build Status:** +![GH Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/connectivecpp/chops-net-ip/gen_docs.yml?branch=main&label=GH%20Actions%20generate%20docs) -![CMake Build Matrix](https://github.com/connectivecpp/chops-net-ip/workflows/CMake%20Build%20Matrix/badge.svg) +![GH Tag](https://img.shields.io/github/v/tag/connectivecpp/chops-net-ip?label=GH%20tag) -**Latest tag:** ![Latest Tag](https://img.shields.io/github/v/tag/connectivecpp/chops-net-ip) +## Overview -Release 1.0 is under development as of January 2020, awaiting CMake enhancements, a comprehensive tutorial, and additional testing under multiple compilers and platforms. +`periodic_timer` is an asynchronous periodic timer that wraps and simplifies Asio timers when periodic callbacks are needed. The periodicity can be based on either a simple duration or on timepoints based on a duration. -Release notes and upcoming development plans are [available here](doc/release.md). +Timepoint calculations are performed by this class template so that timepoint durations don't "drift". In other words, if the processing during a callback takes 15 milliseconds, the next callback invocation is adjusted accordingly. -This project is distributed under the [Boost Software License](LICENSE.txt): [![Licence](https://img.shields.io/badge/license-boost-4480cc.svg)](http://www.boost.org/LICENSE_1_0.txt) +Asynchronous timers from Asio are relatively easy to use. However, there are no timers that are periodic. This class simplifies the usage, using application supplied function object callbacks. When the timer is started, the application specifies whether each callback is invoked based on a duration (e.g. one second after the last callback), or on timepoints (e.g. a callback will be invoked each second according to the clock). -# Overview +## Generated Documentation -For many software developers, asynchronous network programming in C++ is not easy. It is complex, has many pitfalls, and requires designing C++ code in a way that is not natural, even for those with years of experience. Chops Net IP ("C"onnective "H"andcrafted "Op"enwork "S"oftware, Networking over Internet Protocol) simplifies asynchronous network programming and provides useful (and tasty!) abstractions for many types of communication patterns. +The generated Doxygen documentation for `periodic_timer` is [here](https://connectivecpp.github.io/chops-net-ip/). -Chops Net IP is layered on top of Chris Kohlhoff's Asio library (see [References](https://connectivecpp.github.io/doc/references.html)) allowing it to be portable across many compilers and platforms. When the C++ Networking TS is standardized (possibly C++ 23 but more likely C++ 26) Chops Net IP will directly use the networking facilities of the C++ standard library. +## Dependencies -Chops Net IP simplifies application code that processes data on multiple simultaneous TCP connections or UDP endpoints. All Chops Net IP operations (from the application viewpoint) are no-wait (i.e. there are no blocking methods) and all network processing operations are performed asynchronously. +The `periodic_timer` header file has the stand-alone Asio library for a dependency. Specific version (or branch) specs for the Asio dependency is in `cmake/download_asio_cpm.cmake`. -## Tasty Bites +## C++ Standard -Chops Net IP functionality: +`periodic_timer` is built under C++ 20, but (currently) does not use any specific C++ 20 features. In the future `concepts` / `requires` will be added. -- simplifies the creation of various IP (Internet Protocol) networking entities including TCP acceptors and connectors, UDP senders and receivers, and UDP multicast senders and receivers. -- simplifies the resolution of network names to IP addresses (i.e. domain name system lookups). -- abstracts message concepts in TCP (Transmission Control Protocol) and provides customization points in two areas: - 1. message framing, which is the code and logic that determines the begin and end of a message within the TCP byte stream. - 2. message processing, which is the code and logic that processes a message when the framing determines a complete message has arrived. -- provides buffer lifetime management for outgoing data. -- provides customization points for state changes in the networking entities, including: - - a TCP connection has become active and is ready for input and output. - - a UDP endpoint has been created and is ready for input and output. - - a TCP connection has been destroyed or a UDP socket has closed. -- implements the "plumbing" for asynchronous processing on multiple simultaneous connections. -- abstracts many differences between network protocols (TCP, UDP, UDP multicast), allowing easier application transitioning between protocol types. -- allows the application to control threading (no threads are created or managed inside Chops Net IP). -- is agnostic with respect to data marshalling or serialization or "wire protocols" (application code provides any and all data marshalling and endian logic). -- does not impose any structure on network message content. +## Supported Compilers -Chops Net IP is designed to make it easy and efficient for an application to create hundreds (or thousands) of network connections and handle them simultaneously. In particular, there are no threads or thread pools within Chops Net IP, and it works well with only one application thread invoking the event loop (an executor, in current C++ terminology). +Continuous integration workflows build and unit test on g++ (through Ubuntu), MSVC (through Windows), and clang (through macOS). -## Tasty Uses +## Unit Test Dependencies -Example environments where Chops Net IP is a good fit: +The unit test code uses [Catch2](https://github.com/catchorg/Catch2). If the `PERIODIC_TIMER_BUILD_TESTS` flag is provided to Cmake (see commands below) the Cmake configure / generate will download the Catch2 library as appropriate using the [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake) dependency manager. If Catch2 (v3 or greater) is already installed using a different package manager (such as Conan or vcpkg), the `CPM_USE_LOCAL_PACKAGES` variable can be set which results in `find_package` being attempted. Note that v3 (or later) of Catch2 is required. -- Applications that are event driven or highly asynchronous in nature. -- Applications where data is generated and handled in a non-symmetric manner. For example, data may be generated on the TCP acceptor side, or may be generated on a TCP connector side, or on both sides depending on the use case. Similarly, applications where the data flow is bi-directional and sends or receives are data-driven versus pattern-driven work well with this library. -- Applications interacting with multiple (many) connections (e.g. handling multiple sensors or inputs or outputs), each with low to moderate throughput needs (i.e. IoT environments, chat networks, gaming networks). -- Small footprint or embedded environments, where all network processing is run inside a single thread. In particular, environments where a JVM (or similar run-time support) is too costly in terms of system resources, but have a relatively rich operating environment (e.g. Linux running on a small chip) are a very good fit. (Currently the main constraint is small system support in the Asio library implementation.) -- Applications with relatively simple network processing that need an easy-to-use and quick-for-development networking library. -- Applications with configuration driven networks that may need to switch (for example) between TCP connect versus TCP accept for a given connection, or between TCP and UDP for a given communication path. -- Peer-to-peer applications where the application doesn't care which side connects or accepts. -- Frameworks or groups of applications where abstracting wire-protocol logic from message processing logic makes sense. +Specific version (or branch) specs for the Catch2 dependency is in the [test/CMakeLists.txt](test/CMakeLists.txt) file, look for the `CPMAddPackage` command. -## Examples +## Build and Run Unit Tests -Example demo programs are in the [`/example`](https://github.com/connectivecpp/chops-net-ip) directory. +To build and run the unit test program: -The `simple_chat_demo.cpp` program has a listing of the multiple steps to set up working example. +First clone the `periodic-timer` repository, then create a build directory in parallel to the `periodic-timer` directory (this is called "out of source" builds, which is recommended), then `cd` (change directory) into the build directory. The CMake commands: -## Want More? +``` +cmake -D PERIODIC_TIMER_BUILD_TESTS:BOOL=ON ../periodic-timer -A detailed overview, a C++ socket library comparison, and a FAQ is [available here](doc/overview.md). +cmake --build . -# C++ Language Requirements and Alternatives +ctest +``` -C++ 17 is the primary baseline for this repository. Additional notes on possible alternatives are [available here](https://connectivecpp.github.io/). +For additional test output, run the unit test individually, for example: -# External Dependencies +``` +test/periodic_timer_test -s +``` -Production external dependencies: - -- Version 1.13 (or later) of Chris Kohlhoff's [`asio`](https://github.com/chriskohlhoff/asio) library is required. Note that it is the stand-alone Asio library, not the Boost Asio version. -- The [`utility-rack`](https://github.com/connectivecpp/utility-rack) library, which is a repository in the same GitHub account as Chops Net IP. - -Test external dependencies: - -- Version 2.8.0 (or later) of Phil Nash's [`Catch2`](https://github.com/catchorg/Catch2) library is required for all test scenarios. - -There are single file headers that have been copied into the `third_party` directory of the `utility-rack` repository from various GitHub repositories and do not require any external dependency management. These are: - -- Martin Moene's [`expected-lite`](https://github.com/martinmoene/expected-lite) library. - -See [References](https://connectivecpp.github.io/doc/references.html) for additional details. - -# Supported Compilers and Platforms - -Chops Net IP has been compiled and tests run on: - -- g++ 7.2, g++ 7.3, Linux (Ubuntu 17.10 - kernel 4.13, Ubuntu 18.04 - kernel 4.15) -- (TBD, will include at least clang on linux and vc++ on Windows) - -Follow the CI links for additional build environments. - -# Installation - -Chops Net IP is header-only, so installation consists of downloading or cloning and setting compiler include paths appropriately. No compile time configuration macros are defined. - -# References - -See [References](https://connectivecpp.github.io/doc/references.html) for details on dependencies and inspirations for Chops Net IP. - -# About - -Team member information is [available here](https://connectivecpp.github.io/). - -A few "Cliff Notes" are [available here](doc/cliff_notes.md). +The example can be built by adding `-D PERIODIC_TIMER_BUILD_EXAMPLES:BOOL=ON` to the CMake configure / generate step. diff --git a/cmake/download_asio_cpm.cmake b/cmake/download_asio_cpm.cmake new file mode 100644 index 0000000..103cd19 --- /dev/null +++ b/cmake/download_asio_cpm.cmake @@ -0,0 +1,64 @@ +# This Asio CMake code is taken from CPM.cmake examples/asio-standalone. +# +# This code assumes it is run from a top-level CMakeLists.txt file, +# with a download_cpm.cmake file in a parallel cmake directory. +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +set ( CMAKE_THREAD_PREFER_PTHREAD TRUE ) +set ( THREADS_PREFER_PTHREAD_FLAG TRUE ) +find_package ( Threads REQUIRED ) + +include ( cmake/download_cpm.cmake ) +CPMAddPackage ( "gh:chriskohlhoff/asio#asio-1-30-2@1.30.2" ) + +# ASIO doesn't use CMake, we have to configure it manually. Extra notes for using on Windows: +# +# 1) If _WIN32_WINNT is not set, ASIO assumes _WIN32_WINNT=0x0501, i.e. Windows XP target, which is +# definitely not the platform which most users target. +# +# 2) WIN32_LEAN_AND_MEAN is defined to make Winsock2 work. + +if(asio_ADDED) + add_library(asio INTERFACE) + + target_include_directories(asio SYSTEM INTERFACE ${asio_SOURCE_DIR}/asio/include) + + target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED) + + target_link_libraries(asio INTERFACE Threads::Threads) + + if(WIN32) + # macro see @ https://stackoverflow.com/a/40217291/1746503 + macro(get_win32_winnt version) + if(CMAKE_SYSTEM_VERSION) + set(ver ${CMAKE_SYSTEM_VERSION}) + string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver}) + string(REGEX MATCH "^([0-9]+)" verMajor ${ver}) + # Check for Windows 10, b/c we'll need to convert to hex 'A'. + if("${verMajor}" MATCHES "10") + set(verMajor "A") + string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver}) + endif("${verMajor}" MATCHES "10") + # Remove all remaining '.' characters. + string(REPLACE "." "" ver ${ver}) + # Prepend each digit with a zero. + string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver}) + set(${version} "0x${ver}") + endif() + endmacro() + + if(NOT DEFINED _WIN32_WINNT) + get_win32_winnt(ver) + set(_WIN32_WINNT ${ver}) + endif() + + message(STATUS "Set _WIN32_WINNET=${_WIN32_WINNT}") + + target_compile_definitions(asio INTERFACE _WIN32_WINNT=${_WIN32_WINNT} WIN32_LEAN_AND_MEAN) + endif() +endif() + +# end of file + diff --git a/cmake/download_cpm.cmake b/cmake/download_cpm.cmake new file mode 100644 index 0000000..b4e123b --- /dev/null +++ b/cmake/download_cpm.cmake @@ -0,0 +1,10 @@ + +# copied from CPM.cmake GitHub site +# download CPM.cmake + +file( + DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v0.39.0/CPM.cmake + ${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake +) +include(${CMAKE_CURRENT_BINARY_DIR}/cmake/CPM.cmake) diff --git a/oldCMakeLists.txt b/oldCMakeLists.txt new file mode 100644 index 0000000..9a159d3 --- /dev/null +++ b/oldCMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright 2019-2020 by Cliff Green +# +# https://github.com/connectivecpp/chops-net-ip +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# CMake 3.8 required for cxx_std_17 target_compile_features + +cmake_minimum_required ( VERSION 3.12 ) + +option ( CHOPS_NET_IP_OPT_BUILD_TESTS "Build and perform chops-net-ip tests" ON ) +option ( CHOPS_NET_IP_OPT_BUILD_EXAMPLES "Build and perform chops-net-ip examples" ON ) +option ( CHOPS_NET_IP_OPT_BUILD_DOCS "Build doxygen documentation" OFF ) + +set ( OPTIONS "" ) +set ( DEFINITIONS "" ) + +project ( chops-net-ip VERSION 1.0 LANGUAGES CXX ) + +set ( package_name "chops-net-ip" ) + +set ( include_source_dir "${CMAKE_SOURCE_DIR}/include" ) +set ( utility_rack_dir "${CMAKE_SOURCE_DIR}/../utility-rack" ) +set ( utility_rack_include_source_dir "${utility_rack_dir}/include" ) +set ( third_party_include_source_dir "${utility_rack_dir}/third_party" ) +set ( cmake_include_dir "${CMAKE_SOURCE_DIR}/cmake" ) +set ( cmake_all_repos_include_dir "${utility_rack_dir}/cmake/all_repos" ) + + +# Interface library: + +add_library ( ${package_name} INTERFACE ) + +target_include_directories ( ${package_name} INTERFACE ${include_source_dir} ) +target_include_directories ( ${package_name} INTERFACE ${third_party_include_source_dir} ) +target_compile_features ( ${package_name} INTERFACE cxx_std_17) + +if ( CHOPS_NET_IP_OPT_BUILD_TESTS ) + enable_testing() + add_subdirectory ( test ) +endif() + +if ( CHOPS_NET_IP_OPT_BUILD_EXAMPLES ) + add_subdirectory ( example ) +endif() + +if ( CHOPS_NET_IP_OPT_BUILD_DOCS ) + add_subdirectory ( doc ) +endif() + +# end of file + diff --git a/oldReadme.md b/oldReadme.md new file mode 100644 index 0000000..7870261 --- /dev/null +++ b/oldReadme.md @@ -0,0 +1,124 @@ +# Chops Net IP - Connective Handcrafted Openwork Software for Asynchronous IP Networking + +Chops Net IP is a C++ library that makes asynchronous networking programming fun. Or at least if not fun, it makes network programming easier and safer, without significantly sacrificing performance. Chops Net IP handles Internet Protocol (IP) communications including TCP, UDP, and UDP multicast. It is written using modern C++ design idioms and the latest (2017) C++ standard. + +Chops Net IP is not like any other high-level, general purpose C++ socket library. + +Chops Net IP is layered on top of the Asio asynchronous networking library, taking advantage of the portability and functionality that Asio provides. However, it simplifies network programming compared to coding against the Asio API, while providing easy scalability through the asynchronous facilities. + +# Build and Release Status, License Info + +**Travis CI Build Status:** + +*Master Branch* | [![Build Status](https://travis-ci.org/connectivecpp/chops-net-ip.svg?branch=master)](https://travis-ci.org/connectivecpp/chops-net-ip) +*Develop Branch* | [![Build Status](https://travis-ci.org/connectivecpp/chops-net-ip.svg?branch=develop)](https://travis-ci.org/connectivecpp/chops-net-ip) + +**GitHub Actions CI Build Status:** + +![CMake Build Matrix](https://github.com/connectivecpp/chops-net-ip/workflows/CMake%20Build%20Matrix/badge.svg) + +**Latest tag:** ![Latest Tag](https://img.shields.io/github/v/tag/connectivecpp/chops-net-ip) + +Release 1.0 is under development as of January 2020, awaiting CMake enhancements, a comprehensive tutorial, and additional testing under multiple compilers and platforms. + +Release notes and upcoming development plans are [available here](doc/release.md). + +This project is distributed under the [Boost Software License](LICENSE.txt): [![Licence](https://img.shields.io/badge/license-boost-4480cc.svg)](http://www.boost.org/LICENSE_1_0.txt) + +# Overview + +For many software developers, asynchronous network programming in C++ is not easy. It is complex, has many pitfalls, and requires designing C++ code in a way that is not natural, even for those with years of experience. Chops Net IP ("C"onnective "H"andcrafted "Op"enwork "S"oftware, Networking over Internet Protocol) simplifies asynchronous network programming and provides useful (and tasty!) abstractions for many types of communication patterns. + +Chops Net IP is layered on top of Chris Kohlhoff's Asio library (see [References](https://connectivecpp.github.io/doc/references.html)) allowing it to be portable across many compilers and platforms. When the C++ Networking TS is standardized (possibly C++ 23 but more likely C++ 26) Chops Net IP will directly use the networking facilities of the C++ standard library. + +Chops Net IP simplifies application code that processes data on multiple simultaneous TCP connections or UDP endpoints. All Chops Net IP operations (from the application viewpoint) are no-wait (i.e. there are no blocking methods) and all network processing operations are performed asynchronously. + +## Tasty Bites + +Chops Net IP functionality: + +- simplifies the creation of various IP (Internet Protocol) networking entities including TCP acceptors and connectors, UDP senders and receivers, and UDP multicast senders and receivers. +- simplifies the resolution of network names to IP addresses (i.e. domain name system lookups). +- abstracts message concepts in TCP (Transmission Control Protocol) and provides customization points in two areas: + 1. message framing, which is the code and logic that determines the begin and end of a message within the TCP byte stream. + 2. message processing, which is the code and logic that processes a message when the framing determines a complete message has arrived. +- provides buffer lifetime management for outgoing data. +- provides customization points for state changes in the networking entities, including: + - a TCP connection has become active and is ready for input and output. + - a UDP endpoint has been created and is ready for input and output. + - a TCP connection has been destroyed or a UDP socket has closed. +- implements the "plumbing" for asynchronous processing on multiple simultaneous connections. +- abstracts many differences between network protocols (TCP, UDP, UDP multicast), allowing easier application transitioning between protocol types. +- allows the application to control threading (no threads are created or managed inside Chops Net IP). +- is agnostic with respect to data marshalling or serialization or "wire protocols" (application code provides any and all data marshalling and endian logic). +- does not impose any structure on network message content. + +Chops Net IP is designed to make it easy and efficient for an application to create hundreds (or thousands) of network connections and handle them simultaneously. In particular, there are no threads or thread pools within Chops Net IP, and it works well with only one application thread invoking the event loop (an executor, in current C++ terminology). + +## Tasty Uses + +Example environments where Chops Net IP is a good fit: + +- Applications that are event driven or highly asynchronous in nature. +- Applications where data is generated and handled in a non-symmetric manner. For example, data may be generated on the TCP acceptor side, or may be generated on a TCP connector side, or on both sides depending on the use case. Similarly, applications where the data flow is bi-directional and sends or receives are data-driven versus pattern-driven work well with this library. +- Applications interacting with multiple (many) connections (e.g. handling multiple sensors or inputs or outputs), each with low to moderate throughput needs (i.e. IoT environments, chat networks, gaming networks). +- Small footprint or embedded environments, where all network processing is run inside a single thread. In particular, environments where a JVM (or similar run-time support) is too costly in terms of system resources, but have a relatively rich operating environment (e.g. Linux running on a small chip) are a very good fit. (Currently the main constraint is small system support in the Asio library implementation.) +- Applications with relatively simple network processing that need an easy-to-use and quick-for-development networking library. +- Applications with configuration driven networks that may need to switch (for example) between TCP connect versus TCP accept for a given connection, or between TCP and UDP for a given communication path. +- Peer-to-peer applications where the application doesn't care which side connects or accepts. +- Frameworks or groups of applications where abstracting wire-protocol logic from message processing logic makes sense. + +## Examples + +Example demo programs are in the [`/example`](https://github.com/connectivecpp/chops-net-ip) directory. + +The `simple_chat_demo.cpp` program has a listing of the multiple steps to set up working example. + +## Want More? + +A detailed overview, a C++ socket library comparison, and a FAQ is [available here](doc/overview.md). + +# C++ Language Requirements and Alternatives + +C++ 17 is the primary baseline for this repository. Additional notes on possible alternatives are [available here](https://connectivecpp.github.io/). + +# External Dependencies + +Production external dependencies: + +- Version 1.13 (or later) of Chris Kohlhoff's [`asio`](https://github.com/chriskohlhoff/asio) library is required. Note that it is the stand-alone Asio library, not the Boost Asio version. +- The [`utility-rack`](https://github.com/connectivecpp/utility-rack) library, which is a repository in the same GitHub account as Chops Net IP. + +Test external dependencies: + +- Version 2.8.0 (or later) of Phil Nash's [`Catch2`](https://github.com/catchorg/Catch2) library is required for all test scenarios. + +There are single file headers that have been copied into the `third_party` directory of the `utility-rack` repository from various GitHub repositories and do not require any external dependency management. These are: + +- Martin Moene's [`expected-lite`](https://github.com/martinmoene/expected-lite) library. + +See [References](https://connectivecpp.github.io/doc/references.html) for additional details. + +# Supported Compilers and Platforms + +Chops Net IP has been compiled and tests run on: + +- g++ 7.2, g++ 7.3, Linux (Ubuntu 17.10 - kernel 4.13, Ubuntu 18.04 - kernel 4.15) +- (TBD, will include at least clang on linux and vc++ on Windows) + +Follow the CI links for additional build environments. + +# Installation + +Chops Net IP is header-only, so installation consists of downloading or cloning and setting compiler include paths appropriately. No compile time configuration macros are defined. + +# References + +See [References](https://connectivecpp.github.io/doc/references.html) for details on dependencies and inspirations for Chops Net IP. + +# About + +Team member information is [available here](https://connectivecpp.github.io/). + +A few "Cliff Notes" are [available here](doc/cliff_notes.md). + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ee73cf1..a738e9b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,59 +1,34 @@ -# Copyright 2019-2020 by Cliff Green -# -# https://github.com/connectivecpp/chops-net-ip +# Copyright (c) 2019-2024 by Cliff Green # # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -cmake_minimum_required ( VERSION 3.12 ) - -project ( chops-net-ip-test VERSION 1.0 LANGUAGES CXX ) - -include ( "${cmake_all_repos_include_dir}/unit_test_vars.cmake" ) - -include ( "${cmake_include_dir}/header_dirs_var.cmake" ) -# the following will allow shared_test headers to be picked up by test code -set (header_dirs ${header_dirs} "${CMAKE_SOURCE_DIR}/test" ) - -set ( test_sources - "${test_source_dir}/shared_test/mock_classes_test.cpp" - "${test_source_dir}/shared_test/msg_handling_test.cpp" - "${test_source_dir}/shared_test/msg_handling_start_funcs_test.cpp" - "${test_source_dir}/shared_test/io_buf_test.cpp" - "${test_source_dir}/net_ip/detail/io_common_test.cpp" - "${test_source_dir}/net_ip/detail/net_entity_common_test.cpp" - "${test_source_dir}/net_ip/detail/output_queue_test.cpp" - "${test_source_dir}/net_ip/detail/tcp_acceptor_test.cpp" - "${test_source_dir}/net_ip/detail/tcp_connector_test.cpp" - "${test_source_dir}/net_ip/detail/tcp_io_test.cpp" - "${test_source_dir}/net_ip/detail/udp_entity_io_test.cpp" - "${test_source_dir}/net_ip/detail/wp_access_test.cpp" - "${test_source_dir}/net_ip_component/error_delivery_test.cpp" - "${test_source_dir}/net_ip_component/io_output_delivery_test.cpp" - "${test_source_dir}/net_ip_component/output_queue_stats_test.cpp" - "${test_source_dir}/net_ip_component/send_to_all_test.cpp" - "${test_source_dir}/net_ip/basic_io_interface_test.cpp" - "${test_source_dir}/net_ip/basic_io_output_test.cpp" - "${test_source_dir}/net_ip/endpoints_resolver_test.cpp" - "${test_source_dir}/net_ip/net_entity_test.cpp" - "${test_source_dir}/net_ip/net_ip_error_test.cpp" - "${test_source_dir}/net_ip/simple_variable_len_msg_frame_test.cpp" - "${test_source_dir}/net_ip/tcp_connector_timeout_test.cpp" - "${test_source_dir}/net_ip/net_ip_test.cpp" ) - -include ( "${cmake_include_dir}/add_target_dependencies.cmake" ) - -include ( "${cmake_all_repos_include_dir}/add_target_info_func.cmake" ) -include ( "${cmake_all_repos_include_dir}/unit_test_main_lib.cmake" ) -include ( "${cmake_all_repos_include_dir}/target_exe_func.cmake" ) +# (See accompanying file LICENSE.txt or copy at https://www.boost.org/LICENSE_1_0.txt) -enable_testing() +cmake_minimum_required ( VERSION 3.14 FATAL_ERROR ) + +# create project +project ( periodic_timer_test LANGUAGES CXX ) + +# add executable +add_executable ( periodic_timer_test periodic_timer_test.cpp ) +target_compile_features ( periodic_timer_test PRIVATE cxx_std_20 ) + +# add dependencies +include ( ../cmake/download_cpm.cmake ) -foreach ( test_src IN LISTS test_sources ) - get_filename_component ( targ ${test_src} NAME_WE ) - message ( "Calling unit_test_target_exe for: ${targ}" ) - unit_test_target_exe ( ${targ} ${test_src} ) -endforeach() +CPMAddPackage ( "gh:catchorg/Catch2@3.6.0" ) + +set ( CMAKE_THREAD_PREFER_PTHREAD TRUE ) +set ( THREADS_PREFER_PTHREAD_FLAG TRUE ) +find_package ( Threads REQUIRED ) + +# link dependencies +target_link_libraries ( periodic_timer_test PRIVATE + Threads::Threads periodic_timer asio Catch2::Catch2WithMain ) + +enable_testing() -# end of file +add_test ( NAME run_periodic_timer_test COMMAND periodic_timer_test ) +set_tests_properties ( run_periodic_timer_test + PROPERTIES PASS_REGULAR_EXPRESSION "All tests passed" + ) diff --git a/test/net_ip/CMakeLists.txt b/test/net_ip/CMakeLists.txt new file mode 100644 index 0000000..2ed862a --- /dev/null +++ b/test/net_ip/CMakeLists.txt @@ -0,0 +1,48 @@ +# Copyright (c) 2024 by Cliff Green +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +cmake_minimum_required ( VERSION 3.14 FATAL_ERROR ) + +# create project +project ( net_ip_test LANGUAGES CXX ) + +add_subdirectory ( detail ) + +# add dependencies +include ( ../../cmake/download_cpm.cmake ) + +CPMAddPackage ( "gh:catchorg/Catch2@3.6.0" ) + +set ( CMAKE_THREAD_PREFER_PTHREAD TRUE ) +set ( THREADS_PREFER_PTHREAD_FLAG TRUE ) +find_package ( Threads REQUIRED ) + +set ( test_app_names basic_io_interface_test + basic_io_output_test + endpoints_resolver_test + net_entity_test + net_ip_error_test + net_ip_test + simple_variable_len_msg_frame_test + tcp_connector_timeout_test ) + +# add executable +foreach ( test_app_name IN LISTS test_app_names ) + message ( "Creating test executable: ${test_app_name}" ) + add_executable ( ${test_app_name} ${test_app_name}.cpp ) + target_compile_features ( ${test_app_name} PRIVATE cxx_std_20 ) + target_link_libraries ( ${test_app_name} PRIVATE chops_net_ip Catch2::Catch2WithMain ) +endforeach() + +enable_testing() + +foreach ( test_app_name IN LISTS test_app_names ) + message ( "Creating test: run_${test_app_name}" ) + add_test ( NAME run_${test_app_name} COMMAND ${test_app_name} ) + set_tests_properties ( run_${test_app_name} + PROPERTIES PASS_REGULAR_EXPRESSION "All tests passed" + ) +endforeach() + diff --git a/test/net_ip/detail/CMakeLists.txt b/test/net_ip/detail/CMakeLists.txt new file mode 100644 index 0000000..9a0d09c --- /dev/null +++ b/test/net_ip/detail/CMakeLists.txt @@ -0,0 +1,46 @@ +# Copyright (c) 2024 by Cliff Green +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +cmake_minimum_required ( VERSION 3.14 FATAL_ERROR ) + +# create project +project ( net_ip_detail_test LANGUAGES CXX ) + +# add dependencies +include ( ../../../cmake/download_cpm.cmake ) + +CPMAddPackage ( "gh:catchorg/Catch2@3.6.0" ) + +set ( CMAKE_THREAD_PREFER_PTHREAD TRUE ) +set ( THREADS_PREFER_PTHREAD_FLAG TRUE ) +find_package ( Threads REQUIRED ) + +set ( test_app_names io_common_test + net_entity_common_test + output_queue_test + tcp_acceptor_test + tcp_connector_test + tcp_io_test + udp_entity_io_test + wp_access_test ) + +# add executable +foreach ( test_app_name IN LISTS test_app_names ) + message ( "Creating test executable: ${test_app_name}" ) + add_executable ( ${test_app_name} ${test_app_name}.cpp ) + target_compile_features ( ${test_app_name} PRIVATE cxx_std_20 ) + target_link_libraries ( ${test_app_name} PRIVATE chops_net_ip Catch2::Catch2WithMain ) +endforeach() + +enable_testing() + +foreach ( test_app_name IN LISTS test_app_names ) + message ( "Creating test: run_${test_app_name}" ) + add_test ( NAME run_${test_app_name} COMMAND ${test_app_name} ) + set_tests_properties ( run_${test_app_name} + PROPERTIES PASS_REGULAR_EXPRESSION "All tests passed" + ) +endforeach() + diff --git a/test/oldCMakeLists.txt b/test/oldCMakeLists.txt new file mode 100644 index 0000000..ee73cf1 --- /dev/null +++ b/test/oldCMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright 2019-2020 by Cliff Green +# +# https://github.com/connectivecpp/chops-net-ip +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +cmake_minimum_required ( VERSION 3.12 ) + +project ( chops-net-ip-test VERSION 1.0 LANGUAGES CXX ) + +include ( "${cmake_all_repos_include_dir}/unit_test_vars.cmake" ) + +include ( "${cmake_include_dir}/header_dirs_var.cmake" ) +# the following will allow shared_test headers to be picked up by test code +set (header_dirs ${header_dirs} "${CMAKE_SOURCE_DIR}/test" ) + +set ( test_sources + "${test_source_dir}/shared_test/mock_classes_test.cpp" + "${test_source_dir}/shared_test/msg_handling_test.cpp" + "${test_source_dir}/shared_test/msg_handling_start_funcs_test.cpp" + "${test_source_dir}/shared_test/io_buf_test.cpp" + "${test_source_dir}/net_ip/detail/io_common_test.cpp" + "${test_source_dir}/net_ip/detail/net_entity_common_test.cpp" + "${test_source_dir}/net_ip/detail/output_queue_test.cpp" + "${test_source_dir}/net_ip/detail/tcp_acceptor_test.cpp" + "${test_source_dir}/net_ip/detail/tcp_connector_test.cpp" + "${test_source_dir}/net_ip/detail/tcp_io_test.cpp" + "${test_source_dir}/net_ip/detail/udp_entity_io_test.cpp" + "${test_source_dir}/net_ip/detail/wp_access_test.cpp" + "${test_source_dir}/net_ip_component/error_delivery_test.cpp" + "${test_source_dir}/net_ip_component/io_output_delivery_test.cpp" + "${test_source_dir}/net_ip_component/output_queue_stats_test.cpp" + "${test_source_dir}/net_ip_component/send_to_all_test.cpp" + "${test_source_dir}/net_ip/basic_io_interface_test.cpp" + "${test_source_dir}/net_ip/basic_io_output_test.cpp" + "${test_source_dir}/net_ip/endpoints_resolver_test.cpp" + "${test_source_dir}/net_ip/net_entity_test.cpp" + "${test_source_dir}/net_ip/net_ip_error_test.cpp" + "${test_source_dir}/net_ip/simple_variable_len_msg_frame_test.cpp" + "${test_source_dir}/net_ip/tcp_connector_timeout_test.cpp" + "${test_source_dir}/net_ip/net_ip_test.cpp" ) + +include ( "${cmake_include_dir}/add_target_dependencies.cmake" ) + +include ( "${cmake_all_repos_include_dir}/add_target_info_func.cmake" ) +include ( "${cmake_all_repos_include_dir}/unit_test_main_lib.cmake" ) +include ( "${cmake_all_repos_include_dir}/target_exe_func.cmake" ) + +enable_testing() + +foreach ( test_src IN LISTS test_sources ) + get_filename_component ( targ ${test_src} NAME_WE ) + message ( "Calling unit_test_target_exe for: ${targ}" ) + unit_test_target_exe ( ${targ} ${test_src} ) +endforeach() + +# end of file +