Giter VIP home page Giter VIP logo

chops-net-ip's Introduction

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 Develop Branch | Build Status

GitHub Actions CI Build Status:

CMake Build Matrix

Latest tag: Latest Tag

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.

This project is distributed under the Boost Software License: Licence

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) 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 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.

C++ Language Requirements and Alternatives

C++ 17 is the primary baseline for this repository. Additional notes on possible alternatives are available here.

External Dependencies

Production external dependencies:

  • Version 1.13 (or later) of Chris Kohlhoff's asio library is required. Note that it is the stand-alone Asio library, not the Boost Asio version.
  • The 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 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:

See References 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 for details on dependencies and inspirations for Chops Net IP.

About

Team member information is available here.

A few "Cliff Notes" are available here.

chops-net-ip's People

Contributors

cliffg-softwarelibre avatar crghilardi avatar n-deutsch avatar ragerone avatar tgill880 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

chops-net-ip's Issues

Enhance net_entity class to add method to apply a function object to all IO interfaces

A useful addition to the net_entity class is to provide a way to apply a function object to all current IO interfaces active for the net entity. For a TCP connector it would allow sending data to the single (if present) TCP connection, for a TCP acceptor it would allow sending to all (0 to N) TCP connections (and for UDP it would be similar to the TCP connector).

A design decision will need to be made to either 1) provide a method that returns a list of active io_interface objects; or 2) provide a method that takes a function object to be invoked with each active io_interface.

Determine IPv4 vs IPv6 processing in the UDP entity

There is a "TODO" in the net_ip/detail/udp_entity_io.hpp file that needs to be analyzed and implemented. The current code only supports IPv4 UDP datagrams, and this needs to be generalized for both IPv4 and IPv6.

Use std::expected for error and exception handling

The std::expected feature, which is likely to be in C++ 20, adds some significant improvements to the way errors are handled and reported. This is significant in chops--net-ip. This issue is to integrate std::expected (an early non-standard version, probably from Martin Moene) into the codebase and design.

Provide simple variable len message framing as start_io method

Currently the start_io methods of the basic_io_interface class template offer two ways to start a binary TCP data flow - either with an application supplied message frame, or with fixed size messages. A "simple variable length message" component is defined, which implements a very common use case - binary messages with a fixed size header containing a message length, and a variable length message body.

The "simple variable length message framing" is such as common use case that it should be directly supported by the Chops Net IP core library instead of being offered as a component. Note that this is a specific implementation of the message frame, so start_io can simply use a small functor class and pass it to the generalized start_io call.

Consider providing a future-based send method

An alternative to output queues for outgoing data is to let applications send a message or buffer one at a time with some form of notification when each write completes. This would require a send method that returns a std::future, which resolves when the write completes. Discussion is needed as to whether the application would be completely responsible for buffer lifetime management, or whether we require some form of reference count or move (or similar) for the output buffer.

Chops Net IP would need to track whether a write is in progress or not. The library should prevent applications from more than one write at a time (on a given connection).

Split basic_io_interface into basic_io_interface and basic_io_output classes

Currently the basic_io_interface class template provides (primarily) two sets of operations - methods for starting and stopping io, and sending data. The application code for these two sets of operations is distinct, different, and may be (typically will be) in different subsystems.

By splitting the basic_io_interface class into two classes, it separates the functionality into more logical responsibilities. It also allows a performance improvement for sending data, as the basic_io_output class can keep a pointer or reference to the IO handler, so that a weak_ptr does not have to be locked into a shared_ptr for every send.

Consider templatizing outgoing data buffer container

As of April 2019 outgoing buffers are hard-coded to const-shared-buffer. This could be templatized, allowing application code to use other types for outgoing buffers. However, the hard constraint on the type is that the lifetime of the underlying data buffer must be valid until notification is received within chops-net-ip that the data has been delivered. const-shared-buffer is a reference counted buffer, which satisfies this constraint. Buffers that move may also satisfy this constraint, although some analysis needs to be performed. Static / global data buffers also satisfy the constraint, although then it is up to the application to manage which static / global buffer is being used or not.

Making this design change will affect many portions of the code and API, so this is not a simple or trivial redesign.

Consider templatizing the net_entity container in the net_ip class

Currently the container inside the net_ip class is a std::vector, which is a good default. However, some applications may wish to use a different container, or may wish to use statically allocated memory instead of a dynamic sized container (e.g. in a small embedded environment).

The container type could be a template parameter on the class (changing net_ip into a class template instead of a regular class).

This issue is similar to the other Chops Net IP issues where we are providing more flexibility in the container and buffer types.

Analyze connect error flag in TCP connector implementation

There is a "TODO" in the net_ip/detail/tcp_connector.hpp file that needs to be analyzed and implemented as appropriate. Specifically, an error on connect might be due to multiple reasons and different error branches taken. In addition, the handler may be shutting down.

Wrap all Asio constructs in public API

The chops-net-ip API exposes Asio constructs in multiple places (e.g. an Asio endpoint). Consider a very light wrapper over these so that the API is only chops-net-ip (or std). An easy way to accomplish this might be with using declarations.

Improve and decide on shutdown handling

Shutting down has lingering object cleanup issues. Investigate and improve shutdown logic. This may include using "post to the executor" logic instead of directly calling state change callbacks.

First demo program (local_chat_demo.cpp) leaks memory like a sieve

Describe the bug
When the program successfully exits, there are multiple memory allocations that have not been deallocated.

To Reproduce
g++ -std=c++17 -g3 -fsanitize=address (etc)
OR
valgrind --tool=memcheck --leak-check=yes ./a.out

Expected behavior
No memory leaks should be present

Desktop:

  • OS: [Ubuntu Linux 13.04]
  • Compiler [g++ 7.3]
  • Version [1.0]

Remove const char* overload of make_tcp_connector method in net_ip class

Currently there is an overload of the make_tcp_connector method in the net_ip class for const char*. This is so that calling make_tcp_connector with two C style strings does not match the make_tcp_connector method that takes a beginning and end iterator. A const char* can be an iterator, and the compiler matches that before doing an implicit conversion and matching the method that takes std::string_view (which is the method that should be matched).

The iterator version of make_tcp_connector can be disabled through std::enable_if matching on const char* (or char*), which then leaves only the std::string_view method as a matching method. This should be implemented to simplify the API.

Create a "Hello World" example tutorial

A "Hello World" type of example tutorial is needed. This fits into the bigger picture of the missing "middle layer" of documentation - tutorials, how-to's, etc.

Create an in-depth tutorial

An in-depth tutorial is needed, explaining the layers of the software, how they fit together, the various flavors of how to use the main pieces of the library. Appropriate diagrams are also needed.

Heighten visibility of component directory and contents

The Chops Net IP library has a set of core classes and functions, the minimum feature set needed for a cohesive library. In addition, there is a "component" directory under "net_ip" that contains classes and functions layered on top of the core set. The functionality in "component" packages up commonly needed use cases.

The code in the "component" directory should be more visible. The directory could be pushed up to be parallel to the "net_ip" directory. Alternatively, the contents could be split out into a separate repository.

Pros and cons:

  1. Push "component" directory up one level, keep it in the chops_net_ip repo:
  • work to do: small amount of restructuring of production and test (and possibly example) code
  • pros: keeps component code in the same repo as core code, bugs and unit tests are tightly integrated
  • cons: enhancements and bug fixes in the component code causes churn (more releases, for example) in the chops-net-ip repo.
  1. Create a "chops-net-ip-component" repository:
  • work to do: create repo, move existing component contents to new directory, change unit tests to not use component classes, only core facilities
  • pros: makes a clear delineation between core functionality (in chops-net-ip) and functionality on top of the core classes; changes can be made to component while keeping core unchanged
  • cons: unit tests will need some significant changes to not use component functionality

The earlier this decision is made, the better, so comments are very welcome, @tgill880, @oxenran - thanks!

Implement UDP multicast

Most of the UDP multicast framework is in place, but much of the implementation is missing.

Consider templatizing outgoing queue container

As of April 2019, the outgoing queue is hard-coded in chops-net-ip (as std::queue). Consider making this more generic by templatizing the outgoing queue container. This will affect many aspects of the API, so this is not a simple or trivial redesign.

Change TCP connector timeout parameter to a policy function object instead of an integer

The TCP connector provides a timeout parameter. However, this does not allow any application customization of how to manage timeouts. A common use case is an "exponential backoff" timeout algorithm, which increases the timeout if the connection attempt fails. This minimizes network traffic in the case where a remote host is not available, but the TCP connector should keep attempting to connect. Other algorithms to manage the timeout value should be allowed.

In addition to allowing the application to vary the timeout value, it should be possible for the application to specify "you've tried enough, quit trying to connect".

This is a better way for a TCP connector to stop connection attempts than another design enhancement - returning bool from the state change notification (which ended up being rejected for many implementation reasons).

A specific implementation of a timeout parameter policy would provide a default timeout policy by Chops Net IP (with some initialization parameters that would be useful for many applications), but the overall policy would be a function object allowing the application complete customization as needed.

Change TCP connector to auto reconnect after connection failure

Currently the TCP connector will not automatically attempt reconnects after a TCP connection failure. The application code is required to call "start" on the TCP connector net entity. The default behavior should be to automatically reconnect (assuming the reconnect timeout parameter is >0), and if the application does not want reconnects it can call "stop" on the net entity.

This requires careful thought about the use cases (both approaches are present in real world applications) and investigation of example and test code.

Change IO State Change function object callback signature to return bool

Currently the IO State Change function object callback does not return a value. Change the API to return a bool instead. If false, this results in the same as calling stop on the net_entity object. Returning true continues the net_entity processing.

True or false can be returned in both phases of the IO state change - on connection startup as well as connection teardown. Returning false allows the TCP connector to quit attempting to reconnect, or to bring down a TCP acceptor. For UDP net entities it is less useful, as the state change will only be invoked after stop or after an error.

Create a distributed testing application

Apps for distributed TCP and UDP testing will be very useful for verifying functional interaction both between operating systems (Windows, Linux, macOS, Raspbian, etc) as well as different hosts running the same operating system.

The first distributed test application will be named "Test Data Blaster" (T-DB) and consists of two (initially) executables - an executable that sends and receives test data, and a monitoring process which receives statistics and status messages and sends a shutdown message when initiated by the user.

The monitoring app is a server (acceptor), and both a C++ and Python version is expected. An initial console mode C++ monitoring app should be written, then later a GUI oriented monitoring app (Python or other similar language).

Initially TCP (only) will be supported, but at some point UDP will be supported.

More details for T-DB is in the README in the chops-net-ip/test/test_data_blaster directory.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.