├── .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: "R Consortium" 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 | --------------------------------------------------------------------------------