Compare commits

...

4 commits

Author SHA1 Message Date
8f2eddec47 fixes for nng-1.8.0 2024-12-18 18:33:27 +01:00
7f02df4e1b git subtree add --squash -P external/nng https://github.com/nanomsg/nng.git v1.8.0
Merge commit '7063e2102e655079574d6644b323f28f48685c5a' as 'external/nng'
2024-12-18 18:33:08 +01:00
7063e2102e Squashed 'external/nng/' content from commit 29b73962
git-subtree-dir: external/nng
git-subtree-split: 29b73962b939a6fbbf6ea8d5d7680bb06d0eeb99
2024-12-18 18:29:29 +01:00
60d4ea7afd remove nng 2024-12-18 18:27:57 +01:00
293 changed files with 13030 additions and 5059 deletions

View file

@ -5,10 +5,12 @@ ColumnLimit: 79
AlignConsecutiveAssignments: true AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true AlignConsecutiveDeclarations: true
AlignTrailingComments: true AlignTrailingComments: true
AlignEscapedNewlinesLeft: true AlignEscapedNewlines: Left
PointerAlignment: Right PointerAlignment: Right
DerivePointerAlignment: false
ForEachMacros: ['NNI_LIST_FOREACH'] ForEachMacros: ['NNI_LIST_FOREACH']
AlwaysBreakAfterReturnType: TopLevelDefinitions AlwaysBreakAfterReturnType: TopLevelDefinitions
SpaceAfterCStyleCast: true SpaceAfterCStyleCast: true
AllowShortFunctionsOnASingleLine: Inline AllowShortFunctionsOnASingleLine: Inline
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
TabWidth: 8

View file

@ -1,19 +1,21 @@
name: darwin name: darwin
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
name: build name: build
runs-on: [ macos-latest ] runs-on: [macos-latest]
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: Install Mbed TLS
run: brew install mbedtls
- name: Install ninja - name: Install ninja
run: brew install ninja run: brew install ninja
- name: Configure - name: Configure
run: mkdir build && cd build && cmake -G Ninja .. run: mkdir build && cd build && cmake -G Ninja -DNNG_ENABLE_TLS=ON ..
- name: build - name: build
run: cd build && ninja run: cd build && ninja

View file

@ -15,10 +15,11 @@ jobs:
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: mstksg/get-package@v1 - name: Install mbedTLS
with: run: sudo apt-get install libmbedtls-dev
apt-get: ninja-build libmbedtls-dev
brew: ninja mbedtls - name: Install ninja
run: sudo apt-get install ninja-build
- name: Configure - name: Configure
run: | run: |

View file

@ -1,16 +1,24 @@
name: windows name: windows
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
build: build:
name: build name: build
runs-on: [ windows-latest ] runs-on: [windows-latest]
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@v1 uses: actions/checkout@v1
- name: vcpkg build
id: vcpkg
uses: johnwason/vcpkg-action@v6
with:
pkgs: mbedtls
triplet: x64-windows
token: ${{ github.token }}
github-binarycache: true
- name: Configure - name: Configure
run: cmake -B build run: cmake ${{ steps.vcpkg.outputs.vcpkg-cmake-config }} -D NNG_ENABLE_TLS=ON -B build
- name: Build - name: Build
run: cmake --build build run: cmake --build build
@ -19,4 +27,3 @@ jobs:
run: | run: |
cd build cd build
ctest -C Debug --output-on-failure ctest -C Debug --output-on-failure

View file

@ -2,6 +2,7 @@ build
lxbuild lxbuild
winbuild winbuild
wbuild wbuild
.cache
.vs .vs
.vscode/.cmaketools.json .vscode/.cmaketools.json
.vscode .vscode

View file

@ -1,5 +1,5 @@
# #
# Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
# Copyright (c) 2012 Martin Sustrik All rights reserved. # Copyright (c) 2012 Martin Sustrik All rights reserved.
# Copyright (c) 2013 GoPivotal, Inc. All rights reserved. # Copyright (c) 2013 GoPivotal, Inc. All rights reserved.
# Copyright (c) 2015-2016 Jack R. Dunaway. All rights reserved. # Copyright (c) 2015-2016 Jack R. Dunaway. All rights reserved.
@ -96,6 +96,9 @@ target_compile_definitions(nng_private INTERFACE NNG_PRIVATE)
if (NNG_ELIDE_DEPRECATED) if (NNG_ELIDE_DEPRECATED)
target_compile_definitions(nng PRIVATE NNG_ELIDE_DEPRECATED) target_compile_definitions(nng PRIVATE NNG_ELIDE_DEPRECATED)
endif() endif()
if (NNG_ENABLE_COMPAT)
target_compile_definitions(nng PRIVATE NNG_ENABLE_COMPAT)
endif()
# We can use rlimit to configure the stack size for systems # We can use rlimit to configure the stack size for systems
@ -114,22 +117,55 @@ endif ()
nng_defines_if(NNG_ENABLE_STATS NNG_ENABLE_STATS) nng_defines_if(NNG_ENABLE_STATS NNG_ENABLE_STATS)
# IPv6 enable
nng_defines_if(NNG_ENABLE_IPV6 NNG_ENABLE_IPV6)
set(NNG_RESOLV_CONCURRENCY 4 CACHE STRING "Resolver (DNS) concurrency.")
mark_as_advanced(NNG_RESOLV_CONCURRENCY)
if (NNG_RESOLV_CONCURRENCY) if (NNG_RESOLV_CONCURRENCY)
add_definitions(-DNNG_RESOLV_CONCURRENCY=${NNG_RESOLV_CONCURRENCY}) add_definitions(-DNNG_RESOLV_CONCURRENCY=${NNG_RESOLV_CONCURRENCY})
endif () endif ()
mark_as_advanced(NNG_RESOLV_CONCURRENCY)
set(NNG_NUM_TASKQ_THREADS 0 CACHE STRING "Fixed number of task threads, 0 for automatic")
mark_as_advanced(NNG_NUM_TASKQ_THREADS)
if (NNG_NUM_TASKQ_THREADS) if (NNG_NUM_TASKQ_THREADS)
add_definitions(-DNNG_NUM_TASKQ_THREADS=${NNG_NUM_TASKQ_THREADS}) add_definitions(-DNNG_NUM_TASKQ_THREADS=${NNG_NUM_TASKQ_THREADS})
endif () endif ()
mark_as_advanced(NNG_NUM_TASKQ_THREADS)
set(NNG_MAX_TASKQ_THREADS 16 CACHE STRING "Upper bound on taskq threads, 0 for no limit") set(NNG_MAX_TASKQ_THREADS 16 CACHE STRING "Upper bound on task threads, 0 for no limit")
mark_as_advanced(NNG_MAX_TASKQ_THREADS) mark_as_advanced(NNG_MAX_TASKQ_THREADS)
if (NNG_MAX_TASKQ_THREADS) if (NNG_MAX_TASKQ_THREADS)
add_definitions(-DNNG_MAX_TASKQ_THREADS=${NNG_MAX_TASKQ_THREADS}) add_definitions(-DNNG_MAX_TASKQ_THREADS=${NNG_MAX_TASKQ_THREADS})
endif () endif ()
# Expire threads. This runs the timeout handling, and having more of them
# reduces contention on the common locks used for aio expiration.
set(NNG_NUM_EXPIRE_THREADS 0 CACHE STRING "Fixed number of expire threads, 0 for automatic")
mark_as_advanced(NNG_NUM_EXPIRE_THREADS)
if (NNG_NUM_EXPIRE_THREADS)
add_definitions(-DNNG_NUM_EXPIRE_THREADS=${NNG_NUM_EXPIRE_THREADS})
endif ()
set(NNG_MAX_EXPIRE_THREADS 8 CACHE STRING "Upper bound on expire threads, 0 for no limit")
mark_as_advanced(NNG_MAX_EXPIRE_THREADS)
if (NNG_MAX_EXPIRE_THREADS)
add_definitions(-DNNG_MAX_EXPIRE_THREADS=${NNG_MAX_EXPIRE_THREADS})
endif()
# Poller threads. These threads run the pollers. This is mostly used
# on Windows right now, as the POSIX platforms use a single threaded poller.
set(NNG_NUM_POLLER_THREADS 0 CACHE STRING "Fixed number of I/O poller threads, 0 for automatic")
if (NNG_NUM_POLLER_THREADS)
add_definitions(-DNNG_NUM_POLLER_THREADS=${NNG_NUM_POLLER_THREADS})
endif ()
mark_as_advanced(NNG_NUM_POLLER_THREADS)
set(NNG_MAX_POLLER_THREADS 8 CACHE STRING "Upper bound on I/O poller threads, 0 for no limit")
mark_as_advanced(NNG_MAX_POLLER_THREADS)
if (NNG_MAX_POLLER_THREADS)
add_definitions(-DNNG_MAX_POLLER_THREADS=${NNG_MAX_POLLER_THREADS})
endif()
# Platform checks. # Platform checks.
if (CMAKE_C_COMPILER_ID STREQUAL "GNU") if (CMAKE_C_COMPILER_ID STREQUAL "GNU")

View file

@ -5,23 +5,20 @@ endif::[]
= nng - nanomsg-next-gen = nng - nanomsg-next-gen
// Note: This README is optimized for display with Asciidoctor, or // Note: This README is optimized for display with Asciidoctor, or
// on the github status page. An HTML version is in the same directory // on the GitHub project page at https://github.com/nanomsg/nng.
// and may be more pleasantly formatted for human readers (when opened
// in a browser).
// Note: If you're updating this file, don't forget to re-run asciidoctor image:https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg[Stand With Ukraine,link="https://stand-with-ukraine.pp.ua"]
// to update the aforementioned HTML file! image:https://img.shields.io/github/actions/workflow/status/nanomsg/nng/linux.yml?branch=master&logoColor=grey&logo=ubuntu&label=[Linux Status,link="https://github.com/nanomsg/nng/actions"]
image:https://img.shields.io/github/actions/workflow/status/nanomsg/nng/windows.yml?branch=master&logoColor=grey&logo=windows&label=[Windows Status,link="https://github.com/nanomsg/nng/actions"]
image:https://img.shields.io/github/workflow/status/nanomsg/nng/linux/master?logoColor=grey&logo=ubuntu&label=[Linux Status,link="https://github.com/nanomsg/nng/actions"] image:https://img.shields.io/github/actions/workflow/status/nanomsg/nng/darwin.yml?branch=master&logoColor=grey&logo=apple&label=[macOS Status,link="https://github.com/nanomsg/nng/actions"]
image:https://img.shields.io/github/workflow/status/nanomsg/nng/windows/master?logoColor=grey&logo=windows&label=[Windows Status,link="https://github.com/nanomsg/nng/actions"]
image:https://img.shields.io/github/workflow/status/nanomsg/nng/darwin/master?logoColor=grey&logo=apple&label=[macOS Status,link="https://github.com/nanomsg/nng/actions"]
image:https://img.shields.io/codecov/c/github/nanomsg/nng?logo=codecov&logoColor=grey&label=[Coverage,link="https://codecov.io/gh/nanomsg/nng"] image:https://img.shields.io/codecov/c/github/nanomsg/nng?logo=codecov&logoColor=grey&label=[Coverage,link="https://codecov.io/gh/nanomsg/nng"]
image:https://img.shields.io/lgtm/grade/cpp/github/nanomsg/nng?logo=lgtm&logoColor=grey&label=[LGTM,link="https://lgtm.com/projects/g/nanomsg/nng/?mode=list"]
image:https://img.shields.io/discord/639573728212156478?label=&logo=discord[Discord,link="https://discord.gg/Xnac6b9"] image:https://img.shields.io/discord/639573728212156478?label=&logo=discord[Discord,link="https://discord.gg/Xnac6b9"]
image:https://img.shields.io/static/v1?label=&message=docs&logo=asciidoctor&logoColor=silver&color=blue[Manual,link="https://nng.nanomsg.org/man"] image:https://img.shields.io/static/v1?label=&message=docs&logo=asciidoctor&logoColor=silver&color=blue[Manual,link="https://nng.nanomsg.org/man"]
image:https://img.shields.io/github/license/nanomsg/nng.svg?logoColor=silver&logo=open-source-initiative&label=&color=blue[MIT License,link="https://github.com/nanomsg/nng/blob/master/LICENSE.txt"] image:https://img.shields.io/github/license/nanomsg/nng.svg?logoColor=silver&logo=open-source-initiative&label=&color=blue[MIT License,link="https://github.com/nanomsg/nng/blob/master/LICENSE.txt"]
image:https://img.shields.io/github/v/tag/nanomsg/nng.svg?logo=github&label=[Latest version,link="https://github.com/nanomsg/nng/releases"] image:https://img.shields.io/github/v/tag/nanomsg/nng.svg?logo=github&label=[Latest version,link="https://github.com/nanomsg/nng/releases"]
Please see <<UKRAINE#,here>> for an important message for the people of Russia.
NOTE: If you are looking for the legacy version of nanomsg, please NOTE: If you are looking for the legacy version of nanomsg, please
see the https://github.com/nanomsg/nanomsg[nanomsg] repository. see the https://github.com/nanomsg/nanomsg[nanomsg] repository.
@ -128,7 +125,7 @@ system (pass "-G Ninja" to CMake) when you can.
blindingly fast and has made our lives as developers measurably better.) blindingly fast and has made our lives as developers measurably better.)
If you want to build with TLS support you will also need If you want to build with TLS support you will also need
https://tls.mbed.org[mbedTLS]. See <<docs/BUILD_TLS.adoc#>> for details. https://tls.mbed.org[Mbed TLS]. See <<docs/BUILD_TLS.adoc#>> for details.
== Quick Start == Quick Start
@ -149,7 +146,9 @@ With a Linux or UNIX environment:
The API documentation is provided in Asciidoc format in the The API documentation is provided in Asciidoc format in the
`docs/man` subdirectory, and also `docs/man` subdirectory, and also
https://nanomsg.github.io/nng[online]. https://nanomsg.github.io/nng[online].
The <<docs/man/libnng.3.adoc#,libnng(3)>> page is a good starting point. The <<docs/man/nng.7.adoc#,nng(7)>> page provides a conceptual overview and links to
manuals for various patterns.
The <<docs/man/libnng.3.adoc#,libnng(3)>> page is a good starting point for the API reference.
You can also purchase a copy of the You can also purchase a copy of the
http://staysail.tech/books/nng_reference/index.html[__NNG Reference Manual__]. http://staysail.tech/books/nng_reference/index.html[__NNG Reference Manual__].
@ -163,7 +162,7 @@ These are located in the `demo` directory.
== Legacy Compatibility == Legacy Compatibility
A legacy libnanomsg compatible API is available, and while it offers A legacy `libnanomsg` compatible API is available, and while it offers
less capability than the modern NNG API, it may serve as a transition aid. less capability than the modern NNG API, it may serve as a transition aid.
Please see <<docs/man/nng_compat.3compat.adoc#,nng_compat(3)>> for details. Please see <<docs/man/nng_compat.3compat.adoc#,nng_compat(3)>> for details.

View file

@ -1,67 +1,115 @@
= NNG Release Notes ifdef::env-github[]
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
endif::[]
== Release 1.3.0 (since 1.2.6) = RELEASE NOTES FOR NNG v1.7.0
=== Features This document has the following sections:
* Support for TLS 1.3 and external TLS providers. * Notable Changes
There is now an API whereby external "`engines`" can be developed * End of Feature Announcements
for different TLS implementations. The first of these, for wolfSSL,
is available. Set this with the `NNG_TLS_ENGINE` cmake option.
The default is still to use Mbed TLS. The wolfSSL plugin is
available under a different license (GPLv3 or commercial), and also
provides support for TLS 1.3 and FIPS 140-2 capable solutions.
* Message cloning and related performance improvements. This is not == Notable Changes (since 1.6.0)
a feature, so much as a rather large improvement in terms of performance.
All workloads will see some benefit -- some will see substantial benefits.
* Numerous other performance improvements. Much effort was made to A new compile time setting, `NNG_MAX_POLLER_THREADS` is introduced,
reducing allocations, improving cache effectiveness, and eliminating with a default value of 8, and will limit the number of threads
extra context switches. This work is not yet done, but this is a big used for pollers that are concurrent (currently only Windows).
step in the right direction. Additionally, for single core systems only two threads will be started
instead of four.
* HTTP Server support for "non-exclusive" registration -- a given handler A new supplemental API, nng_id_map(3), is made available.
may be registered as a fallback handler (e.g. for a directory), even if This exposes the internal ID hash API NNG uses mapping integer IDs
more specific handlers are registered. (like socket IDs) to data structures.
It also brings back support for 64-bit IDs.
See bug #1740.
* Performance test programs grew more options to select different Setting the `NNG_OPT_RECVMAXSZ` setting no longer affects pipes
protocols and to change the URL to test across different transports. that are already established. The old behavior was undocumented
and racy. Please set this setting before starting any listeners
or dialers.
=== Notable Bug Fixes A new transport (experimental), for `socket://` is available.
This allows one to create a connection using sockets created
with `socketpair()` (or the new `nng_socket_pair()` supplemental API),
which can help use cases where file descriptors are passed between
processes or inherited via `fork()`. This API is only available on
Linux. It does have somewhat different semantics for establishing
the connection, so please see the manual page for `nng_socket(5)` for more information.
* Thread count is limited. WebSocket close is fixed to conform to RFC 6455, sending the
Previously we would spawn potentially vast numbers of threads based on the close frame, and waiting to receive the close frame from the
number of available cores. By default we set an upper limit on this that peer. This allows websocket based connections to ensure that
is about 20 threads. Tune this with the `NNG_MAX_TASKQ_WORKERS` cmake option. data messages are fully delivered before shutting down.
See bugs #1733, #1734 and #1735.
Thanks @alawn-wang for the inspiration and a first
draft of the change.
* Raw mode fixes for XREQ and XRESPONDENT. These protocols used the raw mode The REQ and SURVEYOR protocols were fixed to improve scalability
inconsistently, leaving the header in the message body. This is corrected when many clients or many contexts are used. As part of this change,
and the protocol headers are kept in the message headers. There is some small a new option, `NNG_OPT_REQ_RESENDTICK` is available to adjust how
risk that some applications broken, but we are not aware of any that used often we check for expired requests.
RAW mode to parse message headers.
* HTTP Server root URL handling had a few issues which are resolved. A new ability to override compile-time settings for thread counts
is available. This facility is considered experimental, and is not
documented in manual pages -- and is subject to change without notice.
Please see nng_init_set_parameter() in the nng.h header file. The
values that can be tuned are listed there along with comments
describing their use. See bug #1572.
* Some platforms had difficult building due to inconsistencies in the As part of the fixes for #1572, tunable values for setting fixed
handling of atomics. values (rather upper limits) for thread counts are now exposed properly
via CMake variables. These are `NNG_NUM_EXPIRE_THREADS` and `NNG_NUM_TASKQ_THREADS`.
* Numerous test suites uncovered small (rare) races, etc. The tests A new API, `nng_aio_set_expire()` is introduced as a complement to
themselves were often racy. Fixes to both NNG and the tests have been `nng_aio_set_timeout()`. This provides absolute expiration times,
made, while increasing overall test coverage. which may be easier in circumstances involving multiple actions such
as common state-machine based idioms.
* REP protocol with SENDFD was inconsistent (#1088). A bug which caused TLS connections to spin on accept, causing high
CPU usage, is fixed. (See bug #1673)
Various minor documentation fixes were made, some contributed by
Patrik Wenger <patrik.wenger@mindclue.ch>.
=== Other Changes == End of Feature Announcements
* Polyamorous Pair v1 mode is changed, such that a new API call is needed === Windows Legacy Support
to use it. Further, this mode will likely be removed in a future release.
Note that this mode also does not work with other implementations, nor
does it support operation with `nng_device()`.
* Maximum hop count across `nng_device()` proxies is now limited to 15. As announced in 1.6.0,
This limit should be sufficient for all reasonable configurations, NNG no longer officially claims support for Windows Vista, Windows 7, Windows 8, or Windows 8.1.
and forcing this allowed us to to inline the header for performance We have no ability to build or test these versions, and Microsoft no longer supports them.
reasons. Continued use of these systems may be possible, but future changes may break
compatibility with these systems without further notice.
* The nng_msg_options support was removed. It was not used for anything. === Windows Named Pipe Support Changes
A future release of NNG may make the ipc:// URL format operate over UNIX domain sockets by default.
We plan to do this for the other projects we control, such as mangos, as well.
Should this occur, it will be breaking for Windows versions older than Windows 10 17063.
=== macOS Legacy Support
As announced in 1.6.0,
NNG no longer officially supports macOS versions older than 10.12.
Future versions of NNG may depend on features not available on versions of macOS older than 10.12.
=== Documentation Restructuring
A future release of NNG may restructure the documentation to make it more
approachable for more users. This would break the organization as UNIX manual
pages, and would also drop the ability to format them as UNIX nroff source.
The best way to view this documentation is on the NNG website, or with the PDF or printed manual.
=== ZeroTier Incompatible Changes
A future release of NNG may break compatibility for applications built using earlier versions
of NNG when using the ZeroTier transport. ZeroTier support is an experimental feature.
=== Pair1 Polyamorous Mode
A future release of NNG may remove Pair 1 Polyamorous support, but *only* if a suitable
replacement is provided. Pair1 Polyamorous mode is an experimental feature.
Alternatively we may change the Pair1 wire protocol in a way that breaks compatibility with
earlier versions of Pair1 Polyamorous mode.

90
external/nng/UKRAINE.adoc vendored Normal file
View file

@ -0,0 +1,90 @@
# Ukraine, Russia, and a World Tragedy
## A message to those inside Russia
### Written March 4, 2022.
It is with a very heavy heart that I write this. I am normally opposed to the use of open source
projects to communicate political positions or advocate for things outside the immediate relevancy
to that project.
However, the events occurring in Ukraine, and specifically the unprecedented invasion of Ukraine by
Russian forces operating under orders from Russian President Vladimir Putin compel me to speak out.
Those who know me, know that I have family, friends, and colleagues in Russia, and Ukraine both. My closest friends
have historically been Russian friends my wife's hometown of Chelyabinsk. I myself have in the past
frequently traveled to Russia, and indeed operated a software development firm with offices in St. Petersburg.
I had a special kinship with Russia and its people.
I say "had", because I fear that the actions of Putin, and the massive disinformation campaign that his regime
has waged inside Russia, mean that it's likely that I won't see those friends again. At present, I'm not sure
my wife will see her own mother again. We no longer feel it's safe for either of us to return Russia given
actions taken by the regime to crack down on those who express disagreement.
Russian citizens are being led to believe it is acting purely defensively, and that only legitimate military
targets are being targeted, and that all the information we have received in the West are fakes.
I am confident that nothing could be further from the truth.
This has caused many in Russia, including people whom I respect and believe to be smarter than this, to
stand by Putin, and endorse his actions. The claim is that the entirety of NATO is operating at the behest
of the USA, and that the entirety of Europe was poised to attack Russia. While this is clearly absurd to those
of us with any understanding of western politics, Russian citizens are being fed this lie, and believing it.
If you're reading this from inside Russia -- YOU are the person that I hope this message reaches. Your
government is LYING to you. Of course, all governments lie all the time. But consider this. Almost the
entire world has condemned the invasion of Ukraine as criminal, and has applied sanctions. Even countries
which have poor relations with the US sanctioning Russia, as well as nations which historically have remained
neutral. (Famously neutral -- even during World War II, Switzerland has acted to apply sanctions in
concert with the rest of the world.)
Ask yourself, why does Putin fear a free press so much, if what he says is true? Why the crack-downs on
children expressing only a desire for peace with Ukraine? Why would the entire world unified against him,
if Putin was in the right? Why would the only countries that stood with Russia against
the UN resolution to condemn these acts as crimes be Belarus, North Korea, and Syria? Even countries normally
allied to Russia could not bring themselves to do more than abstain from the vote to condemn it.
To be clear, I do not claim that the actions taken by the West or by the Ukrainian government were completely
blameless. On the contrary, I understand that Western media is biased, and the truth is rarely exactly
as reported. I believe that there is a kernel of truth in the claims of fascists and ultra-nationalist
militias operating in Ukraine and specifically Donbas. However, I am also equally certain that Putin's
response is out of proportion, and that concerns about such militias are principally just a pretext to justify
an invasion.
Europe is at war, unlike we've seen in my lifetime. The world is more divided, and closer to nuclear holocaust
than it has been since the Cold War. And that is 100% the fault of Putin.
While Putin remains in power, there cannot really be any way for Russian international relations to return
to normal. Putin has set your country on a path to return to the Cold War, likely because he fancies himself
to be a new Stalin. However, unlike the Soviet Union, the Russian economy does not have the wherewithal to
stand on its own, and the invasion of Ukraine has fully ensured that Russia will not find any friends anywhere
else in Europe, and probably few places in Asia.
The *only* paths forward for Russia are either a Russia without Putin (and those who would support his agenda),
or a complete breakdown of Russian prosperity, likely followed by the increasing international conflict that will
be the natural escalation from a country that is isolated and impoverished. Those of us observing from the West are
gravely concerned, because we cannot see any end to this madness that does not result in nuclear conflict,
unless from within.
In the meantime, the worst prices will be paid for by innocents in Ukraine, and by young Russian men
forced to carry out the orders of Putin's corrupt regime.
And *that* is why I write this -- to appeal to those within Russia to open your eyes, and think with
your minds. It is right and proper to be proud of your country and its rich heritage. But it is also
right and proper to look for ways to save it from the ruinous path that its current leadership has set it upon,
and to recognize when that leadership is no longer acting in interest of the country or its people.
- Garrett D'Amore, March 4, 2022
Updates on March 16, 2024:
I've made some minor typographical fixes.
It is extremely distressing to see that two years on, the
people of both Ukraine and Russia continue to suffer under this needless, pointless, conflict fought solely to assuage
the ego of a dictator.
The actions done here, have killed thousands, probably hundreds of thousands, of soldiers and civilians alike, and there seems to be no end to the madness. I still pray for sanity to return, because the current path, if followed
to its logical conclusion, most likely ends in apocalpyse.
If you find my sharing these truths uncomfortable, please feel welcome to cease use of my software. While the license does permit use by anyone for any reason, I would not be displeased if the Russian military, and those sympathetic to it, declined from use of any of my work.

119
external/nng/cmake/FindMbedTLS.cmake vendored Normal file
View file

@ -0,0 +1,119 @@
#
# Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
# Copyright 2017 Capitar IT Group BV <info@capitar.com>
#
# This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this
# file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT.
#
#
# Try to find the Mbed TLS libraries.
# This tries to emulate the same expectations that the stock Mbed TLS
# module uses in Mbed TLS v3.x.
#
# Sets the following:
#
# MbedTLS_FOUND - True if we found Mbed TLS.
# MbedTLS_TARGET - Target of the mbedtls library.
# MbedX509_TARGET - Target of the mbedx509 library.
# MbedCrypto_TARGET - Target of the mbedcrypto library.
# MbedTLS_VERSION - $major.$minor.$revision (e.g. ``2.6.0``).
#
# MBEDTLS_CRYPTO_LIBRARY - The mbedcrypto library.
# MBEDTLS_X509_LIBRARY - The mbedx509 library.
# MBEDTLS_TLS_LIBRARY - The mbedtls library.
# MBEDTLS_LIBRARIES - List of all three Mbed TLS libraries.
#
# Hints:
#
# Set ``MBEDTLS_ROOT`` to the root directory of Mbed TLS installation.
#
set(_MBEDTLS_ROOT_HINTS ${MBEDTLS_ROOT} ENV MBEDTLS_ROOT)
if (NOT _MBEDTLS_ROOT_HINTS)
set(_MBEDTLS_ROOT_HINTS ${MBEDTLS_ROOT_DIR} ENV MBEDTLS_ROOT_DIR)
endif()
set(_MBED_REQUIRED_VARS MbedTLS_TARGET MbedX509_TARGET MbedCrypto_TARGET MbedTLS_VERSION)
include(FindPackageHandleStandardArgs)
include(CMakePushCheckState)
find_path(_MBEDTLS_INCLUDE_DIR
NAMES mbedtls/ssl.h
HINTS ${_MBEDTLS_ROOT_HINTS}
# PATHS /usr/local
PATH_SUFFIXES include)
find_library(_MBEDCRYPTO_LIBRARY
NAMES mbedcrypto
HINTS ${_MBEDTLS_ROOT_HINTS}
# PATHS /usr/local
# PATH_SUFFIXES lib
)
find_library(_MBEDX509_LIBRARY
NAMES mbedx509
HINTS ${_MBEDTLS_ROOT_HINTS}
#PATHS /usr/local
# PATH_SUFFIXES lib
)
find_library(_MBEDTLS_LIBRARY
NAMES mbedtls
HINTS ${_MBEDTLS_ROOT_HINTS}
#PATHS /usr/local
#PATH_SUFFIXES lib
)
if ("${_MBEDTLS_TLS_LIBRARY}" STREQUAL "_MBEDTLS_TLS_LIBRARY-NOTFOUND")
message("Failed to find Mbed TLS library")
else()
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_INCLUDES ${_MBEDTLS_INCLUDE_DIR} ${CMAKE_REQUIRED_INCLUDES_${BUILD_TYPE}})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${_MBEDTLS_LIBRARY} ${_MBEDX509_LIBRARY} ${_MBEDCRYPTO_LIBRARY})
check_symbol_exists(mbedtls_ssl_init "mbedtls/ssl.h" _MBEDTLS_V2_OR_NEWER)
cmake_pop_check_state()
if (NOT _MBEDTLS_V2_OR_NEWER)
message("Mbed TLS too old (must be version 2 or newer) ${_MBEDTLS_V2_OR_NEWER} UP ${_MbedTLS_V2}")
else()
# Extract the version from the header... hopefully it matches the library.
if (EXISTS ${_MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h)
file(STRINGS ${_MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h _MBEDTLS_VERLINE
REGEX "^#define[ \t]+MBEDTLS_VERSION_STRING[\t ].*")
else ()
file(STRINGS ${_MBEDTLS_INCLUDE_DIR}/mbedtls/version.h _MBEDTLS_VERLINE
REGEX "^#define[ \t]+MBEDTLS_VERSION_STRING[\t ].*")
endif ()
string(REGEX REPLACE ".*MBEDTLS_VERSION_STRING[\t ]+\"(.*)\"" "\\1" MbedTLS_VERSION ${_MBEDTLS_VERLINE})
message("Mbed TLS version: ${MbedTLS_VERSION}")
endif()
endif()
add_library(MbedTLS::mbedtls UNKNOWN IMPORTED)
add_library(MbedTLS::mbedx509 UNKNOWN IMPORTED)
add_library(MbedTLS::mbedcrypto UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedtls PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_MBEDTLS_INCLUDE_DIR}")
set_target_properties(MbedTLS::mbedx509 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_MBEDTLS_INCLUDE_DIR}")
set_target_properties(MbedTLS::mbedcrypto PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_MBEDTLS_INCLUDE_DIR}")
set_target_properties(MbedTLS::mbedtls PROPERTIES IMPORTED_LOCATION "${_MBEDTLS_LIBRARY}")
set_target_properties(MbedTLS::mbedx509 PROPERTIES IMPORTED_LOCATION "${_MBEDX509_LIBRARY}")
set_target_properties(MbedTLS::mbedcrypto PROPERTIES IMPORTED_LOCATION "${_MBEDCRYPTO_LIBRARY}")
set(MbedTLS_TARGET MbedTLS::mbedtls)
set(MbedX509_TARGET MbedTLS::mbedx509)
set(MbedCrypto_TARGET MbedTLS::mbedcrypto)
find_package_handle_standard_args(MbedTLS REQUIRED_VARS ${_MBED_REQUIRED_VARS})
mark_as_advanced(${_MBED_REQUIRED_VARS})

View file

@ -1,86 +0,0 @@
#
# Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
# Copyright 2017 Capitar IT Group BV <info@capitar.com>
#
# This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this
# file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT.
#
#
# Try to find the Mbed TLS libraries.
#
# Sets the following:
#
# MBEDTLS_INCLUDE_DIR - Where to find mbedtls/ssl.h, etc.
# MBEDTLS_FOUND - True if we found Mbed TLS.
# MBEDTLS_CRYPTO_LIBRARY - The mbedcrypto library.
# MBEDTLS_X509_LIBRARY - The mbedx509 library.
# MBEDTLS_TLS_LIBRARY - The mbedtls library.
# MBEDTLS_LIBRARIES - List of all three Mbed TLS libraries.
# MBEDTLS_VERSION - $major.$minor.$revision (e.g. ``2.6.0``).
#
# Hints:
#
# Set ``MBEDTLS_ROOT_DIR`` to the root directory of Mbed TLS installation.
#
set(_MBEDTLS_ROOT_HINTS ${MBEDTLS_ROOT_DIR} ENV MBEDTLS_ROOT_DIR)
include(FindPackageHandleStandardArgs)
find_path(MBEDTLS_INCLUDE_DIR
NAMES mbedtls/ssl.h
HINTS ${_MBEDTLS_ROOT_HINTS}
PATHS /usr/local
PATH_SUFFIXES include)
find_library(MBEDTLS_CRYPTO_LIBRARY
NAMES mbedcrypto
HINTS ${_MBEDTLS_ROOT_HINTS}
PATHS /usr/local
PATH_SUFFIXES lib)
find_library(MBEDTLS_X509_LIBRARY
NAMES mbedx509
HINTS ${_MBEDTLS_ROOT_HINTS}
PATHS /usr/local
PATH_SUFFIXES lib)
find_library(MBEDTLS_TLS_LIBRARY
NAMES mbedtls
HINTS ${_MBEDTLS_ROOT_HINTS}
PATHS /usr/local
PATH_SUFFIXES lib)
set(MBEDTLS_LIBRARIES
${MBEDTLS_TLS_LIBRARY}
${MBEDTLS_X509_LIBRARY}
${MBEDTLS_CRYPTO_LIBRARY})
if (${MBEDTLS_TLS_LIBRARY-NOTFOUND})
message(FATAL_ERROR "Failed to find Mbed TLS library")
endif ()
mark_as_advanced(
MBEDSSL_INCLUDE_DIR
MBEDTLS_LIBRARIES
MBEDTLS_CRYPTO_LIBRARY
MBEDTLS_X509_LIBRARY
MBEDTLS_TLS_LIBRARY)
# Extract the version from the header... hopefully it matches the library.
if (EXISTS ${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h)
file(STRINGS ${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h _MBEDTLS_VERLINE
REGEX "^#define[ \t]+MBEDTLS_VERSION_STRING[\t ].*")
else ()
file(STRINGS ${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h _MBEDTLS_VERLINE
REGEX "^#define[ \t]+MBEDTLS_VERSION_STRING[\t ].*")
endif ()
string(REGEX REPLACE ".*MBEDTLS_VERSION_STRING[\t ]+\"(.*)\"" "\\1" MBEDTLS_VERSION ${_MBEDTLS_VERLINE})
find_package_handle_standard_args(mbedTLS
REQUIRED_VARS MBEDTLS_TLS_LIBRARY MBEDTLS_CRYPTO_LIBRARY MBEDTLS_X509_LIBRARY MBEDTLS_INCLUDE_DIR VERSION_VAR MBEDTLS_VERSION)

View file

@ -1,5 +1,5 @@
# #
# Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
# #
# This software is supplied under the terms of the MIT License, a # This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this # copy of which should be located in the distribution where this
@ -41,12 +41,26 @@ function(nng_defines)
target_compile_definitions(nng_private INTERFACE ${ARGN}) target_compile_definitions(nng_private INTERFACE ${ARGN})
endfunction() endfunction()
# nng_find_package looks up required package and adds dependency to the cmake config.
macro(nng_find_package PACKAGE_NAME)
find_package(${PACKAGE_NAME} REQUIRED)
list(APPEND NNG_PKGS ${PACKAGE_NAME})
list(REMOVE_DUPLICATES NNG_PKGS)
set(NNG_PKGS ${NNG_PKGS} CACHE INTERNAL "nng package dependencies" FORCE)
endmacro()
# nng_link_libraries adds link dependencies to the libraries. # nng_link_libraries adds link dependencies to the libraries.
function(nng_link_libraries) function(nng_link_libraries)
target_link_libraries(nng PRIVATE ${ARGN}) target_link_libraries(nng PRIVATE ${ARGN})
target_link_libraries(nng_testing PRIVATE ${ARGN}) target_link_libraries(nng_testing PRIVATE ${ARGN})
endfunction() endfunction()
function(nng_link_libraries_public)
target_link_libraries(nng PRIVATE ${ARGN})
target_link_libraries(nng_testing PRIVATE ${ARGN})
endfunction()
# nng_include_directories adds include directories. # nng_include_directories adds include directories.
function(nng_include_directories) function(nng_include_directories)
target_include_directories(nng PRIVATE ${ARGN}) target_include_directories(nng PRIVATE ${ARGN})

View file

@ -1,5 +1,5 @@
# #
# Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
# #
# This software is supplied under the terms of the MIT License, a # This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this # copy of which should be located in the distribution where this
@ -39,6 +39,11 @@ option(NNG_ENABLE_COVERAGE "Enable coverage reporting." OFF)
# for the public library. # for the public library.
option(NNG_ELIDE_DEPRECATED "Elide deprecated functionality." OFF) option(NNG_ELIDE_DEPRECATED "Elide deprecated functionality." OFF)
# Turning off the compatibility layer can save some space, and
# compilation time, but may break legacy applications It should
# be left enabled when building a shared library.
option(NNG_ENABLE_COMPAT "Enable legacy nanomsg API." ON)
option(NNG_ENABLE_STATS "Enable statistics." ON) option(NNG_ENABLE_STATS "Enable statistics." ON)
mark_as_advanced(NNG_ENABLE_STATS) mark_as_advanced(NNG_ENABLE_STATS)
@ -101,6 +106,11 @@ if (NNG_ENABLE_HTTP)
endif() endif()
mark_as_advanced(NNG_ENABLE_HTTP) mark_as_advanced(NNG_ENABLE_HTTP)
# Some sites or kernels lack IPv6 support. This override allows us
# to prevent the use of IPv6 in environments where it isn't supported.
option (NNG_ENABLE_IPV6 "Enable IPv6." ON)
mark_as_advanced(NNG_ENABLE_IPV6)
# #
# Transport Options. # Transport Options.
# #
@ -127,6 +137,9 @@ CMAKE_DEPENDENT_OPTION(NNG_TRANSPORT_WSS "Enable WSS transport." ON
"NNG_ENABLE_TLS" OFF) "NNG_ENABLE_TLS" OFF)
mark_as_advanced(NNG_TRANSPORT_WSS) mark_as_advanced(NNG_TRANSPORT_WSS)
option (NNG_TRANSPORT_FDC "Enable File Descriptor transport (EXPERIMENTAL)" ON)
mark_as_advanced(NNG_TRANSPORT_FDC)
# ZeroTier # ZeroTier
option (NNG_TRANSPORT_ZEROTIER "Enable ZeroTier transport (requires libzerotiercore)." OFF) option (NNG_TRANSPORT_ZEROTIER "Enable ZeroTier transport (requires libzerotiercore)." OFF)
mark_as_advanced(NNG_TRANSPORT_ZEROTIER) mark_as_advanced(NNG_TRANSPORT_ZEROTIER)

View file

@ -1,4 +1,4 @@
# Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
# #
# This software is supplied under the terms of the MIT License, a # This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this # copy of which should be located in the distribution where this
@ -8,9 +8,9 @@
@PACKAGE_INIT@ @PACKAGE_INIT@
set(NNG_VERSION_MAJOR "@NNG_MAJOR_VERSION@") set(NNG_MAJOR_VERSION "@NNG_MAJOR_VERSION@")
set(NNG_VERSION_MINOR "@NNG_MINOR_VERSION@") set(NNG_MINOR_VERSION "@NNG_MINOR_VERSION@")
set(NNG_VERSION_PATCH "@NNG_PATCH_VERSION@") set(NNG_PATCH_VERSION "@NNG_PATCH_VERSION@")
set_and_check(NNG_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIRS@") set_and_check(NNG_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIRS@")

View file

@ -7,7 +7,7 @@
# file was obtained (LICENSE.txt). A copy of the license may also be # file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT. # found online at https://opensource.org/licenses/MIT.
cmake_minimum_required (VERSION 2.8.7) cmake_minimum_required (VERSION 2.8.12)
project(nng-asyncdemo) project(nng-asyncdemo)
@ -16,9 +16,12 @@ set(PARALLEL 128 CACHE STRING "Parallelism (min 4, max 1000)")
# Call this from your own project's makefile. # Call this from your own project's makefile.
find_package(nng CONFIG REQUIRED) find_package(nng CONFIG REQUIRED)
find_package(Threads)
add_executable(server server.c) add_executable(server server.c)
target_link_libraries(server nng::nng) target_link_libraries(server nng::nng)
target_compile_definitions(server PRIVATE -DPARALLEL=${PARALLEL}) target_compile_definitions(server PRIVATE NNG_ELIDE_DEPRECATED PARALLEL=${PARALLEL})
add_executable(client client.c) add_executable(client client.c)
target_link_libraries(client nng::nng) target_link_libraries(client nng::nng)
target_compile_definitions(client PRIVATE NNG_ELIDE_DEPRECATED)

View file

@ -67,7 +67,7 @@ client(const char *url, const char *msecstr)
} }
if ((rv = nng_sendmsg(sock, msg, 0)) != 0) { if ((rv = nng_sendmsg(sock, msg, 0)) != 0) {
fatal("nng_send", rv); fatal("nng_sendmsg", rv);
} }
if ((rv = nng_recvmsg(sock, &msg, 0)) != 0) { if ((rv = nng_recvmsg(sock, &msg, 0)) != 0) {

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
ADDR=ipc:///tmp/async_demo ADDR=ipc:///tmp/async_demo
COUNT=10 COUNT=10

View file

@ -7,12 +7,15 @@
# file was obtained (LICENSE.txt). A copy of the license may also be # file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT. # found online at https://opensource.org/licenses/MIT.
cmake_minimum_required (VERSION 2.8.7) cmake_minimum_required (VERSION 2.8.12)
project(http_client) project(http_client)
# Call this from your own project's makefile. # Call this from your own project's makefile.
find_package(nng CONFIG REQUIRED) find_package(nng CONFIG REQUIRED)
find_package(Threads)
add_executable(http_client http_client.c) add_executable(http_client http_client.c)
target_link_libraries(http_client nng::nng) target_link_libraries(http_client nng::nng)
target_compile_definitions(http_client PRIVATE NNG_ELIDE_DEPRECATED)

View file

@ -0,0 +1,18 @@
# This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this
# file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT.
cmake_minimum_required(VERSION 3.10)
project(pubsub_forwarder C)
# Find the nng library
find_package(nng REQUIRED)
# Add the executable target
add_executable(pubsub_forwarder pubsub_forwarder.c)
target_compile_options(pubsub_forwarder PRIVATE -Wall -Wextra -Wpedantic -Werror -O2)
# Link against the nng library
target_link_libraries(pubsub_forwarder PRIVATE nng)

View file

@ -0,0 +1,62 @@
= PubSub Forwarder
This is a trivial example of a forwarder/proxy for the pub/sub pattern.
The concept is as follows: the forwarder will listen for connections on
both a front-end port and a back-end port. The front-end will act as a
subscriber so that publishers can publish to it. The back-end will act
as a publisher so that subscribers can subscribe to it. The front-end
then forwards to the back end.
== Compiling
CMake with ninja-build is simplest:
[source, bash]
----
cmake -GNinja -B build
cd build
ninja
----
Or if you prefer a traditional approach,
the following is an example typical of UNIX and similar systems like
Linux and macOS may appeal:
[source, bash]
----
export CPPFLAGS="-I /usr/local/include"
export LDFLAGS="-L /usr/local/lib -lnng"
export CC="cc"
${CC} ${CPPFLAGS} pubsub_forwarder.c -o pubsub_forwarder ${LDFLAGS}
----
== Running
An example setup for running this example would involve the following:
. Step 1: Run this example binary (in the background or a terminal, etc)
. Step 2: In a new terminal, run the following
[source, bash]
----
nngcat --sub --dial "tcp://localhost:3328" --quoted
----
. Step 3: In a second terminal, run the same command again to give us two subscribers
[source, bash]
----
nngcat --sub --dial "tcp://localhost:3328" --quoted
----
. In a third terminal, run the following to publish a counter
[source, bash]
----
for n in $(seq 0 99); do nngcat --pub --dial "tcp://localhost:3327" --data "$n"; done
----

View file

@ -0,0 +1,96 @@
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
//
// Forwarder example based on https://github.com/C-o-r-E/nng_pubsub_proxy
//
// This example shows how to use raw sockets to set up a forwarder or proxy for
// pub/sub.
//
// An example setup for running this example would involve the following:
//
// - Run this example binary (in the background or a terminal, etc)
// - In a new terminal, run
// `nngcat --sub --dial "tcp://localhost:3328" --quoted`
// - In a second terminal, run
// `nngcat --sub --dial "tcp://localhost:3328" --quoted`
// - In a third terminal, run
// `for n in $(seq 0 99);`
// `do nngcat --pub --dial "tcp://localhost:3327" --data "$n";`
// `done`
//
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <nng/nng.h>
#include <nng/protocol/pubsub0/pub.h>
#include <nng/protocol/pubsub0/sub.h>
#define PROXY_FRONT_URL "tcp://localhost:3327"
#define PROXY_BACK_URL "tcp://localhost:3328"
void
panic_on_error(int should_panic, const char *format, ...)
{
if (should_panic) {
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
exit(EXIT_FAILURE);
}
}
int
main()
{
nng_socket sock_front_end = NNG_SOCKET_INITIALIZER;
nng_socket sock_back_end = NNG_SOCKET_INITIALIZER;
int ret = 0;
//
// First we need some nng sockets. Not to be confused with network
// sockets
//
ret = nng_sub0_open_raw(&sock_front_end);
panic_on_error(ret, "Failed to open front end socket\n");
ret = nng_pub0_open_raw(&sock_back_end);
panic_on_error(ret, "Failed to open back end socket\n");
//
// Now we need to set up a listener for each socket so that they have
// addresses
//
nng_listener front_ls = NNG_LISTENER_INITIALIZER;
nng_listener back_ls = NNG_LISTENER_INITIALIZER;
ret = nng_listener_create(&front_ls, sock_front_end, PROXY_FRONT_URL);
panic_on_error(ret, "Failed to create front listener\n");
ret = nng_listener_create(&back_ls, sock_back_end, PROXY_BACK_URL);
panic_on_error(ret, "Failed to create back listener\n");
ret = nng_listener_start(front_ls, 0);
panic_on_error(ret, "Failed to start front listener\n");
ret = nng_listener_start(back_ls, 0);
panic_on_error(ret, "Failed to start back listener\n");
//
// Finally let nng do the forwarding/proxying
//
ret = nng_device(sock_front_end, sock_back_end);
panic_on_error(
ret, "nng_device returned %d: %s\n", ret, nng_strerror(ret));
printf("done");
return 0;
}

View file

@ -7,7 +7,7 @@
# file was obtained (LICENSE.txt). A copy of the license may also be # file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT. # found online at https://opensource.org/licenses/MIT.
cmake_minimum_required (VERSION 2.8.7) cmake_minimum_required (VERSION 2.8.12)
project(raw) project(raw)
@ -15,6 +15,8 @@ set(PARALLEL 128 CACHE STRING "Parallelism (min 4, max 1000)")
find_package(nng CONFIG REQUIRED) find_package(nng CONFIG REQUIRED)
find_package(Threads)
add_executable(raw raw.c) add_executable(raw raw.c)
target_link_libraries(raw nng::nng) target_link_libraries(raw nng::nng)
target_compile_definitions(raw PRIVATE -DPARALLEL=${PARALLEL}) target_compile_definitions(raw PRIVATE NNG_ELIDE_DEPRECATED PARALLEL=${PARALLEL})

View file

@ -7,7 +7,7 @@
# file was obtained (LICENSE.txt). A copy of the license may also be # file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT. # found online at https://opensource.org/licenses/MIT.
cmake_minimum_required (VERSION 2.8.7) cmake_minimum_required (VERSION 2.8.12)
project(reqrep) project(reqrep)
@ -20,3 +20,4 @@ find_package(Threads)
add_executable(reqrep reqrep.c) add_executable(reqrep reqrep.c)
target_link_libraries(reqrep nng::nng) target_link_libraries(reqrep nng::nng)
target_compile_definitions(reqrep PRIVATE NNG_ELIDE_DEPRECATED)

View file

@ -88,15 +88,15 @@ server(const char *url)
if (strncmp(url, "zt://", 5) == 0) { if (strncmp(url, "zt://", 5) == 0) {
printf("ZeroTier transport will store its keys in current working directory.\n"); printf("ZeroTier transport will store its keys in current working directory.\n");
printf("The server and client instances must run in separate directories.\n"); printf("The server and client instances must run in separate directories.\n");
nng_listener_setopt_string(listener, NNG_OPT_ZT_HOME, "."); nng_listener_set_string(listener, NNG_OPT_ZT_HOME, ".");
nng_listener_setopt_ms(listener, NNG_OPT_RECONNMINT, 1); nng_listener_set_ms(listener, NNG_OPT_RECONNMINT, 1);
nng_listener_setopt_ms(listener, NNG_OPT_RECONNMAXT, 1000); nng_listener_set_ms(listener, NNG_OPT_RECONNMAXT, 1000);
nng_setopt_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000); nng_socket_set_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000);
nng_setopt_ms(sock, NNG_OPT_RECVMAXSZ, 0); nng_socket_set_ms(sock, NNG_OPT_RECVMAXSZ, 0);
nng_listener_setopt_ms(listener, NNG_OPT_ZT_PING_TIME, 10000); nng_listener_set_ms(listener, NNG_OPT_ZT_PING_TIME, 10000);
nng_listener_setopt_ms(listener, NNG_OPT_ZT_CONN_TIME, 1000); nng_listener_set_ms(listener, NNG_OPT_ZT_CONN_TIME, 1000);
} else { } else {
nng_setopt_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000); nng_socket_set_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000);
} }
nng_listener_start(listener, 0); nng_listener_start(listener, 0);
@ -158,15 +158,15 @@ client(const char *url)
if (strncmp(url, "zt://", 5) == 0) { if (strncmp(url, "zt://", 5) == 0) {
printf("ZeroTier transport will store its keys in current working directory\n"); printf("ZeroTier transport will store its keys in current working directory\n");
printf("The server and client instances must run in separate directories.\n"); printf("The server and client instances must run in separate directories.\n");
nng_dialer_setopt_string(dialer, NNG_OPT_ZT_HOME, "."); nng_dialer_set_string(dialer, NNG_OPT_ZT_HOME, ".");
nng_dialer_setopt_ms(dialer, NNG_OPT_RECONNMINT, 1); nng_dialer_set_ms(dialer, NNG_OPT_RECONNMINT, 1);
nng_dialer_setopt_ms(dialer, NNG_OPT_RECONNMAXT, 1000); nng_dialer_set_ms(dialer, NNG_OPT_RECONNMAXT, 1000);
nng_setopt_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000); nng_socket_set_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000);
nng_setopt_ms(sock, NNG_OPT_RECVMAXSZ, 0); nng_socket_set_ms(sock, NNG_OPT_RECVMAXSZ, 0);
nng_dialer_setopt_ms(dialer, NNG_OPT_ZT_PING_TIME, 10000); nng_dialer_set_ms(dialer, NNG_OPT_ZT_PING_TIME, 10000);
nng_dialer_setopt_ms(dialer, NNG_OPT_ZT_CONN_TIME, 1000); nng_dialer_set_ms(dialer, NNG_OPT_ZT_CONN_TIME, 1000);
} else { } else {
nng_setopt_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000); nng_socket_set_ms(sock, NNG_OPT_REQ_RESENDTIME, 2000);
} }
nng_dialer_start(dialer, NNG_FLAG_NONBLOCK); nng_dialer_start(dialer, NNG_FLAG_NONBLOCK);

View file

@ -7,11 +7,14 @@
# file was obtained (LICENSE.txt). A copy of the license may also be # file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT. # found online at https://opensource.org/licenses/MIT.
cmake_minimum_required (VERSION 2.8.7) cmake_minimum_required (VERSION 2.8.12)
project(rest) project(rest)
find_package(nng CONFIG REQUIRED) find_package(nng CONFIG REQUIRED)
find_package(Threads)
add_executable(rest-server server.c) add_executable(rest-server server.c)
target_link_libraries(rest-server nng::nng) target_link_libraries(rest-server nng::nng)
target_compile_definitions(rest-server PRIVATE NNG_ELIDE_DEPRECATED)

View file

@ -20,7 +20,7 @@ There is a single "server" (rest-server) program, that does these:
% ./rest-server & % ./rest-server &
% curl -d ABC http://127.0.0.1:8888/api/rest/rot13; echo % curl -d ABC http://127.0.0.1:8888/api/rest/rot13; echo
NOP NOP
% curl -d ABC http://127.0.0.1:8888/api/rest/rot13; echo % curl -d NOP http://127.0.0.1:8888/api/rest/rot13; echo
ABC ABC
---- ----

27
external/nng/demo/stream/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,27 @@
#
# Copyright 2020 Hugo Lindström <hugolm84@gmail.com>
#
# This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this
# file was obtained (LICENSE.txt). A copy of the license may also be
# found online at https://opensource.org/licenses/MIT.
cmake_minimum_required (VERSION 2.8.7)
project(stream)
find_package(nng CONFIG REQUIRED)
add_executable(${PROJECT_NAME})
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/stream.c)
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/server.c)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/platform/windows/server.c)
endif()
target_link_libraries(stream nng::nng)

View file

@ -0,0 +1,53 @@
// Copyright 2020 Hugo Lindström <hugolm84@gmail.com>
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
void
error(const char *msg)
{
perror(msg);
exit(1);
}
int
server(int portno)
{
int sockfd, newsockfd;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
error("ERROR opening socket");
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <
0) {
error("ERROR on binding");
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
error("ERROR on accept");
}
n = write(newsockfd, "Hello Client!", 13);
if (n < 0)
error("ERROR writing to socket");
close(newsockfd);
close(sockfd);
return 0;
}

View file

@ -0,0 +1,87 @@
// Copyright 2020 Hugo Lindström <hugolm84@gmail.com>
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void
wsa_fatal(const char *func)
{
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
exit(1);
}
int
server(int portno)
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
char * message;
printf("Initialising Winsock...\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
wsa_fatal("Failed to call WSAStartup");
}
printf("Initialised WSA.\n");
// Create a socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
wsa_fatal("Could not create socket");
}
printf("Socket created.\n");
// Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portno);
// Bind
if (bind(s, (struct sockaddr *) &server, sizeof(server)) ==
SOCKET_ERROR) {
wsa_fatal("Bind failed");
}
printf("Bind done\n");
// Listen to incoming connections
listen(s, 3);
// Accept and incoming connection
printf("Waiting for incoming connections...\n");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(s, (struct sockaddr *) &client, &c)) !=
INVALID_SOCKET) {
printf("Connection accepted\n");
// Reply to the client
message = "Hello Client!";
if (send(new_socket, message, (int) strlen(message), 0) ==
SOCKET_ERROR) {
wsa_fatal("Failed to send message to client!");
}
}
if (new_socket == INVALID_SOCKET) {
wsa_fatal("accept failed");
}
if (closesocket(s) == SOCKET_ERROR) {
wsa_fatal("Failed to close socket");
}
if (WSACleanup() == SOCKET_ERROR) {
wsa_fatal("Failed to WSACleanup");
}
return 0;
}

109
external/nng/demo/stream/stream.c vendored Normal file
View file

@ -0,0 +1,109 @@
// Copyright 2020 Hugo Lindström <hugolm84@gmail.com>
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
// This program serves as an example for how to write async communication with
// an arbitrary socket using nng_stream. The server receives a connection and
// sends a hello message to the nng_stream iov.
// To run this program, start the server as stream -s <portnumber>
// Then connect to it with the client as stream -c <url>
//
// For example:
//
// % ./stream -s 5555 &
// % ./stream -c tcp://127.0.0.1:5555
#include <nng/nng.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void
nng_fatal(const char *func, int rv)
{
fprintf(stderr, "%s: %s\n", func, nng_strerror(rv));
exit(1);
}
int server(int port);
int client(const char *url);
int
main(int argc, char **argv)
{
int rc;
if (argc < 3) {
fprintf(stderr, "Usage: %s [-s port|-c url]\n", argv[0]);
exit(EXIT_FAILURE);
}
if (strcmp(argv[1], "-s") == 0) {
rc = server(atoi(argv[2]));
} else {
rc = client(argv[2]);
}
exit(rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
int
client(const char *url)
{
nng_stream_dialer *dialer;
nng_aio * aio;
nng_iov iov;
int rv;
// Allocatate dialer and aio assoicated with this connection
if ((rv = nng_stream_dialer_alloc(&dialer, url)) != 0) {
nng_fatal("call to nng_stream_dialer_alloc failed", rv);
}
if ((rv = nng_aio_alloc(&aio, NULL, NULL)) != 0) {
nng_fatal("call to nng_aio_alloc", rv);
}
nng_aio_set_timeout(aio, 5000); // 5 sec
// Allocatate a buffer to recv
iov.iov_len = 100;
iov.iov_buf = (char *) malloc(sizeof(char) * iov.iov_len);
if ((rv = nng_aio_set_iov(aio, 1, &iov)) != 0) {
nng_fatal("call to nng_aio_alloc", rv);
}
// Connect to the socket via url provided to alloc
nng_stream_dialer_dial(dialer, aio);
// Wait for connection
nng_aio_wait(aio);
if ((rv = nng_aio_result(aio)) != 0) {
nng_fatal("waiting for ng_stream_dialer_dial failed", rv);
}
// Get the stream (connection) at position 0
nng_stream *c1 = (nng_stream *) nng_aio_get_output(aio, 0);
nng_stream_recv(c1, aio);
nng_aio_wait(aio);
if ((rv = nng_aio_result(aio)) != 0) {
nng_fatal("waiting for nng_stream_recv failed", rv);
}
size_t recv_count = nng_aio_count(aio);
if (recv_count <= 0) {
nng_fatal("Recv count was 0!", NNG_ECONNABORTED);
} else {
printf("received %zu bytes, message: '%s'\n", recv_count,
(char *) iov.iov_buf);
}
// Send ELCOSE to send/recv associated wit this stream
free(iov.iov_buf);
nng_stream_free(c1);
nng_aio_free(aio);
nng_stream_dialer_free(dialer);
return 0;
}

View file

@ -2,42 +2,42 @@ ifdef::env-github[]
:important-caption: :heavy_exclamation_mark: :important-caption: :heavy_exclamation_mark:
endif::[] endif::[]
= Building for TLSv1.2 Support = Building for TLS Support
If you want to include support for Transport Layer Security If you want to include support for Transport Layer Security
(tls+tcp:// and wss:// URLs) you should follow these directions. (tls+tcp:// and wss:// URLs) you should follow these directions.
At this time, TLS support depends on the mbedTLS library. At this time, TLS support depends on the https://tls.mbed.org/[Mbed TLS]
See https://tls.mbed.org/ for details. library.
IMPORTANT: mbedTLS is licensed under different terms than NNG. IMPORTANT: Mbed TLS is licensed under different terms than NNG.
You are responsible for reading those license terms, and ensuring You are responsible for reading those license terms, and ensuring
that your use conforms to them. that your use conforms to them.
On many distributions you may be able to install a pre-packaged version On many distributions you may be able to install a pre-packaged version
of mbedTLS. We recommend doing so if this is an option for you. of Mbed TLS. We recommend doing so if this is an option for you.
For example, Ubuntu users can install the `libmbedtls-dev` package. For example, Ubuntu users can install the `libmbedtls-dev` package.
You can also build mbedTLS from source; if you choose to do so, You can also build Mbed TLS from source; if you choose to do so,
please make sure you also *install* it somewhere (even a temporary please make sure you also *install* it somewhere (even a temporary
staging directory). staging directory).
== Configuring NNG with mbedTLS == Configuring NNG with Mbed TLS
TLS support is not enabled by default, but can be enabled by configuring TLS support is not enabled by default, but can be enabled by configuring
with the CMake option `NNG_ENABLE_TLS=ON`. with the CMake option `NNG_ENABLE_TLS=ON`.
By default NNG searches for an installed copy of mbedTLS in `/usr/local`, By default NNG searches for an installed copy of Mbed TLS in `/usr/local`,
as well as the normal installation directories for libraries on your system. as well as the normal installation directories for libraries on your system.
If you have installed mbedTLS elsewhere, you can direct the NNG configuration If you have installed Mbed TLS elsewhere, you can direct the NNG configuration
to it by setting the `MBEDTLS_ROOT_DIR` CMake variable. to it by setting the `MBEDTLS_ROOT_DIR` CMake variable.
== Example == Example
The following example would work on either Linux or macOS, and assumes The following example would work on either Linux or macOS, and assumes
that we have checked out github source trees into `$HOME/work`. that we have checked out github source trees into `$HOME/work`.
It also assumes that mbedTLS is already installed in /usr/local or It also assumes that Mbed TLS is already installed in /usr/local or
a standard search path. a standard search path.
[source, sh] [source, sh]

View file

@ -1,5 +1,5 @@
# #
# Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
# Copyright 2018 Capitar IT Group BV <info@capitar.com> # Copyright 2018 Capitar IT Group BV <info@capitar.com>
# Copyright 2019 Devolutions <info@devolutions.net> # Copyright 2019 Devolutions <info@devolutions.net>
# #
@ -115,6 +115,11 @@ if (NNG_ENABLE_DOC)
nng_listener_set nng_listener_set
nng_listener_setopt nng_listener_setopt
nng_listener_start nng_listener_start
nng_log
nng_log_get_level
nng_log_set_facility
nng_log_set_level
nng_log_set_logger
nng_msg_alloc nng_msg_alloc
nng_msg_append nng_msg_append
nng_msg_body nng_msg_body
@ -177,6 +182,7 @@ if (NNG_ENABLE_DOC)
nng_stat_type nng_stat_type
nng_stat_unit nng_stat_unit
nng_stat_value nng_stat_value
nng_str_sockaddr
nng_strdup nng_strdup
nng_strerror nng_strerror
nng_strfree nng_strfree
@ -295,6 +301,7 @@ if (NNG_ENABLE_DOC)
nng_cv_wait nng_cv_wait
nng_cv_wake nng_cv_wake
nng_cv_wake1 nng_cv_wake1
nng_id_map
nng_msleep nng_msleep
nng_mtx_alloc nng_mtx_alloc
nng_mtx_free nng_mtx_free
@ -302,6 +309,7 @@ if (NNG_ENABLE_DOC)
nng_mtx_unlock nng_mtx_unlock
nng_opts_parse nng_opts_parse
nng_random nng_random
nng_socket_pair
nng_thread_create nng_thread_create
nng_thread_destroy nng_thread_destroy
nng_thread_set_name nng_thread_set_name
@ -388,6 +396,7 @@ if (NNG_ENABLE_DOC)
nng_rep nng_rep
nng_req nng_req
nng_respondent nng_respondent
nng_socket
nng_sub nng_sub
nng_surveyor nng_surveyor
nng_tcp nng_tcp

View file

@ -1,6 +1,6 @@
= libnng(3) = libnng(3)
// //
// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// Copyright 2019 Devolutions <info@devolutions.net> // Copyright 2019 Devolutions <info@devolutions.net>
// Copyright 2020 Dirac Research <robert.bielik@dirac.com> // Copyright 2020 Dirac Research <robert.bielik@dirac.com>
@ -164,6 +164,7 @@ The following functions are used in the asynchronous model:
|xref:nng_aio_abort.3.adoc[nng_aio_abort()]|abort asynchronous I/O operation |xref:nng_aio_abort.3.adoc[nng_aio_abort()]|abort asynchronous I/O operation
|xref:nng_aio_alloc.3.adoc[nng_aio_alloc()]|allocate asynchronous I/O handle |xref:nng_aio_alloc.3.adoc[nng_aio_alloc()]|allocate asynchronous I/O handle
|xref:nng_aio_begin.3.adoc[nng_aio_begin()]|begin asynchronous I/O operation |xref:nng_aio_begin.3.adoc[nng_aio_begin()]|begin asynchronous I/O operation
|xref:nng_aio_busy.3.adoc[nng_aio_busy()]|test if asynchronous I/O is busy
|xref:nng_aio_cancel.3.adoc[nng_aio_cancel()]|cancel asynchronous I/O operation |xref:nng_aio_cancel.3.adoc[nng_aio_cancel()]|cancel asynchronous I/O operation
|xref:nng_aio_count.3.adoc[nng_aio_count()]|return number of bytes transferred |xref:nng_aio_count.3.adoc[nng_aio_count()]|return number of bytes transferred
|xref:nng_aio_defer.3.adoc[nng_aio_defer()]|defer asynchronous I/O operation |xref:nng_aio_defer.3.adoc[nng_aio_defer()]|defer asynchronous I/O operation
@ -231,11 +232,22 @@ concurrent applications.
|xref:nng_ctx_id.3.adoc[nng_ctx_id()]|get numeric context identifier |xref:nng_ctx_id.3.adoc[nng_ctx_id()]|get numeric context identifier
|xref:nng_ctx_open.3.adoc[nng_ctx_open()]|create context |xref:nng_ctx_open.3.adoc[nng_ctx_open()]|create context
|xref:nng_ctx_recv.3.adoc[nng_ctx_recv()]|receive message using context asynchronously |xref:nng_ctx_recv.3.adoc[nng_ctx_recv()]|receive message using context asynchronously
|xref:nng_ctx_recvmsg.3.adoc[nng_ctx_recvmsg()]|receive a message using context
|xref:nng_ctx_send.3.adoc[nng_ctx_send()]|send message using context asynchronously |xref:nng_ctx_send.3.adoc[nng_ctx_send()]|send message using context asynchronously
|xref:nng_ctx_sendmsg.3.adoc[nng_ctx_sendmsg()]|send a message using context
|xref:nng_ctx_set.3.adoc[nng_ctx_set()]|set context option |xref:nng_ctx_set.3.adoc[nng_ctx_set()]|set context option
|xref:nng_ctx_setopt.3.adoc[nng_ctx_setopt()]|set context option |xref:nng_ctx_setopt.3.adoc[nng_ctx_setopt()]|set context option
|=== |===
=== Devices, Relays
The following function family is used to create forwarders or relayers
that route messages from one socket to another.
|===
|xref:nng_device.3.adoc[nng_device()]|message forwarding device
|===
=== Statistics === Statistics
The following functions provide access to statistics which can be used The following functions provide access to statistics which can be used
@ -271,6 +283,16 @@ universal resource locators (URLS).
|xref:nng_url_parse.3.adoc[nng_url_parse()]|create URL structure from string |xref:nng_url_parse.3.adoc[nng_url_parse()]|create URL structure from string
|=== |===
=== Logging Support
Common functionality for message logging.
|===
|xref:nng_log.3.adoc[nng_log()]|log a message
|xref:nng_log_facility.3.adoc[nng_log_set_facility()]|set log facility
|xref:nng_log_level.3.adoc[nng_log_set_level()]|set log level
|xref:nng_log_logger.3.adoc[nng_log_set_logger()]|set logging handler
|===
=== Supplemental API === Supplemental API
@ -286,6 +308,7 @@ as a convenience to aid in creating portable applications.
|xref:nng_cv_wait.3supp.adoc[nng_cv_wait()]|wait for condition |xref:nng_cv_wait.3supp.adoc[nng_cv_wait()]|wait for condition
|xref:nng_cv_wake.3supp.adoc[nng_cv_wake()]|wake all waiters |xref:nng_cv_wake.3supp.adoc[nng_cv_wake()]|wake all waiters
|xref:nng_cv_wake1.3supp.adoc[nng_cv_wake1()]|wake one waiter |xref:nng_cv_wake1.3supp.adoc[nng_cv_wake1()]|wake one waiter
|xref:nng_id_map.3supp.adoc[nng_id_map]|identifier based mapping table
|xref:nng_msleep.3supp.adoc[nng_msleep()]|sleep for milliseconds |xref:nng_msleep.3supp.adoc[nng_msleep()]|sleep for milliseconds
|xref:nng_mtx_alloc.3supp.adoc[nng_mtx_alloc()]|allocate mutex |xref:nng_mtx_alloc.3supp.adoc[nng_mtx_alloc()]|allocate mutex
|xref:nng_mtx_free.3supp.adoc[nng_mtx_free()]|free mutex |xref:nng_mtx_free.3supp.adoc[nng_mtx_free()]|free mutex
@ -293,6 +316,7 @@ as a convenience to aid in creating portable applications.
|xref:nng_mtx_unlock.3supp.adoc[nng_mtx_unlock()]|unlock mutex |xref:nng_mtx_unlock.3supp.adoc[nng_mtx_unlock()]|unlock mutex
|xref:nng_opts_parse.3supp.adoc[nng_opts_parse()]|parse command line options |xref:nng_opts_parse.3supp.adoc[nng_opts_parse()]|parse command line options
|xref:nng_random.3supp.adoc[nng_random()]|get random number |xref:nng_random.3supp.adoc[nng_random()]|get random number
|xref:nng_socket_pair.3supp.adoc[nng_socket_pair()]|create connected pair of BSD sockets
|xref:nng_thread_create.3supp.adoc[nng_thread_create()]|create thread |xref:nng_thread_create.3supp.adoc[nng_thread_create()]|create thread
|xref:nng_thread_destroy.3supp.adoc[nng_thread_destroy()]|reap thread |xref:nng_thread_destroy.3supp.adoc[nng_thread_destroy()]|reap thread
|xref:nng_thread_set_name.3supp.adoc[nng_thread_set_name()]|set thread name |xref:nng_thread_set_name.3supp.adoc[nng_thread_set_name()]|set thread name

View file

@ -69,6 +69,7 @@ xref:nng_surveyor.7.adoc[nng_surveyor(7)]:: Surveyor side of survey protocol
[horizontal] [horizontal]
xref:nng_inproc.7.adoc[nng_inproc(7)]:: Intra-process transport xref:nng_inproc.7.adoc[nng_inproc(7)]:: Intra-process transport
xref:nng_ipc.7.adoc[nng_ipc(7)]:: Inter-process transport xref:nng_ipc.7.adoc[nng_ipc(7)]:: Inter-process transport
xref:nng_socket.7.adoc[nng_socket(7)]:: BSD socket transport
xref:nng_tls.7.adoc[nng_tls(7)]:: TLSv1.2 over TCP transport xref:nng_tls.7.adoc[nng_tls(7)]:: TLSv1.2 over TCP transport
xref:nng_tcp.7.adoc[nng_tcp(7)]:: TCP (and TCPv6) transport xref:nng_tcp.7.adoc[nng_tcp(7)]:: TCP (and TCPv6) transport
xref:nng_ws.7.adoc[nng_ws(7)]:: WebSocket transport xref:nng_ws.7.adoc[nng_ws(7)]:: WebSocket transport

View file

@ -1,6 +1,6 @@
= nng_aio_alloc(3) = nng_aio_alloc(3)
// //
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -37,7 +37,7 @@ This also means you should avoid operations such as allocating new objects,
which also means opening or closing sockets, dialers, and so forth. which also means opening or closing sockets, dialers, and so forth.
TIP: If more complex or blocking work needs to be performed by _callb_, a separate TIP: If more complex or blocking work needs to be performed by _callb_, a separate
thread can be used, along with a xref:nng_cv_alloc.3.adoc[condition variable] thread can be used, along with a xref:nng_cv_alloc.3supp.adoc[condition variable]
which can be signaled by the callback. which can be signaled by the callback.
Asynchronous I/O operations all take an xref:nng_aio.5.adoc[`nng_aio`] Asynchronous I/O operations all take an xref:nng_aio.5.adoc[`nng_aio`]

View file

@ -0,0 +1,56 @@
= nng_aio_busy(3)
//
// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_aio_busy - test if asynchronous I/O is busy
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
bool nng_aio_busy(nng_aio *aio);
----
== DESCRIPTION
The `nng_aio_busy()` function returns true if the
_aio_ is currently busy performing an asynchronous I/O
operation or is executing a completion callback.
If no operation has been started, or the operation has
been completed or canceled, and any callback has been
executed, then it returns false.
This is the same test used internally by
xref:nng_aio_wait.3.adoc[`nng_aio_wait()`]
NOTE: Care should be taken to ensure that the _aio_ object is not
freed when using this function. The caller is responsible for
coordinating any use of this with any reuse of the _aio_.
== RETURN VALUES
True if the _aio_ is busy, false otherwise.
== ERRORS
None.
== SEE ALSO
[.text-left]
xref:nng_aio_abort.3.adoc[nng_aio_abort(3)],
xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)],
xref:nng_aio_wait.3.adoc[nng_aio_wait(3)],
xref:nng_aio.5.adoc[nng_aio(5)],
xref:nng.7.adoc[nng(7)]

View file

@ -32,7 +32,7 @@ that it is safe to deallocate the handle and any associated resources.
(This is done by implicitly calling xref:nng_aio_stop.3.adoc[`nng_aio_stop()`].) (This is done by implicitly calling xref:nng_aio_stop.3.adoc[`nng_aio_stop()`].)
The `nng_aio_reap()` function is the same as `nng_aio_free()`, but does The `nng_aio_reap()` function is the same as `nng_aio_free()`, but does
it's work in a background thread. its work in a background thread.
This can be useful to discard the _aio_ object from within the callback for the _aio_. This can be useful to discard the _aio_ object from within the callback for the _aio_.
IMPORTANT: Once either of these functions are called, the _aio_ object is invalid and must not be used again. IMPORTANT: Once either of these functions are called, the _aio_ object is invalid and must not be used again.

View file

@ -1,6 +1,6 @@
= nng_aio_set_timeout(3) = nng_aio_set_timeout(3)
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -21,6 +21,9 @@ nng_aio_set_timeout - set asynchronous I/O timeout
typedef int nng_duration; typedef int nng_duration;
void nng_aio_set_timeout(nng_aio *aio, nng_duration timeout); void nng_aio_set_timeout(nng_aio *aio, nng_duration timeout);
typedef uint64_t nng_time;
void nng_aio_set_expire(nng_aio *aio, nng_time expiration);
---- ----
== DESCRIPTION == DESCRIPTION
@ -37,6 +40,12 @@ If the timeout is `NNG_DURATION_DEFAULT`, then a "default" or socket-specific
timeout is used. timeout is used.
(This is frequently the same as `NNG_DURATION_INFINITE`.) (This is frequently the same as `NNG_DURATION_INFINITE`.)
The `nng_aio_set_expire()` function is similar to `nng_aio_set_timeout()`, but sets
an absolute expiration time based on the system clock. The _expiration_
is expressed as a number of milliseconds since some point in the past.
The xref:nng_clock.3supp.adoc[`nng_clock()`] function can be used to determine
the current value of the clock.
TIP: As most operations involve some context switching, it is usually a good TIP: As most operations involve some context switching, it is usually a good
idea to allow at least a few tens of milliseconds before timing them out -- idea to allow at least a few tens of milliseconds before timing them out --
a too small timeout might not allow the operation to properly begin before a too small timeout might not allow the operation to properly begin before

View file

@ -1,6 +1,6 @@
= nng_aio_stop(3) = nng_aio_stop(3)
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -26,22 +26,18 @@ void nng_aio_stop(nng_aio *aio);
The `nng_aio_stop()` function stops the asynchronous I/O operation The `nng_aio_stop()` function stops the asynchronous I/O operation
associated with _aio_ by aborting with `NNG_ECANCELED`, and then waits associated with _aio_ by aborting with `NNG_ECANCELED`, and then waits
for it to complete or to be completely aborted. for it to complete or to be completely aborted, and for the
callback associated with the _aio_ to have completed executing.
If an operation is in progress when this function is called, that operation Further calls to
is canceled and the callback function is _not_ allowed to run. xref:nng_aio_begin.3.adoc[`nng_aio_begin()`] using this _aio_ will return false.
If the callback function is already running when this function is called, It is safe to call this for an _aio_, even when no operation is currently
then it is allowed to complete before returning to the caller. pending for it.
No new operations will be started on this _aio_.
NOTE: Calling this function means that the operation may be aborted without
completing its callback function.
TIP: When multiple asynchronous I/O handles are in use and need to be TIP: When multiple asynchronous I/O handles are in use and need to be
shut down, it is safest to stop all of them, before deallocating any of shut down, it is safest to stop all of them, before deallocating any of
this with xref:nng_aio_free.3.adoc[`nng_aio_free()`], particularly if the callbacks them with xref:nng_aio_free.3.adoc[`nng_aio_free()`], particularly if the callbacks
might attempt to reschedule additional operations. might attempt to reschedule additional operations.
== RETURN VALUES == RETURN VALUES
@ -55,9 +51,10 @@ None.
== SEE ALSO == SEE ALSO
[.text-left] [.text-left]
xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)],
xref:nng_aio_cancel.3.adoc[nng_aio_cancel(3)], xref:nng_aio_cancel.3.adoc[nng_aio_cancel(3)],
xref:nng_aio_free.3.adoc[nng_aio_free(3)], xref:nng_aio_free.3.adoc[nng_aio_free(3)],
xref:nng_aio_begin.3.adoc[nng_aio_begin(3)],
xref:nng_aio_wait.3.adoc[nng_aio_wait(3)], xref:nng_aio_wait.3.adoc[nng_aio_wait(3)],
xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)],
xref:nng_aio.5.adoc[nng_aio(5)], xref:nng_aio.5.adoc[nng_aio(5)],
xref:nng.7.adoc[nng(7)] xref:nng.7.adoc[nng(7)]

View file

@ -1,6 +1,6 @@
= nng_aio_wait(3) = nng_aio_wait(3)
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -29,9 +29,13 @@ to complete.
If the operation has not been started, or has already If the operation has not been started, or has already
completed, then it returns immediately. completed, then it returns immediately.
If the a callback was set with _aio_ when it was allocated, then this If a callback was set with _aio_ when it was allocated, then this
function will not be called until the callback has completed. function will not be called until the callback has completed.
IMPORTANT: This function should never be called from a function that itself
is a callback of an xref:nng_aio.5.adoc[`aio`], either this one or any other.
Doing so may result in a deadlock.
== RETURN VALUES == RETURN VALUES
None. None.
@ -45,5 +49,6 @@ None.
[.text-left] [.text-left]
xref:nng_aio_abort.3.adoc[nng_aio_abort(3)], xref:nng_aio_abort.3.adoc[nng_aio_abort(3)],
xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)], xref:nng_aio_alloc.3.adoc[nng_aio_alloc(3)],
xref:nng_aio_busy.3.adoc[nng_aio_busy(3)],
xref:nng_aio.5.adoc[nng_aio(5)], xref:nng_aio.5.adoc[nng_aio(5)],
xref:nng.7.adoc[nng(7)] xref:nng.7.adoc[nng(7)]

View file

@ -32,7 +32,7 @@ arbitrary time in the past.
The resolution of the clock depends on the underlying timing facilities The resolution of the clock depends on the underlying timing facilities
of the system. of the system.
This function may be used for timing, but applications should not expect This function may be used for timing, but applications should not expect
very fine grained values. very fine-grained values.
IMPORTANT: The reference time will be the same for a given program, IMPORTANT: The reference time will be the same for a given program,
but different programs may have different references. but different programs may have different references.

View file

@ -141,17 +141,17 @@ or xref:nng_listen.3.adoc[`nng_listen()`].
---- ----
#define CONCURRENCY 1024 #define CONCURRENCY 1024
echo_context ecs[CONCURRENCY]; static struct echo_context ecs[CONCURRENCY];
void void
start_echo_service(nng_socket rep_socket) start_echo_service(nng_socket rep_socket)
{ {
for (int i = 0; i < CONCURRENCY; i++) { for (int i = 0; i < CONCURRENCY; i++) {
// error checks elided for clarity // error checks elided for clarity
nng_ctx_open(ec[i].ctx, rep_socket) nng_ctx_open(&ecs[i].ctx, rep_socket);
nng_aio_alloc(ec[i].aio, echo, &e[i]); nng_aio_alloc(&ecs[i].aio, echo, ecs+i);
ec[i].state = INIT; ecs[i].state = INIT;
echo(&ec[i]); // start it running echo(ecs+i); // start it running
} }
} }
---- ----
@ -165,7 +165,9 @@ xref:nng_ctx_open.3.adoc[nng_ctx_open(3)],
xref:nng_ctx_get.3.adoc[nng_ctx_get(3)], xref:nng_ctx_get.3.adoc[nng_ctx_get(3)],
xref:nng_ctx_id.3.adoc[nng_ctx_id(3)], xref:nng_ctx_id.3.adoc[nng_ctx_id(3)],
xref:nng_ctx_recv.3.adoc[nng_ctx_recv(3)], xref:nng_ctx_recv.3.adoc[nng_ctx_recv(3)],
xref:nng_ctx_recvmsg.3.adoc[nng_ctx_recvmsg(3)],
xref:nng_ctx_send.3.adoc[nng_ctx_send(3)], xref:nng_ctx_send.3.adoc[nng_ctx_send(3)],
xref:nng_ctx_sendmsg.3.adoc[nng_ctx_sendmsg(3)],
xref:nng_ctx_set.3.adoc[nng_ctx_set(3)], xref:nng_ctx_set.3.adoc[nng_ctx_set(3)],
xref:nng_dialer.5.adoc[nng_dialer(5)], xref:nng_dialer.5.adoc[nng_dialer(5)],
xref:nng_listener.5.adoc[nng_listener(5)], xref:nng_listener.5.adoc[nng_listener(5)],

View file

@ -85,8 +85,8 @@ The value will be stored at _ivalp_.
`nng_ctx_get_ms()`:: `nng_ctx_get_ms()`::
This function is used to retrieve time xref:nng_duration.5.adoc[durations] This function is used to retrieve time xref:nng_duration.5.adoc[durations]
(such as timeouts), stored in _durp_ as a number of milliseconds. (such as timeouts), stored in _durp_ as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_ctx_get_size()`:: `nng_ctx_get_size()`::
This function is used to retrieve a size into the pointer _zp_, This function is used to retrieve a size into the pointer _zp_,

View file

@ -88,8 +88,8 @@ The value will be stored at _ivalp_.
`nng_ctx_getopt_ms()`:: `nng_ctx_getopt_ms()`::
This function is used to retrieve time xref:nng_duration.5.adoc[durations] This function is used to retrieve time xref:nng_duration.5.adoc[durations]
(such as timeouts), stored in _durp_ as a number of milliseconds. (such as timeouts), stored in _durp_ as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_ctx_getopt_size()`:: `nng_ctx_getopt_size()`::
This function is used to retrieve a size into the pointer _zp_, This function is used to retrieve a size into the pointer _zp_,

View file

@ -0,0 +1,63 @@
= nng_ctx_recvmsg(3)
//
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_ctx_recvmsg - receive message using socket
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
int nng_ctx_recvmsg(nng_ctx ctx, nng_msg **msgp, int flags);
----
== DESCRIPTION
The `nng_ctx_recvmsg()` receives a message on context _ctx_, storing the
received message at the location pointed to by _msgp_.
The _flags_ may contain the following value:
`NNG_FLAG_NONBLOCK`::
The function returns immediately, even if no message is available.
Without this flag, the function will wait until a message is receivable
on the context _ctx_, or any configured timer expires.
NOTE: The semantics of what receiving a message means vary from protocol to
protocol, so examination of the protocol documentation is encouraged.
== RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
== ERRORS
[horizontal]
`NNG_EAGAIN`:: The operation would block, but `NNG_FLAG_NONBLOCK` was specified.
`NNG_ECLOSED`:: The context or socket is not open.
`NNG_EINVAL`:: An invalid set of _flags_ was specified.
`NNG_ENOMEM`:: Insufficient memory is available.
`NNG_ENOTSUP`:: The protocol does not support receiving.
`NNG_ESTATE`:: The context cannot receive data in this state.
`NNG_ETIMEDOUT`:: The operation timed out.
== SEE ALSO
[.text-left]
xref:nng_msg_free.3.adoc[nng_msg_free(3)],
xref:nng_ctx_open.3.adoc[nng_ctx_open(3)],
xref:nng_ctx_recv.3.adoc[nng_ctx_recv(3)],
xref:nng_ctx_sendmsg.3.adoc[nng_ctx_sendmsg(3)],
xref:nng_strerror.3.adoc[nng_strerror(3)],
xref:nng_ctx.5.adoc[nng_ctx(5)],
xref:nng.7.adoc[nng(7)]

View file

@ -0,0 +1,84 @@
= nng_ctx_sendmsg(3)
//
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_ctx_sendmsg - send message using context
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
int nng_ctx_sendmsg(nng_ctx c, nng_msg *msg, int flags);
----
== DESCRIPTION
The `nng_ctx_sendmsg()` sends message _msg_ using the context _ctx_.
If the function returns zero, indicating it has accepted the message for
delivery, then the _msg_ is owned by the socket _s_, and the caller
must not make any further use of it.
The socket will free the message when it is finished.
If the function returns non-zero, then it is the caller's responsibility
to dispose of the _msg_, which may include freeing it, sending it to
another socket, or simply trying again later.
NOTE: The semantics of what sending a message means vary from protocol to
protocol, so examination of the protocol documentation is encouraged.
The _flags_ may contain the following value:
`NNG_FLAG_NONBLOCK`::
The function returns immediately, regardless of whether
the context is able to accept the data or not.
If the context is unable to accept the data (such as if backpressure exists
because the peers are consuming messages too slowly, or no peer is present),
then the function will return with `NNG_EAGAIN`.
If this flag is not specified, then the function will block if such a
condition exists.
NOTE: Regardless of the presence or absence of `NNG_FLAG_NONBLOCK`, there may
be queues between the sender and the receiver.
Furthermore, there is no guarantee that the message has actually been delivered.
Finally, with some protocols, the semantic is implicitly `NNG_FLAG_NONBLOCK`.
== RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
== ERRORS
[horizontal]
`NNG_EAGAIN`:: The operation would block, but `NNG_FLAG_NONBLOCK` was specified.
`NNG_ECLOSED`:: The context or socket is not open.
`NNG_EINVAL`:: An invalid set of _flags_ was specified.
`NNG_EMSGSIZE`:: The value of _size_ is too large.
`NNG_ENOMEM`:: Insufficient memory is available.
`NNG_ENOTSUP`:: The protocol does not support sending.
`NNG_ESTATE`:: The context cannot send data in this state.
`NNG_ETIMEDOUT`:: The operation timed out.
== SEE ALSO
[.text-left]
xref:nng_msg_alloc.3.adoc[nng_msg_alloc(3)],
xref:nng_ctx_open.3.adoc[nng_ctx_open(3)],
xref:nng_ctx_recvmsg.3.adoc[nng_ctx_recvmsg(3)],
xref:nng_ctx_send.3.adoc[nng_ctx_send(3)],
xref:nng_sendmsg.3.adoc[nng_sendmsg(3)],
xref:nng_strerror.3.adoc[nng_strerror(3)],
xref:nng_msg.5.adoc[nng_msg(5)],
xref:nng_ctx.5.adoc[nng_ctx(5)],
xref:nng.7.adoc[nng(7)]

View file

@ -1,6 +1,6 @@
= nng_device(3) = nng_device(3)
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -20,14 +20,16 @@ nng_device - message forwarding device
#include <nng/nng.h> #include <nng/nng.h>
int nng_device(nng_socket s1, nng_socket s2); int nng_device(nng_socket s1, nng_socket s2);
void nng_device_aio(nng_aio *aio, nng_socket s1, nng_socket s2);
---- ----
== DESCRIPTION == DESCRIPTION
The `nng_device()` function forwards messages received from one The `nng_device()` and `nng_device_aio()` functions forward messages received from one
xref:nng_socket.5.adoc[socket] _s1_ to another socket _s2_, and vice versa. xref:nng_socket.5.adoc[socket] _s1_ to another socket _s2_, and vice versa.
This function is used to create forwarders, which can be used to create These functions are used to create forwarders, which can be used to create
complex network topologies to provide for improved ((horizontal scalability)), complex network topologies to provide for improved ((horizontal scalability)),
reliability, and isolation. reliability, and isolation.
@ -38,6 +40,8 @@ such as xref:nng_req_open.3.adoc[`nng_req0_open_raw()`].
The `nng_device()` function does not return until one of the sockets The `nng_device()` function does not return until one of the sockets
is closed. is closed.
The `nng_device_aio()` function returns immediately, and operates completely in
the background.
=== Reflectors === Reflectors
@ -49,7 +53,7 @@ xref:nng_pair.7.adoc[_pair_] or
xref:nng_bus.7.adoc[_bus_].) xref:nng_bus.7.adoc[_bus_].)
In this case the device acts as a ((reflector)) or loop-back device, In this case the device acts as a ((reflector)) or loop-back device,
where messages received from the valid socket are merely returned where messages received from the valid socket are merely returned
back to the sender. to the sender.
=== Forwarders === Forwarders
@ -75,6 +79,9 @@ adjustments to add or remove routing headers as needed.
This allows replies to be This allows replies to be
returned to requesters, and responses to be routed back to surveyors. returned to requesters, and responses to be routed back to surveyors.
The caller of these functions is required to close the sockets when the
device is stopped.
Additionally, some protocols have a maximum ((time-to-live)) to protect Additionally, some protocols have a maximum ((time-to-live)) to protect
against forwarding loops and especially amplification loops. against forwarding loops and especially amplification loops.
In these cases, the default limit (usually 8), ensures that messages will In these cases, the default limit (usually 8), ensures that messages will
@ -88,7 +95,7 @@ IMPORTANT: Not all protocols have support for guarding against forwarding loops,
and even for those that do, forwarding loops can be extremely detrimental and even for those that do, forwarding loops can be extremely detrimental
to network performance. to network performance.
NOTE: Devices (forwarders and reflectors) act in best effort delivery mode only. NOTE: Devices (forwarders and reflectors) act in best-effort delivery mode only.
If a message is received from one socket that cannot be accepted by the If a message is received from one socket that cannot be accepted by the
other (due to backpressure or other issues), then the message is discarded. other (due to backpressure or other issues), then the message is discarded.

View file

@ -88,8 +88,8 @@ The value will be stored at _ivalp_.
`nng_dialer_get_ms()`:: `nng_dialer_get_ms()`::
This function is used to retrieve time xref:nng_duration.5.adoc[durations] This function is used to retrieve time xref:nng_duration.5.adoc[durations]
(such as timeouts), stored in _durp_ as a number of milliseconds. (such as timeouts), stored in _durp_ as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_dialer_get_ptr()`:: `nng_dialer_get_ptr()`::
This function is used to retrieve a pointer, _ptr_, to structured data. This function is used to retrieve a pointer, _ptr_, to structured data.

View file

@ -91,8 +91,8 @@ The value will be stored at _ivalp_.
`nng_dialer_getopt_ms()`:: `nng_dialer_getopt_ms()`::
This function is used to retrieve time xref:nng_duration.5.adoc[durations] This function is used to retrieve time xref:nng_duration.5.adoc[durations]
(such as timeouts), stored in _durp_ as a number of milliseconds. (such as timeouts), stored in _durp_ as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_dialer_getopt_ptr()`:: `nng_dialer_getopt_ptr()`::
This function is used to retrieve a pointer, _ptr_, to structured data. This function is used to retrieve a pointer, _ptr_, to structured data.

View file

@ -90,8 +90,8 @@ The value will be stored at _ivalp_.
`nng_getopt_ms()`:: `nng_getopt_ms()`::
This function is used to retrieve time xref:nng_duration.5.adoc[durations] This function is used to retrieve time xref:nng_duration.5.adoc[durations]
(such as timeouts), stored in _durp_ as a number of milliseconds. (such as timeouts), stored in _durp_ as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_getopt_ptr()`:: `nng_getopt_ptr()`::
This function is used to retrieve a pointer, _ptr_, to structured data. This function is used to retrieve a pointer, _ptr_, to structured data.

View file

@ -25,7 +25,7 @@ int nng_http_handler_collect_body(nng_http_handler *handler, bool want, size_t m
== DESCRIPTION == DESCRIPTION
The `nng_http_handler_collect_data()` function causes the _handler_ to The `nng_http_handler_collect_body()` function causes the _handler_ to
collect any request body that was submitted with the request, and attach collect any request body that was submitted with the request, and attach
it to the `nng_http_req` before the handler is called. it to the `nng_http_req` before the handler is called.

View file

@ -0,0 +1,100 @@
= nng_id_map(3supp)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_id_map - identifier based mapping table
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
#include <nng/supplemental/util/idhash.h>
typedef struct nng_id_map_s nng_id_map;
#define NNG_MAP_RANDOM 1
int nng_id_map_alloc(nng_id_map **map_p, uint64_t lo, uint64_t hi, int flags);
void nng_id_map_free(nng_id_map *map);
void *nng_id_get(nng_id_map *map, uint64_t id);
int nng_id_set(nng_id_map *map, uint64_t, void *value);
int nng_id_alloc(nng_id_map *map, uint64_t *id_p, void *value);
int nng_id_remove(nng_id_map *map, uint64_t id);
----
== DESCRIPTION
These functions provide support for managing tables of data based on
identifiers, ensuring that identifiers are allocated uniquely and within
specified range limits.
The table stores data pointers (which must not be `NULL`) at a logical numeric index.
It does so efficiently, even if large gaps exist, and it provides a means to efficiently
allocate a numeric identifier from a pool of unused identifiers.
Identifiers are allocated in increasing order, without reusing old identifiers until the
largest possible identifier is allocated. After wrapping, only identifiers that are no longer
in use will be considered.
No effort to order the availability of identifiers based on when they were freed is made.
An initial table is allocated with `nng_id_map_alloc()`, which takes the lowest legal identifier in _lo_,
and the largest legal identifier in _hi_.
The new table is returned in _map_p_, and should be used as the _map_ argument to the rest of these functions.
****
As a special convenience, if these are specified as zero, then a full range of 32-bit identifiers is assumed.
If identifiers larger than or equal to 2^32^ are required, then both _lo_ and _hi_ must be specified with the
exact values desired.
****
The _flags_ argument is a bit mask of flags for the table.
If `NNG_MAP_RANDOM` is specified, then the starting point for allocations is randomized, but subsequent allocations will then be monotonically increasing.
This is useful to reduce the odds of different instances of an application using the same identifiers at the same time.
The `nng_id_get()` function returns the value previously stored with the given identifier.
If no value is currently associated with the identifer, it returns `NULL`.
The `nng_id_set()` function sets the value with the associated identifier.
This can be used to replace a previously allocated identifier.
If the identifier was not previously allocated, then it is allocated as part of the call.
This function does not necessarily honor the identifier range limits set for the map when it was allocated.
The `nng_id_alloc()` function allocates a new identifier from the range for the map, and associates it with
the supplied _value_.
The `nng_id_remove()` function removes the identifier and its associated value from the table.
NOTE: These functions are limited to storing at most 2^32^ identifiers, even though the identifers may
themselves be larger than 2^32^.
IMPORTANT: These functions are *not* thread-safe.
Callers should use a xref:nng_mtx_lock.3supp[mutex] or similar approach when thread-safety is needed.
== RETURN VALUES
The `nng_id_map_alloc()`, `nng_id_set()`, `nng_id_alloc()`, and `nng_id_remove()` functions
return 0 on success, or -1 on failure.
The `nng_id_map_get()` function returns the requested data pointer, or `NULL` if the identifier was not found.
== ERRORS
[horizontal]
`NNG_ENOENT`:: The _id_ does not exist in the table.
`NNG_ENOMEM`:: Insufficient memory is available, or the table is full.
== SEE ALSO
[.text-left]
xref:nng_mtx_lock.3supp.adoc[nng(7)]
xref:nng.7.adoc[nng(7)]

View file

@ -1,6 +1,6 @@
= nng_ipc(7) = nng_ipc(7)
// //
// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -107,14 +107,14 @@ except for abstract sockets, which use xref:nng_sockaddr_abstract.5.adoc[`nng_so
The following transport options are supported by this transport, The following transport options are supported by this transport,
where supported by the underlying platform. where supported by the underlying platform.
* xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_PEER_GID[`NNG_OPT_IPC_PEER_GID`]
* xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_PEER_PID[`NNG_OPT_IPC_PEER_PID`]
* xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_PEER_UID[`NNG_OPT_IPC_PEER_UID`]
* xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_PEER_ZONEID[`NNG_OPT_IPC_PEER_ZONEID`]
* xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_PERMISSIONS[`NNG_OPT_IPC_PERMISSIONS`] * xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_PERMISSIONS[`NNG_OPT_IPC_PERMISSIONS`]
* xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_SECURITY_DESCRIPTOR[`NNG_OPT_IPC_SECURITY_DESCRIPTOR`] * xref:nng_ipc_options.5.adoc#NNG_OPT_IPC_SECURITY_DESCRIPTOR[`NNG_OPT_IPC_SECURITY_DESCRIPTOR`]
* xref:nng_options.5.adoc#NNG_OPT_LOCADDR[`NNG_OPT_LOCADDR`] * xref:nng_options.5.adoc#NNG_OPT_LOCADDR[`NNG_OPT_LOCADDR`]
* xref:nng_options.5.adoc#NNG_OPT_REMADDR[`NNG_OPT_REMADDR`] * xref:nng_options.5.adoc#NNG_OPT_REMADDR[`NNG_OPT_REMADDR`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_GID[`NNG_OPT_PEER_GID`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_PID[`NNG_OPT_PEER_PID`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_UID[`NNG_OPT_PEER_UID`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_ZONEID[`NNG_OPT_PEER_ZONEID`]
* xref:nng_options.5.adoc#NNG_OPT_URL[`NNG_OPT_URL`] * xref:nng_options.5.adoc#NNG_OPT_URL[`NNG_OPT_URL`]
== SEE ALSO == SEE ALSO

View file

@ -1,6 +1,6 @@
= nng_ipc_options(5) = nng_ipc_options(5)
// //
// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// Copyright 2019 Devolutions <info@devolutions.net> // Copyright 2019 Devolutions <info@devolutions.net>
// //
@ -43,43 +43,9 @@ have other access restrictions.
An attempt has been made to include details about such restrictions in the An attempt has been made to include details about such restrictions in the
description of the option. description of the option.
NOTE: The availability of any of the following options is platform-specific, NOTE: The availability of the following options is platform-specific,
as the implementations of IPC are quite different on Windows and POSIX systems. as the implementations of IPC are quite different on Windows and POSIX systems.
=== IPC Options
[[NNG_OPT_IPC_PEER_GID]]((`NNG_OPT_IPC_PEER_GID`))::
(`uint64_t`)
This read-only option provides a connected peer's primary
group id.
This is the effective group id of the peer when either the underlying
`listen()` or `connect()` calls were made, and is not forgeable.
This option is generally only available on POSIX systems.
[[NNG_OPT_IPC_PEER_PID]]((`NNG_OPT_IPC_PEER_PID`))::
(`uint64_t`)
This read-only option provides the the process id
of the connected peer.
This option is only available on Windows, Linux, and certain other systems.
+
NOTE: Applications should not assume that the process ID does not change,
as it is possible (although unsupported!) for a nefarious process to pass a
file descriptor between processes.
However, it is not possible for a nefarious application to forge the identity
of a well-behaved one using this method.
[[NNG_OPT_IPC_PEER_UID]]((`NNG_OPT_IPC_PEER_UID`))::
(`uint64_t`)
This read-only option provides a connected peer's user id.
This is the effective user id of the peer when either the underlying
`listen()` or `connect()` calls were made, and is not forgeable.
This option is generally only available on POSIX systems.
[[NNG_OPT_IPC_PEER_ZONEID]]((`NNG_OPT_IPC_PEER_ZONEID`))::
(`uint64_t`)
This read-only option provides a connected peer's the zone id.
Zones (and this option) are only supported on Solaris and illumos systems.
[[NNG_OPT_IPC_PERMISSIONS]]((`NNG_OPT_IPC_PERMISSIONS`)):: [[NNG_OPT_IPC_PERMISSIONS]]((`NNG_OPT_IPC_PERMISSIONS`))::
(`int`) (`int`)
This write-only option may be applied to a listener to configure the This write-only option may be applied to a listener to configure the
@ -115,10 +81,18 @@ named pipe.
The value is a pointer, `PSECURITY_DESCRIPTOR`, and may only be The value is a pointer, `PSECURITY_DESCRIPTOR`, and may only be
applied to listeners that have not been started yet. applied to listeners that have not been started yet.
=== Common Platform Specific Options
The following options are supported by this transport when the underlying platform supports them:
* xref:nng_options.5.adoc#NNG_OPT_PEER_GID[`NNG_OPT_PEER_GID`] (also available as `NNG_OPT_IPC_PEER_GID`)
* xref:nng_options.5.adoc#NNG_OPT_PEER_PID[`NNG_OPT_PEER_PID`] (also available as `NNG_OPT_IPC_PEER_PID`)
* xref:nng_options.5.adoc#NNG_OPT_PEER_UID[`NNG_OPT_PEER_UID`] (also available as `NNG_OPT_IPC_PEER_UID`)
* xref:nng_options.5.adoc#NNG_OPT_PEER_ZONEID[`NNG_OPT_PEER_ZONEID`] (also available as `NNG_OPT_IPC_PEER_ZONEID`)
=== Inherited Options === Inherited Options
Generally, the following option values are also available for TLS objects, Generally, the following option values are also available when appropriate for the context:
when appropriate for the context:
* xref:nng_options.5.adoc#NNG_OPT_LOCADDR[`NNG_OPT_LOCADDR`] * xref:nng_options.5.adoc#NNG_OPT_LOCADDR[`NNG_OPT_LOCADDR`]
* xref:nng_options.5.adoc#NNG_OPT_REMADDR[`NNG_OPT_REMADDR`] * xref:nng_options.5.adoc#NNG_OPT_REMADDR[`NNG_OPT_REMADDR`]
@ -126,11 +100,11 @@ when appropriate for the context:
== SEE ALSO == SEE ALSO
[.text-left] [.text-left]
xref:nng_ipc_dialer_getopt.3ipc.adoc[nng_ipc_dialer_getopt(3ipc)], xref:nng_dialer_get.3.adoc[nng_dialer_get(3)],
xref:nng_ipc_dialer_setopt.3ipc.adoc[nng_ipc_dialer_setopt(3ipc)], xref:nng_dialer_set.3.adoc[nng_dialer_set(3)],
xref:nng_ipc_getopt.3ipc.adoc[nng_ipc_getopt(3ipc)], xref:nng_listener_get.3.adoc[nng_listener_get(3)],
xref:nng_ipc_listener_getopt.3ipc.adoc[nng_ipc_listener_getopt(3ipc)], xref:nng_listener_set.3.adoc[nng_listener_set(3)],
xref:nng_ipc_listener_setopt.3ipc.adoc[nng_ipc_listener_setopt(3ipc)], xref:nng_pipe_get.3.adoc[nng_pipe_get(3)],
xref:nng_ipc_setopt.3ipc.adoc[nng_ipc_setopt(3ipc)],
xref:nng_options.5.adoc[nng_options(5)] xref:nng_options.5.adoc[nng_options(5)]
xref:nng.7.adoc[nng(7)] xref:nng.7.adoc[nng(7)],
xref:nng_ipc.7.adoc[nng_ipc(7)]

65
external/nng/docs/man/nng_log.3.adoc vendored Normal file
View file

@ -0,0 +1,65 @@
= nng_log(3)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_log - log messages
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
void nng_log_err(const char *msgid, const char *msg, ...);
void nng_log_warn(const char *msgid, const char *msg, ...);
void nng_log_notice(const char *msgid, const char *msg, ...);
void nng_log_info(const char *msgid, const char *msg, ...);
void nng_log_debug(const char *msgid, const char *msg, ...);
void nng_log_auth(nng_log_level level, const char *msgid, const char *msg, ...);
----
== DESCRIPTION
These functions are used to post a message to system or application logs.
The first five forms all post a message at the severity indicated by the function name.
The _msgid_ should be a short message identifier that should indicate the message in question.
A `NULL` value for _msgid_ canbe used as well.
Message identifiers can be used to assist in filtering logs.
These should uniquely identify the nature of the problem, whe possible, to assist in trouble-shooting.
They should also be short.
Eight characters or less is ideal, and more than sixteen is strongly discouraged.
The message is formatting as if by `sprintf`, using `msg` as the format, and remaining arguments as arguments to the format.
The final function, `nng_log_auth`, is used for posting authentication related messages which might be treated specially, such as be storing them in a separate secured log file.
It takes the severity as a level in _level_.
The severity can be one of the following values:
* `NNG_LOG_ERR`
* `NNG_LOG_WARN`
* `NNG_LOG_NOTICE`
* `NNG_LOG_INFO`
* `NNG_LOG_DEBUG`
The message itself is handled according to the logging facility set up with xref:nng_mg_set_logger.3.adoc[`nng_log_set_logger`].
Message delivery is best effort, and messages may be suppressed based on the priority set with xref:nng_log_set_level.3.adoc[`nng_log_set_level`].
Note that in order to get log messages, a suitable logger must be set using `nng_log_set_logger`.
The default logger, `nng_null_logger` simply discards logged content.
== SEE ALSO
xref:nng_log_set_facility.3.adoc[nng_log_set_facility(3)],
xref:nng_log_set_level.3.adoc[nng_log_set_level(3)],
xref:nng_log_set_logger.3.adoc[nng_log_set_logger(3)]

View file

@ -0,0 +1,42 @@
= nng_log_get_level(3)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_log_get_level - get minimum level for logging messagse
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
typedef enum nng_log_level {
NNG_LOG_NONE = 0, // used for filters only, NNG suppresses these
NNG_LOG_ERR = 3,
NNG_LOG_WARN = 4,
NNG_LOG_NOTICE = 5,
NNG_LOG_INFO = 6,
NNG_LOG_DEBUG = 7
} nng_log_level;
nng_log_level nng_log_set_level(void);
----
== DESCRIPTION
The `nng_log_get_level` function is used to get the minimum severity to _level_ for processing log messages.
The intended use case is to avoid expensive operations used solely to provide debugging information in logs,
if the logged content would merely be discarded.
== SEE ALSO
xref:nng_log_set_facility.3.adoc[nng_log_set_facility(3)],
xref:nng_log_set_level.3.adoc[nng_log_set_level(3)]

View file

@ -0,0 +1,47 @@
= nng_log_set_facility(3)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_log_set_facility - set facility used for log messages
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
typedef enum nng_log_facility {
NNG_LOG_USER = 1,
NNG_LOG_DAEMON = 3,
NNG_LOG_AUTH = 10,
NNG_LOG_LOCAL0 = 16,
NNG_LOG_LOCAL1 = 17,
NNG_LOG_LOCAL2 = 18,
NNG_LOG_LOCAL3 = 19,
NNG_LOG_LOCAL4 = 20,
NNG_LOG_LOCAL5 = 21,
NNG_LOG_LOCAL6 = 22,
NNG_LOG_LOCAL7 = 23,
} nng_log_facility;
void nng_log_set_facility(nng_log_facility facility);
----
== DESCRIPTION
The `nng_log_set_facility` is used to set the _facility_ of the application posting logs.
This is used to assist with directing log content when handled by services such as `syslog`.
Note that while the log levels used here overlap with common levels used by the syslog facility on POSIX systems, applications should not rely on this.
== SEE ALSO
xref:nng_log_set_level.3.adoc[nng_log_set_level(3)]

View file

@ -0,0 +1,43 @@
= nng_log_set_level(3)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_log_set_level - set minimum level for logging messagse
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
typedef enum nng_log_level {
NNG_LOG_NONE = 0, // used for filters only, NNG suppresses these
NNG_LOG_ERR = 3,
NNG_LOG_WARN = 4,
NNG_LOG_NOTICE = 5,
NNG_LOG_INFO = 6,
NNG_LOG_DEBUG = 7
} nng_log_level;
void nng_log_set_level(nng_log_level level);
----
== DESCRIPTION
The `nng_log_set_level` function is used to set the minimum severity to _level_ for processing log messages.
Any messages with a less severe rating are not processed and simply are discarded.
Use `NNG_LOG_NONE` to suppress all log messages.
Use `NNG_LOG_DEBUG` to receive all log messages.
== SEE ALSO
xref:nng_log_get_level.3.adoc[nng_log_set_level(3)]
xref:nng_log_set_facility.3.adoc[nng_log_set_facility(3)]

View file

@ -0,0 +1,53 @@
= nng_log_set_logger(3)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_log_set_logger - set logging handler
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
typedef void (*nng_logger)(nng_log_level level, nng_log_facility facility,
const char *msgid, const char *msg);
void nng_null_logger(nng_log_level, nng_log_facility, const char *, const char *);
void nng_stderr_logger(nng_log_level, nng_log_facility, const char *, const char *);
void nng_system_logger(nng_log_level, nng_log_facility, const char *, const char *);
void nng_log_set_logger(nng_logger logger);
----
== DESCRIPTION
The `nng_log_set_logger` is used to set the base logging function to _logger_.
The _logger_ may be a user defined function to process log messages.
Only a single logger may be registered at a time.
If needed, the logger should make copies of either _msgid_ or _msg_, as those may not be valid once the logger function returns.
The `nng_null_logger` function is an implementation of `nng_logger` that simply discards the content.
This is the default logger, so logging is disabled by default.
The `nng_stderr_logger` function is an implementation that logs messages to the standard error stream.
It will attempt to colorize messages by the severity, if the standard error is a terminal device.
This can be supressed by setting either the `NO_COLOR` or `NNG_LOG_NO_COLOR` environment variables.
The `nng_system_logger` attempts to use an appropriate system facility to log messages.
For POSIX systems, this means using `syslog` to process the messages.
For other the `nng_stderr_log` may be used as a fallback.
== SEE ALSO
xref:nng_log_set_facility.3.adoc[nng_log_set_facility(3)],
xref:nng_log_set_level.3.adoc[nng_log_set_level(3)],
xref:nng_log.3.adoc[nng_log(3)]

View file

@ -1,6 +1,6 @@
= nng_options(5) = nng_options(5)
// //
// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// Copyright 2019 Devolutions <info@devolutions.net> // Copyright 2019 Devolutions <info@devolutions.net>
// //
@ -39,6 +39,10 @@ nng_options - socket, dialer, listener, and pipe options
#define NNG_OPT_RECVMAXSZ "recv-size-max" #define NNG_OPT_RECVMAXSZ "recv-size-max"
#define NNG_OPT_RECONNMINT "reconnect-time-min" #define NNG_OPT_RECONNMINT "reconnect-time-min"
#define NNG_OPT_RECONNMAXT "reconnect-time-max" #define NNG_OPT_RECONNMAXT "reconnect-time-max"
#define NNG_OPT_PEER_GID "ipc:peer-gid"
#define NNG_OPT_PEER_PID "ipc:peer-pid"
#define NNG_OPT_PEER_UID "ipc:peer-uid"
#define NNG_OPT_PEER_ZONEID "ipc:peer-zoneid"
---- ----
== DESCRIPTION == DESCRIPTION
@ -47,21 +51,21 @@ This page documents the various standard options that can be set or
retrieved on objects. retrieved on objects.
Sockets (xref:nng_socket.5.adoc[`nng_socket`] objects) use the functions Sockets (xref:nng_socket.5.adoc[`nng_socket`] objects) use the functions
xref:nng_getopt.3.adoc[`nng_getopt()`] xref:nng_socket_get.3.adoc[`nng_socket_get()`]
and xref:nng_setopt.3.adoc[`nng_setopt()`] to set and retrieve option values. and xref:nng_socket_set.3.adoc[`nng_socket_set()`] to set and retrieve option values.
Dialers (xref:nng_dialer.5.adoc[`nng_dialer`] objects) use the functions Dialers (xref:nng_dialer.5.adoc[`nng_dialer`] objects) use the functions
xref:nng_dialer_getopt.3.adoc[`nng_dialer_getopt()`] and xref:nng_dialer_get.3.adoc[`nng_dialer_get()`] and
xref:nng_dialer_setopt.3.adoc[`nng_dialer_setopt()`] to set and retrieve option xref:nng_dialer_set.3.adoc[`nng_dialer_set()`] to set and retrieve option
values. values.
Listeners (xref:nng_listener.5.adoc[`nng_listener`] objects) use the functions Listeners (xref:nng_listener.5.adoc[`nng_listener`] objects) use the functions
xref:nng_listener_getopt.3.adoc[`nng_listener_getopt()`] xref:nng_listener_get.3.adoc[`nng_listener_get()`]
and xref:nng_listener_setopt.3.adoc[`nng_listener_setopt()`] to set and and xref:nng_listener_set.3.adoc[`nng_listener_set()`] to set and
retrieve option values. retrieve option values.
Pipes (xref:nng_pipe.5.adoc[`nng_pipe`] objects) can only retrieve option values using Pipes (xref:nng_pipe.5.adoc[`nng_pipe`] objects) can only retrieve option values using
the xref:nng_pipe_getopt.3.adoc[`nng_pipe_getopt()`] function. the xref:nng_pipe_get.3.adoc[`nng_pipe_get()`] function.
Other object types may have additional methods to access these options. Other object types may have additional methods to access these options.
@ -282,7 +286,7 @@ return value of `NNG_ETIMEDOUT`.
(((name, socket))) (((name, socket)))
(string) (string)
This the socket name. This the socket name.
By default this is a string corresponding to the value of the socket. By default, this is a string corresponding to the value of the socket.
The string must fit within 64-bytes, including the terminating The string must fit within 64-bytes, including the terminating
`NUL` byte. `NUL` byte.
The value is intended for application use, and is not used for anything The value is intended for application use, and is not used for anything
@ -328,27 +332,59 @@ This read-only option is used to obtain the 16-bit number for the socket's proto
This read-only option is used to obtain the 16-bit number of the This read-only option is used to obtain the 16-bit number of the
peer protocol for the socket. peer protocol for the socket.
[[NNG_OPT_PEER_GID]]
((`NNG_OPT_PEER_GID`))::
(`uint64_t`)
This read-only option provides a connected peer's primary group id, when known.
This is the effective group id of the peer when either the underlying
`listen()` or `connect()` calls were made, and is not forgeable.
This option is generally only available on POSIX systems, only on certain transports.
[[NNG_OPT_PEER_PID]]
((`NNG_OPT_PEER_PID`))::
(`uint64_t`)
This read-only option provides the process id of the connected peer, when known.
This option is only available on certain platforms and transports.
+
NOTE: Applications should not assume that the process ID does not change,
as it may be possible for a process to pass a file descriptor between processes.
However, it is not possible for a nefarious application to forge the identity
of a well-behaved one using this method.
[[NNG_OPT_PEER_UID]]
((`NNG_OPT_PEER_UID`))::
(`uint64_t`)
This read-only option provides a connected peer's user id.
This is the effective user id of the peer when either the underlying
`listen()` or `connect()` calls were made, and cannot be forged.
This option is generally only available on POSIX systems, on certain transports.
[[NNG_OPT_PEER_ZONEID]]
((`NNG_OPT_PEER_ZONEID`))::
(`uint64_t`)
This read-only option provides a connected peer's the zone id.
Zones (and this option) are only supported on Solaris and illumos systems, on select transports.
[[NNG_OPT_PEERNAME]]
((`NNG_OPT_PEERNAME`))::
(string)
This read-only option is used to obtain the name of the peer protocol for the socket.
[[NNG_OPT_PROTONAME]] [[NNG_OPT_PROTONAME]]
((`NNG_OPT_PROTONAME`)):: ((`NNG_OPT_PROTONAME`))::
(string) (string)
This read-only option is used to obtain the name of the socket's protocol. This read-only option is used to obtain the name of the socket's protocol.
[[NNG_OPT_PEERNAME]]
((`NNG_OPT_PEERNAME`))::
(string)
This read-only option is used to obtain the name of the peer protocol for
the socket.
== SEE ALSO == SEE ALSO
[.text-left] [.text-left]
xref:nng_dialer_getopt.3.adoc[nng_dialer_getopt(3)], xref:nng_dialer_get.3.adoc[nng_dialer_get(3)],
xref:nng_dialer_setopt.3.adoc[nng_dialer_setopt(3)], xref:nng_dialer_set.3.adoc[nng_dialer_set(3)],
xref:nng_getopt.3.adoc[nng_getopt(3)], xref:nng_listener_get.3.adoc[nng_listener_get(3)],
xref:nng_listener_getopt.3.adoc[nng_listener_getopt(3)], xref:nng_listener_set.3.adoc[nng_listener_set(3)],
xref:nng_listener_setopt.3.adoc[nng_listener_setopt(3)], xref:nng_pipe_get.3.adoc[nng_pipe_get(3)],
xref:nng_pipe_getopt.3.adoc[nng_pipe_getopt(3)], xref:nng_socket_get.3.adoc[nng_socket_get(3)],
xref:nng_setopt.3.adoc[nng_setopt(3)], xref:nng_socket_set.3.adoc[nng_socket_set(3)],
xref:nng_ipc_options.5.adoc[nng_ipc_options(5)], xref:nng_ipc_options.5.adoc[nng_ipc_options(5)],
xref:nng_tcp_options.5.adoc[nng_tcp_options(5)], xref:nng_tcp_options.5.adoc[nng_tcp_options(5)],
xref:nng_tls_options.5.adoc[nng_tls_options(5)], xref:nng_tls_options.5.adoc[nng_tls_options(5)],

View file

@ -60,6 +60,10 @@ from the socket.
The underlying transport may be closed at this point, and it is not The underlying transport may be closed at this point, and it is not
possible communicate using this pipe. possible communicate using this pipe.
WARNING: The callback _cb_ function must *not* attempt to perform any
accesses to the socket, as it is called with a lock on the socket held!
Doing so would thus result in a deadlock.
TIP: The callback _cb_ may close a pipe for any reason by simply closing TIP: The callback _cb_ may close a pipe for any reason by simply closing
it using xref:nng_pipe_close.3.adoc[`nng_pipe_close()`]. it using xref:nng_pipe_close.3.adoc[`nng_pipe_close()`].
This might be done before the pipe is added to the socket (during This might be done before the pipe is added to the socket (during

View file

@ -1,6 +1,6 @@
= nng_recvmsg(3) = nng_recvmsg(3)
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -11,7 +11,7 @@
== NAME == NAME
nng_recvmsg - recv message nng_recvmsg - receive a message
== SYNOPSIS == SYNOPSIS
@ -67,4 +67,5 @@ xref:nng_msg_free.3.adoc[nng_msg_free(3)],
xref:nng_recv.3.adoc[nng_recv(3)], xref:nng_recv.3.adoc[nng_recv(3)],
xref:nng_sendmsg.3.adoc[nng_sendmsg(3)], xref:nng_sendmsg.3.adoc[nng_sendmsg(3)],
xref:nng_strerror.3.adoc[nng_strerror(3)], xref:nng_strerror.3.adoc[nng_strerror(3)],
xref:nng_socket.5.adoc[nng_socket(5)],
xref:nng.7.adoc[nng(7)] xref:nng.7.adoc[nng(7)]

View file

@ -30,7 +30,7 @@ The request is resent if no reply arrives,
until a reply is received or the request times out. until a reply is received or the request times out.
TIP: This protocol is useful in setting up RPC-like services. TIP: This protocol is useful in setting up RPC-like services.
It is also reliable, in that a the requester will keep retrying until It is also reliable, in that a requester will keep retrying until
a reply is received. a reply is received.
The _rep_ protocol is the replier side, and the The _rep_ protocol is the replier side, and the
@ -58,7 +58,7 @@ This protocol supports the creation of xref:nng_ctx.5.adoc[contexts] for concurr
use cases using xref:nng_ctx_open.3.adoc[`nng_ctx_open()`]. use cases using xref:nng_ctx_open.3.adoc[`nng_ctx_open()`].
Each context may have at most one outstanding request, and operates Each context may have at most one outstanding request, and operates
independently from the others. independently of the others.
The restrictions for order of operations with sockets apply equally The restrictions for order of operations with sockets apply equally
well for contexts, except that each context will be treated as if it were well for contexts, except that each context will be treated as if it were
a separate socket. a separate socket.

View file

@ -1,6 +1,6 @@
= nng_req(7) = nng_req(7)
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This document is supplied under the terms of the MIT License, a // This document is supplied under the terms of the MIT License, a
@ -101,9 +101,26 @@ The following protocol-specific option is available.
When a new request is started, a timer of this duration is also started. When a new request is started, a timer of this duration is also started.
If no reply is received before this timer expires, then the request will If no reply is received before this timer expires, then the request will
be resent. be resent.
(Requests are also automatically resent if the peer to whom +
the original request was sent disconnects, or if a peer becomes available (Requests are also automatically resent if the peer to whom
while the requester is waiting for an available peer.) the original request was sent disconnects, or if a peer becomes available
while the requester is waiting for an available peer.)
+
Resending may be deferred up to the value of the `NNG_OPT_RESENDTICK` parameter.
((`NNG_OPT_REQ_RESENDTICK`))::
(xref:nng_duration.5.adoc[`nng_duration`])
This is the granularity of the clock that is used to check for resending.
The default is a second. Setting this to a higher rate will allow for
more timely resending to occur, but may incur significant additional
overhead when the socket has many outstanding requests (contexts).
+
When there are no requests outstanding that have a resend set, then
the clock does not tick at all.
+
This option is shared for all contexts on a socket, and is only available for the socket itself.
=== Protocol Headers === Protocol Headers

74
external/nng/docs/man/nng_socket.7.adoc vendored Normal file
View file

@ -0,0 +1,74 @@
= nng_socket(7)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_socket - BSD Socket transport (experimental)
== DESCRIPTION
(((BSD Socket)))(((transport, _socket_)))
The ((_socket_ transport)) supports communication between
peers across arbitrary BSD sockets, such as those that are
created with xref:nng_socket_pair.3supp.adoc[`nng_socket_pair()`].
This transport only supports xref:nng_listener.5.adoc[listeners], using xref:nng_listener_create.3.adoc[`nng_listener_create()`].
NOTE: Attempts to create xref:nng_dialer.5.adoc[dialers] using this transport will result in `NNG_ENOTSUP`.
The socket file descriptor is passed to the listener using the `NNG_OPT_SOCKET_FD` option (as an integer).
Setting this option will cause the listener to create a xref:nng_pipe.5.adoc[pipe] associated backed by the file descriptor.
The protocol between peers using this transport is compatible with the protocol used for the
xref:nng_tcp.7.adoc[TCP] transport, but this is an implementation detail and subject to change without notice.
NOTE: This transport is *experimental*, and at present is only supported on POSIX platforms.
=== Registration
No special action is necessary to register this transport.
=== URI Format
(((URI, `socket://`)))
This transport uses the URL `socket://`, without further qualification.
=== Socket Address
The socket address will be of family `NNG_AF_UNSPEC`.
There are no further socket details available.
=== Transport Options
The following transport option is available:
((`NNG_OPT_SOCKET_FD`))::
(int) This is a write-only option, that may be set multiple times on a listener.
Each time this is set, the listener will create a xref:nng_pipe.5.adoc[pipe] backed by the given file
descriptor passed as an argument.
Additionally, the following options may be supported on pipes when the platform supports them:
* xref:nng_options.5.adoc#NNG_OPT_PEER_GID[`NNG_OPT_PEER_GID`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_PID[`NNG_OPT_PEER_PID`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_UID[`NNG_OPT_PEER_UID`]
* xref:nng_options.5.adoc#NNG_OPT_PEER_ZONEID[`NNG_OPT_PEER_ZONEID`]
== SEE ALSO
[.text-left]
xref:nng_socket_pair.3supp.adoc[nng_socket_pair(3)],
xref:nng_dialer.5.adoc[nng_dialer(5)],
xref:nng_listener.5.adoc[nng_listener(5)],
xref:nng_options.5.adoc[nng_options(5)],
xref:nng_pipe.5.adoc[nng_pipe(5)],
xref:nng_sockaddr.5.adoc[nng_sockaddr(5)],
xref:nng.7.adoc[nng(7)]

View file

@ -93,8 +93,8 @@ The value will be stored at _ivalp_.
`nng_socket_get_ms()`:: `nng_socket_get_ms()`::
This function is used to retrieve time xref:nng_duration.5.adoc[durations] This function is used to retrieve time xref:nng_duration.5.adoc[durations]
(such as timeouts), stored in _durp_ as a number of milliseconds. (such as timeouts), stored in _durp_ as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_socket_get_ptr()`:: `nng_socket_get_ptr()`::
This function is used to retrieve a pointer, _ptr_, to structured data. This function is used to retrieve a pointer, _ptr_, to structured data.

View file

@ -0,0 +1,53 @@
= nng_socket_pair(3supp)
//
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_socket_pair - create a connected pair of BSD sockets
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
int nng_socket_pair(int fds[2]);
----
== DESCRIPTION
The `nng_socket_pair()` function creates a pair of connected BSD sockets.
These sockets, which are returned in the _fds_ array, are suitable for
use with the xref:nng_socket.7.adoc[_socket_] transport.
On POSIX platforms, this is a thin wrapper around the standard `socketpair()` function,
using the `AF_UNIX` family and the `SOCK_STREAM` socket type.
NOTE: At present only POSIX platforms implementing `socketpair()` are supported with this function.
TIP: This function may be useful for creating a shared connection between a parent process and
a child process on UNIX platforms, without requiring the processes use a shared filesystem or TCP connection.
== RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
== ERRORS
[horizontal]
`NNG_ENOMEM`:: Insufficient memory exists.
`NNG_ENOTSUP`:: This platform does not support socket pairs.
== SEE ALSO
[.text-left]
xref:nng_socket.7.adoc[nng_socket(7)],
xref:nng.7.adoc[nng(7)]

View file

@ -0,0 +1,52 @@
= nng_str_sockaddr(3)
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This document is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
== NAME
nng_str_sockaddr - get string representation of socket address
== SYNOPSIS
[source, c]
----
#include <nng/nng.h>
#define NNG_MAXADDRSTRLEN (NNG_MAXADDRLEN+16)
const char *nng_str_sockaddr(const nng_sockaddr *sa, char *buf, size_t bufsz)
----
== DESCRIPTION
The `nng_str_sockaddr()` is used to provide a displayable representation
for the socket address _sa_.
The content will be stored the location provided by _buf_, and will be
formatted to fit within _bufsz_ bytes, truncating if necessary.
As long as _bufsz_ is greater than zero, the result will be properly
zero-terminated in the usual fashion.
The `NNG_MAXADDRSTRLEN` can be used to provide a buffer large enough to hold most socket addresses.
It is possible for applications to use very much larger socket addresses (using very long paths
for IPC or inproc), but such addresses are not generally compatible with other implementations,
and will be truncated here.
== RETURN VALUES
This function returns the _buf_ argument.
== ERRORS
None.
== SEE ALSO
[.text-left]
xref:nng_sockaddr.5.adoc[nng_sockaddr(5)]

View file

@ -88,8 +88,8 @@ This function is for options which take an integer (`int`).
This function is used to retrieve time This function is used to retrieve time
xref:nng_duration.5.adoc[durations] xref:nng_duration.5.adoc[durations]
(such as timeouts), stored as a number of milliseconds. (such as timeouts), stored as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_stream_dialer_get_ptr()`:: `nng_stream_dialer_get_ptr()`::
This function is used to retrieve a pointer to structured data. This function is used to retrieve a pointer to structured data.

View file

@ -88,8 +88,8 @@ This function is for options which take an integer (`int`).
This function is used to retrieve time This function is used to retrieve time
xref:nng_duration.5.adoc[durations] xref:nng_duration.5.adoc[durations]
(such as timeouts), stored as a number of milliseconds. (such as timeouts), stored as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_stream_get_ptr()`:: `nng_stream_get_ptr()`::
This function is used to retrieve a pointer to structured data. This function is used to retrieve a pointer to structured data.

View file

@ -89,8 +89,8 @@ This function is for options which take an integer (`int`).
This function is used to retrieve time This function is used to retrieve time
xref:nng_duration.5.adoc[durations] xref:nng_duration.5.adoc[durations]
(such as timeouts), stored as a number of milliseconds. (such as timeouts), stored as a number of milliseconds.
(The special value ((`NNG_DUR_INFINITE`)) means an infinite amount of time, and (The special value ((`NNG_DURATION_INFINITE`)) means an infinite amount of time, and
the special value ((`NNG_DUR_DEFAULT`)) means a context-specific default.) the special value ((`NNG_DURATION_DEFAULT`)) means a context-specific default.)
`nng_stream_listener_get_ptr()`:: `nng_stream_listener_get_ptr()`::
This function is used to retrieve a pointer to structured data. This function is used to retrieve a pointer to structured data.

View file

@ -19,7 +19,7 @@ nng_thread_set_name - set thread name
#include <nng/nng.h> #include <nng/nng.h>
#include <nng/supplemental/util/platform.h> #include <nng/supplemental/util/platform.h>
void nng_set_thread_name(nng_thread *thread, const char *name); void nng_thread_set_name(nng_thread *thread, const char *name);
---- ----
== DESCRIPTION == DESCRIPTION

View file

@ -127,6 +127,8 @@ Note that setting these must be done before the transport is started.
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_CERT_KEY_FILE[`NNG_OPT_TLS_CERT_KEY_FILE`] * xref:nng_tls_options.5.adoc#NNG_OPT_TLS_CERT_KEY_FILE[`NNG_OPT_TLS_CERT_KEY_FILE`]
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_CONFIG[`NNG_OPT_TLS_CONFIG`] * xref:nng_tls_options.5.adoc#NNG_OPT_TLS_CONFIG[`NNG_OPT_TLS_CONFIG`]
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_VERIFIED[`NNG_OPT_TLS_VERIFIED_`] * xref:nng_tls_options.5.adoc#NNG_OPT_TLS_VERIFIED[`NNG_OPT_TLS_VERIFIED_`]
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_PEER_CN[`NNG_OPT_TLS_PEER_CN`]
* xref:nng_tls_options.5.adoc#NNG_OPT_TLS_PEER_ALT_NAMES[`NNG_OPT_TLS_PEER_ALT_NAMES`]
* xref:nng_options.5.adoc#NNG_OPT_URL[`NNG_OPT_URL`] * xref:nng_options.5.adoc#NNG_OPT_URL[`NNG_OPT_URL`]
== SEE ALSO == SEE ALSO

View file

@ -26,6 +26,8 @@ nng_tls_options - TLS-specific options
#define NNG_OPT_TLS_CONFIG "tls-config" #define NNG_OPT_TLS_CONFIG "tls-config"
#define NNG_OPT_TLS_SERVER_NAME "tls-server-name" #define NNG_OPT_TLS_SERVER_NAME "tls-server-name"
#define NNG_OPT_TLS_VERIFIED "tls-verified" #define NNG_OPT_TLS_VERIFIED "tls-verified"
#define NNG_OPT_TLS_PEER_CN "tls-peer-cn"
#define NNG_OPT_TLS_PEER_ALT_NAMES "tls-peer-alt-names"
---- ----
== DESCRIPTION == DESCRIPTION
@ -91,6 +93,16 @@ This read-only option indicates whether the remote peer has been properly verifi
authentication. authentication.
May return incorrect results if peer authentication is disabled. May return incorrect results if peer authentication is disabled.
[[NNG_OPT_TLS_PEER_CN]]((`NNG_OPT_TLS_PEER_CN`))::
(string)
This read-only option returns the common name of the peer certificate.
May return incorrect results if peer authentication is disabled.
[[NNG_OPT_TLS_PEER_ALT_NAMES]]((`NNG_OPT_TLS_PEER_ALT_NAMES`))::
(string)
This read-only option returns string list with the subject alternative names of the
peer certificate. May return incorrect results if peer authentication is disabled.
=== Inherited Options === Inherited Options
Generally, the following option values are also available for TLS objects, Generally, the following option values are also available for TLS objects,

View file

@ -199,6 +199,15 @@ more details.
authentication. authentication.
May return incorrect results if peer authentication is disabled. May return incorrect results if peer authentication is disabled.
`NNG_OPT_TLS_PEER_CN`::
(string) This read-only option returns the common name of the peer certificate.
May return incorrect results if peer authentication is disabled.
`NNG_OPT_TLS_PEER_ALT_NAMES`::
(string list) returns string list with the subject alternative names of the
peer certificate. May return incorrect results if peer authentication
is disabled.
// We should also look at a hook mechanism for listeners. Probably this could // We should also look at a hook mechanism for listeners. Probably this could
// look like NNG_OPT_WS_LISTEN_HOOK_FUNC which would take a function pointer // look like NNG_OPT_WS_LISTEN_HOOK_FUNC which would take a function pointer
// along the lines of int hook(void *, char *req_headers, char **res_headers), // along the lines of int hook(void *, char *req_headers, char **res_headers),

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
# Copyright 2017 Garrett D'Amore <garrett@damore.org> # Copyright 2017 Garrett D'Amore <garrett@damore.org>
# Copyright 2017 Capitar IT Group BV <info@capitar.com> # Copyright 2017 Capitar IT Group BV <info@capitar.com>

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
# Copyright 2017 Garrett D'Amore <garrett@damore.org> # Copyright 2017 Garrett D'Amore <garrett@damore.org>
# Copyright 2017 Capitar IT Group BV <info@capitar.com> # Copyright 2017 Capitar IT Group BV <info@capitar.com>

View file

@ -1,4 +1,4 @@
#!/bin/sh #!/usr/bin/env bash
# #
# Copyright 2016 Garrett D'Amore <garrett@damore.org> # Copyright 2016 Garrett D'Amore <garrett@damore.org>
# #

View file

@ -1,11 +1,44 @@
module go.nanomsg.org/nng/pubrefman module go.nanomsg.org/nng/pubrefman
go 1.14 go 1.18
require ( require (
github.com/bytesparadise/libasciidoc v0.3.1-0.20200802124845-5dcda3220c31 github.com/bytesparadise/libasciidoc v0.8.0
github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-billy/v5 v5.5.0
github.com/go-git/go-git/v5 v5.1.0 github.com/go-git/go-git/v5 v5.11.0
github.com/google/uuid v1.1.1 github.com/google/uuid v1.3.1
github.com/spf13/jwalterweatherman v1.0.0 github.com/spf13/jwalterweatherman v1.1.0
)
require (
dario.cat/mergo v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/alecthomas/chroma/v2 v2.9.1 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/mna/pigeon v1.1.0 // indirect
github.com/onsi/ginkgo/v2 v2.12.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
) )

View file

@ -1,277 +1,164 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/DataDog/gostackparse v0.5.0 h1:jb72P6GFHPHz2W0onsN51cS3FkaMDcjb0QzgxxA4gDk=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/alecthomas/chroma v0.7.1 h1:G1i02OhUbRi2nJxcNkwJaY/J1gHXj9tt72qN6ZouLFQ= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/alecthomas/chroma v0.7.1/go.mod h1:gHw09mkX1Qp80JlYbmN9L3+4R5o6DJJ3GRShh+AICNc= github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo= github.com/alecthomas/chroma/v2 v2.9.1 h1:0O3lTQh9FxazJ4BYE/MOi/vDGuHn7B+6Bu902N2UZvU=
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0= github.com/alecthomas/chroma/v2 v2.9.1/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bytesparadise/libasciidoc v0.8.0 h1:iWAlYR7gm4Aes3NSvuGQyzRavatQpUBAJZyU9uMmwm0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bytesparadise/libasciidoc v0.8.0/go.mod h1:Q2ZeBQ1fko5+NTUTs8rGu9gjTtbVaD6Qxg37GOPYdN4=
github.com/bytesparadise/libasciidoc v0.3.1-0.20200802124845-5dcda3220c31 h1:Rf+HhYMHL9wl4nKv8Jgy5ss8Pksii1TWCgZIP6Cr1qE= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/bytesparadise/libasciidoc v0.3.1-0.20200802124845-5dcda3220c31/go.mod h1:kWkgc6KJVCDUT2QlPbYIlYspvy0+3vuWriL0kV2NDig= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/felixge/fgtrace v0.1.0 h1:cuMLI5NoBg/9IxIVmJzsxA3Aoz5eIKRca6WE1U2C1zc=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8 h1:gpptm606MZYGaMHMsB4Srmb6EbW/IVHnt04rcMXnkBQ=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/google/pprof v0.0.0-20230912144702-c363fe2c2ed8/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mna/pigeon v1.1.0 h1:EjlvVbkGnNGemf8OrjeJX0nH8orujY/HkJgzJtd7kxc=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mna/pigeon v1.1.0/go.mod h1:rkFeDZ0gc+YbnrXPw0q2RlI0QRuKBBPu67fgYIyGRNg=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/onsi/ginkgo/v2 v2.12.0/go.mod h1:ZNEzXISYlqpb8S36iN71ifqLi3vVD1rVJGvWRCJOUpQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mna/pigeon v1.0.1-0.20200224192238-18953b277063 h1:V7s6vhIrNeOqocziAmRoVJh6gnPPx83ovlpT7Hf5shI=
github.com/mna/pigeon v1.0.1-0.20200224192238-18953b277063/go.mod h1:rkFeDZ0gc+YbnrXPw0q2RlI0QRuKBBPu67fgYIyGRNg=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5 h1:8Q0qkMVC/MmWkpIdlvZgcv2o2jrlF6zqVOh7W5YHdMA=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sozorogami/gover v0.0.0-20171022184752-b58185e213c5 h1:TAPeDBsd52dRWoWzf5trgBzxzMYHTYjYI+4xNyCdoCU=
github.com/sozorogami/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:nHNlDYIQZn44RvqH0kCpl/dMMVWXkav0QIgzGxV1Ab4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190830223141-573d9926052a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190830223141-573d9926052a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6 h1:nULzSsKgihxFGLnQFv2T7lE5vIhOtg8ZPpJHapEt7o0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -89,7 +89,7 @@ type Global struct {
SrcFs billy.Filesystem SrcFs billy.Filesystem
DstFs billy.Filesystem DstFs billy.Filesystem
DstDir string DstDir string
LaConfig configuration.Configuration LaConfig *configuration.Configuration
Sections map[string]*Section Sections map[string]*Section
Pages map[string]*Page Pages map[string]*Page
Repo *git.Repository Repo *git.Repository
@ -111,14 +111,13 @@ func (g *Global) Init() {
g.SrcFs = memfs.New() g.SrcFs = memfs.New()
g.DstFs = memfs.New() g.DstFs = memfs.New()
g.DstDir = path.Join("man", g.Config.Version) g.DstDir = path.Join("man", g.Config.Version)
g.LaConfig = configuration.Configuration{ g.LaConfig = configuration.NewConfiguration(
AttributeOverrides: map[string]string{ configuration.WithAttributes(map[string]interface{}{
"nofooter": "yes", "nofooter": "yes",
"icons": "font", "icons": "font",
"linkcss": "yes", "linkcss": "yes",
"source-highlighter": "pygments", "source-highlighter": "pygments",
}, }))
}
thresh := jww.LevelInfo thresh := jww.LevelInfo
if g.Config.Quiet { if g.Config.Quiet {
thresh = jww.LevelError thresh = jww.LevelError
@ -232,6 +231,7 @@ func (g *Global) ProcessManPage(page os.FileInfo) {
_, _ = fmt.Fprintf(result, "---\n") _, _ = fmt.Fprintf(result, "---\n")
_, _ = fmt.Fprintf(result, "version: %s\n", g.Config.Version) _, _ = fmt.Fprintf(result, "version: %s\n", g.Config.Version)
_, _ = fmt.Fprintf(result, "layout: %s\n", "manpage_v2") _, _ = fmt.Fprintf(result, "layout: %s\n", "manpage_v2")
_, _ = fmt.Fprintf(result, "title: %s\n", fmt.Sprintf("%s(%s)", name, sect))
_, _ = fmt.Fprintf(result, "---\n") _, _ = fmt.Fprintf(result, "---\n")
_, _ = fmt.Fprintf(result, "<h1>%s(%s)</h1>\n", name, sect) _, _ = fmt.Fprintf(result, "<h1>%s(%s)</h1>\n", name, sect)
result.WriteString(html.String()) result.WriteString(html.String())
@ -427,7 +427,7 @@ func (g *Global) Push() {
}) })
g.CheckError(err, "getting commit log") g.CheckError(err, "getting commit log")
commit, err := ci.Next() commit, err := ci.Next()
g.CheckError(err,"getting single commit") g.CheckError(err, "getting single commit")
if commit != nil { if commit != nil {
g.Print(commit.String()) g.Print(commit.String())
if fs, _ := commit.Stats(); fs != nil { if fs, _ := commit.Stats(); fs != nil {

510
external/nng/etc/pubrefman/pubrefman2.go vendored Normal file
View file

@ -0,0 +1,510 @@
// Copyright 2024 Staysail Systems, Inc.
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
// This tool uses a local in memory copy of git, and a docker
// installation, to format the man pages. The documentation will be
// pushed up into a branch.
package main
import (
"context"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"sort"
"strings"
"time"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/google/uuid"
jww "github.com/spf13/jwalterweatherman"
)
type Configuration struct {
Version string
Debug bool
Trace bool
Quiet bool
DryRun bool
Author string
Email string
Url string
Message string
}
var Config Configuration
func init() {
flag.StringVar(&Config.Version, "v", "tip", "Version to publish")
flag.BoolVar(&Config.Debug, "d", false, "Enable debugging")
flag.BoolVar(&Config.Trace, "t", false, "Enable tracing")
flag.BoolVar(&Config.Quiet, "q", false, "Run quietly")
flag.BoolVar(&Config.DryRun, "n", false, "Dry run, does not push changes")
flag.StringVar(&Config.Url, "u", "ssh://git@github.com/nanomsg/nng.git", "URL of repo to publish from")
flag.StringVar(&Config.Email, "E", "info@staysail.tech", "Author email for commit")
flag.StringVar(&Config.Author, "A", "Staysail Systems, Inc.", "Author name for commit")
flag.StringVar(&Config.Message, "m", "", "Commit message")
}
func (g *Global) CheckError(err error, prefix string, args ...interface{}) {
if err == nil {
g.Log.TRACE.Printf("%s: ok", fmt.Sprintf(prefix, args...))
return
}
g.Log.FATAL.Fatalf("Error: %s: %v", fmt.Sprintf(prefix, args...), err)
}
func (g *Global) Fatal(format string, args ...interface{}) {
g.Log.FATAL.Fatalf("Error: %s", fmt.Sprintf(format, args...))
}
type Section struct {
Name string
Synopsis string
Description string
Pages []*Page
}
type Page struct {
Name string
Section string
Description string
Content string
}
type Global struct {
Config Configuration
SrcFs billy.Filesystem
DstFs billy.Filesystem
DstDir string
Sections map[string]*Section
Pages map[string]*Page
Repo *git.Repository
Index string
ToC string
Added map[string]bool
WorkTree *git.Worktree
Branch string
OldHash plumbing.Hash
NewHash plumbing.Hash
Log *jww.Notepad
}
func (g *Global) Init() {
g.Config = Config
g.Sections = make(map[string]*Section)
g.Pages = make(map[string]*Page)
g.Added = make(map[string]bool)
g.SrcFs = memfs.New()
g.DstFs = memfs.New()
g.DstDir = path.Join("man", g.Config.Version)
thresh := jww.LevelInfo
if g.Config.Quiet {
thresh = jww.LevelError
}
if g.Config.Debug {
thresh = jww.LevelDebug
}
if g.Config.Trace {
thresh = jww.LevelTrace
}
g.Log = jww.NewNotepad(thresh, thresh, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime)
}
func (g *Global) Destroy() {
}
func (g *Global) Debug(format string, args ...interface{}) {
g.Log.DEBUG.Printf(format, args...)
}
func (g *Global) Print(format string, args ...interface{}) {
g.Log.INFO.Printf(format, args...)
}
func (g *Global) CloneSource() {
tag := g.Config.Version
if tag == "" || tag == "tip" {
tag = "master"
}
ref := plumbing.NewBranchReferenceName(tag)
if strings.HasPrefix(tag, "v") {
ref = plumbing.NewTagReferenceName(tag)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
now := time.Now()
_, err := git.CloneContext(ctx, memory.NewStorage(), g.SrcFs, &git.CloneOptions{
URL: g.Config.Url,
ReferenceName: ref,
})
g.CheckError(err, "clone source")
g.Debug("Cloned source (%s) in %v", tag, time.Since(now))
}
func (g *Global) ClonePages() {
ref := plumbing.NewBranchReferenceName("gh-pages")
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
now := time.Now()
repo, err := git.CloneContext(ctx, memory.NewStorage(), g.DstFs, &git.CloneOptions{
URL: g.Config.Url,
ReferenceName: ref,
RemoteName: "origin",
})
g.CheckError(err, "clone gh-pages")
g.Repo = repo
g.Debug("Cloned pages in %v", time.Since(now))
}
func (g *Global) DockerCmd(source string, output *strings.Builder) *exec.Cmd {
cmd := exec.Command("/usr/local/bin/docker", "run", "-i", "--rm", "asciidoctor/docker-asciidoctor")
cmd.Args = append(cmd.Args, "asciidoctor")
cmd.Args = append(cmd.Args, "-a", "linkcss")
cmd.Args = append(cmd.Args, "-a", "icons=font")
cmd.Args = append(cmd.Args, "-a", "nofooter")
cmd.Args = append(cmd.Args, "-a", "source-highlighter=pygments") // rouge is recommended, but our stylesheet is for pygments
cmd.Args = append(cmd.Args, "-s", "-o", "-", "-") // pipe it
cmd.Stdin = strings.NewReader(source)
cmd.Stdout = output
cmd.Stderr = &strings.Builder{}
return cmd
}
func (g *Global) ProcessManPage(page os.FileInfo) {
source := g.ReadFile(page.Name())
// Let's look for the description
inName := false
desc := ""
name := ""
title := ""
for _, line := range strings.Split(source, "\n") {
line = strings.TrimRight(line, " \t\r")
if line == "" {
continue
}
if strings.HasPrefix(line, "= ") {
title = strings.TrimSpace(line[2:])
continue
}
if line == "== NAME" {
inName = true
continue
}
if inName {
w := strings.SplitN(line, " - ", 2)
if len(w) != 2 || w[1] == "" {
g.Fatal("page %s NAME malformed", page.Name())
}
name = w[0]
desc = w[1]
strings.TrimSpace(name)
strings.TrimSpace(desc)
break
}
}
if desc == "" {
g.Fatal("page %s NAME missing", page.Name())
}
if title == "" {
g.Fatal("page %s title missing", page.Name())
}
html := &strings.Builder{}
w := strings.SplitN(title, "(", 2)
sect := strings.TrimSuffix(w[1], ")")
if len(w) != 2 || name != w[0] || !strings.HasSuffix(w[1], ")") {
g.Fatal("page %s title incorrect (%s)", page.Name(), name)
}
if page.Name() != name+"."+sect+".adoc" {
g.Fatal("page %s(%s) does not match file name %s", name, sect, page.Name())
}
_, _ = fmt.Fprintf(html, "---\n")
_, _ = fmt.Fprintf(html, "version: %s\n", g.Config.Version)
_, _ = fmt.Fprintf(html, "layout: %s\n", "manpage_v2")
_, _ = fmt.Fprintf(html, "title: %s\n", fmt.Sprintf("%s(%s)", name, sect))
_, _ = fmt.Fprintf(html, "---\n")
_, _ = fmt.Fprintf(html, "<h1>%s(%s)</h1>\n", name, sect)
cmd := g.DockerCmd(source, html)
err := cmd.Run()
if err != nil {
g.Fatal("Failed %v: %s", err, cmd.Stderr)
}
g.Pages[page.Name()] = &Page{
Name: name,
Section: sect,
Description: desc,
Content: html.String(),
}
g.Log.TRACE.Printf("HTML for %s:\n%s\n", name, html.String())
}
func (g *Global) ReadFile(name string) string {
f, err := g.SrcFs.Open(path.Join("docs/man", name))
g.CheckError(err, "open file %s", name)
b, err := ioutil.ReadAll(f)
g.CheckError(err, "read file %s", name)
return string(b)
}
func (g *Global) LoadSection(name string) {
section := strings.TrimPrefix(name, "man")
g.Sections[section] = &Section{
Name: section,
Synopsis: g.ReadFile(name + ".sect"),
Description: g.ReadFile(name + ".desc"),
}
}
func (g *Global) ProcessSource() {
pages, err := g.SrcFs.ReadDir("docs/man")
g.CheckError(err, "reading source directory")
count := 0
g.Debug("Total of %d files in man directory", len(pages))
now := time.Now()
for i, page := range pages {
if page.IsDir() {
continue
}
if strings.HasSuffix(page.Name(), ".sect") {
g.LoadSection(strings.TrimSuffix(page.Name(), ".sect"))
}
if !strings.HasSuffix(page.Name(), ".adoc") {
continue
}
g.ProcessManPage(page)
g.Print("Processed %s (%d of %d)", page.Name(), i, len(pages))
count++
}
g.Print("Processed %d pages in %v", count, time.Since(now))
}
func (g *Global) GenerateToC() {
toc := &strings.Builder{}
idx := &strings.Builder{}
for _, page := range g.Pages {
if sect := g.Sections[page.Section]; sect == nil {
g.Fatal("page %s section %s not found", page.Name, page.Section)
} else {
sect.Pages = append(sect.Pages, page)
}
}
var sects []string
for name, sect := range g.Sections {
sects = append(sects, name)
sort.Slice(sect.Pages, func(i, j int) bool { return sect.Pages[i].Name < sect.Pages[j].Name })
}
sort.Strings(sects)
// And also the index page.
// Emit the toc leader part
toc.WriteString("<nav id=\"toc\" class=\"toc2\">\n")
toc.WriteString("<div id=\"toctitle\">Table of Contents</div>\n")
toc.WriteString("<ul class=\"sectlevel1\n\">\n")
idx.WriteString("= NNG Reference Manual\n")
for _, sect := range sects {
s := g.Sections[sect]
_, _ = fmt.Fprintf(toc, "<li>%s</li>\n", s.Synopsis)
_, _ = fmt.Fprintf(toc, "<ul class=\"sectlevel2\">\n")
_, _ = fmt.Fprintf(idx, "\n== Section %s: %s\n\n", s.Name, s.Synopsis)
_, _ = fmt.Fprintln(idx, s.Description)
_, _ = fmt.Fprintln(idx, "\n[cols=\"3,5\"]\n|===")
for _, page := range s.Pages {
_, _ = fmt.Fprintf(toc, "<li><a href=\"%s.%s.html\">%s</a></li>\n",
page.Name, page.Section, page.Name)
_, _ = fmt.Fprintf(idx, "|xref:%s.%s.adoc[%s(%s)]\n", page.Name, page.Section,
page.Name, page.Section)
_, _ = fmt.Fprintf(idx, "|%s\n", page.Description)
}
_, _ = fmt.Fprintf(toc, "</ul>\n")
_, _ = fmt.Fprintln(idx, "|===")
}
_, _ = fmt.Fprintf(toc, "</ul>\n")
_, _ = fmt.Fprintf(toc, "</nav>\n")
index := &strings.Builder{}
_, _ = fmt.Fprintf(index, "---\n")
_, _ = fmt.Fprintf(index, "version: %s\n", g.Config.Version)
_, _ = fmt.Fprintf(index, "layout: %s\n", "manpage_v2")
_, _ = fmt.Fprintf(index, "---\n")
_, _ = fmt.Fprintf(index, "<h1>NNG Reference Manual</h1>\n")
cmd := g.DockerCmd(idx.String(), index)
cmd.Stdout = index
err := cmd.Run()
g.CheckError(err, "formatting index")
g.Index = index.String()
g.ToC = toc.String()
}
func (g *Global) CreateBranch() {
brName := uuid.New().String()
var err error
refName := plumbing.ReferenceName("refs/heads/" + brName)
g.Branch = brName
g.WorkTree, err = g.Repo.Worktree()
g.CheckError(err, "getting worktree")
err = g.WorkTree.Checkout(&git.CheckoutOptions{
Branch: refName,
Create: true,
})
g.CheckError(err, "creating branch")
g.Print("Checked out branch %v", brName)
pr, err := g.Repo.Head()
g.CheckError(err, "getting head hash")
g.OldHash = pr.Hash()
}
func (g *Global) WriteFile(name string, content string) {
full := path.Join(g.DstDir, name)
f, err := g.DstFs.Create(full)
g.CheckError(err, "creating file %s", name)
_, err = f.Write([]byte(content))
g.CheckError(err, "writing file %s", name)
err = f.Close()
g.CheckError(err, "closing file %s", name)
g.Add(name)
}
func (g *Global) Add(name string) {
g.Log.TRACE.Printf("Adding file %s", name)
g.Added[name] = true
}
func (g *Global) Delete(name string) {
g.Debug("Removing file %s", name)
_, err := g.WorkTree.Remove(path.Join(g.DstDir, name))
g.CheckError(err, "removing file %s", name)
}
func (g *Global) Commit() {
if status, err := g.WorkTree.Status(); status == nil {
g.CheckError(err, "obtaining status")
} else if status.IsClean() {
g.Print("No changes to commit.")
return
}
message := g.Config.Message
if message == "" {
message = "Manual page updates for " + g.Config.Version
}
var err error
g.NewHash, err = g.WorkTree.Commit(message, &git.CommitOptions{
Author: &object.Signature{
Email: g.Config.Email,
Name: g.Config.Author,
When: time.Now(),
},
})
g.CheckError(err, "committing branch")
}
func (g *Global) Push() {
if g.NewHash.IsZero() {
g.Print("Nothing to push.")
return
}
ci, err := g.Repo.Log(&git.LogOptions{
From: g.NewHash,
})
g.CheckError(err, "getting commit log")
commit, err := ci.Next()
g.CheckError(err, "getting single commit")
if commit != nil {
g.Print(commit.String())
if fs, _ := commit.Stats(); fs != nil {
g.Debug(fs.String())
}
}
if g.Config.DryRun {
g.Print("Not pushing changes (dry-run mode.)")
} else {
err := g.Repo.Push(&git.PushOptions{
RemoteName: "origin",
})
g.CheckError(err, "pushing changes")
g.Print("Pushed branch %v\n", g.Branch)
}
}
func (g *Global) WriteOutput() {
for _, p := range g.Pages {
fName := fmt.Sprintf("%s.%s.html", p.Name, p.Section)
g.WriteFile(fName, p.Content)
}
g.WriteFile("_toc.html", g.ToC)
g.WriteFile("index.html", g.Index)
_, err := g.WorkTree.Add(g.DstDir)
g.CheckError(err, "adding directory")
files, err := g.DstFs.ReadDir(g.DstDir)
g.CheckError(err, "scanning destination directory")
for _, file := range files {
if file.IsDir() {
continue
}
if g.Added[file.Name()] {
continue
}
g.Delete(file.Name())
}
status, err := g.WorkTree.Status()
g.CheckError(err, "obtaining commit status")
if !status.IsClean() {
g.Debug("No changes.")
} else {
g.Debug(status.String())
}
}
func main() {
g := &Global{}
flag.Parse()
g.Init()
defer g.Destroy()
g.CloneSource()
g.ClonePages()
g.ProcessSource()
g.GenerateToC()
g.CreateBranch()
g.WriteOutput()
g.Commit()
g.Push()
}

View file

@ -1,5 +1,5 @@
// //
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -45,13 +45,22 @@ extern "C" {
#endif // _WIN32 && !NNG_STATIC_LIB #endif // _WIN32 && !NNG_STATIC_LIB
#endif // NNG_DECL #endif // NNG_DECL
#ifndef NNG_DEPRECATED
#if defined(__GNUC__) || defined(__clang__)
#define NNG_DEPRECATED __attribute__((deprecated))
#else
#define NNG_DEPRECATED
#endif
#endif
// NNG Library & API version. // NNG Library & API version.
// We use SemVer, and these versions are about the API, and // We use SemVer, and these versions are about the API, and
// may not necessarily match the ABI versions. // may not necessarily match the ABI versions.
#define NNG_MAJOR_VERSION 1 #define NNG_MAJOR_VERSION 1
#define NNG_MINOR_VERSION 5 #define NNG_MINOR_VERSION 8
#define NNG_PATCH_VERSION 2 #define NNG_PATCH_VERSION 0
#define NNG_RELEASE_SUFFIX "" // if non-empty, this is a pre-release #define NNG_RELEASE_SUFFIX \
"" // if non-empty (i.e. "pre"), this is a pre-release
// Maximum length of a socket address. This includes the terminating NUL. // Maximum length of a socket address. This includes the terminating NUL.
// This limit is built into other implementations, so do not change it. // This limit is built into other implementations, so do not change it.
@ -94,6 +103,11 @@ typedef struct nng_socket_s {
} nng_socket; } nng_socket;
typedef int32_t nng_duration; // in milliseconds typedef int32_t nng_duration; // in milliseconds
// nng_time represents an absolute time since some arbitrary point in the
// past, measured in milliseconds. The values are always positive.
typedef uint64_t nng_time;
typedef struct nng_msg nng_msg; typedef struct nng_msg nng_msg;
typedef struct nng_stat nng_stat; typedef struct nng_stat nng_stat;
typedef struct nng_aio nng_aio; typedef struct nng_aio nng_aio;
@ -146,7 +160,7 @@ struct nng_sockaddr_abstract {
uint8_t sa_name[107]; // 108 linux/windows, without leading NUL uint8_t sa_name[107]; // 108 linux/windows, without leading NUL
}; };
// nng_sockaddr_storage is the the size required to store any nng_sockaddr. // nng_sockaddr_storage is the size required to store any nng_sockaddr.
// This size must not change, and no individual nng_sockaddr type may grow // This size must not change, and no individual nng_sockaddr type may grow
// larger than this without breaking binary compatibility. // larger than this without breaking binary compatibility.
struct nng_sockaddr_storage { struct nng_sockaddr_storage {
@ -186,7 +200,7 @@ enum nng_sockaddr_family {
// Scatter/gather I/O. // Scatter/gather I/O.
typedef struct nng_iov { typedef struct nng_iov {
void * iov_buf; void *iov_buf;
size_t iov_len; size_t iov_len;
} nng_iov; } nng_iov;
@ -236,6 +250,17 @@ NNG_DECL int nng_socket_get_ptr(nng_socket, const char *, void **);
NNG_DECL int nng_socket_get_ms(nng_socket, const char *, nng_duration *); NNG_DECL int nng_socket_get_ms(nng_socket, const char *, nng_duration *);
NNG_DECL int nng_socket_get_addr(nng_socket, const char *, nng_sockaddr *); NNG_DECL int nng_socket_get_addr(nng_socket, const char *, nng_sockaddr *);
// Utility function for getting a printable form of the socket address
// for display in logs, etc. It is not intended to be parsed, and the
// display format may change without notice. Generally you should alow
// at least NNG_MAXADDRSTRLEN if you want to avoid typical truncations.
// It is still possible for very long IPC paths to be truncated, but that
// is an edge case and applications that pass such long paths should
// expect some truncation (but they may pass larger values).
#define NNG_MAXADDRSTRLEN (NNG_MAXADDRLEN + 16) // extra bytes for scheme
NNG_DECL const char *nng_str_sockaddr(
const nng_sockaddr *sa, char *buf, size_t bufsz);
// Arguably the pipe callback functions could be handled as an option, // Arguably the pipe callback functions could be handled as an option,
// but with the need to specify an argument, we find it best to unify // but with the need to specify an argument, we find it best to unify
// this as a separate function to pass in the argument and the callback. // this as a separate function to pass in the argument and the callback.
@ -346,7 +371,7 @@ NNG_DECL int nng_listener_get_ptr(nng_listener, const char *, void **);
NNG_DECL int nng_listener_get_ms(nng_listener, const char *, nng_duration *); NNG_DECL int nng_listener_get_ms(nng_listener, const char *, nng_duration *);
NNG_DECL int nng_listener_get_addr(nng_listener, const char *, nng_sockaddr *); NNG_DECL int nng_listener_get_addr(nng_listener, const char *, nng_sockaddr *);
// nng_strerror returns a human readable string associated with the error // nng_strerror returns a human-readable string associated with the error
// code supplied. // code supplied.
NNG_DECL const char *nng_strerror(int); NNG_DECL const char *nng_strerror(int);
@ -372,7 +397,7 @@ NNG_DECL int nng_recv(nng_socket, void *, size_t *, int);
// nng_sendmsg is like nng_send, but offers up a message structure, which // nng_sendmsg is like nng_send, but offers up a message structure, which
// gives the ability to provide more control over the message, including // gives the ability to provide more control over the message, including
// providing backtrace information. It also can take a message that was // providing backtrace information. It also can take a message that was
// obtain via nn_recvmsg, allowing for zero copy forwarding. // obtained via nn_recvmsg, allowing for zero copy forwarding.
NNG_DECL int nng_sendmsg(nng_socket, nng_msg *, int); NNG_DECL int nng_sendmsg(nng_socket, nng_msg *, int);
// nng_recvmsg is like nng_recv, but is used to obtain a message structure // nng_recvmsg is like nng_recv, but is used to obtain a message structure
@ -385,7 +410,7 @@ NNG_DECL int nng_recvmsg(nng_socket, nng_msg **, int);
// the completion may be executed before the data has actually been delivered, // the completion may be executed before the data has actually been delivered,
// but only when it is accepted for delivery. The supplied AIO must have // but only when it is accepted for delivery. The supplied AIO must have
// been initialized, and have an associated message. The message will be // been initialized, and have an associated message. The message will be
// "owned" by the socket if the operation completes successfully. Otherwise // "owned" by the socket if the operation completes successfully. Otherwise,
// the caller is responsible for freeing it. // the caller is responsible for freeing it.
NNG_DECL void nng_send_aio(nng_socket, nng_aio *); NNG_DECL void nng_send_aio(nng_socket, nng_aio *);
@ -421,10 +446,20 @@ NNG_DECL int nng_ctx_id(nng_ctx);
// uses a local context instead of the socket global context. // uses a local context instead of the socket global context.
NNG_DECL void nng_ctx_recv(nng_ctx, nng_aio *); NNG_DECL void nng_ctx_recv(nng_ctx, nng_aio *);
// nng_ctx_recvmsg allows for receiving a message synchronously using
// a context. It has the same semantics as nng_recvmsg, but operates
// on a context instead of a socket.
NNG_DECL int nng_ctx_recvmsg(nng_ctx, nng_msg **, int);
// nng_ctx_send sends asynchronously. It works like nng_send_aio, but // nng_ctx_send sends asynchronously. It works like nng_send_aio, but
// uses a local context instead of the socket global context. // uses a local context instead of the socket global context.
NNG_DECL void nng_ctx_send(nng_ctx, nng_aio *); NNG_DECL void nng_ctx_send(nng_ctx, nng_aio *);
// nng_ctx_sendmsg is allows for sending a message synchronously using
// a context. It has the same semantics as nng_sendmsg, but operates
// on a context instead of a socket.
NNG_DECL int nng_ctx_sendmsg(nng_ctx, nng_msg *, int);
NNG_DECL int nng_ctx_get(nng_ctx, const char *, void *, size_t *); NNG_DECL int nng_ctx_get(nng_ctx, const char *, void *, size_t *);
NNG_DECL int nng_ctx_get_bool(nng_ctx, const char *, bool *); NNG_DECL int nng_ctx_get_bool(nng_ctx, const char *, bool *);
NNG_DECL int nng_ctx_get_int(nng_ctx, const char *, int *); NNG_DECL int nng_ctx_get_int(nng_ctx, const char *, int *);
@ -497,7 +532,7 @@ NNG_DECL void nng_aio_reap(nng_aio *);
// nng_aio_stop stops any outstanding operation, and waits for the // nng_aio_stop stops any outstanding operation, and waits for the
// AIO to be free, including for the callback to have completed // AIO to be free, including for the callback to have completed
// execution. Therefore the caller must NOT hold any locks that // execution. Therefore, the caller must NOT hold any locks that
// are acquired in the callback, or deadlock will occur. // are acquired in the callback, or deadlock will occur.
NNG_DECL void nng_aio_stop(nng_aio *); NNG_DECL void nng_aio_stop(nng_aio *);
@ -526,6 +561,12 @@ NNG_DECL void nng_aio_abort(nng_aio *, int);
// callback or deadlock may occur. // callback or deadlock may occur.
NNG_DECL void nng_aio_wait(nng_aio *); NNG_DECL void nng_aio_wait(nng_aio *);
// nng_aio_busy returns true if the aio is still busy processing the
// operation, or executing associated completion functions. Note that
// if the completion function schedules a new operation using the aio,
// then this function will continue to return true.
NNG_DECL bool nng_aio_busy(nng_aio *);
// nng_aio_set_msg sets the message structure to use for asynchronous // nng_aio_set_msg sets the message structure to use for asynchronous
// message send operations. // message send operations.
NNG_DECL void nng_aio_set_msg(nng_aio *, nng_msg *); NNG_DECL void nng_aio_set_msg(nng_aio *, nng_msg *);
@ -554,6 +595,11 @@ NNG_DECL void *nng_aio_get_output(nng_aio *, unsigned);
// that any socket specific timeout should be used. // that any socket specific timeout should be used.
NNG_DECL void nng_aio_set_timeout(nng_aio *, nng_duration); NNG_DECL void nng_aio_set_timeout(nng_aio *, nng_duration);
// nng_aio_set_expire is like nng_aio_set_timeout, except it sets an absolute
// expiration time. This is useful when chaining actions on a single aio
// as part of a state machine.
NNG_DECL void nng_aio_set_expire(nng_aio *, nng_time);
// nng_aio_set_iov sets a scatter/gather vector on the aio. The iov array // nng_aio_set_iov sets a scatter/gather vector on the aio. The iov array
// itself is copied. Data members (the memory regions referenced) *may* be // itself is copied. Data members (the memory regions referenced) *may* be
// copied as well, depending on the operation. This operation is guaranteed // copied as well, depending on the operation. This operation is guaranteed
@ -596,9 +642,9 @@ NNG_DECL void nng_msg_free(nng_msg *);
NNG_DECL int nng_msg_realloc(nng_msg *, size_t); NNG_DECL int nng_msg_realloc(nng_msg *, size_t);
NNG_DECL int nng_msg_reserve(nng_msg *, size_t); NNG_DECL int nng_msg_reserve(nng_msg *, size_t);
NNG_DECL size_t nng_msg_capacity(nng_msg *); NNG_DECL size_t nng_msg_capacity(nng_msg *);
NNG_DECL void * nng_msg_header(nng_msg *); NNG_DECL void *nng_msg_header(nng_msg *);
NNG_DECL size_t nng_msg_header_len(const nng_msg *); NNG_DECL size_t nng_msg_header_len(const nng_msg *);
NNG_DECL void * nng_msg_body(nng_msg *); NNG_DECL void *nng_msg_body(nng_msg *);
NNG_DECL size_t nng_msg_len(const nng_msg *); NNG_DECL size_t nng_msg_len(const nng_msg *);
NNG_DECL int nng_msg_append(nng_msg *, const void *, size_t); NNG_DECL int nng_msg_append(nng_msg *, const void *, size_t);
NNG_DECL int nng_msg_insert(nng_msg *, const void *, size_t); NNG_DECL int nng_msg_insert(nng_msg *, const void *, size_t);
@ -685,8 +731,8 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
// TLS options are only used when the underlying transport supports TLS. // TLS options are only used when the underlying transport supports TLS.
// NNG_OPT_TLS_CONFIG is a pointer to an nng_tls_config object. Generally // NNG_OPT_TLS_CONFIG is a pointer to a nng_tls_config object. Generally
// this can used with endpoints, although once an endpoint is started, or // this can be used with endpoints, although once an endpoint is started, or
// once a configuration is used, the value becomes read-only. Note that // once a configuration is used, the value becomes read-only. Note that
// when configuring the object, a hold is placed on the TLS configuration, // when configuring the object, a hold is placed on the TLS configuration,
// using a reference count. When retrieving the object, no such hold is // using a reference count. When retrieving the object, no such hold is
@ -706,7 +752,7 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
// NNG_OPT_TLS_CERT_KEY_FILE names a single file that contains a certificate // NNG_OPT_TLS_CERT_KEY_FILE names a single file that contains a certificate
// and key identifying the endpoint. This is a write-only value. This can be // and key identifying the endpoint. This is a write-only value. This can be
// set multiple times for times for different keys/certs corresponding to // set multiple times for different keys/certs corresponding to
// different algorithms on listeners, whereas dialers only support one. The // different algorithms on listeners, whereas dialers only support one. The
// file must contain both cert and key as PEM blocks, and the key must // file must contain both cert and key as PEM blocks, and the key must
// not be encrypted. (If more flexibility is needed, use the TLS configuration // not be encrypted. (If more flexibility is needed, use the TLS configuration
@ -726,11 +772,24 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
#define NNG_OPT_TLS_SERVER_NAME "tls-server-name" #define NNG_OPT_TLS_SERVER_NAME "tls-server-name"
// NNG_OPT_TLS_VERIFIED returns a boolean indicating whether the peer has // NNG_OPT_TLS_VERIFIED returns a boolean indicating whether the peer has
// been verified (true) or not (false). Typically this is read-only, and // been verified (true) or not (false). Typically, this is read-only, and
// only available for pipes. This option may return incorrect results if // only available for pipes. This option may return incorrect results if
// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`. // peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`.
#define NNG_OPT_TLS_VERIFIED "tls-verified" #define NNG_OPT_TLS_VERIFIED "tls-verified"
// NNG_OPT_TLS_PEER_CN returns the string with the common name
// of the peer certificate. Typically, this is read-only and
// only available for pipes. This option may return incorrect results if
// peer authentication is disabled with `NNG_TLS_AUTH_MODE_NONE`.
#define NNG_OPT_TLS_PEER_CN "tls-peer-cn"
// NNG_OPT_TLS_PEER_ALT_NAMES returns string list with the
// subject alternative names of the peer certificate. Typically this is
// read-only and only available for pipes. This option may return
// incorrect results if peer authentication is disabled with
// `NNG_TLS_AUTH_MODE_NONE`.
#define NNG_OPT_TLS_PEER_ALT_NAMES "tls-peer-alt-names"
// TCP options. These may be supported on various transports that use // TCP options. These may be supported on various transports that use
// TCP underneath such as TLS, or not. // TCP underneath such as TLS, or not.
@ -774,24 +833,30 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
// this for security. // this for security.
#define NNG_OPT_IPC_PERMISSIONS "ipc:permissions" #define NNG_OPT_IPC_PERMISSIONS "ipc:permissions"
// IPC peer options may also be used in some cases with other socket types.
// Peer UID. This is only available on POSIX style systems. // Peer UID. This is only available on POSIX style systems.
#define NNG_OPT_IPC_PEER_UID "ipc:peer-uid" #define NNG_OPT_PEER_UID "ipc:peer-uid"
#define NNG_OPT_IPC_PEER_UID NNG_OPT_PEER_UID
// Peer GID (primary group). This is only available on POSIX style systems. // Peer GID (primary group). This is only available on POSIX style systems.
#define NNG_OPT_IPC_PEER_GID "ipc:peer-gid" #define NNG_OPT_PEER_GID "ipc:peer-gid"
#define NNG_OPT_IPC_PEER_GID NNG_OPT_PEER_GID
// Peer process ID. Available on Windows, Linux, and SunOS. // Peer process ID. Available on Windows, Linux, and SunOS.
// In theory we could obtain this with the first message sent, // In theory, we could obtain this with the first message sent,
// but we have elected not to do this for now. (Nice RFE for a FreeBSD // but we have elected not to do this for now. (Nice RFE for a FreeBSD
// guru though.) // guru though.)
#define NNG_OPT_IPC_PEER_PID "ipc:peer-pid" #define NNG_OPT_PEER_PID "ipc:peer-pid"
#define NNG_OPT_IPC_PEER_PID NNG_OPT_PEER_PID
// Peer Zone ID. Only on SunOS systems. (Linux containers have no // Peer Zone ID. Only on SunOS systems. (Linux containers have no
// definable kernel identity; they are a user-land fabrication made up // definable kernel identity; they are a user-land fabrication made up
// from various pieces of different namespaces. FreeBSD does have // from various pieces of different namespaces. FreeBSD does have
// something called JailIDs, but it isn't obvious how to determine this, // something called JailIDs, but it isn't obvious how to determine this,
// or even if processes can use IPC across jail boundaries.) // or even if processes can use IPC across jail boundaries.)
#define NNG_OPT_IPC_PEER_ZONEID "ipc:peer-zoneid" #define NNG_OPT_PEER_ZONEID "ipc:peer-zoneid"
#define NNG_OPT_IPC_PEER_ZONEID NNG_OPT_PEER_ZONEID
// WebSocket Options. // WebSocket Options.
@ -856,6 +921,16 @@ NNG_DECL nng_listener nng_pipe_listener(nng_pipe);
// peers that cannot be coerced into sending binary frames. // peers that cannot be coerced into sending binary frames.
#define NNG_OPT_WS_RECV_TEXT "ws:recv-text" #define NNG_OPT_WS_RECV_TEXT "ws:recv-text"
// NNG_OPT_SOCKET_FD is a write-only integer property that is used to
// file descriptors (or FILE HANDLE objects on Windows) to a
// socket:// based listener. This file descriptor will be taken
// over and used as a stream connection. The protocol is compatible
// with SP over TCP. This facility is experimental, and intended to
// allow use with descriptors created via socketpair() or similar.
// Note that unidirectional pipes (such as those from pipe(2) or mkfifo)
// are not supported.
#define NNG_OPT_SOCKET_FD "socket:fd"
// XXX: TBD: priorities, ipv4only // XXX: TBD: priorities, ipv4only
// Statistics. These are for informational purposes only, and subject // Statistics. These are for informational purposes only, and subject
@ -890,7 +965,7 @@ NNG_DECL nng_stat *nng_stat_next(nng_stat *);
NNG_DECL nng_stat *nng_stat_child(nng_stat *); NNG_DECL nng_stat *nng_stat_child(nng_stat *);
// nng_stat_name is used to determine the name of the statistic. // nng_stat_name is used to determine the name of the statistic.
// This is a human readable name. Statistic names, as well as the presence // This is a human-readable name. Statistic names, as well as the presence
// or absence or semantic of any particular statistic are not part of any // or absence or semantic of any particular statistic are not part of any
// stable API, and may be changed without notice in future updates. // stable API, and may be changed without notice in future updates.
NNG_DECL const char *nng_stat_name(nng_stat *); NNG_DECL const char *nng_stat_name(nng_stat *);
@ -937,14 +1012,12 @@ enum nng_unit_enum {
NNG_UNIT_EVENTS = 4 // Some other type of event NNG_UNIT_EVENTS = 4 // Some other type of event
}; };
// nng_stat_value returns returns the actual value of the statistic. // nng_stat_value returns the actual value of the statistic.
// Statistic values reflect their value at the time that the corresponding // Statistic values reflect their value at the time that the corresponding
// snapshot was updated, and are undefined until an update is performed. // snapshot was updated, and are undefined until an update is performed.
NNG_DECL uint64_t nng_stat_value(nng_stat *); NNG_DECL uint64_t nng_stat_value(nng_stat *);
// nng_stat_value returns returns the actual value of the statistic. // nng_stat_bool returns the boolean value of the statistic.
// Statistic values reflect their value at the time that the corresponding
// snapshot was updated, and are undefined until an update is performed.
NNG_DECL bool nng_stat_bool(nng_stat *); NNG_DECL bool nng_stat_bool(nng_stat *);
// nng_stat_string returns the string associated with a string statistic, // nng_stat_string returns the string associated with a string statistic,
@ -952,7 +1025,7 @@ NNG_DECL bool nng_stat_bool(nng_stat *);
// is valid until the associated statistic is freed. // is valid until the associated statistic is freed.
NNG_DECL const char *nng_stat_string(nng_stat *); NNG_DECL const char *nng_stat_string(nng_stat *);
// nng_stat_desc returns a human readable description of the statistic. // nng_stat_desc returns a human-readable description of the statistic.
// This may be useful for display in diagnostic interfaces, etc. // This may be useful for display in diagnostic interfaces, etc.
NNG_DECL const char *nng_stat_desc(nng_stat *); NNG_DECL const char *nng_stat_desc(nng_stat *);
@ -963,8 +1036,18 @@ NNG_DECL uint64_t nng_stat_timestamp(nng_stat *);
// Device functionality. This connects two sockets together in a device, // Device functionality. This connects two sockets together in a device,
// which means that messages from one side are forwarded to the other. // which means that messages from one side are forwarded to the other.
// This version is synchronous, which means the caller will block until
// one of the sockets is closed. Note that caller is responsible for
// finally closing both sockets when this function returns.
NNG_DECL int nng_device(nng_socket, nng_socket); NNG_DECL int nng_device(nng_socket, nng_socket);
// Asynchronous form of nng_device. When this succeeds, the device is
// left intact and functioning in the background, until one of the sockets
// is closed or the application exits. The sockets may be shut down if
// the device fails, but the caller is responsible for ultimately closing
// the sockets properly after the device is torn down.
NNG_DECL void nng_device_aio(nng_aio *, nng_socket, nng_socket);
// Symbol name and visibility. TBD. The only symbols that really should // Symbol name and visibility. TBD. The only symbols that really should
// be directly exported to runtimes IMO are the option symbols. And frankly // be directly exported to runtimes IMO are the option symbols. And frankly
// they have enough special logic around them that it might be best not to // they have enough special logic around them that it might be best not to
@ -1179,110 +1262,310 @@ NNG_DECL int nng_stream_listener_set_ptr(
NNG_DECL int nng_stream_listener_set_addr( NNG_DECL int nng_stream_listener_set_addr(
nng_stream_listener *, const char *, const nng_sockaddr *); nng_stream_listener *, const char *, const nng_sockaddr *);
#define NNG_CAN_LIMIT_THREADS
NNG_DECL void nng_set_ncpu_max(int);
NNG_DECL void nng_set_pool_thread_limit_min(int);
NNG_DECL void nng_set_pool_thread_limit_max(int);
NNG_DECL void nng_set_resolve_thread_max(int);
#ifndef NNG_ELIDE_DEPRECATED #ifndef NNG_ELIDE_DEPRECATED
// These are legacy APIs that have been deprecated. // These are legacy APIs that have been deprecated.
// Their use is strongly discouraged. // Their use is strongly discouraged.
// nng_msg_getopt is defunct, and should not be used by programs. It // nng_msg_getopt is defunct, and should not be used by programs. It
// always returns NNG_ENOTSUP. // always returns NNG_ENOTSUP.
NNG_DECL int nng_msg_getopt(nng_msg *, int, void *, size_t *); NNG_DECL int nng_msg_getopt(nng_msg *, int, void *, size_t *) NNG_DEPRECATED;
// Socket options. Use nng_socket_get and nng_socket_set isnetadl // Socket options. Use nng_socket_get and nng_socket_set instead.
NNG_DECL int nng_getopt(nng_socket, const char *, void *, size_t *); NNG_DECL int nng_getopt(
NNG_DECL int nng_getopt_bool(nng_socket, const char *, bool *); nng_socket, const char *, void *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_getopt_int(nng_socket, const char *, int *); NNG_DECL int nng_getopt_bool(nng_socket, const char *, bool *) NNG_DEPRECATED;
NNG_DECL int nng_getopt_ms(nng_socket, const char *, nng_duration *); NNG_DECL int nng_getopt_int(nng_socket, const char *, int *) NNG_DEPRECATED;
NNG_DECL int nng_getopt_size(nng_socket, const char *, size_t *); NNG_DECL int nng_getopt_ms(
NNG_DECL int nng_getopt_uint64(nng_socket, const char *, uint64_t *); nng_socket, const char *, nng_duration *) NNG_DEPRECATED;
NNG_DECL int nng_getopt_ptr(nng_socket, const char *, void **); NNG_DECL int nng_getopt_size(
NNG_DECL int nng_getopt_string(nng_socket, const char *, char **); nng_socket, const char *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_setopt(nng_socket, const char *, const void *, size_t); NNG_DECL int nng_getopt_uint64(
NNG_DECL int nng_setopt_bool(nng_socket, const char *, bool); nng_socket, const char *, uint64_t *) NNG_DEPRECATED;
NNG_DECL int nng_setopt_int(nng_socket, const char *, int); NNG_DECL int nng_getopt_ptr(nng_socket, const char *, void **) NNG_DEPRECATED;
NNG_DECL int nng_setopt_ms(nng_socket, const char *, nng_duration); NNG_DECL int nng_getopt_string(
NNG_DECL int nng_setopt_size(nng_socket, const char *, size_t); nng_socket, const char *, char **) NNG_DEPRECATED;
NNG_DECL int nng_setopt_uint64(nng_socket, const char *, uint64_t); NNG_DECL int nng_setopt(
NNG_DECL int nng_setopt_string(nng_socket, const char *, const char *); nng_socket, const char *, const void *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_setopt_ptr(nng_socket, const char *, void *); NNG_DECL int nng_setopt_bool(nng_socket, const char *, bool) NNG_DEPRECATED;
NNG_DECL int nng_setopt_int(nng_socket, const char *, int) NNG_DEPRECATED;
NNG_DECL int nng_setopt_ms(
nng_socket, const char *, nng_duration) NNG_DEPRECATED;
NNG_DECL int nng_setopt_size(nng_socket, const char *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_setopt_uint64(
nng_socket, const char *, uint64_t) NNG_DEPRECATED;
NNG_DECL int nng_setopt_string(
nng_socket, const char *, const char *) NNG_DEPRECATED;
NNG_DECL int nng_setopt_ptr(nng_socket, const char *, void *) NNG_DEPRECATED;
// Context options. Use nng_ctx_get and nng_ctx_set instead. // Context options. Use nng_ctx_get and nng_ctx_set instead.
NNG_DECL int nng_ctx_getopt(nng_ctx, const char *, void *, size_t *); NNG_DECL int nng_ctx_getopt(
NNG_DECL int nng_ctx_getopt_bool(nng_ctx, const char *, bool *); nng_ctx, const char *, void *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_ctx_getopt_int(nng_ctx, const char *, int *); NNG_DECL int nng_ctx_getopt_bool(nng_ctx, const char *, bool *) NNG_DEPRECATED;
NNG_DECL int nng_ctx_getopt_ms(nng_ctx, const char *, nng_duration *); NNG_DECL int nng_ctx_getopt_int(nng_ctx, const char *, int *) NNG_DEPRECATED;
NNG_DECL int nng_ctx_getopt_size(nng_ctx, const char *, size_t *); NNG_DECL int nng_ctx_getopt_ms(
NNG_DECL int nng_ctx_setopt(nng_ctx, const char *, const void *, size_t); nng_ctx, const char *, nng_duration *) NNG_DEPRECATED;
NNG_DECL int nng_ctx_setopt_bool(nng_ctx, const char *, bool); NNG_DECL int nng_ctx_getopt_size(
NNG_DECL int nng_ctx_setopt_int(nng_ctx, const char *, int); nng_ctx, const char *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_ctx_setopt_ms(nng_ctx, const char *, nng_duration); NNG_DECL int nng_ctx_setopt(
NNG_DECL int nng_ctx_setopt_size(nng_ctx, const char *, size_t); nng_ctx, const char *, const void *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_ctx_setopt_bool(nng_ctx, const char *, bool) NNG_DEPRECATED;
NNG_DECL int nng_ctx_setopt_int(nng_ctx, const char *, int) NNG_DEPRECATED;
NNG_DECL int nng_ctx_setopt_ms(
nng_ctx, const char *, nng_duration) NNG_DEPRECATED;
NNG_DECL int nng_ctx_setopt_size(nng_ctx, const char *, size_t) NNG_DEPRECATED;
// Dialer options. Use nng_dialer_get and nng_dialer_set instead. // Dialer options. Use nng_dialer_get and nng_dialer_set instead.
NNG_DECL int nng_dialer_getopt(nng_dialer, const char *, void *, size_t *); NNG_DECL int nng_dialer_getopt(
NNG_DECL int nng_dialer_getopt_bool(nng_dialer, const char *, bool *); nng_dialer, const char *, void *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_int(nng_dialer, const char *, int *); NNG_DECL int nng_dialer_getopt_bool(
NNG_DECL int nng_dialer_getopt_ms(nng_dialer, const char *, nng_duration *); nng_dialer, const char *, bool *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_size(nng_dialer, const char *, size_t *); NNG_DECL int nng_dialer_getopt_int(
nng_dialer, const char *, int *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_ms(
nng_dialer, const char *, nng_duration *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_size(
nng_dialer, const char *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_sockaddr( NNG_DECL int nng_dialer_getopt_sockaddr(
nng_dialer, const char *, nng_sockaddr *); nng_dialer, const char *, nng_sockaddr *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_uint64(nng_dialer, const char *, uint64_t *); NNG_DECL int nng_dialer_getopt_uint64(
NNG_DECL int nng_dialer_getopt_ptr(nng_dialer, const char *, void **); nng_dialer, const char *, uint64_t *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_getopt_string(nng_dialer, const char *, char **); NNG_DECL int nng_dialer_getopt_ptr(
NNG_DECL int nng_dialer_setopt(nng_dialer, const char *, const void *, size_t); nng_dialer, const char *, void **) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_bool(nng_dialer, const char *, bool); NNG_DECL int nng_dialer_getopt_string(
NNG_DECL int nng_dialer_setopt_int(nng_dialer, const char *, int); nng_dialer, const char *, char **) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_ms(nng_dialer, const char *, nng_duration); NNG_DECL int nng_dialer_setopt(
NNG_DECL int nng_dialer_setopt_size(nng_dialer, const char *, size_t); nng_dialer, const char *, const void *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_uint64(nng_dialer, const char *, uint64_t); NNG_DECL int nng_dialer_setopt_bool(
NNG_DECL int nng_dialer_setopt_ptr(nng_dialer, const char *, void *); nng_dialer, const char *, bool) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_string(nng_dialer, const char *, const char *); NNG_DECL int nng_dialer_setopt_int(
nng_dialer, const char *, int) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_ms(
nng_dialer, const char *, nng_duration) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_size(
nng_dialer, const char *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_uint64(
nng_dialer, const char *, uint64_t) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_ptr(
nng_dialer, const char *, void *) NNG_DEPRECATED;
NNG_DECL int nng_dialer_setopt_string(
nng_dialer, const char *, const char *) NNG_DEPRECATED;
// Listener options. Use nng_listener_get and nng_listener_set instead. // Listener options. Use nng_listener_get and nng_listener_set instead.
NNG_DECL int nng_listener_getopt(nng_listener, const char *, void *, size_t *); NNG_DECL int nng_listener_getopt(
NNG_DECL int nng_listener_getopt_bool(nng_listener, const char *, bool *); nng_listener, const char *, void *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_int(nng_listener, const char *, int *); NNG_DECL int nng_listener_getopt_bool(
nng_listener, const char *, bool *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_int(
nng_listener, const char *, int *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_ms( NNG_DECL int nng_listener_getopt_ms(
nng_listener, const char *, nng_duration *); nng_listener, const char *, nng_duration *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_size(nng_listener, const char *, size_t *); NNG_DECL int nng_listener_getopt_size(
nng_listener, const char *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_sockaddr( NNG_DECL int nng_listener_getopt_sockaddr(
nng_listener, const char *, nng_sockaddr *); nng_listener, const char *, nng_sockaddr *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_uint64( NNG_DECL int nng_listener_getopt_uint64(
nng_listener, const char *, uint64_t *); nng_listener, const char *, uint64_t *) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_ptr(nng_listener, const char *, void **); NNG_DECL int nng_listener_getopt_ptr(
NNG_DECL int nng_listener_getopt_string(nng_listener, const char *, char **); nng_listener, const char *, void **) NNG_DEPRECATED;
NNG_DECL int nng_listener_getopt_string(
nng_listener, const char *, char **) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt( NNG_DECL int nng_listener_setopt(
nng_listener, const char *, const void *, size_t); nng_listener, const char *, const void *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_bool(nng_listener, const char *, bool); NNG_DECL int nng_listener_setopt_bool(
NNG_DECL int nng_listener_setopt_int(nng_listener, const char *, int); nng_listener, const char *, bool) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_ms(nng_listener, const char *, nng_duration); NNG_DECL int nng_listener_setopt_int(
NNG_DECL int nng_listener_setopt_size(nng_listener, const char *, size_t); nng_listener, const char *, int) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_uint64(nng_listener, const char *, uint64_t); NNG_DECL int nng_listener_setopt_ms(
NNG_DECL int nng_listener_setopt_ptr(nng_listener, const char *, void *); nng_listener, const char *, nng_duration) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_size(
nng_listener, const char *, size_t) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_uint64(
nng_listener, const char *, uint64_t) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_ptr(
nng_listener, const char *, void *) NNG_DEPRECATED;
NNG_DECL int nng_listener_setopt_string( NNG_DECL int nng_listener_setopt_string(
nng_listener, const char *, const char *); nng_listener, const char *, const char *) NNG_DEPRECATED;
// Pipe options. Use nng_pipe_get instead. // Pipe options. Use nng_pipe_get instead.
NNG_DECL int nng_pipe_getopt(nng_pipe, const char *, void *, size_t *); NNG_DECL int nng_pipe_getopt(
NNG_DECL int nng_pipe_getopt_bool(nng_pipe, const char *, bool *); nng_pipe, const char *, void *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_int(nng_pipe, const char *, int *); NNG_DECL int nng_pipe_getopt_bool(
NNG_DECL int nng_pipe_getopt_ms(nng_pipe, const char *, nng_duration *); nng_pipe, const char *, bool *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_size(nng_pipe, const char *, size_t *); NNG_DECL int nng_pipe_getopt_int(nng_pipe, const char *, int *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_sockaddr(nng_pipe, const char *, nng_sockaddr *); NNG_DECL int nng_pipe_getopt_ms(
NNG_DECL int nng_pipe_getopt_uint64(nng_pipe, const char *, uint64_t *); nng_pipe, const char *, nng_duration *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_ptr(nng_pipe, const char *, void **); NNG_DECL int nng_pipe_getopt_size(
NNG_DECL int nng_pipe_getopt_string(nng_pipe, const char *, char **); nng_pipe, const char *, size_t *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_sockaddr(
nng_pipe, const char *, nng_sockaddr *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_uint64(
nng_pipe, const char *, uint64_t *) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_ptr(
nng_pipe, const char *, void **) NNG_DEPRECATED;
NNG_DECL int nng_pipe_getopt_string(
nng_pipe, const char *, char **) NNG_DEPRECATED;
// nng_closeall closes all open sockets. Do not call this from // nng_closeall closes all open sockets. Do not call this from
// a library; it will affect all sockets. // a library; it will affect all sockets.
NNG_DECL void nng_closeall(void); NNG_DECL void nng_closeall(void) NNG_DEPRECATED;
#endif #endif // NNG_ELIDE_DEPRECATED
// nng_init_parameter is used by applications to change a tunable setting.
// This function must be called before any other NNG function for the setting
// to have any effect. This function is also not thread-safe!
//
// The list of parameters supported is *not* documented, and subject to change.
//
// We try to provide sane defaults, so the use here is intended to provide
// more control for applications that cannot use compile-time configuration.
//
// Applications should not depend on this API for correct operation.
//
// This API is intentionally undocumented.
//
// Parameter settings are lost after nng_fini() is called.
typedef int nng_init_parameter;
NNG_DECL void nng_init_set_parameter(nng_init_parameter, uint64_t);
// The following list of parameters is not part of our API stability promise.
// In particular the set of parameters that are supported, the default values,
// the range of valid values, and semantics associated therein are subject to
// change at any time. We won't go out of our way to break these, and we will
// try to prevent changes here from breaking working applications, but this is
// on a best effort basis only.
//
// NOTE: When removing a value, please leave the enumeration in place and add
// a suffix _RETIRED ... this will preserve the binary values for binary
// compatibility.
enum {
NNG_INIT_PARAMETER_NONE = 0, // ensure values start at 1.
// Fix the number of threads used for tasks (callbacks),
// Default is 2 threads per core, capped to NNG_INIT_MAX_TASK_THREADS.
// At least 2 threads will be created in any case.
NNG_INIT_NUM_TASK_THREADS,
// Fix the number of threads used for expiration. Default is one
// thread per core, capped to NNG_INIT_MAX_EXPIRE_THREADS. At least
// one thread will be created.
NNG_INIT_NUM_EXPIRE_THREADS,
// Fix the number of poller threads (used for I/O). Support varies
// by platform (many platforms only support a single poller thread.)
NNG_INIT_NUM_POLLER_THREADS,
// Fix the number of threads used for DNS resolution. At least one
// will be used. Default is controlled by NNG_RESOLV_CONCURRENCY
// compile time variable.
NNG_INIT_NUM_RESOLVER_THREADS,
// Limit the number of threads of created for tasks.
// NNG will always create at least 2 of these in order to prevent
// deadlocks. Zero means no limit. Default is determined by
// NNG_MAX_TASKQ_THREADS compile time variable.
NNG_INIT_MAX_TASK_THREADS,
// Limit the number of threads created for expiration. Zero means no
// limit. Default is determined by the NNG_MAX_EXPIRE_THREADS compile
// time variable.
NNG_INIT_MAX_EXPIRE_THREADS,
// Limit the number of poller/IO threads created. Zero means no limit.
// Default is determined by NNG_MAX_POLLER_THREADS compile time
// variable.
NNG_INIT_MAX_POLLER_THREADS,
};
// Logging support.
// Log levels. These correspond to RFC 5424 (syslog) levels.
// NNG never only uses priorities 3 - 7.
//
// Note that LOG_EMER is 0, but we don't let applications submit'
// such messages, so this is a useful value to prevent logging altogether.
typedef enum nng_log_level {
NNG_LOG_NONE = 0, // used for filters only, NNG suppresses these
NNG_LOG_ERR = 3,
NNG_LOG_WARN = 4,
NNG_LOG_NOTICE = 5,
NNG_LOG_INFO = 6,
NNG_LOG_DEBUG = 7
} nng_log_level;
// Facilities. Also from RFC 5424.
// Not all values are enumerated here. Values not enumerated here
// should be assumed reserved for system use, and not available for
// NNG or general applications.
typedef enum nng_log_facility {
NNG_LOG_USER = 1,
NNG_LOG_DAEMON = 3,
NNG_LOG_AUTH = 10, // actually AUTHPRIV, for sensitive logs
NNG_LOG_LOCAL0 = 16,
NNG_LOG_LOCAL1 = 17,
NNG_LOG_LOCAL2 = 18,
NNG_LOG_LOCAL3 = 19,
NNG_LOG_LOCAL4 = 20,
NNG_LOG_LOCAL5 = 21,
NNG_LOG_LOCAL6 = 22,
NNG_LOG_LOCAL7 = 23,
} nng_log_facility;
// Logging function, which may be supplied by application code. Only
// one logging function may be registered. The level and facility are
// as above. The message ID is chosen by the submitter - internal NNG
// messages will have MSGIDs starting with "NNG-". The MSGID should be
// not more than 8 characters, though this is not a hard requirement.
// Loggers are required ot make a copy of the msgid and message if required,
// because the values will not be valid once the logger returns.
typedef void (*nng_logger)(nng_log_level level, nng_log_facility facility,
const char *msgid, const char *msg);
// Discard logger, simply throws logs away.
NNG_DECL void nng_null_logger(
nng_log_level, nng_log_facility, const char *, const char *);
// Very simple, prints formatted messages to stderr.
NNG_DECL void nng_stderr_logger(
nng_log_level, nng_log_facility, const char *, const char *);
// Performs an appropriate logging function for the system. On
// POSIX systems it uses syslog(3). Details vary by system, and the
// logging may be influenced by other APIs not provided by NNG, such as
// openlog() for POSIX systems. This may be nng_stderr_logger on
// other systems.
NNG_DECL void nng_system_logger(
nng_log_level, nng_log_facility, const char *, const char *);
// Set the default facility to use when logging. NNG uses NNG_LOG_USER by
// default.
NNG_DECL void nng_log_set_facility(nng_log_facility facility);
// Set the default logging level. Use NNG_LOG_DEBUG to get everything.
// Use NNG_LOG_NONE to prevent logging altogether. Logs that are less
// severe (numeric level is higher) will be discarded.
NNG_DECL void nng_log_set_level(nng_log_level level);
// Get the current logging level. The intention here os to allow
// bypassing expensive formatting operations that will be discarded
// anyway.
NNG_DECL nng_log_level nng_log_get_level(void);
// Register a logger.
NNG_DECL void nng_log_set_logger(nng_logger logger);
// Log a message. The msg is formatted using following arguments as per
// sprintf. The msgid may be NULL.
NNG_DECL void nng_log_err(const char *msgid, const char *msg, ...);
NNG_DECL void nng_log_warn(const char *msgid, const char *msg, ...);
NNG_DECL void nng_log_notice(const char *msgid, const char *msg, ...);
NNG_DECL void nng_log_info(const char *msgid, const char *msg, ...);
NNG_DECL void nng_log_debug(const char *msgid, const char *msg, ...);
// Log an authentication related message. These will use the NNG_LOG_AUTH
// facility.
NNG_DECL void nng_log_auth(
nng_log_level level, const char *msgid, const char *msg, ...);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,5 +1,5 @@
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -27,6 +27,11 @@ NNG_DECL int nng_bus0_open_raw(nng_socket *);
#define nng_bus_open_raw nng_bus0_open_raw #define nng_bus_open_raw nng_bus0_open_raw
#endif #endif
#define NNG_BUS0_SELF 0x70
#define NNG_BUS0_PEER 0x70
#define NNG_BUS0_SELF_NAME "bus"
#define NNG_BUS0_PEER_NAME "bus"
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -31,6 +31,7 @@ NNG_DECL int nng_req0_open_raw(nng_socket *);
#define NNG_REQ0_PEER_NAME "rep" #define NNG_REQ0_PEER_NAME "rep"
#define NNG_OPT_REQ_RESENDTIME "req:resend-time" #define NNG_OPT_REQ_RESENDTIME "req:resend-time"
#define NNG_OPT_REQ_RESENDTICK "req:resend-tick"
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -80,6 +80,14 @@ typedef struct nng_tls_engine_conn_ops_s {
// verified returns true if the connection is fully // verified returns true if the connection is fully
// TLS verified, false otherwise. // TLS verified, false otherwise.
bool (*verified)(nng_tls_engine_conn *); bool (*verified)(nng_tls_engine_conn *);
// peer_cn returns the common name of the peer
// The return string needs to be freed.
char *(*peer_cn)(nng_tls_engine_conn *);
// peer_alt_names returns the subject alternative names.
// The return string list and its strings need to be freed.
char **(*peer_alt_names)(nng_tls_engine_conn *);
} nng_tls_engine_conn_ops; } nng_tls_engine_conn_ops;
typedef struct nng_tls_engine_config_ops_s { typedef struct nng_tls_engine_config_ops_s {

View file

@ -0,0 +1,35 @@
//
// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#ifndef NNG_SUPPLEMENTAL_UTIL_IDHASH_H
#define NNG_SUPPLEMENTAL_UTIL_IDHASH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <nng/nng.h>
typedef struct nng_id_map_s nng_id_map;
#define NNG_MAP_RANDOM 1
NNG_DECL int nng_id_map_alloc(
nng_id_map **map, uint64_t lo, uint64_t hi, int flags);
NNG_DECL void nng_id_map_free(nng_id_map *map);
NNG_DECL void *nng_id_get(nng_id_map *, uint64_t);
NNG_DECL int nng_id_set(nng_id_map *, uint64_t, void *);
NNG_DECL int nng_id_alloc(nng_id_map *, uint64_t *, void *);
NNG_DECL int nng_id_remove(nng_id_map *, uint64_t);
#ifdef __cplusplus
}
#endif
#endif // NNG_SUPPLEMENTAL_IDHASH_IDHASH_H

View file

@ -1,5 +1,5 @@
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -27,13 +27,9 @@
extern "C" { extern "C" {
#endif #endif
// nng_time represents an absolute time since some arbitrary point in the
// past, measured in milliseconds. The values are always positive.
typedef uint64_t nng_time;
// Return an absolute time from some arbitrary point. The value is // Return an absolute time from some arbitrary point. The value is
// provided in milliseconds, and is of limited resolution based on the // provided in milliseconds, and is of limited resolution based on the
// system clock. (Do not use it for fine grained performance measurements.) // system clock. (Do not use it for fine-grained performance measurements.)
NNG_DECL nng_time nng_clock(void); NNG_DECL nng_time nng_clock(void);
// Sleep for specified msecs. // Sleep for specified msecs.
@ -104,6 +100,13 @@ NNG_DECL void nng_cv_wake1(nng_cv *);
// nng_random returns a "strong" (cryptographic sense) random number. // nng_random returns a "strong" (cryptographic sense) random number.
NNG_DECL uint32_t nng_random(void); NNG_DECL uint32_t nng_random(void);
// nng_socket_pair is used to create a bound pair of file descriptors
// typically using the socketpair() call. The descriptors are backed
// by reliable, bidirectional, byte streams. This will return NNG_ENOTSUP
// if the platform lacks support for this. The argument is a pointer
// to an array of file descriptors (or HANDLES or similar).
NNG_DECL int nng_socket_pair(int [2]);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -1,5 +1,5 @@
# #
# Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
# Copyright 2018 Capitar IT Group BV <info@capitar.com> # Copyright 2018 Capitar IT Group BV <info@capitar.com>
# #
# This software is supplied under the terms of the MIT License, a # This software is supplied under the terms of the MIT License, a
@ -16,12 +16,15 @@ target_include_directories(nng_testing PRIVATE ${PROJECT_SOURCE_DIR}/src)
add_subdirectory(core) add_subdirectory(core)
add_subdirectory(platform) add_subdirectory(platform)
add_subdirectory(compat)
add_subdirectory(sp) add_subdirectory(sp)
add_subdirectory(supplemental) add_subdirectory(supplemental)
add_subdirectory(tools) add_subdirectory(tools)
add_subdirectory(testing) add_subdirectory(testing)
if (NNG_ENABLE_COMPAT)
add_subdirectory(compat)
endif()
# When building shared libraries we prefer to suppress default symbol # When building shared libraries we prefer to suppress default symbol
# visibility, so that only the symbols that should be exposed in the # visibility, so that only the symbols that should be exposed in the
# resulting library are. This is the default with Windows. # resulting library are. This is the default with Windows.

View file

@ -1,5 +1,5 @@
# #
# Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
# #
# This software is supplied under the terms of the MIT License, a # This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this # copy of which should be located in the distribution where this
@ -11,4 +11,5 @@ nng_sources(nn.c)
set(NNG_TEST_PREFIX ${NNG_TEST_PREFIX}.compat.nanomsg) set(NNG_TEST_PREFIX ${NNG_TEST_PREFIX}.compat.nanomsg)
nng_test(compat_msg_test)
nng_test(compat_tcp_test) nng_test(compat_tcp_test)

View file

@ -0,0 +1,92 @@
//
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt). A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//
#include <nng/compat/nanomsg/nn.h>
#include <nng/compat/nanomsg/pair.h>
#include <nng/compat/nanomsg/tcp.h>
#include "nuts_compat.h"
#include <nuts.h>
void
test_msg_alloc(void)
{
char *msg;
msg = nn_allocmsg(1, 0);
NUTS_TRUE(msg != NULL);
NUTS_NN_PASS(nn_freemsg(msg));
}
void
test_msg_zero_length(void)
{
char *msg;
msg = nn_allocmsg(0, 0); // empty message is invalid
NUTS_TRUE(msg == NULL);
NUTS_TRUE(nn_errno() == EINVAL);
}
void
test_msg_overflow(void)
{
char *msg;
msg = nn_allocmsg((size_t)-1, 0); // this will overflow
NUTS_TRUE(msg == NULL);
NUTS_TRUE(nn_errno() == EINVAL);
}
void
test_msg_bad_type(void)
{
char *msg;
msg = nn_allocmsg(0, 1); // we only support message type 0
NUTS_TRUE(msg == NULL);
NUTS_TRUE(nn_errno() == EINVAL);
}
void
test_msg_realloc(void)
{
char *msg0;
char *msg1;
char *msg2;
char *msg3;
msg0 = nn_allocmsg(5, 0);
NUTS_TRUE(msg0 != NULL);
memcpy(msg0, "this", 5);
msg1 = nn_reallocmsg(msg0, 65536);
NUTS_TRUE(msg1 != NULL);
NUTS_TRUE(msg1 != msg0);
NUTS_MATCH(msg1, "this");
msg1[65000] = 'A';
msg2 = nn_reallocmsg(msg1, 5);
NUTS_TRUE(msg2 == msg1);
// test for overflow
msg3 = nn_reallocmsg(msg2, (size_t)-1);
NUTS_TRUE(msg3 == NULL);
NUTS_TRUE(nn_errno() == EINVAL);
nn_freemsg(msg2);
}
TEST_LIST = {
{ "alloc msg", test_msg_alloc },
{ "zero length", test_msg_zero_length },
{ "invalid type", test_msg_bad_type },
{ "overflow", test_msg_overflow },
{ "reallocate msg", test_msg_realloc },
{ NULL, NULL },
};

View file

@ -1,5 +1,5 @@
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -237,7 +237,7 @@ nn_socket(int domain, int protocol)
return (-1); return (-1);
} }
// Legacy sockets have nodelay disabled. // Legacy sockets have Nagle disabled.
(void) nng_socket_set_bool(sock, NNG_OPT_TCP_NODELAY, false); (void) nng_socket_set_bool(sock, NNG_OPT_TCP_NODELAY, false);
return ((int) sock.id); return ((int) sock.id);
} }
@ -298,7 +298,7 @@ nn_shutdown(int s, int ep)
// Socket is wired into the endpoint... so passing a bad endpoint // Socket is wired into the endpoint... so passing a bad endpoint
// ID can result in affecting the wrong socket. But this requires // ID can result in affecting the wrong socket. But this requires
// a buggy application, and because we don't recycle endpoints // a buggy application, and because we don't recycle endpoints
// until wrap, its unlikely to actually come up in practice. // until wrap, it's unlikely to actually come up in practice.
// Note that listeners and dialers share the same namespace // Note that listeners and dialers share the same namespace
// in the core, so we can close either one this way. // in the core, so we can close either one this way.
@ -326,13 +326,12 @@ nn_allocmsg(size_t size, int type)
// So our "messages" from nn are really going to be nng messages // So our "messages" from nn are really going to be nng messages
// but to make this work, we use a bit of headroom in the message // but to make this work, we use a bit of headroom in the message
// to stash the message header. // to stash the message header.
if ((rv = nng_msg_alloc(&msg, size + (sizeof(msg)))) != 0) { if ((rv = nng_msg_alloc(&msg, size)) != 0) {
nn_seterror(rv); nn_seterror(rv);
return (NULL); return (NULL);
} }
// This counts on message bodies being aligned sensibly. nng_msg_insert(msg, &msg, sizeof(msg));
*(nng_msg **) (nng_msg_body(msg)) = msg;
// We are counting on the implementation of nn_msg_trim to not // We are counting on the implementation of nn_msg_trim to not
// reallocate the message but just to leave the prefix inplace. // reallocate the message but just to leave the prefix inplace.
@ -367,14 +366,14 @@ nn_reallocmsg(void *ptr, size_t len)
msg = *(nng_msg **) (((char *) ptr) - sizeof(msg)); msg = *(nng_msg **) (((char *) ptr) - sizeof(msg));
// We need to realloc the requested len, plus size for our header. // We need to realloc the requested len, plus size for our header.
if ((rv = nng_msg_realloc(msg, len + sizeof(msg))) != 0) { if ((rv = nng_msg_realloc(msg, len)) != 0) {
// We don't free the old message. Code is free to cope // We don't free the old message. Code is free to cope
// as it sees fit. // as it sees fit.
nn_seterror(rv); nn_seterror(rv);
return (NULL); return (NULL);
} }
// Stash the msg header pointer // Stash the msg header pointer
*(nng_msg **) (nng_msg_body(msg)) = msg; nng_msg_insert(msg, &msg, sizeof(msg));
nng_msg_trim(msg, sizeof(msg)); nng_msg_trim(msg, sizeof(msg));
return (nng_msg_body(msg)); return (nng_msg_body(msg));
} }
@ -433,7 +432,7 @@ int
nn_recvmsg(int s, struct nn_msghdr *mh, int flags) nn_recvmsg(int s, struct nn_msghdr *mh, int flags)
{ {
int rv; int rv;
nng_msg * msg; nng_msg *msg;
size_t len; size_t len;
int keep = 0; int keep = 0;
nng_socket sid; nng_socket sid;
@ -498,7 +497,7 @@ nn_recvmsg(int s, struct nn_msghdr *mh, int flags)
// If the caller has requested control information (header details), // If the caller has requested control information (header details),
// we grab it. // we grab it.
if (mh->msg_control != NULL) { if (mh->msg_control != NULL) {
char * cdata; char *cdata;
size_t clen; size_t clen;
size_t tlen; size_t tlen;
size_t spsz; size_t spsz;
@ -552,10 +551,10 @@ nn_recvmsg(int s, struct nn_msghdr *mh, int flags)
int int
nn_sendmsg(int s, const struct nn_msghdr *mh, int flags) nn_sendmsg(int s, const struct nn_msghdr *mh, int flags)
{ {
nng_msg * msg = NULL; nng_msg *msg = NULL;
nng_msg * cmsg = NULL; nng_msg *cmsg = NULL;
nng_socket sid; nng_socket sid;
char * cdata; char *cdata;
int keep = 0; int keep = 0;
size_t sz; size_t sz;
int rv; int rv;
@ -1145,6 +1144,13 @@ nn_setsockopt(int s, int nnlevel, int nnopt, const void *valp, size_t sz)
nn_seterror(rv); nn_seterror(rv);
return (-1); return (-1);
} }
if ((nnlevel == NN_REQ) && (nnopt == NN_REQ_RESEND_IVL)) {
// Only one context here, so it won't be too bad to tick
// as quickly as this, and it avoids some possible friction
// (e.g. with legacy tests).
(void) nng_socket_set_ms(sid, NNG_OPT_REQ_RESENDTICK, 10);
}
return (0); return (0);
} }
@ -1152,7 +1158,7 @@ struct nn_cmsghdr *
nn_cmsg_next(struct nn_msghdr *mh, struct nn_cmsghdr *first) nn_cmsg_next(struct nn_msghdr *mh, struct nn_cmsghdr *first)
{ {
size_t clen; size_t clen;
char * data; char *data;
// We only support SP headers, so there can be at most one header. // We only support SP headers, so there can be at most one header.
if (first != NULL) { if (first != NULL) {
@ -1201,8 +1207,8 @@ nn_device(int s1, int s2)
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h>
#include <mswsock.h> #include <mswsock.h>
#include <windows.h>
#elif defined NNG_PLATFORM_POSIX #elif defined NNG_PLATFORM_POSIX
#include <poll.h> #include <poll.h>
#endif #endif
@ -1234,8 +1240,8 @@ nn_poll(struct nn_pollfd *fds, int nfds, int timeout)
if (fds[i].events & NN_POLLIN) { if (fds[i].events & NN_POLLIN) {
nng_socket s; nng_socket s;
s.id = fds[i].fd; s.id = fds[i].fd;
if ((rv = nng_socket_get_int(s, NNG_OPT_RECVFD, &fd)) != if ((rv = nng_socket_get_int(
0) { s, NNG_OPT_RECVFD, &fd)) != 0) {
nn_seterror(rv); nn_seterror(rv);
NNI_FREE_STRUCTS(pfd, nfds * 2); NNI_FREE_STRUCTS(pfd, nfds * 2);
return (-1); return (-1);
@ -1251,8 +1257,8 @@ nn_poll(struct nn_pollfd *fds, int nfds, int timeout)
if (fds[i].events & NN_POLLOUT) { if (fds[i].events & NN_POLLOUT) {
nng_socket s; nng_socket s;
s.id = fds[i].fd; s.id = fds[i].fd;
if ((rv = nng_socket_get_int(s, NNG_OPT_SENDFD, &fd)) != if ((rv = nng_socket_get_int(
0) { s, NNG_OPT_SENDFD, &fd)) != 0) {
nn_seterror(rv); nn_seterror(rv);
NNI_FREE_STRUCTS(pfd, nfds * 2); NNI_FREE_STRUCTS(pfd, nfds * 2);
return (-1); return (-1);

View file

@ -1,5 +1,5 @@
# #
# Copyright 2021 Staysail Systems, Inc. <info@staystail.tech> # Copyright 2024 Staysail Systems, Inc. <info@staystail.tech>
# #
# This software is supplied under the terms of the MIT License, a # This software is supplied under the terms of the MIT License, a
# copy of which should be located in the distribution where this # copy of which should be located in the distribution where this
@ -14,6 +14,7 @@ nng_check_sym(strlcpy string.h NNG_HAVE_STRLCPY)
nng_check_sym(strnlen string.h NNG_HAVE_STRNLEN) nng_check_sym(strnlen string.h NNG_HAVE_STRNLEN)
nng_check_sym(strcasecmp string.h NNG_HAVE_STRCASECMP) nng_check_sym(strcasecmp string.h NNG_HAVE_STRCASECMP)
nng_check_sym(strncasecmp string.h NNG_HAVE_STRNCASECMP) nng_check_sym(strncasecmp string.h NNG_HAVE_STRNCASECMP)
nng_check_sym(localtime_r time.h NNG_HAVE_LOCALTIME_R)
nng_sources( nng_sources(
defs.h defs.h
@ -24,6 +25,8 @@ nng_sources(
device.h device.h
dialer.c dialer.c
dialer.h dialer.h
sockfd.c
sockfd.h
file.c file.c
file.h file.h
idhash.c idhash.c
@ -36,6 +39,7 @@ nng_sources(
listener.h listener.h
lmq.c lmq.c
lmq.h lmq.h
log.c
message.c message.c
message.h message.h
msgqueue.c msgqueue.c
@ -50,10 +54,10 @@ nng_sources(
pipe.c pipe.c
pipe.h pipe.h
platform.h platform.h
protocol.c
protocol.h protocol.h
reap.c reap.c
reap.h reap.h
sockaddr.c
socket.c socket.c
socket.h socket.h
sockimpl.h sockimpl.h
@ -69,8 +73,6 @@ nng_sources(
tcp.h tcp.h
thread.c thread.c
thread.h thread.h
timer.c
timer.h
url.c url.c
url.h url.h
) )
@ -79,8 +81,12 @@ nng_test(aio_test)
nng_test(buf_size_test) nng_test(buf_size_test)
nng_test(errors_test) nng_test(errors_test)
nng_test(id_test) nng_test(id_test)
nng_test(init_test)
nng_test(list_test) nng_test(list_test)
nng_test(log_test)
nng_test(message_test) nng_test(message_test)
nng_test(reconnect_test) nng_test(reconnect_test)
nng_test(sock_test) nng_test(sock_test)
nng_test(sockaddr_test)
nng_test(stats_test)
nng_test(url_test) nng_test(url_test)

View file

@ -1,5 +1,5 @@
// //
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -15,7 +15,6 @@ struct nni_aio_expire_q {
nni_mtx eq_mtx; nni_mtx eq_mtx;
nni_cv eq_cv; nni_cv eq_cv;
nni_list eq_list; nni_list eq_list;
uint32_t eq_len;
nni_thr eq_thr; nni_thr eq_thr;
nni_time eq_next; // next expiration nni_time eq_next; // next expiration
bool eq_exit; bool eq_exit;
@ -38,11 +37,11 @@ static int nni_aio_expire_q_cnt;
// free to examine the aio for list membership, etc. The provider must // free to examine the aio for list membership, etc. The provider must
// not call finish more than once though. // not call finish more than once though.
// //
// We use an array of expiration queues, each with it's own lock and // We use an array of expiration queues, each with its own lock and
// condition variable, and expiration thread. By default this is one // condition variable, and expiration thread. By default, this is one
// per CPU core present -- the goal being to reduce overall pressure // per CPU core present -- the goal being to reduce overall pressure
// caused by a single lock. The number of queues (and threads) can // caused by a single lock. The number of queues (and threads) can
// be tuned using the NNG_EXPIRE_THREADS tunable. // be tuned using the NNG_NUM_EXPIRE_THREADS tunable.
// //
// We will not permit an AIO // We will not permit an AIO
// to be marked done if an expiration is outstanding. // to be marked done if an expiration is outstanding.
@ -89,8 +88,8 @@ static int nni_aio_expire_q_cnt;
#define aio_safe_lock(l) nni_mtx_lock(l) #define aio_safe_lock(l) nni_mtx_lock(l)
#define aio_safe_unlock(l) nni_mtx_unlock(l) #define aio_safe_unlock(l) nni_mtx_unlock(l)
#else #else
#define aio_safe_lock(l) #define aio_safe_lock(l) ((void) 1)
#define aio_safe_unlock(l) #define aio_safe_unlock(l) ((void) 1)
#endif #endif
static nni_reap_list aio_reap_list = { static nni_reap_list aio_reap_list = {
@ -249,6 +248,20 @@ void
nni_aio_set_timeout(nni_aio *aio, nni_duration when) nni_aio_set_timeout(nni_aio *aio, nni_duration when)
{ {
aio->a_timeout = when; aio->a_timeout = when;
aio->a_use_expire = false;
}
void
nni_aio_set_expire(nni_aio *aio, nni_time expire)
{
aio->a_expire = expire;
aio->a_use_expire = true;
}
nng_duration
nni_aio_get_timeout(nni_aio *aio)
{
return (aio->a_timeout);
} }
void void
@ -315,6 +328,12 @@ nni_aio_wait(nni_aio *aio)
nni_task_wait(&aio->a_task); nni_task_wait(&aio->a_task);
} }
bool
nni_aio_busy(nni_aio *aio)
{
return (nni_task_busy(&aio->a_task));
}
int int
nni_aio_begin(nni_aio *aio) nni_aio_begin(nni_aio *aio)
{ {
@ -331,7 +350,7 @@ nni_aio_begin(nni_aio *aio)
NNI_ASSERT(aio->a_cancel_fn == NULL); NNI_ASSERT(aio->a_cancel_fn == NULL);
NNI_ASSERT(!nni_list_node_active(&aio->a_expire_node)); NNI_ASSERT(!nni_list_node_active(&aio->a_expire_node));
// Some initialization can be done outside of the lock, because // Some initialization can be done outside the lock, because
// we must have exclusive access to the aio. // we must have exclusive access to the aio.
for (unsigned i = 0; i < NNI_NUM_ELEMENTS(aio->a_outputs); i++) { for (unsigned i = 0; i < NNI_NUM_ELEMENTS(aio->a_outputs); i++) {
aio->a_outputs[i] = NULL; aio->a_outputs[i] = NULL;
@ -364,7 +383,7 @@ nni_aio_schedule(nni_aio *aio, nni_aio_cancel_fn cancel, void *data)
{ {
nni_aio_expire_q *eq = aio->a_expire_q; nni_aio_expire_q *eq = aio->a_expire_q;
if (!aio->a_sleep) { if ((!aio->a_sleep) && (!aio->a_use_expire)) {
// Convert the relative timeout to an absolute timeout. // Convert the relative timeout to an absolute timeout.
switch (aio->a_timeout) { switch (aio->a_timeout) {
case NNG_DURATION_ZERO: case NNG_DURATION_ZERO:
@ -444,6 +463,7 @@ nni_aio_finish_impl(
aio->a_expire = NNI_TIME_NEVER; aio->a_expire = NNI_TIME_NEVER;
aio->a_sleep = false; aio->a_sleep = false;
aio->a_use_expire = false;
nni_mtx_unlock(&eq->eq_mtx); nni_mtx_unlock(&eq->eq_mtx);
if (sync) { if (sync) {
@ -503,6 +523,40 @@ nni_aio_list_active(nni_aio *aio)
return (nni_list_node_active(&aio->a_prov_node)); return (nni_list_node_active(&aio->a_prov_node));
} }
// completions list.
// Implementation note: in order to avoid wasting space, we
// reuse the reap node -- which will be inactive here.
void
nni_aio_completions_init(nni_aio_completions *clp)
{
*clp = NULL;
}
void
nni_aio_completions_add(
nni_aio_completions *clp, nni_aio *aio, int result, size_t count)
{
NNI_ASSERT(!nni_aio_list_active(aio));
aio->a_reap_node.rn_next = *clp;
aio->a_result = result;
aio->a_count = count;
*clp = aio;
}
void
nni_aio_completions_run(nni_aio_completions *clp)
{
nni_aio *aio;
nni_aio *cl = *clp;
*clp = NULL;
while ((aio = cl) != NULL) {
cl = (void *) aio->a_reap_node.rn_next;
aio->a_reap_node.rn_next = NULL;
nni_aio_finish_sync(aio, aio->a_result, aio->a_count);
}
}
static void static void
nni_aio_expire_add(nni_aio *aio) nni_aio_expire_add(nni_aio *aio)
{ {
@ -619,15 +673,15 @@ nni_aio_expire_loop(void *arg)
} }
void * void *
nni_aio_get_prov_extra(nni_aio *aio, unsigned index) nni_aio_get_prov_data(nni_aio *aio)
{ {
return (aio->a_prov_extra[index]); return (aio->a_prov_data);
} }
void void
nni_aio_set_prov_extra(nni_aio *aio, unsigned index, void *data) nni_aio_set_prov_data(nni_aio *aio, void *data)
{ {
aio->a_prov_extra[index] = data; aio->a_prov_data = data;
} }
void void
@ -789,17 +843,29 @@ int
nni_aio_sys_init(void) nni_aio_sys_init(void)
{ {
int num_thr; int num_thr;
int max_thr;
// We create a thread per CPU core for expiration by default. #ifndef NNG_MAX_EXPIRE_THREADS
#ifndef NNG_EXPIRE_THREADS #define NNG_MAX_EXPIRE_THREADS 8
num_thr = nni_plat_ncpu();
#else
num_thr = NNG_EXPIRE_THREADS;
#endif #endif
if (num_thr > nni_thr_get_pool_thread_limit_max()) {
num_thr = nni_thr_get_pool_thread_limit_max();
}
#ifndef NNG_NUM_EXPIRE_THREADS
#define NNG_NUM_EXPIRE_THREADS (nni_plat_ncpu())
#endif
max_thr = (int) nni_init_get_param(
NNG_INIT_MAX_EXPIRE_THREADS, NNG_MAX_EXPIRE_THREADS);
num_thr = (int) nni_init_get_param(
NNG_INIT_NUM_EXPIRE_THREADS, NNG_NUM_EXPIRE_THREADS);
if ((max_thr > 0) && (num_thr > max_thr)) {
num_thr = max_thr;
}
if (num_thr < 1) {
num_thr = 1;
}
nni_init_set_effective(NNG_INIT_NUM_EXPIRE_THREADS, num_thr);
nni_aio_expire_q_list = nni_aio_expire_q_list =
nni_zalloc(sizeof(nni_aio_expire_q *) * num_thr); nni_zalloc(sizeof(nni_aio_expire_q *) * num_thr);
nni_aio_expire_q_cnt = num_thr; nni_aio_expire_q_cnt = num_thr;

View file

@ -1,5 +1,5 @@
// //
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -93,6 +93,10 @@ extern int nni_aio_result(nni_aio *);
// completed. // completed.
extern size_t nni_aio_count(nni_aio *); extern size_t nni_aio_count(nni_aio *);
// nni_aio_busy returns true if the aio is still busy processing work.
// This is a non-blocking form of the check used by nni_aio_wait().
extern bool nni_aio_busy(nni_aio *);
// nni_aio_wait blocks the caller until the operation is complete. // nni_aio_wait blocks the caller until the operation is complete.
// The operation must have already been started. This routine will // The operation must have already been started. This routine will
// block until the AIO, as well as any callback, has completed execution. // block until the AIO, as well as any callback, has completed execution.
@ -133,8 +137,8 @@ extern void nni_aio_abort(nni_aio *, int rv);
// nng_aio_finish family of functions.) // nng_aio_finish family of functions.)
extern int nni_aio_begin(nni_aio *); extern int nni_aio_begin(nni_aio *);
extern void *nni_aio_get_prov_extra(nni_aio *, unsigned); extern void *nni_aio_get_prov_data(nni_aio *);
extern void nni_aio_set_prov_extra(nni_aio *, unsigned, void *); extern void nni_aio_set_prov_data(nni_aio *, void *);
// nni_aio_advance_iov moves up the iov, reflecting that some I/O as // nni_aio_advance_iov moves up the iov, reflecting that some I/O as
// been performed. It returns the amount of data remaining in the argument; // been performed. It returns the amount of data remaining in the argument;
// i.e. if the count refers to more data than the iov can support, then // i.e. if the count refers to more data than the iov can support, then
@ -146,6 +150,8 @@ extern size_t nni_aio_iov_count(nni_aio *);
extern int nni_aio_set_iov(nni_aio *, unsigned, const nni_iov *); extern int nni_aio_set_iov(nni_aio *, unsigned, const nni_iov *);
extern void nni_aio_set_timeout(nni_aio *, nng_duration); extern void nni_aio_set_timeout(nni_aio *, nng_duration);
extern void nni_aio_set_expire(nni_aio *, nni_time);
extern nng_duration nni_aio_get_timeout(nni_aio *);
extern void nni_aio_get_iov(nni_aio *, unsigned *, nni_iov **); extern void nni_aio_get_iov(nni_aio *, unsigned *, nni_iov **);
extern void nni_aio_normalize_timeout(nni_aio *, nng_duration); extern void nni_aio_normalize_timeout(nni_aio *, nng_duration);
extern void nni_aio_bump_count(nni_aio *, size_t); extern void nni_aio_bump_count(nni_aio *, size_t);
@ -162,6 +168,30 @@ extern int nni_aio_schedule(nni_aio *, nni_aio_cancel_fn, void *);
extern void nni_sleep_aio(nni_duration, nni_aio *); extern void nni_sleep_aio(nni_duration, nni_aio *);
// nni_aio_completion_list is used after removing the aio from an
// active work queue, and keeping them so that the completions can
// be run in a deferred manner. These lists are simple, and intended
// to be used as local variables. It's important to initialize the
// list before using it. Also, any AIO added to a completion list must
// not be in active use anywhere.
typedef void *nni_aio_completions;
// nni_aio_completions_init just initializes a completions list.
// This just sets the pointed value to NULL.
extern void nni_aio_completions_init(nni_aio_completions *);
// nni_aio_completions_run runs nni_aio_finish_sync for all the aio objects
// that have been added to the completions. The result code and count used
// are those supplied in nni_aio_completions_add. Callers should not hold
// locks when calling this.
extern void nni_aio_completions_run(nni_aio_completions *);
// nni_aio_completions_add adds an aio (with the result code and length as
// appropriate) to the completion list. This should be done while the
// appropriate lock is held. The aio must not be scheduled.
extern void nni_aio_completions_add(
nni_aio_completions *, nni_aio *, int, size_t);
extern int nni_aio_sys_init(void); extern int nni_aio_sys_init(void);
extern void nni_aio_sys_fini(void); extern void nni_aio_sys_fini(void);
@ -182,6 +212,7 @@ struct nng_aio {
bool a_sleep; // Sleeping with no action bool a_sleep; // Sleeping with no action
bool a_expire_ok; // Expire from sleep is ok bool a_expire_ok; // Expire from sleep is ok
bool a_expiring; // Expiration in progress bool a_expiring; // Expiration in progress
bool a_use_expire; // Use expire instead of timeout
nni_task a_task; nni_task a_task;
// Read/write operations. // Read/write operations.
@ -200,9 +231,8 @@ struct nng_aio {
// Provider-use fields. // Provider-use fields.
nni_aio_cancel_fn a_cancel_fn; nni_aio_cancel_fn a_cancel_fn;
void *a_cancel_arg; void *a_cancel_arg;
void *a_prov_data;
nni_list_node a_prov_node; // Linkage on provider list. nni_list_node a_prov_node; // Linkage on provider list.
void *a_prov_extra[2]; // Extra data used by provider
nni_aio_expire_q *a_expire_q; nni_aio_expire_q *a_expire_q;
nni_list_node a_expire_node; // Expiration node nni_list_node a_expire_node; // Expiration node
nni_reap_node a_reap_node; nni_reap_node a_reap_node;

View file

@ -1,5 +1,5 @@
// //
// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -190,6 +190,27 @@ test_explicit_timeout(void)
NUTS_PASS(nng_close(s)); NUTS_PASS(nng_close(s));
} }
void
test_explicit_expiration(void)
{
nng_socket s;
nng_aio * a;
int done = 0;
nng_time now;
NUTS_PASS(nng_pair1_open(&s));
NUTS_PASS(nng_aio_alloc(&a, cb_done, &done));
now = nng_clock();
now += 40;
nng_aio_set_expire(a, now);
nng_recv_aio(s, a);
nng_aio_wait(a);
NUTS_TRUE(done == 1);
NUTS_FAIL(nng_aio_result(a), NNG_ETIMEDOUT);
nng_aio_free(a);
NUTS_PASS(nng_close(s));
}
void void
test_inherited_timeout(void) test_inherited_timeout(void)
{ {
@ -364,6 +385,18 @@ test_sleep_cancel(void)
nng_mtx_free(sl.mx); nng_mtx_free(sl.mx);
} }
void
test_aio_busy(void)
{
nng_aio *aio;
NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL));
nng_sleep_aio(100, aio);
NUTS_ASSERT(nng_aio_busy(aio));
nng_aio_wait(aio);
NUTS_ASSERT(!nng_aio_busy(aio));
nng_aio_free(aio);
}
NUTS_TESTS = { NUTS_TESTS = {
{ "sleep", test_sleep }, { "sleep", test_sleep },
{ "sleep timeout", test_sleep_timeout }, { "sleep timeout", test_sleep_timeout },
@ -372,10 +405,12 @@ NUTS_TESTS = {
{ "consumer cancel", test_consumer_cancel }, { "consumer cancel", test_consumer_cancel },
{ "traffic", test_traffic }, { "traffic", test_traffic },
{ "explicit timeout", test_explicit_timeout }, { "explicit timeout", test_explicit_timeout },
{ "explicit expire", test_explicit_expiration },
{ "inherited timeout", test_inherited_timeout }, { "inherited timeout", test_inherited_timeout },
{ "zero timeout", test_zero_timeout }, { "zero timeout", test_zero_timeout },
{ "aio reap", test_aio_reap }, { "aio reap", test_aio_reap },
{ "sleep loop", test_sleep_loop }, { "sleep loop", test_sleep_loop },
{ "sleep cancel", test_sleep_cancel }, { "sleep cancel", test_sleep_cancel },
{ "aio busy", test_aio_busy },
{ NULL, NULL }, { NULL, NULL },
}; };

View file

@ -10,15 +10,17 @@
#include <nuts.h> #include <nuts.h>
#if NNG_ENABLE_COMPAT
#include <nng/compat/nanomsg/nn.h> #include <nng/compat/nanomsg/nn.h>
#endif
void void
test_buffer_options(void) test_buffer_options(void)
{ {
nng_socket s1; nng_socket s1;
int val; int val;
size_t sz; size_t sz;
char * opt; char *opt;
char *cases[] = { char *cases[] = {
NNG_OPT_RECVBUF, NNG_OPT_RECVBUF,
@ -62,8 +64,9 @@ test_buffer_options(void)
void void
test_buffer_legacy(void) test_buffer_legacy(void)
{ {
#if NNG_ENABLE_COMPAT
nng_socket s1; nng_socket s1;
char * opt; char *opt;
char *cases[] = { char *cases[] = {
NNG_OPT_RECVBUF, NNG_OPT_RECVBUF,
@ -104,10 +107,13 @@ test_buffer_legacy(void)
NUTS_TRUE(nn_errno() == EINVAL); NUTS_TRUE(nn_errno() == EINVAL);
} }
NUTS_PASS(nng_close(s1)); NUTS_PASS(nng_close(s1));
#endif
} }
NUTS_TESTS = { NUTS_TESTS = {
{ "buffer options", test_buffer_options }, { "buffer options", test_buffer_options },
#if NNG_ENABLE_COMPAT
{ "buffer legacy", test_buffer_legacy }, { "buffer legacy", test_buffer_legacy },
#endif
{ NULL, NULL }, { NULL, NULL },
}; };

View file

@ -23,7 +23,7 @@
if (!(x)) \ if (!(x)) \
nni_panic("%s: %d: assert err: %s", __FILE__, __LINE__, #x) nni_panic("%s: %d: assert err: %s", __FILE__, __LINE__, #x)
#else #else
#define NNI_ASSERT(x) (0) #define NNI_ASSERT(x) ((void)(0))
#endif #endif
// Returns the size of an array in elements. (Convenience.) // Returns the size of an array in elements. (Convenience.)
@ -77,49 +77,49 @@ typedef void (*nni_cb)(void *);
#define NNI_PUT16(ptr, u) \ #define NNI_PUT16(ptr, u) \
do { \ do { \
(ptr)[0] = (uint8_t)(((uint16_t)(u)) >> 8u); \ (ptr)[0] = (uint8_t) (((uint16_t) (u)) >> 8u); \
(ptr)[1] = (uint8_t)((uint16_t)(u)); \ (ptr)[1] = (uint8_t) ((uint16_t) (u)); \
} while (0) } while (0)
#define NNI_PUT32(ptr, u) \ #define NNI_PUT32(ptr, u) \
do { \ do { \
(ptr)[0] = (uint8_t)(((uint32_t)(u)) >> 24u); \ (ptr)[0] = (uint8_t) (((uint32_t) (u)) >> 24u); \
(ptr)[1] = (uint8_t)(((uint32_t)(u)) >> 16u); \ (ptr)[1] = (uint8_t) (((uint32_t) (u)) >> 16u); \
(ptr)[2] = (uint8_t)(((uint32_t)(u)) >> 8u); \ (ptr)[2] = (uint8_t) (((uint32_t) (u)) >> 8u); \
(ptr)[3] = (uint8_t)((uint32_t)(u)); \ (ptr)[3] = (uint8_t) ((uint32_t) (u)); \
} while (0) } while (0)
#define NNI_PUT64(ptr, u) \ #define NNI_PUT64(ptr, u) \
do { \ do { \
(ptr)[0] = (uint8_t)(((uint64_t)(u)) >> 56u); \ (ptr)[0] = (uint8_t) (((uint64_t) (u)) >> 56u); \
(ptr)[1] = (uint8_t)(((uint64_t)(u)) >> 48u); \ (ptr)[1] = (uint8_t) (((uint64_t) (u)) >> 48u); \
(ptr)[2] = (uint8_t)(((uint64_t)(u)) >> 40u); \ (ptr)[2] = (uint8_t) (((uint64_t) (u)) >> 40u); \
(ptr)[3] = (uint8_t)(((uint64_t)(u)) >> 32u); \ (ptr)[3] = (uint8_t) (((uint64_t) (u)) >> 32u); \
(ptr)[4] = (uint8_t)(((uint64_t)(u)) >> 24u); \ (ptr)[4] = (uint8_t) (((uint64_t) (u)) >> 24u); \
(ptr)[5] = (uint8_t)(((uint64_t)(u)) >> 16u); \ (ptr)[5] = (uint8_t) (((uint64_t) (u)) >> 16u); \
(ptr)[6] = (uint8_t)(((uint64_t)(u)) >> 8u); \ (ptr)[6] = (uint8_t) (((uint64_t) (u)) >> 8u); \
(ptr)[7] = (uint8_t)((uint64_t)(u)); \ (ptr)[7] = (uint8_t) ((uint64_t) (u)); \
} while (0) } while (0)
#define NNI_GET16(ptr, v) \ #define NNI_GET16(ptr, v) \
v = (((uint16_t)((uint8_t)(ptr)[0])) << 8u) + \ v = (((uint16_t) ((uint8_t) (ptr)[0])) << 8u) + \
(((uint16_t)(uint8_t)(ptr)[1])) (((uint16_t) (uint8_t) (ptr)[1]))
#define NNI_GET32(ptr, v) \ #define NNI_GET32(ptr, v) \
v = (((uint32_t)((uint8_t)(ptr)[0])) << 24u) + \ v = (((uint32_t) ((uint8_t) (ptr)[0])) << 24u) + \
(((uint32_t)((uint8_t)(ptr)[1])) << 16u) + \ (((uint32_t) ((uint8_t) (ptr)[1])) << 16u) + \
(((uint32_t)((uint8_t)(ptr)[2])) << 8u) + \ (((uint32_t) ((uint8_t) (ptr)[2])) << 8u) + \
(((uint32_t)(uint8_t)(ptr)[3])) (((uint32_t) (uint8_t) (ptr)[3]))
#define NNI_GET64(ptr, v) \ #define NNI_GET64(ptr, v) \
v = (((uint64_t)((uint8_t)(ptr)[0])) << 56u) + \ v = (((uint64_t) ((uint8_t) (ptr)[0])) << 56u) + \
(((uint64_t)((uint8_t)(ptr)[1])) << 48u) + \ (((uint64_t) ((uint8_t) (ptr)[1])) << 48u) + \
(((uint64_t)((uint8_t)(ptr)[2])) << 40u) + \ (((uint64_t) ((uint8_t) (ptr)[2])) << 40u) + \
(((uint64_t)((uint8_t)(ptr)[3])) << 32u) + \ (((uint64_t) ((uint8_t) (ptr)[3])) << 32u) + \
(((uint64_t)((uint8_t)(ptr)[4])) << 24u) + \ (((uint64_t) ((uint8_t) (ptr)[4])) << 24u) + \
(((uint64_t)((uint8_t)(ptr)[5])) << 16u) + \ (((uint64_t) ((uint8_t) (ptr)[5])) << 16u) + \
(((uint64_t)((uint8_t)(ptr)[6])) << 8u) + \ (((uint64_t) ((uint8_t) (ptr)[6])) << 8u) + \
(((uint64_t)(uint8_t)(ptr)[7])) (((uint64_t) (uint8_t) (ptr)[7]))
// This increments a pointer a fixed number of byte cells. // This increments a pointer a fixed number of byte cells.
#define NNI_INCPTR(ptr, n) ((ptr) = (void *) ((char *) (ptr) + (n))) #define NNI_INCPTR(ptr, n) ((ptr) = (void *) ((char *) (ptr) + (n)))
@ -171,4 +171,11 @@ typedef nni_type nni_opt_type;
#define NNI_EXPIRE_BATCH 100 #define NNI_EXPIRE_BATCH 100
#endif #endif
#if __GNUC__ > 3
// NNI_GCC_VERSION is used to indicate a GNU version. It is used
// to trigger certain cases like atomics that might be compiler specific.
#define NNI_GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
#endif // CORE_DEFS_H #endif // CORE_DEFS_H

View file

@ -1,5 +1,5 @@
// //
// Copyright 2018 Staysail Systems, Inc. <info@staysail.com> // Copyright 2021 Staysail Systems, Inc. <info@staysail.com>
// Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Capitar IT Group BV <info@capitar.com>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
@ -10,107 +10,130 @@
#include "core/nng_impl.h" #include "core/nng_impl.h"
#include <string.h> typedef struct device_data_s device_data;
typedef struct device_path_s device_path;
typedef struct nni_device_path { struct device_path_s {
nni_aio * user; // user aio int state;
nni_aio * aio; device_data *d;
nni_sock *src; nni_sock *src;
nni_sock *dst; nni_sock *dst;
int state; nni_aio aio;
} nni_device_path; };
#define NNI_DEVICE_STATE_INIT 0 #define NNI_DEVICE_STATE_INIT 0
#define NNI_DEVICE_STATE_RECV 1 #define NNI_DEVICE_STATE_RECV 1
#define NNI_DEVICE_STATE_SEND 2 #define NNI_DEVICE_STATE_SEND 2
#define NNI_DEVICE_STATE_FINI 3 #define NNI_DEVICE_STATE_FINI 3
typedef struct nni_device_data { struct device_data_s {
nni_aio * user; nni_aio *user;
int npath; int num_paths;
nni_device_path paths[2]; int running;
nni_mtx mtx; int rv;
bool running; device_path paths[2];
} nni_device_data; nni_reap_node reap;
};
typedef struct nni_device_pair nni_device_pair; static void device_fini(void *);
static nni_mtx device_mtx = NNI_MTX_INITIALIZER;
static nni_reap_list device_reap = {
.rl_offset = offsetof(device_data, reap),
.rl_func = device_fini,
};
static void static void
nni_device_cancel(nni_aio *aio, void *arg, int rv) device_fini(void *arg)
{ {
nni_device_data *dd = arg; device_data *d = arg;
// cancellation is the only path to shutting it down.
nni_mtx_lock(&dd->mtx); for (int i = 0; i < d->num_paths; i++) {
if ((!dd->running) || (dd->user != aio)) { nni_aio_stop(&d->paths[i].aio);
nni_mtx_unlock(&dd->mtx);
return;
} }
dd->running = false; NNI_FREE_STRUCT(d);
dd->user = NULL;
nni_mtx_unlock(&dd->mtx);
nni_sock_shutdown(dd->paths[0].src);
nni_sock_shutdown(dd->paths[0].dst);
nni_aio_finish_error(aio, rv);
} }
static void static void
nni_device_cb(void *arg) device_cancel(nni_aio *aio, void *arg, int rv)
{ {
nni_device_path *p = arg; device_data *d = arg;
nni_aio * aio = p->aio; // cancellation is the only path to shutting it down.
nni_mtx_lock(&device_mtx);
if (d->user == aio) {
for (int i = 0; i < d->num_paths; i++) {
nni_aio_abort(&d->paths[i].aio, rv);
}
}
nni_mtx_unlock(&device_mtx);
}
static void
device_cb(void *arg)
{
device_path *p = arg;
device_data *d = p->d;
int rv; int rv;
if ((rv = nni_aio_result(aio)) != 0) { if ((rv = nni_aio_result(&p->aio)) != 0) {
nni_mtx_lock(&device_mtx);
if (p->state == NNI_DEVICE_STATE_SEND) {
nni_msg_free(nni_aio_get_msg(&p->aio));
nni_aio_set_msg(&p->aio, NULL);
}
p->state = NNI_DEVICE_STATE_FINI; p->state = NNI_DEVICE_STATE_FINI;
nni_aio_abort(p->user, rv); d->running--;
if (d->rv == 0) {
d->rv = rv;
}
for (int i = 0; i < d->num_paths; i++) {
if (p != &d->paths[i]) {
nni_aio_abort(&d->paths[i].aio, rv);
}
}
if (d->running == 0) {
if (d->user != NULL) {
nni_aio_finish_error(d->user, d->rv);
d->user = NULL;
}
nni_sock_rele(d->paths[0].src);
nni_sock_rele(d->paths[0].dst);
nni_reap(&device_reap, d);
}
nni_mtx_unlock(&device_mtx);
return; return;
} }
switch (p->state) { switch (p->state) {
case NNI_DEVICE_STATE_INIT: case NNI_DEVICE_STATE_INIT:
break;
case NNI_DEVICE_STATE_SEND: case NNI_DEVICE_STATE_SEND:
p->state = NNI_DEVICE_STATE_RECV; p->state = NNI_DEVICE_STATE_RECV;
nni_sock_recv(p->src, aio); nni_sock_recv(p->src, &p->aio);
break; break;
case NNI_DEVICE_STATE_RECV: case NNI_DEVICE_STATE_RECV:
// Leave the message where it is. // Leave the message where it is.
p->state = NNI_DEVICE_STATE_SEND; p->state = NNI_DEVICE_STATE_SEND;
nni_sock_send(p->dst, aio); nni_sock_send(p->dst, &p->aio);
break; break;
case NNI_DEVICE_STATE_FINI: case NNI_DEVICE_STATE_FINI:
break; break;
} }
} }
void static int
nni_device_fini(nni_device_data *dd) device_init(device_data **dp, nni_sock *s1, nni_sock *s2)
{ {
int i; int num_paths = 2;
for (i = 0; i < dd->npath; i++) {
nni_device_path *p = &dd->paths[i];
nni_aio_stop(p->aio);
}
for (i = 0; i < dd->npath; i++) {
nni_device_path *p = &dd->paths[i];
nni_aio_free(p->aio);
}
nni_mtx_fini(&dd->mtx);
NNI_FREE_STRUCT(dd);
}
int
nni_device_init(nni_device_data **dp, nni_sock *s1, nni_sock *s2)
{
nni_device_data *dd;
int npath = 2;
int i; int i;
bool raw; bool raw;
size_t rsz; size_t rsz;
device_data *d;
// Specifying either of these as null turns the device into // Specifying either of these as null turns the device into
// a loopback reflector. // a reflector.
if (s1 == NULL) { if (s1 == NULL) {
s1 = s2; s1 = s2;
} }
@ -141,8 +164,8 @@ nni_device_init(nni_device_data **dp, nni_sock *s1, nni_sock *s2)
return (NNG_EINVAL); return (NNG_EINVAL);
} }
// Note we assume that since they peers, we only need to look // Note we assume that since they are peers, we only need to look
// at the receive flags -- the other side is assumed to be able // at the recv flags -- the other side is assumed to be able
// to send. // to send.
if ((nni_sock_flags(s1) & NNI_PROTO_FLAG_RCV) == 0) { if ((nni_sock_flags(s1) & NNI_PROTO_FLAG_RCV) == 0) {
nni_sock *temp = s1; nni_sock *temp = s1;
@ -157,82 +180,65 @@ nni_device_init(nni_device_data **dp, nni_sock *s1, nni_sock *s2)
// not strictly necessary, but it saves resources and minimizes any // not strictly necessary, but it saves resources and minimizes any
// extra reordering.) // extra reordering.)
if (((nni_sock_flags(s2) & NNI_PROTO_FLAG_RCV) == 0) || (s1 == s2)) { if (((nni_sock_flags(s2) & NNI_PROTO_FLAG_RCV) == 0) || (s1 == s2)) {
npath = 1; num_paths = 1;
} }
if ((dd = NNI_ALLOC_STRUCT(dd)) == NULL) { if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
return (NNG_ENOMEM); return (NNG_ENOMEM);
} }
nni_mtx_init(&dd->mtx);
for (i = 0; i < npath; i++) { d->num_paths = 0;
int rv; for (i = 0; i < num_paths; i++) {
nni_device_path *p = &dd->paths[i]; device_path *p = &d->paths[i];
p->src = i == 0 ? s1 : s2; p->src = i == 0 ? s1 : s2;
p->dst = i == 0 ? s2 : s1; p->dst = i == 0 ? s2 : s1;
p->d = d;
p->state = NNI_DEVICE_STATE_INIT; p->state = NNI_DEVICE_STATE_INIT;
if ((rv = nni_aio_alloc(&p->aio, nni_device_cb, p)) != 0) { nni_aio_init(&p->aio, device_cb, p);
nni_device_fini(dd);
return (rv);
}
nni_aio_set_timeout(p->aio, NNG_DURATION_INFINITE); nni_aio_set_timeout(&p->aio, NNG_DURATION_INFINITE);
} }
dd->npath = npath; nni_sock_hold(d->paths[0].src);
*dp = dd; nni_sock_hold(d->paths[0].dst);
d->num_paths = num_paths;
*dp = d;
return (0); return (0);
} }
void static void
nni_device_start(nni_device_data *dd, nni_aio *user) device_start(device_data *d, nni_aio *user)
{ {
int i; d->user = user;
int rv; for (int i = 0; i < d->num_paths; i++) {
device_path *p = &d->paths[i];
if (nni_aio_begin(user) != 0) {
return;
}
nni_mtx_lock(&dd->mtx);
if ((rv = nni_aio_schedule(user, nni_device_cancel, dd)) != 0) {
nni_mtx_unlock(&dd->mtx);
nni_aio_finish_error(user, rv);
return;
}
dd->user = user;
for (i = 0; i < dd->npath; i++) {
nni_device_path *p = &dd->paths[i];
p->user = user;
p->state = NNI_DEVICE_STATE_INIT;
}
for (i = 0; i < dd->npath; i++) {
nni_device_path *p = &dd->paths[i];
p->state = NNI_DEVICE_STATE_RECV; p->state = NNI_DEVICE_STATE_RECV;
nni_sock_recv(p->src, p->aio); nni_sock_recv(p->src, &p->aio);
d->running++;
} }
dd->running = true;
nni_mtx_unlock(&dd->mtx);
} }
int void
nni_device(nni_sock *s1, nni_sock *s2) nni_device(nni_aio *aio, nni_sock *s1, nni_sock *s2)
{ {
nni_device_data *dd; device_data *d;
nni_aio * aio;
int rv; int rv;
if ((rv = nni_aio_alloc(&aio, NULL, NULL)) != 0) { if (nni_aio_begin(aio) != 0) {
return (rv); return;
} }
if ((rv = nni_device_init(&dd, s1, s2)) != 0) { nni_mtx_lock(&device_mtx);
nni_aio_free(aio); if ((rv = device_init(&d, s1, s2)) != 0) {
return (rv); nni_mtx_unlock(&device_mtx);
nni_aio_finish_error(aio, rv);
return;
} }
nni_device_start(dd, aio); if ((rv = nni_aio_schedule(aio, device_cancel, d)) != 0) {
nni_aio_wait(aio); nni_mtx_unlock(&device_mtx);
nni_aio_finish_error(aio, rv);
rv = nni_aio_result(aio); nni_reap(&device_reap, d);
nni_device_fini(dd); }
nni_aio_free(aio); device_start(d, aio);
return (rv); nni_mtx_unlock(&device_mtx);
} }

View file

@ -1,5 +1,5 @@
// //
// Copyright 2017 Garrett D'Amore <garrett@damore.org> // Copyright 2021 Staysail Systems, Inc. <info@staysail.tech>
// //
// This software is supplied under the terms of the MIT License, a // This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this // copy of which should be located in the distribution where this
@ -14,6 +14,6 @@
// It works in both directions. Arguably we should build versions of this // It works in both directions. Arguably we should build versions of this
// that are unidirectional, and we could extend this API with user-defined // that are unidirectional, and we could extend this API with user-defined
// filtering functions. // filtering functions.
extern int nni_device(nni_sock *, nni_sock *); extern void nni_device(nni_aio *aio, nni_sock *, nni_sock *);
#endif // CORE_DEVICE_H #endif // CORE_DEVICE_H

Some files were not shown because too many files have changed in this diff Show more