{"id":19168344,"url":"https://github.com/bloomberg/ntf-core","last_synced_at":"2025-04-05T20:09:32.328Z","repository":{"id":146904112,"uuid":"575595477","full_name":"bloomberg/ntf-core","owner":"bloomberg","description":"Sockets, timers, resolvers, events, reactors, proactors, and thread pools for asynchronous network programming","archived":false,"fork":false,"pushed_at":"2025-03-25T02:35:39.000Z","size":4392,"stargazers_count":82,"open_issues_count":18,"forks_count":28,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-29T19:08:09.512Z","etag":null,"topics":["asynchronous","cpp","socket"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bloomberg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-07T21:42:13.000Z","updated_at":"2025-03-28T01:22:50.000Z","dependencies_parsed_at":"2023-10-11T16:05:30.158Z","dependency_job_id":"9ec3c6a6-d846-4103-81fa-dde23cd47be2","html_url":"https://github.com/bloomberg/ntf-core","commit_stats":null,"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fntf-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fntf-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fntf-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bloomberg%2Fntf-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bloomberg","download_url":"https://codeload.github.com/bloomberg/ntf-core/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393572,"owners_count":20931813,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous","cpp","socket"],"created_at":"2024-11-09T09:42:21.191Z","updated_at":"2025-04-05T20:09:32.309Z","avatar_url":"https://github.com/bloomberg.png","language":"C++","readme":"## The Network Transport Framework: Core Libraries\n\nThe Network Transport Framework (NTF) is an open-source collection of libraries\nfor asynchronous network programming for scalable, high-performance\napplications.  This repository contains libraries providing the core APIs\nfor asynchronous sockets, timers, resolvers, reactors, proactors, and thread\npools.\n\nIn general, NTF provides building blocks and higher-level abstractions for\nasynchronously sending and receiving data between processes. More specifically,\nNTF provides an abstraction around the differences in the native networking\nAPIs offered by the supported operating system, and introduces many useful\nfeatures commonly required by networked applications. The principle feature\nof the sockets of this library is the introduction of *virtual* *send* *and*\n*receive* *queues*, which provide a message-oriented, thread-safe (concurrent),\nsend and receive API for sockets using transports with either datagram\nsemantics or stream semantics. Additionally, these virtual queues allow users\nto operate sockets both reactively (i.e. in the Unix readiness model) or\nproactively (i.e. in the Windows I/O completion model), regardless of the\noperating system and interface to that operating system (e.g. *select*,\n*kqueue*, *epoll*, *io_uring*, *I/O completion ports* etc.) NTF supports both\nstream sockets using TCP and datagram sockets using UDP communicating over\neither IPv4 or IPv6 networks. NTF also supports local (aka Unix) domain\nsockets for efficiently communicating between processes on the same machine.\n\nThe mechanisms in NTF are scalable, efficient, and multi-threaded. Its\nlibraries are intended for applications needing to manage anywhere from\na single socket to many thousands of simultaneous sockets.\n\n#### Table of Contents\n\n- [Architecture](#architecture)\n- [Features](#features)\n- [Quick Start](#quick-start)\n- [System Requirements](#system-requirements)\n- [Build Instructions](#build-instructions)\n- [Contributing](#contributing)\n- [License](#license)\n- [Code of Conduct](#code-of-conduct)\n- [More Information](#more-information)\n\n---\n\n### Architecture\n\nThe Network Transport Framework designs its core API around the following\nconcepts.\n\n- [Datagram Socket](groups/ntc/ntci/ntci_datagramsocket.h)\n  \u003cp\u003e\n  A connection-less, unreliable, unicasting or multicasting socket with unordered message semantics sending and receiving data.\n  \u003c/p\u003e\n- [Stream Socket](groups/ntc/ntci/ntci_streamsocket.h)\n  \u003cp\u003e\n  A connection-oriented, reliable, unicasting socket with stream semantics sending and receiving data.\n  \u003c/p\u003e\n- [Listener Socket](groups/ntc/ntci/ntci_listenersocket.h)\n  \u003cp\u003e\n  An acceptor of stream socket connections.\n  \u003c/p\u003e\n- [Timer](groups/ntc/ntci/ntci_timer.h)\n  \u003cp\u003e\n  Schedule and reschedule a function to execute at a point in time, and to potentially recur.\n  \u003c/p\u003e\n- [Strand](groups/ntc/ntci/ntci_strand.h)\n  \u003cp\u003e\n  Guarantee the sequential, non-concurrent execution of a series of functions.\n  \u003c/p\u003e\n- [Reactor](groups/ntc/ntci/ntci_reactor.h)\n  \u003cp\u003e\n  Asynchronous I/O events in the \"Unix\" readiness paradigm. Available on all platforms.\n  \u003c/p\u003e\n- [Proactor](groups/ntc/ntci/ntci_proactor.h)\n  \u003cp\u003e\n  Asynchronous socket I/O and timers in the \"Windows\" completion paradigm. Available on Darwin, Linux, and Windows.\n  \u003c/p\u003e\n- [Driver](groups/ntc/ntci/ntci_driver.h)\n  \u003cp\u003e\n  A socket and timer factory where I/O and timers are driven manually by a user thread (e.g., the main program thread), at the user's discretion.  The user thread drives an internally managed reactor or proactor, the implementation (e.g., epoll, kqueue, I/O completion ports) of which is configurable at runtime.\n  \u003c/p\u003e\n- [Thread](groups/ntc/ntci/ntci_thread.h)\n  \u003cp\u003e\n  A single thread, acting as a socket and timer factory, running in the background that automatically manages the detection and completion of socket I/O events and timers. The thread drives an internally managed reactor or proactor, of the implementation (e.g., epoll, kqueue, I/O completion ports, etc.) of which is configurable at runtime.\n  \u003c/p\u003e\n- [Interface](groups/ntc/ntci/ntci_interface.h)\n  \u003cp\u003e\n  A group of threads, collectively acting as a socket and timer factory, over which sockets and timers are statically or dynamically load balanced according to configurable and programmable criteria. Each thread is run in the background and automatically manages the detection and completion of socket I/O operations, events, and timers. Threads in the thread pool drive internally managed reactors or proactors, the implementation (e.g., epoll, kqueue, I/O completion ports, etc.) of which are configurable at run-time.\n  \u003c/p\u003e\n\n\u003ccenter\u003e\u003cimg src=\"docs/architecture.svg\"/\u003e\u003c/center\u003e\n\n\u003csub\u003e\u003csup\u003e\nJump to\n[Table of Contents](#table-of-contents) |\n[Architecture](#architecture) |\n[Features](#features) |\n[Quick Start](#quick-start) |\n[System Requirements](#system-requirements) |\n[Build Instructions](#build-instructions)\n\u003c/sup\u003e\u003c/sub\u003e\n\n---\n\n### Features\n\nThe Network Transport Framework supports a wide variety of features across the\ntwo core libraries.\n\n#### Network Transport System (NTS)\n\n- Rich set of networking vocabulary types including addresses, endpoints, and errors\n- Basic blocking and non-blocking, object-oriented, unicasting or multicasting datagram sockets using either UDP over IPv4/IPv6 or in the local (aka Unix) domain\n- Basic blocking and non-blocking, object-oriented, unicasting stream sockets using either TCP over IPv4/IPv6 or in the local (aka Unix) domain\n- Blocking hostname to address resolution and address to hostname reverse resolution\n- Blocking service name to port number resolution and port number to service name reverse resolution\n\n#### Network Transport Core (NTC)\n\n- Asynchronous datagram and stream sockets using callbacks (in the proactive \"Windows\" style) or events (in the reactive \"Unix\" style)\n- Run-time selectable drivers: select, poll, epoll (on Linux), pollset (on AIX), event ports and /dev/poll (on Solaris), kqueue (on FreeBSD/Darwin), and I/O completion ports (on Windows)\n- Asynchronous hostname to address resolution and address to hostname reverse resolution\n- Asynchronous service name to port number resolution and port number to service name reverse resolution\n- Asynchronous, high-precision one-shot or periodic timers\n- Strand semantics: serializability of a sequence of operations executed on multiple threads\n- Integrated TLS: any stream socket can be arbitrarily upgraded into a TLS session and then downgraded back into a raw transport\n- Static load balancing: I/O for a particular socket is always performed by the same I/O thread; fast and efficient but subject to \"head of line blocking\" situations where I/O for one thread may starve the process from processing available I/O for other sockets assigned to the same I/O thread\n- Dynamic load balancing: I/O for a particular socket may be performed by any I/O thread; slower and less efficient but avoids \"head of line blocking\" situations, where I/O for one thread will not starve the process from processing available I/O for other sockets\n- Read operation queuing: multiple read operations can be simultaneously queued from multiple threads\n- Automatic and manual read flow control to apply back pressure to remote senders\n- Read rate limiting: Limit the rate at which data is copied from socket receive buffers, using a policy that may be potentially shared and enforced across multiple sockets\n- Read cancellation: Cancel a read operation that has not yet been satisfied\n- Read expiration: Assign a deadline before which a read operation must be satisfied\n- Write operation queueing: multiple write operations can be simultaneously queued from multiple threads\n- Write atomicity: Write operations are guaranteed to be entirely transmitted as a logical sequence, without the need to handle partial writes\n- Automatic and manual write flow control to cooperate with back pressure applied by remote receivers\n- Write rate limiting: Limit the rate at which data is copied to a socket send buffer, using a policy that may be potentially shared and enforced across multiple sockets\n- Write expiration: Assign a deadline before which a blob must be started to be copied to a socket send buffer, otherwise the write fails and is discarded.\n- Write cancellation: Cancel a write operation provided it has not yet been started to be copied to a socket send buffer\n- Write callbacks: Notify the user when data to be sent is fully copied to a socket send buffer; useful for senders that represent the data to be sent using something like a raw pointer to the buffer and a length, to manage the lifetime of that data\n- Write data representation variability: Data to be sent may be represented as a raw pointer and a length, or an array of (non-data owning) buffers, or blobs, or blob  buffers\n- Efficient transmission of data stored in a file on the local filesystem, without copying that data into userspace. [on Linux and Solaris only]\n\n\u003csub\u003e\u003csup\u003e\nJump to\n[Table of Contents](#table-of-contents) |\n[Architecture](#architecture) |\n[Features](#features) |\n[Quick Start](#quick-start) |\n[System Requirements](#system-requirements) |\n[Build Instructions](#build-instructions)\n\u003c/sup\u003e\u003c/sub\u003e\n\n---\n\n### Quick Start\n\nThe following code illustrates the general look and feel of the NTF core API.\nThis example shows how to create an asynchronous listener socket to accept\na connection, an asynchronous client socket that connects to that listener\nsocket, and an asynchronous server socket accepted by the listener that is the\npeer of the client socket. The sockets are asynchronously driven by a pool of\nI/O threads.\n```c++\n    // Initialize the library.\n\n    ntcf::SystemGuard systemGuard(ntscfg::Signal::e_PIPE);\n\n    ntsa::Error      error;\n    bslmt::Semaphore semaphore;\n\n    // Create and start a pool of I/O threads.\n\n    ntca::InterfaceConfig interfaceConfig;\n    interfaceConfig.setThreadName(\"example\");\n\n    bsl::shared_ptr\u003cntci::Interface\u003e interface =\n                               ntcf::System::createInterface(interfaceConfig);\n\n    error = interface-\u003estart();\n    BSLS_ASSERT(!error);\n\n    // Create a listener socket and begin listening.\n\n    ntca::ListenerSocketOptions listenerSocketOptions;\n    listenerSocketOptions.setTransport(ntsa::Transport::e_TCP_IPV4_STREAM);\n    listenerSocketOptions.setSourceEndpoint(\n                          ntsa::Endpoint(ntsa::Ipv4Address::loopback(), 0));\n\n    bsl::shared_ptr\u003cntci::ListenerSocket\u003e listenerSocket =\n                    interface-\u003ecreateListenerSocket(listenerSocketOptions);\n\n    error = listenerSocket-\u003eopen();\n    BSLS_ASSERT(!error);\n\n    error = listenerSocket-\u003elisten();\n    BSLS_ASSERT(!error);\n\n    // Connect a socket to the listener.\n\n    ntca::StreamSocketOptions streamSocketOptions;\n    streamSocketOptions.setTransport(ntsa::Transport::e_TCP_IPV4_STREAM);\n\n    bsl::shared_ptr\u003cntci::StreamSocket\u003e clientSocket =\n                          interface-\u003ecreateStreamSocket(streamSocketOptions);\n\n    ntca::ConnectOptions connectOptions;\n\n    ntci::ConnectCallback connectCallback =\n        clientSocket-\u003ecreateConnectCallback(\n            [\u0026](const bsl::shared_ptr\u003cntci::Connector\u003e\u0026 connector,\n                const ntca::ConnectEvent\u0026               event)\n    {\n        BSLS_ASSERT(!event.context().error());\n        semaphore.post();\n    });\n\n    error = clientSocket-\u003econnect(listenerSocket-\u003esourceEndpoint(),\n                                  connectOptions,\n                                  connectCallback);\n    BSLS_ASSERT(!error);\n\n    semaphore.wait();\n\n    // Accept a connection from the listener socket's backlog.\n\n    bsl::shared_ptr\u003cntci::StreamSocket\u003e serverSocket;\n\n    ntca::AcceptOptions acceptOptions;\n\n    ntci::AcceptCallback acceptCallback =\n        listenerSocket-\u003ecreateAcceptCallback(\n            [\u0026](const bsl::shared_ptr\u003cntci::Acceptor\u003e\u0026     acceptor,\n                const bsl::shared_ptr\u003cntci::StreamSocket\u003e\u0026 streamSocket,\n                const ntca::AcceptEvent\u0026                   event)\n    {\n        BSLS_ASSERT(acceptor == listenerSocket);\n        BSLS_ASSERT(!event.context().error());\n        serverSocket = streamSocket;\n        semaphore.post();\n    });\n\n    error = listenerSocket-\u003eaccept(acceptOptions, acceptCallback);\n    BSLS_ASSERT(!error);\n\n    semaphore.wait();\n\n    // Send some data from the client to the server.\n\n    const char        k_CLIENT_DATA[]    = \"Hello, world!\";\n    const bsl::size_t k_CLIENT_DATA_SIZE = sizeof k_CLIENT_DATA - 1;\n\n    bdlbb::Blob clientData(clientSocket-\u003eoutgoingBlobBufferFactory().get());\n    bdlbb::BlobUtil::append(\u0026clientData, k_CLIENT_DATA, k_CLIENT_DATA_SIZE);\n\n    ntca::SendOptions sendOptions;\n\n    ntci::SendCallback sendCallback =\n        clientSocket-\u003ecreateSendCallback(\n            [\u0026](const bsl::shared_ptr\u003cntci::Sender\u003e\u0026 sender,\n                const ntca::SendEvent\u0026               event)\n    {\n        BSLS_ASSERT(sender == clientSocket);\n        BSLS_ASSERT(!event.context().error());\n        semaphore.post();\n    });\n\n    error = clientSocket-\u003esend(clientData, sendOptions, sendCallback);\n    BSLS_ASSERT(!error);\n\n    semaphore.wait();\n\n    // Receive the expected amount of data from the client.\n\n    bdlbb::Blob serverData(serverSocket-\u003eoutgoingBlobBufferFactory().get());\n\n    ntca::ReceiveOptions receiveOptions;\n    receiveOptions.setSize(k_CLIENT_DATA_SIZE);\n\n    ntci::ReceiveCallback receiveCallback =\n        serverSocket-\u003ecreateReceiveCallback(\n            [\u0026](const bsl::shared_ptr\u003cntci::Receiver\u003e\u0026 receiver,\n                const bsl::shared_ptr\u003cbdlbb::Blob\u003e     data,\n                const ntca::ReceiveEvent\u0026              event)\n    {\n        BSLS_ASSERT(receiver == serverSocket);\n        BSLS_ASSERT(!event.context().error());\n        serverData = *data;\n        semaphore.post();\n    });\n\n    error = serverSocket-\u003ereceive(receiveOptions, receiveCallback);\n    BSLS_ASSERT(!error);\n\n    semaphore.wait();\n\n    // Ensure the data received matches the data sent.\n\n    BSLS_ASSERT(bdlbb::BlobUtil::compare(clientData, serverData) == 0);\n\n    // Close the listener socket.\n\n    {\n        ntci::CloseCallback closeCallback =\n            listenerSocket-\u003ecreateCloseCallback([\u0026]()\n        {\n            semaphore.post();\n        });\n\n        listenerSocket-\u003eclose(closeCallback);\n        semaphore.wait();\n    }\n\n    // Close the client socket.\n\n    {\n        ntci::CloseCallback closeCallback =\n            clientSocket-\u003ecreateCloseCallback([\u0026]()\n        {\n            semaphore.post();\n        });\n\n        clientSocket-\u003eclose(closeCallback);\n        semaphore.wait();\n    }\n\n    // Close the server socket.\n\n    {\n        ntci::CloseCallback closeCallback =\n            serverSocket-\u003ecreateCloseCallback([\u0026]()\n        {\n            semaphore.post();\n        });\n\n        serverSocket-\u003eclose(closeCallback);\n        semaphore.wait();\n    }\n\n    // Stop the pool of I/O threads.\n\n    interface-\u003eshutdown();\n    interface-\u003elinger();\n```\n\u003csub\u003e\u003csup\u003e\nJump to\n[Table of Contents](#table-of-contents) |\n[Architecture](#architecture) |\n[Features](#features) |\n[Quick Start](#quick-start) |\n[System Requirements](#system-requirements) |\n[Build Instructions](#build-instructions)\n\u003c/sup\u003e\u003c/sub\u003e\n\n---\n\n### System Requirements\n\nNTF requires the following minimum operating system versions. Any operating\nsystem not listed, or any operating system listed but whose version is less\nthan the minimum specified version is not supported.\n\n| Operating System | Version |\n| ---------------- | ------- |\n| AIX              | 7.1     |\n| Darwin           | 18.7.0  |\n| Linux            | 3.10.0  |\n| Windows          | Windows Vista with Service Pack 1 (SP1), Windows Server 2008 |\n| Solaris          | 5.11    |\n\nNTF requires the following minimum compiler versions. Any compiler not listed,\nor any compiler listed but whose version is less than the minimum specified\nversion is not supported.\n\n| Compiler       | Version |\n| --------       | ------- |\n| GCC            | 7.3     |\n| clang          | 10.0.1  |\n| Solaris Studio | 5.13    |\n| xlc            | 16.1.0  |\n\nNTF requires the C++03 or later language standard version.\n\n---\n\n### Build Instructions\n\nNTF uses a build system that emulates a standard GNU autotools-like build\nprocess, which drives the either the\n[BDE build system](https://github.com/bloomberg/bde-tools) or a custom\nbuild system implemented in this repository. Both supported build systems are\nimplemented using [CMake](https://cmake.org/).\n\nUsers are encouraged to first run `./configure` to setup the build\nconfiguration, then run `make` to build all artifacts, the run `make install`\nto install all headers, libraries, and build meta-data into the desired\ndirectories on the file system.\n\nAlternatively, users may use the BDE build system interface directly, depending\non their comfort level. When using the BDE build system directly, users are\nresponsible for setting up all environment variables and installing all\nnecessary dependencies themselves.\n\nThe exact build instructions depend on the type of machine on which this\nrepository is being built. See the following sections for more details.\n\n#### Building on AIX, Darwin, FreeBSD, Linux, and Solaris\n\nFirst, ensure that the build prerequisites are installed on the build machine:\nGit, Perl, Python3, and CMake. Ensure that the directories containing each\nrespective software's binaries are on the PATH.\n\nNext, install the [BDE build system](https://github.com/bloomberg/bde-tools).\nEnsure the directory containing the BDE build system executables is included in\nthe PATH environment variable.\n\nNext, build and install the [BDE libraries](https://github.com/bloomberg/bde).\n\nWhen all prerequisites are satisfied, perform the following steps to build,\ntest, and install the binary artifacts of this repository:\n\n1. Clone the repository.\n```\n    $ git clone https://github.com/bloomberg/ntf-core \u003cpath/to/ntf-core\u003e\n    $ cd \u003cpath/to/ntf/core\u003e\n```\n\n2. Configure the build for the current platform. Specify the `--prefix` to\n   the directory tree into which the BDE libraries are installed, which is\n   typically `/opt/bb` by default. The build artifacts that result from\n   building this repository will be installed in the same location.\n```\n    $ ./configure --prefix \u003cpath/to/bde\u003e\n```\n\n3. Build all libraries.\n```\n    $ make\n```\n\n4. Optionally build and run all tests.\n```\n    $ make test\n```\n\n5. Optionally install the build output into the prefix.\n```\n    $ make install\n```\n\nRun `./configure --help` for a complete description of all build configuration\noptions.\n\n#### Building on Windows\n\nFirst, ensure that the build prerequisites are installed on the build machine:\nGit, Strawberry Perl, Python3, CMake, and Visual Studio. Note that modern\nversions of Visual Studio may have CMake bundled. Ensure that the directories\ncontaining each respective software's binaries are on the PATH.\n\nNext, install the [BDE build system](https://github.com/bloomberg/bde-tools).\nEnsure the directory containing the BDE build system executables is included in\nthe PATH environment variable.\n\nNext, build and install the [BDE libraries](https://github.com/bloomberg/bde).\n\nWhen all prerequisites are satisfied, perform the following steps to build,\ntest, and install the binary artifacts of this repository:\n\n1. Open a Visual Studio command prompt.\n\n2. Clone the repository.\n```\n    $ git clone https://github.com/bloomberg/ntf-core \u003cpath/to/ntf-core\u003e\n    $ cd \u003cpath/to/ntf/core\u003e\n```\n\n3. Configure the build for the current platform. Specify the `--prefix` to\n   the directory tree into which the BDE libraries are installed, which is\n   typically `/opt/bb` by default. The build artifacts that result from\n   building this repository will be installed in the same location.\n```\n    $ .\\configure --prefix \u003cpath/to/bde\u003e\n```\n\n4. Build all libraries.\n```\n    $ nmake\n```\n\n5. Optionally build and run all tests.\n```\n    $ nmake test\n```\n\n6. Optionally install the build output into the prefix.\n```\n    $ nmake install\n```\n\nRun `.\\configure --help` for a complete description of all build configuration\noptions.\n\n\u003csub\u003e\u003csup\u003e\nJump to\n[Table of Contents](#table-of-contents) |\n[Architecture](#architecture) |\n[Features](#features) |\n[Quick Start](#quick-start) |\n[System Requirements](#system-requirements) |\n[Build Instructions](#build-instructions)\n\u003c/sup\u003e\u003c/sub\u003e\n\n---\n\n### Contributing\n\nContributions to this project are welcome. Open an [issue](../../issues) to\nask a question or a report a bug. Create a [pull request](../../pulls) to\npropose a change to the code in this repository. Contributors are expected to\nfollow a [code of conduct](https://github.com/bloomberg/.github/blob/main/CODE_OF_CONDUCT.md).\nIf you have any concerns about this code, or behavior which you have\nexperienced in the project, please contact us at opensource@bloomberg.net.\n\n#### Developer's Certificate of Origin\n\nSince this project is distributed under the terms of the\n[Apache License version 2.0](LICENSE), contributions that you make are\nlicensed under the same terms. For us to be able to accept your pull\nrequest, we will need explicit confirmation from you that you are able and\nwilling to provide them under these terms, and the mechanism we use to do this\nis called a [Developer's Certificate of Origin](https://github.com/bloomberg/.github/blob/main/DCO.md).\nThis is very similar to the process used by the Linux(R) kernel, Samba, and\nmany other major open source projects.\n\nTo participate under these terms, all that you must do is include a line like\nthe following as the last line of the commit message for each commit in your\npull request:\n\n    Signed-Off-By: Random J. Developer \u003crandom@developer.example.org\u003e\n\nThe simplest way to accomplish this is to add `-s` or `--signoff` to your `git\ncommit` command.\n\nYou must use your real name (sorry, no pseudonyms, and no anonymous\ncontributions).\n\n\n#### Reporting Security Vulnerabilities\n\nIf you believe you have identified a security vulnerability in this project,\nplease send email to the project team at opensource@bloomberg.net, detailing\nthe suspected issue and any methods you've found to reproduce it.\n\nPlease do *not* open an issue in the GitHub repository, as we'd prefer to keep\nvulnerability reports private until we've had an opportunity to review and\naddress them.\n\n---\n\n### License\n\nAll source code in this repository is distributed under the\n[Apache License version 2.0](LICENSE).\n\n---\n\n### Code of Conduct\n\nThis project has adopted a [code of conduct](https://github.com/bloomberg/.github/blob/main/CODE_OF_CONDUCT.md).\nIf you have any concerns about this code, or behavior which you have\nexperienced in the project, please contact us at opensource@bloomberg.net.\n\n---\n\n### More Information\n\nMore detailed information is available on certain topics.\n\n- [Package and Component Levelization](docs/levelization.svg)\n\nNTF is collection of BDE-style libraries built on top of BDE.  For more\ninformation about the BDE framework, please see:\n\n- [BDE Repository](http://github.com/bloomberg/bde)\n- [BDE Wiki](http://github.com/bloomberg/bde/wiki)\n- [BDE Mission Statement](http://github.com/bloomberg/bde/wiki/Mission-Statement)\n- [BDE Quick-Start Guide](http://github.com/bloomberg/bde/wiki/Getting-Started)\n\n\u003csub\u003e\u003csup\u003e\nJump to\n[Table of Contents](#table-of-contents) |\n[Architecture](#architecture) |\n[Features](#features) |\n[Quick Start](#quick-start) |\n[Build Instructions](#build-instructions)\n\u003c/sup\u003e\u003c/sub\u003e\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbloomberg%2Fntf-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbloomberg%2Fntf-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbloomberg%2Fntf-core/lists"}