├── .Rbuildignore
├── .github
├── .gitignore
├── CODE_OF_CONDUCT.md
└── workflows
│ ├── R-CMD-check.yaml
│ ├── check-no-suggests.yaml
│ ├── pkgdown.yaml
│ ├── pr-commands.yaml
│ ├── rhub.yaml
│ └── test-coverage.yaml
├── .gitignore
├── DESCRIPTION
├── LICENSE
├── LICENSE.md
├── LICENSE.note
├── NAMESPACE
├── NEWS.md
├── R
├── aio.R
├── context.R
├── docs.R
├── listdial.R
├── messenger.R
├── nano.R
├── nanonext-package.R
├── ncurl.R
├── opts.R
├── sendrecv.R
├── socket.R
├── stats.R
├── stream.R
├── sync.R
├── tls.R
└── utils.R
├── README.Rmd
├── README.md
├── cleanup
├── cleanup.win
├── codecov.yml
├── configure
├── configure.ucrt
├── configure.win
├── cran-comments.md
├── inst
└── CITATION
├── man
├── as.promise.ncurlAio.Rd
├── as.promise.recvAio.Rd
├── call_aio.Rd
├── close.Rd
├── collect_aio.Rd
├── context.Rd
├── cv.Rd
├── dial.Rd
├── dot-advance.Rd
├── dot-context.Rd
├── dot-interrupt.Rd
├── dot-keep.Rd
├── dot-read_header.Rd
├── dot-unresolved.Rd
├── figures
│ └── logo.png
├── grapes-twiddle-greater-than-grapes.Rd
├── ip_addr.Rd
├── is_aio.Rd
├── is_error_value.Rd
├── listen.Rd
├── mclock.Rd
├── messenger.Rd
├── monitor.Rd
├── msleep.Rd
├── nano.Rd
├── nanonext-package.Rd
├── ncurl.Rd
├── ncurl_aio.Rd
├── ncurl_session.Rd
├── nng_error.Rd
├── nng_version.Rd
├── opt.Rd
├── parse_url.Rd
├── pipe_id.Rd
├── pipe_notify.Rd
├── protocols.Rd
├── random.Rd
├── read_stdin.Rd
├── reap.Rd
├── recv.Rd
├── recv_aio.Rd
├── reply.Rd
├── request.Rd
├── send.Rd
├── send_aio.Rd
├── serial_config.Rd
├── socket.Rd
├── start.Rd
├── stat.Rd
├── status_code.Rd
├── stop_aio.Rd
├── stream.Rd
├── subscribe.Rd
├── survey_time.Rd
├── tls_config.Rd
├── transports.Rd
├── unresolved.Rd
├── write_cert.Rd
├── write_stdout.Rd
└── zzz.Rd
├── nanonext.Rproj
├── pkgdown
├── _pkgdown.yml
└── favicon
│ ├── apple-touch-icon-120x120.png
│ ├── apple-touch-icon-152x152.png
│ ├── apple-touch-icon-180x180.png
│ ├── apple-touch-icon-60x60.png
│ ├── apple-touch-icon-76x76.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-48x48.png
│ ├── favicon.ico
│ ├── favicon.svg
│ ├── site.webmanifest
│ ├── web-app-manifest-192x192.png
│ └── web-app-manifest-512x512.png
├── src
├── .gitignore
├── Makevars.in
├── Makevars.ucrt
├── Makevars.win
├── aio.c
├── comms.c
├── core.c
├── init.c
├── mbedtls-362.tar.xz
├── nanonext.h
├── ncurl.c
├── net.c
├── nng-111.tar.xz
├── proto.c
├── sync.c
├── thread.c
├── tls.c
└── utils.c
├── tests
└── tests.R
├── vignettes-src
├── _nanonext.Rmd
└── precompile.R
└── vignettes
├── .gitignore
└── nanonext.Rmd
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^.*\.Rproj$
2 | ^\.Rproj\.user$
3 | ^LICENSE\.md$
4 | ^README\.Rmd$
5 | ^_pkgdown\.yml$
6 | ^docs$
7 | ^pkgdown$
8 | ^revdep$
9 | ^\.github$
10 | ^codecov\.yml$
11 | ^compile_commands\.json$
12 | ^\.cache$
13 | ^vignettes-src$
14 | ^cran-comments\.md$
15 |
--------------------------------------------------------------------------------
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | codeofconduct@posit.co.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | #
4 | # NOTE: This workflow is overkill for most R packages and
5 | # check-standard.yaml is likely a better choice.
6 | # usethis::use_github_action("check-standard") will install it.
7 | on:
8 | push:
9 | branches: [main, dev]
10 | pull_request:
11 |
12 | name: R-CMD-check.yaml
13 |
14 | permissions: read-all
15 |
16 | jobs:
17 | R-CMD-check:
18 | runs-on: ${{ matrix.config.os }}
19 |
20 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
21 |
22 | strategy:
23 | fail-fast: false
24 | matrix:
25 | config:
26 | - {os: ubuntu-24.04-arm, r: 'devel', http-user-agent: 'release'}
27 | - {os: ubuntu-latest, r: 'release'}
28 | - {os: ubuntu-latest, r: 'oldrel-1'}
29 | - {os: ubuntu-22.04, r: 'oldrel-2'}
30 | - {os: macOS-latest, r: 'release'}
31 | - {os: macOS-13, r: 'oldrel-3'}
32 | - {os: windows-latest, r: 'release'}
33 | - {os: windows-latest, r: 'oldrel-4'}
34 |
35 | env:
36 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
37 | R_KEEP_PKG_SOURCE: yes
38 |
39 | steps:
40 | - uses: actions/checkout@v4
41 |
42 | - uses: r-lib/actions/setup-pandoc@v2
43 |
44 | - uses: r-lib/actions/setup-r@v2
45 | with:
46 | r-version: ${{ matrix.config.r }}
47 | http-user-agent: ${{ matrix.config.http-user-agent }}
48 | use-public-rspm: true
49 |
50 | - uses: r-lib/actions/setup-r-dependencies@v2
51 | with:
52 | extra-packages: any::rcmdcheck
53 | needs: check
54 |
55 | - uses: r-lib/actions/check-r-package@v2
56 | with:
57 | upload-snapshots: true
58 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
59 |
--------------------------------------------------------------------------------
/.github/workflows/check-no-suggests.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | #
4 | # NOTE: This workflow only directly installs "hard" dependencies, i.e. Depends,
5 | # Imports, and LinkingTo dependencies. Notably, Suggests dependencies are never
6 | # installed, with the exception of testthat, knitr, and rmarkdown. The cache is
7 | # never used to avoid accidentally restoring a cache containing a suggested
8 | # dependency.
9 | on:
10 | push:
11 | branches: [main, dev]
12 | pull_request:
13 |
14 | name: R-CMD-check-hard
15 |
16 | permissions: read-all
17 |
18 | jobs:
19 | R-CMD-check:
20 | runs-on: ${{ matrix.config.os }}
21 |
22 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
23 |
24 | strategy:
25 | fail-fast: false
26 | matrix:
27 | config:
28 | - {os: ubuntu-latest, r: 'release'}
29 |
30 | env:
31 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
32 | R_KEEP_PKG_SOURCE: yes
33 |
34 | steps:
35 | - uses: actions/checkout@v4
36 |
37 | - uses: r-lib/actions/setup-pandoc@v2
38 |
39 | - uses: r-lib/actions/setup-r@v2
40 | with:
41 | r-version: ${{ matrix.config.r }}
42 | http-user-agent: ${{ matrix.config.http-user-agent }}
43 | use-public-rspm: true
44 |
45 | - uses: r-lib/actions/setup-r-dependencies@v2
46 | with:
47 | dependencies: '"hard"'
48 | cache: false
49 | extra-packages: |
50 | any::rcmdcheck
51 | any::litedown
52 | needs: check
53 |
54 | - uses: r-lib/actions/check-r-package@v2
55 | with:
56 | upload-snapshots: true
57 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
58 |
--------------------------------------------------------------------------------
/.github/workflows/pkgdown.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | release:
8 | types: [published]
9 | workflow_dispatch:
10 |
11 | name: pkgdown.yaml
12 |
13 | permissions: read-all
14 |
15 | jobs:
16 | pkgdown:
17 | runs-on: ubuntu-latest
18 | # Only restrict concurrency for non-PR jobs
19 | concurrency:
20 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
21 | env:
22 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
23 | permissions:
24 | contents: write
25 | steps:
26 | - uses: actions/checkout@v4
27 |
28 | - uses: r-lib/actions/setup-pandoc@v2
29 |
30 | - uses: r-lib/actions/setup-r@v2
31 | with:
32 | use-public-rspm: true
33 |
34 | - uses: r-lib/actions/setup-r-dependencies@v2
35 | with:
36 | extra-packages: any::pkgdown, local::.
37 | needs: website
38 |
39 | - name: Build site
40 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
41 | shell: Rscript {0}
42 |
43 | - name: Deploy to GitHub pages 🚀
44 | if: github.event_name != 'pull_request'
45 | uses: JamesIves/github-pages-deploy-action@v4.5.0
46 | with:
47 | clean: false
48 | branch: gh-pages
49 | folder: docs
50 |
--------------------------------------------------------------------------------
/.github/workflows/pr-commands.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | issue_comment:
5 | types: [created]
6 |
7 | name: pr-commands.yaml
8 |
9 | permissions: read-all
10 |
11 | jobs:
12 | document:
13 | if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/document') }}
14 | name: document
15 | runs-on: ubuntu-latest
16 | env:
17 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
18 | permissions:
19 | contents: write
20 | steps:
21 | - uses: actions/checkout@v4
22 |
23 | - uses: r-lib/actions/pr-fetch@v2
24 | with:
25 | repo-token: ${{ secrets.GITHUB_TOKEN }}
26 |
27 | - uses: r-lib/actions/setup-r@v2
28 | with:
29 | use-public-rspm: true
30 |
31 | - uses: r-lib/actions/setup-r-dependencies@v2
32 | with:
33 | extra-packages: any::roxygen2
34 | needs: pr-document
35 |
36 | - name: Document
37 | run: roxygen2::roxygenise()
38 | shell: Rscript {0}
39 |
40 | - name: commit
41 | run: |
42 | git config --local user.name "$GITHUB_ACTOR"
43 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com"
44 | git add man/\* NAMESPACE
45 | git commit -m 'Document'
46 |
47 | - uses: r-lib/actions/pr-push@v2
48 | with:
49 | repo-token: ${{ secrets.GITHUB_TOKEN }}
50 |
51 | style:
52 | if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/style') }}
53 | name: style
54 | runs-on: ubuntu-latest
55 | env:
56 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
57 | permissions:
58 | contents: write
59 | steps:
60 | - uses: actions/checkout@v4
61 |
62 | - uses: r-lib/actions/pr-fetch@v2
63 | with:
64 | repo-token: ${{ secrets.GITHUB_TOKEN }}
65 |
66 | - uses: r-lib/actions/setup-r@v2
67 |
68 | - name: Install dependencies
69 | run: install.packages("styler")
70 | shell: Rscript {0}
71 |
72 | - name: Style
73 | run: styler::style_pkg()
74 | shell: Rscript {0}
75 |
76 | - name: commit
77 | run: |
78 | git config --local user.name "$GITHUB_ACTOR"
79 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com"
80 | git add \*.R
81 | git commit -m 'Style'
82 |
83 | - uses: r-lib/actions/pr-push@v2
84 | with:
85 | repo-token: ${{ secrets.GITHUB_TOKEN }}
86 |
--------------------------------------------------------------------------------
/.github/workflows/rhub.yaml:
--------------------------------------------------------------------------------
1 | # R-hub's generic GitHub Actions workflow file. It's canonical location is at
2 | # https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml
3 | # You can update this file to a newer version using the rhub2 package:
4 | #
5 | # rhub::rhub_setup()
6 | #
7 | # It is unlikely that you need to modify this file manually.
8 |
9 | name: R-hub
10 | run-name: "${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}"
11 |
12 | on:
13 | workflow_dispatch:
14 | inputs:
15 | config:
16 | description: 'A comma separated list of R-hub platforms to use.'
17 | type: string
18 | default: 'linux,windows,macos'
19 | name:
20 | description: 'Run name. You can leave this empty now.'
21 | type: string
22 | id:
23 | description: 'Unique ID. You can leave this empty now.'
24 | type: string
25 |
26 | jobs:
27 |
28 | setup:
29 | runs-on: ubuntu-latest
30 | outputs:
31 | containers: ${{ steps.rhub-setup.outputs.containers }}
32 | platforms: ${{ steps.rhub-setup.outputs.platforms }}
33 |
34 | steps:
35 | # NO NEED TO CHECKOUT HERE
36 | - uses: r-hub/actions/setup@v1
37 | with:
38 | config: ${{ github.event.inputs.config }}
39 | id: rhub-setup
40 |
41 | linux-containers:
42 | needs: setup
43 | if: ${{ needs.setup.outputs.containers != '[]' }}
44 | runs-on: ubuntu-latest
45 | name: ${{ matrix.config.label }}
46 | strategy:
47 | fail-fast: false
48 | matrix:
49 | config: ${{ fromJson(needs.setup.outputs.containers) }}
50 | container:
51 | image: ${{ matrix.config.container }}
52 |
53 | steps:
54 | - uses: r-hub/actions/checkout@v1
55 | - uses: r-hub/actions/platform-info@v1
56 | with:
57 | token: ${{ secrets.RHUB_TOKEN }}
58 | job-config: ${{ matrix.config.job-config }}
59 | - uses: r-hub/actions/setup-deps@v1
60 | with:
61 | token: ${{ secrets.RHUB_TOKEN }}
62 | job-config: ${{ matrix.config.job-config }}
63 | - uses: r-hub/actions/run-check@v1
64 | with:
65 | token: ${{ secrets.RHUB_TOKEN }}
66 | job-config: ${{ matrix.config.job-config }}
67 |
68 | other-platforms:
69 | needs: setup
70 | if: ${{ needs.setup.outputs.platforms != '[]' }}
71 | runs-on: ${{ matrix.config.os }}
72 | name: ${{ matrix.config.label }}
73 | strategy:
74 | fail-fast: false
75 | matrix:
76 | config: ${{ fromJson(needs.setup.outputs.platforms) }}
77 |
78 | steps:
79 | - uses: r-hub/actions/checkout@v1
80 | - uses: r-hub/actions/setup-r@v1
81 | with:
82 | job-config: ${{ matrix.config.job-config }}
83 | token: ${{ secrets.RHUB_TOKEN }}
84 | - uses: r-hub/actions/platform-info@v1
85 | with:
86 | token: ${{ secrets.RHUB_TOKEN }}
87 | job-config: ${{ matrix.config.job-config }}
88 | - uses: r-hub/actions/setup-deps@v1
89 | with:
90 | job-config: ${{ matrix.config.job-config }}
91 | token: ${{ secrets.RHUB_TOKEN }}
92 | - uses: r-hub/actions/run-check@v1
93 | with:
94 | job-config: ${{ matrix.config.job-config }}
95 | token: ${{ secrets.RHUB_TOKEN }}
96 |
--------------------------------------------------------------------------------
/.github/workflows/test-coverage.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 |
8 | name: test-coverage.yaml
9 |
10 | permissions: read-all
11 |
12 | jobs:
13 | test-coverage:
14 | runs-on: ubuntu-latest
15 | env:
16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
17 |
18 | steps:
19 | - uses: actions/checkout@v4
20 |
21 | - uses: r-lib/actions/setup-r@v2
22 | with:
23 | use-public-rspm: true
24 |
25 | - uses: r-lib/actions/setup-r-dependencies@v2
26 | with:
27 | extra-packages: any::covr, any::xml2
28 | needs: coverage
29 |
30 | - name: Test coverage
31 | run: |
32 | cov <- covr::package_coverage(
33 | quiet = FALSE,
34 | clean = FALSE,
35 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
36 | )
37 | print(cov)
38 | covr::to_cobertura(cov)
39 | shell: Rscript {0}
40 |
41 | - uses: codecov/codecov-action@v5
42 | with:
43 | # Fail if error if not on PR, or if on PR and token is given
44 | fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
45 | files: ./cobertura.xml
46 | plugins: noop
47 | disable_search: true
48 | token: ${{ secrets.CODECOV_TOKEN }}
49 |
50 | - name: Show testthat output
51 | if: always()
52 | run: |
53 | ## --------------------------------------------------------------------
54 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
55 | shell: bash
56 |
57 | - name: Upload test results
58 | if: failure()
59 | uses: actions/upload-artifact@v4
60 | with:
61 | name: coverage-test-failures
62 | path: ${{ runner.temp }}/package
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | .Ruserdata
5 | *.log
6 | src/Makevars
7 | nanonext.Rcheck/00_pkg_src/nanonext/
8 | nanonext.Rcheck/
9 | *.gz
10 | docs
11 | install
12 | inst/doc
13 | compile_commands.json
14 | .cache
15 | revdep/
16 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Type: Package
2 | Package: nanonext
3 | Title: NNG (Nanomsg Next Gen) Lightweight Messaging Library
4 | Version: 1.6.0.9001
5 | Authors@R: c(
6 | person("Charlie", "Gao", , "charlie.gao@posit.co", role = c("aut", "cre"),
7 | comment = c(ORCID = "0000-0002-0750-061X")),
8 | person("Posit Software, PBC", role = c("cph", "fnd"),
9 | comment = c(ROR = "03wc8by49")),
10 | person("Hibiki AI Limited", role = "cph"),
11 | person("R Consortium", role = "fnd")
12 | )
13 | Description: R binding for NNG (Nanomsg Next Gen), a successor to ZeroMQ.
14 | NNG is a socket library for reliable, high-performance messaging over
15 | in-process, IPC, TCP, WebSocket and secure TLS transports. Implements
16 | 'Scalability Protocols', a standard for common communications patterns
17 | including publish/subscribe, request/reply and service discovery. As
18 | its own threaded concurrency framework, provides a toolkit for
19 | asynchronous programming and distributed computing. Intuitive 'aio'
20 | objects resolve automatically when asynchronous operations complete,
21 | and synchronisation primitives allow R to wait upon events signalled
22 | by concurrent threads.
23 | License: MIT + file LICENSE
24 | URL: https://nanonext.r-lib.org, https://github.com/r-lib/nanonext
25 | BugReports: https://github.com/r-lib/nanonext/issues
26 | Depends:
27 | R (>= 3.6)
28 | Suggests:
29 | later,
30 | litedown
31 | Enhances:
32 | promises
33 | VignetteBuilder:
34 | litedown
35 | Biarch: true
36 | Config/build/compilation-database: true
37 | Config/Needs/website: tidyverse/tidytemplate
38 | Config/usethis/last-upkeep: 2025-04-23
39 | Encoding: UTF-8
40 | Roxygen: list(markdown = TRUE)
41 | RoxygenNote: 7.3.2.9000
42 | SystemRequirements: 'libnng' >= 1.9 and 'libmbedtls' >= 2.5, or 'cmake'
43 | and 'xz' to compile NNG and/or Mbed TLS included in package sources
44 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2025
2 | COPYRIGHT HOLDER: nanonext authors
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2025 nanonext authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | S3method("$",nano)
4 | S3method("$<-",nano)
5 | S3method("$<-",nanoObject)
6 | S3method("$<-",recvAio)
7 | S3method("$<-",sendAio)
8 | S3method("[",nano)
9 | S3method("[",recvAio)
10 | S3method("[",sendAio)
11 | S3method("[[",nano)
12 | S3method(close,nanoContext)
13 | S3method(close,nanoDialer)
14 | S3method(close,nanoListener)
15 | S3method(close,nanoSocket)
16 | S3method(close,nanoStream)
17 | S3method(close,ncurlSession)
18 | S3method(print,conditionVariable)
19 | S3method(print,errorValue)
20 | S3method(print,nanoContext)
21 | S3method(print,nanoDialer)
22 | S3method(print,nanoListener)
23 | S3method(print,nanoMonitor)
24 | S3method(print,nanoObject)
25 | S3method(print,nanoSocket)
26 | S3method(print,nanoStream)
27 | S3method(print,ncurlAio)
28 | S3method(print,ncurlSession)
29 | S3method(print,recvAio)
30 | S3method(print,sendAio)
31 | S3method(print,tlsConfig)
32 | S3method(print,unresolvedValue)
33 | S3method(promises::as.promise,ncurlAio)
34 | S3method(promises::as.promise,recvAio)
35 | S3method(promises::is.promising,ncurlAio)
36 | S3method(promises::is.promising,recvAio)
37 | S3method(stats::start,nanoDialer)
38 | S3method(stats::start,nanoListener)
39 | S3method(utils::.DollarNames,nano)
40 | S3method(utils::.DollarNames,ncurlAio)
41 | S3method(utils::.DollarNames,recvAio)
42 | S3method(utils::.DollarNames,sendAio)
43 | export("%~>%")
44 | export("opt<-")
45 | export(.advance)
46 | export(.context)
47 | export(.interrupt)
48 | export(.keep)
49 | export(.mark)
50 | export(.read_header)
51 | export(.read_marker)
52 | export(.unresolved)
53 | export(call_aio)
54 | export(call_aio_)
55 | export(collect_aio)
56 | export(collect_aio_)
57 | export(context)
58 | export(cv)
59 | export(cv_reset)
60 | export(cv_signal)
61 | export(cv_value)
62 | export(dial)
63 | export(ip_addr)
64 | export(is_aio)
65 | export(is_error_value)
66 | export(is_nano)
67 | export(is_ncurl_session)
68 | export(is_nul_byte)
69 | export(listen)
70 | export(mclock)
71 | export(messenger)
72 | export(monitor)
73 | export(msleep)
74 | export(nano)
75 | export(ncurl)
76 | export(ncurl_aio)
77 | export(ncurl_session)
78 | export(nng_error)
79 | export(nng_version)
80 | export(opt)
81 | export(parse_url)
82 | export(pipe_id)
83 | export(pipe_notify)
84 | export(random)
85 | export(read_monitor)
86 | export(read_stdin)
87 | export(reap)
88 | export(recv)
89 | export(recv_aio)
90 | export(reply)
91 | export(request)
92 | export(send)
93 | export(send_aio)
94 | export(serial_config)
95 | export(socket)
96 | export(stat)
97 | export(status_code)
98 | export(stop_aio)
99 | export(stream)
100 | export(subscribe)
101 | export(survey_time)
102 | export(tls_config)
103 | export(transact)
104 | export(unresolved)
105 | export(unsubscribe)
106 | export(until)
107 | export(until_)
108 | export(wait)
109 | export(wait_)
110 | export(write_cert)
111 | export(write_stdout)
112 | useDynLib(nanonext, .registration = TRUE)
113 |
--------------------------------------------------------------------------------
/R/listdial.R:
--------------------------------------------------------------------------------
1 | # nanonext - Listeners / Dialers -----------------------------------------------
2 |
3 | #' Dial an Address from a Socket
4 | #'
5 | #' Creates a new Dialer and binds it to a Socket.
6 | #'
7 | #' To view all Dialers bound to a socket use `$dialer` on the socket, which
8 | #' returns a list of Dialer objects. To access any individual Dialer (e.g. to
9 | #' set options on it), index into the list e.g. `$dialer[[1]]` to return the
10 | #' first Dialer.
11 | #'
12 | #' A Dialer is an external pointer to a dialer object, which creates a single
13 | #' outgoing connection at a time. If the connection is broken, or fails, the
14 | #' dialer object will automatically attempt to reconnect, and will keep doing so
15 | #' until the dialer or socket is destroyed.
16 | #'
17 | #' @param socket a Socket.
18 | #' @param url \[default 'inproc://nanonext'\] a URL to dial, specifying the
19 | #' transport and address as a character string e.g. 'inproc://anyvalue' or
20 | #' 'tcp://127.0.0.1:5555' (see [transports]).
21 | #' @param tls \[default NULL\] for secure tls+tcp:// or wss:// connections only,
22 | #' provide a TLS configuration object created by [tls_config()].
23 | #' @param autostart \[default TRUE\] whether to start the dialer (by default
24 | #' asynchronously). Set to NA to start synchronously - this is less resilient
25 | #' if a connection is not immediately possible, but avoids subtle errors from
26 | #' attempting to use the socket before an asynchronous dial has completed. Set
27 | #' to FALSE if setting configuration options on the dialer as it is not
28 | #' generally possible to change these once started.
29 | #' @param fail \[default 'warn'\] failure mode - a character value or integer
30 | #' equivalent, whether to warn (1L), error (2L), or for none (3L) just return
31 | #' an 'errorValue' without any corresponding warning.
32 | #'
33 | #' @return Invisibly, an integer exit code (zero on success). A new Dialer
34 | #' (object of class 'nanoDialer' and 'nano') is created and bound to the
35 | #' Socket if successful.
36 | #'
37 | #' @section Further details:
38 | #'
39 | #' Dialers and Listeners are always associated with a single socket. A given
40 | #' socket may have multiple Listeners and/or multiple Dialers.
41 | #'
42 | #' The client/server relationship described by dialer/listener is completely
43 | #' orthogonal to any similar relationship in the protocols. For example, a rep
44 | #' socket may use a dialer to connect to a listener on an req socket. This
45 | #' orthogonality can lead to innovative solutions to otherwise challenging
46 | #' communications problems.
47 | #'
48 | #' Any configuration options on the dialer/listener should be set by [opt<-()]
49 | #' before starting the dialer/listener with [start()].
50 | #'
51 | #' Dialers/Listeners may be destroyed by [close()]. They are also closed when
52 | #' their associated socket is closed.
53 | #'
54 | #' @examples
55 | #' socket <- socket("rep")
56 | #' dial(socket, url = "inproc://nanodial", autostart = FALSE)
57 | #' socket$dialer
58 | #' start(socket$dialer[[1]])
59 | #' socket$dialer
60 | #' close(socket$dialer[[1]])
61 | #' close(socket)
62 | #'
63 | #' nano <- nano("bus")
64 | #' nano$dial(url = "inproc://nanodial", autostart = FALSE)
65 | #' nano$dialer
66 | #' nano$dialer_start()
67 | #' nano$dialer
68 | #' close(nano$dialer[[1]])
69 | #' nano$close()
70 | #'
71 | #' @export
72 | #'
73 | dial <- function(socket, url = "inproc://nanonext", tls = NULL, autostart = TRUE, fail = c("warn", "error", "none"))
74 | invisible(.Call(rnng_dial, socket, url, tls, autostart, fail))
75 |
76 | #' Listen to an Address from a Socket
77 | #'
78 | #' Creates a new Listener and binds it to a Socket.
79 | #'
80 | #' To view all Listeners bound to a socket use `$listener` on the socket,
81 | #' which returns a list of Listener objects. To access any individual Listener
82 | #' (e.g. to set options on it), index into the list e.g. `$listener[[1]]`
83 | #' to return the first Listener.
84 | #'
85 | #' A listener is an external pointer to a listener object, which accepts
86 | #' incoming connections. A given listener object may have many connections at
87 | #' the same time, much like an HTTP server can have many connections to multiple
88 | #' clients simultaneously.
89 | #'
90 | #' @inheritParams dial
91 | #' @param autostart \[default TRUE\] whether to start the listener. Set to FALSE
92 | #' if setting configuration options on the listener as it is not generally
93 | #' possible to change these once started.
94 | #'
95 | #' @return Invisibly, an integer exit code (zero on success). A new Listener
96 | #' (object of class 'nanoListener' and 'nano') is created and bound to the
97 | #' Socket if successful.
98 | #'
99 | #' @inheritSection dial Further details
100 | #'
101 | #' @examples
102 | #' socket <- socket("req")
103 | #' listen(socket, url = "inproc://nanolisten", autostart = FALSE)
104 | #' socket$listener
105 | #' start(socket$listener[[1]])
106 | #' socket$listener
107 | #' close(socket$listener[[1]])
108 | #' close(socket)
109 | #'
110 | #' nano <- nano("bus")
111 | #' nano$listen(url = "inproc://nanolisten", autostart = FALSE)
112 | #' nano$listener
113 | #' nano$listener_start()
114 | #' nano$listener
115 | #' close(nano$listener[[1]])
116 | #' nano$close()
117 | #'
118 | #' @export
119 | #'
120 | listen <- function(socket, url = "inproc://nanonext", tls = NULL, autostart = TRUE, fail = c("warn", "error", "none"))
121 | invisible(.Call(rnng_listen, socket, url, tls, autostart, fail))
122 |
123 | #' Start Listener/Dialer
124 | #'
125 | #' Start a Listener/Dialer.
126 | #'
127 | #' @param x a Listener or Dialer.
128 | #' @param async \[default TRUE\] (applicable to Dialers only) logical flag
129 | #' whether the connection attempt, including any name resolution, is to be
130 | #' made asynchronously. This behaviour is more resilient, but also generally
131 | #' makes diagnosing failures somewhat more difficult. If FALSE, failure, such
132 | #' as if the connection is refused, will be returned immediately, and no
133 | #' further action will be taken.
134 | #' @param ... not used.
135 | #'
136 | #' @return Invisibly, an integer exit code (zero on success).
137 | #'
138 | #' @name start
139 | #' @rdname start
140 | #'
141 | NULL
142 |
143 | #' @rdname start
144 | #' @exportS3Method stats::start
145 | #'
146 | start.nanoListener <- function(x, ...)
147 | invisible(.Call(rnng_listener_start, x))
148 |
149 | #' @rdname start
150 | #' @exportS3Method stats::start
151 | #'
152 | start.nanoDialer <- function(x, async = TRUE, ...)
153 | invisible(.Call(rnng_dialer_start, x, async))
154 |
155 | #' @rdname close
156 | #' @method close nanoDialer
157 | #' @export
158 | #'
159 | close.nanoDialer <- function(con, ...)
160 | invisible(.Call(rnng_dialer_close, con))
161 |
162 | #' @rdname close
163 | #' @method close nanoListener
164 | #' @export
165 | #'
166 | close.nanoListener <- function(con, ...)
167 | invisible(.Call(rnng_listener_close, con))
168 |
--------------------------------------------------------------------------------
/R/messenger.R:
--------------------------------------------------------------------------------
1 | # nanonext - Messenger ---------------------------------------------------------
2 |
3 | # nocov start
4 | # tested interactively
5 |
6 | #' Messenger
7 | #'
8 | #' Multi-threaded, console-based, 2-way instant messaging system with
9 | #' authentication, based on NNG scalability protocols.
10 | #'
11 | #' @param url a URL to connect to, specifying the transport and address as a
12 | #' character string e.g. 'tcp://127.0.0.1:5555' (see [transports]).
13 | #' @param auth \[default NULL\] an R object (possessed by both parties) which
14 | #' serves as a pre-shared key on which to authenticate the communication.
15 | #' Note: the object is never sent, only a random subset of its md5 hash after
16 | #' serialization.
17 | #'
18 | #' @return Invisible NULL.
19 | #'
20 | #' @note The authentication protocol is an experimental proof of concept which
21 | #' is not secure, and should not be used for critical applications.
22 | #'
23 | #' @section Usage:
24 | #'
25 | #' Type outgoing messages and hit return to send.
26 | #'
27 | #' The timestamps of outgoing messages are prefixed by `>` and that of
28 | #' incoming messages by `<`.
29 | #'
30 | #' `:q` is the command to quit.
31 | #'
32 | #' Both parties must supply the same argument for `auth`, otherwise the party
33 | #' trying to connect will receive an 'authentication error' and be immediately
34 | #' disconnected.
35 | #'
36 | #' @export
37 | #'
38 | messenger <- function(url, auth = NULL) {
39 | lock <- md5_object(auth)
40 | comb <- order(as.integer(random(20L, convert = FALSE)))
41 | key <- c(comb, as.integer(lock)[comb])
42 |
43 | sock <- .Call(rnng_messenger, url)
44 | on.exit(expr = {
45 | send(sock, data = writeBin(":d ", raw()), mode = 2L, block = FALSE)
46 | reap(sock)
47 | })
48 | cat("\n", file = stdout())
49 | intro <- unlist(strsplit("nanonext messenger", ""))
50 | for (i in seq_along(intro)) {
51 | cat("\r", `length<-`(intro, i), sep = " ", file = stdout())
52 | msleep(32L)
53 | }
54 | cat(sprintf("\n| url: %s\n", url), file = stdout())
55 |
56 | s <- send(sock, data = writeBin(":c ", raw()), mode = 2L, block = FALSE)
57 | if (s) {
58 | length(attr(sock, "dialer")) && {
59 | cat("| connection error... exiting\n", file = stderr())
60 | return(invisible())
61 | }
62 | cat(sprintf("| peer offline: %s\n", format.POSIXct(Sys.time())), file = stderr())
63 | } else {
64 | cat(sprintf("| peer online: %s\n", format.POSIXct(Sys.time())), file = stderr())
65 | r <- recv(sock, mode = 5L, block = TRUE)
66 | for (i in seq_len(20L))
67 | lock[r[i]] == r[i + 20L] || {
68 | cat("| authentication failed\n", file = stderr())
69 | return(invisible())
70 | }
71 | cat("| authenticated\n", file = stderr())
72 | }
73 |
74 | sock <- .External(rnng_messenger_thread_create, sock, key)
75 | cat("type your message:\n", file = stdout())
76 |
77 | repeat {
78 | data <- readline()
79 | if (identical(data, ":q")) break
80 | if (identical(data, "")) next
81 | s <- send(sock, data = data, mode = 2L, block = FALSE)
82 | if (s)
83 | cat(sprintf("%*s > not sent: peer offline: %s\n", nchar(data), "", format.POSIXct(Sys.time())), file = stderr()) else
84 | cat(sprintf("%*s > %s\n", nchar(data), "", format.POSIXct(Sys.time())), file = stdout())
85 | }
86 | }
87 |
88 | # nocov end
89 |
90 | md5_object <- function(x) {
91 | file <- tempfile()
92 | on.exit(unlink(file))
93 | saveRDS(x, file)
94 | charToRaw(tools::md5sum(file))
95 | }
96 |
--------------------------------------------------------------------------------
/R/nanonext-package.R:
--------------------------------------------------------------------------------
1 | # nanonext - Package -----------------------------------------------------------
2 |
3 | #' nanonext: NNG (Nanomsg Next Gen) Lightweight Messaging Library
4 | #'
5 | #' R binding for NNG (Nanomsg Next Gen), a successor to ZeroMQ. NNG is a socket
6 | #' library for reliable, high-performance messaging over in-process, IPC, TCP,
7 | #' WebSocket and secure TLS transports. Implements 'Scalability Protocols', a
8 | #' standard for common communications patterns including publish/subscribe,
9 | #' request/reply and service discovery. As its own threaded concurrency
10 | #' framework, provides a toolkit for asynchronous programming and distributed
11 | #' computing. Intuitive 'aio' objects resolve automatically when asynchronous
12 | #' operations complete, and synchronisation primitives allow R to wait upon
13 | #' events signalled by concurrent threads.
14 | #'
15 | #' @section Usage notes:
16 | #'
17 | #' \pkg{nanonext} offers 2 equivalent interfaces: a functional interface, and an
18 | #' object-oriented interface.
19 | #'
20 | #' The primary object in the functional interface is the Socket. Use [socket()]
21 | #' to create a socket and dial or listen at an address. The socket is then
22 | #' passed as the first argument of subsequent actions such as `send()` or
23 | #' `recv()`.
24 | #'
25 | #' The primary object in the object-oriented interface is the nano object. Use
26 | #' [nano()] to create a nano object which encapsulates a Socket and
27 | #' Dialer/Listener. Methods such as `$send()` or `$recv()` can then be accessed
28 | #' directly from the object.
29 | #'
30 | #' @section Documentation:
31 | #'
32 | #' Guide to the implemented protocols for sockets: [protocols]
33 | #'
34 | #' Guide to the supported transports for dialers and listeners:
35 | #' [transports]
36 | #'
37 | #' Guide to the options that can be inspected and set using: [opt] /
38 | #' [opt<-]
39 | #'
40 | #' @section Reference Manual:
41 | #'
42 | #' `vignette("nanonext", package = "nanonext")`
43 | #'
44 | #' @section Conceptual overview:
45 | #'
46 | #' NNG presents a socket view of networking. A socket implements precisely one
47 | #' protocol, such as 'bus', etc.
48 | #'
49 | #' Each socket can be used to send and receive messages (if the protocol
50 | #' supports it, and implements the appropriate protocol semantics). For example,
51 | #' the 'sub' protocol automatically filters incoming messages to discard topics
52 | #' that have not been subscribed.
53 | #'
54 | #' NNG sockets are message-oriented, and messages are either delivered wholly,
55 | #' or not at all. Partial delivery is not possible. Furthermore, NNG does not
56 | #' provide any other delivery or ordering guarantees: messages may be dropped or
57 | #' reordered (some protocols, such as 'req' may offer stronger guarantees by
58 | #' performing their own retry and validation schemes).
59 | #'
60 | #' Each socket can have zero, one, or many endpoints, which are either listeners
61 | #' or dialers (a given socket may use listeners, dialers, or both). These
62 | #' endpoints provide access to underlying transports, such as TCP, etc.
63 | #'
64 | #' Each endpoint is associated with a URL, which is a service address. For
65 | #' dialers, this is the service address that is contacted, whereas for listeners
66 | #' this is where new connections will be accepted.
67 | #'
68 | #' @section Links:
69 | #'
70 | #' NNG: \cr
71 | #' Mbed TLS:
72 | #'
73 | #' @useDynLib nanonext, .registration = TRUE
74 | #'
75 | "_PACKAGE"
76 |
--------------------------------------------------------------------------------
/R/sendrecv.R:
--------------------------------------------------------------------------------
1 | # nanonext - Core Functions - send/recv ----------------------------------------
2 |
3 | #' Send
4 | #'
5 | #' Send data over a connection (Socket, Context or Stream).
6 | #'
7 | #' @param con a Socket, Context or Stream.
8 | #' @param data an object (a vector, if `mode = "raw"`).
9 | #' @param mode \[default 'serial'\] character value or integer equivalent -
10 | #' either `"serial"` (1L) to send serialised R objects, or `"raw"` (2L) to
11 | #' send atomic vectors of any type as a raw byte vector. For Streams, `"raw"`
12 | #' is the only option and this argument is ignored.
13 | #' @param block \[default NULL\] which applies the connection default (see
14 | #' section 'Blocking' below). Specify logical `TRUE` to block until successful
15 | #' or `FALSE` to return immediately even if unsuccessful (e.g. if no
16 | #' connection is available), or else an integer value specifying the maximum
17 | #' time to block in milliseconds, after which the operation will time out.
18 | #' @param pipe \[default 0L\] only applicable to Sockets using the 'poly'
19 | #' protocol, an integer pipe ID if directing the send via a specific pipe.
20 | #'
21 | #' @return An integer exit code (zero on success).
22 | #'
23 | #' @section Blocking:
24 | #'
25 | #' For Sockets and Contexts: the default behaviour is non-blocking with
26 | #' `block = FALSE`. This will return immediately with an error if the message
27 | #' could not be queued for sending. Certain protocol / transport combinations
28 | #' may limit the number of messages that can be queued if they have yet to be
29 | #' received.
30 | #'
31 | #' For Streams: the default behaviour is blocking with `block = TRUE`. This will
32 | #' wait until the send has completed. Set a timeout to ensure that the function
33 | #' returns under all scenarios. As the underlying implementation uses an
34 | #' asynchronous send with a wait, it is recommended to set a small positive
35 | #' value for `block` rather than `FALSE`.
36 | #'
37 | #' @section Send Modes:
38 | #'
39 | #' The default mode `"serial"` sends serialised R objects to ensure perfect
40 | #' reproducibility within R. When receiving, the corresponding mode `"serial"`
41 | #' should be used. Custom serialization and unserialization functions for
42 | #' reference objects may be enabled by the function [serial_config()].
43 | #'
44 | #' Mode `"raw"` sends atomic vectors of any type as a raw byte vector, and must
45 | #' be used when interfacing with external applications or raw system sockets,
46 | #' where R serialization is not in use. When receiving, the mode corresponding
47 | #' to the vector sent should be used.
48 | #'
49 | #' @seealso [send_aio()] for asynchronous send.
50 | #'
51 | #' @examples
52 | #' pub <- socket("pub", dial = "inproc://nanonext")
53 | #'
54 | #' send(pub, data.frame(a = 1, b = 2))
55 | #' send(pub, c(10.1, 20.2, 30.3), mode = "raw", block = 100)
56 | #'
57 | #' close(pub)
58 | #'
59 | #' req <- socket("req", listen = "inproc://nanonext")
60 | #' rep <- socket("rep", dial = "inproc://nanonext")
61 | #'
62 | #' ctx <- context(req)
63 | #' send(ctx, data.frame(a = 1, b = 2), block = 100)
64 | #'
65 | #' msg <- recv_aio(rep, timeout = 100)
66 | #' send(ctx, c(1.1, 2.2, 3.3), mode = "raw", block = 100)
67 | #'
68 | #' close(req)
69 | #' close(rep)
70 | #'
71 | #' @export
72 | #'
73 | send <- function(con, data, mode = c("serial", "raw"), block = NULL, pipe = 0L)
74 | .Call(rnng_send, con, data, mode, block, pipe)
75 |
76 | #' Receive
77 | #'
78 | #' Receive data over a connection (Socket, Context or Stream).
79 | #'
80 | #' @inheritParams send
81 | #' @param mode \[default 'serial'\] character value or integer equivalent - one
82 | #' of `"serial"` (1L), `"character"` (2L), `"complex"` (3L), `"double"` (4L),
83 | #' `"integer"` (5L), `"logical"` (6L), `"numeric"` (7L), `"raw"` (8L), or
84 | #' `"string"` (9L). The default `"serial"` means a serialised R object; for
85 | #' the other modes, received bytes are converted into the respective mode.
86 | #' `"string"` is a faster option for length one character vectors. For
87 | #' Streams, `"serial"` will default to `"character"`.
88 | #' @param n \[default 65536L\] applicable to Streams only, the maximum number of
89 | #' bytes to receive. Can be an over-estimate, but note that a buffer of this
90 | #' size is reserved.
91 | #'
92 | #' @return The received data in the `mode` specified.
93 | #'
94 | #' @section Errors:
95 | #'
96 | #' In case of an error, an integer 'errorValue' is returned (to be
97 | #' distiguishable from an integer message value). This can be verified using
98 | #' [is_error_value()].
99 | #'
100 | #' If an error occurred in unserialization or conversion of the message data to
101 | #' the specified mode, a raw vector will be returned instead to allow recovery
102 | #' (accompanied by a warning).
103 | #'
104 | #' @section Blocking:
105 | #'
106 | #' For Sockets and Contexts: the default behaviour is non-blocking with
107 | #' `block = FALSE`. This will return immediately with an error if no messages
108 | #' are available.
109 | #'
110 | #' For Streams: the default behaviour is blocking with `block = TRUE`. This will
111 | #' wait until a message is received. Set a timeout to ensure that the function
112 | #' returns under all scenarios. As the underlying implementation uses an
113 | #' asynchronous receive with a wait, it is recommended to set a small positive
114 | #' value for `block` rather than `FALSE`.
115 | #'
116 | #' @seealso [recv_aio()] for asynchronous receive.
117 | #'
118 | #' @examples
119 | #' s1 <- socket("pair", listen = "inproc://nanonext")
120 | #' s2 <- socket("pair", dial = "inproc://nanonext")
121 | #'
122 | #' send(s1, data.frame(a = 1, b = 2))
123 | #' res <- recv(s2)
124 | #' res
125 | #' send(s1, data.frame(a = 1, b = 2))
126 | #' recv(s2)
127 | #'
128 | #' send(s1, c(1.1, 2.2, 3.3), mode = "raw")
129 | #' res <- recv(s2, mode = "double", block = 100)
130 | #' res
131 | #' send(s1, "example message", mode = "raw")
132 | #' recv(s2, mode = "character")
133 | #'
134 | #' close(s1)
135 | #' close(s2)
136 | #'
137 | #' req <- socket("req", listen = "inproc://nanonext")
138 | #' rep <- socket("rep", dial = "inproc://nanonext")
139 | #'
140 | #' ctxq <- context(req)
141 | #' ctxp <- context(rep)
142 | #' send(ctxq, data.frame(a = 1, b = 2), block = 100)
143 | #' recv(ctxp, block = 100)
144 | #'
145 | #' send(ctxq, c(1.1, 2.2, 3.3), mode = "raw", block = 100)
146 | #' recv(ctxp, mode = "double", block = 100)
147 | #'
148 | #' close(req)
149 | #' close(rep)
150 | #'
151 | #' @export
152 | #'
153 | recv <- function(
154 | con,
155 | mode = c("serial", "character", "complex", "double", "integer", "logical", "numeric", "raw", "string"),
156 | block = NULL,
157 | n = 65536L
158 | )
159 | .Call(rnng_recv, con, mode, block, n)
160 |
--------------------------------------------------------------------------------
/R/socket.R:
--------------------------------------------------------------------------------
1 | # nanonext - Core - Sockets ----------------------------------------------------
2 |
3 | #' Open Socket
4 | #'
5 | #' Open a Socket implementing `protocol`, and optionally dial (establish an
6 | #' outgoing connection) or listen (accept an incoming connection) at an address.
7 | #'
8 | #' NNG presents a socket view of networking. The sockets are constructed using
9 | #' protocol-specific functions, as a given socket implements precisely one
10 | #' protocol.
11 | #'
12 | #' Each socket may be used to send and receive messages (if the protocol
13 | #' supports it, and implements the appropriate protocol semantics). For example,
14 | #' sub sockets automatically filter incoming messages to discard those for
15 | #' topics that have not been subscribed.
16 | #'
17 | #' This function (optionally) binds a single Dialer and/or Listener to a Socket.
18 | #' More complex network topologies may be created by binding further Dialers /
19 | #' Listeners to the Socket as required using [dial()] and [listen()].
20 | #'
21 | #' New contexts may also be created using [context()] if the protocol supports
22 | #' it.
23 | #'
24 | #' @param protocol \[default 'bus'\] choose protocol - `"bus"`, `"pair"`,
25 | #' `"poly"`, `"push"`, `"pull"`, `"pub"`, `"sub"`, `"req"`, `"rep"`,
26 | #' `"surveyor"`, or `"respondent"` - see [protocols].
27 | #' @param dial (optional) a URL to dial, specifying the transport and address as
28 | #' a character string e.g. 'inproc://anyvalue' or 'tcp://127.0.0.1:5555' (see
29 | #' [transports]).
30 | #' @param listen (optional) a URL to listen at, specifying the transport and
31 | #' address as a character string e.g. 'inproc://anyvalue' or
32 | #' 'tcp://127.0.0.1:5555' (see [transports]).
33 | #' @param autostart \[default TRUE\] whether to start the dialer/listener. Set
34 | #' to FALSE if setting configuration options on the dialer/listener as it is
35 | #' not generally possible to change these once started. For dialers only: set
36 | #' to NA to start synchronously - this is less resilient if a connection is
37 | #' not immediately possible, but avoids subtle errors from attempting to use
38 | #' the socket before an asynchronous dial has completed.
39 | #' @param raw \[default FALSE\] whether to open raw mode sockets. Note: not for
40 | #' general use - do not enable unless you have a specific need (refer to NNG
41 | #' documentation).
42 | #' @inheritParams dial
43 | #'
44 | #' @return A Socket (object of class 'nanoSocket' and 'nano').
45 | #'
46 | #' @section Protocols:
47 | #'
48 | #' The following Scalability Protocols (communication patterns) are implemented:
49 | #' \itemize{
50 | #' \item Bus (mesh networks) - protocol: 'bus'
51 | #' \item Pair (two-way radio) - protocol: 'pair'
52 | #' \item Poly (one-to-one of many) - protocol: 'poly'
53 | #' \item Pipeline (one-way pipe) - protocol: 'push', 'pull'
54 | #' \item Publisher/Subscriber (topics & broadcast) - protocol: 'pub', 'sub'
55 | #' \item Request/Reply (RPC) - protocol: 'req', 'rep'
56 | #' \item Survey (voting & service discovery) - protocol: 'surveyor',
57 | #' 'respondent'
58 | #' }
59 | #'
60 | #' Please see [protocols] for further documentation.
61 | #'
62 | #' @section Transports:
63 | #'
64 | #' The following communications transports may be used:
65 | #'
66 | #' \itemize{
67 | #' \item Inproc (in-process) - url: 'inproc://'
68 | #' \item IPC (inter-process communications) - url: 'ipc://' (or 'abstract://'
69 | #' on Linux)
70 | #' \item TCP and TLS over TCP - url: 'tcp://' and 'tls+tcp://'
71 | #' \item WebSocket and TLS over WebSocket - url: 'ws://' and 'wss://'
72 | #' }
73 | #'
74 | #' Please see [transports] for further documentation.
75 | #'
76 | #' @examples
77 | #' s <- socket(protocol = "req", listen = "inproc://nanosocket")
78 | #' s
79 | #' s1 <- socket(protocol = "rep", dial = "inproc://nanosocket")
80 | #' s1
81 | #'
82 | #' send(s, "hello world!")
83 | #' recv(s1)
84 | #'
85 | #' close(s1)
86 | #' close(s)
87 | #'
88 | #' @export
89 | #'
90 | socket <- function(
91 | protocol = c("bus", "pair", "poly", "push", "pull", "pub", "sub", "req", "rep", "surveyor", "respondent"),
92 | dial = NULL,
93 | listen = NULL,
94 | tls = NULL,
95 | autostart = TRUE,
96 | raw = FALSE
97 | )
98 | .Call(rnng_protocol_open, protocol, dial, listen, tls, autostart, raw)
99 |
100 | #' Close Connection
101 | #'
102 | #' Close Connection on a Socket, Context, Dialer, Listener, Stream, Pipe, or
103 | #' ncurl Session.
104 | #'
105 | #' Closing an object explicitly frees its resources. An object can also be
106 | #' removed directly in which case its resources are freed when the object is
107 | #' garbage collected.
108 | #'
109 | #' Closing a Socket associated with a Context also closes the Context.
110 | #'
111 | #' Dialers and Listeners are implicitly closed when the Socket they are
112 | #' associated with is closed.
113 | #'
114 | #' Closing a Socket or a Context: messages that have been submitted for sending
115 | #' may be flushed or delivered, depending upon the transport. Closing the Socket
116 | #' while data is in transmission will likely lead to loss of that data. There is
117 | #' no automatic linger or flush to ensure that the Socket send buffers have
118 | #' completely transmitted.
119 | #'
120 | #' Closing a Stream: if any send or receive operations are pending, they will be
121 | #' terminated and any new operations will fail after the connection is closed.
122 | #'
123 | #' Closing an 'ncurlSession' closes the http(s) connection.
124 | #'
125 | #' @param con a Socket, Context, Dialer, Listener, Stream, or 'ncurlSession'.
126 | #' @param ... not used.
127 | #'
128 | #' @return Invisibly, an integer exit code (zero on success).
129 | #'
130 | #' @seealso [reap()]
131 | #'
132 | #' @name close
133 | #' @rdname close
134 | #'
135 | NULL
136 |
137 | #' @rdname close
138 | #' @method close nanoSocket
139 | #' @export
140 | #'
141 | close.nanoSocket <- function(con, ...) invisible(.Call(rnng_close, con))
142 |
143 | #' Reap
144 | #'
145 | #' An alternative to `close` for Sockets, Contexts, Listeners, and Dialers
146 | #' avoiding S3 method dispatch.
147 | #'
148 | #' May be used on unclassed external pointers e.g. those created by
149 | #' [.context()]. Returns silently and does not warn or error, nor does it update
150 | #' the state of object attributes.
151 | #'
152 | #' @param con a Socket, Context, Listener or Dialer.
153 | #'
154 | #' @return An integer exit code (zero on success).
155 | #'
156 | #' @seealso [close()]
157 | #'
158 | #' @examples
159 | #' s <- socket("req")
160 | #' listen(s)
161 | #' dial(s)
162 | #' ctx <- .context(s)
163 | #'
164 | #' reap(ctx)
165 | #' reap(s[["dialer"]][[1]])
166 | #' reap(s[["listener"]][[1]])
167 | #' reap(s)
168 | #' reap(s)
169 | #'
170 | #' @export
171 | #'
172 | reap <- function(con) .Call(rnng_reap, con)
173 |
174 | #' Monitor a Socket for Pipe Changes
175 | #'
176 | #' This function monitors pipe additions and removals from a socket.
177 | #'
178 | #' @param sock a Socket.
179 | #' @param cv a 'conditionVariable'.
180 | #'
181 | #' @return For `monitor`: a Monitor (object of class 'nanoMonitor'). \cr
182 | #' For `read_monitor`: an integer vector of pipe IDs (positive if added,
183 | #' negative if removed), or else NULL if there were no changes since the
184 | #' previous read.
185 | #'
186 | #' @examples
187 | #' cv <- cv()
188 | #' s <- socket("poly")
189 | #' s1 <- socket("poly")
190 | #'
191 | #' m <- monitor(s, cv)
192 | #' m
193 | #'
194 | #' listen(s)
195 | #' dial(s1)
196 | #'
197 | #' cv_value(cv)
198 | #' read_monitor(m)
199 | #'
200 | #' close(s)
201 | #' close(s1)
202 | #'
203 | #' read_monitor(m)
204 | #'
205 | #' @export
206 | #'
207 | monitor <- function(sock, cv) .Call(rnng_monitor_create, sock, cv)
208 |
209 | #' @param x a Monitor.
210 | #'
211 | #' @rdname monitor
212 | #' @export
213 | #'
214 | read_monitor <- function(x) .Call(rnng_monitor_read, x)
215 |
--------------------------------------------------------------------------------
/R/stats.R:
--------------------------------------------------------------------------------
1 | # nanonext - Stats -------------------------------------------------------------
2 |
3 | #' Get Statistic for a Socket, Listener or Dialer
4 | #'
5 | #' Obtain value of a statistic for a Socket, Listener or Dialer. This function
6 | #' exposes the stats interface of NNG.
7 | #'
8 | #' Note: the values of individual statistics are guaranteed to be atomic, but
9 | #' due to the way statistics are collected there may be discrepancies between
10 | #' them at times. For example, statistics counting bytes and messages received
11 | #' may not reflect the same number of messages, depending on when the snapshot
12 | #' is taken. This potential inconsistency arises as a result of optimisations to
13 | #' minimise the impact of statistics on actual operations.
14 | #'
15 | #' @param object a Socket, Listener or Dialer.
16 | #' @param name character name of statistic to return.
17 | #'
18 | #' @return The value of the statistic (character or double depending on the type
19 | #' of statistic requested) if available, or else NULL.
20 | #'
21 | #' @section Stats:
22 | #'
23 | #' The following stats may be requested for a Socket:
24 | #' \itemize{
25 | #' \item 'id' - numeric id of the socket.
26 | #' \item 'name' - character socket name.
27 | #' \item 'protocol' - character protocol type e.g. 'bus'.
28 | #' \item 'pipes' - numeric number of pipes (active connections).
29 | #' \item 'dialers' - numeric number of listeners attached to the socket.
30 | #' \item 'listeners' - numeric number of dialers attached to the socket.
31 | #' }
32 | #'
33 | #' The following stats may be requested for a Listener / Dialer:
34 | #' \itemize{
35 | #' \item 'id' - numeric id of the listener / dialer.
36 | #' \item 'socket' - numeric id of the socket of the listener / dialer.
37 | #' \item 'url' - character URL address.
38 | #' \item 'pipes' - numeric number of pipes (active connections).
39 | #' }
40 | #'
41 | #' The following additional stats may be requested for a Listener:
42 | #' \itemize{
43 | #' \item 'accept' - numeric total number of connection attempts, whether
44 | #' successful or not.
45 | #' \item 'reject' - numeric total number of rejected connection attempts e.g.
46 | #' due to incompatible protocols.
47 | #' }
48 | #'
49 | #' The following additional stats may be requested for a Dialer:
50 | #' \itemize{
51 | #' \item 'connect' - numeric total number of connection attempts, whether
52 | #' successful or not.
53 | #' \item 'reject' - numeric total number of rejected connection attempts e.g.
54 | #' due to incompatible protocols.
55 | #' \item 'refused' - numeric total number of refused connections e.g. when
56 | #' starting synchronously with no listener on the other side.
57 | #' }
58 | #'
59 | #' @examples
60 | #' s <- socket("bus", listen = "inproc://stats")
61 | #' stat(s, "pipes")
62 | #'
63 | #' s1 <- socket("bus", dial = "inproc://stats")
64 | #' stat(s, "pipes")
65 | #'
66 | #' close(s1)
67 | #' stat(s, "pipes")
68 | #'
69 | #' close(s)
70 | #'
71 | #' @export
72 | #'
73 | stat <- function(object, name) .Call(rnng_stats_get, object, name)
74 |
--------------------------------------------------------------------------------
/R/stream.R:
--------------------------------------------------------------------------------
1 | # nanonext - Byte Stream Interface ---------------------------------------------
2 |
3 | #' Open Stream
4 | #'
5 | #' Open a Stream by either dialing (establishing an outgoing connection) or
6 | #' listening (accepting an incoming connection) at an address. This is a
7 | #' low-level interface intended for communicating with non-NNG endpoints.
8 | #'
9 | #' A Stream is used for raw byte stream connections. Byte streams are reliable
10 | #' in that data will not be delivered out of order, or with portions missing.
11 | #'
12 | #' Can be used to dial a (secure) websocket address starting 'ws://' or
13 | #' 'wss://'. It is often the case that `textframes` needs to be set to `TRUE`.
14 | #'
15 | #' Specify only one of `dial` or `listen`. If both are specified, `listen` will
16 | #' be ignored.
17 | #'
18 | #' Closing a stream renders it invalid and attempting to perform additional
19 | #' operations on it will error.
20 | #'
21 | #' @param dial a URL to dial, specifying the transport and address as a
22 | #' character string e.g. 'ipc:///tmp/anyvalue' or 'tcp://127.0.0.1:5555' (not
23 | #' all transports are supported).
24 | #' @param listen a URL to listen at, specifying the transport and address as a
25 | #' character string e.g. 'ipc:///tmp/anyvalue' or 'tcp://127.0.0.1:5555' (not
26 | #' all transports are supported).
27 | #' @param textframes \[default FALSE\] applicable to the websocket transport
28 | #' only, enables sending and receiving of TEXT frames (ignored otherwise).
29 | #' @param tls (optional) applicable to secure websockets only, a client or
30 | #' server TLS configuration object created by [tls_config()]. If missing or
31 | #' NULL, certificates are not validated.
32 | #'
33 | #' @return A Stream (object of class 'nanoStream' and 'nano').
34 | #'
35 | #' @examples
36 | #' # Will succeed only if there is an open connection at the address:
37 | #' s <- tryCatch(stream(dial = "tcp://127.0.0.1:5555"), error = identity)
38 | #' s
39 | #' @examplesIf interactive()
40 | #' # Run in interactive sessions only as connection is not always available:
41 | #' s <- tryCatch(
42 | #' stream(dial = "wss://echo.websocket.events/", textframes = TRUE),
43 | #' error = identity
44 | #' )
45 | #' s
46 | #' if (is_nano(s)) recv(s)
47 | #' if (is_nano(s)) send(s, "hello")
48 | #' if (is_nano(s)) recv(s)
49 | #' if (is_nano(s)) close(s)
50 | #'
51 | #' @export
52 | #'
53 | stream <- function(dial = NULL, listen = NULL, textframes = FALSE, tls = NULL)
54 | .Call(rnng_stream_open, dial, listen, textframes, tls)
55 |
56 | #' @rdname close
57 | #' @method close nanoStream
58 | #' @export
59 | #'
60 | close.nanoStream <- function(con, ...) invisible(.Call(rnng_stream_close, con))
61 |
--------------------------------------------------------------------------------
/R/sync.R:
--------------------------------------------------------------------------------
1 | # nanonext - Synchronisation Primitives ----------------------------------------
2 |
3 | #' Condition Variables
4 | #'
5 | #' `cv` creates a new condition variable (protected by a mutex internal to the
6 | #' object).
7 | #'
8 | #' Pass the 'conditionVariable' to the asynchronous receive functions
9 | #' [recv_aio()] or [request()]. Alternatively, to be notified of a pipe event,
10 | #' pass it to [pipe_notify()].
11 | #'
12 | #' Completion of the receive or pipe event, which happens asynchronously and
13 | #' independently of the main R thread, will signal the condition variable by
14 | #' incrementing it by 1.
15 | #'
16 | #' This will cause the R execution thread waiting on the condition variable
17 | #' using `wait()` or `until()` to wake and continue.
18 | #'
19 | #' For argument `msec`, non-integer values will be coerced to integer.
20 | #' Non-numeric input will be ignored and return immediately.
21 | #'
22 | #' @return For **cv**: a 'conditionVariable' object.
23 | #'
24 | #' For **wait**: (invisibly) logical TRUE, or else FALSE if a flag has been
25 | #' set.
26 | #'
27 | #' For **until**: (invisibly) logical TRUE if signalled, or else FALSE if the
28 | #' timeout was reached.
29 | #'
30 | #' For **cv_value**: integer value of the condition variable.
31 | #'
32 | #' For **cv_reset** and **cv_signal**: zero (invisibly).
33 | #'
34 | #' @section Condition:
35 | #'
36 | #' The condition internal to this 'conditionVariable' maintains a state (value).
37 | #' Each signal increments the value by 1. Each time `wait()` or `until()`
38 | #' returns (apart from due to timeout), the value is decremented by 1.
39 | #'
40 | #' The internal condition may be inspected at any time using `cv_value()` and
41 | #' reset using `cv_reset()`. This affords a high degree of flexibility in
42 | #' designing complex concurrent applications.
43 | #'
44 | #' @section Flag:
45 | #'
46 | #' The condition variable also contains a flag that certain signalling functions
47 | #' such as [pipe_notify()] can set. When this flag has been set, all subsequent
48 | #' `wait()` calls will return logical FALSE instead of TRUE.
49 | #'
50 | #' Note that the flag is not automatically reset, but may be reset manually
51 | #' using `cv_reset()`.
52 | #'
53 | #' @examples
54 | #' cv <- cv()
55 | #'
56 | #' @export
57 | #'
58 | cv <- function() .Call(rnng_cv_alloc)
59 |
60 | #' Condition Variables - Wait
61 | #'
62 | #' `wait` waits on a condition being signalled by completion of an
63 | #' asynchronous receive or pipe event. \cr `wait_` is a variant that allows
64 | #' user interrupts, suitable for interactive use.
65 | #'
66 | #' @param cv a 'conditionVariable' object.
67 | #'
68 | #' @examples
69 | #' \dontrun{
70 | #' wait(cv) # would block until the cv is signalled
71 | #' wait_(cv) # would block until the cv is signalled or interrupted
72 | #' }
73 | #'
74 | #' @rdname cv
75 | #' @export
76 | #'
77 | wait <- function(cv) invisible(.Call(rnng_cv_wait, cv))
78 |
79 | #' @rdname cv
80 | #' @export
81 | #'
82 | wait_ <- function(cv) invisible(.Call(rnng_cv_wait_safe, cv))
83 |
84 | #' Condition Variables - Until
85 | #'
86 | #' `until` waits until a future time on a condition being signalled by
87 | #' completion of an asynchronous receive or pipe event. \cr `until_` is a
88 | #' variant that allows user interrupts, suitable for interactive use.
89 | #'
90 | #' @param msec maximum time in milliseconds to wait for the condition variable
91 | #' to be signalled.
92 | #'
93 | #' @examples
94 | #' until(cv, 10L)
95 | #' until_(cv, 10L)
96 | #'
97 | #' @rdname cv
98 | #' @export
99 | #'
100 | until <- function(cv, msec) invisible(.Call(rnng_cv_until, cv, msec))
101 |
102 | #' @rdname cv
103 | #' @export
104 | #'
105 | until_ <- function(cv, msec) invisible(.Call(rnng_cv_until_safe, cv, msec))
106 |
107 | #' Condition Variables - Value
108 | #'
109 | #' `cv_value` inspects the internal value of a condition variable.
110 | #'
111 | #' @examples
112 | #' cv_value(cv)
113 | #'
114 | #' @rdname cv
115 | #' @export
116 | #'
117 | cv_value <- function(cv) .Call(rnng_cv_value, cv)
118 |
119 | #' Condition Variables - Reset
120 | #'
121 | #' `cv_reset` resets the internal value and flag of a condition variable.
122 | #'
123 | #' @examples
124 | #' cv_reset(cv)
125 | #'
126 | #' @rdname cv
127 | #' @export
128 | #'
129 | cv_reset <- function(cv) invisible(.Call(rnng_cv_reset, cv))
130 |
131 | #' Condition Variables - Signal
132 | #'
133 | #' `cv_signal` signals a condition variable.
134 | #'
135 | #' @examples
136 | #' cv_value(cv)
137 | #' cv_signal(cv)
138 | #' cv_value(cv)
139 | #'
140 | #' @rdname cv
141 | #' @export
142 | #'
143 | cv_signal <- function(cv) invisible(.Call(rnng_cv_signal, cv))
144 |
145 | #' Pipe Notify
146 | #'
147 | #' Signals a 'conditionVariable' whenever pipes (individual connections) are
148 | #' added or removed at a socket.
149 | #'
150 | #' For add: this event occurs after the pipe is fully added to the socket. Prior
151 | #' to this time, it is not possible to communicate over the pipe with the
152 | #' socket.
153 | #'
154 | #' For remove: this event occurs after the pipe has been removed from the
155 | #' socket. The underlying transport may be closed at this point, and it is not
156 | #' possible to communicate using this pipe.
157 | #'
158 | #' @param socket a Socket.
159 | #' @param cv a 'conditionVariable' to signal, or NULL to cancel a previously set
160 | #' signal.
161 | #' @param add \[default FALSE\] logical value whether to signal (or cancel
162 | #' signal) when a pipe is added.
163 | #' @param remove \[default FALSE\] logical value whether to signal (or cancel
164 | #' signal) when a pipe is removed.
165 | #' @param flag \[default FALSE\] logical value whether to also set a flag in the
166 | #' 'conditionVariable'. This can help distinguish between different types of
167 | #' signal, and causes any subsequent [wait()] to return FALSE instead of TRUE.
168 | #' If a signal from the \pkg{tools} package, e.g. `tools::SIGINT`, or an
169 | #' equivalent integer value is supplied, this sets a flag and additionally
170 | #' raises this signal upon the flag being set.
171 | #'
172 | #' @return Invisibly, zero on success (will otherwise error).
173 | #'
174 | #' @examples
175 | #' s <- socket(listen = "inproc://nanopipe")
176 | #' cv <- cv()
177 | #'
178 | #' pipe_notify(s, cv, add = TRUE, remove = TRUE, flag = TRUE)
179 | #' cv_value(cv)
180 | #'
181 | #' s1 <- socket(dial = "inproc://nanopipe")
182 | #' cv_value(cv)
183 | #' reap(s1)
184 | #' cv_value(cv)
185 | #'
186 | #' pipe_notify(s, NULL, add = TRUE, remove = TRUE)
187 | #' s1 <- socket(dial = "inproc://nanopipe")
188 | #' cv_value(cv)
189 | #' reap(s1)
190 | #'
191 | #' (wait(cv))
192 | #'
193 | #' close(s)
194 | #'
195 | #' @export
196 | #'
197 | pipe_notify <- function(socket, cv, add = FALSE, remove = FALSE, flag = FALSE)
198 | invisible(.Call(rnng_pipe_notify, socket, cv, add, remove, flag))
199 |
200 | #' Signal Forwarder
201 | #'
202 | #' Forwards signals from one 'conditionVariable' to another.
203 | #'
204 | #' The condition value of `cv` is initially reset to zero when this operator
205 | #' returns. Only one forwarder can be active on a `cv` at any given time, and
206 | #' assigning a new forwarding target cancels any currently existing forwarding.
207 | #'
208 | #' Changes in the condition value of `cv` are forwarded to `cv2`, but only on
209 | #' each occassion `cv` is signalled. This means that waiting on `cv` will cause
210 | #' a temporary divergence between the actual condition value of `cv` and that
211 | #' recorded at `cv2`, until the next time `cv` is signalled.
212 | #'
213 | #' @param cv a 'conditionVariable' object, from which to forward the signal.
214 | #' @param cv2 a 'conditionVariable' object, to which the signal is forwarded.
215 | #'
216 | #' @return Invisibly, `cv2`.
217 | #'
218 | #' @examples
219 | #' cva <- cv(); cvb <- cv(); cv1 <- cv(); cv2 <- cv()
220 | #'
221 | #' cva %~>% cv1 %~>% cv2
222 | #' cvb %~>% cv2
223 | #'
224 | #' cv_signal(cva)
225 | #' cv_signal(cvb)
226 | #' cv_value(cv1)
227 | #' cv_value(cv2)
228 | #'
229 | #' @export
230 | #'
231 | `%~>%` <- function(cv, cv2) invisible(.Call(rnng_signal_thread_create, cv, cv2))
232 |
--------------------------------------------------------------------------------
/R/tls.R:
--------------------------------------------------------------------------------
1 | # nanonext - TLS Configuration -------------------------------------------------
2 |
3 | #' Create TLS Configuration
4 | #'
5 | #' Create a TLS configuration object to be used for secure connections. Specify
6 | #' `client` to create a client configuration or `server` to create a server
7 | #' configuration.
8 | #'
9 | #' Specify one of `client` or `server` only, or neither (in which case an empty
10 | #' client configuration is created), as a configuration can only be of one type.
11 | #'
12 | #' For creating client configurations for public internet usage, root CA
13 | #' ceritficates may usually be found at \file{/etc/ssl/certs/ca-certificates.crt}
14 | #' on Linux systems. Otherwise, root CA certificates in PEM format are available
15 | #' at the Common CA Database site run by Mozilla:
16 | #' (select the Server Authentication
17 | #' SSL/TLS certificates text file).
18 | #' *This link is not endorsed; use at your own risk.*
19 | #'
20 | #' @param client **either** the character path to a file containing X.509
21 | #' certificate(s) in PEM format, comprising the certificate authority
22 | #' certificate chain (and revocation list if present), used to validate
23 | #' certificates presented by peers,\cr
24 | #' **or** a length 2 character vector comprising \[i\] the certificate
25 | #' authority certificate chain and \[ii\] the certificate revocation list, or
26 | #' empty string `""` if not applicable.
27 | #' @param server **either** the character path to a file containing the
28 | #' PEM-encoded TLS certificate and associated private key (may contain
29 | #' additional certificates leading to a validation chain, with the leaf
30 | #' certificate first),\cr
31 | #' **or** a length 2 character vector comprising \[i\] the TLS certificate
32 | #' (optionally certificate chain) and \[ii\] the associated private key.
33 | #' @param pass (optional) required only if the secret key supplied to `server`
34 | #' is encrypted with a password. For security, consider providing through a
35 | #' function that returns this value, rather than directly.
36 | #' @param auth logical value whether to require authentication - by default TRUE
37 | #' for client and FALSE for server configurations. If TRUE, the session is
38 | #' only allowed to proceed if the peer has presented a certificate and it has
39 | #' been validated. If FALSE, authentication is optional, whereby a certificate
40 | #' is validated if presented by the peer, but the session allowed to proceed
41 | #' otherwise. If neither `client` nor `server` are supplied, then no
42 | #' authentication is performed and this argument has no effect.
43 | #'
44 | #' @return A 'tlsConfig' object.
45 | #'
46 | #' @examples
47 | #' tls <- tls_config()
48 | #' tls
49 | #' ncurl("https://postman-echo.com/get", timeout = 1000L, tls = tls)
50 | #'
51 | #' @export
52 | #'
53 | tls_config <- function(client = NULL, server = NULL, pass = NULL, auth = is.null(server))
54 | .Call(rnng_tls_config, client, server, pass, auth)
55 |
56 | # nanonext - Key Gen and Certificates ------------------------------------------
57 |
58 | #' Generate Self-Signed Certificate and Key
59 | #'
60 | #' Generate self-signed x509 certificate and 4096 bit RSA private/public key
61 | #' pair for use with authenticated, encrypted TLS communications.
62 | #'
63 | #' Note that it can take a second or two for the key and certificate to be
64 | #' generated.
65 | #'
66 | #' @param cn \[default '127.0.0.1'\] character issuer common name (CN) for the
67 | #' certificate. This can be either a hostname or an IP address, but must match
68 | #' the actual server URL as client authentication will depend on it.
69 | #' @param valid \[default '20301231235959'\] character 'not after' date-time in
70 | #' 'yyyymmddhhmmss' format. The certificate is not valid after this time.
71 | #'
72 | #' @return A list of length 2, comprising `$server` and `$client`. These may be
73 | #' passed directly to the relevant argument of [tls_config()].
74 | #'
75 | #' @examplesIf interactive()
76 | #' cert <- write_cert(cn = "127.0.0.1")
77 | #' ser <- tls_config(server = cert$server)
78 | #' cli <- tls_config(client = cert$client)
79 | #'
80 | #' s <- socket(listen = "tls+tcp://127.0.0.1:5555", tls = ser)
81 | #' s1 <- socket(dial = "tls+tcp://127.0.0.1:5555", tls = cli)
82 | #'
83 | #' # secure TLS connection established
84 | #'
85 | #' close(s1)
86 | #' close(s)
87 | #'
88 | #' cert
89 | #'
90 | #' @export
91 | #'
92 | write_cert <- function(cn = "127.0.0.1", valid = "20301231235959")
93 | .Call(rnng_write_cert, cn, valid)
94 |
--------------------------------------------------------------------------------
/cleanup:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | rm -rf src/Makevars install
3 |
--------------------------------------------------------------------------------
/cleanup.win:
--------------------------------------------------------------------------------
1 | rm -rf src/Makevars install
2 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | comment: false
2 |
3 | coverage:
4 | status:
5 | project:
6 | default:
7 | target: auto
8 | threshold: 1%
9 | informational: true
10 | patch:
11 | default:
12 | target: auto
13 | threshold: 1%
14 | informational: true
15 |
16 | github_checks:
17 | annotations: false
18 |
--------------------------------------------------------------------------------
/configure:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Library versions
4 | LIB_VER="111"
5 | TLS_VER="362"
6 |
7 | # Initialise
8 | PKG_CFLAGS=""
9 | PKG_LIBS=""
10 | MBEDTLS_CFLAGS=""
11 | MBEDTLS_LIBS="-lmbedtls -lmbedx509 -lmbedcrypto"
12 | NNG_CFLAGS=""
13 | NNG_LIBS="-lnng"
14 |
15 | # Find compiler and export flags
16 | CC=`"${R_HOME}/bin/R" CMD config CC`
17 | CFLAGS=`"${R_HOME}/bin/R" CMD config CFLAGS`
18 | LDFLAGS=`"${R_HOME}/bin/R" CMD config LDFLAGS`
19 | export CC CFLAGS LDFLAGS
20 |
21 | if [ -z "$MACOSX_DEPLOYMENT_TARGET" ]; then
22 | export MACOSX_DEPLOYMENT_TARGET=`echo $CC | sed -En 's/.*-version-min=([0-9][0-9.]*).*/\1/p'`
23 | fi
24 |
25 | # Detect -latomic linker flag for ARM architectures (Raspberry Pi etc.)
26 | echo "#include
27 | uint64_t v;
28 | int main() {
29 | return (int)__atomic_load_n(&v, __ATOMIC_ACQUIRE);
30 | }" | ${CC} -xc - -o /dev/null > /dev/null 2>&1
31 | if [ $? -ne 0 ]
32 | then
33 | echo "Adding -latomic linker flag ..."
34 | PKG_LIBS="$PKG_LIBS -latomic"
35 | fi
36 |
37 | # Force build bundled libs
38 | if [ -z "$NANONEXT_LIBS" ]; then
39 |
40 | # Find MbedTLS and compile if necessary
41 | if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]
42 | then
43 | MBEDTLS_CFLAGS="-I$INCLUDE_DIR"
44 | MBEDTLS_LIBS="-L$LIB_DIR $MBEDTLS_LIBS"
45 | echo "Found INCLUDE_DIR $INCLUDE_DIR"
46 | echo "Found LIB_DIR $LIB_DIR"
47 | elif [ -d "/usr/local/include/mbedtls" ]
48 | then
49 | MBEDTLS_CFLAGS="-I/usr/local/include"
50 | MBEDTLS_LIBS="-L/usr/local/lib $MBEDTLS_LIBS"
51 | elif [ -d "/usr/include/mbedtls" ]
52 | then
53 | MBEDTLS_CFLAGS="-I/usr/include"
54 | MBEDTLS_LIBS="-L/usr/lib $MBEDTLS_LIBS"
55 | elif [ -d "/usr/local/opt/mbedtls" ]
56 | then
57 | MBEDTLS_CFLAGS="-I/usr/local/opt/mbedtls/include"
58 | MBEDTLS_LIBS="-L/usr/local/opt/mbedtls/lib $MBEDTLS_LIBS"
59 | fi
60 | echo "#include
61 | int main() {
62 | #if MBEDTLS_VERSION_MAJOR < 2 || MBEDTLS_VERSION_MAJOR == 2 && MBEDTLS_VERSION_MINOR < 5
63 | *(void *) 0 = 0;
64 | #endif
65 | }" | ${CC} ${MBEDTLS_CFLAGS} -xc - -o /dev/null > /dev/null 2>&1
66 |
67 | else
68 | echo "NANONEXT_LIBS is set... skipping detection"
69 | false
70 | fi
71 |
72 | if [ $? -ne 0 ]
73 | then
74 | echo "Existing 'libmbedtls' >= 2.5.0 not found"
75 | echo "Detecting 'cmake'..."
76 | which cmake
77 | if [ $? -ne 0 ]
78 | then
79 | export PATH=$PATH:/Applications/CMake.app/Contents/bin
80 | which cmake
81 | if [ $? -ne 0 ]
82 | then
83 | echo "Required 'cmake' not found"
84 | exit 1
85 | fi
86 | fi
87 | echo "Detecting 'xz'..."
88 | which xz
89 | if [ $? -ne 0 ]
90 | then
91 | tar -xf src/mbedtls-$TLS_VER.tar.xz
92 | if [ $? -ne 0 ]
93 | then
94 | echo "No 'xz' command found"
95 | exit 1
96 | fi
97 | else
98 | xz -dc src/mbedtls-$TLS_VER.tar.xz | tar -xf -
99 | fi
100 | cd mbedtls-$TLS_VER
101 | echo "Compiling 'libmbedtls' from source ..."
102 | cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_INSTALL_LIBDIR=lib .
103 | cmake --build . --target install
104 | cd ..
105 | rm -rf mbedtls-$TLS_VER
106 | else
107 | echo "Found 'libmbedtls' $MBEDTLS_CFLAGS"
108 | PKG_CFLAGS="$MBEDTLS_CFLAGS $PKG_CFLAGS"
109 | PKG_LIBS="$MBEDTLS_LIBS $PKG_LIBS"
110 | fi
111 |
112 | # Force build bundled libs
113 | if [ -z "$NANONEXT_LIBS" ]; then
114 |
115 | # Find NNG and compile if necessary
116 | if [ "$INCLUDE_DIR" ] || [ "$LIB_DIR" ]
117 | then
118 | NNG_CFLAGS="-I$INCLUDE_DIR"
119 | NNG_LIBS="-L$LIB_DIR $NNG_LIBS"
120 | elif [ -d "/usr/local/include/nng" ]
121 | then
122 | NNG_CFLAGS="-I/usr/local/include"
123 | NNG_LIBS="-L/usr/local/lib $NNG_LIBS"
124 | elif [ -d "/usr/include/nng" ]
125 | then
126 | NNG_CFLAGS="-I/usr/include"
127 | NNG_LIBS="-L/usr/lib $NNG_LIBS"
128 | elif [ -d "/usr/local/opt/nng" ]
129 | then
130 | NNG_CFLAGS="-I/usr/local/opt/nng/include"
131 | NNG_LIBS="-L/usr/local/opt/nng/lib $NNG_LIBS"
132 | fi
133 |
134 | echo "#include
135 | int main() {
136 | #if NNG_MAJOR_VERSION < 1 || NNG_MAJOR_VERSION == 1 && NNG_MINOR_VERSION < 9
137 | *(void *) 0 = 0;
138 | #endif
139 | }" | ${CC} ${NNG_CFLAGS} -xc - -o /dev/null > /dev/null 2>&1
140 |
141 | else
142 | echo "NANONEXT_LIBS is set... skipping detection"
143 | false
144 | fi
145 |
146 | if [ $? -ne 0 ]
147 | then
148 | echo "Existing 'libnng' >= 1.9.0 not found"
149 | echo "Detecting 'cmake'..."
150 | which cmake
151 | if [ $? -ne 0 ]
152 | then
153 | export PATH=$PATH:/Applications/CMake.app/Contents/bin
154 | which cmake
155 | if [ $? -ne 0 ]
156 | then
157 | echo "Required 'cmake' not found"
158 | exit 1
159 | fi
160 | fi
161 | echo "Detecting 'xz'..."
162 | which xz
163 | if [ $? -ne 0 ]
164 | then
165 | tar -xf src/nng-$LIB_VER.tar.xz
166 | if [ $? -ne 0 ]
167 | then
168 | echo "No 'xz' command found"
169 | exit 1
170 | fi
171 | else
172 | xz -dc src/nng-$LIB_VER.tar.xz | tar -xf -
173 | fi
174 | cd nng-$LIB_VER
175 | echo "Compiling 'libnng' from source ..."
176 | cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_INSTALL_LIBDIR=lib .
177 | cmake --build . --target install
178 | cd ..
179 | rm -rf nng-$LIB_VER
180 | else
181 | echo "Found 'libnng' $NNG_CFLAGS"
182 | PKG_CFLAGS="$NNG_CFLAGS $PKG_CFLAGS"
183 | PKG_LIBS="$NNG_LIBS $PKG_LIBS"
184 | fi
185 |
186 | if [ -d "install/lib" ]
187 | then
188 | PKG_CFLAGS="-I../install/include $PKG_CFLAGS"
189 | if [ -f "install/lib/libmbedtls.b" ]
190 | then
191 | PKG_LIBS="../install/lib/libnng.b ../install/lib/libmbedtls.b ../install/lib/libmbedx509.b ../install/lib/libmbedcrypto.b $PKG_LIBS"
192 | else
193 | PKG_LIBS="../install/lib/libnng.b $PKG_LIBS"
194 | fi
195 | fi
196 |
197 | # Write to Makevars
198 | sed -e "s|@cflags@|$PKG_CFLAGS|" -e "s|@libs@|$PKG_LIBS|" src/Makevars.in > src/Makevars
199 |
200 | # Success
201 | exit 0
202 |
--------------------------------------------------------------------------------
/configure.ucrt:
--------------------------------------------------------------------------------
1 | # Library versions
2 | LIB_VER="111"
3 | TLS_VER="362"
4 |
5 | # Find compiler and export flags
6 | CC=`"${R_HOME}/bin/R" CMD config CC`
7 | CFLAGS=`"${R_HOME}/bin/R" CMD config CFLAGS`
8 | LDFLAGS=`"${R_HOME}/bin/R" CMD config LDFLAGS`
9 | export CC CFLAGS LDFLAGS
10 |
11 | tar -xf src/mbedtls-$TLS_VER.tar.xz
12 | cd mbedtls-$TLS_VER
13 | echo "Compiling 'libmbedtls' from source ..."
14 | cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=../install .
15 | cmake --build . --target install
16 | cd ..
17 | rm -rf mbedtls-$TLS_VER
18 |
19 | tar -xf src/nng-$LIB_VER.tar.xz
20 | cd nng-$LIB_VER
21 | echo "Compiling 'libnng' from source ..."
22 | cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=../install .
23 | cmake --build . --target install
24 | cd ..
25 | rm -rf nng-$LIB_VER
26 |
27 | # Success
28 | exit 0
29 |
--------------------------------------------------------------------------------
/configure.win:
--------------------------------------------------------------------------------
1 | # Library versions
2 | LIB_VER="111"
3 | TLS_VER="362"
4 |
5 | tar -xf src/mbedtls-$TLS_VER.tar.xz
6 | tar -xf src/nng-$LIB_VER.tar.xz
7 |
8 | for ARCH in x64 i386; do
9 |
10 | if [ -e "${R_HOME}/bin/${ARCH}/R" ]; then
11 | CC=`"${R_HOME}/bin/${ARCH}/R" CMD config CC`
12 | CFLAGS=`"${R_HOME}/bin/${ARCH}/R" CMD config CFLAGS`
13 | LDFLAGS=`"${R_HOME}/bin/${ARCH}/R" CMD config LDFLAGS`
14 | export CC CFLAGS LDFLAGS
15 |
16 | cd mbedtls-$TLS_VER
17 | mkdir ${ARCH}
18 | cd ${ARCH}
19 | echo "Compiling 'libmbedtls' from source for ${ARCH} ..."
20 | cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=../../install/${ARCH} ..
21 | cmake --build . --target install
22 | cd ../..
23 |
24 | cd nng-$LIB_VER
25 | mkdir ${ARCH}
26 | cd ${ARCH}
27 | echo "Compiling 'libnng' from source for ${ARCH} ..."
28 | cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=../../install/${ARCH} ..
29 | cmake --build . --target install
30 | cd ../..
31 |
32 | else
33 | echo "Note: ${ARCH} not installed, skipping ..."
34 | fi
35 |
36 | done
37 |
38 | rm -rf mbedtls-$TLS_VER
39 | rm -rf nng-$LIB_VER
40 |
41 | # Success
42 | exit 0
43 |
--------------------------------------------------------------------------------
/cran-comments.md:
--------------------------------------------------------------------------------
1 | ## R CMD check results
2 |
3 | 0 errors | 0 warnings | 1 note
4 |
5 | Note on CRAN incoming feasibility: change of maintainer email address. I've already emailed cran-submissions about this.
6 |
7 | ## revdepcheck results
8 |
9 | We checked 6 reverse dependencies (6 from CRAN), comparing R CMD check results across CRAN and dev versions of this package.
10 |
11 | * We saw 0 new problems
12 | * We failed to check 0 packages
13 |
--------------------------------------------------------------------------------
/inst/CITATION:
--------------------------------------------------------------------------------
1 | bibentry(bibtype = "Manual",
2 | title = "nanonext: NNG (Nanomsg Next Gen) Lightweight Messaging Library",
3 | author = person("Charlie", "Gao"),
4 | year = 2025,
5 | note = sprintf("R package version %s", meta$Version),
6 | url = "https://doi.org/10.5281/zenodo.7903429")
7 |
--------------------------------------------------------------------------------
/man/as.promise.ncurlAio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ncurl.R
3 | \name{as.promise.ncurlAio}
4 | \alias{as.promise.ncurlAio}
5 | \title{Make ncurlAio Promise}
6 | \usage{
7 | \method{as.promise}{ncurlAio}(x)
8 | }
9 | \arguments{
10 | \item{x}{an object of class 'ncurlAio'.}
11 | }
12 | \value{
13 | A 'promise' object.
14 | }
15 | \description{
16 | Creates a 'promise' from an 'ncurlAio' object.
17 | }
18 | \details{
19 | This function is an S3 method for the generic \code{as.promise} for class
20 | 'ncurlAio'.
21 |
22 | Requires the \pkg{promises} package.
23 |
24 | Allows an 'ncurlAio' to be used with the promise pipe \verb{\%...>\%}, which
25 | schedules a function to run upon resolution of the Aio.
26 | }
27 |
--------------------------------------------------------------------------------
/man/as.promise.recvAio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{as.promise.recvAio}
4 | \alias{as.promise.recvAio}
5 | \title{Make recvAio Promise}
6 | \usage{
7 | \method{as.promise}{recvAio}(x)
8 | }
9 | \arguments{
10 | \item{x}{an object of class 'recvAio'.}
11 | }
12 | \value{
13 | A 'promise' object.
14 | }
15 | \description{
16 | Creates a 'promise' from an 'recvAio' object.
17 | }
18 | \details{
19 | This function is an S3 method for the generic \code{as.promise} for class
20 | 'recvAio'.
21 |
22 | Requires the \pkg{promises} package.
23 |
24 | Allows a 'recvAio' to be used with the promise pipe \verb{\%...>\%}, which schedules
25 | a function to run upon resolution of the Aio.
26 | }
27 |
--------------------------------------------------------------------------------
/man/call_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{call_aio}
4 | \alias{call_aio}
5 | \alias{call_aio_}
6 | \title{Call the Value of an Asynchronous Aio Operation}
7 | \usage{
8 | call_aio(x)
9 |
10 | call_aio_(x)
11 | }
12 | \arguments{
13 | \item{x}{an Aio or list of Aios (objects of class 'sendAio', 'recvAio' or
14 | 'ncurlAio').}
15 | }
16 | \value{
17 | The passed object (invisibly).
18 | }
19 | \description{
20 | \code{call_aio} retrieves the value of an asynchronous Aio operation, waiting
21 | for the operation to complete if still in progress. For a list of Aios, waits
22 | for all asynchronous operations to complete before returning.
23 |
24 | \code{call_aio_} is a variant that allows user interrupts, suitable for
25 | interactive use.
26 | }
27 | \details{
28 | For a 'recvAio', the received value may be retrieved at \verb{$data}.
29 |
30 | For a 'sendAio', the send result may be retrieved at \verb{$result}.
31 | This will be zero on success, or else an integer error code.
32 |
33 | To access the values directly, use for example on a 'recvAio' \code{x}:
34 | \code{call_aio(x)$data}.
35 |
36 | For a 'recvAio', if an error occurred in unserialization or conversion of the
37 | message data to the specified mode, a raw vector will be returned instead to
38 | allow recovery (accompanied by a warning).
39 |
40 | Note: this function operates silently and does not error even if \code{x} is not
41 | an active Aio or list of Aios, always returning invisibly the passed object.
42 | }
43 | \section{Alternatively}{
44 |
45 |
46 | Aio values may be accessed directly at \verb{$result} for a 'sendAio', and \verb{$data}
47 | for a 'recvAio'. If the Aio operation is yet to complete, an 'unresolved'
48 | logical NA will be returned. Once complete, the resolved value will be
49 | returned instead.
50 |
51 | \code{\link[=unresolved]{unresolved()}} may also be used, which returns \code{TRUE} only if an Aio or Aio
52 | value has yet to resolve and \code{FALSE} otherwise. This is suitable for use in
53 | control flow statements such as \code{while} or \code{if}.
54 | }
55 |
56 | \examples{
57 | s1 <- socket("pair", listen = "inproc://nanonext")
58 | s2 <- socket("pair", dial = "inproc://nanonext")
59 |
60 | res <- send_aio(s1, data.frame(a = 1, b = 2), timeout = 100)
61 | res
62 | call_aio(res)
63 | res$result
64 |
65 | msg <- recv_aio(s2, timeout = 100)
66 | msg
67 | call_aio_(msg)$data
68 |
69 | close(s1)
70 | close(s2)
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/man/close.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/context.R, R/listdial.R, R/ncurl.R, R/socket.R,
3 | % R/stream.R
4 | \name{close.nanoContext}
5 | \alias{close.nanoContext}
6 | \alias{close.nanoDialer}
7 | \alias{close.nanoListener}
8 | \alias{close.ncurlSession}
9 | \alias{close}
10 | \alias{close.nanoSocket}
11 | \alias{close.nanoStream}
12 | \title{Close Connection}
13 | \usage{
14 | \method{close}{nanoContext}(con, ...)
15 |
16 | \method{close}{nanoDialer}(con, ...)
17 |
18 | \method{close}{nanoListener}(con, ...)
19 |
20 | \method{close}{ncurlSession}(con, ...)
21 |
22 | \method{close}{nanoSocket}(con, ...)
23 |
24 | \method{close}{nanoStream}(con, ...)
25 | }
26 | \arguments{
27 | \item{con}{a Socket, Context, Dialer, Listener, Stream, or 'ncurlSession'.}
28 |
29 | \item{...}{not used.}
30 | }
31 | \value{
32 | Invisibly, an integer exit code (zero on success).
33 | }
34 | \description{
35 | Close Connection on a Socket, Context, Dialer, Listener, Stream, Pipe, or
36 | ncurl Session.
37 | }
38 | \details{
39 | Closing an object explicitly frees its resources. An object can also be
40 | removed directly in which case its resources are freed when the object is
41 | garbage collected.
42 |
43 | Closing a Socket associated with a Context also closes the Context.
44 |
45 | Dialers and Listeners are implicitly closed when the Socket they are
46 | associated with is closed.
47 |
48 | Closing a Socket or a Context: messages that have been submitted for sending
49 | may be flushed or delivered, depending upon the transport. Closing the Socket
50 | while data is in transmission will likely lead to loss of that data. There is
51 | no automatic linger or flush to ensure that the Socket send buffers have
52 | completely transmitted.
53 |
54 | Closing a Stream: if any send or receive operations are pending, they will be
55 | terminated and any new operations will fail after the connection is closed.
56 |
57 | Closing an 'ncurlSession' closes the http(s) connection.
58 | }
59 | \seealso{
60 | \code{\link[=reap]{reap()}}
61 | }
62 |
--------------------------------------------------------------------------------
/man/collect_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{collect_aio}
4 | \alias{collect_aio}
5 | \alias{collect_aio_}
6 | \title{Collect Data of an Aio or List of Aios}
7 | \usage{
8 | collect_aio(x)
9 |
10 | collect_aio_(x)
11 | }
12 | \arguments{
13 | \item{x}{an Aio or list of Aios (objects of class 'sendAio', 'recvAio' or
14 | 'ncurlAio').}
15 | }
16 | \value{
17 | Depending on the type of \code{x} supplied, an object or list of objects
18 | (the same length as \code{x}, preserving names).
19 | }
20 | \description{
21 | \code{collect_aio} collects the data of an Aio or list of Aios, waiting for
22 | resolution if still in progress.
23 |
24 | \code{collect_aio_} is a variant that allows user interrupts, suitable for
25 | interactive use.
26 | }
27 | \details{
28 | This function will wait for the asynchronous operation(s) to complete if
29 | still in progress (blocking).
30 |
31 | Using \code{x[]} on an Aio \code{x} is equivalent to the user-interruptible
32 | \code{collect_aio_(x)}.
33 | }
34 | \examples{
35 | s1 <- socket("pair", listen = "inproc://nanonext")
36 | s2 <- socket("pair", dial = "inproc://nanonext")
37 |
38 | res <- send_aio(s1, data.frame(a = 1, b = 2), timeout = 100)
39 | collect_aio(res)
40 |
41 | msg <- recv_aio(s2, timeout = 100)
42 | collect_aio_(msg)
43 |
44 | msg[]
45 |
46 | close(s1)
47 | close(s2)
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/man/context.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/context.R
3 | \name{context}
4 | \alias{context}
5 | \title{Open Context}
6 | \usage{
7 | context(socket)
8 | }
9 | \arguments{
10 | \item{socket}{a Socket.}
11 | }
12 | \value{
13 | A Context (object of class 'nanoContext' and 'nano').
14 | }
15 | \description{
16 | Open a new Context to be used with a Socket. The purpose of a Context is to
17 | permit applications to share a single socket, with its underlying dialers and
18 | listeners, while still benefiting from separate state tracking.
19 | }
20 | \details{
21 | Contexts allow the independent and concurrent use of stateful operations
22 | using the same socket. For example, two different contexts created on a rep
23 | socket can each receive requests, and send replies to them, without any
24 | regard to or interference with each other.
25 |
26 | Only the following protocols support creation of contexts: req, rep, sub
27 | (in a pub/sub pattern), surveyor, respondent.
28 |
29 | To send and receive over a context use \code{\link[=send]{send()}} and \code{\link[=recv]{recv()}} or their async
30 | counterparts \code{\link[=send_aio]{send_aio()}} and \code{\link[=recv_aio]{recv_aio()}}.
31 |
32 | For nano objects, use the \verb{$context_open()} method, which will attach a new
33 | context at \verb{$context}. See \code{\link[=nano]{nano()}}.
34 | }
35 | \examples{
36 | s <- socket("req", listen = "inproc://nanonext")
37 | ctx <- context(s)
38 | ctx
39 | close(ctx)
40 | close(s)
41 |
42 | n <- nano("req", listen = "inproc://nanonext")
43 | n$context_open()
44 | n$context
45 | n$context_open()
46 | n$context
47 | n$context_close()
48 | n$close()
49 |
50 | }
51 | \seealso{
52 | \code{\link[=request]{request()}} and \code{\link[=reply]{reply()}} for use with contexts.
53 | }
54 |
--------------------------------------------------------------------------------
/man/cv.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sync.R
3 | \name{cv}
4 | \alias{cv}
5 | \alias{wait}
6 | \alias{wait_}
7 | \alias{until}
8 | \alias{until_}
9 | \alias{cv_value}
10 | \alias{cv_reset}
11 | \alias{cv_signal}
12 | \title{Condition Variables}
13 | \usage{
14 | cv()
15 |
16 | wait(cv)
17 |
18 | wait_(cv)
19 |
20 | until(cv, msec)
21 |
22 | until_(cv, msec)
23 |
24 | cv_value(cv)
25 |
26 | cv_reset(cv)
27 |
28 | cv_signal(cv)
29 | }
30 | \arguments{
31 | \item{cv}{a 'conditionVariable' object.}
32 |
33 | \item{msec}{maximum time in milliseconds to wait for the condition variable
34 | to be signalled.}
35 | }
36 | \value{
37 | For \strong{cv}: a 'conditionVariable' object.
38 |
39 | For \strong{wait}: (invisibly) logical TRUE, or else FALSE if a flag has been
40 | set.
41 |
42 | For \strong{until}: (invisibly) logical TRUE if signalled, or else FALSE if the
43 | timeout was reached.
44 |
45 | For \strong{cv_value}: integer value of the condition variable.
46 |
47 | For \strong{cv_reset} and \strong{cv_signal}: zero (invisibly).
48 | }
49 | \description{
50 | \code{cv} creates a new condition variable (protected by a mutex internal to the
51 | object).
52 |
53 | \code{wait} waits on a condition being signalled by completion of an
54 | asynchronous receive or pipe event. \cr \code{wait_} is a variant that allows
55 | user interrupts, suitable for interactive use.
56 |
57 | \code{until} waits until a future time on a condition being signalled by
58 | completion of an asynchronous receive or pipe event. \cr \code{until_} is a
59 | variant that allows user interrupts, suitable for interactive use.
60 |
61 | \code{cv_value} inspects the internal value of a condition variable.
62 |
63 | \code{cv_reset} resets the internal value and flag of a condition variable.
64 |
65 | \code{cv_signal} signals a condition variable.
66 | }
67 | \details{
68 | Pass the 'conditionVariable' to the asynchronous receive functions
69 | \code{\link[=recv_aio]{recv_aio()}} or \code{\link[=request]{request()}}. Alternatively, to be notified of a pipe event,
70 | pass it to \code{\link[=pipe_notify]{pipe_notify()}}.
71 |
72 | Completion of the receive or pipe event, which happens asynchronously and
73 | independently of the main R thread, will signal the condition variable by
74 | incrementing it by 1.
75 |
76 | This will cause the R execution thread waiting on the condition variable
77 | using \code{wait()} or \code{until()} to wake and continue.
78 |
79 | For argument \code{msec}, non-integer values will be coerced to integer.
80 | Non-numeric input will be ignored and return immediately.
81 | }
82 | \section{Condition}{
83 |
84 |
85 | The condition internal to this 'conditionVariable' maintains a state (value).
86 | Each signal increments the value by 1. Each time \code{wait()} or \code{until()}
87 | returns (apart from due to timeout), the value is decremented by 1.
88 |
89 | The internal condition may be inspected at any time using \code{cv_value()} and
90 | reset using \code{cv_reset()}. This affords a high degree of flexibility in
91 | designing complex concurrent applications.
92 | }
93 |
94 | \section{Flag}{
95 |
96 |
97 | The condition variable also contains a flag that certain signalling functions
98 | such as \code{\link[=pipe_notify]{pipe_notify()}} can set. When this flag has been set, all subsequent
99 | \code{wait()} calls will return logical FALSE instead of TRUE.
100 |
101 | Note that the flag is not automatically reset, but may be reset manually
102 | using \code{cv_reset()}.
103 | }
104 |
105 | \examples{
106 | cv <- cv()
107 |
108 | \dontrun{
109 | wait(cv) # would block until the cv is signalled
110 | wait_(cv) # would block until the cv is signalled or interrupted
111 | }
112 |
113 | until(cv, 10L)
114 | until_(cv, 10L)
115 |
116 | cv_value(cv)
117 |
118 | cv_reset(cv)
119 |
120 | cv_value(cv)
121 | cv_signal(cv)
122 | cv_value(cv)
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/man/dial.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/listdial.R
3 | \name{dial}
4 | \alias{dial}
5 | \title{Dial an Address from a Socket}
6 | \usage{
7 | dial(
8 | socket,
9 | url = "inproc://nanonext",
10 | tls = NULL,
11 | autostart = TRUE,
12 | fail = c("warn", "error", "none")
13 | )
14 | }
15 | \arguments{
16 | \item{socket}{a Socket.}
17 |
18 | \item{url}{[default 'inproc://nanonext'] a URL to dial, specifying the
19 | transport and address as a character string e.g. 'inproc://anyvalue' or
20 | 'tcp://127.0.0.1:5555' (see \link{transports}).}
21 |
22 | \item{tls}{[default NULL] for secure tls+tcp:// or wss:// connections only,
23 | provide a TLS configuration object created by \code{\link[=tls_config]{tls_config()}}.}
24 |
25 | \item{autostart}{[default TRUE] whether to start the dialer (by default
26 | asynchronously). Set to NA to start synchronously - this is less resilient
27 | if a connection is not immediately possible, but avoids subtle errors from
28 | attempting to use the socket before an asynchronous dial has completed. Set
29 | to FALSE if setting configuration options on the dialer as it is not
30 | generally possible to change these once started.}
31 |
32 | \item{fail}{[default 'warn'] failure mode - a character value or integer
33 | equivalent, whether to warn (1L), error (2L), or for none (3L) just return
34 | an 'errorValue' without any corresponding warning.}
35 | }
36 | \value{
37 | Invisibly, an integer exit code (zero on success). A new Dialer
38 | (object of class 'nanoDialer' and 'nano') is created and bound to the
39 | Socket if successful.
40 | }
41 | \description{
42 | Creates a new Dialer and binds it to a Socket.
43 | }
44 | \details{
45 | To view all Dialers bound to a socket use \verb{$dialer} on the socket, which
46 | returns a list of Dialer objects. To access any individual Dialer (e.g. to
47 | set options on it), index into the list e.g. \verb{$dialer[[1]]} to return the
48 | first Dialer.
49 |
50 | A Dialer is an external pointer to a dialer object, which creates a single
51 | outgoing connection at a time. If the connection is broken, or fails, the
52 | dialer object will automatically attempt to reconnect, and will keep doing so
53 | until the dialer or socket is destroyed.
54 | }
55 | \section{Further details}{
56 |
57 |
58 | Dialers and Listeners are always associated with a single socket. A given
59 | socket may have multiple Listeners and/or multiple Dialers.
60 |
61 | The client/server relationship described by dialer/listener is completely
62 | orthogonal to any similar relationship in the protocols. For example, a rep
63 | socket may use a dialer to connect to a listener on an req socket. This
64 | orthogonality can lead to innovative solutions to otherwise challenging
65 | communications problems.
66 |
67 | Any configuration options on the dialer/listener should be set by \code{\link[=opt<-]{opt<-()}}
68 | before starting the dialer/listener with \code{\link[=start]{start()}}.
69 |
70 | Dialers/Listeners may be destroyed by \code{\link[=close]{close()}}. They are also closed when
71 | their associated socket is closed.
72 | }
73 |
74 | \examples{
75 | socket <- socket("rep")
76 | dial(socket, url = "inproc://nanodial", autostart = FALSE)
77 | socket$dialer
78 | start(socket$dialer[[1]])
79 | socket$dialer
80 | close(socket$dialer[[1]])
81 | close(socket)
82 |
83 | nano <- nano("bus")
84 | nano$dial(url = "inproc://nanodial", autostart = FALSE)
85 | nano$dialer
86 | nano$dialer_start()
87 | nano$dialer
88 | close(nano$dialer[[1]])
89 | nano$close()
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/man/dot-advance.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{.advance}
4 | \alias{.advance}
5 | \title{Advances the RNG State}
6 | \usage{
7 | .advance()
8 | }
9 | \value{
10 | NULL.
11 | }
12 | \description{
13 | Internal package function.
14 | }
15 | \keyword{internal}
16 |
--------------------------------------------------------------------------------
/man/dot-context.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/context.R
3 | \name{.context}
4 | \alias{.context}
5 | \title{Technical Utility: Open Context}
6 | \usage{
7 | .context(socket)
8 | }
9 | \arguments{
10 | \item{socket}{a Socket.}
11 | }
12 | \value{
13 | An external pointer.
14 | }
15 | \description{
16 | Open a new Context to be used with a Socket. This function is a performance
17 | variant of \code{\link[=context]{context()}}, designed to wrap a socket in a function argument when
18 | calling \code{\link[=request]{request()}} or \code{\link[=reply]{reply()}}.
19 | }
20 | \details{
21 | External pointers created by this function are unclassed, hence methods for
22 | contexts such as \code{\link[=close]{close()}} will not work (use \code{\link[=reap]{reap()}} instead). Otherwise
23 | they function identically to a Context when passed to all messaging
24 | functions.
25 | }
26 |
--------------------------------------------------------------------------------
/man/dot-interrupt.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{.interrupt}
4 | \alias{.interrupt}
5 | \title{Interrupt Switch}
6 | \usage{
7 | .interrupt(x = TRUE)
8 | }
9 | \arguments{
10 | \item{x}{logical value.}
11 | }
12 | \value{
13 | The logical value \code{x} supplied.
14 | }
15 | \description{
16 | Sets whether async receive completions trigger an interrupt.
17 | Internal package function.
18 | }
19 | \keyword{internal}
20 |
--------------------------------------------------------------------------------
/man/dot-keep.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{.keep}
4 | \alias{.keep}
5 | \title{Keep Promise}
6 | \usage{
7 | .keep(x, ctx)
8 | }
9 | \arguments{
10 | \item{x}{a 'recvAio' or 'ncurlAio' object.}
11 |
12 | \item{ctx}{the return value of \code{environment()}.}
13 | }
14 | \value{
15 | NULL.
16 | }
17 | \description{
18 | Internal package function.
19 | }
20 | \details{
21 | If successful, both \code{x} and \code{ctx} are preserved and accessible from the
22 | promise callback.
23 | }
24 | \keyword{internal}
25 |
--------------------------------------------------------------------------------
/man/dot-read_header.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{.read_header}
4 | \alias{.read_header}
5 | \alias{.mark}
6 | \alias{.read_marker}
7 | \title{Serialization Headers and Markers}
8 | \usage{
9 | .read_header(x)
10 |
11 | .mark(bool = TRUE)
12 |
13 | .read_marker(x)
14 | }
15 | \arguments{
16 | \item{x}{raw vector.}
17 |
18 | \item{bool}{logical value.}
19 | }
20 | \value{
21 | For \code{.read_header()}: integer value.
22 |
23 | For \code{.mark()}: the logical \code{bool} supplied.
24 |
25 | For \code{.read_marker()}: logical value \code{TRUE} or \code{FALSE}.
26 | }
27 | \description{
28 | Internal package functions.
29 | }
30 | \keyword{internal}
31 |
--------------------------------------------------------------------------------
/man/dot-unresolved.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{.unresolved}
4 | \alias{.unresolved}
5 | \title{Technical Utility: Query if an Aio is Unresolved}
6 | \usage{
7 | .unresolved(x)
8 | }
9 | \arguments{
10 | \item{x}{an Aio or list of Aios (objects of class 'sendAio', 'recvAio' or
11 | 'ncurlAio').}
12 | }
13 | \value{
14 | Logical \code{TRUE} if \code{x} is an unresolved Aio or else \code{FALSE}, or if \code{x}
15 | is a list, the integer number of unresolved Aios in the list.
16 | }
17 | \description{
18 | Query whether an Aio or list of Aios remains unresolved. This is an
19 | experimental technical utility version of \code{\link[=unresolved]{unresolved()}} not intended for
20 | ordinary use. Provides a method of querying the busy status of an Aio without
21 | altering its state in any way i.e. not attempting to retrieve the result or
22 | message.
23 | }
24 | \details{
25 | \code{.unresolved()} is not intended to be used for 'recvAio' returned by a
26 | signalling function, in which case \code{\link[=unresolved]{unresolved()}} must be used in all cases.
27 | }
28 | \keyword{internal}
29 |
--------------------------------------------------------------------------------
/man/figures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/man/figures/logo.png
--------------------------------------------------------------------------------
/man/grapes-twiddle-greater-than-grapes.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sync.R
3 | \name{\%~>\%}
4 | \alias{\%~>\%}
5 | \title{Signal Forwarder}
6 | \usage{
7 | cv \%~>\% cv2
8 | }
9 | \arguments{
10 | \item{cv}{a 'conditionVariable' object, from which to forward the signal.}
11 |
12 | \item{cv2}{a 'conditionVariable' object, to which the signal is forwarded.}
13 | }
14 | \value{
15 | Invisibly, \code{cv2}.
16 | }
17 | \description{
18 | Forwards signals from one 'conditionVariable' to another.
19 | }
20 | \details{
21 | The condition value of \code{cv} is initially reset to zero when this operator
22 | returns. Only one forwarder can be active on a \code{cv} at any given time, and
23 | assigning a new forwarding target cancels any currently existing forwarding.
24 |
25 | Changes in the condition value of \code{cv} are forwarded to \code{cv2}, but only on
26 | each occassion \code{cv} is signalled. This means that waiting on \code{cv} will cause
27 | a temporary divergence between the actual condition value of \code{cv} and that
28 | recorded at \code{cv2}, until the next time \code{cv} is signalled.
29 | }
30 | \examples{
31 | cva <- cv(); cvb <- cv(); cv1 <- cv(); cv2 <- cv()
32 |
33 | cva \%~>\% cv1 \%~>\% cv2
34 | cvb \%~>\% cv2
35 |
36 | cv_signal(cva)
37 | cv_signal(cvb)
38 | cv_value(cv1)
39 | cv_value(cv2)
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/man/ip_addr.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{ip_addr}
4 | \alias{ip_addr}
5 | \title{IP Address}
6 | \usage{
7 | ip_addr()
8 | }
9 | \value{
10 | A named character string.
11 | }
12 | \description{
13 | Returns a character string comprising the local network IPv4 address, or
14 | vector if there are multiple addresses from multiple network adapters, or
15 | an empty character string if unavailable.
16 | }
17 | \details{
18 | The IP addresses will be named by interface (adapter friendly name on
19 | Windows) e.g. 'eth0' or 'en0'.
20 | }
21 | \examples{
22 | ip_addr()
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/man/is_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{is_aio}
4 | \alias{is_aio}
5 | \alias{is_nano}
6 | \alias{is_ncurl_session}
7 | \title{Validators}
8 | \usage{
9 | is_aio(x)
10 |
11 | is_nano(x)
12 |
13 | is_ncurl_session(x)
14 | }
15 | \arguments{
16 | \item{x}{an object.}
17 | }
18 | \value{
19 | Logical value TRUE or FALSE.
20 | }
21 | \description{
22 | Validator functions for object types created by \pkg{nanonext}.
23 | }
24 | \details{
25 | Is the object an Aio (inheriting from class 'sendAio' or 'recvAio').
26 |
27 | Is the object an object inheriting from class 'nano' i.e. a nanoSocket,
28 | nanoContext, nanoStream, nanoListener, nanoDialer, nanoMonitor or nano
29 | Object.
30 |
31 | Is the object an ncurlSession (object of class 'ncurlSession').
32 |
33 | Is the object a Condition Variable (object of class 'conditionVariable').
34 | }
35 | \examples{
36 | nc <- call_aio(ncurl_aio("https://postman-echo.com/get", timeout = 1000L))
37 | is_aio(nc)
38 |
39 | s <- socket()
40 | is_nano(s)
41 | n <- nano()
42 | is_nano(n)
43 | close(s)
44 | n$close()
45 |
46 | s <- ncurl_session("https://postman-echo.com/get", timeout = 1000L)
47 | is_ncurl_session(s)
48 | if (is_ncurl_session(s)) close(s)
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/man/is_error_value.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{is_error_value}
4 | \alias{is_error_value}
5 | \alias{is_nul_byte}
6 | \title{Error Validators}
7 | \usage{
8 | is_error_value(x)
9 |
10 | is_nul_byte(x)
11 | }
12 | \arguments{
13 | \item{x}{an object.}
14 | }
15 | \value{
16 | Logical value TRUE or FALSE.
17 | }
18 | \description{
19 | Validator functions for error value types created by \pkg{nanonext}.
20 | }
21 | \details{
22 | Is the object an error value generated by the package. All non-success
23 | integer return values are classed 'errorValue' to be distinguishable from
24 | integer message values. Includes error values returned after a timeout etc.
25 |
26 | Is the object a nul byte.
27 | }
28 | \examples{
29 | s <- socket()
30 | r <- recv_aio(s, timeout = 10)
31 | call_aio(r)$data
32 | close(s)
33 | r$data == 5L
34 | is_error_value(r$data)
35 | is_error_value(5L)
36 |
37 | is_nul_byte(as.raw(0L))
38 | is_nul_byte(raw(length = 1L))
39 | is_nul_byte(writeBin("", con = raw()))
40 | is_nul_byte(0L)
41 | is_nul_byte(NULL)
42 | is_nul_byte(NA)
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/man/listen.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/listdial.R
3 | \name{listen}
4 | \alias{listen}
5 | \title{Listen to an Address from a Socket}
6 | \usage{
7 | listen(
8 | socket,
9 | url = "inproc://nanonext",
10 | tls = NULL,
11 | autostart = TRUE,
12 | fail = c("warn", "error", "none")
13 | )
14 | }
15 | \arguments{
16 | \item{socket}{a Socket.}
17 |
18 | \item{url}{[default 'inproc://nanonext'] a URL to dial, specifying the
19 | transport and address as a character string e.g. 'inproc://anyvalue' or
20 | 'tcp://127.0.0.1:5555' (see \link{transports}).}
21 |
22 | \item{tls}{[default NULL] for secure tls+tcp:// or wss:// connections only,
23 | provide a TLS configuration object created by \code{\link[=tls_config]{tls_config()}}.}
24 |
25 | \item{autostart}{[default TRUE] whether to start the listener. Set to FALSE
26 | if setting configuration options on the listener as it is not generally
27 | possible to change these once started.}
28 |
29 | \item{fail}{[default 'warn'] failure mode - a character value or integer
30 | equivalent, whether to warn (1L), error (2L), or for none (3L) just return
31 | an 'errorValue' without any corresponding warning.}
32 | }
33 | \value{
34 | Invisibly, an integer exit code (zero on success). A new Listener
35 | (object of class 'nanoListener' and 'nano') is created and bound to the
36 | Socket if successful.
37 | }
38 | \description{
39 | Creates a new Listener and binds it to a Socket.
40 | }
41 | \details{
42 | To view all Listeners bound to a socket use \verb{$listener} on the socket,
43 | which returns a list of Listener objects. To access any individual Listener
44 | (e.g. to set options on it), index into the list e.g. \verb{$listener[[1]]}
45 | to return the first Listener.
46 |
47 | A listener is an external pointer to a listener object, which accepts
48 | incoming connections. A given listener object may have many connections at
49 | the same time, much like an HTTP server can have many connections to multiple
50 | clients simultaneously.
51 | }
52 | \section{Further details}{
53 |
54 |
55 | Dialers and Listeners are always associated with a single socket. A given
56 | socket may have multiple Listeners and/or multiple Dialers.
57 |
58 | The client/server relationship described by dialer/listener is completely
59 | orthogonal to any similar relationship in the protocols. For example, a rep
60 | socket may use a dialer to connect to a listener on an req socket. This
61 | orthogonality can lead to innovative solutions to otherwise challenging
62 | communications problems.
63 |
64 | Any configuration options on the dialer/listener should be set by \code{\link[=opt<-]{opt<-()}}
65 | before starting the dialer/listener with \code{\link[=start]{start()}}.
66 |
67 | Dialers/Listeners may be destroyed by \code{\link[=close]{close()}}. They are also closed when
68 | their associated socket is closed.
69 | }
70 |
71 | \examples{
72 | socket <- socket("req")
73 | listen(socket, url = "inproc://nanolisten", autostart = FALSE)
74 | socket$listener
75 | start(socket$listener[[1]])
76 | socket$listener
77 | close(socket$listener[[1]])
78 | close(socket)
79 |
80 | nano <- nano("bus")
81 | nano$listen(url = "inproc://nanolisten", autostart = FALSE)
82 | nano$listener
83 | nano$listener_start()
84 | nano$listener
85 | close(nano$listener[[1]])
86 | nano$close()
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/man/mclock.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{mclock}
4 | \alias{mclock}
5 | \title{Clock Utility}
6 | \usage{
7 | mclock()
8 | }
9 | \value{
10 | A double.
11 | }
12 | \description{
13 | Provides the number of elapsed milliseconds since an arbitrary reference time
14 | in the past. The reference time will be the same for a given session, but may
15 | differ between sessions.
16 | }
17 | \details{
18 | A convenience function for building concurrent applications. The resolution
19 | of the clock depends on the underlying system timing facilities and may not
20 | be particularly fine-grained. This utility should however be faster than
21 | using \code{Sys.time()}.
22 | }
23 | \examples{
24 | time <- mclock(); msleep(100); mclock() - time
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/man/messenger.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/messenger.R
3 | \name{messenger}
4 | \alias{messenger}
5 | \title{Messenger}
6 | \usage{
7 | messenger(url, auth = NULL)
8 | }
9 | \arguments{
10 | \item{url}{a URL to connect to, specifying the transport and address as a
11 | character string e.g. 'tcp://127.0.0.1:5555' (see \link{transports}).}
12 |
13 | \item{auth}{[default NULL] an R object (possessed by both parties) which
14 | serves as a pre-shared key on which to authenticate the communication.
15 | Note: the object is never sent, only a random subset of its md5 hash after
16 | serialization.}
17 | }
18 | \value{
19 | Invisible NULL.
20 | }
21 | \description{
22 | Multi-threaded, console-based, 2-way instant messaging system with
23 | authentication, based on NNG scalability protocols.
24 | }
25 | \note{
26 | The authentication protocol is an experimental proof of concept which
27 | is not secure, and should not be used for critical applications.
28 | }
29 | \section{Usage}{
30 |
31 |
32 | Type outgoing messages and hit return to send.
33 |
34 | The timestamps of outgoing messages are prefixed by \code{>} and that of
35 | incoming messages by \code{<}.
36 |
37 | \verb{:q} is the command to quit.
38 |
39 | Both parties must supply the same argument for \code{auth}, otherwise the party
40 | trying to connect will receive an 'authentication error' and be immediately
41 | disconnected.
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/man/monitor.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/socket.R
3 | \name{monitor}
4 | \alias{monitor}
5 | \alias{read_monitor}
6 | \title{Monitor a Socket for Pipe Changes}
7 | \usage{
8 | monitor(sock, cv)
9 |
10 | read_monitor(x)
11 | }
12 | \arguments{
13 | \item{sock}{a Socket.}
14 |
15 | \item{cv}{a 'conditionVariable'.}
16 |
17 | \item{x}{a Monitor.}
18 | }
19 | \value{
20 | For \code{monitor}: a Monitor (object of class 'nanoMonitor'). \cr
21 | For \code{read_monitor}: an integer vector of pipe IDs (positive if added,
22 | negative if removed), or else NULL if there were no changes since the
23 | previous read.
24 | }
25 | \description{
26 | This function monitors pipe additions and removals from a socket.
27 | }
28 | \examples{
29 | cv <- cv()
30 | s <- socket("poly")
31 | s1 <- socket("poly")
32 |
33 | m <- monitor(s, cv)
34 | m
35 |
36 | listen(s)
37 | dial(s1)
38 |
39 | cv_value(cv)
40 | read_monitor(m)
41 |
42 | close(s)
43 | close(s1)
44 |
45 | read_monitor(m)
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/man/msleep.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{msleep}
4 | \alias{msleep}
5 | \title{Sleep Utility}
6 | \usage{
7 | msleep(time)
8 | }
9 | \arguments{
10 | \item{time}{integer number of milliseconds to block the caller.}
11 | }
12 | \value{
13 | Invisible NULL.
14 | }
15 | \description{
16 | Sleep function. May block for longer than requested, with the actual wait
17 | time determined by the capabilities of the underlying system.
18 | }
19 | \details{
20 | Non-integer values for \code{time} are coerced to integer. Negative, logical and
21 | other non-numeric values are ignored, causing the function to return
22 | immediately.
23 |
24 | Note that unlike \code{Sys.sleep()}, this function is not user-interruptible by
25 | sending SIGINT e.g. with ctrl + c.
26 | }
27 | \examples{
28 | time <- mclock(); msleep(100); mclock() - time
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/man/nano.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/nano.R
3 | \name{nano}
4 | \alias{nano}
5 | \title{Create Nano Object}
6 | \usage{
7 | nano(
8 | protocol = c("bus", "pair", "poly", "push", "pull", "pub", "sub", "req", "rep",
9 | "surveyor", "respondent"),
10 | dial = NULL,
11 | listen = NULL,
12 | tls = NULL,
13 | autostart = TRUE
14 | )
15 | }
16 | \arguments{
17 | \item{protocol}{[default 'bus'] choose protocol - \code{"bus"}, \code{"pair"},
18 | \code{"poly"}, \code{"push"}, \code{"pull"}, \code{"pub"}, \code{"sub"}, \code{"req"}, \code{"rep"},
19 | \code{"surveyor"}, or \code{"respondent"} - see \link{protocols}.}
20 |
21 | \item{dial}{(optional) a URL to dial, specifying the transport and address as
22 | a character string e.g. 'inproc://anyvalue' or 'tcp://127.0.0.1:5555' (see
23 | \link{transports}).}
24 |
25 | \item{listen}{(optional) a URL to listen at, specifying the transport and
26 | address as a character string e.g. 'inproc://anyvalue' or
27 | 'tcp://127.0.0.1:5555' (see \link{transports}).}
28 |
29 | \item{tls}{[default NULL] for secure tls+tcp:// or wss:// connections only,
30 | provide a TLS configuration object created by \code{\link[=tls_config]{tls_config()}}.}
31 |
32 | \item{autostart}{[default TRUE] whether to start the dialer/listener. Set
33 | to FALSE if setting configuration options on the dialer/listener as it is
34 | not generally possible to change these once started. For dialers only: set
35 | to NA to start synchronously - this is less resilient if a connection is
36 | not immediately possible, but avoids subtle errors from attempting to use
37 | the socket before an asynchronous dial has completed.}
38 | }
39 | \value{
40 | A nano object of class 'nanoObject'.
41 | }
42 | \description{
43 | Create a nano object, encapsulating a Socket, Dialers/Listeners and
44 | associated methods.
45 | }
46 | \details{
47 | This function encapsulates a Socket, Dialer and/or Listener, and its
48 | associated methods.
49 |
50 | The Socket may be accessed by \verb{$socket}, and the Dialer or Listener by
51 | \verb{$dialer[[1]]} or \verb{$listener[[1]]} respectively.
52 |
53 | The object's methods may be accessed by \code{$} e.g. \verb{$send()} or \verb{$recv()}.
54 | These methods mirror their functional equivalents, with the same arguments
55 | and defaults, apart from that the first argument of the functional equivalent
56 | is mapped to the object's encapsulated socket (or context, if active) and
57 | does not need to be supplied.
58 |
59 | More complex network topologies may be created by binding further dialers or
60 | listeners using the object's \verb{$dial()} and \verb{$listen()} methods. The new
61 | dialer/listener will be attached to the object e.g. if the object already has
62 | a dialer, then at \verb{$dialer[[2]]} etc.
63 |
64 | Note that \verb{$dialer_opt()} and \verb{$listener_opt()} methods will be available
65 | once dialers/listeners are attached to the object. These methods get or apply
66 | settings for all dialers or listeners equally. To get or apply settings for
67 | individual dialers/listeners, access them directly via \verb{$dialer[[2]]} or
68 | \verb{$listener[[2]]} etc.
69 |
70 | The methods \verb{$opt()}, and also \verb{$dialer_opt()} or \verb{$listener_opt()} as may be
71 | applicable, will get the requested option if a single argument \code{name} is
72 | provided, and will set the value for the option if both arguments \code{name} and
73 | \code{value} are provided.
74 |
75 | For Dialers or Listeners not automatically started, the \verb{$dialer_start()} or
76 | \verb{$listener_start()} methods will be available. These act on the most recently
77 | created Dialer or Listener respectively.
78 |
79 | For applicable protocols, new contexts may be created by using the
80 | \verb{$context_open()} method. This will attach a new context at \verb{$context} as
81 | well as a \verb{$context_close()} method. While a context is active, all object
82 | methods use the context rather than the socket. A new context may be created
83 | by calling \verb{$context_open()}, which will replace any existing context. It is
84 | only necessary to use \verb{$context_close()} to close the existing context and
85 | revert to using the socket.
86 | }
87 | \examples{
88 | nano <- nano("bus", listen = "inproc://nanonext")
89 | nano
90 | nano$socket
91 | nano$listener[[1]]
92 |
93 | nano$opt("send-timeout", 1500)
94 | nano$opt("send-timeout")
95 |
96 | nano$listen(url = "inproc://nanonextgen")
97 | nano$listener
98 |
99 | nano1 <- nano("bus", dial = "inproc://nanonext")
100 | nano$send("example test", mode = "raw")
101 | nano1$recv("character")
102 |
103 | nano$close()
104 | nano1$close()
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/man/nanonext-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/nanonext-package.R
3 | \docType{package}
4 | \name{nanonext-package}
5 | \alias{nanonext}
6 | \alias{nanonext-package}
7 | \title{nanonext: NNG (Nanomsg Next Gen) Lightweight Messaging Library}
8 | \description{
9 | R binding for NNG (Nanomsg Next Gen), a successor to ZeroMQ. NNG is a socket
10 | library for reliable, high-performance messaging over in-process, IPC, TCP,
11 | WebSocket and secure TLS transports. Implements 'Scalability Protocols', a
12 | standard for common communications patterns including publish/subscribe,
13 | request/reply and service discovery. As its own threaded concurrency
14 | framework, provides a toolkit for asynchronous programming and distributed
15 | computing. Intuitive 'aio' objects resolve automatically when asynchronous
16 | operations complete, and synchronisation primitives allow R to wait upon
17 | events signalled by concurrent threads.
18 | }
19 | \section{Usage notes}{
20 |
21 |
22 | \pkg{nanonext} offers 2 equivalent interfaces: a functional interface, and an
23 | object-oriented interface.
24 |
25 | The primary object in the functional interface is the Socket. Use \code{\link[=socket]{socket()}}
26 | to create a socket and dial or listen at an address. The socket is then
27 | passed as the first argument of subsequent actions such as \code{send()} or
28 | \code{recv()}.
29 |
30 | The primary object in the object-oriented interface is the nano object. Use
31 | \code{\link[=nano]{nano()}} to create a nano object which encapsulates a Socket and
32 | Dialer/Listener. Methods such as \verb{$send()} or \verb{$recv()} can then be accessed
33 | directly from the object.
34 | }
35 |
36 | \section{Documentation}{
37 |
38 |
39 | Guide to the implemented protocols for sockets: \link{protocols}
40 |
41 | Guide to the supported transports for dialers and listeners:
42 | \link{transports}
43 |
44 | Guide to the options that can be inspected and set using: \link{opt} /
45 | \link{opt<-}
46 | }
47 |
48 | \section{Reference Manual}{
49 |
50 |
51 | \code{vignette("nanonext", package = "nanonext")}
52 | }
53 |
54 | \section{Conceptual overview}{
55 |
56 |
57 | NNG presents a socket view of networking. A socket implements precisely one
58 | protocol, such as 'bus', etc.
59 |
60 | Each socket can be used to send and receive messages (if the protocol
61 | supports it, and implements the appropriate protocol semantics). For example,
62 | the 'sub' protocol automatically filters incoming messages to discard topics
63 | that have not been subscribed.
64 |
65 | NNG sockets are message-oriented, and messages are either delivered wholly,
66 | or not at all. Partial delivery is not possible. Furthermore, NNG does not
67 | provide any other delivery or ordering guarantees: messages may be dropped or
68 | reordered (some protocols, such as 'req' may offer stronger guarantees by
69 | performing their own retry and validation schemes).
70 |
71 | Each socket can have zero, one, or many endpoints, which are either listeners
72 | or dialers (a given socket may use listeners, dialers, or both). These
73 | endpoints provide access to underlying transports, such as TCP, etc.
74 |
75 | Each endpoint is associated with a URL, which is a service address. For
76 | dialers, this is the service address that is contacted, whereas for listeners
77 | this is where new connections will be accepted.
78 | }
79 |
80 | \section{Links}{
81 |
82 |
83 | NNG: \url{https://nng.nanomsg.org/} \cr
84 | Mbed TLS: \url{https://www.trustedfirmware.org/projects/mbed-tls/}
85 | }
86 |
87 | \seealso{
88 | Useful links:
89 | \itemize{
90 | \item \url{https://nanonext.r-lib.org}
91 | \item \url{https://github.com/r-lib/nanonext}
92 | \item Report bugs at \url{https://github.com/r-lib/nanonext/issues}
93 | }
94 |
95 | }
96 | \author{
97 | \strong{Maintainer}: Charlie Gao \email{charlie.gao@posit.co} (\href{https://orcid.org/0000-0002-0750-061X}{ORCID})
98 |
99 | Other contributors:
100 | \itemize{
101 | \item Posit Software, PBC (\href{https://ror.org/03wc8by49}{ROR}) [copyright holder, funder]
102 | \item Hibiki AI Limited [copyright holder]
103 | \item R Consortium [funder]
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/man/ncurl.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ncurl.R
3 | \name{ncurl}
4 | \alias{ncurl}
5 | \title{ncurl}
6 | \usage{
7 | ncurl(
8 | url,
9 | convert = TRUE,
10 | follow = FALSE,
11 | method = NULL,
12 | headers = NULL,
13 | data = NULL,
14 | response = NULL,
15 | timeout = NULL,
16 | tls = NULL
17 | )
18 | }
19 | \arguments{
20 | \item{url}{the URL address.}
21 |
22 | \item{convert}{[default TRUE] logical value whether to attempt conversion
23 | of the received raw bytes to a character vector. Set to \code{FALSE} if
24 | downloading non-text data.}
25 |
26 | \item{follow}{[default FALSE] logical value whether to automatically follow
27 | redirects (not applicable for async requests). If \code{FALSE}, the redirect
28 | address is returned as response header 'Location'.}
29 |
30 | \item{method}{(optional) the HTTP method as a character string. Defaults to
31 | 'GET' if not specified, and could also be 'POST', 'PUT' etc.}
32 |
33 | \item{headers}{(optional) a named character vector specifying the HTTP
34 | request headers, for example: \cr
35 | \code{c(Authorization = "Bearer APIKEY", "Content-Type" = "text/plain")} \cr
36 | A non-character or non-named vector will be ignored.}
37 |
38 | \item{data}{(optional) character string request data to be submitted. If a
39 | vector, only the first element is taken, and non-character objects are
40 | ignored.}
41 |
42 | \item{response}{(optional) a character vector specifying the response headers
43 | to return e.g. \code{c("date", "server")}. These are case-insensitive and
44 | will return NULL if not present. A non-character vector will be ignored.}
45 |
46 | \item{timeout}{(optional) integer value in milliseconds after which the
47 | transaction times out if not yet complete.}
48 |
49 | \item{tls}{(optional) applicable to secure HTTPS sites only, a client TLS
50 | Configuration object created by \code{\link[=tls_config]{tls_config()}}. If missing or NULL,
51 | certificates are not validated.}
52 | }
53 | \value{
54 | Named list of 3 elements:
55 | \itemize{
56 | \item \verb{$status} - integer HTTP repsonse status code (200 - OK).
57 | Use \code{\link[=status_code]{status_code()}} for a translation of the meaning.
58 | \item \verb{$headers} - named list of response headers supplied in \code{response},
59 | or NULL otherwise. If the status code is within the 300 range, i.e. a
60 | redirect, the response header 'Location' is automatically appended to
61 | return the redirect address.
62 | \item \verb{$data} - the response body, as a character string if
63 | \code{convert = TRUE} (may be further parsed as html, json, xml etc. as
64 | required), or a raw byte vector if FALSE (use \code{\link[=writeBin]{writeBin()}} to save as a
65 | file).
66 | }
67 | }
68 | \description{
69 | nano cURL - a minimalist http(s) client.
70 | }
71 | \examples{
72 | ncurl(
73 | "https://postman-echo.com/get",
74 | convert = FALSE,
75 | response = c("date", "content-type"),
76 | timeout = 1200L
77 | )
78 | ncurl(
79 | "https://postman-echo.com/put",
80 | method = "PUT",
81 | headers = c(Authorization = "Bearer APIKEY"),
82 | data = "hello world",
83 | timeout = 1500L
84 | )
85 | ncurl(
86 | "https://postman-echo.com/post",
87 | method = "POST",
88 | headers = c(`Content-Type` = "application/json"),
89 | data = '{"key":"value"}',
90 | timeout = 1500L
91 | )
92 |
93 | }
94 | \seealso{
95 | \code{\link[=ncurl_aio]{ncurl_aio()}} for asynchronous http requests; \code{\link[=ncurl_session]{ncurl_session()}} for
96 | persistent connections.
97 | }
98 |
--------------------------------------------------------------------------------
/man/ncurl_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ncurl.R
3 | \name{ncurl_aio}
4 | \alias{ncurl_aio}
5 | \title{ncurl Async}
6 | \usage{
7 | ncurl_aio(
8 | url,
9 | convert = TRUE,
10 | method = NULL,
11 | headers = NULL,
12 | data = NULL,
13 | response = NULL,
14 | timeout = NULL,
15 | tls = NULL
16 | )
17 | }
18 | \arguments{
19 | \item{url}{the URL address.}
20 |
21 | \item{convert}{[default TRUE] logical value whether to attempt conversion
22 | of the received raw bytes to a character vector. Set to \code{FALSE} if
23 | downloading non-text data.}
24 |
25 | \item{method}{(optional) the HTTP method as a character string. Defaults to
26 | 'GET' if not specified, and could also be 'POST', 'PUT' etc.}
27 |
28 | \item{headers}{(optional) a named character vector specifying the HTTP
29 | request headers, for example: \cr
30 | \code{c(Authorization = "Bearer APIKEY", "Content-Type" = "text/plain")} \cr
31 | A non-character or non-named vector will be ignored.}
32 |
33 | \item{data}{(optional) character string request data to be submitted. If a
34 | vector, only the first element is taken, and non-character objects are
35 | ignored.}
36 |
37 | \item{response}{(optional) a character vector specifying the response headers
38 | to return e.g. \code{c("date", "server")}. These are case-insensitive and
39 | will return NULL if not present. A non-character vector will be ignored.}
40 |
41 | \item{timeout}{(optional) integer value in milliseconds after which the
42 | transaction times out if not yet complete.}
43 |
44 | \item{tls}{(optional) applicable to secure HTTPS sites only, a client TLS
45 | Configuration object created by \code{\link[=tls_config]{tls_config()}}. If missing or NULL,
46 | certificates are not validated.}
47 | }
48 | \value{
49 | An 'ncurlAio' (object of class 'ncurlAio' and 'recvAio') (invisibly).
50 | The following elements may be accessed:
51 | \itemize{
52 | \item \verb{$status} - integer HTTP repsonse status code (200 - OK).
53 | Use \code{\link[=status_code]{status_code()}} for a translation of the meaning.
54 | \item \verb{$headers} - named list of response headers supplied in \code{response},
55 | or NULL otherwise. If the status code is within the 300 range, i.e. a
56 | redirect, the response header 'Location' is automatically appended to
57 | return the redirect address.
58 | \item \verb{$data} - the response body, as a character string if
59 | \code{convert = TRUE} (may be further parsed as html, json, xml etc. as
60 | required), or a raw byte vector if FALSE (use \code{\link[=writeBin]{writeBin()}} to save as a
61 | file).
62 | }
63 | }
64 | \description{
65 | nano cURL - a minimalist http(s) client - async edition.
66 | }
67 | \section{Promises}{
68 |
69 |
70 | 'ncurlAio' may be used anywhere that accepts a 'promise' from the
71 | \CRANpkg{promises} package through the included \code{as.promise} method.
72 |
73 | The promises created are completely event-driven and non-polling.
74 |
75 | If a status code of 200 (OK) is returned then the promise is resolved with
76 | the reponse body, otherwise it is rejected with a translation of the status
77 | code or 'errorValue' as the case may be.
78 | }
79 |
80 | \examples{
81 | nc <- ncurl_aio(
82 | "https://postman-echo.com/get",
83 | response = c("date", "server"),
84 | timeout = 2000L
85 | )
86 | call_aio(nc)
87 | nc$status
88 | nc$headers
89 | nc$data
90 |
91 | \dontshow{if (interactive() && requireNamespace("promises", quietly = TRUE)) withAutoprint(\{ # examplesIf}
92 | library(promises)
93 | p <- as.promise(nc)
94 | print(p)
95 |
96 | p2 <- ncurl_aio("https://postman-echo.com/get") \%...>\% cat
97 | is.promise(p2)
98 | \dontshow{\}) # examplesIf}
99 | }
100 | \seealso{
101 | \code{\link[=ncurl]{ncurl()}} for synchronous http requests; \code{\link[=ncurl_session]{ncurl_session()}} for
102 | persistent connections.
103 | }
104 |
--------------------------------------------------------------------------------
/man/ncurl_session.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ncurl.R
3 | \name{ncurl_session}
4 | \alias{ncurl_session}
5 | \alias{transact}
6 | \title{ncurl Session}
7 | \usage{
8 | ncurl_session(
9 | url,
10 | convert = TRUE,
11 | method = NULL,
12 | headers = NULL,
13 | data = NULL,
14 | response = NULL,
15 | timeout = NULL,
16 | tls = NULL
17 | )
18 |
19 | transact(session)
20 | }
21 | \arguments{
22 | \item{url}{the URL address.}
23 |
24 | \item{convert}{[default TRUE] logical value whether to attempt conversion
25 | of the received raw bytes to a character vector. Set to \code{FALSE} if
26 | downloading non-text data.}
27 |
28 | \item{method}{(optional) the HTTP method as a character string. Defaults to
29 | 'GET' if not specified, and could also be 'POST', 'PUT' etc.}
30 |
31 | \item{headers}{(optional) a named character vector specifying the HTTP
32 | request headers, for example: \cr
33 | \code{c(Authorization = "Bearer APIKEY", "Content-Type" = "text/plain")} \cr
34 | A non-character or non-named vector will be ignored.}
35 |
36 | \item{data}{(optional) character string request data to be submitted. If a
37 | vector, only the first element is taken, and non-character objects are
38 | ignored.}
39 |
40 | \item{response}{(optional) a character vector specifying the response headers
41 | to return e.g. \code{c("date", "server")}. These are case-insensitive and
42 | will return NULL if not present. A non-character vector will be ignored.}
43 |
44 | \item{timeout}{(optional) integer value in milliseconds after which the
45 | connection and subsequent transact attempts time out.}
46 |
47 | \item{tls}{(optional) applicable to secure HTTPS sites only, a client TLS
48 | Configuration object created by \code{\link[=tls_config]{tls_config()}}. If missing or NULL,
49 | certificates are not validated.}
50 |
51 | \item{session}{an 'ncurlSession' object.}
52 | }
53 | \value{
54 | For \code{ncurl_session}: an 'ncurlSession' object if successful, or else
55 | an 'errorValue'.
56 |
57 | For \code{transact}: a named list of 3 elements:
58 | \itemize{
59 | \item \verb{$status} - integer HTTP repsonse status code (200 - OK).
60 | Use \code{\link[=status_code]{status_code()}} for a translation of the meaning.
61 | \item \verb{$headers} - named list of response headers (if specified in the
62 | session), or NULL otherwise. If the status code is within the 300 range,
63 | i.e. a redirect, the response header 'Location' is automatically appended
64 | to return the redirect address.
65 | \item \verb{$data} - the response body as a character string (if
66 | \code{convert = TRUE} was specified for the session), which may be further
67 | parsed as html, json, xml etc. as required, or else a raw byte vector,
68 | which may be saved as a file using \code{\link[=writeBin]{writeBin()}}.
69 | }
70 | }
71 | \description{
72 | nano cURL - a minimalist http(s) client. A session encapsulates a connection,
73 | along with all related parameters, and may be used to return data multiple
74 | times by repeatedly calling \code{transact()}, which transacts once over the
75 | connection.
76 | }
77 | \examples{
78 | s <- ncurl_session(
79 | "https://postman-echo.com/get",
80 | response = "date",
81 | timeout = 2000L
82 | )
83 | s
84 | if (is_ncurl_session(s)) transact(s)
85 | if (is_ncurl_session(s)) close(s)
86 |
87 | }
88 | \seealso{
89 | \code{\link[=ncurl]{ncurl()}} for synchronous http requests; \code{\link[=ncurl_aio]{ncurl_aio()}} for
90 | asynchronous http requests.
91 | }
92 |
--------------------------------------------------------------------------------
/man/nng_error.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{nng_error}
4 | \alias{nng_error}
5 | \title{Translate Error Codes}
6 | \usage{
7 | nng_error(xc)
8 | }
9 | \arguments{
10 | \item{xc}{integer exit code to translate.}
11 | }
12 | \value{
13 | A character string comprising the error code and error message
14 | separated by \code{'|'}.
15 | }
16 | \description{
17 | Translate integer exit codes generated by the NNG library. All package
18 | functions return an integer exit code on error rather than the expected
19 | return value. These are classed 'errorValue' and may be checked by
20 | \code{\link[=is_error_value]{is_error_value()}}.
21 | }
22 | \examples{
23 | nng_error(1L)
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/man/nng_version.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{nng_version}
4 | \alias{nng_version}
5 | \title{NNG Library Version}
6 | \usage{
7 | nng_version()
8 | }
9 | \value{
10 | A character vector of length 2.
11 | }
12 | \description{
13 | Returns the versions of the 'libnng' and 'libmbedtls' libraries used by the
14 | package.
15 | }
16 | \examples{
17 | nng_version()
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/man/parse_url.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{parse_url}
4 | \alias{parse_url}
5 | \title{Parse URL}
6 | \usage{
7 | parse_url(url)
8 | }
9 | \arguments{
10 | \item{url}{character string containing a URL.}
11 | }
12 | \value{
13 | A named character vector of length 10, comprising:
14 | \itemize{
15 | \item \code{rawurl} - the unparsed URL string.
16 | \item \code{scheme} - the URL scheme, such as "http" or "inproc" (always lower
17 | case).
18 | \item \code{userinfo} - the username and password if supplied in the URL
19 | string.
20 | \item \code{host} - the full host part of the URL, including the port if
21 | present (separated by a colon).
22 | \item \code{hostname} - the name of the host.
23 | \item \code{port} - the port (if not specified, the default port if defined by
24 | the scheme).
25 | \item \code{path} - the path, typically used with HTTP or WebSocket.
26 | \item \code{query} - the query info (typically following ? in the URL).
27 | \item \code{fragment} - used for specifying an anchor, the part after # in a
28 | URL.
29 | \item \code{requri} - the full Request-URI (path[?query][#fragment]).
30 | }
31 | Values that cannot be determined are represented by an empty string \code{""}.
32 | }
33 | \description{
34 | Parses a character string containing an RFC 3986 compliant URL as per NNG.
35 | }
36 | \examples{
37 | parse_url("https://user:password@w3.org:8080/type/path?q=info#intro")
38 | parse_url("tcp://192.168.0.2:5555")
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/man/pipe_id.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{pipe_id}
4 | \alias{pipe_id}
5 | \title{Get the Pipe ID of a recvAio}
6 | \usage{
7 | pipe_id(x)
8 | }
9 | \arguments{
10 | \item{x}{a resolved 'recvAio'.}
11 | }
12 | \value{
13 | Integer pipe ID.
14 | }
15 | \description{
16 | Caution: must only be used on an already-resolved 'recvAio'. This function
17 | does not perform validation of these pre-conditions.
18 | }
19 |
--------------------------------------------------------------------------------
/man/pipe_notify.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sync.R
3 | \name{pipe_notify}
4 | \alias{pipe_notify}
5 | \title{Pipe Notify}
6 | \usage{
7 | pipe_notify(socket, cv, add = FALSE, remove = FALSE, flag = FALSE)
8 | }
9 | \arguments{
10 | \item{socket}{a Socket.}
11 |
12 | \item{cv}{a 'conditionVariable' to signal, or NULL to cancel a previously set
13 | signal.}
14 |
15 | \item{add}{[default FALSE] logical value whether to signal (or cancel
16 | signal) when a pipe is added.}
17 |
18 | \item{remove}{[default FALSE] logical value whether to signal (or cancel
19 | signal) when a pipe is removed.}
20 |
21 | \item{flag}{[default FALSE] logical value whether to also set a flag in the
22 | 'conditionVariable'. This can help distinguish between different types of
23 | signal, and causes any subsequent \code{\link[=wait]{wait()}} to return FALSE instead of TRUE.
24 | If a signal from the \pkg{tools} package, e.g. \code{tools::SIGINT}, or an
25 | equivalent integer value is supplied, this sets a flag and additionally
26 | raises this signal upon the flag being set.}
27 | }
28 | \value{
29 | Invisibly, zero on success (will otherwise error).
30 | }
31 | \description{
32 | Signals a 'conditionVariable' whenever pipes (individual connections) are
33 | added or removed at a socket.
34 | }
35 | \details{
36 | For add: this event occurs after the pipe is fully added to the socket. Prior
37 | to this time, it is not possible to communicate over the pipe with the
38 | socket.
39 |
40 | For remove: this event occurs after the pipe has been removed from the
41 | socket. The underlying transport may be closed at this point, and it is not
42 | possible to communicate using this pipe.
43 | }
44 | \examples{
45 | s <- socket(listen = "inproc://nanopipe")
46 | cv <- cv()
47 |
48 | pipe_notify(s, cv, add = TRUE, remove = TRUE, flag = TRUE)
49 | cv_value(cv)
50 |
51 | s1 <- socket(dial = "inproc://nanopipe")
52 | cv_value(cv)
53 | reap(s1)
54 | cv_value(cv)
55 |
56 | pipe_notify(s, NULL, add = TRUE, remove = TRUE)
57 | s1 <- socket(dial = "inproc://nanopipe")
58 | cv_value(cv)
59 | reap(s1)
60 |
61 | (wait(cv))
62 |
63 | close(s)
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/man/protocols.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/docs.R
3 | \name{protocols}
4 | \alias{protocols}
5 | \title{Protocols (Documentation)}
6 | \description{
7 | Protocols implemented by \pkg{nanonext}.
8 |
9 | For an authoritative guide please refer to the online documentation for the
10 | NNG library at \url{https://nng.nanomsg.org/man/}.
11 | }
12 | \section{Bus (mesh networks)}{
13 |
14 |
15 | \strong{[protocol, bus]} The bus protocol is useful for routing applications or
16 | for building mesh networks where every peer is connected to every other peer.
17 |
18 | In this protocol, each message sent by a node is sent to every one of its
19 | directly-connected peers. This protocol may be used to send and receive
20 | messages. Sending messages will attempt to deliver to each directly connected
21 | peer. Indirectly-connected peers will not receive messages. When using this
22 | protocol to build mesh networks, it is therefore important that a
23 | fully-connected mesh network be constructed.
24 |
25 | All message delivery in this pattern is best-effort, which means that peers
26 | may not receive messages. Furthermore, delivery may occur to some, all, or
27 | none of the directly connected peers (messages are not delivered when peer
28 | nodes are unable to receive). Hence, send operations will never block;
29 | instead if the message cannot be delivered for any reason it is discarded.
30 | }
31 |
32 | \section{Pair (two-way radio)}{
33 |
34 |
35 | \strong{[protocol, pair]} This is NNG's pair v0. The pair protocol implements a
36 | peer-to-peer pattern, where relationships between peers are one-to-one. Only
37 | one peer may be connected to another peer at a time, but both may send and
38 | receive messages freely.
39 |
40 | Normally, this pattern will block when attempting to send a message if no
41 | peer is able to receive the message.
42 | }
43 |
44 | \section{Poly (one-to-one of many)}{
45 |
46 |
47 | \strong{[protocol, poly]} This is NNG's pair v1 polyamorous mode. It allows a
48 | socket to communicate with multiple directly-connected peers.
49 |
50 | If no remote peer is specified by the sender, then the protocol willselect
51 | any available connected peer.
52 |
53 | If the peer on the given pipe is not able to receive (or the pipe is no
54 | longer available, such as if the peer has disconnected), then the message
55 | will be discarded with no notification to the sender.
56 | }
57 |
58 | \section{Push/Pull (one-way pipeline)}{
59 |
60 |
61 | In the pipeline pattern, pushers distribute messages to pullers, hence useful
62 | for solving producer/consumer problems.
63 |
64 | If multiple peers are connected, the pattern attempts to distribute fairly.
65 | Each message sent by a pusher will be sent to one of its peer pullers, chosen
66 | in a round-robin fashion. This property makes this pattern useful in
67 | load-balancing scenarios.
68 |
69 | \strong{[protocol, push]} The push protocol is one half of a pipeline pattern.
70 | The other side is the pull protocol.
71 |
72 | \strong{[protocol, pull]} The pull protocol is one half of a pipeline pattern.
73 | The other half is the push protocol.
74 | }
75 |
76 | \section{Publisher/Subscriber (topics & broadcast)}{
77 |
78 |
79 | In a publisher/subscriber pattern, a publisher sends data, which is broadcast
80 | to all subscribers. The subscriber only see the data to which they have
81 | subscribed.
82 |
83 | \strong{[protocol, pub]} The pub protocol is one half of a publisher/subscriber
84 | pattern. This protocol may be used to send messages, but is unable to receive
85 | them.
86 |
87 | \strong{[protocol, sub]} The sub protocol is one half of a publisher/subscriber
88 | pattern. This protocol may be used to receive messages, but is unable to send
89 | them.
90 | }
91 |
92 | \section{Request/Reply (RPC)}{
93 |
94 |
95 | In a request/reply pattern, a requester sends a message to one replier, who
96 | is expected to reply with a single answer. This is used for synchronous
97 | communications, for example remote procedure calls (RPCs).
98 |
99 | The request is resent automatically if no reply arrives, until a reply is
100 | received or the request times out.
101 |
102 | \strong{[protocol, req]} The req protocol is one half of a request/reply
103 | pattern. This socket may be used to send messages (requests), and then to
104 | receive replies. Generally a reply can only be received after sending a
105 | request.
106 |
107 | \strong{[protocol, rep]} The rep protocol is one half of a request/reply
108 | pattern. This socket may be used to receive messages (requests), and then to
109 | send replies. Generally a reply can only be sent after receiving a request.
110 | }
111 |
112 | \section{Surveyor/Respondent (voting & service discovery)}{
113 |
114 |
115 | In a survey pattern, a surveyor sends a survey, which is broadcast to all
116 | peer respondents. The respondents then have a chance to reply (but are not
117 | obliged). The survey itself is a timed event, so that responses received
118 | after the survey has finished are discarded.
119 |
120 | \strong{[protocol, surveyor]} The surveyor protocol is one half of a survey
121 | pattern. This protocol may be used to send messages (surveys), and then to
122 | receive replies. A reply can only be received after sending a survey. A
123 | surveyor can normally expect to receive at most one reply from each responder
124 | (messages may be duplicated in some topologies, so there is no guarantee of
125 | this).
126 |
127 | \strong{[protocol, respondent]} The respondent protocol is one half of a survey
128 | pattern. This protocol may be used to receive messages, and then to send
129 | replies. A reply can only be sent after receiving a survey, and generally the
130 | reply will be sent to the surveyor from which the last survey was received.
131 | }
132 |
133 |
--------------------------------------------------------------------------------
/man/random.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{random}
4 | \alias{random}
5 | \title{Random Data Generation}
6 | \usage{
7 | random(n = 1L, convert = TRUE)
8 | }
9 | \arguments{
10 | \item{n}{[default 1L] integer random bytes to generate (from 0 to 1024),
11 | coerced to integer if required. If a vector, the first element is taken.}
12 |
13 | \item{convert}{[default TRUE] logical \code{FALSE} to return a raw vector, or
14 | \code{TRUE} to return the hex representation of the bytes as a character string.}
15 | }
16 | \value{
17 | A length \code{n} raw vector, or length one vector of \verb{2n} random
18 | characters, depending on the value of \code{convert} supplied.
19 | }
20 | \description{
21 | Strictly not for use in statistical analysis. Non-reproducible and with
22 | unknown statistical properties. Provides an alternative source of randomness
23 | from the Mbed TLS library for purposes such as cryptographic key generation.
24 | Mbed TLS uses a block-cipher in counter mode operation, as defined in
25 | NIST SP800-90A: \emph{Recommendation for Random Number Generation Using
26 | Deterministic Random Bit Generators}. The implementation uses AES-256 as the
27 | underlying block cipher, with a derivation function, and an entropy collector
28 | combining entropy from multiple sources including at least one strong entropy
29 | source.
30 | }
31 | \note{
32 | Results obtained are independent of and do not alter the state of R's
33 | own pseudo-random number generators.
34 | }
35 | \examples{
36 | random()
37 | random(8L)
38 | random(n = 8L, convert = FALSE)
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/man/read_stdin.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{read_stdin}
4 | \alias{read_stdin}
5 | \title{Read stdin}
6 | \usage{
7 | read_stdin()
8 | }
9 | \value{
10 | a Socket.
11 | }
12 | \description{
13 | Reads \code{stdin} from a background thread, allowing the stream to be accessed as
14 | messages from an NNG 'inproc' socket. As the read is blocking, it can only be
15 | used in non-interactive sessions. Closing \code{stdin} causes the background
16 | thread to exit and the socket connection to end.
17 | }
18 | \details{
19 | A 'pull' protocol socket is returned, and hence can only be used with receive
20 | functions.
21 | }
22 |
--------------------------------------------------------------------------------
/man/reap.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/socket.R
3 | \name{reap}
4 | \alias{reap}
5 | \title{Reap}
6 | \usage{
7 | reap(con)
8 | }
9 | \arguments{
10 | \item{con}{a Socket, Context, Listener or Dialer.}
11 | }
12 | \value{
13 | An integer exit code (zero on success).
14 | }
15 | \description{
16 | An alternative to \code{close} for Sockets, Contexts, Listeners, and Dialers
17 | avoiding S3 method dispatch.
18 | }
19 | \details{
20 | May be used on unclassed external pointers e.g. those created by
21 | \code{\link[=.context]{.context()}}. Returns silently and does not warn or error, nor does it update
22 | the state of object attributes.
23 | }
24 | \examples{
25 | s <- socket("req")
26 | listen(s)
27 | dial(s)
28 | ctx <- .context(s)
29 |
30 | reap(ctx)
31 | reap(s[["dialer"]][[1]])
32 | reap(s[["listener"]][[1]])
33 | reap(s)
34 | reap(s)
35 |
36 | }
37 | \seealso{
38 | \code{\link[=close]{close()}}
39 | }
40 |
--------------------------------------------------------------------------------
/man/recv.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sendrecv.R
3 | \name{recv}
4 | \alias{recv}
5 | \title{Receive}
6 | \usage{
7 | recv(
8 | con,
9 | mode = c("serial", "character", "complex", "double", "integer", "logical", "numeric",
10 | "raw", "string"),
11 | block = NULL,
12 | n = 65536L
13 | )
14 | }
15 | \arguments{
16 | \item{con}{a Socket, Context or Stream.}
17 |
18 | \item{mode}{[default 'serial'] character value or integer equivalent - one
19 | of \code{"serial"} (1L), \code{"character"} (2L), \code{"complex"} (3L), \code{"double"} (4L),
20 | \code{"integer"} (5L), \code{"logical"} (6L), \code{"numeric"} (7L), \code{"raw"} (8L), or
21 | \code{"string"} (9L). The default \code{"serial"} means a serialised R object; for
22 | the other modes, received bytes are converted into the respective mode.
23 | \code{"string"} is a faster option for length one character vectors. For
24 | Streams, \code{"serial"} will default to \code{"character"}.}
25 |
26 | \item{block}{[default NULL] which applies the connection default (see
27 | section 'Blocking' below). Specify logical \code{TRUE} to block until successful
28 | or \code{FALSE} to return immediately even if unsuccessful (e.g. if no
29 | connection is available), or else an integer value specifying the maximum
30 | time to block in milliseconds, after which the operation will time out.}
31 |
32 | \item{n}{[default 65536L] applicable to Streams only, the maximum number of
33 | bytes to receive. Can be an over-estimate, but note that a buffer of this
34 | size is reserved.}
35 | }
36 | \value{
37 | The received data in the \code{mode} specified.
38 | }
39 | \description{
40 | Receive data over a connection (Socket, Context or Stream).
41 | }
42 | \section{Errors}{
43 |
44 |
45 | In case of an error, an integer 'errorValue' is returned (to be
46 | distiguishable from an integer message value). This can be verified using
47 | \code{\link[=is_error_value]{is_error_value()}}.
48 |
49 | If an error occurred in unserialization or conversion of the message data to
50 | the specified mode, a raw vector will be returned instead to allow recovery
51 | (accompanied by a warning).
52 | }
53 |
54 | \section{Blocking}{
55 |
56 |
57 | For Sockets and Contexts: the default behaviour is non-blocking with
58 | \code{block = FALSE}. This will return immediately with an error if no messages
59 | are available.
60 |
61 | For Streams: the default behaviour is blocking with \code{block = TRUE}. This will
62 | wait until a message is received. Set a timeout to ensure that the function
63 | returns under all scenarios. As the underlying implementation uses an
64 | asynchronous receive with a wait, it is recommended to set a small positive
65 | value for \code{block} rather than \code{FALSE}.
66 | }
67 |
68 | \examples{
69 | s1 <- socket("pair", listen = "inproc://nanonext")
70 | s2 <- socket("pair", dial = "inproc://nanonext")
71 |
72 | send(s1, data.frame(a = 1, b = 2))
73 | res <- recv(s2)
74 | res
75 | send(s1, data.frame(a = 1, b = 2))
76 | recv(s2)
77 |
78 | send(s1, c(1.1, 2.2, 3.3), mode = "raw")
79 | res <- recv(s2, mode = "double", block = 100)
80 | res
81 | send(s1, "example message", mode = "raw")
82 | recv(s2, mode = "character")
83 |
84 | close(s1)
85 | close(s2)
86 |
87 | req <- socket("req", listen = "inproc://nanonext")
88 | rep <- socket("rep", dial = "inproc://nanonext")
89 |
90 | ctxq <- context(req)
91 | ctxp <- context(rep)
92 | send(ctxq, data.frame(a = 1, b = 2), block = 100)
93 | recv(ctxp, block = 100)
94 |
95 | send(ctxq, c(1.1, 2.2, 3.3), mode = "raw", block = 100)
96 | recv(ctxp, mode = "double", block = 100)
97 |
98 | close(req)
99 | close(rep)
100 |
101 | }
102 | \seealso{
103 | \code{\link[=recv_aio]{recv_aio()}} for asynchronous receive.
104 | }
105 |
--------------------------------------------------------------------------------
/man/recv_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{recv_aio}
4 | \alias{recv_aio}
5 | \title{Receive Async}
6 | \usage{
7 | recv_aio(
8 | con,
9 | mode = c("serial", "character", "complex", "double", "integer", "logical", "numeric",
10 | "raw", "string"),
11 | timeout = NULL,
12 | cv = NULL,
13 | n = 65536L
14 | )
15 | }
16 | \arguments{
17 | \item{con}{a Socket, Context or Stream.}
18 |
19 | \item{mode}{[default 'serial'] character value or integer equivalent - one
20 | of \code{"serial"} (1L), \code{"character"} (2L), \code{"complex"} (3L), \code{"double"} (4L),
21 | \code{"integer"} (5L), \code{"logical"} (6L), \code{"numeric"} (7L), \code{"raw"} (8L), or
22 | \code{"string"} (9L). The default \code{"serial"} means a serialised R object; for
23 | the other modes, received bytes are converted into the respective mode.
24 | \code{"string"} is a faster option for length one character vectors. For
25 | Streams, \code{"serial"} will default to \code{"character"}.}
26 |
27 | \item{timeout}{[default NULL] integer value in milliseconds or NULL, which
28 | applies a socket-specific default, usually the same as no timeout.}
29 |
30 | \item{cv}{(optional) a 'conditionVariable' to signal when the async receive
31 | is complete.}
32 |
33 | \item{n}{[default 65536L] applicable to Streams only, the maximum number of
34 | bytes to receive. Can be an over-estimate, but note that a buffer of this
35 | size is reserved.}
36 | }
37 | \value{
38 | A 'recvAio' (object of class 'recvAio') (invisibly).
39 | }
40 | \description{
41 | Receive data asynchronously over a connection (Socket, Context or Stream).
42 | }
43 | \details{
44 | Async receive is always non-blocking and returns a 'recvAio' immediately.
45 |
46 | For a 'recvAio', the received message is available at \verb{$data}. An
47 | 'unresolved' logical NA is returned if the async operation is yet to
48 | complete.
49 |
50 | To wait for the async operation to complete and retrieve the received
51 | message, use \code{\link[=call_aio]{call_aio()}} on the returned 'recvAio' object.
52 |
53 | Alternatively, to stop the async operation, use \code{\link[=stop_aio]{stop_aio()}}.
54 |
55 | In case of an error, an integer 'errorValue' is returned (to be
56 | distiguishable from an integer message value). This can be checked using
57 | \code{\link[=is_error_value]{is_error_value()}}.
58 |
59 | If an error occurred in unserialization or conversion of the message data to
60 | the specified mode, a raw vector will be returned instead to allow recovery
61 | (accompanied by a warning).
62 | }
63 | \section{Signalling}{
64 |
65 |
66 | By supplying a 'conditionVariable', when the receive is complete, the
67 | 'conditionVariable' is signalled by incrementing its value by 1. This
68 | happens asynchronously and independently of the R execution thread.
69 | }
70 |
71 | \examples{
72 | s1 <- socket("pair", listen = "inproc://nanonext")
73 | s2 <- socket("pair", dial = "inproc://nanonext")
74 |
75 | res <- send_aio(s1, data.frame(a = 1, b = 2), timeout = 100)
76 | msg <- recv_aio(s2, timeout = 100)
77 | msg
78 | msg$data
79 |
80 | res <- send_aio(s1, c(1.1, 2.2, 3.3), mode = "raw", timeout = 100)
81 | msg <- recv_aio(s2, mode = "double", timeout = 100)
82 | msg
83 | msg$data
84 |
85 | res <- send_aio(s1, "example message", mode = "raw", timeout = 100)
86 | msg <- recv_aio(s2, mode = "character", timeout = 100)
87 | call_aio(msg)
88 | msg$data
89 |
90 | close(s1)
91 | close(s2)
92 |
93 | # Signalling a condition variable
94 |
95 | s1 <- socket("pair", listen = "inproc://cv-example")
96 | cv <- cv()
97 | msg <- recv_aio(s1, timeout = 100, cv = cv)
98 | until(cv, 10L)
99 | msg$data
100 | close(s1)
101 |
102 | # in another process in parallel
103 | s2 <- socket("pair", dial = "inproc://cv-example")
104 | res <- send_aio(s2, c(1.1, 2.2, 3.3), mode = "raw", timeout = 100)
105 | close(s2)
106 |
107 | }
108 | \seealso{
109 | \code{\link[=recv]{recv()}} for synchronous receive.
110 | }
111 |
--------------------------------------------------------------------------------
/man/reply.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/context.R
3 | \name{reply}
4 | \alias{reply}
5 | \title{Reply over Context (RPC Server for Req/Rep Protocol)}
6 | \usage{
7 | reply(
8 | context,
9 | execute,
10 | recv_mode = c("serial", "character", "complex", "double", "integer", "logical",
11 | "numeric", "raw", "string"),
12 | send_mode = c("serial", "raw"),
13 | timeout = NULL,
14 | ...
15 | )
16 | }
17 | \arguments{
18 | \item{context}{a Context.}
19 |
20 | \item{execute}{a function which takes the received (converted) data as its
21 | first argument. Can be an anonymous function of the form
22 | \code{function(x) do(x)}. Additional arguments can also be passed in through
23 | \code{...}.}
24 |
25 | \item{recv_mode}{[default 'serial'] character value or integer equivalent -
26 | one of \code{"serial"} (1L), \code{"character"} (2L), \code{"complex"} (3L), \code{"double"}
27 | (4L), \code{"integer"} (5L), \code{"logical"} (6L), \code{"numeric"} (7L), \code{"raw"} (8L),
28 | or \code{"string"} (9L). The default \code{"serial"} means a serialised R object; for
29 | the other modes, received bytes are converted into the respective mode.
30 | \code{"string"} is a faster option for length one character vectors.}
31 |
32 | \item{send_mode}{[default 'serial'] character value or integer equivalent -
33 | either \code{"serial"} (1L) to send serialised R objects, or \code{"raw"} (2L) to
34 | send atomic vectors of any type as a raw byte vector.}
35 |
36 | \item{timeout}{[default NULL] integer value in milliseconds or NULL, which
37 | applies a socket-specific default, usually the same as no timeout. Note
38 | that this applies to receiving the request. The total elapsed time would
39 | also include performing 'execute' on the received data. The timeout then
40 | also applies to sending the result (in the event that the requestor has
41 | become unavailable since sending the request).}
42 |
43 | \item{...}{additional arguments passed to the function specified by
44 | 'execute'.}
45 | }
46 | \value{
47 | Integer exit code (zero on success).
48 | }
49 | \description{
50 | Implements an executor/server for the rep node of the req/rep protocol.
51 | Awaits data, applies an arbitrary specified function, and returns the result
52 | to the caller/client.
53 | }
54 | \details{
55 | Receive will block while awaiting a message to arrive and is usually the
56 | desired behaviour. Set a timeout to allow the function to return if no data
57 | is forthcoming.
58 |
59 | In the event of an error in either processing the messages or in evaluation
60 | of the function with respect to the data, a nul byte \code{00} (or serialized
61 | nul byte) will be sent in reply to the client to signal an error. This is to
62 | be distinguishable from a possible return value. \code{\link[=is_nul_byte]{is_nul_byte()}} can be used
63 | to test for a nul byte.
64 | }
65 | \section{Send Modes}{
66 |
67 |
68 | The default mode \code{"serial"} sends serialised R objects to ensure perfect
69 | reproducibility within R. When receiving, the corresponding mode \code{"serial"}
70 | should be used. Custom serialization and unserialization functions for
71 | reference objects may be enabled by the function \code{\link[=serial_config]{serial_config()}}.
72 |
73 | Mode \code{"raw"} sends atomic vectors of any type as a raw byte vector, and must
74 | be used when interfacing with external applications or raw system sockets,
75 | where R serialization is not in use. When receiving, the mode corresponding
76 | to the vector sent should be used.
77 | }
78 |
79 | \examples{
80 | req <- socket("req", listen = "inproc://req-example")
81 | rep <- socket("rep", dial = "inproc://req-example")
82 |
83 | ctxq <- context(req)
84 | ctxp <- context(rep)
85 |
86 | send(ctxq, 2022, block = 100)
87 | reply(ctxp, execute = function(x) x + 1, send_mode = "raw", timeout = 100)
88 | recv(ctxq, mode = "double", block = 100)
89 |
90 | send(ctxq, 100, mode = "raw", block = 100)
91 | reply(ctxp, recv_mode = "double", execute = log, base = 10, timeout = 100)
92 | recv(ctxq, block = 100)
93 |
94 | close(req)
95 | close(rep)
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/man/request.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/context.R
3 | \name{request}
4 | \alias{request}
5 | \title{Request over Context (RPC Client for Req/Rep Protocol)}
6 | \usage{
7 | request(
8 | context,
9 | data,
10 | send_mode = c("serial", "raw"),
11 | recv_mode = c("serial", "character", "complex", "double", "integer", "logical",
12 | "numeric", "raw", "string"),
13 | timeout = NULL,
14 | cv = NULL,
15 | id = NULL
16 | )
17 | }
18 | \arguments{
19 | \item{context}{a Context.}
20 |
21 | \item{data}{an object (if \code{send_mode = "raw"}, a vector).}
22 |
23 | \item{send_mode}{[default 'serial'] character value or integer equivalent -
24 | either \code{"serial"} (1L) to send serialised R objects, or \code{"raw"} (2L) to
25 | send atomic vectors of any type as a raw byte vector.}
26 |
27 | \item{recv_mode}{[default 'serial'] character value or integer equivalent -
28 | one of \code{"serial"} (1L), \code{"character"} (2L), \code{"complex"} (3L), \code{"double"}
29 | (4L), \code{"integer"} (5L), \code{"logical"} (6L), \code{"numeric"} (7L), \code{"raw"} (8L),
30 | or \code{"string"} (9L). The default \code{"serial"} means a serialised R object; for
31 | the other modes, received bytes are converted into the respective mode.
32 | \code{"string"} is a faster option for length one character vectors.}
33 |
34 | \item{timeout}{[default NULL] integer value in milliseconds or NULL, which
35 | applies a socket-specific default, usually the same as no timeout.}
36 |
37 | \item{cv}{(optional) a 'conditionVariable' to signal when the async receive
38 | is complete, or NULL. If any other value is supplied, this will cause the
39 | pipe connection to be dropped when the async receive is complete.}
40 |
41 | \item{id}{(optional) specify a non-NULL value to send a message via the
42 | context upon timeout (asynchronously) consisting of an integer zero,
43 | followed by the integer context ID.}
44 | }
45 | \value{
46 | A 'recvAio' (object of class 'mirai' and 'recvAio') (invisibly).
47 | }
48 | \description{
49 | Implements a caller/client for the req node of the req/rep protocol. Sends
50 | data to the rep node (executor/server) and returns an Aio, which can be
51 | called for the value when required.
52 | }
53 | \details{
54 | Sending the request and receiving the result are both performed async, hence
55 | the function will return immediately with a 'recvAio' object. Access the
56 | return value at \verb{$data}.
57 |
58 | This is designed so that the process on the server can run concurrently
59 | without blocking the client.
60 |
61 | Optionally use \code{\link[=call_aio]{call_aio()}} on the 'recvAio' to call (and wait for) the
62 | result.
63 |
64 | If an error occured in the server process, a nul byte \code{00} will be received.
65 | This allows an error to be easily distinguished from a NULL return value.
66 | \code{\link[=is_nul_byte]{is_nul_byte()}} can be used to test for a nul byte.
67 |
68 | It is recommended to use a new context for each request to ensure consistent
69 | state tracking. For safety, the context used for the request is closed when
70 | all references to the returned 'recvAio' are removed and the object is
71 | garbage collected.
72 | }
73 | \section{Send Modes}{
74 |
75 |
76 | The default mode \code{"serial"} sends serialised R objects to ensure perfect
77 | reproducibility within R. When receiving, the corresponding mode \code{"serial"}
78 | should be used. Custom serialization and unserialization functions for
79 | reference objects may be enabled by the function \code{\link[=serial_config]{serial_config()}}.
80 |
81 | Mode \code{"raw"} sends atomic vectors of any type as a raw byte vector, and must
82 | be used when interfacing with external applications or raw system sockets,
83 | where R serialization is not in use. When receiving, the mode corresponding
84 | to the vector sent should be used.
85 | }
86 |
87 | \section{Signalling}{
88 |
89 |
90 | By supplying a 'conditionVariable', when the receive is complete, the
91 | 'conditionVariable' is signalled by incrementing its value by 1. This
92 | happens asynchronously and independently of the R execution thread.
93 | }
94 |
95 | \examples{
96 | \dontrun{
97 |
98 | # works if req and rep are running in parallel in different processes
99 |
100 | req <- socket("req", listen = "tcp://127.0.0.1:6546")
101 | rep <- socket("rep", dial = "tcp://127.0.0.1:6546")
102 |
103 | reply(.context(rep), execute = function(x) x + 1, timeout = 50)
104 | aio <- request(.context(req), data = 2022)
105 | aio$data
106 |
107 | close(req)
108 | close(rep)
109 |
110 | # Signalling a condition variable
111 |
112 | req <- socket("req", listen = "tcp://127.0.0.1:6546")
113 | ctxq <- context(req)
114 | cv <- cv()
115 | aio <- request(ctxq, data = 2022, cv = cv)
116 | until(cv, 10L)
117 | close(req)
118 |
119 | # The following should be run in another process
120 | rep <- socket("rep", dial = "tcp://127.0.0.1:6546")
121 | ctxp <- context(rep)
122 | reply(ctxp, execute = function(x) x + 1)
123 | close(rep)
124 |
125 | }
126 |
127 | }
128 |
--------------------------------------------------------------------------------
/man/send.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sendrecv.R
3 | \name{send}
4 | \alias{send}
5 | \title{Send}
6 | \usage{
7 | send(con, data, mode = c("serial", "raw"), block = NULL, pipe = 0L)
8 | }
9 | \arguments{
10 | \item{con}{a Socket, Context or Stream.}
11 |
12 | \item{data}{an object (a vector, if \code{mode = "raw"}).}
13 |
14 | \item{mode}{[default 'serial'] character value or integer equivalent -
15 | either \code{"serial"} (1L) to send serialised R objects, or \code{"raw"} (2L) to
16 | send atomic vectors of any type as a raw byte vector. For Streams, \code{"raw"}
17 | is the only option and this argument is ignored.}
18 |
19 | \item{block}{[default NULL] which applies the connection default (see
20 | section 'Blocking' below). Specify logical \code{TRUE} to block until successful
21 | or \code{FALSE} to return immediately even if unsuccessful (e.g. if no
22 | connection is available), or else an integer value specifying the maximum
23 | time to block in milliseconds, after which the operation will time out.}
24 |
25 | \item{pipe}{[default 0L] only applicable to Sockets using the 'poly'
26 | protocol, an integer pipe ID if directing the send via a specific pipe.}
27 | }
28 | \value{
29 | An integer exit code (zero on success).
30 | }
31 | \description{
32 | Send data over a connection (Socket, Context or Stream).
33 | }
34 | \section{Blocking}{
35 |
36 |
37 | For Sockets and Contexts: the default behaviour is non-blocking with
38 | \code{block = FALSE}. This will return immediately with an error if the message
39 | could not be queued for sending. Certain protocol / transport combinations
40 | may limit the number of messages that can be queued if they have yet to be
41 | received.
42 |
43 | For Streams: the default behaviour is blocking with \code{block = TRUE}. This will
44 | wait until the send has completed. Set a timeout to ensure that the function
45 | returns under all scenarios. As the underlying implementation uses an
46 | asynchronous send with a wait, it is recommended to set a small positive
47 | value for \code{block} rather than \code{FALSE}.
48 | }
49 |
50 | \section{Send Modes}{
51 |
52 |
53 | The default mode \code{"serial"} sends serialised R objects to ensure perfect
54 | reproducibility within R. When receiving, the corresponding mode \code{"serial"}
55 | should be used. Custom serialization and unserialization functions for
56 | reference objects may be enabled by the function \code{\link[=serial_config]{serial_config()}}.
57 |
58 | Mode \code{"raw"} sends atomic vectors of any type as a raw byte vector, and must
59 | be used when interfacing with external applications or raw system sockets,
60 | where R serialization is not in use. When receiving, the mode corresponding
61 | to the vector sent should be used.
62 | }
63 |
64 | \examples{
65 | pub <- socket("pub", dial = "inproc://nanonext")
66 |
67 | send(pub, data.frame(a = 1, b = 2))
68 | send(pub, c(10.1, 20.2, 30.3), mode = "raw", block = 100)
69 |
70 | close(pub)
71 |
72 | req <- socket("req", listen = "inproc://nanonext")
73 | rep <- socket("rep", dial = "inproc://nanonext")
74 |
75 | ctx <- context(req)
76 | send(ctx, data.frame(a = 1, b = 2), block = 100)
77 |
78 | msg <- recv_aio(rep, timeout = 100)
79 | send(ctx, c(1.1, 2.2, 3.3), mode = "raw", block = 100)
80 |
81 | close(req)
82 | close(rep)
83 |
84 | }
85 | \seealso{
86 | \code{\link[=send_aio]{send_aio()}} for asynchronous send.
87 | }
88 |
--------------------------------------------------------------------------------
/man/send_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{send_aio}
4 | \alias{send_aio}
5 | \title{Send Async}
6 | \usage{
7 | send_aio(con, data, mode = c("serial", "raw"), timeout = NULL, pipe = 0L)
8 | }
9 | \arguments{
10 | \item{con}{a Socket, Context or Stream.}
11 |
12 | \item{data}{an object (a vector, if \code{mode = "raw"}).}
13 |
14 | \item{mode}{[default 'serial'] character value or integer equivalent -
15 | either \code{"serial"} (1L) to send serialised R objects, or \code{"raw"} (2L) to
16 | send atomic vectors of any type as a raw byte vector. For Streams, \code{"raw"}
17 | is the only option and this argument is ignored.}
18 |
19 | \item{timeout}{[default NULL] integer value in milliseconds or NULL, which
20 | applies a socket-specific default, usually the same as no timeout.}
21 |
22 | \item{pipe}{[default 0L] only applicable to Sockets using the 'poly'
23 | protocol, an integer pipe ID if directing the send via a specific pipe.}
24 | }
25 | \value{
26 | A 'sendAio' (object of class 'sendAio') (invisibly).
27 | }
28 | \description{
29 | Send data asynchronously over a connection (Socket, Context, Stream or Pipe).
30 | }
31 | \details{
32 | Async send is always non-blocking and returns a 'sendAio' immediately.
33 |
34 | For a 'sendAio', the send result is available at \verb{$result}. An 'unresolved'
35 | logical NA is returned if the async operation is yet to complete. The
36 | resolved value will be zero on success, or else an integer error code.
37 |
38 | To wait for and check the result of the send operation, use \code{\link[=call_aio]{call_aio()}} on
39 | the returned 'sendAio' object.
40 |
41 | Alternatively, to stop the async operation, use \code{\link[=stop_aio]{stop_aio()}}.
42 | }
43 | \section{Send Modes}{
44 |
45 |
46 | The default mode \code{"serial"} sends serialised R objects to ensure perfect
47 | reproducibility within R. When receiving, the corresponding mode \code{"serial"}
48 | should be used. Custom serialization and unserialization functions for
49 | reference objects may be enabled by the function \code{\link[=serial_config]{serial_config()}}.
50 |
51 | Mode \code{"raw"} sends atomic vectors of any type as a raw byte vector, and must
52 | be used when interfacing with external applications or raw system sockets,
53 | where R serialization is not in use. When receiving, the mode corresponding
54 | to the vector sent should be used.
55 | }
56 |
57 | \examples{
58 | pub <- socket("pub", dial = "inproc://nanonext")
59 |
60 | res <- send_aio(pub, data.frame(a = 1, b = 2), timeout = 100)
61 | res
62 | res$result
63 |
64 | res <- send_aio(pub, "example message", mode = "raw", timeout = 100)
65 | call_aio(res)$result
66 |
67 | close(pub)
68 |
69 | }
70 | \seealso{
71 | \code{\link[=send]{send()}} for synchronous send.
72 | }
73 |
--------------------------------------------------------------------------------
/man/serial_config.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{serial_config}
4 | \alias{serial_config}
5 | \title{Create Serialization Configuration}
6 | \usage{
7 | serial_config(class, sfunc, ufunc)
8 | }
9 | \arguments{
10 | \item{class}{a character string (or vector) of the class of object custom
11 | serialization functions are applied to, e.g. \code{'ArrowTabular'} or
12 | \code{c('torch_tensor', 'ArrowTabular')}.}
13 |
14 | \item{sfunc}{a function (or list of functions) that accepts a reference
15 | object inheriting from \code{class} and returns a raw vector.}
16 |
17 | \item{ufunc}{a function (or list of functions) that accepts a raw vector and
18 | returns a reference object.}
19 | }
20 | \value{
21 | A list comprising the configuration. This should be set on a Socket
22 | using \code{\link[=opt<-]{opt<-()}} with option name \code{"serial"}.
23 | }
24 | \description{
25 | Returns a serialization configuration, which may be set on a Socket for
26 | custom serialization and unserialization of non-system reference objects,
27 | allowing these to be sent and received between different R sessions. Once
28 | set, the functions apply to all send and receive operations performed in mode
29 | 'serial' over the Socket, or Context created from the Socket.
30 | }
31 | \details{
32 | This feature utilises the 'refhook' system of R native serialization.
33 | }
34 | \examples{
35 | cfg <- serial_config("test_cls", function(x) serialize(x, NULL), unserialize)
36 | cfg
37 |
38 | cfg <- serial_config(
39 | c("class_one", "class_two"),
40 | list(function(x) serialize(x, NULL), function(x) serialize(x, NULL)),
41 | list(unserialize, unserialize)
42 | )
43 | cfg
44 |
45 | s <- socket()
46 | opt(s, "serial") <- cfg
47 |
48 | # provide an empty list to remove registered functions
49 | opt(s, "serial") <- list()
50 |
51 | close(s)
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/man/socket.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/socket.R
3 | \name{socket}
4 | \alias{socket}
5 | \title{Open Socket}
6 | \usage{
7 | socket(
8 | protocol = c("bus", "pair", "poly", "push", "pull", "pub", "sub", "req", "rep",
9 | "surveyor", "respondent"),
10 | dial = NULL,
11 | listen = NULL,
12 | tls = NULL,
13 | autostart = TRUE,
14 | raw = FALSE
15 | )
16 | }
17 | \arguments{
18 | \item{protocol}{[default 'bus'] choose protocol - \code{"bus"}, \code{"pair"},
19 | \code{"poly"}, \code{"push"}, \code{"pull"}, \code{"pub"}, \code{"sub"}, \code{"req"}, \code{"rep"},
20 | \code{"surveyor"}, or \code{"respondent"} - see \link{protocols}.}
21 |
22 | \item{dial}{(optional) a URL to dial, specifying the transport and address as
23 | a character string e.g. 'inproc://anyvalue' or 'tcp://127.0.0.1:5555' (see
24 | \link{transports}).}
25 |
26 | \item{listen}{(optional) a URL to listen at, specifying the transport and
27 | address as a character string e.g. 'inproc://anyvalue' or
28 | 'tcp://127.0.0.1:5555' (see \link{transports}).}
29 |
30 | \item{tls}{[default NULL] for secure tls+tcp:// or wss:// connections only,
31 | provide a TLS configuration object created by \code{\link[=tls_config]{tls_config()}}.}
32 |
33 | \item{autostart}{[default TRUE] whether to start the dialer/listener. Set
34 | to FALSE if setting configuration options on the dialer/listener as it is
35 | not generally possible to change these once started. For dialers only: set
36 | to NA to start synchronously - this is less resilient if a connection is
37 | not immediately possible, but avoids subtle errors from attempting to use
38 | the socket before an asynchronous dial has completed.}
39 |
40 | \item{raw}{[default FALSE] whether to open raw mode sockets. Note: not for
41 | general use - do not enable unless you have a specific need (refer to NNG
42 | documentation).}
43 | }
44 | \value{
45 | A Socket (object of class 'nanoSocket' and 'nano').
46 | }
47 | \description{
48 | Open a Socket implementing \code{protocol}, and optionally dial (establish an
49 | outgoing connection) or listen (accept an incoming connection) at an address.
50 | }
51 | \details{
52 | NNG presents a socket view of networking. The sockets are constructed using
53 | protocol-specific functions, as a given socket implements precisely one
54 | protocol.
55 |
56 | Each socket may be used to send and receive messages (if the protocol
57 | supports it, and implements the appropriate protocol semantics). For example,
58 | sub sockets automatically filter incoming messages to discard those for
59 | topics that have not been subscribed.
60 |
61 | This function (optionally) binds a single Dialer and/or Listener to a Socket.
62 | More complex network topologies may be created by binding further Dialers /
63 | Listeners to the Socket as required using \code{\link[=dial]{dial()}} and \code{\link[=listen]{listen()}}.
64 |
65 | New contexts may also be created using \code{\link[=context]{context()}} if the protocol supports
66 | it.
67 | }
68 | \section{Protocols}{
69 |
70 |
71 | The following Scalability Protocols (communication patterns) are implemented:
72 | \itemize{
73 | \item Bus (mesh networks) - protocol: 'bus'
74 | \item Pair (two-way radio) - protocol: 'pair'
75 | \item Poly (one-to-one of many) - protocol: 'poly'
76 | \item Pipeline (one-way pipe) - protocol: 'push', 'pull'
77 | \item Publisher/Subscriber (topics & broadcast) - protocol: 'pub', 'sub'
78 | \item Request/Reply (RPC) - protocol: 'req', 'rep'
79 | \item Survey (voting & service discovery) - protocol: 'surveyor',
80 | 'respondent'
81 | }
82 |
83 | Please see \link{protocols} for further documentation.
84 | }
85 |
86 | \section{Transports}{
87 |
88 |
89 | The following communications transports may be used:
90 |
91 | \itemize{
92 | \item Inproc (in-process) - url: 'inproc://'
93 | \item IPC (inter-process communications) - url: 'ipc://' (or 'abstract://'
94 | on Linux)
95 | \item TCP and TLS over TCP - url: 'tcp://' and 'tls+tcp://'
96 | \item WebSocket and TLS over WebSocket - url: 'ws://' and 'wss://'
97 | }
98 |
99 | Please see \link{transports} for further documentation.
100 | }
101 |
102 | \examples{
103 | s <- socket(protocol = "req", listen = "inproc://nanosocket")
104 | s
105 | s1 <- socket(protocol = "rep", dial = "inproc://nanosocket")
106 | s1
107 |
108 | send(s, "hello world!")
109 | recv(s1)
110 |
111 | close(s1)
112 | close(s)
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/man/start.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/listdial.R
3 | \name{start}
4 | \alias{start}
5 | \alias{start.nanoListener}
6 | \alias{start.nanoDialer}
7 | \title{Start Listener/Dialer}
8 | \usage{
9 | \method{start}{nanoListener}(x, ...)
10 |
11 | \method{start}{nanoDialer}(x, async = TRUE, ...)
12 | }
13 | \arguments{
14 | \item{x}{a Listener or Dialer.}
15 |
16 | \item{...}{not used.}
17 |
18 | \item{async}{[default TRUE] (applicable to Dialers only) logical flag
19 | whether the connection attempt, including any name resolution, is to be
20 | made asynchronously. This behaviour is more resilient, but also generally
21 | makes diagnosing failures somewhat more difficult. If FALSE, failure, such
22 | as if the connection is refused, will be returned immediately, and no
23 | further action will be taken.}
24 | }
25 | \value{
26 | Invisibly, an integer exit code (zero on success).
27 | }
28 | \description{
29 | Start a Listener/Dialer.
30 | }
31 |
--------------------------------------------------------------------------------
/man/stat.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stats.R
3 | \name{stat}
4 | \alias{stat}
5 | \title{Get Statistic for a Socket, Listener or Dialer}
6 | \usage{
7 | stat(object, name)
8 | }
9 | \arguments{
10 | \item{object}{a Socket, Listener or Dialer.}
11 |
12 | \item{name}{character name of statistic to return.}
13 | }
14 | \value{
15 | The value of the statistic (character or double depending on the type
16 | of statistic requested) if available, or else NULL.
17 | }
18 | \description{
19 | Obtain value of a statistic for a Socket, Listener or Dialer. This function
20 | exposes the stats interface of NNG.
21 | }
22 | \details{
23 | Note: the values of individual statistics are guaranteed to be atomic, but
24 | due to the way statistics are collected there may be discrepancies between
25 | them at times. For example, statistics counting bytes and messages received
26 | may not reflect the same number of messages, depending on when the snapshot
27 | is taken. This potential inconsistency arises as a result of optimisations to
28 | minimise the impact of statistics on actual operations.
29 | }
30 | \section{Stats}{
31 |
32 |
33 | The following stats may be requested for a Socket:
34 | \itemize{
35 | \item 'id' - numeric id of the socket.
36 | \item 'name' - character socket name.
37 | \item 'protocol' - character protocol type e.g. 'bus'.
38 | \item 'pipes' - numeric number of pipes (active connections).
39 | \item 'dialers' - numeric number of listeners attached to the socket.
40 | \item 'listeners' - numeric number of dialers attached to the socket.
41 | }
42 |
43 | The following stats may be requested for a Listener / Dialer:
44 | \itemize{
45 | \item 'id' - numeric id of the listener / dialer.
46 | \item 'socket' - numeric id of the socket of the listener / dialer.
47 | \item 'url' - character URL address.
48 | \item 'pipes' - numeric number of pipes (active connections).
49 | }
50 |
51 | The following additional stats may be requested for a Listener:
52 | \itemize{
53 | \item 'accept' - numeric total number of connection attempts, whether
54 | successful or not.
55 | \item 'reject' - numeric total number of rejected connection attempts e.g.
56 | due to incompatible protocols.
57 | }
58 |
59 | The following additional stats may be requested for a Dialer:
60 | \itemize{
61 | \item 'connect' - numeric total number of connection attempts, whether
62 | successful or not.
63 | \item 'reject' - numeric total number of rejected connection attempts e.g.
64 | due to incompatible protocols.
65 | \item 'refused' - numeric total number of refused connections e.g. when
66 | starting synchronously with no listener on the other side.
67 | }
68 | }
69 |
70 | \examples{
71 | s <- socket("bus", listen = "inproc://stats")
72 | stat(s, "pipes")
73 |
74 | s1 <- socket("bus", dial = "inproc://stats")
75 | stat(s, "pipes")
76 |
77 | close(s1)
78 | stat(s, "pipes")
79 |
80 | close(s)
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/man/status_code.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{status_code}
4 | \alias{status_code}
5 | \title{Translate HTTP Status Codes}
6 | \usage{
7 | status_code(x)
8 | }
9 | \arguments{
10 | \item{x}{numeric HTTP status code to translate.}
11 | }
12 | \value{
13 | A character vector comprising the status code and explanation
14 | separated by \code{'|'}.
15 | }
16 | \description{
17 | Provides an explanation for HTTP response status codes (in the range 100 to
18 | 599). If the status code is not defined as per RFC 9110,
19 | \code{"Unknown HTTP Status"} is returned - this may be a custom code used by the
20 | server.
21 | }
22 | \examples{
23 | status_code(200)
24 | status_code(404)
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/man/stop_aio.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{stop_aio}
4 | \alias{stop_aio}
5 | \title{Stop Asynchronous Aio Operation}
6 | \usage{
7 | stop_aio(x)
8 | }
9 | \arguments{
10 | \item{x}{an Aio or list of Aios (objects of class 'sendAio', 'recvAio' or
11 | 'ncurlAio').}
12 | }
13 | \value{
14 | Invisible NULL.
15 | }
16 | \description{
17 | Stop an asynchronous Aio operation, or a list of Aio operations.
18 | }
19 | \details{
20 | Stops the asynchronous I/O operation associated with Aio \code{x} by aborting, and
21 | then waits for it to complete or to be completely aborted, and for the
22 | callback associated with the Aio to have completed executing. If successful,
23 | the Aio will resolve to an 'errorValue' 20 (Operation canceled).
24 |
25 | Note this function operates silently and does not error even if \code{x} is not an
26 | active Aio, always returning invisible NULL.
27 | }
28 |
--------------------------------------------------------------------------------
/man/stream.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/stream.R
3 | \name{stream}
4 | \alias{stream}
5 | \title{Open Stream}
6 | \usage{
7 | stream(dial = NULL, listen = NULL, textframes = FALSE, tls = NULL)
8 | }
9 | \arguments{
10 | \item{dial}{a URL to dial, specifying the transport and address as a
11 | character string e.g. 'ipc:///tmp/anyvalue' or 'tcp://127.0.0.1:5555' (not
12 | all transports are supported).}
13 |
14 | \item{listen}{a URL to listen at, specifying the transport and address as a
15 | character string e.g. 'ipc:///tmp/anyvalue' or 'tcp://127.0.0.1:5555' (not
16 | all transports are supported).}
17 |
18 | \item{textframes}{[default FALSE] applicable to the websocket transport
19 | only, enables sending and receiving of TEXT frames (ignored otherwise).}
20 |
21 | \item{tls}{(optional) applicable to secure websockets only, a client or
22 | server TLS configuration object created by \code{\link[=tls_config]{tls_config()}}. If missing or
23 | NULL, certificates are not validated.}
24 | }
25 | \value{
26 | A Stream (object of class 'nanoStream' and 'nano').
27 | }
28 | \description{
29 | Open a Stream by either dialing (establishing an outgoing connection) or
30 | listening (accepting an incoming connection) at an address. This is a
31 | low-level interface intended for communicating with non-NNG endpoints.
32 | }
33 | \details{
34 | A Stream is used for raw byte stream connections. Byte streams are reliable
35 | in that data will not be delivered out of order, or with portions missing.
36 |
37 | Can be used to dial a (secure) websocket address starting 'ws://' or
38 | 'wss://'. It is often the case that \code{textframes} needs to be set to \code{TRUE}.
39 |
40 | Specify only one of \code{dial} or \code{listen}. If both are specified, \code{listen} will
41 | be ignored.
42 |
43 | Closing a stream renders it invalid and attempting to perform additional
44 | operations on it will error.
45 | }
46 | \examples{
47 | # Will succeed only if there is an open connection at the address:
48 | s <- tryCatch(stream(dial = "tcp://127.0.0.1:5555"), error = identity)
49 | s
50 | \dontshow{if (interactive()) withAutoprint(\{ # examplesIf}
51 | # Run in interactive sessions only as connection is not always available:
52 | s <- tryCatch(
53 | stream(dial = "wss://echo.websocket.events/", textframes = TRUE),
54 | error = identity
55 | )
56 | s
57 | if (is_nano(s)) recv(s)
58 | if (is_nano(s)) send(s, "hello")
59 | if (is_nano(s)) recv(s)
60 | if (is_nano(s)) close(s)
61 | \dontshow{\}) # examplesIf}
62 | }
63 |
--------------------------------------------------------------------------------
/man/subscribe.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/opts.R
3 | \name{subscribe}
4 | \alias{subscribe}
5 | \alias{unsubscribe}
6 | \title{Subscribe / Unsubscribe Topic}
7 | \usage{
8 | subscribe(con, topic = NULL)
9 |
10 | unsubscribe(con, topic = NULL)
11 | }
12 | \arguments{
13 | \item{con}{a Socket or Context using the 'sub' protocol.}
14 |
15 | \item{topic}{[default NULL] an atomic type or \code{NULL}. The default \code{NULL}
16 | subscribes to all topics / unsubscribes from all topics (if all topics were
17 | previously subscribed).}
18 | }
19 | \value{
20 | Invisibly, the passed Socket or Context.
21 | }
22 | \description{
23 | For a socket or context using the sub protocol in a publisher/subscriber
24 | pattern. Set a topic to subscribe to, or remove a topic from the subscription
25 | list.
26 | }
27 | \details{
28 | To use pub/sub the publisher must:
29 | \itemize{
30 | \item specify \code{mode = 'raw'} when sending.
31 | \item ensure the sent vector starts with the topic.
32 | }
33 | The subscriber should then receive specifying the correct mode.
34 | }
35 | \examples{
36 | pub <- socket("pub", listen = "inproc://nanonext")
37 | sub <- socket("sub", dial = "inproc://nanonext")
38 |
39 | subscribe(sub, "examples")
40 |
41 | send(pub, c("examples", "this is an example"), mode = "raw")
42 | recv(sub, "character")
43 | send(pub, "examples will also be received", mode = "raw")
44 | recv(sub, "character")
45 | send(pub, c("other", "this other topic will not be received"), mode = "raw")
46 | recv(sub, "character")
47 | unsubscribe(sub, "examples")
48 | send(pub, c("examples", "this example is no longer received"), mode = "raw")
49 | recv(sub, "character")
50 |
51 | subscribe(sub, 2)
52 | send(pub, c(2, 10, 10, 20), mode = "raw")
53 | recv(sub, "double")
54 | unsubscribe(sub, 2)
55 | send(pub, c(2, 10, 10, 20), mode = "raw")
56 | recv(sub, "double")
57 |
58 | close(pub)
59 | close(sub)
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/man/survey_time.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/opts.R
3 | \name{survey_time}
4 | \alias{survey_time}
5 | \title{Set Survey Time}
6 | \usage{
7 | survey_time(con, value = 1000L)
8 | }
9 | \arguments{
10 | \item{con}{a Socket or Context using the 'surveyor' protocol.}
11 |
12 | \item{value}{[default 1000L] integer survey timeout in milliseconds.}
13 | }
14 | \value{
15 | Invisibly, the passed Socket or Context.
16 | }
17 | \description{
18 | For a socket or context using the surveyor protocol in a surveyor/respondent
19 | pattern. Set the survey timeout in milliseconds (remains valid for all
20 | subsequent surveys). Messages received by the surveyor after the timer has
21 | ended are discarded.
22 | }
23 | \details{
24 | After using this function, to start a new survey, the surveyor must:
25 | \itemize{
26 | \item send a message.
27 | \item switch to receiving responses.
28 | }
29 |
30 | To respond to a survey, the respondent must:
31 | \itemize{
32 | \item receive the survey message.
33 | \item send a reply using \code{\link[=send_aio]{send_aio()}} before the survey has timed out (a
34 | reply can only be sent after receiving a survey).
35 | }
36 | }
37 | \examples{
38 | sur <- socket("surveyor", listen = "inproc://nanonext")
39 | res <- socket("respondent", dial = "inproc://nanonext")
40 |
41 | survey_time(sur, 1000)
42 |
43 | send(sur, "reply to this survey")
44 | aio <- recv_aio(sur)
45 |
46 | recv(res)
47 | s <- send_aio(res, "replied")
48 |
49 | call_aio(aio)$data
50 |
51 | close(sur)
52 | close(res)
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/man/tls_config.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tls.R
3 | \name{tls_config}
4 | \alias{tls_config}
5 | \title{Create TLS Configuration}
6 | \usage{
7 | tls_config(client = NULL, server = NULL, pass = NULL, auth = is.null(server))
8 | }
9 | \arguments{
10 | \item{client}{\strong{either} the character path to a file containing X.509
11 | certificate(s) in PEM format, comprising the certificate authority
12 | certificate chain (and revocation list if present), used to validate
13 | certificates presented by peers,\cr
14 | \strong{or} a length 2 character vector comprising [i] the certificate
15 | authority certificate chain and [ii] the certificate revocation list, or
16 | empty string \code{""} if not applicable.}
17 |
18 | \item{server}{\strong{either} the character path to a file containing the
19 | PEM-encoded TLS certificate and associated private key (may contain
20 | additional certificates leading to a validation chain, with the leaf
21 | certificate first),\cr
22 | \strong{or} a length 2 character vector comprising [i] the TLS certificate
23 | (optionally certificate chain) and [ii] the associated private key.}
24 |
25 | \item{pass}{(optional) required only if the secret key supplied to \code{server}
26 | is encrypted with a password. For security, consider providing through a
27 | function that returns this value, rather than directly.}
28 |
29 | \item{auth}{logical value whether to require authentication - by default TRUE
30 | for client and FALSE for server configurations. If TRUE, the session is
31 | only allowed to proceed if the peer has presented a certificate and it has
32 | been validated. If FALSE, authentication is optional, whereby a certificate
33 | is validated if presented by the peer, but the session allowed to proceed
34 | otherwise. If neither \code{client} nor \code{server} are supplied, then no
35 | authentication is performed and this argument has no effect.}
36 | }
37 | \value{
38 | A 'tlsConfig' object.
39 | }
40 | \description{
41 | Create a TLS configuration object to be used for secure connections. Specify
42 | \code{client} to create a client configuration or \code{server} to create a server
43 | configuration.
44 | }
45 | \details{
46 | Specify one of \code{client} or \code{server} only, or neither (in which case an empty
47 | client configuration is created), as a configuration can only be of one type.
48 |
49 | For creating client configurations for public internet usage, root CA
50 | ceritficates may usually be found at \file{/etc/ssl/certs/ca-certificates.crt}
51 | on Linux systems. Otherwise, root CA certificates in PEM format are available
52 | at the Common CA Database site run by Mozilla:
53 | \url{https://www.ccadb.org/resources} (select the Server Authentication
54 | SSL/TLS certificates text file).
55 | \emph{This link is not endorsed; use at your own risk.}
56 | }
57 | \examples{
58 | tls <- tls_config()
59 | tls
60 | ncurl("https://postman-echo.com/get", timeout = 1000L, tls = tls)
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/man/transports.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/docs.R
3 | \name{transports}
4 | \alias{transports}
5 | \title{Transports (Documentation)}
6 | \description{
7 | Transports supported by \pkg{nanonext}.
8 |
9 | For an authoritative guide please refer to the online documentation for the
10 | NNG library at \url{https://nng.nanomsg.org/man/}.
11 | }
12 | \section{Inproc}{
13 |
14 |
15 | The inproc transport provides communication support between sockets within
16 | the same process. This may be used as an alternative to slower transports
17 | when data must be moved within the same process. This transport tries hard to
18 | avoid copying data, and thus is very light-weight.
19 |
20 | \strong{[URI, inproc://]} This transport uses URIs using the scheme inproc://,
21 | followed by an arbitrary string of text, terminated by a NUL byte.
22 | inproc://nanonext is a valid example URL.
23 |
24 | \itemize{
25 | \item Multiple URIs can be used within the same application, and they will
26 | not interfere with one another.
27 |
28 | \item Two applications may also use the same URI without interfering with
29 | each other, and they will be unable to communicate with each other using
30 | that URI.
31 | }
32 | }
33 |
34 | \section{IPC}{
35 |
36 |
37 | The IPC transport provides communication support between sockets within
38 | different processes on the same host. For POSIX platforms, this is
39 | implemented using UNIX domain sockets. For Windows, this is implemented using
40 | Windows Named Pipes. Other platforms may have different implementation
41 | strategies.
42 |
43 | \emph{Traditional Names}
44 |
45 | \strong{[URI, ipc://]} This transport uses URIs using the scheme ipc://,
46 | followed by a path name in the file system where the socket or named pipe
47 | should be created.
48 |
49 | \itemize{
50 | \item On POSIX platforms, the path is taken literally, and is relative to
51 | the current directory, unless it begins with /, in which case it is
52 | relative to the root directory. For example, ipc://nanonext refers to the
53 | name nanonext in the current directory, whereas ipc:///tmp/nanonext refers
54 | to nanonext located in /tmp.
55 | \item On Windows, all names are prefixed by \\.\ pipe\ and do not reside in
56 | the normal file system - the required prefix is added automatically by NNG,
57 | so a URL of the form ipc://nanonext is fine.
58 | }
59 |
60 | \emph{UNIX Aliases}
61 |
62 | \strong{[URI, unix://]} The unix:// scheme is an alias for ipc:// and can be
63 | used inter-changeably, but only on POSIX systems. The purpose of this scheme
64 | is to support a future transport making use of AF_UNIX on Windows systems, at
65 | which time it will be necessary to discriminate between the Named Pipes and
66 | the AF_UNIX based transports.
67 |
68 | \emph{Abstract Names}
69 |
70 | \strong{[URI, abstract://]} On Linux, this transport also can support abstract
71 | sockets. Abstract sockets use a URI-encoded name after the scheme, which
72 | allows arbitrary values to be conveyed in the path, including embedded NUL
73 | bytes. abstract://nanonext is a valid example URL.
74 |
75 | \itemize{
76 | \item Abstract sockets do not have any representation in the file system,
77 | and are automatically freed by the system when no longer in use. Abstract
78 | sockets ignore socket permissions, but it is still possible to determine
79 | the credentials of the peer.
80 | }
81 | }
82 |
83 | \section{TCP/IP}{
84 |
85 |
86 | The TCP transport provides communication support between sockets across a
87 | TCP/IP network. Both IPv4 and IPv6 are supported when supported by the
88 | underlying platform.
89 |
90 | \strong{[URI, tcp://]} This transport uses URIs using the scheme tcp://,
91 | followed by an IP address or hostname, followed by a colon and finally a TCP
92 | port number. For example, to contact port 80 on the localhost either of the
93 | following URIs could be used: tcp://127.0.0.1:80 or tcp://localhost:80.
94 |
95 | \itemize{
96 | \item A URI may be restricted to IPv6 using the scheme tcp6://, and may be
97 | restricted to IPv4 using the scheme tcp4://
98 |
99 | \item Note: Specifying tcp6:// may not prevent IPv4 hosts from being used
100 | with IPv4-in-IPv6 addresses, particularly when using a wildcard hostname
101 | with listeners. The details of this varies across operating systems.
102 |
103 | \item Note: both tcp6:// and tcp4:// are specific to NNG, and might not be
104 | understood by other implementations.
105 |
106 | \item It is recommended to use either numeric IP addresses, or names that
107 | are specific to either IPv4 or IPv6 to prevent confusion and surprises.
108 |
109 | \item When specifying IPv6 addresses, the address must be enclosed in
110 | square brackets ([]) to avoid confusion with the final colon separating
111 | the port. For example, the same port 80 on the IPv6 loopback address (::1)
112 | would be specified as tcp://[::1]:80.
113 |
114 | \item The special value of 0 (INADDR_ANY) can be used for a listener to
115 | indicate that it should listen on all interfaces on the host. A shorthand
116 | for this form is to either omit the address, or specify the asterisk (\emph{)
117 | character. For example, the following three URIs are all equivalent, and
118 | could be used to listen to port 9999 on the host: (1) tcp://0.0.0.0:9999
119 | (2) tcp://}:9999 (3) tcp://:9999
120 | }
121 | }
122 |
123 | \section{TLS}{
124 |
125 |
126 | The TLS transport provides communication support between peers across a
127 | TCP/IP network using TLS v1.2 on top of TCP. Both IPv4 and IPv6 are supported
128 | when supported by the underlying platform.
129 |
130 | \strong{[URI, tls+tcp://]} This transport uses URIs using the scheme tls+tcp://,
131 | followed by an IP address or hostname, followed by a colon and finally a TCP
132 | port number. For example, to contact port 4433 on the localhost either of the
133 | following URIs could be used: tls+tcp://127.0.0.1:4433 or
134 | tls+tcp://localhost:4433.
135 | \itemize{
136 | \item A URI may be restricted to IPv6 using the scheme tls+tcp6://, or IPv4
137 | using the scheme tls+tcp4://.
138 | }
139 | }
140 |
141 | \section{WebSocket}{
142 |
143 |
144 | The ws and wss transport provides communication support between peers across
145 | a TCP/IP network using WebSockets. Both IPv4 and IPv6 are supported when
146 | supported by the underlying platform.
147 |
148 | \strong{[URI, ws://]} This transport uses URIs using the scheme ws://, followed
149 | by an IP address or hostname, optionally followed by a colon and a TCP port
150 | number, optionally followed by a path. (If no port number is specified then
151 | port 80 is assumed. If no path is specified then a path of / is assumed.) For
152 | example, the URI ws://localhost/app/pubsub would use port 80 on localhost,
153 | with the path /app/pubsub.
154 |
155 | \strong{[URI, wss://]} Secure WebSockets use the scheme wss://, and the default
156 | TCP port number of 443. Otherwise the format is the same as for regular
157 | WebSockets.
158 |
159 | \itemize{
160 | \item A URI may be restricted to IPv6 using the scheme ws6:// or wss6://,
161 | or IPv4 using the scheme ws4:// or wss4://.
162 |
163 | \item When specifying IPv6 addresses, the address must be enclosed in
164 | square brackets ([]) to avoid confusion with the final colon separating
165 | the port. For example, the same path and port on the IPv6 loopback address
166 | (::1) would be specified as ws://[::1]/app/pubsub.
167 |
168 | \item Note: The value specified as the host, if any, will also be used in
169 | the Host: HTTP header during HTTP negotiation.
170 |
171 | \item To listen to all ports on the system, the host name may be elided
172 | from the URL on the listener. This will wind up listening to all interfaces
173 | on the system, with possible caveats for IPv4 and IPv6 depending on what
174 | the underlying system supports. (On most modern systems it will map to the
175 | special IPv6 address ::, and both IPv4 and IPv6 connections will be
176 | permitted, with IPv4 addresses mapped to IPv6 addresses.)
177 |
178 | \item This transport makes use of shared HTTP server instances, permitting
179 | multiple sockets or listeners to be configured with the same hostname and
180 | port. When creating a new listener, it is registered with an existing HTTP
181 | server instance if one can be found. Note that the matching algorithm is
182 | somewhat simple, using only a string based hostname or IP address and port
183 | to match. Therefore it is recommended to use only IP addresses or the empty
184 | string as the hostname in listener URLs.
185 |
186 | \item All sharing of server instances is only typically possible within the
187 | same process.
188 |
189 | \item The server may also be used by other things (for example to serve
190 | static content), in the same process.
191 | }
192 | }
193 |
194 |
--------------------------------------------------------------------------------
/man/unresolved.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/aio.R
3 | \name{unresolved}
4 | \alias{unresolved}
5 | \title{Query if an Aio is Unresolved}
6 | \usage{
7 | unresolved(x)
8 | }
9 | \arguments{
10 | \item{x}{an Aio or list of Aios (objects of class 'sendAio', 'recvAio' or
11 | 'ncurlAio'), or Aio value stored at \verb{$result} or \verb{$data} etc.}
12 | }
13 | \value{
14 | Logical \code{TRUE} if \code{x} is an unresolved Aio or Aio value or the list
15 | of Aios contains at least one unresolved Aio, or \code{FALSE} otherwise.
16 | }
17 | \description{
18 | Query whether an Aio, Aio value or list of Aios remains unresolved. Unlike
19 | \code{\link[=call_aio]{call_aio()}}, this function does not wait for completion.
20 | }
21 | \details{
22 | Suitable for use in control flow statements such as \code{while} or \code{if}.
23 |
24 | Note: querying resolution may cause a previously unresolved Aio to resolve.
25 | }
26 | \examples{
27 | s1 <- socket("pair", listen = "inproc://nanonext")
28 | aio <- send_aio(s1, "test", timeout = 100)
29 |
30 | while (unresolved(aio)) {
31 | # do stuff before checking resolution again
32 | cat("unresolved\n")
33 | msleep(20)
34 | }
35 |
36 | unresolved(aio)
37 |
38 | close(s1)
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/man/write_cert.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tls.R
3 | \name{write_cert}
4 | \alias{write_cert}
5 | \title{Generate Self-Signed Certificate and Key}
6 | \usage{
7 | write_cert(cn = "127.0.0.1", valid = "20301231235959")
8 | }
9 | \arguments{
10 | \item{cn}{[default '127.0.0.1'] character issuer common name (CN) for the
11 | certificate. This can be either a hostname or an IP address, but must match
12 | the actual server URL as client authentication will depend on it.}
13 |
14 | \item{valid}{[default '20301231235959'] character 'not after' date-time in
15 | 'yyyymmddhhmmss' format. The certificate is not valid after this time.}
16 | }
17 | \value{
18 | A list of length 2, comprising \verb{$server} and \verb{$client}. These may be
19 | passed directly to the relevant argument of \code{\link[=tls_config]{tls_config()}}.
20 | }
21 | \description{
22 | Generate self-signed x509 certificate and 4096 bit RSA private/public key
23 | pair for use with authenticated, encrypted TLS communications.
24 | }
25 | \details{
26 | Note that it can take a second or two for the key and certificate to be
27 | generated.
28 | }
29 | \examples{
30 | \dontshow{if (interactive()) withAutoprint(\{ # examplesIf}
31 | cert <- write_cert(cn = "127.0.0.1")
32 | ser <- tls_config(server = cert$server)
33 | cli <- tls_config(client = cert$client)
34 |
35 | s <- socket(listen = "tls+tcp://127.0.0.1:5555", tls = ser)
36 | s1 <- socket(dial = "tls+tcp://127.0.0.1:5555", tls = cli)
37 |
38 | # secure TLS connection established
39 |
40 | close(s1)
41 | close(s)
42 |
43 | cert
44 | \dontshow{\}) # examplesIf}
45 | }
46 |
--------------------------------------------------------------------------------
/man/write_stdout.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{write_stdout}
4 | \alias{write_stdout}
5 | \title{Write to Stdout}
6 | \usage{
7 | write_stdout(x)
8 | }
9 | \arguments{
10 | \item{x}{character string.}
11 | }
12 | \value{
13 | Invisible NULL. As a side effect, \code{x} is output to \code{stdout}.
14 | }
15 | \description{
16 | Performs a non-buffered write to \code{stdout} using the C function \code{writev()} or
17 | equivalent. Avoids interleaved output when writing concurrently from multiple
18 | processes.
19 | }
20 | \details{
21 | This function writes to the C-level \code{stdout} of the process and hence cannot
22 | be re-directed by \code{\link[=sink]{sink()}}.
23 |
24 | A newline character is automatically appended to \code{x}, hence there is no need
25 | to include this within the input string.
26 | }
27 | \examples{
28 | write_stdout("")
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/man/zzz.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{zzz}
4 | \alias{zzz}
5 | \title{Internal Package Function}
6 | \usage{
7 | zzz()
8 | }
9 | \description{
10 | Only present for cleaning up after running examples and tests. Do not attempt
11 | to run the examples.
12 | }
13 | \examples{
14 | if (Sys.info()[["sysname"]] == "Linux") {
15 | rm(list = ls())
16 | invisible(gc())
17 | .Call(nanonext:::rnng_fini_priors)
18 | Sys.sleep(1L)
19 | .Call(nanonext:::rnng_fini)
20 | }
21 |
22 | }
23 | \keyword{internal}
24 |
--------------------------------------------------------------------------------
/nanonext.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 | ProjectId: 6e5884e8-3d22-48de-a8f2-62c1a7a01346
3 |
4 | RestoreWorkspace: Default
5 | SaveWorkspace: Default
6 | AlwaysSaveHistory: Default
7 |
8 | EnableCodeIndexing: Yes
9 | UseSpacesForTab: Yes
10 | NumSpacesForTab: 2
11 | Encoding: UTF-8
12 |
13 | RnwWeave: Sweave
14 | LaTeX: pdfLaTeX
15 |
16 | AutoAppendNewline: Yes
17 | StripTrailingWhitespace: Yes
18 |
19 | BuildType: Package
20 | PackageUseDevtools: Yes
21 | PackageInstallArgs: --no-multiarch --with-keep.source
22 |
--------------------------------------------------------------------------------
/pkgdown/_pkgdown.yml:
--------------------------------------------------------------------------------
1 | url: https://nanonext.r-lib.org
2 | template:
3 | package: tidytemplate
4 | bootstrap: 5
5 |
6 | includes:
7 | in_header: |
8 |
9 |
10 | reference:
11 | - contents:
12 | - nanonext-package
13 | - matches("^[a-zA-Z]*")
14 | authors:
15 | R Consortium:
16 | html: "
"
17 | development:
18 | mode: auto
19 |
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/favicon-48x48.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/favicon.ico
--------------------------------------------------------------------------------
/pkgdown/favicon/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/web-app-manifest-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png",
9 | "purpose": "maskable"
10 | },
11 | {
12 | "src": "/web-app-manifest-512x512.png",
13 | "sizes": "512x512",
14 | "type": "image/png",
15 | "purpose": "maskable"
16 | }
17 | ],
18 | "theme_color": "#ffffff",
19 | "background_color": "#ffffff",
20 | "display": "standalone"
21 | }
--------------------------------------------------------------------------------
/pkgdown/favicon/web-app-manifest-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/web-app-manifest-192x192.png
--------------------------------------------------------------------------------
/pkgdown/favicon/web-app-manifest-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/pkgdown/favicon/web-app-manifest-512x512.png
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.so
3 | *.dll
4 |
--------------------------------------------------------------------------------
/src/Makevars.in:
--------------------------------------------------------------------------------
1 | PKG_CFLAGS=@cflags@ $(C_VISIBILITY)
2 | PKG_LIBS=@libs@
3 |
--------------------------------------------------------------------------------
/src/Makevars.ucrt:
--------------------------------------------------------------------------------
1 | PKG_CFLAGS=-I../install/include -DNNG_STATIC_LIB $(C_VISIBILITY)
2 | PKG_LIBS=../install/lib/libnng.b ../install/lib/libmbedtls.b ../install/lib/libmbedx509.b ../install/lib/libmbedcrypto.b -lbcrypt -liphlpapi -lws2_32
3 |
--------------------------------------------------------------------------------
/src/Makevars.win:
--------------------------------------------------------------------------------
1 | PKG_CFLAGS=-I../install${R_ARCH}/include -DNNG_STATIC_LIB $(C_VISIBILITY)
2 | PKG_LIBS=../install${R_ARCH}/lib/libnng.b ../install${R_ARCH}/lib/libmbedtls.b ../install${R_ARCH}/lib/libmbedx509.b ../install${R_ARCH}/lib/libmbedcrypto.b -lbcrypt -liphlpapi -lws2_32
3 |
--------------------------------------------------------------------------------
/src/mbedtls-362.tar.xz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/src/mbedtls-362.tar.xz
--------------------------------------------------------------------------------
/src/net.c:
--------------------------------------------------------------------------------
1 | // nanonext - C level - Net Utils ----------------------------------------------
2 |
3 | #define NANONEXT_NET
4 | #include "nanonext.h"
5 |
6 | // IP Addresses ----------------------------------------------------------------
7 |
8 | SEXP rnng_ip_addr(void) {
9 |
10 | char buf[INET_ADDRSTRLEN];
11 | int i = 0;
12 | SEXP out, names;
13 | PROTECT_INDEX pxi, pxn;
14 | PROTECT_WITH_INDEX(out = Rf_allocVector(STRSXP, 1), &pxi);
15 | PROTECT_WITH_INDEX(names = Rf_allocVector(STRSXP, 1), &pxn);
16 |
17 | #ifdef _WIN32
18 |
19 | DWORD ret;
20 | ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
21 | ULONG bufsize = 15000;
22 | IP_ADAPTER_ADDRESSES *adapter, *addrs;
23 | IP_ADAPTER_UNICAST_ADDRESS *addr;
24 |
25 | int j = 0;
26 | do {
27 | addrs = malloc(bufsize);
28 | if (addrs == NULL)
29 | goto cleanup;
30 |
31 | ret = GetAdaptersAddresses(AF_INET, flags, NULL, addrs, &bufsize);
32 | if (ret == ERROR_BUFFER_OVERFLOW)
33 | free(addrs);
34 | } while ((ret == ERROR_BUFFER_OVERFLOW) && (++j == 1));
35 |
36 | if (ret != NO_ERROR) {
37 | free(addrs);
38 | goto cleanup;
39 | }
40 |
41 | for (adapter = addrs; adapter != NULL; adapter = adapter->Next) {
42 | if (adapter->OperStatus == IfOperStatusUp) {
43 | for (addr = adapter->FirstUnicastAddress; addr != NULL; addr = addr->Next) {
44 | if (addr->Address.lpSockaddr->sa_family == AF_INET) {
45 |
46 | struct sockaddr_in *sa_in = (struct sockaddr_in *) addr->Address.lpSockaddr;
47 | inet_ntop(AF_INET, &sa_in->sin_addr, buf, sizeof(buf));
48 | if (i) {
49 | REPROTECT(out = Rf_xlengthgets(out, i + 1), pxi);
50 | REPROTECT(names = Rf_xlengthgets(names, i + 1), pxn);
51 | }
52 | SET_STRING_ELT(out, i, Rf_mkChar(buf));
53 | int sz = WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, NULL, 0, NULL, NULL);
54 | char nbuf[sz];
55 | if (WideCharToMultiByte(CP_UTF8, 0, adapter->FriendlyName, -1, nbuf, sz, NULL, NULL)) {}
56 | SET_STRING_ELT(names, i++, Rf_mkChar(nbuf));
57 |
58 | }
59 | }
60 | }
61 | }
62 | free(addrs);
63 |
64 | #else
65 |
66 | struct ifaddrs *ifaddr, *ifa;
67 | if (getifaddrs(&ifaddr))
68 | goto cleanup;
69 |
70 |
71 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
72 | if ((ifa->ifa_addr != NULL) &&
73 | (ifa->ifa_addr->sa_family == AF_INET) &&
74 | !(ifa->ifa_flags & IFF_LOOPBACK)) {
75 |
76 | struct sockaddr_in *sa_in = (struct sockaddr_in *) ifa->ifa_addr;
77 | inet_ntop(AF_INET, &(sa_in->sin_addr), buf, sizeof(buf));
78 | if (i) {
79 | REPROTECT(out = Rf_xlengthgets(out, i + 1), pxi);
80 | REPROTECT(names = Rf_xlengthgets(names, i + 1), pxn);
81 | }
82 | SET_STRING_ELT(out, i, Rf_mkChar(buf));
83 | SET_STRING_ELT(names, i++, Rf_mkChar(ifa->ifa_name));
84 |
85 | }
86 | }
87 | freeifaddrs(ifaddr);
88 |
89 | #endif
90 |
91 | Rf_namesgets(out, names);
92 |
93 | cleanup:
94 | UNPROTECT(2);
95 | return out;
96 |
97 | }
98 |
99 | // misc utils ------------------------------------------------------------------
100 |
101 | SEXP rnng_write_stdout(SEXP x) {
102 |
103 | const char *buf = CHAR(STRING_ELT(x, 0));
104 | #ifdef _WIN32
105 | char nbuf[strlen(buf) + 2];
106 | snprintf(nbuf, sizeof(nbuf), "%s\n", buf);
107 | DWORD bytes;
108 | if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), nbuf, (DWORD) strlen(nbuf), &bytes, NULL)) {}
109 | #else
110 | struct iovec iov[2] = {
111 | {.iov_base = (void *) buf, .iov_len = strlen(buf)},
112 | {.iov_base = "\n", .iov_len = 1}
113 | };
114 | if (writev(STDOUT_FILENO, iov, 2)) {}
115 | #endif
116 | return R_NilValue;
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/src/nng-111.tar.xz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-lib/nanonext/0a749f86ff8c41dd4c8403cc37c34ca1beb6b4af/src/nng-111.tar.xz
--------------------------------------------------------------------------------
/vignettes-src/precompile.R:
--------------------------------------------------------------------------------
1 | # Vignettes precompiled as require setup of communications between separate processes, python etc.
2 | knitr::knit("vignettes-src/_nanonext.Rmd", "vignettes/nanonext.Rmd")
3 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------