├── .github
└── workflows
│ ├── build.yml
│ ├── codeql-analysis.yml
│ └── mattermost-ziti-webhook.yml
├── .gitignore
├── .gitmodules
├── .npmignore
├── API_REFERENCE.hbs
├── API_REFERENCE.md
├── CMakeLists.txt
├── CMakePresets.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.hbs
├── README.md
├── SECURITY.md
├── binding.gyp
├── cmake
└── variables.cmake
├── configure
├── configure.cmd
├── deps
├── CMakeLists.txt
├── common-ziti.gypi
└── tlsuv-libuv.patch
├── jsdoc.json
├── lib
├── close.js
├── dial.js
├── enroll.js
├── express-listener.js
├── express.js
├── httpRequest.js
├── httpRequestData.js
├── httpRequestEnd.js
├── index.js
├── init.js
├── listen.js
├── serviceAvailable.js
├── servicesRefresh.js
├── setLogLevel.js
├── write.js
├── ziti-socket.js
└── ziti.js
├── package-lock.json
├── package.json
├── scripts
├── build-appveyor.bat
├── install_node.sh
└── validate_tag.sh
├── src
├── Ziti_https_request.c
├── Ziti_https_request_data.c
├── Ziti_https_request_end.c
├── build_config.h.in
├── stack_traces.c
├── utils.c
├── utils.h
├── ziti-add-on.c
├── ziti-nodejs.h
├── ziti_close.c
├── ziti_dial.c
├── ziti_enroll.c
├── ziti_init.c
├── ziti_listen.c
├── ziti_sdk_version.c
├── ziti_service_available.c
├── ziti_services_refresh.c
├── ziti_set_log_level.c
├── ziti_shutdown.c
├── ziti_websocket_connect.c
├── ziti_websocket_write.c
└── ziti_write.c
├── tests
├── enroll-test.js
├── hello.js
├── https-test.js
├── mattermost-test.js
└── websocket-test.js
├── toolchains
├── Linux-arm.cmake
├── Linux-arm64.cmake
├── Windows-arm64-msvc.cmake
├── Windows-x86.cmake
├── Windows-x86_64.cmake
├── linux-embedded.cmake
├── macOS-arm64.cmake
└── macOS-x86_64.cmake
├── vcpkg.json
├── ziti.js
└── ziti.png
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 |
2 | name: Build
3 |
4 | on:
5 | release:
6 | types: [ published ]
7 |
8 | push:
9 | branches: [ main ]
10 | paths-ignore:
11 | - 'package.json'
12 | - 'CHANGELOG.md'
13 | pull_request:
14 | branches: [ main ]
15 | workflow_dispatch:
16 | inputs:
17 | tags:
18 | required: false
19 | description: 'Misc tags'
20 |
21 | # cancel older, redundant runs of same workflow on same branch
22 | concurrency:
23 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
24 | cancel-in-progress: true
25 |
26 | jobs:
27 |
28 | # -------------------------------------------------------------------------------
29 | # Do a clean build, test, and publish
30 | # -------------------------------------------------------------------------------
31 | build:
32 | name: Build for Node-${{ matrix.node_ver }} ${{ matrix.config.target }}/${{ matrix.config.arch }}
33 | runs-on: ${{ matrix.config.os }}
34 | # container: ${{ matrix.config.container }}
35 |
36 | env:
37 | BUILD_NUMBER: ${{ github.run_number }}
38 | AWS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
39 |
40 | strategy:
41 | matrix:
42 | config:
43 | - { os: windows-latest, target: "windows", arch: "x64" }
44 | - { os: ubuntu-20.04, target: "linux", arch: "x64" }
45 | - { os: ubuntu-20.04, target: "linux", arch: "arm64" }
46 | - { os: macos-13, target: "macos", arch: "x64" }
47 | - { os: macos-14, target: "macos", arch: "arm64" }
48 | node_ver: [ 18, 20, 21, 22, 23 ]
49 | fail-fast: false
50 |
51 | steps:
52 |
53 | - name: Checkout
54 | uses: actions/checkout@v4
55 | with:
56 | fetch-depth: 0
57 | submodules: 'recursive'
58 | # token: ${{ secrets.ZITI_CI_GH_TOKEN }}
59 |
60 | - name: macOS tools
61 | if: runner.os == 'macOS'
62 | shell: bash
63 | run: brew install autoconf autoconf-archive automake pkg-config libtool
64 |
65 | - name: Setup PkgConfig (Windows)
66 | if: matrix.config.target == 'windows'
67 | run: |
68 | choco install pkgconfiglite
69 |
70 | - name: Get crossbuild tools
71 | if: matrix.config.target == 'linux' && matrix.config.arch != 'x64'
72 | run: |
73 | sudo apt update -y
74 | sudo apt install -y crossbuild-essential-${{ matrix.config.arch }}
75 |
76 | - name: Node Version
77 | uses: actions/setup-node@v3
78 | with:
79 | node-version: ${{ matrix.node_ver }}
80 |
81 | - name: Extract branch name
82 | shell: bash
83 | run: echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
84 | id: extract_branch
85 |
86 | - name: Print branch name
87 | shell: bash
88 | run: |
89 | echo "## branch name is: ${{ steps.extract_branch.outputs.branch }}"
90 |
91 | - name: Get current date
92 | id: date
93 | run: echo "date=$(date)" >> $GITHUB_OUTPUT
94 |
95 | - name: Install CMake/Ninja
96 | uses: lukka/get-cmake@v3.30.1
97 |
98 | - name: Run VCPKG
99 | uses: lukka/run-vcpkg@v11
100 | # will use baseline from vcpkg.json
101 | with:
102 | # get baseline from vcpkg
103 | vcpkgJsonGlob: './vcpkg.json'
104 |
105 | - name: show versions
106 | run: |
107 | echo ===== gcc =====
108 | gcc --version
109 | echo ===== cmake =====
110 | cmake --version
111 | echo "ninja: $(ninja --version)"
112 | echo "node: $(node --version)"
113 | echo "npm: $(npm --version)"
114 |
115 | - name: restore dependencies cache
116 | uses: actions/cache/restore@v4
117 | id: cache-restore
118 | with:
119 | key: deps-${{ matrix.config.target }}-${{ matrix.config.arch }}-${{ hashFiles('./vcpkg.json') }}
120 | path: './vcpkg/packages'
121 |
122 | - name: Build NodeJS-SDK
123 | id: buildSDK
124 | run: |
125 | cd ${{ runner.workspace }}/${{ github.event.repository.name }}
126 | npm install
127 | npm run build:package -- --target_arch=${{ matrix.config.arch }}
128 | env:
129 | PRESET: ci-${{ matrix.config.target }}-${{ matrix.config.arch }}
130 | TARGET_ARCH: ${{ matrix.config.arch }}
131 | BUILD_DATE: ${{ steps.date.outputs.date }}
132 |
133 | - name: show build result
134 | if: always()
135 | run: echo build result ${{ steps.buildSDK.outcome }}
136 |
137 | - name: debug build failure
138 | if: always() && steps.buildSDK.outcome == 'failure'
139 | uses: actions/upload-artifact@v4
140 | with:
141 | name: build-logs-${{ matrix.config.target }}-${{ matrix.config.arch }}
142 | path: |
143 | ./vcpkg/buildtrees/**/*.log
144 | ./build/**/*log
145 |
146 | - name: Hello test
147 | if: matrix.config.arch == 'x64'
148 | run: |
149 | node tests/hello.js
150 |
151 | - name: save dependencies cache
152 | uses: actions/cache/save@v4
153 | id: cache-save
154 | # save deps even build has failed
155 | if: always()
156 | with:
157 | key: ${{ steps.cache-restore.outputs.cache-primary-key }}
158 | path: './vcpkg/packages'
159 |
160 | - name: upload artifacts
161 | uses: actions/upload-artifact@v4
162 | with:
163 | name: ziti_nodejs_${{ matrix.config.target }}_${{ matrix.config.arch }}_nodev${{ matrix.node_ver }}
164 | path: |
165 | ./build/Release/ziti_sdk_nodejs.node
166 | if-no-files-found: error
167 |
168 | - name: upload release bundle
169 | uses: softprops/action-gh-release@v0.1.13
170 | if: startsWith(github.ref, 'refs/tags/')
171 | with:
172 | files: |
173 | ./build/stage/**/ziti_sdk_nodejs*.tar.gz
174 |
175 | - name: Configure AWS Credentials
176 | uses: aws-actions/configure-aws-credentials@v4
177 | if: env.AWS_KEY_ID != '' && startsWith(github.ref, 'refs/tags/')
178 | with:
179 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
180 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
181 | aws-region: us-east-1
182 |
183 | - name: Publish Binary to S3 (for all OS's, Node versions, and architectures)
184 | run: |
185 | ./node_modules/.bin/node-pre-gyp --target_arch=${{ matrix.config.arch }} unpublish publish
186 | sleep 5
187 | if: startsWith(github.ref, 'refs/tags/')
188 |
189 | - name: Install Binary
190 | run: |
191 | npm install --fallback-to-build=false
192 | sleep 5
193 | if: startsWith(github.ref, 'refs/tags/')
194 |
195 | - name: Fetch Binary info
196 | if: env.AWS_KEY_ID != '' && startsWith(github.ref, 'refs/tags/')
197 | run: |
198 | ./node_modules/.bin/node-pre-gyp info
199 |
200 | - name: NPM Publish
201 | uses: JS-DevTools/npm-publish@v1
202 | with:
203 | token: ${{ secrets.NPM_TOKEN }}
204 | access: public
205 | if: |
206 | matrix.config.os == 'ubuntu-20.04' && matrix.node_ver == '20' && matrix.config.arch == 'x64' && startsWith(github.ref, 'refs/tags/')
207 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | name: "CodeQL"
7 |
8 | on:
9 | push:
10 | branches: [master]
11 | pull_request:
12 | # The branches below must be a subset of the branches above
13 | branches: [master]
14 | schedule:
15 | - cron: '0 12 * * 5'
16 |
17 | jobs:
18 | analyze:
19 | name: Analyze
20 | runs-on: ubuntu-latest
21 |
22 | strategy:
23 | fail-fast: false
24 | matrix:
25 | # Override automatic language detection by changing the below list
26 | # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
27 | language: ['cpp', 'javascript', 'python']
28 | # Learn more...
29 | # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
30 |
31 | steps:
32 | - name: Checkout repository
33 | uses: actions/checkout@v4
34 | with:
35 | # We must fetch at least the immediate parents so that if this is
36 | # a pull request then we can checkout the head.
37 | fetch-depth: 2
38 |
39 | # If this run was triggered by a pull request event, then checkout
40 | # the head of the pull request instead of the merge commit.
41 | - run: git checkout HEAD^2
42 | if: ${{ github.event_name == 'pull_request' }}
43 |
44 | # Initializes the CodeQL tools for scanning.
45 | - name: Initialize CodeQL
46 | uses: github/codeql-action/init@v2
47 | with:
48 | languages: ${{ matrix.language }}
49 | # If you wish to specify custom queries, you can do so here or in a config file.
50 | # By default, queries listed here will override any specified in a config file.
51 | # Prefix the list here with "+" to use these queries and those in the config file.
52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
53 |
54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55 | # If this step fails, then you should remove it and run the build manually (see below)
56 | - name: Autobuild
57 | uses: github/codeql-action/autobuild@v2
58 |
59 | # ℹ️ Command-line programs to run using the OS shell.
60 | # 📚 https://git.io/JvXDl
61 |
62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63 | # and modify them (or add more) to build your code if your project
64 | # uses a compiled language
65 |
66 | #- run: |
67 | # make bootstrap
68 | # make release
69 |
70 | - name: Perform CodeQL Analysis
71 | uses: github/codeql-action/analyze@v2
72 |
--------------------------------------------------------------------------------
/.github/workflows/mattermost-ziti-webhook.yml:
--------------------------------------------------------------------------------
1 | name: mattermost-ziti-webhook
2 | on:
3 | create:
4 | delete:
5 | issues:
6 | issue_comment:
7 | pull_request_review:
8 | pull_request_review_comment:
9 | pull_request:
10 | push:
11 | fork:
12 | release:
13 |
14 | jobs:
15 | mattermost-ziti-webhook:
16 | runs-on: ubuntu-latest
17 | name: POST Webhook
18 | env:
19 | ZITI_LOG: 99
20 | ZITI_NODEJS_LOG: 99
21 | steps:
22 | - uses: openziti/ziti-webhook-action@main
23 | with:
24 | ziti-id: ${{ secrets.ZITI_MATTERMOST_IDENTITY }}
25 | webhook-url: ${{ secrets.ZITI_MATTERMOST_WEBHOOK_URL }}
26 | webhook-secret: ${{ secrets.ZITI_MATTERMOSTI_WEBHOOK_SECRET }}
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | .vscode/
107 | .DS_Store
108 | /CMakeUserPresets.json
109 |
110 | # Jetbrains tools
111 | .idea/
112 | cmake-build-*
113 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openziti/ziti-sdk-nodejs/53f2a339ffb16e8a11939618877e4590b982a8f7/.gitmodules
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/
39 | deps/
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # TypeScript v1 declaration files
46 | typings/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Microbundle cache
58 | .rpt2_cache/
59 | .rts2_cache_cjs/
60 | .rts2_cache_es/
61 | .rts2_cache_umd/
62 |
63 | # Optional REPL history
64 | .node_repl_history
65 |
66 | # Output of 'npm pack'
67 | *.tgz
68 |
69 | # Yarn Integrity file
70 | .yarn-integrity
71 |
72 | # dotenv environment variables file
73 | .env
74 | .env.test
75 |
76 | # parcel-bundler cache (https://parceljs.org/)
77 | .cache
78 |
79 | # Next.js build output
80 | .next
81 |
82 | # Nuxt.js build / generate output
83 | .nuxt
84 | dist
85 |
86 | # Gatsby files
87 | .cache/
88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
89 | # https://nextjs.org/blog/next-9-1#public-directory-support
90 | # public
91 |
92 | # vuepress build output
93 | .vuepress/dist
94 |
95 | # Serverless directories
96 | .serverless/
97 |
98 | # FuseBox cache
99 | .fusebox/
100 |
101 | # DynamoDB Local files
102 | .dynamodb/
103 |
104 | # TernJS port file
105 | .tern-port
106 |
107 | .vscode/
108 | .DS_Store
109 |
--------------------------------------------------------------------------------
/API_REFERENCE.hbs:
--------------------------------------------------------------------------------
1 |
2 | # API Reference
3 | {{#module name="@openziti/ziti-sdk-nodejs"}}
4 | {{>body~}}
5 | {{>member-index~}}
6 | {{>separator~}}
7 | {{>members~}}
8 | {{/module}}
9 |
10 | * * *
11 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.19)
2 | cmake_policy(SET CMP0091 NEW)
3 | cmake_policy(SET CMP0042 NEW)
4 |
5 | include(cmake/variables.cmake)
6 |
7 | message(NOTICE "branch: ${ZITI_BRANCH}/${ZITI_COMMIT}")
8 |
9 | project (ziti_sdk_nodejs)
10 |
11 | configure_file(
12 | ${CMAKE_CURRENT_SOURCE_DIR}/src/build_config.h.in
13 | ${CMAKE_CURRENT_BINARY_DIR}/include/build_config.h
14 | )
15 |
16 | # add_definitions(-DNAPI_VERSION=4)
17 |
18 | if (WIN32)
19 | # make sure TLSUV picks it up
20 | include_directories(${CMAKE_JS_INC})
21 | endif (WIN32)
22 |
23 | file(GLOB SOURCE_FILES ./src/*.c ./src/.cpp)
24 |
25 | add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
26 | set_target_properties(${PROJECT_NAME} PROPERTIES
27 | PREFIX ""
28 | SUFFIX ".node"
29 | C_STANDARD 11
30 | POSITION_INDEPENDENT_CODE ON
31 | )
32 |
33 | target_include_directories(${PROJECT_NAME}
34 | PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include
35 | PRIVATE ${CMAKE_JS_INC}
36 | )
37 |
38 | if (WIN32)
39 | target_compile_definitions(${PROJECT_NAME} PRIVATE WIN32_LEAN_AND_MEAN)
40 | endif (WIN32)
41 |
42 |
43 | if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)
44 | # Generate node.lib
45 | execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})
46 | endif()
47 |
48 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/deps)
49 |
50 | target_link_libraries(${PROJECT_NAME} PRIVATE ziti ${CMAKE_JS_LIB})
51 | if (WIN32)
52 | target_link_libraries(${PROJECT_NAME} PRIVATE dbghelp version ntdll)
53 | endif (WIN32)
--------------------------------------------------------------------------------
/CMakePresets.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 6,
3 | "cmakeMinimumRequired": {
4 | "major": 3,
5 | "minor": 23
6 | },
7 | "configurePresets": [
8 | {
9 | "name": "base-win64",
10 | "hidden": false,
11 | "inherits": [ "base" ],
12 | "condition": {
13 | "type": "equals",
14 | "lhs": "${hostSystemName}",
15 | "rhs": "Windows"
16 | },
17 | "cacheVariables": {
18 | "VCPKG_TARGET_TRIPLET": "x64-windows-static"
19 | }
20 | },
21 | {
22 | "name": "base",
23 | "hidden": false,
24 | "generator": "Ninja",
25 | "cacheVariables": {
26 | "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
27 | "CMAKE_C_EXTENSIONS": "ON",
28 | "CMAKE_C_STANDARD": "99",
29 | "CMAKE_C_STANDARD_REQUIRED": "ON",
30 | "CMAKE_CXX_EXTENSIONS": "OFF",
31 | "CMAKE_CXX_STANDARD": "11",
32 | "CMAKE_CXX_STANDARD_REQUIRED": "ON",
33 | "CMAKE_BUILD_TYPE": "Debug"
34 | }
35 | },
36 | {
37 | "name": "ci",
38 | "hidden": true,
39 | "binaryDir": "${sourceDir}/build",
40 | "inherits": [
41 | "base"
42 | ],
43 | "cacheVariables": {
44 | "CMAKE_BUILD_TYPE": "Release"
45 | }
46 | },
47 | {
48 | "name": "ci-macos-x64",
49 | "inherits": [ "ci" ]
50 | },
51 | {
52 | "name": "ci-macos-arm64",
53 | "inherits": [ "ci" ],
54 | "cacheVariables": {
55 | "VCPKG_TARGET_ARCHITECTURE": "arm64",
56 | "VCPKG_TARGET_TRIPLET": "arm64-osx",
57 | "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/macOS-arm64.cmake"
58 | }
59 | },
60 | {
61 | "name": "ci-linux-x64",
62 | "inherits": [ "ci" ]
63 | },
64 | {
65 | "name": "ci-linux-arm64",
66 | "inherits": "ci-linux-x64",
67 | "cacheVariables": {
68 | "VCPKG_TARGET_TRIPLET": "arm64-linux",
69 | "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/Linux-arm64.cmake"
70 | }
71 | },
72 | {
73 | "name": "ci-linux-arm",
74 | "inherits": "ci-linux-x64",
75 | "cacheVariables": {
76 | "VCPKG_TARGET_TRIPLET": "arm-linux",
77 | "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/Linux-arm.cmake"
78 | }
79 | },
80 | {
81 | "name": "ci-windows-x64",
82 | "inherits": [ "ci", "base-win64"]
83 | },
84 | {
85 | "name": "ci-windows-arm64",
86 | "inherits": [ "ci-windows-x64" ],
87 | "cacheVariables": {
88 | "VCPKG_TARGET_TRIPLET": "arm64-windows-static-md"
89 | }
90 | }
91 | ]
92 | }
93 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of Conduct
2 |
3 | All open source projects managed by OpenZiti share a common [code of conduct](https://docs.openziti.io/policies/CODE_OF_CONDUCT.html)
4 | which all contributors are expected to follow. Please be sure you read, understand and adhere to the guidelines expressed therein.
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | NetFoundry welcomes all and any contributions. All open source projects managed by NetFoundry share a common
4 | [guide for contributions](https://docs.openziti.io/policies/CONTRIBUTING.html).
5 |
6 | If you are eager to contribute to a NetFoundry-managed open source project please read and act accordingly.
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright NetFoundry Inc.
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.hbs:
--------------------------------------------------------------------------------
1 |
2 | OpenZiti is a free and open source project focused on bringing zero trust to any application.
3 |
4 | The project provides all the pieces required to implement or integrate zero trust into your solutions.
5 |
6 |
7 | Please star us.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | @openziti/ziti-sdk-nodejs
21 |
22 |
23 |
24 | This repo hosts the OpenZiti SDK for NodeJS, and is designed to help you deliver secure applications over a OpenZiti Network
25 |
26 |
27 | Part of the OpenZiti ecosystem
28 |
29 |
30 |
31 |
32 | Are you interested in knowing how to easily embed programmable, high performance, zero trust networking into your NodeJS app, on any internet connection, without VPNs?
33 |
34 | Learn more about our OpenZiti project.
35 |
36 |
37 |
38 | ---
39 | []()
40 | []()
41 | [](https://badge.fury.io/js/@openziti%2Fziti-sdk-nodejs.svg)
42 | [](https://opensource.org/licenses/Apache-2.0)
43 | []()
44 | [](CONTRIBUTING.md)
45 | [](CODE_OF_CONDUCT.md)
46 |
47 | ---
48 |
49 | # Associated Article(s)
50 | For more context on this SDK, you may be interested in this
51 | [article concerning how to secure NodeJS applications](https://openziti.io/securing-nodejs-applications)
52 |
53 |
54 |
55 | # Supported platforms
56 |
57 | The `@openziti/ziti-sdk-nodejs` module works with the following Node.js versions:
58 | - v12.x
59 | - v13.x
60 | - v14.x
61 | - v15.x
62 | - v16.x
63 | - v17.x
64 | - v18.x
65 |
66 | Binaries for most Node versions and platforms are provided by default via [@mapbox/node-pre-gyp](https://github.com/mapbox/node-pre-gyp).
67 |
68 | # Installing
69 |
70 | NPM
71 | ``` js
72 | npm i @openziti/ziti-sdk-nodejs
73 | ```
74 | or Yarn
75 | ``` js
76 | yarn add @openziti/ziti-sdk-nodejs
77 | ```
78 |
79 | Special note on previous package:
80 |
81 | On June 7, 2020 @openziti/ziti-sdk-nodejs@0.6.0 was released. Older, unscoped versions that are not part of the @openziti org are deprecated and only @openziti/ziti-sdk-nodejs will see updates going forward. To upgrade to the new package do:
82 |
83 | ``` js
84 | npm uninstall ziti-sdk-nodejs --save
85 | npm install @openziti/ziti-sdk-nodejs --save
86 | ```
87 |
88 | # Usage
89 |
90 | **Note:** the module must be [installed](#installing) before use.
91 |
92 | ESM example (client-side)
93 | ``` js
94 | import ziti from '@openziti/ziti-sdk-nodejs';
95 |
96 | // Somehow provide path to identity file, e.g. via env var
97 | const zitiIdentityFile = process.env.ZITI_IDENTITY_FILE;
98 | // Authenticate ourselves onto the Ziti network
99 | await ziti.init( zitiIdentityFile ).catch(( err ) => { /* probably exit */ });
100 |
101 | const on_resp_data = ( obj ) => {
102 | console.log(`response is: ${obj.body.toString('utf8')}`);
103 | };
104 |
105 | // Perform an HTTP GET request to a dark OpenZiti web service
106 | ziti.httpRequest(
107 | 'myDarkWebService', // OpenZiti Service name or HTTP origin part of the URL
108 | 'GET',
109 | '/', // path part of the URL including query params
110 | ['Accept: application/json' ], // headers
111 | undefined, // optional on_req cb
112 | undefined, // optional on_req_data cb
113 | on_resp_data // optional on_resp_data cb
114 | );
115 |
116 | ```
117 |
118 | ESM example (server-side ExpressJS)
119 | ``` js
120 | import ziti from '@openziti/ziti-sdk-nodejs';
121 | import express from 'express';
122 | let app = ziti.express( express, zitiServiceName );
123 | app.listen(ignored, function() { ... }
124 |
125 | /**
126 |
127 | That's right.
128 |
129 | With only a single-line code change (the ziti.express call), your web server is now capable
130 | of being invisible to malicious attackers on the internet, and only accessible to your
131 | trusted remote users.
132 |
133 | Nothing else in your existing ExpressJS web server code needs to change!
134 |
135 | Existing routing, middleware, etc., all operates the same as it always did...
136 | but now you enjoy the comfort of knowing that if a connection comes in, it is from
137 | a trusted identity on the client side.
138 |
139 | No malicious actors can see your dark web server, and thus, no malicious actors can attack it.
140 |
141 | */
142 | ```
143 |
144 | CJS example (client-side)
145 | ``` js
146 | var ziti = require('@openziti/ziti-sdk-nodejs');
147 |
148 | const ziti_init = async (identity) => {
149 | return new Promise((resolve) => {
150 | ziti.ziti_init(identity, () => {
151 | resolve();
152 | });
153 | });
154 | };
155 |
156 | const ziti_service_available = (service) => {
157 | return new Promise((resolve) => {
158 | ziti.ziti_service_available(service, (status) => {
159 | resolve(status);
160 | });
161 | });
162 | };
163 |
164 | function ziti_dial(service) {
165 | return new Promise((resolve, reject) => {
166 | ziti.ziti_dial(
167 | service,
168 | (conn) => {
169 | resolve(conn);
170 | },
171 | (data) => {
172 | // Do something with data...
173 | },
174 | );
175 | });
176 | }
177 |
178 | const ziti_write = (conn, data) => {
179 | return new Promise((resolve) => {
180 | ziti.ziti_write(conn, data, () => {
181 | resolve();
182 | });
183 | });
184 | };
185 |
186 | (async () => {
187 |
188 | await ziti_init(LOCATION_OF_IDENTITY_FILE);
189 |
190 | let status = await ziti_service_available(YOUR_SERVICE_NAME);
191 |
192 | if (status === 0) {
193 |
194 | const conn = await ziti_dial(YOUR_SERVICE_NAME);
195 |
196 | let data = SOME_KIND_OF_DATA;
197 |
198 | let buffer = Buffer.from(data);
199 |
200 | await ziti_write(conn, buffer);
201 |
202 | ...etc
203 | }
204 |
205 | })();
206 | ```
207 |
208 | # API Reference
209 | {{#module name="@openziti/ziti-sdk-nodejs"}}
210 | {{>body~}}
211 | {{>member-index~}}
212 | {{>separator~}}
213 | {{>members~}}
214 | {{/module}}
215 |
216 | * * *
217 |
218 | Getting Help
219 | ------------
220 | Please use these community resources for getting help. We use GitHub [issues](https://github.com/openziti/ziti-sdk-nodejs/issues)
221 | for tracking bugs and feature requests and have limited bandwidth to address them.
222 |
223 | - Read the [docs](https://openziti.github.io/ziti/overview.html)
224 | - Participate in discussion on [Discourse](https://openziti.discourse.group/)
225 |
226 |
227 | Copyright© NetFoundry, Inc.
228 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
4 | OpenZiti is a free and open source project focused on bringing zero trust to any application.
5 |
6 | The project provides all the pieces required to implement or integrate zero trust into your solutions.
7 |
8 |
9 | Please star us.
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | @openziti/ziti-sdk-nodejs
23 |
24 |
25 |
26 | This repo hosts the OpenZiti SDK for NodeJS, and is designed to help you deliver secure applications over a OpenZiti Network
27 |
28 |
29 | Part of the OpenZiti ecosystem
30 |
31 |
32 |
33 |
34 | Are you interested in knowing how to easily embed programmable, high performance, zero trust networking into your NodeJS app, on any internet connection, without VPNs?
35 |
36 | Learn more about our OpenZiti project.
37 |
38 |
39 |
40 | ---
41 | []()
42 | []()
43 | [](https://badge.fury.io/js/@openziti%2Fziti-sdk-nodejs.svg)
44 | [](https://opensource.org/licenses/Apache-2.0)
45 | []()
46 | [](CONTRIBUTING.md)
47 | [](CODE_OF_CONDUCT.md)
48 |
49 | ---
50 |
51 | # Associated Article(s)
52 | For more context on this SDK, you may be interested in this
53 | [article concerning how to secure NodeJS applications](https://blog.openziti.io/securing-nodejs-applications)
54 |
55 |
56 |
57 | # Supported platforms
58 |
59 | The `@openziti/ziti-sdk-nodejs` module works with the following Node.js versions:
60 | - v16.x
61 | - v18.x
62 | - v19.x
63 | - v20.x
64 | - v21.x
65 | - v22.x
66 | - v23.x
67 |
68 | The `@openziti/ziti-sdk-nodejs` module works with the following architectures:
69 | - amd64
70 | - arm64
71 |
72 | The `@openziti/ziti-sdk-nodejs` module works with the following Operating Systems:
73 | - macos
74 | - linux
75 | - windows
76 |
77 |
78 | # Installing
79 |
80 | NPM
81 | ``` js
82 | npm i @openziti/ziti-sdk-nodejs
83 | ```
84 | or Yarn
85 | ``` js
86 | yarn add @openziti/ziti-sdk-nodejs
87 | ```
88 |
89 | Special note on previous package:
90 |
91 | On June 7, 2020 @openziti/ziti-sdk-nodejs@0.6.0 was released. Older, unscoped versions that are not part of the @openziti org are deprecated and only @openziti/ziti-sdk-nodejs will see updates going forward. To upgrade to the new package do:
92 |
93 | ``` js
94 | npm uninstall ziti-sdk-nodejs --save
95 | npm install @openziti/ziti-sdk-nodejs --save
96 | ```
97 |
98 | # Usage
99 |
100 | **Note:** the module must be [installed](#installing) before use.
101 |
102 | ESM example (client-side)
103 | ``` js
104 | import ziti from '@openziti/ziti-sdk-nodejs';
105 |
106 | // Somehow provide path to identity file, e.g. via env var
107 | const zitiIdentityFile = process.env.ZITI_IDENTITY_FILE;
108 | // Authenticate ourselves onto the Ziti network
109 | await ziti.init( zitiIdentityFile ).catch(( err ) => { /* probably exit */ });
110 |
111 | const on_resp_data = ( obj ) => {
112 | console.log(`response is: ${obj.body.toString('utf8')}`);
113 | };
114 |
115 | // Perform an HTTP GET request to a dark OpenZiti web service
116 | ziti.httpRequest(
117 | 'myDarkWebService', // OpenZiti Service name or HTTP origin part of the URL
118 | undefined, // schemeHostPort parm is mutually-exclusive with serviceName parm
119 | 'GET',
120 | '/', // path part of the URL including query params
121 | ['Accept: application/json' ], // headers
122 | undefined, // optional on_req cb
123 | undefined, // optional on_req_data cb
124 | on_resp_data // optional on_resp_data cb
125 | );
126 |
127 | ```
128 |
129 | ESM example (server-side ExpressJS)
130 | ``` js
131 | import ziti from '@openziti/ziti-sdk-nodejs';
132 | import express from 'express';
133 | let app = ziti.express( express, zitiServiceName );
134 | app.listen(ignored, function() { ... }
135 |
136 | /**
137 |
138 | That's right.
139 |
140 | With only a single-line code change (the ziti.express call), your web server is now capable
141 | of being invisible to malicious attackers on the internet, and only accessible to your
142 | trusted remote users.
143 |
144 | Nothing else in your existing ExpressJS web server code needs to change!
145 |
146 | Existing routing, middleware, etc., all operates the same as it always did...
147 | but now you enjoy the comfort of knowing that if a connection comes in, it is from
148 | a trusted identity on the client side.
149 |
150 | No malicious actors can see your dark web server, and thus, no malicious actors can attack it.
151 |
152 | */
153 | ```
154 |
155 | CJS example (client-side)
156 | ``` js
157 | var ziti = require('@openziti/ziti-sdk-nodejs');
158 |
159 | const ziti_init = async (identity) => {
160 | return new Promise((resolve) => {
161 | ziti.ziti_init(identity, () => {
162 | resolve();
163 | });
164 | });
165 | };
166 |
167 | const ziti_service_available = (service) => {
168 | return new Promise((resolve) => {
169 | ziti.ziti_service_available(service, (status) => {
170 | resolve(status);
171 | });
172 | });
173 | };
174 |
175 | function ziti_dial(service) {
176 | return new Promise((resolve, reject) => {
177 | ziti.ziti_dial(
178 | service,
179 | (conn) => {
180 | resolve(conn);
181 | },
182 | (data) => {
183 | // Do something with data...
184 | },
185 | );
186 | });
187 | }
188 |
189 | const ziti_write = (conn, data) => {
190 | return new Promise((resolve) => {
191 | ziti.ziti_write(conn, data, () => {
192 | resolve();
193 | });
194 | });
195 | };
196 |
197 | (async () => {
198 |
199 | await ziti_init(LOCATION_OF_IDENTITY_FILE);
200 |
201 | let status = await ziti_service_available(YOUR_SERVICE_NAME);
202 |
203 | if (status === 0) {
204 |
205 | const conn = await ziti_dial(YOUR_SERVICE_NAME);
206 |
207 | let data = SOME_KIND_OF_DATA;
208 |
209 | let buffer = Buffer.from(data);
210 |
211 | await ziti_write(conn, buffer);
212 |
213 | ...etc
214 | }
215 |
216 | })();
217 | ```
218 |
219 | # API Reference
220 | For doc concerning API's contained in this SDK, you may be interested in this
221 | [SDK API Reference](API_REFERENCE.md)
222 |
223 |
224 | Getting Help
225 | ------------
226 | Please use these community resources for getting help. We use GitHub [issues](https://github.com/openziti/ziti-sdk-nodejs/issues)
227 | for tracking bugs and feature requests and have limited bandwidth to address them.
228 |
229 | - Read the [docs](https://openziti.github.io/ziti/overview.html)
230 | - Participate in discussion on [Discourse](https://openziti.discourse.group/)
231 |
232 |
233 | # Building from source on MacOS
234 |
235 | ``` js
236 | git clone https://github.com/microsoft/vcpkg.git
237 | ./vcpkg/bootstrap-vcpkg.sh
238 | export VCPKG_ROOT=`pwd`/vcpkg
239 | brew install cmake
240 | brew install ninja
241 | brew install pkg-config
242 | git clone https://github.com/openziti/ziti-sdk-nodejs.git
243 | cd ziti-sdk-nodejs
244 | npm run build
245 | ```
246 |
247 | Copyright© NetFoundry, Inc.
248 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | Please refer to the [openziti-security repository](https://github.com/openziti/openziti-security) for details of the security policies and processes for this repository.
--------------------------------------------------------------------------------
/binding.gyp:
--------------------------------------------------------------------------------
1 | {
2 | # "includes": [ "deps/common-ziti.gypi" ],
3 |
4 | # The "cd" variable is passed in, and used, only during Windows builds
5 | 'variables': {
6 | 'cd%': '.',
7 |
8 | # node v0.6.x doesn't give us its build variables,
9 | # but on Unix it was only possible to use the system OpenSSL library,
10 | # so default the variable to "true", v0.8.x node and up will overwrite it.
11 | 'node_shared_openssl%': 'true',
12 |
13 | },
14 |
15 | "targets": [
16 | {
17 | 'defines': [
18 | 'BUILD_DATE= {
24 |
25 | ziti.ziti_close( conn );
26 |
27 | };
28 |
29 | exports.close = close;
30 |
--------------------------------------------------------------------------------
/lib/dial.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 |
19 | /**
20 | * on_connect()
21 | *
22 | */
23 | const on_connect = ( status ) => {
24 |
25 | };
26 |
27 | /**
28 | * on_data()
29 | *
30 | */
31 | const on_data = ( status ) => {
32 |
33 | };
34 |
35 |
36 | /**
37 | * dial()
38 | *
39 | * @param {*} serviceName
40 | * @param {*} isWebSocket
41 | * @param {*} on_connect_cb callback
42 | * @param {*} on_data_cb callback
43 | */
44 | const dial = ( serviceName, isWebSocket, on_connect_cb, on_data_cb ) => {
45 |
46 | let connect_cb;
47 | let data_cb;
48 |
49 | if (typeof on_connect_cb === 'undefined') {
50 | connect_cb = on_connect;
51 | } else {
52 | connect_cb = on_connect_cb;
53 | }
54 |
55 | if (typeof on_data_cb === 'undefined') {
56 | data_cb = on_data;
57 | } else {
58 | data_cb = on_data_cb;
59 | }
60 |
61 | ziti.ziti_dial(serviceName, isWebSocket, connect_cb, data_cb);
62 |
63 | };
64 |
65 |
66 | exports.dial = dial;
67 |
--------------------------------------------------------------------------------
/lib/enroll.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 |
19 | /**
20 | * on_enroll()
21 | *
22 | */
23 | const on_enroll = ( status ) => {
24 |
25 | };
26 |
27 |
28 | /**
29 | * enroll()
30 | *
31 | * @param {*} jwt_path
32 | * @param {*} on_enroll_cb callback
33 | */
34 | const enroll = ( jwt_path, on_enroll_cb ) => {
35 |
36 | let enroll_cb;
37 |
38 | if (typeof on_enroll_cb === 'undefined') {
39 | enroll_cb = on_enroll;
40 | } else {
41 | enroll_cb = on_enroll_cb;
42 | }
43 |
44 | ziti.ziti_enroll(jwt_path, enroll_cb);
45 |
46 | };
47 |
48 |
49 | exports.enroll = enroll;
50 |
--------------------------------------------------------------------------------
/lib/express-listener.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | const zitiListen = require('./listen').listen;
18 | const EventEmitter = require('events');
19 | const { ZitiSocket } = require('./ziti-socket');
20 |
21 |
22 | const normalizedArgsSymbol = Symbol('normalizedArgs');
23 |
24 |
25 | var _serversIndex = 1;
26 | var _servers = new Map();
27 |
28 | /**
29 | * on_listen()
30 | *
31 | * @param {*} status
32 | */
33 | Server.prototype.on_listen = ( status ) => {
34 |
35 | };
36 |
37 | /**
38 | * on_listen_client()
39 | *
40 | * @param {*} obj
41 | */
42 | Server.prototype.on_listen_client = ( obj ) => {
43 |
44 | };
45 |
46 | /**
47 | * on_client_write()
48 | *
49 | * @param {*} obj
50 | */
51 | Server.prototype.on_client_write = ( obj ) => {
52 |
53 | };
54 |
55 | /**
56 | * on_listen_client_connect()
57 | *
58 | * @param {*} obj
59 | */
60 | Server.prototype.on_listen_client_connect = ( obj ) => {
61 |
62 | let self = _servers.get(obj.js_arb_data);
63 |
64 | const socket = new ZitiSocket({ client: obj.client });
65 |
66 | self._socket = socket;
67 |
68 | self.emit('connection', socket);
69 | };
70 |
71 | /**
72 | * on_listen_client_data()
73 | *
74 | * @param {*} obj
75 | */
76 | Server.prototype.on_listen_client_data = ( obj ) => {
77 |
78 | let self = _servers.get(obj.js_arb_data);
79 | let socket = self._socket;
80 |
81 | socket.captureData(obj.app_data);
82 | };
83 |
84 |
85 | /**
86 | *
87 | * @param {*} args
88 | */
89 | function normalizeArgs(args) {
90 | let arr;
91 |
92 | if (args.length === 0) {
93 | arr = [{}, null];
94 | arr[normalizedArgsSymbol] = true;
95 | return arr;
96 | }
97 |
98 | const arg0 = args[0];
99 | let options = {};
100 | if (typeof arg0 === 'object' && arg0 !== null) {
101 | // (options[...][, cb])
102 | options = arg0;
103 | } else {
104 | // ([port][, host][...][, cb])
105 | options.port = arg0;
106 | if (args.length > 1 && typeof args[1] === 'string') {
107 | options.host = args[1];
108 | }
109 | }
110 |
111 | const cb = args[args.length - 1];
112 | if (typeof cb !== 'function')
113 | arr = [options, null];
114 | else
115 | arr = [options, cb];
116 |
117 | arr[normalizedArgsSymbol] = true;
118 | return arr;
119 | }
120 |
121 | function Server(serviceName, options, connectionListener) {
122 |
123 | if (!(this instanceof Server))
124 | return new Server(options, connectionListener);
125 |
126 | EventEmitter.call(this);
127 |
128 | if (typeof options === 'function') {
129 | connectionListener = options;
130 | options = {};
131 | this.on('connection', connectionListener);
132 | } else if (options == null || typeof options === 'object') {
133 | options = { ...options };
134 |
135 | if (typeof connectionListener === 'function') {
136 | this.on('connection', connectionListener);
137 | }
138 | } else {
139 | throw new ERR_INVALID_ARG_TYPE('options', 'Object', options);
140 | }
141 | if (typeof options.keepAliveInitialDelay !== 'undefined') {
142 | validateNumber(
143 | options.keepAliveInitialDelay, 'options.keepAliveInitialDelay'
144 | );
145 |
146 | if (options.keepAliveInitialDelay < 0) {
147 | options.keepAliveInitialDelay = 0;
148 | }
149 | }
150 |
151 | this._serviceName = serviceName;
152 |
153 | this._connections = 0;
154 |
155 | // this[async_id_symbol] = -1;
156 | this._handle = null;
157 | this._usingWorkers = false;
158 | this._workers = [];
159 | this._unref = false;
160 |
161 | this.allowHalfOpen = options.allowHalfOpen || false;
162 | this.pauseOnConnect = !!options.pauseOnConnect;
163 | this.noDelay = Boolean(options.noDelay);
164 | this.keepAlive = Boolean(options.keepAlive);
165 | this.keepAliveInitialDelay = ~~(options.keepAliveInitialDelay / 1000);
166 | }
167 | Object.setPrototypeOf(Server.prototype, EventEmitter.prototype);
168 | Object.setPrototypeOf(Server, EventEmitter);
169 |
170 |
171 | Server.prototype.listen = function( serviceName, ...args ) {
172 |
173 | let normalized = normalizeArgs(args);
174 | normalized = normalizeArgs(normalized[0]);
175 |
176 | // let options = normalized[0]; // we currently ignore options (a.k.a. `port`)
177 | let cb = normalized[1];
178 | if (cb === null) { cb = this.on_listen; } // Use our on_listen cb is necessary, else use cb from teh calling app
179 |
180 | let index = _serversIndex++;
181 | _servers.set(index, this);
182 |
183 | zitiListen( serviceName, index, cb, this.on_listen_client, this.on_listen_client_connect, this.on_listen_client_data );
184 | };
185 |
186 | Server.prototype.address = function() {
187 | if (this._handle && this._handle.getsockname) {
188 | const out = {};
189 | const err = this._handle.getsockname(out);
190 | if (err) {
191 | throw errnoException(err, 'address');
192 | }
193 | return out;
194 | } else if (this._pipeName) {
195 | return this._pipeName;
196 | }
197 | return null;
198 | };
199 |
200 | Server.prototype.close = function(cb) {
201 | if (typeof cb === 'function') {
202 | if (!this._handle) {
203 | this.once('close', function close() {
204 | cb(new ERR_SERVER_NOT_RUNNING());
205 | });
206 | } else {
207 | this.once('close', cb);
208 | }
209 | }
210 |
211 | if (this._handle) {
212 | this._handle.close();
213 | this._handle = null;
214 | }
215 |
216 | if (this._usingWorkers) {
217 | let left = this._workers.length;
218 | const onWorkerClose = () => {
219 | if (--left !== 0) return;
220 |
221 | this._connections = 0;
222 | this._emitCloseIfDrained();
223 | };
224 |
225 | // Increment connections to be sure that, even if all sockets will be closed
226 | // during polling of workers, `close` event will be emitted only once.
227 | this._connections++;
228 |
229 | // Poll workers
230 | for (let n = 0; n < this._workers.length; n++)
231 | this._workers[n].close(onWorkerClose);
232 | } else {
233 | this._emitCloseIfDrained();
234 | }
235 |
236 | return this;
237 | };
238 |
239 | Object.defineProperty(Server.prototype, 'listening', {
240 | __proto__: null,
241 | get: function() {
242 | return !!this._handle;
243 | },
244 | configurable: true,
245 | enumerable: true
246 | });
247 |
248 |
249 | module.exports = {
250 | Server,
251 | };
252 |
--------------------------------------------------------------------------------
/lib/express.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | const expressListener = require('./express-listener');
18 | const { Server } = require('_http_server'); // from NodeJS internals
19 |
20 |
21 |
22 | /**
23 | * express()
24 | *
25 | * @param {*} express
26 | * @param {*} serviceName
27 | */
28 | const express = ( express, serviceName ) => {
29 |
30 | var wrappedExpressApp = express();
31 |
32 | /**
33 | * Listen for connections.
34 | *
35 | * A node `http.Server` is returned, with this
36 | * application (which is a `Function`) as its
37 | * callback.
38 | *
39 | * @return {http.Server}
40 | * @public
41 | */
42 | wrappedExpressApp.listen = function() {
43 |
44 | Object.setPrototypeOf(Server.prototype, expressListener.Server.prototype);
45 | Object.setPrototypeOf(Server, expressListener.Server);
46 | var server = new Server(this);
47 |
48 | expressListener.Server.call( server, serviceName, { } );
49 |
50 | return server.listen(serviceName, arguments);
51 |
52 | };
53 |
54 | return wrappedExpressApp;
55 |
56 | };
57 |
58 | exports.express = express;
59 |
--------------------------------------------------------------------------------
/lib/httpRequest.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * on_req()
20 | *
21 | */
22 | const on_req = ( obj ) => {
23 |
24 | console.log('on_req entered: ', obj);
25 |
26 | };
27 |
28 | /**
29 | * on_resp()
30 | *
31 | */
32 | const on_resp = ( obj ) => {
33 |
34 | console.log('on_resp entered: ', obj);
35 |
36 | };
37 |
38 | /**
39 | * on_resp_data()
40 | *
41 | */
42 | const on_resp_data = ( obj ) => {
43 |
44 | console.log('on_resp_data entered: ', obj);
45 | console.log('as string: ', obj.body.toString('utf8'));
46 |
47 | };
48 |
49 | const httpRequest = ( serviceName, schemeHostPort, method, path, headers, on_req_cb, on_resp_cb, on_resp_data_cb ) => {
50 |
51 | let _on_req_cb;
52 | let _on_resp_cb;
53 | let _on_resp_data_cb;
54 |
55 | if (typeof on_req_cb === 'undefined') {
56 | _on_req_cb = on_req;
57 | } else {
58 | _on_req_cb = on_req_cb;
59 | }
60 |
61 | if (typeof on_resp_cb === 'undefined') {
62 | _on_resp_cb = on_resp;
63 | } else {
64 | _on_resp_cb = on_req_cb;
65 | }
66 |
67 | if (typeof on_resp_data_cb === 'undefined') {
68 | _on_resp_data_cb = on_resp_data;
69 | } else {
70 | _on_resp_data_cb = on_resp_data_cb;
71 | }
72 |
73 | ziti.Ziti_http_request( serviceName, schemeHostPort, method, path, headers, _on_req_cb, _on_resp_cb, _on_resp_data_cb );
74 |
75 | };
76 |
77 |
78 | exports.httpRequest = httpRequest;
79 |
80 |
--------------------------------------------------------------------------------
/lib/httpRequestData.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * on_req_data()
20 | *
21 | */
22 | const on_req_data = ( obj ) => {
23 |
24 | console.log('on_req_data entered: ', obj);
25 | console.log('as string: ', obj.body.toString('utf8'));
26 |
27 | };
28 |
29 | const httpRequestData = ( req, buffer, on_req_data_cb ) => {
30 |
31 | console.log('httpRequestData entered: ', req, buffer);
32 |
33 | let _on_req_data_cb;
34 |
35 | if (typeof on_req_data_cb === 'undefined') {
36 | _on_req_data_cb = on_req_data;
37 | } else {
38 | _on_req_data_cb = on_req_data_cb;
39 | }
40 |
41 | ziti.Ziti_http_request_data( req, buffer, _on_req_data_cb );
42 | };
43 |
44 |
45 | exports.httpRequestData = httpRequestData;
46 |
47 |
--------------------------------------------------------------------------------
/lib/httpRequestEnd.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | const httpRequestEnd = ( req ) => {
19 | ziti.Ziti_http_request_end( req );
20 | };
21 |
22 | exports.httpRequestEnd = httpRequestEnd;
23 |
24 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | module.exports = require('./ziti');
--------------------------------------------------------------------------------
/lib/init.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | const init = ( identityPath ) => {
19 |
20 | return new Promise((resolve, reject) => {
21 |
22 | let rc = ziti.ziti_init( identityPath, ( result ) => {
23 |
24 | return resolve( result );
25 |
26 | });
27 |
28 | if (rc < 0) {
29 | return reject(`ziti.init() failed with return code ${rc}`);
30 | }
31 |
32 | });
33 | };
34 |
35 | exports.init = init;
36 |
--------------------------------------------------------------------------------
/lib/listen.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * listen()
20 | *
21 | * @param {*} identityPath
22 | */
23 | const listen = ( serviceName, js_arb_data, on_listen, on_listen_client, on_client_connect, on_client_data ) => {
24 |
25 | ziti.ziti_listen( serviceName, js_arb_data, on_listen, on_listen_client, on_client_connect, on_client_data );
26 |
27 | };
28 |
29 | exports.listen = listen;
30 |
--------------------------------------------------------------------------------
/lib/serviceAvailable.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * on_serviceAvailable()
20 | *
21 | */
22 | const on_serviceAvailable = ( status ) => {
23 |
24 | };
25 |
26 |
27 | /**
28 | * write()
29 | *
30 | * @param {*} service
31 | * @param {*} on_write callback
32 | */
33 | const serviceAvailable = ( service, sa_cb ) => {
34 |
35 | let cb;
36 |
37 | if (typeof sa_cb === 'undefined') {
38 | cb = on_serviceAvailable;
39 | } else {
40 | cb = sa_cb;
41 | }
42 |
43 | ziti.ziti_service_available( service, cb );
44 |
45 | };
46 |
47 | exports.serviceAvailable = serviceAvailable;
48 |
--------------------------------------------------------------------------------
/lib/servicesRefresh.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * servicesRefresh()
20 | *
21 | */
22 | const servicesRefresh = () => {
23 |
24 | ziti.ziti_services_refresh();
25 |
26 | };
27 |
28 | exports.servicesRefresh = servicesRefresh;
29 |
--------------------------------------------------------------------------------
/lib/setLogLevel.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * setLogLevel()
20 | *
21 | * @param {*} lvl
22 | */
23 | const setLogLevel = ( lvl ) => {
24 |
25 | ziti.ziti_set_log_level( lvl );
26 |
27 | };
28 |
29 | exports.setLogLevel = setLogLevel;
30 |
--------------------------------------------------------------------------------
/lib/write.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 |
18 | /**
19 | * on_write()
20 | *
21 | */
22 | const on_write = ( status ) => {
23 |
24 | };
25 |
26 |
27 | /**
28 | * write()
29 | *
30 | * @param {*} conn
31 | * @param {*} buf
32 | * @param {*} on_write callback
33 | */
34 | const write = ( conn, buf, on_write_cb ) => {
35 |
36 | let cb;
37 |
38 | if (typeof on_write_cb === 'undefined') {
39 | cb = on_write;
40 | } else {
41 | cb = on_write_cb;
42 | }
43 |
44 | ziti.ziti_write( conn, buf, cb );
45 |
46 | };
47 |
48 | exports.write = write;
49 |
--------------------------------------------------------------------------------
/lib/ziti-socket.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | const EventEmitter = require('events');
18 | const stream = require('stream');
19 | const zitiWrite = require('./write').write;
20 |
21 |
22 |
23 | class ZitiSocket extends EventEmitter {
24 |
25 | constructor(opts) {
26 |
27 | super();
28 |
29 | if (typeof opts !== 'undefined') {
30 | if (typeof opts.client !== 'undefined') {
31 | this.client = opts.client;
32 | }
33 | }
34 |
35 | this._writableState = new stream.Writable.WritableState({}, this, true);
36 |
37 | /**
38 | * This stream is where we'll put any data returned from Ziti (see on_listen_client_data cb)
39 | */
40 | let self = this;
41 | this.readableZitiStream = new ReadableStream({
42 | start(controller) {
43 | self.readableZitiStreamController = controller;
44 | }
45 | });
46 | }
47 |
48 |
49 | /**
50 | *
51 | */
52 | captureData(data) {
53 |
54 | if ((typeof data !== 'undefined') && (data.byteLength > 0)) {
55 |
56 | this.readableZitiStreamController.enqueue(data);
57 | this.emit('data', data);
58 |
59 | } else {
60 |
61 | this.emit('close');
62 |
63 | }
64 | }
65 |
66 |
67 | /**
68 | * Implements the writeable stream method `_write` by pushing the data onto the underlying Ziti connection.
69 | */
70 | async write(chunk, encoding, cb) {
71 |
72 | let buffer;
73 |
74 | if (typeof chunk === 'string' || chunk instanceof String) {
75 | buffer = Buffer.from(chunk, 'utf8');
76 | } else if (Buffer.isBuffer(chunk)) {
77 | buffer = chunk;
78 | } else if (chunk instanceof Uint8Array) {
79 | buffer = Buffer.from(chunk, 'utf8');
80 | } else {
81 | throw new Error('chunk type of [' + typeof chunk + '] is not a supported type');
82 | }
83 |
84 | if (buffer.length > 0) {
85 | zitiWrite(this.client, buffer);
86 | }
87 | if (cb) {
88 | cb();
89 | }
90 | }
91 |
92 | /**
93 | *
94 | */
95 | _read() { /* NOP */ }
96 | read() { /* NOP */ }
97 | destroy() { /* NOP */ }
98 | cork() { /* NOP */ }
99 | uncork() { /* NOP */ }
100 | pause() { /* NOP */ }
101 | resume() { /* NOP */ }
102 | destroy() { /* NOP */ }
103 | end(data, encoding, callback) { /* NOP */ }
104 | _final(cb) { cb(); }
105 | setTimeout() { /* NOP */ }
106 | setNoDelay() { /* NOP */ }
107 | unshift(head) { /* NOP */ }
108 | }
109 |
110 | Object.defineProperty(ZitiSocket.prototype, 'writable', {
111 | get() {
112 | return (
113 | true
114 | );
115 | }
116 | });
117 |
118 |
119 | exports.ZitiSocket = ZitiSocket;
120 |
--------------------------------------------------------------------------------
/lib/ziti.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | /**
18 | * OpenZiti SDK for Node.js
19 | *
20 | * @module @openziti/ziti-sdk-nodejs
21 | *
22 | */
23 |
24 | var binding;
25 |
26 | function importAll (r) {
27 | r.keys().forEach(key => {
28 | binding = r(key); // Load the addon
29 | });
30 | }
31 |
32 | if (typeof require.context == 'function') {
33 |
34 | importAll( require.context("../build/", true, /\.node$/) );
35 |
36 | } else {
37 |
38 | const binary = require('@mapbox/node-pre-gyp');
39 | const path = require('path')
40 | const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: false});
41 |
42 | binding = require(binding_path);
43 |
44 | }
45 |
46 | ziti = module.exports = exports = binding;
47 |
48 |
49 |
50 | /**
51 | * Attach the external, app-facing, API to the 'ziti' object
52 | */
53 |
54 | /**
55 | * Close a Ziti connection.
56 | * @function close
57 | * @param {number} conn - A Ziti connection handle.
58 | * @returns {void} No return value.
59 | */
60 | exports.close = require('./close').close;
61 |
62 | /**
63 | * Create a connection to Ziti Service.
64 | * @async
65 | * @function dial
66 | * @param {string} serviceName - The name of the Ziti Service to connect to
67 | * @param {boolean} isWebSocket - True or False indicator concerning whether this connection if bi-directional.
68 | * @param {onConnectCallback} onConnect - The callback that receives the connection handle.
69 | * @param {onDataCallback} onData - The callback that receives incoming data from the connection.
70 | * @returns {void} No return value.
71 | */
72 | /**
73 | * This callback is part of the `dial` API.
74 | * @callback onDataCallback - The callback that receives the connection handle.
75 | * @param {number} conn - A Ziti connection handle.
76 | */
77 | /**
78 | * This callback is part of the `dial` API.
79 | * @callback onConnectCallback - The callback that receives incoming data from the connection.
80 | * @param {Buffer} data - Incoming data from the Ziti connection.
81 | * @returns {void} No return value.
82 | */
83 | exports.dial = require('./dial').dial;
84 |
85 | /**
86 | * Enroll a Ziti Identity.
87 | * @async
88 | * @function enroll
89 | * @param {string} jwt_path - The path to the JWT
90 | * @param {onEnrollCallback} onEnroll - The callback that receives the enrollment status.
91 | * @returns {void} No return value.
92 | */
93 | /**
94 | * This callback is part of the `enroll` API.
95 | * @callback onEnrollCallback - The callback that receives the enrollment status.
96 | * @param {object} obj - enrollment status.
97 | */
98 | exports.enroll = require('./enroll').enroll;
99 |
100 | /**
101 | * Wrap ExpressJS to facilitate hosting (listening) on a Ziti Service instead of a TCP port.
102 | * @function express
103 | * @param {*} express - The express() object.
104 | * @param {string} serviceName - The name of the Ziti Service being served (hosted).
105 | * @returns {*} The wrapped express() object.
106 | */
107 | exports.express = require('./express').express;
108 |
109 | /**
110 | * Initiate an HTTP request to a Ziti Service.
111 | * @function httpRequest
112 | * @param {string} serviceName - The name of the Ziti Service to send the request. (mutually exclusive with url)
113 | * @param {string} schemeHostPort - The scheme/host/port (e.g. http://myserver.ziti:8080) of a Ziti service-config/intercept to send the request. (mutually exclusive with serviceName)
114 | * @param {string} method - The REST verb to use (e.g. `GET`, `POST`).
115 | * @param {string} path - The URL PATH to use on the request (can include HTTP query parms).
116 | * @param {string[]} headers - The HTTP Headers to use on the request.
117 | * @param {onRequestCallback} onRequest - The callback that receives the request handle.
118 | * @param {onResonseCallback} onResponse - The callback that receives the HTTP Response.
119 | * @param {onResonseDataCallback} onResponseData - The callback that receives the HTTP Response data.
120 | * @returns {void} No return value.
121 | */
122 | /**
123 | * This callback is part of the `httpRequest` API.
124 | * @callback onRequestCallback - The callback that receives the request handle.
125 | * @param {number} req - A Ziti HttpRequest handle.
126 | * @returns {void} No return value.
127 | */
128 | /**
129 | * This callback is part of the `httpRequest` API.
130 | * @callback onResonseCallback - The callback that receives response from the request.
131 | * @param resp - Incoming response from the HTTP request.
132 | * @param resp.req - The request handle.
133 | * @param resp.code - The HTTP status code.
134 | * @param resp.headers - The HTTP Headers on the response.
135 | * @returns {void} No return value.
136 | */
137 | /**
138 | * This callback is part of the `httpRequest` API.
139 | * @callback onResonseDataCallback - The callback that receives incoming data from the request.
140 | * @param respData - Incoming response data from the HTTP request.
141 | * @param respData.req - The request handle.
142 | * @param respData.len - The length of the response body.
143 | * @param respData.body - The response body.
144 | * @returns {void} No return value.
145 | */
146 | exports.httpRequest = require('./httpRequest').httpRequest;
147 |
148 | /**
149 | * Send payload data for HTTP POST request to a Ziti Service.
150 | * @function httpRequestData
151 | * @param {number} req - A Ziti HttpRequest handle.
152 | * @param {Buffer} data - The HTTP payload data to send.
153 | * @param {onRequestDataCallback} onRequestData - The callback that acknowleges the send.
154 | * @returns {void} No return value.
155 | */
156 | /**
157 | * This callback is part of the `httpRequestData` API.
158 | * @callback onRequestDataCallback - The callback that acknowleges the send.
159 | * @param reqData - Incoming status data from the HTTP request.
160 | * @param respData.req - The request handle.
161 | * @param respData.status - positive value indicates successful transmit.
162 | * @returns {void} No return value.
163 | */
164 | exports.httpRequestData = require('./httpRequestData').httpRequestData;
165 |
166 | /**
167 | * Terminate payload data transmission for HTTP POST request to a Ziti Service.
168 | * @function httpRequestEnd
169 | * @param {number} req - A Ziti HttpRequest handle.
170 | * @returns {void} No return value.
171 | */
172 | exports.httpRequestEnd = require('./httpRequestEnd').httpRequestEnd;
173 |
174 | /**
175 | * Initialize the Ziti session and authenticate with control plane.
176 | * @function init
177 | * @param {string} identityPath - File system path to the identity file.
178 | * @returns {number} A status value ranging from 0 to 255.
179 | */
180 | exports.init = require('./init').init;
181 |
182 | // Internal use only
183 | exports.listen = require('./listen').listen;
184 |
185 | /**
186 | * Set the logging level.
187 | * @function setLogLevel
188 | * @param {number} level - 0=NONE, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG, 5=TRACE
189 | * @returns {void} No return value.
190 | */
191 | exports.setLogLevel = require('./setLogLevel').setLogLevel;
192 |
193 | /**
194 | * Set the logging level.
195 | * @function serviceAvailable
196 | * @param {string} serviceName - The name of the Ziti Service being queried.
197 | * @param {onServiceAvailableCallback} onServiceAvailable - The callback that returns results of the query.
198 | * @returns {void} No return value.
199 | */
200 | /**
201 | * This callback is part of the `serviceAvailable` API.
202 | * @callback onServiceAvailableCallback - The callback that returns results of the query.
203 | * @param availability - results of the query.
204 | * @param availability.status - 0 means `available and OK`, <0 means `unavailable`
205 | * @param availability.permissions - 1 means the identity can dial, 2 means the identity can bind
206 | * @returns {void} No return value.
207 | */
208 | exports.serviceAvailable = require('./serviceAvailable').serviceAvailable;
209 |
210 | /**
211 | * write data to a Ziti connection.
212 | * @function write
213 | * @param {number} conn - A Ziti connection handle.
214 | * @param {Buffer} data - The data to send.
215 | * @param {onWriteCallback} onWrite - The callback that returns status of the write.
216 | * @returns {void} No return value.
217 | */
218 | /**
219 | * This callback is part of the `write` API.
220 | * @callback onWriteCallback - The callback that returns results of the v.
221 | * @param status - 0 means success, <0 means failure.
222 | * @returns {void} No return value.
223 | */
224 | exports.write = require('./write').write;
225 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@openziti/ziti-sdk-nodejs",
3 | "description": "A NodeJS-based SDK for delivering secure applications over a Ziti Network",
4 | "version": "0.20.0",
5 | "main": "./lib/ziti",
6 | "scripts": {
7 | "build": "npm run build:configure && npm run build:make",
8 | "build:configure": "run-script-os",
9 | "build:configure:windows": "configure",
10 | "build:configure:linux:darwin": "./configure",
11 | "build:make": "cmake-js build",
12 | "build:package": "node-pre-gyp package",
13 | "clean": "cmake-js clean",
14 | "test": "echo \"Error: no test specified\"",
15 | "install": "node-pre-gyp install || npm run build",
16 | "publish": "node-pre-gyp package publish",
17 | "docs": "jsdoc2md -t API_REFERENCE.hbs lib/*.js > API_REFERENCE.md"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "https://github.com/openziti/ziti-sdk-nodejs.git"
22 | },
23 | "binary": {
24 | "module_name": "ziti_sdk_nodejs",
25 | "module_path": "./build/{configuration}/",
26 | "remote_path": "./{module_name}/v{version}/{configuration}/",
27 | "package_name": "{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz",
28 | "host": "https://ziti-npm.s3.amazonaws.com"
29 | },
30 | "license": "Apache-2.0",
31 | "licenses": [
32 | {
33 | "type": "Apache-2.0",
34 | "url": "http://www.apache.org/licenses/LICENSE-2.0"
35 | }
36 | ],
37 | "keywords": [
38 | "ziti",
39 | "nodejs"
40 | ],
41 | "engines": {
42 | "node": ">=11.0.0"
43 | },
44 | "author": {
45 | "name": "OpenZiti",
46 | "url": "http://openziti.io"
47 | },
48 | "devDependencies": {
49 | "aws-sdk": "^2.1692.0",
50 | "docdash": "^1.2.0",
51 | "jsdoc": "^4.0.4",
52 | "jsdoc-to-markdown": "^7.1.1",
53 | "run-script-os": "^1.1.6"
54 | },
55 | "dependencies": {
56 | "@mapbox/node-pre-gyp": "^1.0.11",
57 | "bindings": "^1.5.0",
58 | "cmake-js": "^7.3.0"
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/scripts/build-appveyor.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | SETLOCAL
3 | SET EL=0
4 |
5 | ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | IF /I "%msvs_toolset%"=="" ECHO msvs_toolset unset, defaulting to 14 && SET msvs_toolset=14
8 | IF /I "%msvs_version%"=="" ECHO msvs_version unset, defaulting to 2019 && SET msvs_version=2019
9 |
10 | SET PATH=%CD%;%PATH%
11 | IF "%msvs_toolset%"=="12" SET msvs_version=2013
12 | IF NOT "%NODE_RUNTIME%"=="" SET "TOOLSET_ARGS=%TOOLSET_ARGS% --runtime=%NODE_RUNTIME%"
13 | IF NOT "%NODE_RUNTIME_VERSION%"=="" SET "TOOLSET_ARGS=%TOOLSET_ARGS% --target=%NODE_RUNTIME_VERSION%"
14 |
15 | ECHO APPVEYOR^: %APPVEYOR%
16 | ECHO nodejs_version^: %nodejs_version%
17 | ECHO platform^: %platform%
18 | ECHO msvs_toolset^: %msvs_toolset%
19 | ECHO msvs_version^: %msvs_version%
20 | ECHO TOOLSET_ARGS^: %TOOLSET_ARGS%
21 |
22 | ECHO activating VS command prompt
23 | :: NOTE this call makes the x64 -> X64
24 | IF /I "%platform%"=="x64" ECHO x64 && CALL "C:\Program Files (x86)\Microsoft Visual Studio\%msvs_version%\Community\VC\Auxiliary\Build\vcvarsall.bat" amd64
25 | IF /I "%platform%"=="x86" ECHO x86 && CALL "C:\Program Files (x86)\Microsoft Visual Studio\%msvs_version%\Community\VC\Auxiliary\Build\vcvarsall.bat" x86
26 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
27 |
28 | ECHO using compiler^: && CALL cl
29 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
30 |
31 | ECHO using MSBuild^: && CALL msbuild /version && ECHO.
32 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
33 |
34 | ECHO downloading/installing node
35 | powershell Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) $env:PLATFORM
36 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
37 |
38 | powershell Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
39 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
40 |
41 | ECHO available node.exe^:
42 | call where node
43 | ECHO available npm^:
44 | call where npm
45 |
46 | ECHO node^: && call node -v
47 | call node -e "console.log(' - arch:',process.arch,'\n - argv:',process.argv,'\n - execPath:',process.execPath)"
48 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
49 |
50 | ECHO npm^: && CALL npm -v
51 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
52 |
53 | ECHO ===== where npm puts stuff START ============
54 | ECHO npm root && CALL npm root
55 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
56 | ECHO npm root -g && CALL npm root -g
57 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
58 |
59 | ECHO npm bin && CALL npm bin
60 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
61 | ECHO npm bin -g && CALL npm bin -g
62 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
63 |
64 | SET NPM_BIN_DIR=
65 | FOR /F "tokens=*" %%i in ('CALL npm bin -g') DO SET NPM_BIN_DIR=%%i
66 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
67 | IF /I "%NPM_BIN_DIR%"=="%CD%" ECHO ERROR npm bin -g equals local directory && SET ERRORLEVEL=1 && GOTO ERROR
68 | ECHO ===== where npm puts stuff END ============
69 |
70 | IF "%nodejs_version:~0,1%"=="4" CALL npm install node-gyp@3.x
71 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
72 | IF "%nodejs_version:~0,1%"=="5" CALL npm install node-gyp@3.x
73 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
74 |
75 | ::Need to force update node-gyp to v6+ for electron v6 and v5
76 | ECHO ===== conditional node-gyp upgrade START ============
77 | :: Find the folder to install the node-gyp in
78 | SET npm_in_nodejs_dir="%ProgramFiles%\nodejs\node_modules\npm"
79 | ECHO npm_in_nodejs_dir^: %npm_in_nodejs_dir%
80 | IF /I "%platform%"=="x86" SET npm_in_nodejs_dir="%ProgramFiles(x86)%\nodejs\node_modules\npm"
81 | ECHO npm_in_nodejs_dir^: %npm_in_nodejs_dir%
82 | :: Set boolean whether the update has to happen
83 | SET "needs_patch="
84 | IF DEFINED NODE_RUNTIME_VERSION (
85 | ECHO NODE_RUNTIME_VERSION_REDUCED^: %NODE_RUNTIME_VERSION:~0,1%
86 | IF "%NODE_RUNTIME_VERSION:~0,1%"=="5" SET "needs_patch=y"
87 | IF "%NODE_RUNTIME_VERSION:~0,1%"=="6" SET "needs_patch=y"
88 | )
89 | :: Check if electron and install
90 | ECHO NODE_RUNTIME^: %NODE_RUNTIME%
91 | IF DEFINED needs_patch CALL npm install --prefix %npm_in_nodejs_dir% node-gyp@6.x
92 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
93 | ECHO ===== conditional node-gyp upgrade END ============
94 |
95 | :: install node-gyp v6.1
96 | ECHO ===== install node-gyp v6.1 ============
97 | CALL npm install -g node-gyp
98 | REM SET npm_config_node_gyp=C:\Users\appveyor\AppData\Roaming\npm\node-gyp
99 | SET npm_config_node_gyp=C:\Users\appveyor\AppData\Roaming\npm\node_modules\node-gyp\bin\node-gyp.js
100 | ECHO ===== install node-gyp v6.1 completed ============
101 |
102 | :: build Ziti C-SDK
103 | CALL git submodule update --init --recursive
104 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
105 | CALL cd deps
106 | CALL cd ziti-sdk-c
107 | CALL git submodule update --init --recursive
108 | ECHO ===== starting make sequence... ============
109 | CALL mkdir build
110 | CALL cd build
111 |
112 | ECHO ===== calling cmake -G Ninja ============
113 | CALL cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=OFF -G "NMake Makefiles" ..
114 |
115 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
116 | ECHO ===== calling cmake --build ============
117 | CALL nmake ziti
118 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
119 | CALL cd ..
120 | CALL cd ..
121 | CALL cd ..
122 |
123 | :: build Ziti NodeJS-SDK
124 | ECHO ===== calling npm install --build-from-source ============
125 | CALL npm install --build-from-source --cd=%CD% --msvs_version=%msvs_version% %TOOLSET_ARGS%
126 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
127 |
128 | :: test our module
129 | CALL node tests/hello.js
130 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
131 |
132 | FOR /F "tokens=*" %%i in ('"CALL node_modules\.bin\node-pre-gyp reveal module %TOOLSET_ARGS% --silent"') DO SET MODULE=%%i
133 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
134 | FOR /F "tokens=*" %%i in ('node -e "console.log(process.execPath)"') DO SET NODE_EXE=%%i
135 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
136 |
137 | dumpbin /DEPENDENTS "%NODE_EXE%"
138 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
139 | dumpbin /DEPENDENTS "%MODULE%"
140 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
141 |
142 |
143 | IF "%NODE_RUNTIME%"=="electron" GOTO CHECK_ELECTRON_TEST_ERRORLEVEL
144 |
145 | ::skipping check for errorlevel npm test result when using io.js
146 | ::@springmeyer: how to proceed?
147 | IF NOT "%nodejs_version%"=="1.8.1" IF NOT "%nodejs_version%"=="2.0.0" GOTO CHECK_NPM_TEST_ERRORLEVEL
148 |
149 | ECHO test our module
150 | CALL node tests/hello.js
151 | ECHO ==========================================
152 | ECHO ==========================================
153 | ECHO ==========================================
154 |
155 | GOTO NPM_TEST_FINISHED
156 |
157 |
158 | :CHECK_ELECTRON_TEST_ERRORLEVEL
159 | ECHO installing electron
160 | CALL npm install -g "electron@%NODE_RUNTIME_VERSION%"
161 | ECHO installing electron-mocha
162 | IF "%nodejs_version%" LEQ 6 CALL npm install -g "electron-mocha@7"
163 | IF "%nodejs_version%" GTR 6 CALL npm install -g "electron-mocha"
164 | ECHO preparing tests
165 | CALL electron "test/support/createdb-electron.js"
166 | DEL "test\support\createdb-electron.js"
167 | ECHO calling electron-mocha
168 | CALL electron-mocha -R spec --timeout 480000
169 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
170 | GOTO NPM_TEST_FINISHED
171 |
172 |
173 | :CHECK_NPM_TEST_ERRORLEVEL
174 | ECHO calling npm test
175 | CALL npm test
176 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
177 |
178 | :NPM_TEST_FINISHED
179 | ECHO packaging for node-gyp
180 | CALL node_modules\.bin\node-pre-gyp package %TOOLSET_ARGS%
181 | ::make commit message env var shorter
182 | SET CM=%APPVEYOR_REPO_COMMIT_MESSAGE%
183 | IF NOT "%CM%" == "%CM:[publish binary]=%" (ECHO publishing && CALL node_modules\.bin\node-pre-gyp --msvs_version=%msvs_version% publish %TOOLSET_ARGS%) ELSE (ECHO not publishing)
184 | IF %ERRORLEVEL% NEQ 0 GOTO ERROR
185 |
186 | GOTO DONE
187 |
188 |
189 |
190 | :ERROR
191 | ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192 | ECHO ERRORLEVEL^: %ERRORLEVEL%
193 | SET EL=%ERRORLEVEL%
194 |
195 | :DONE
196 | ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197 |
198 | EXIT /b %EL%
199 |
--------------------------------------------------------------------------------
/scripts/install_node.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | do_node_install() {
4 | # if an existing nvm is already installed we need to unload it
5 | nvm unload || true
6 |
7 | # here we set up the node version on the fly based on the matrix value.
8 | # This is done manually so that the build works the same on OS X
9 | rm -rf ./__nvm/ && git clone --depth 1 https://github.com/creationix/nvm.git ./__nvm
10 | source ./__nvm/nvm.sh
11 | nvm install ${NODE_VERSION}
12 | nvm use --delete-prefix ${NODE_VERSION}
13 | which node
14 | }
15 |
16 | do_win_node_install() {
17 | # # install NVS
18 | # choco install nvs
19 |
20 | # Install NVS.
21 | export NVS_HOME="$HOME/.nvs"
22 | git clone https://github.com/jasongin/nvs "$NVS_HOME"
23 | export NVS_EXECUTE=1
24 | . "$NVS_HOME/nvs.sh" install
25 |
26 | echo "DEBUG 1: check nvs version"
27 | nvs --version
28 | echo "DEBUG 1: done"
29 |
30 | echo "DEBUG 2: do nvs add"
31 | nvs add node/${NODE_VERSION}
32 | echo "DEBUG 2: done"
33 |
34 | echo "DEBUG 3: do nvs use"
35 | "$NVS_HOME/nvs.sh" use node/${NODE_VERSION}
36 | $PATH += ~/.nvs/node/${NODE_VERSION}/x64
37 | echo "DEBUG 3: done"
38 |
39 | echo "DEBUG 4: do nvs link"
40 | "$NVS_HOME/nvs.sh" link node/${NODE_VERSION}
41 | echo "DEBUG 4: done"
42 |
43 | echo "DEBUG 5: do node --version"
44 | node --version
45 | echo "DEBUG 5: done"
46 |
47 | echo "DEBUG 6: do npm --version"
48 | npm --version
49 | echo "DEBUG 6: done"
50 |
51 |
52 | # ls -l ${LOCALAPPDATA}/nvs
53 |
54 | # # Install the selected version of Node.js using NVS.
55 | # ${LOCALAPPDATA}/nvs/nvs.cmd add ${NODE_VERSION}
56 | # ${LOCALAPPDATA}/nvs/nvs.cmd use ${NODE_VERSION}
57 | # ${LOCALAPPDATA}/nvs/nvs.cmd link ${NODE_VERSION}
58 |
59 | # export PATH=${LOCALAPPDATA}/nvs/default/:$PATH
60 |
61 | # echo "after nvs, PATH is now: $PATH"
62 |
63 | # ls -l ${LOCALAPPDATA}/nvs/default/node_modules/npm/bin
64 |
65 | }
66 |
67 | if [[ ${1:-false} == 'false' ]]; then
68 | echo "Error: pass node version as first argument"
69 | exit 1
70 | fi
71 |
72 | NODE_VERSION=$1
73 |
74 | echo "OSTYPE is: $OSTYPE"
75 |
76 | if [[ "$OSTYPE" == "linux-gnu" ]]; then
77 | echo "OSTYPE is supported";
78 | do_node_install;
79 | elif [[ "$OSTYPE" == "darwin"* ]]; then
80 | echo "OSTYPE is supported";
81 | do_node_install;
82 | elif [[ "$OSTYPE" == "cygwin" ]]; then
83 | # POSIX compatibility layer and Linux environment emulation for Windows
84 | echo "OSTYPE is supported";
85 | do_win_node_install;
86 | elif [[ "$OSTYPE" == "msys" ]]; then
87 | # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
88 | echo "OSTYPE is supported";
89 | # do_win_node_install;
90 | do_node_install;
91 | elif [[ "$OSTYPE" == "win32" ]]; then
92 | # I'm not sure this can happen.
93 | echo "OSTYPE is unsupported";
94 | elif [[ "$OSTYPE" == "freebsd"* ]]; then
95 | echo "OSTYPE is supported";
96 | do_node_install;
97 | else
98 | echo "OSTYPE is unsupported";
99 | fi
100 |
--------------------------------------------------------------------------------
/scripts/validate_tag.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -u
4 |
5 | # let's catch the case where we tag but
6 | # forget to increment the package.json version
7 |
8 | # check if we are on a tag
9 | if [ `git describe --tags --always HEAD` ]; then
10 | echo 'looks like we are on a tag'
11 | if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]]; then
12 | echo 'git reports the same tag as travis'
13 | # now check to make sure package.json `version` matches
14 | MODULE_VERSION=$(node -e "console.log(require('./package.json').version)")
15 | if [[ $MODULE_VERSION != $TRAVIS_BRANCH ]] && [[ v$MODULE_VERSION != $TRAVIS_BRANCH ]]; then
16 | echo "package.json version ($MODULE_VERSION) does not match tag ($TRAVIS_BRANCH)"
17 | exit 1
18 | else
19 | echo "Validation success: package.json ($MODULE_VERSION) matches tag ($TRAVIS_BRANCH)"
20 | fi
21 | else
22 | echo "warning: travis thinks the tag ($TRAVIS_BRANCH) differs from git (`git describe --tags --always HEAD`)"
23 | fi
24 | fi
25 |
--------------------------------------------------------------------------------
/src/Ziti_https_request_data.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 |
21 | /**
22 | * This function is responsible for calling the JavaScript on_resp_data callback function
23 | * that was specified when the Ziti_https_request_data(...) was called from JavaScript.
24 | */
25 | static void CallJs_on_req_body(napi_env env, napi_value js_cb, void* context, void* data) {
26 |
27 | ZITI_NODEJS_LOG(DEBUG, "entered");
28 |
29 | // This parameter is not used.
30 | (void) context;
31 |
32 | // Retrieve the HttpsRespBodyItem created by the worker thread.
33 | HttpsReqBodyItem* item = (HttpsReqBodyItem*)data;
34 |
35 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
36 | // items are left over from earlier thread-safe calls from the worker thread.
37 | // When env is NULL, we simply skip over the call into Javascript
38 | if (env != NULL) {
39 |
40 | napi_value undefined;
41 |
42 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
43 | // value of the JavaScript function call.
44 | napi_get_undefined(env, &undefined);
45 |
46 | // const obj = {}
47 | napi_value js_http_item, js_req, js_status, js_body;
48 | int rc = napi_create_object(env, &js_http_item);
49 | if (rc != napi_ok) {
50 | napi_throw_error(env, "EINVAL", "failure to create object");
51 | }
52 |
53 | // obj.req = req
54 | napi_create_int64(env, (int64_t)item->req, &js_req);
55 | if (rc != napi_ok) {
56 | napi_throw_error(env, "EINVAL", "failure to create resp.req");
57 | }
58 | rc = napi_set_named_property(env, js_http_item, "req", js_req);
59 | if (rc != napi_ok) {
60 | napi_throw_error(env, "EINVAL", "failure to set named property req");
61 | }
62 | ZITI_NODEJS_LOG(DEBUG, "js_req: %p", item->req);
63 |
64 | // obj.code = status
65 | rc = napi_create_int32(env, item->status, &js_status);
66 | if (rc != napi_ok) {
67 | napi_throw_error(env, "EINVAL", "failure to create resp.status");
68 | }
69 | rc = napi_set_named_property(env, js_http_item, "status", js_status);
70 | if (rc != napi_ok) {
71 | napi_throw_error(env, "EINVAL", "failure to set named property status");
72 | }
73 | ZITI_NODEJS_LOG(DEBUG, "status: %zd", item->status);
74 |
75 | // obj.body = body
76 | rc = napi_create_int32(env, (int64_t)item->body, &js_body);
77 | if (rc != napi_ok) {
78 | napi_throw_error(env, "EINVAL", "failure to create resp.body");
79 | }
80 | rc = napi_set_named_property(env, js_http_item, "body", js_body);
81 | if (rc != napi_ok) {
82 | napi_throw_error(env, "EINVAL", "failure to set named property body");
83 | }
84 |
85 | // Call the JavaScript function and pass it the HttpsRespItem
86 | rc = napi_call_function(
87 | env,
88 | undefined,
89 | js_cb,
90 | 1,
91 | &js_http_item,
92 | NULL
93 | );
94 | if (rc != napi_ok) {
95 | napi_throw_error(env, "EINVAL", "failure to invoke JS callback");
96 | }
97 |
98 | }
99 | }
100 |
101 |
102 |
103 | /**
104 | *
105 | */
106 | void on_req_body(tlsuv_http_req_t *req, char *body, ssize_t status) {
107 |
108 | ZITI_NODEJS_LOG(DEBUG, "status: %zd, body: %p", status, body);
109 |
110 | HttpsAddonData* addon_data = (HttpsAddonData*) req->data;
111 | ZITI_NODEJS_LOG(DEBUG, "addon_data is: %p", addon_data);
112 |
113 | HttpsReqBodyItem* item = calloc(1, sizeof(*item));
114 | ZITI_NODEJS_LOG(DEBUG, "new HttpsReqBodyItem is: %p", item);
115 |
116 | // Grab everything off the tlsuv_http_resp_t that we need to eventually pass on to the JS on_resp_body callback.
117 | // If we wait until CallJs_on_resp_body is invoked to do that work, the tlsuv_http_resp_t may have already been free'd by the C-SDK
118 |
119 | item->req = req;
120 | item->body = (void*)body;
121 | item->status = status;
122 |
123 | ZITI_NODEJS_LOG(DEBUG, "calling tsfn_on_req_body: %p", addon_data->tsfn_on_req_body);
124 |
125 | // Initiate the call into the JavaScript callback.
126 | int rc = napi_call_threadsafe_function(
127 | addon_data->tsfn_on_req_body,
128 | item,
129 | napi_tsfn_blocking);
130 | if (rc != napi_ok) {
131 | napi_throw_error(addon_data->env, "EINVAL", "failure to invoke JS callback");
132 | }
133 | }
134 |
135 |
136 |
137 | /**
138 | * Send Body data over active HTTPS request
139 | *
140 | * @param {string} [0] req
141 | * @param {string} [1] data (we expect a Buffer)
142 | * @param {func} [2] JS on_write callback; This is invoked from 'on_req_body' function above
143 | *
144 | * @returns NULL
145 | */
146 | napi_value _Ziti_http_request_data(napi_env env, const napi_callback_info info) {
147 | napi_status status;
148 | int rc;
149 | size_t argc = 3;
150 | napi_value args[3];
151 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
152 | if (status != napi_ok) {
153 | napi_throw_error(env, NULL, "Failed to parse arguments");
154 | }
155 |
156 | if (argc < 3) {
157 | napi_throw_error(env, "EINVAL", "Too few arguments");
158 | return NULL;
159 | }
160 |
161 | // Obtain tlsuv_http_req_t
162 | int64_t js_req;
163 | status = napi_get_value_int64(env, args[0], &js_req);
164 | if (status != napi_ok) {
165 | napi_throw_error(env, NULL, "Failed to get Req");
166 | }
167 | // tlsuv_http_req_t *r = (tlsuv_http_req_t*)js_req;
168 | HttpsReq* httpsReq = (HttpsReq*)js_req;
169 | tlsuv_http_req_t *r = httpsReq->req;
170 |
171 | ZITI_NODEJS_LOG(DEBUG, "req: %p", r);
172 |
173 | HttpsAddonData* addon_data = httpsReq->addon_data;
174 | ZITI_NODEJS_LOG(DEBUG, "addon_data is: %p", addon_data);
175 |
176 | // If some kind of Ziti error previously occured on this request, then short-circuit now
177 | if (httpsReq->on_resp_has_fired && (httpsReq->respCode < 0)) {
178 | ZITI_NODEJS_LOG(DEBUG, "aborting due to previous error: %d", httpsReq->respCode);
179 | return NULL;
180 | }
181 |
182 | // Obtain data to write (we expect a Buffer)
183 | void* buffer;
184 | size_t bufferLength;
185 | status = napi_get_buffer_info(env, args[1], &buffer, &bufferLength);
186 | if (status != napi_ok) {
187 | napi_throw_error(env, NULL, "Failed to get Buffer info");
188 | }
189 | ZITI_NODEJS_LOG(DEBUG, "bufferLength: %zd", bufferLength);
190 |
191 | // Since the underlying Buffer's lifetime is not guaranteed if it's managed by the VM, we will copy the chunk into our heap
192 | void* chunk = calloc(1, bufferLength + 1);
193 | memcpy(chunk, buffer, bufferLength);
194 |
195 | // Obtain ptr to JS 'on_write' callback function
196 | napi_value js_write_cb = args[2];
197 | napi_value work_name;
198 |
199 | // Create a string to describe this asynchronous operation.
200 | status = napi_create_string_utf8(
201 | env,
202 | "N-API on_write",
203 | NAPI_AUTO_LENGTH,
204 | &work_name);
205 | if (status != napi_ok) {
206 | napi_throw_error(env, NULL, "Failed to napi_create_string_utf8");
207 | }
208 |
209 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
210 | // which we can call from a worker thread.
211 | rc = napi_create_threadsafe_function(
212 | env,
213 | js_write_cb,
214 | NULL,
215 | work_name,
216 | 0,
217 | 1,
218 | NULL,
219 | NULL,
220 | NULL,
221 | CallJs_on_req_body,
222 | &(addon_data->tsfn_on_req_body)
223 | );
224 | if (rc != napi_ok) {
225 | napi_throw_error(env, "EINVAL", "Failed to create threadsafe_function");
226 | }
227 | ZITI_NODEJS_LOG(DEBUG, "napi_create_threadsafe_function addon_data->tsfn_on_req_body() : %p", addon_data->tsfn_on_req_body);
228 |
229 | // Now, call the C-SDK to actually write the data over to the service
230 | tlsuv_http_req_data(r, chunk, bufferLength, on_req_body );
231 |
232 | return NULL;
233 | }
234 |
235 |
236 | void expose_ziti_https_request_data(napi_env env, napi_value exports) {
237 | napi_status status;
238 | napi_value fn;
239 |
240 | status = napi_create_function(env, NULL, 0, _Ziti_http_request_data, NULL, &fn);
241 | if (status != napi_ok) {
242 | napi_throw_error(env, NULL, "Unable to wrap native function '_Ziti_http_request_data");
243 | }
244 |
245 | status = napi_set_named_property(env, exports, "Ziti_http_request_data", fn);
246 | if (status != napi_ok) {
247 | napi_throw_error(env, NULL, "Unable to populate exports for 'Ziti_http_request_data");
248 | }
249 |
250 | }
251 |
--------------------------------------------------------------------------------
/src/Ziti_https_request_end.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 |
21 | /**
22 | * Indicate that an active HTTPS request is now complete
23 | *
24 | * @param {string} [0] req
25 | *
26 | * @returns NULL
27 | */
28 | napi_value _Ziti_http_request_end(napi_env env, const napi_callback_info info) {
29 | napi_status status;
30 | size_t argc = 1;
31 | napi_value args[1];
32 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
33 | if (status != napi_ok) {
34 | napi_throw_error(env, NULL, "Failed to parse arguments");
35 | }
36 |
37 | if (argc != 1) {
38 | napi_throw_error(env, "EINVAL", "Invalid argument count");
39 | return NULL;
40 | }
41 |
42 | // Obtain tlsuv_http_req_t
43 | int64_t js_req;
44 | status = napi_get_value_int64(env, args[0], &js_req);
45 | if (status != napi_ok) {
46 | napi_throw_error(env, NULL, "Failed to get Req");
47 | }
48 | HttpsReq* httpsReq = (HttpsReq*)js_req;
49 | tlsuv_http_req_t *r = httpsReq->req;
50 |
51 | ZITI_NODEJS_LOG(DEBUG, "req: %p", r);
52 |
53 | // TEMP hack to work around an issue still being debugged
54 | ZITI_NODEJS_LOG(DEBUG, "httpsReq->on_resp_has_fired: %o", httpsReq->on_resp_has_fired);
55 | if (httpsReq->on_resp_has_fired) {
56 | ZITI_NODEJS_LOG(DEBUG, "seems as though on_resp has previously fired... skipping call to tlsuv_http_req_end");
57 | } else {
58 | tlsuv_http_req_end(r);
59 | }
60 |
61 | return NULL;
62 | }
63 |
64 |
65 | void expose_ziti_https_request_end(napi_env env, napi_value exports) {
66 | napi_status status;
67 | napi_value fn;
68 |
69 | status = napi_create_function(env, NULL, 0, _Ziti_http_request_end, NULL, &fn);
70 | if (status != napi_ok) {
71 | napi_throw_error(env, NULL, "Unable to wrap native function '_Ziti_http_request_end");
72 | }
73 |
74 | status = napi_set_named_property(env, exports, "Ziti_http_request_end", fn);
75 | if (status != napi_ok) {
76 | napi_throw_error(env, NULL, "Unable to populate exports for 'Ziti_http_request_end");
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/build_config.h.in:
--------------------------------------------------------------------------------
1 | #define ZITI_NODEJS_VERSION @ZITI_VERSION@
2 | #define ZITI_NODEJS_COMMIT @ZITI_COMMIT@
3 | #define ZITI_NODEJS_BRANCH @ZITI_BRANCH@
4 | #define ZITI_OS @CMAKE_SYSTEM_NAME@
5 | #define ZITI_ARCH @CMAKE_SYSTEM_PROCESSOR@
6 | #define BUILD_DATE @BUILD_DATE@
--------------------------------------------------------------------------------
/src/utils.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include
18 | #include "utils.h"
19 | #include
20 | #include
21 |
22 |
23 | #if !defined(BUILD_DATE)
24 | #define BUILD_DATE unknown
25 | #endif
26 |
27 | #if !defined(ZITI_OS)
28 | #define ZITI_OS unknown
29 | #endif
30 |
31 | #if !defined(ZITI_ARCH)
32 | #define ZITI_ARCH unknown
33 | #endif
34 |
35 | #if !defined(ZITI_VERSION)
36 | #define ZITI_VERSION unknown
37 | #endif
38 |
39 | #if !defined(ZITI_BRANCH)
40 | #define ZITI_BRANCH no-branch
41 | #define ZITI_COMMIT sha
42 | #endif
43 |
44 | // #define to_str(x) str(x)
45 | #define str(x) #x
46 |
47 |
48 | const char* ziti_nodejs_get_version(int verbose) {
49 | if (verbose) {
50 | return "\n\tVersion:\t" to_str(ZITI_NODEJS_VERSION)
51 | "\n\tBuild Date:\t" to_str(BUILD_DATE)
52 | "\n\tGit Branch:\t" to_str(ZITI_NODEJS_BRANCH)
53 | "\n\tGit SHA:\t" to_str(ZITI_NODEJS_COMMIT)
54 | "\n\tOS: \t" to_str(ZITI_OS)
55 | "\n\tArch: \t" to_str(ZITI_ARCH)
56 | "\n\t";
57 |
58 | }
59 | return to_str(ZITI_VERSION);
60 | }
61 |
62 | const char* ziti_nodejs_git_branch() {
63 | return to_str(ZITI_BRANCH);
64 | }
65 |
66 | const char* ziti_nodejs_git_commit() {
67 | return to_str(ZITI_COMMIT);
68 | }
69 |
70 | int ziti_nodejs_debug_level = ZITI_LOG_DEFAULT_LEVEL;
71 | FILE *ziti_nodejs_debug_out;
72 |
73 | #if _WIN32
74 | LARGE_INTEGER frequency;
75 | LARGE_INTEGER start;
76 | LARGE_INTEGER end;
77 | #else
78 | struct timespec starttime;
79 | #endif
80 |
81 | void init_nodejs_debug() {
82 | char *level = getenv("ZITI_NODEJS_LOG");
83 | if (level != NULL) {
84 | ziti_nodejs_debug_level = (int) strtol(level, NULL, 10);
85 | }
86 | ziti_nodejs_debug_out = stderr;
87 |
88 | #if _WIN32
89 | QueryPerformanceFrequency(&frequency);
90 | QueryPerformanceCounter(&start);
91 | #else
92 | clock_gettime(CLOCK_MONOTONIC, &starttime);
93 | #endif
94 | }
95 |
96 | long get_nodejs_elapsed() {
97 | #if _WIN32
98 | QueryPerformanceCounter(&end);
99 | return end.QuadPart - start.QuadPart;
100 | #else
101 | struct timespec cur;
102 | clock_gettime(CLOCK_MONOTONIC, &cur);
103 | return (cur.tv_sec - starttime.tv_sec) * 1000 + ((cur.tv_nsec - starttime.tv_nsec) / ((long)1e6));
104 | #endif
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/src/utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef ZITI_TLS_UTILS_H
18 | #define ZITI_TLS_UTILS_H
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #ifdef __cplusplus
25 | extern "C" {
26 | #endif
27 |
28 | extern const char *ziti_nodejs_get_version(int verbose);
29 | extern const char *ziti_nodejs_git_branch();
30 | extern const char *ziti_nodejs_git_commit();
31 | extern void nodejs_hexDump(char *desc, void *addr, int len);
32 |
33 |
34 | typedef const char *(*fmt_error_t)(int);
35 | typedef int *(*cond_error_t)(int);
36 |
37 | #define __FILENAME_NODEJS__ (__FILENAME__)
38 |
39 |
40 | extern void init_nodejs_debug();
41 |
42 | extern int ziti_nodejs_debug_level;
43 | extern FILE *ziti_nodejs_debug_out;
44 |
45 |
46 | /// for windows compilation NOGDI needs to be set:
47 | // #define DEBUG_LEVELS(XX) \
48 | // XX(NONE) \
49 | // XX(ERROR) /*WINDOWS - see comment above wrt NOGDI*/ \
50 | // XX(WARN) \
51 | // XX(INFO) \
52 | // XX(DEBUG) \
53 | // XX(VERBOSE) \
54 | // XX(TRACE)
55 |
56 |
57 | // enum DebugLevel {
58 | // #define _level(n) n,
59 | // DEBUG_LEVELS(_level)
60 | // #undef _level
61 | // };
62 |
63 | // #define container_of(ptr, type, member) ((type *) ((ptr) - offsetof(type, member)))
64 |
65 | // TEMP: skip logging on windows
66 | #ifdef WIN32
67 | #define ZITI_NODEJS_LOG(...)
68 | #else
69 | #define ZITI_NODEJS_LOG(level, fmt, ...) do { \
70 | if (level <= ziti_nodejs_debug_level) {\
71 | long elapsed = get_nodejs_elapsed();\
72 | fprintf(ziti_nodejs_debug_out, "[%9ld.%03ld] " #level "\tziti-sdk-nodejs/%s:%d %s(): " fmt "\n",\
73 | (long int)(elapsed/1000), (long int)(elapsed%1000), __FILENAME_NODEJS__, __LINE__, __func__, ##__VA_ARGS__);\
74 | }\
75 | } while(0)
76 | #endif
77 |
78 | long get_nodejs_elapsed();
79 |
80 |
81 | #ifdef __cplusplus
82 | }
83 | #endif
84 |
85 | #endif //ZITI_TLS_UTILS_H
86 |
--------------------------------------------------------------------------------
/src/ziti-add-on.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 |
19 | extern void set_signal_handler();
20 |
21 | uv_loop_t *thread_loop;
22 |
23 | napi_value Init(napi_env env, napi_value exports) {
24 |
25 | if (uv_mutex_init(&client_pool_lock))
26 | abort();
27 |
28 | // Install call-stack tracer
29 | // set_signal_handler();
30 |
31 | // TEMP: skip logging on windows
32 | #ifndef WIN32
33 |
34 | init_nodejs_debug();
35 |
36 | # ifdef NODE_MAJOR_VERSION
37 | # if NODE_MAJOR_VERSION == 11
38 | uv_timeval_t start_time;
39 | # else
40 | uv_timeval64_t start_time;
41 | # endif
42 | # endif
43 |
44 | uv_gettimeofday(&start_time);
45 |
46 | struct tm *start_tm = gmtime((const time_t*)&start_time.tv_sec);
47 | char time_str[32];
48 | strftime(time_str, sizeof(time_str), "%FT%T", start_tm);
49 |
50 | # ifdef NODE_MAJOR_VERSION
51 | # if NODE_MAJOR_VERSION == 11
52 | ZITI_NODEJS_LOG(INFO, "Ziti NodeJS SDK version %s@%s(%s) starting at (%s.%03ld)",
53 | ziti_nodejs_get_version(true), ziti_nodejs_git_commit(), ziti_nodejs_git_branch(),
54 | time_str,
55 | start_time.tv_usec/1000);
56 | # else
57 | ZITI_NODEJS_LOG(INFO, "Ziti NodeJS SDK version %s@%s(%s) starting at (%s.%03d)",
58 | ziti_nodejs_get_version(true), ziti_nodejs_git_commit(), ziti_nodejs_git_branch(),
59 | time_str,
60 | start_time.tv_usec/1000);
61 | # endif
62 | # endif
63 |
64 | #endif
65 |
66 | napi_status status = napi_get_uv_event_loop(env, &thread_loop);
67 | if (status != napi_ok) {
68 | ZITI_NODEJS_LOG(ERROR, "napi_get_uv_event_loop failed, status: %d", status);
69 | abort();
70 | }
71 |
72 | // Expose some Ziti SDK functions to JavaScript
73 | expose_ziti_close(env, exports);
74 | expose_ziti_dial(env, exports);
75 | expose_ziti_enroll(env, exports);
76 | expose_ziti_sdk_version(env, exports);
77 | expose_ziti_init(env, exports);
78 | expose_ziti_listen(env, exports);
79 | expose_ziti_service_available(env, exports);
80 | expose_ziti_services_refresh(env, exports);
81 | expose_ziti_shutdown(env, exports);
82 | expose_ziti_write(env, exports);
83 |
84 | expose_ziti_https_request(env, exports);
85 | expose_ziti_https_request_data(env, exports);
86 | expose_ziti_https_request_end(env, exports);
87 |
88 | expose_ziti_websocket_connect(env, exports);
89 | expose_ziti_websocket_write(env, exports);
90 |
91 | expose_ziti_set_log_level(env, exports);
92 |
93 | return exports;
94 | }
95 |
96 | NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
--------------------------------------------------------------------------------
/src/ziti-nodejs.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef ZITI_ADD_ON_H
18 | #define ZITI_ADD_ON_H
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include
29 | #define NAPI_EXPERIMENTAL
30 | #include
31 |
32 | #include
33 | #include
34 | #include "utils.h"
35 |
36 |
37 | #define NEWP(var, type) type *var = calloc(1, sizeof(type))
38 |
39 |
40 | #ifdef _WIN32
41 | #define _NO_CRT_STDIO_INLINE 1
42 | /* Windows - set up dll import/export decorators. */
43 | # if defined(BUILDING_UV_SHARED)
44 | /* Building shared library. */
45 | # define UV_EXTERN __declspec(dllexport)
46 | # elif defined(USING_UV_SHARED)
47 | /* Using shared library. */
48 | # define UV_EXTERN __declspec(dllimport)
49 | # else
50 | /* Building static library. */
51 | # define UV_EXTERN /* nothing */
52 | # endif
53 |
54 |
55 | #define strcasecmp _stricmp
56 | #define strncasecmp _strnicmp
57 |
58 | #if !defined (strndup_DEFINED)
59 | #define strndup_DEFINED
60 | static char* strndup(char* p, size_t len) {
61 | char *s = malloc(len + 1);
62 | strncpy(s, p, len);
63 | s[len] = '\0';
64 | return s;
65 | }
66 | #endif // strndup_DEFINED
67 |
68 |
69 | #elif __GNUC__ >= 4
70 | # define UV_EXTERN __attribute__((visibility("default")))
71 | #else
72 | # define UV_EXTERN /* nothing */
73 | #endif
74 |
75 | # ifdef NODE_MAJOR_VERSION
76 | # if NODE_MAJOR_VERSION == 11
77 | UV_EXTERN int uv_gettimeofday(uv_timeval_t* tv);
78 | # else
79 | UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
80 | # endif
81 | # endif
82 |
83 |
84 | /**
85 | *
86 | */
87 | typedef struct {
88 | napi_async_work work;
89 | napi_threadsafe_function tsfn_on_enroll;
90 | } EnrollAddonData;
91 |
92 |
93 | /**
94 | *
95 | */
96 | typedef struct {
97 | bool isWebsocket;
98 | napi_async_work work;
99 | napi_threadsafe_function tsfn_on_connect;
100 | napi_threadsafe_function tsfn_on_data;
101 | napi_threadsafe_function tsfn_on_write;
102 | napi_threadsafe_function tsfn_on_service_available;
103 | } ConnAddonData;
104 |
105 | /**
106 | *
107 | */
108 | typedef struct {
109 | char *service_name;
110 | int64_t js_arb_data;
111 | ziti_connection server;
112 | napi_async_work work;
113 | napi_threadsafe_function tsfn_on_listen;
114 | napi_threadsafe_function tsfn_on_listen_client;
115 | napi_threadsafe_function tsfn_on_listen_client_connect;
116 | napi_threadsafe_function tsfn_on_listen_client_data;
117 | } ListenAddonData;
118 |
119 | /**
120 | *
121 | */
122 | typedef struct {
123 | napi_async_work work;
124 | napi_threadsafe_function tsfn_on_connect;
125 | napi_threadsafe_function tsfn_on_data;
126 | napi_threadsafe_function tsfn_on_write;
127 | tlsuv_src_t ziti_src;
128 | tlsuv_websocket_t ws;
129 | uv_connect_t req;
130 | uint32_t headers_array_length;
131 | char* header_name[100];
132 | char* header_value[100];
133 | char* service;
134 | } WSAddonData;
135 |
136 |
137 | // An item that will be passed into the JavaScript on_resp callback
138 | typedef struct HttpsRespItem {
139 | tlsuv_http_req_t *req;
140 | int code;
141 | char* status;
142 | tlsuv_http_hdr *headers;
143 | } HttpsRespItem;
144 |
145 | // An item that will be passed into the JavaScript on_resp_body callback
146 | typedef struct HttpsRespBodyItem {
147 | tlsuv_http_req_t *req;
148 | const void *body;
149 | ssize_t len;
150 | } HttpsRespBodyItem;
151 |
152 | // An item that will be passed into the JavaScript on_req_body callback
153 | typedef struct HttpsReqBodyItem {
154 | tlsuv_http_req_t *req;
155 | const void *body;
156 | ssize_t status;
157 | } HttpsReqBodyItem;
158 |
159 |
160 | typedef struct HttpsAddonData HttpsAddonData;
161 |
162 | typedef struct HttpsReq {
163 | tlsuv_http_req_t *req;
164 | bool on_resp_has_fired;
165 | int respCode;
166 | HttpsAddonData *addon_data;
167 | } HttpsReq;
168 |
169 | typedef struct {
170 | char* scheme_host_port;
171 | tlsuv_http_t client;
172 | tlsuv_src_t ziti_src;
173 | bool active;
174 | bool purge;
175 | } HttpsClient;
176 |
177 | struct HttpsAddonData {
178 | napi_env env;
179 | tlsuv_http_t client;
180 | tlsuv_http_req_t ziti_src;
181 | napi_threadsafe_function tsfn_on_req;
182 | napi_threadsafe_function tsfn_on_resp;
183 | napi_threadsafe_function tsfn_on_resp_body;
184 | napi_threadsafe_function tsfn_on_req_body;
185 | HttpsRespItem* item;
186 | HttpsReq* httpsReq;
187 | uv_work_t uv_req;
188 | bool haveURL;
189 | char* service;
190 | char* scheme_host_port;
191 | char* method;
192 | char* path;
193 | uint32_t headers_array_length;
194 | char* header_name[100];
195 | char* header_value[100];
196 | HttpsClient* httpsClient;
197 | } ;
198 |
199 |
200 | #ifdef __cplusplus
201 | extern "C" {
202 | #endif
203 |
204 | extern ziti_context ztx;
205 | extern uv_loop_t *thread_loop;
206 |
207 | extern uv_mutex_t client_pool_lock;
208 |
209 | // extern void set_signal_handler();
210 |
211 | extern void expose_ziti_close(napi_env env, napi_value exports);
212 | extern void expose_ziti_dial(napi_env env, napi_value exports);
213 | extern void expose_ziti_enroll(napi_env env, napi_value exports);
214 | extern void expose_ziti_sdk_version(napi_env env, napi_value exports);
215 | extern void expose_ziti_init(napi_env env, napi_value exports);
216 | extern void expose_ziti_listen(napi_env env, napi_value exports);
217 | extern void expose_ziti_service_available(napi_env env, napi_value exports);
218 | extern void expose_ziti_services_refresh(napi_env env, napi_value exports);
219 | extern void expose_ziti_set_log_level(napi_env env, napi_value exports);
220 | extern void expose_ziti_shutdown(napi_env env, napi_value exports);
221 | extern void expose_ziti_write(napi_env env, napi_value exports);
222 | extern void expose_ziti_https_request(napi_env env, napi_value exports);
223 | extern void expose_ziti_https_request_data(napi_env env, napi_value exports);
224 | extern void expose_ziti_https_request_end(napi_env env, napi_value exports);
225 | extern void expose_ziti_websocket_connect(napi_env env, napi_value exports);
226 | extern void expose_ziti_websocket_write(napi_env env, napi_value exports);
227 |
228 | //
229 | extern int tlsuv_websocket_init_with_src (uv_loop_t *loop, tlsuv_websocket_t *ws, tlsuv_src_t *src);
230 |
231 | extern void track_service_to_hostname(const char* service_name, char* hostname, int port);
232 |
233 | #ifdef __cplusplus
234 | }
235 | #endif
236 |
237 | #endif /* ZITI_ADD_ON_H */
--------------------------------------------------------------------------------
/src/ziti_close.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 |
21 | /**
22 | *
23 | */
24 | napi_value _ziti_close(napi_env env, const napi_callback_info info) {
25 | napi_status status;
26 | size_t argc = 1;
27 | napi_value args[1];
28 | napi_value jsRetval;
29 |
30 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
31 | if (status != napi_ok) {
32 | napi_throw_error(env, NULL, "Failed to parse arguments");
33 | }
34 |
35 | if (argc < 1) {
36 | napi_throw_error(env, "EINVAL", "Too few arguments");
37 | return NULL;
38 | }
39 |
40 | // Obtain ziti_connection
41 | int64_t js_conn;
42 | status = napi_get_value_int64(env, args[0], &js_conn);
43 | if (status != napi_ok) {
44 | napi_throw_error(env, NULL, "Failed to get Conn");
45 | }
46 | ziti_connection conn = (ziti_connection)js_conn;
47 |
48 | // Now, call the C-SDK to close the connection
49 | ZITI_NODEJS_LOG(DEBUG, "calling ziti_close for conn=%p", conn);
50 | ziti_close(conn, NULL);
51 |
52 | status = napi_create_int32(env, 0, &jsRetval);
53 | if (status != napi_ok) {
54 | napi_throw_error(env, NULL, "Unable to create return value");
55 | }
56 |
57 | return jsRetval;
58 | }
59 |
60 |
61 | /**
62 | *
63 | */
64 | void expose_ziti_close(napi_env env, napi_value exports) {
65 | napi_status status;
66 | napi_value fn;
67 |
68 | status = napi_create_function(env, NULL, 0, _ziti_close, NULL, &fn);
69 | if (status != napi_ok) {
70 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_close");
71 | }
72 |
73 | status = napi_set_named_property(env, exports, "ziti_close", fn);
74 | if (status != napi_ok) {
75 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_close");
76 | }
77 |
78 | }
79 |
80 |
--------------------------------------------------------------------------------
/src/ziti_dial.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 | // An item that will be generated here and passed into the JavaScript on_data callback
21 | typedef struct OnDataItem {
22 |
23 | const unsigned char *buf;
24 | int len;
25 |
26 | } OnDataItem;
27 |
28 | /**
29 | * This function is responsible for calling the JavaScript 'connect' callback function
30 | * that was specified when the ziti_dial(...) was called from JavaScript.
31 | */
32 | static void CallJs_on_connect(napi_env env, napi_value js_cb, void* context, void* data) {
33 | napi_status status;
34 |
35 | // This parameter is not used.
36 | (void) context;
37 |
38 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
39 | // items are left over from earlier thread-safe calls from the worker thread.
40 | // When env is NULL, we simply skip over the call into Javascript
41 | if (env != NULL) {
42 | napi_value undefined, js_conn;
43 |
44 | ZITI_NODEJS_LOG(INFO, "data: %p", data);
45 |
46 | // Convert the ziti_connection to a napi_value.
47 | if (NULL != data) {
48 | // Retrieve the ziti_connection from the item created by the worker thread.
49 | ziti_connection conn = *(ziti_connection*)data;
50 | status = napi_create_int64(env, (int64_t)conn, &js_conn);
51 | if (status != napi_ok) {
52 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
53 | }
54 | } else {
55 | status = napi_get_undefined(env, &js_conn) == napi_ok;
56 | if (status != napi_ok) {
57 | napi_throw_error(env, NULL, "Unable to napi_get_undefined (1)");
58 | }
59 | }
60 |
61 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
62 | // value of the JavaScript function call.
63 | status = napi_get_undefined(env, &undefined);
64 | if (status != napi_ok) {
65 | napi_throw_error(env, NULL, "Unable to napi_get_undefined (2)");
66 | }
67 |
68 | ZITI_NODEJS_LOG(INFO, "calling JS callback...");
69 |
70 | // Call the JavaScript function and pass it the ziti_connection
71 | status = napi_call_function(
72 | env,
73 | undefined,
74 | js_cb,
75 | 1,
76 | &js_conn,
77 | NULL
78 | );
79 | ZITI_NODEJS_LOG(INFO, "returned from JS callback...");
80 | if (status != napi_ok) {
81 | napi_throw_error(env, NULL, "Unable to napi_call_function");
82 | }
83 | }
84 | }
85 |
86 |
87 | /**
88 | * This function is responsible for calling the JavaScript 'data' callback function
89 | * that was specified when the ziti_dial(...) was called from JavaScript.
90 | */
91 | static void CallJs_on_data(napi_env env, napi_value js_cb, void* context, void* data) {
92 | napi_status status;
93 |
94 | // This parameter is not used.
95 | (void) context;
96 |
97 | // Retrieve the OnDataItem created by the worker thread.
98 | OnDataItem* item = (OnDataItem*)data;
99 |
100 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
101 | // items are left over from earlier thread-safe calls from the worker thread.
102 | // When env is NULL, we simply skip over the call into Javascript and free the
103 | // items.
104 | if (env != NULL) {
105 | napi_value undefined, js_buffer;
106 | void* result_data;
107 |
108 | // Convert the buffer to a napi_value.
109 | status = napi_create_buffer_copy(env,
110 | item->len,
111 | (const void*)item->buf,
112 | (void**)&result_data,
113 | &js_buffer);
114 | if (status != napi_ok) {
115 | napi_throw_error(env, NULL, "Unable to napi_create_buffer_copy");
116 | }
117 |
118 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
119 | // value of the JavaScript function call.
120 | status = napi_get_undefined(env, &undefined);
121 | if (status != napi_ok) {
122 | napi_throw_error(env, NULL, "Unable to napi_get_undefined (3)");
123 | }
124 |
125 | // Call the JavaScript function and pass it the data
126 | status = napi_call_function(
127 | env,
128 | undefined,
129 | js_cb,
130 | 1,
131 | &js_buffer,
132 | NULL
133 | );
134 | if (status != napi_ok) {
135 | napi_throw_error(env, NULL, "Unable to napi_call_function");
136 | }
137 | }
138 | }
139 |
140 |
141 |
142 | /**
143 | * This function is the callback invoked by the C-SDK when data arrives on the connection.
144 | */
145 | long on_data(struct ziti_conn *conn, const unsigned char *buf, long len) {
146 | napi_status status;
147 |
148 | ConnAddonData* addon_data = (ConnAddonData*) ziti_conn_data(conn);
149 |
150 | ZITI_NODEJS_LOG(INFO, "len: %zd, conn: %p", len, conn);
151 |
152 | if (len == ZITI_EOF) {
153 | if (addon_data->isWebsocket) {
154 | ZITI_NODEJS_LOG(DEBUG, "skipping ziti_close on ZITI_EOF due to isWebsocket=true");
155 | return 0;
156 | } else {
157 | ziti_close(conn, NULL);
158 | return 0;
159 | }
160 | }
161 | else if (len < 0) {
162 | ziti_close(conn, NULL);
163 | return 0;
164 | }
165 | else {
166 |
167 | OnDataItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
168 | item->buf = buf;
169 | item->buf = calloc(1, len);
170 | memcpy((void*)item->buf, buf, len);
171 | item->len = len;
172 |
173 | // if (addon_data->isWebsocket) {
174 | // hexDump("on_data", item->buf, item->len);
175 | // }
176 |
177 | // Initiate the call into the JavaScript callback.
178 | // The call into JavaScript will not have happened
179 | // when this function returns, but it will be queued.
180 | status = napi_call_threadsafe_function(
181 | addon_data->tsfn_on_data,
182 | item, // Send the data we received from the service on over to the JS callback
183 | napi_tsfn_blocking);
184 | if (status != napi_ok) {
185 | ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
186 | }
187 |
188 | return len;
189 | }
190 | }
191 |
192 |
193 | /**
194 | *
195 | */
196 | void on_connect(ziti_connection conn, int status) {
197 | napi_status nstatus;
198 |
199 |
200 | ConnAddonData* addon_data = (ConnAddonData*) ziti_conn_data(conn);
201 | ziti_connection* the_conn = NULL;
202 |
203 | ZITI_NODEJS_LOG(DEBUG, "conn: %p, status: %o, isWebsocket: %o", conn, status, addon_data->isWebsocket);
204 |
205 | if (status == ZITI_OK) {
206 |
207 | // Save the 'ziti_connection' to the heap. The JavaScript marshaller (CallJs)
208 | // will free this item after having sent it to JavaScript.
209 | the_conn = malloc(sizeof(ziti_connection));
210 | *the_conn = conn;
211 | }
212 |
213 | ZITI_NODEJS_LOG(DEBUG, "the_conn: %p", the_conn);
214 |
215 | // Initiate the call into the JavaScript callback.
216 | // The call into JavaScript will not have happened
217 | // when this function returns, but it will be queued.
218 | nstatus = napi_call_threadsafe_function(
219 | addon_data->tsfn_on_connect,
220 | the_conn, // Send the ziti_connection over to the JS callback
221 | napi_tsfn_blocking);
222 | if (nstatus != napi_ok) {
223 | ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
224 | }
225 | }
226 |
227 |
228 | /**
229 | *
230 | */
231 | napi_value _ziti_dial(napi_env env, const napi_callback_info info) {
232 |
233 | napi_status status;
234 | size_t argc = 4;
235 | napi_value args[4];
236 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
237 | if (status != napi_ok) {
238 | napi_throw_error(env, NULL, "Failed to parse arguments");
239 | }
240 |
241 | if (argc < 4) {
242 | napi_throw_error(env, "EINVAL", "Too few arguments");
243 | return NULL;
244 | }
245 |
246 | // Obtain service name
247 | size_t result;
248 | char ServiceName[256]; //TODO: make this smarter
249 | status = napi_get_value_string_utf8(env, args[0], ServiceName, 256, &result);
250 | if (status != napi_ok) {
251 | napi_throw_error(env, NULL, "Failed to get Service Name");
252 | }
253 | ZITI_NODEJS_LOG(DEBUG, "ServiceName: %s", ServiceName);
254 |
255 | // Obtain isWebsocket flag
256 | bool isWebsocket = false;
257 | status = napi_get_value_bool(env, args[1], &isWebsocket);
258 | if (status != napi_ok) {
259 | napi_throw_error(env, NULL, "Failed to get isWebsocket flag");
260 | }
261 | ZITI_NODEJS_LOG(DEBUG, "isWebsocket is: %o", isWebsocket);
262 |
263 | // Obtain ptr to JS 'connect' callback function
264 | napi_value js_connect_cb = args[2];
265 | napi_value work_name_connect;
266 |
267 | ConnAddonData* addon_data = memset(malloc(sizeof(*addon_data)), 0, sizeof(*addon_data));
268 |
269 | addon_data->isWebsocket = isWebsocket;
270 |
271 | // Create a string to describe this asynchronous operation.
272 | status = napi_create_string_utf8(
273 | env,
274 | "N-API on_connect",
275 | NAPI_AUTO_LENGTH,
276 | &work_name_connect);
277 | if (status != napi_ok) {
278 | napi_throw_error(env, NULL, "Unable to napi_create_string_utf8");
279 | }
280 |
281 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
282 | // which we can call from a worker thread.
283 | status = napi_create_threadsafe_function(
284 | env,
285 | js_connect_cb,
286 | NULL,
287 | work_name_connect,
288 | 0,
289 | 1,
290 | NULL,
291 | NULL,
292 | NULL,
293 | CallJs_on_connect,
294 | &(addon_data->tsfn_on_connect));
295 | if (status != napi_ok) {
296 | napi_throw_error(env, NULL, "Unable to napi_create_threadsafe_function");
297 | }
298 |
299 | // Obtain ptr to JS 'data' callback function
300 | napi_value js_data_cb = args[3];
301 | napi_value work_name_data;
302 |
303 | // Create a string to describe this asynchronous operation.
304 | status = napi_create_string_utf8(
305 | env,
306 | "N-API on_data",
307 | NAPI_AUTO_LENGTH,
308 | &work_name_data);
309 | if (status != napi_ok) {
310 | napi_throw_error(env, NULL, "Unable to napi_create_string_utf8");
311 | }
312 |
313 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
314 | // which we can call from a worker thread.
315 | status = napi_create_threadsafe_function(
316 | env,
317 | js_data_cb,
318 | NULL,
319 | work_name_data,
320 | 0,
321 | 1,
322 | NULL,
323 | NULL,
324 | NULL,
325 | CallJs_on_data,
326 | &(addon_data->tsfn_on_data));
327 | if (status != napi_ok) {
328 | napi_throw_error(env, NULL, "Unable to napi_create_threadsafe_function");
329 | }
330 |
331 | // Init a Ziti connection object, and attach our add-on data to it so we can
332 | // pass context around between our callbacks, as propagate it all the way out
333 | // to the JavaScript callbacks
334 | ziti_connection conn;
335 | int rc = ziti_conn_init(ztx, &conn, addon_data);
336 | if (rc != ZITI_OK) {
337 | napi_throw_error(env, NULL, "failure in 'ziti_conn_init");
338 | }
339 |
340 |
341 | // Connect to the service
342 | ZITI_NODEJS_LOG(DEBUG, "calling ziti_dial: %p", ztx);
343 | rc = ziti_dial(conn, ServiceName, on_connect, on_data);
344 | if (rc != ZITI_OK) {
345 | napi_throw_error(env, NULL, "failure in 'ziti_dial");
346 | }
347 | ZITI_NODEJS_LOG(DEBUG, "returned from ziti_dial: %p", ztx);
348 |
349 | return NULL;
350 | }
351 |
352 |
353 |
354 | /**
355 | *
356 | */
357 | void expose_ziti_dial(napi_env env, napi_value exports) {
358 | napi_status status;
359 | napi_value fn;
360 |
361 | status = napi_create_function(env, NULL, 0, _ziti_dial, NULL, &fn);
362 | if (status != napi_ok) {
363 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_dial");
364 | }
365 |
366 | status = napi_set_named_property(env, exports, "ziti_dial", fn);
367 | if (status != napi_ok) {
368 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_dial");
369 | }
370 |
371 | }
372 |
373 |
--------------------------------------------------------------------------------
/src/ziti_enroll.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 |
19 |
20 | // An item that will be generated here and passed into the JavaScript enroll callback
21 | typedef struct EnrollItem {
22 |
23 | unsigned char *json_salvo;
24 | int status;
25 | char *err;
26 |
27 | } EnrollItem;
28 |
29 |
30 | /**
31 | * This function is responsible for calling the JavaScript callback function
32 | * that was specified when the ziti_enroll(...) was called from JavaScript.
33 | */
34 | static void CallJs_on_enroll(napi_env env, napi_value js_cb, void* context, void* data) {
35 |
36 | napi_status status;
37 |
38 | ZITI_NODEJS_LOG(DEBUG, "entered");
39 |
40 | // This parameter is not used.
41 | (void) context;
42 |
43 | // Retrieve the EnrollItem created by the worker thread.
44 | EnrollItem* item = (EnrollItem*)data;
45 |
46 | ZITI_NODEJS_LOG(DEBUG, "item->json_salvo: %s", item->json_salvo);
47 | ZITI_NODEJS_LOG(DEBUG, "item->status: %d", item->status);
48 | ZITI_NODEJS_LOG(DEBUG, "item->err: %s", item->err);
49 |
50 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
51 | // items are left over from earlier thread-safe calls from the worker thread.
52 | // When env is NULL, we simply skip over the call into Javascript
53 | if (env != NULL) {
54 |
55 | napi_value undefined;
56 |
57 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
58 | // value of the JavaScript function call.
59 | assert(napi_get_undefined(env, &undefined) == napi_ok);
60 |
61 | // const obj = {}
62 | napi_value js_enroll_item, js_json_salvo, js_status, js_err;
63 | status = napi_create_object(env, &js_enroll_item);
64 | if (status != napi_ok) {
65 | napi_throw_error(env, NULL, "Unable to napi_create_object");
66 | }
67 |
68 | // obj.identity = identity
69 | if (NULL != item->json_salvo) {
70 | napi_create_string_utf8(env, (const char*)item->json_salvo, NAPI_AUTO_LENGTH, &js_json_salvo);
71 | napi_set_named_property(env, js_enroll_item, "identity", js_json_salvo);
72 | }
73 |
74 | // obj.status = status
75 | napi_create_int64(env, (int64_t)item->status, &js_status);
76 | napi_set_named_property(env, js_enroll_item, "status", js_status);
77 |
78 | // obj.err = err
79 | if (NULL != item->err) {
80 | napi_create_string_utf8(env, (const char*)item->err, NAPI_AUTO_LENGTH, &js_err);
81 | napi_set_named_property(env, js_enroll_item, "err", js_err);
82 | }
83 |
84 |
85 | // Call the JavaScript function and pass it the EnrollItem
86 | napi_value global;
87 | status = napi_get_global(env, &global);
88 |
89 | status = napi_call_function(
90 | env,
91 | global,
92 | js_cb,
93 | 1,
94 | &js_enroll_item,
95 | NULL
96 | );
97 |
98 | if (status != napi_ok) {
99 | napi_throw_error(env, "EINVAL", "failure to invoke JS callback");
100 | }
101 |
102 | }
103 | }
104 |
105 |
106 | /**
107 | *
108 | */
109 | void on_ziti_enroll(const ziti_config *cfg, int status, const char *err, void *ctx) {
110 | napi_status nstatus;
111 |
112 | ZITI_NODEJS_LOG(DEBUG, "\nstatus: %d, \nerr: %s,\nctx: %p", status, err, ctx);
113 |
114 | EnrollAddonData* addon_data = (EnrollAddonData*)ctx;
115 |
116 | EnrollItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
117 |
118 | item->status = status;
119 |
120 | if (NULL != err) {
121 | item->err = calloc(1, strlen(err) + 1);
122 | strcpy(item->err, err);
123 | } else {
124 | item->err = NULL;
125 | }
126 |
127 | if (status == ZITI_OK) {
128 | size_t len;
129 | char *output_buf = ziti_config_to_json(cfg, 0, &len);
130 | item->json_salvo = calloc(1, len + 1);
131 | strcpy(item->json_salvo, output_buf);
132 | }
133 |
134 | // Initiate the call into the JavaScript callback.
135 | // The call into JavaScript will not have happened
136 | // when this function returns, but it will be queued.
137 | nstatus = napi_call_threadsafe_function(
138 | addon_data->tsfn_on_enroll,
139 | item,
140 | napi_tsfn_blocking);
141 | if (nstatus != napi_ok) {
142 | ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
143 | }
144 |
145 | }
146 |
147 |
148 |
149 |
150 | /**
151 | *
152 | */
153 | napi_value _ziti_enroll(napi_env env, const napi_callback_info info) {
154 | napi_status status;
155 | napi_value jsRetval;
156 | napi_valuetype js_cb_type;
157 |
158 | ziti_log_init(thread_loop, ZITI_LOG_DEFAULT_LEVEL, NULL);
159 |
160 | ZITI_NODEJS_LOG(DEBUG, "entered");
161 |
162 | size_t argc = 2;
163 | napi_value args[2];
164 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
165 | if (status != napi_ok) {
166 | napi_throw_error(env, NULL, "Failed to parse arguments");
167 | }
168 |
169 | if (argc < 2) {
170 | ZITI_NODEJS_LOG(DEBUG, "Too few arguments");
171 | napi_throw_error(env, "EINVAL", "Too few arguments");
172 | return NULL;
173 | }
174 |
175 | // Obtain location of JWT file
176 | size_t result;
177 | char JWTFileName[256];
178 | status = napi_get_value_string_utf8(env, args[0], JWTFileName, 256, &result);
179 |
180 | // Obtain ptr to JS callback function
181 | // napi_value js_cb = args[1];
182 | napi_typeof(env, args[1], &js_cb_type);
183 | if (js_cb_type != napi_function) {
184 | ZITI_NODEJS_LOG(DEBUG, "args[1] is NOT a napi_function");
185 | } else {
186 | ZITI_NODEJS_LOG(DEBUG, "args[1] IS a napi_function");
187 | }
188 | napi_value work_name;
189 |
190 | EnrollAddonData* addon_data = memset(malloc(sizeof(*addon_data)), 0, sizeof(*addon_data));
191 |
192 | // Create a string to describe this asynchronous operation.
193 | assert(napi_create_string_utf8(
194 | env,
195 | "N-API on_ziti_enroll",
196 | NAPI_AUTO_LENGTH,
197 | &work_name) == napi_ok);
198 |
199 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
200 | // which we can call from a worker thread.
201 | status = napi_create_threadsafe_function(
202 | env,
203 | args[1],
204 | NULL,
205 | work_name,
206 | 0,
207 | 1,
208 | NULL,
209 | NULL,
210 | NULL,
211 | CallJs_on_enroll,
212 | &(addon_data->tsfn_on_enroll));
213 | if (status != napi_ok) {
214 | napi_throw_error(env, NULL, "Unable to napi_create_threadsafe_function");
215 | }
216 |
217 |
218 | // Initiate the enrollment
219 | ziti_enroll_opts opts = {0};
220 | opts.token = JWTFileName;
221 | int rc = ziti_enroll(&opts, thread_loop, on_ziti_enroll, addon_data);
222 |
223 | status = napi_create_int32(env, rc, &jsRetval);
224 | if (status != napi_ok) {
225 | napi_throw_error(env, NULL, "Unable to create return value");
226 | }
227 |
228 | return jsRetval;
229 | }
230 |
231 |
232 | void expose_ziti_enroll(napi_env env, napi_value exports) {
233 | napi_status status;
234 | napi_value fn;
235 |
236 | status = napi_create_function(env, NULL, 0, _ziti_enroll, NULL, &fn);
237 | if (status != napi_ok) {
238 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_enroll");
239 | }
240 |
241 | status = napi_set_named_property(env, exports, "ziti_enroll", fn);
242 | if (status != napi_ok) {
243 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_enroll");
244 | }
245 |
246 | }
247 |
--------------------------------------------------------------------------------
/src/ziti_sdk_version.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 |
19 | #include
20 |
21 |
22 | /**
23 | *
24 | */
25 | napi_value _ziti_sdk_version(napi_env env, const napi_callback_info info) {
26 | napi_value jsRetval = NULL;
27 | napi_status status = napi_generic_failure;
28 |
29 | const ziti_version *ver = ziti_get_version();
30 |
31 | status = napi_create_string_utf8(env, ver->version, NAPI_AUTO_LENGTH, &jsRetval);
32 | if (status != napi_ok) return NULL;
33 |
34 | return jsRetval;
35 | }
36 |
37 |
38 | /**
39 | *
40 | */
41 | void expose_ziti_sdk_version(napi_env env, napi_value exports) {
42 | napi_status status;
43 | napi_value fn;
44 |
45 | status = napi_create_function(env, NULL, 0, _ziti_sdk_version, NULL, &fn);
46 | if (status != napi_ok) {
47 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_sdk_version");
48 | }
49 |
50 | status = napi_set_named_property(env, exports, "ziti_sdk_version", fn);
51 | if (status != napi_ok) {
52 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_sdk_version");
53 | }
54 |
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/src/ziti_service_available.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 |
21 | typedef struct {
22 | napi_async_work work;
23 | napi_threadsafe_function tsfn;
24 | } AddonData;
25 |
26 | // An item that will be generated here and passed into the JavaScript service_available callback
27 | typedef struct ServiceAvailableItem {
28 | ssize_t status;
29 | int permissions;
30 | } ServiceAvailableItem;
31 |
32 |
33 | /**
34 | * This function is responsible for calling the JavaScript 'service_available' callback function
35 | * that was specified when the ziti_service_available(...) was called from JavaScript.
36 | */
37 | static void CallJs_on_service_available(napi_env env, napi_value js_cb, void* context, void* data) {
38 | napi_status status;
39 |
40 | // This parameter is not used.
41 | (void) context;
42 |
43 | // Retrieve the ServiceAvailableItem created by the worker thread.
44 | ServiceAvailableItem* item = (ServiceAvailableItem*)data;
45 |
46 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
47 | // items are left over from earlier thread-safe calls from the worker thread.
48 | // When env is NULL, we simply skip over the call into Javascript and free the
49 | // items.
50 | if (env != NULL) {
51 |
52 | napi_value undefined;
53 |
54 | // const obj = {}
55 | napi_value js_service_available_item, js_status, js_permissions;
56 | status = napi_create_object(env, &js_service_available_item);
57 | if (status != napi_ok) {
58 | napi_throw_error(env, NULL, "Unable to napi_create_object");
59 | }
60 |
61 | // obj.status = status
62 | status = napi_create_int64(env, (int64_t)item->status, &js_status);
63 | if (status != napi_ok) {
64 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
65 | }
66 | status = napi_set_named_property(env, js_service_available_item, "status", js_status);
67 | if (status != napi_ok) {
68 | napi_throw_error(env, NULL, "Unable to napi_set_named_property");
69 | }
70 |
71 | // obj.permissions = permissions
72 | status = napi_create_int64(env, (int64_t)item->permissions, &js_permissions);
73 | if (status != napi_ok) {
74 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
75 | }
76 | status = napi_set_named_property(env, js_service_available_item, "permissions", js_permissions);
77 | if (status != napi_ok) {
78 | napi_throw_error(env, NULL, "Unable to napi_set_named_property");
79 | }
80 |
81 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
82 | // value of the JavaScript function call.
83 | status = napi_get_undefined(env, &undefined);
84 | if (status != napi_ok) {
85 | napi_throw_error(env, NULL, "Unable to napi_get_undefined (4)");
86 | }
87 |
88 | // Call the JavaScript function and pass it the ServiceAvailableItem
89 | status = napi_call_function(
90 | env,
91 | undefined,
92 | js_cb,
93 | 1,
94 | &js_service_available_item,
95 | NULL);
96 | if (status != napi_ok) {
97 | napi_throw_error(env, NULL, "Unable to napi_call_function");
98 | }
99 | }
100 | }
101 |
102 |
103 | /**
104 | *
105 | */
106 | static void on_service_available(ziti_context nf_ctx, const ziti_service* service, int status, void *ctx) {
107 | napi_status nstatus;
108 |
109 | AddonData* addon_data = (AddonData*)ctx;
110 |
111 | ServiceAvailableItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
112 | item->status = status;
113 |
114 | if (ZITI_OK == status) {
115 | item->permissions = service->perm_flags;
116 | }
117 |
118 | // Initiate the call into the JavaScript callback.
119 | // The call into JavaScript will not have happened
120 | // when this function returns, but it will be queued.
121 | nstatus = napi_call_threadsafe_function(
122 | addon_data->tsfn,
123 | item,
124 | napi_tsfn_blocking);
125 | if (nstatus != napi_ok) {
126 | ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
127 | }
128 | }
129 |
130 | /**
131 | *
132 | */
133 | napi_value _ziti_service_available(napi_env env, const napi_callback_info info) {
134 | napi_status status;
135 | size_t argc = 2;
136 | napi_value args[2];
137 | napi_value jsRetval;
138 |
139 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
140 | if (status != napi_ok) {
141 | napi_throw_error(env, NULL, "Failed to parse arguments");
142 | }
143 |
144 | if (argc < 2) {
145 | napi_throw_error(env, "EINVAL", "Too few arguments");
146 | return NULL;
147 | }
148 |
149 | // Obtain service name
150 | size_t result;
151 | char* ServiceName = malloc(256); // TODO: make this smarter
152 | status = napi_get_value_string_utf8(env, args[0], ServiceName, 100, &result);
153 | if (status != napi_ok) {
154 | napi_throw_error(env, NULL, "Service Name not provided");
155 | }
156 |
157 | // Obtain ptr to JS 'service_available' callback function
158 | napi_value js_write_cb = args[1];
159 | napi_value work_name;
160 | AddonData* addon_data = malloc(sizeof(AddonData));
161 |
162 | // Create a string to describe this asynchronous operation.
163 | status = napi_create_string_utf8(
164 | env,
165 | "N-API on_service_available",
166 | NAPI_AUTO_LENGTH,
167 | &work_name);
168 | if (status != napi_ok) {
169 | napi_throw_error(env, NULL, "Unable to napi_create_string_utf8");
170 | }
171 |
172 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
173 | // which we can call from a worker thread.
174 | status = napi_create_threadsafe_function(
175 | env,
176 | js_write_cb,
177 | NULL,
178 | work_name,
179 | 0,
180 | 1,
181 | NULL,
182 | NULL,
183 | NULL,
184 | CallJs_on_service_available,
185 | &(addon_data->tsfn));
186 | if (status != napi_ok) {
187 | napi_throw_error(env, NULL, "Unable to napi_call_threadsafe_function");
188 | }
189 |
190 | // Now, call the C-SDK to see if the service name is present
191 | ziti_service_available(ztx, ServiceName, on_service_available, addon_data);
192 |
193 | status = napi_create_int32(env, 0 /* always succeed here, it is the cb that tells the real tale */, &jsRetval);
194 | if (status != napi_ok) {
195 | napi_throw_error(env, NULL, "Unable to create return value");
196 | }
197 |
198 | free(ServiceName);
199 |
200 | return jsRetval;
201 | }
202 |
203 |
204 | /**
205 | *
206 | */
207 | void expose_ziti_service_available(napi_env env, napi_value exports) {
208 | napi_status status;
209 | napi_value fn;
210 |
211 | status = napi_create_function(env, NULL, 0, _ziti_service_available, NULL, &fn);
212 | if (status != napi_ok) {
213 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_service_available");
214 | }
215 |
216 | status = napi_set_named_property(env, exports, "ziti_service_available", fn);
217 | if (status != napi_ok) {
218 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_service_available");
219 | }
220 |
221 | }
222 |
223 |
--------------------------------------------------------------------------------
/src/ziti_services_refresh.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 | void ziti_services_refresh(ziti_context ztx, bool now);
21 |
22 |
23 | /**
24 | *
25 | */
26 | napi_value _ziti_services_refresh(napi_env env, const napi_callback_info info) {
27 | napi_status status;
28 | napi_value jsRetval;
29 |
30 | ZITI_NODEJS_LOG(INFO, "ziti_services_refresh initiated");
31 |
32 | // Now, call the C-SDK to refresh the services list
33 | ziti_services_refresh(ztx, true);
34 |
35 | status = napi_create_int32(env, 0 /* always succeed here */, &jsRetval);
36 | if (status != napi_ok) {
37 | napi_throw_error(env, NULL, "Unable to create return value");
38 | }
39 |
40 | return jsRetval;
41 | }
42 |
43 |
44 | /**
45 | *
46 | */
47 | void expose_ziti_services_refresh(napi_env env, napi_value exports) {
48 | napi_status status;
49 | napi_value fn;
50 |
51 | status = napi_create_function(env, NULL, 0, _ziti_services_refresh, NULL, &fn);
52 | if (status != napi_ok) {
53 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_services_refresh");
54 | }
55 |
56 | status = napi_set_named_property(env, exports, "ziti_services_refresh", fn);
57 | if (status != napi_ok) {
58 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_services_refresh");
59 | }
60 |
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/src/ziti_set_log_level.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 |
19 |
20 | /**
21 | *
22 | */
23 | napi_value _ziti_set_log_level(napi_env env, const napi_callback_info info) {
24 | napi_status status;
25 | napi_value jsRetval;
26 |
27 | size_t argc = 1;
28 | napi_value args[1];
29 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
30 | if (status != napi_ok) {
31 | napi_throw_error(env, NULL, "Failed to parse arguments");
32 | }
33 |
34 | if (argc < 1) {
35 | napi_throw_error(env, "EINVAL", "Too few arguments");
36 | return NULL;
37 | }
38 |
39 | int64_t js_log_level;
40 | status = napi_get_value_int64(env, args[0], &js_log_level);
41 | if (status != napi_ok) {
42 | napi_throw_error(env, NULL, "Failed to get logLevel");
43 | }
44 |
45 | ZITI_NODEJS_LOG(DEBUG, "js_log_level: %lld", (long long)js_log_level);
46 |
47 | ziti_nodejs_debug_level = js_log_level;
48 | ziti_log_set_level(js_log_level, NULL);
49 |
50 | status = napi_create_int32(env, 0, &jsRetval);
51 | if (status != napi_ok) {
52 | napi_throw_error(env, NULL, "Unable to create return value");
53 | }
54 |
55 | return jsRetval;
56 | }
57 |
58 |
59 | void expose_ziti_set_log_level(napi_env env, napi_value exports) {
60 | napi_status status;
61 | napi_value fn;
62 |
63 | status = napi_create_function(env, NULL, 0, _ziti_set_log_level, NULL, &fn);
64 | if (status != napi_ok) {
65 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_set_log_level");
66 | }
67 |
68 | status = napi_set_named_property(env, exports, "ziti_set_log_level", fn);
69 | if (status != napi_ok) {
70 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_set_log_level");
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/ziti_shutdown.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 |
19 |
20 | /**
21 | *
22 | */
23 | napi_value _ziti_shutdown(napi_env env, const napi_callback_info info) {
24 |
25 | ZITI_NODEJS_LOG(DEBUG, "ztx: %p", ztx);
26 |
27 | ziti_shutdown(ztx);
28 |
29 | return NULL;
30 | }
31 |
32 |
33 | void expose_ziti_shutdown(napi_env env, napi_value exports) {
34 | napi_status status;
35 | napi_value fn;
36 |
37 | status = napi_create_function(env, NULL, 0, _ziti_shutdown, NULL, &fn);
38 | if (status != napi_ok) {
39 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_shutdown");
40 | }
41 |
42 | status = napi_set_named_property(env, exports, "ziti_shutdown", fn);
43 | if (status != napi_ok) {
44 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_shutdown");
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/ziti_websocket_write.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 | // An item that will be generated here and passed into the JavaScript write callback
21 | typedef struct WSWriteItem {
22 | tlsuv_websocket_t *ws;
23 | ssize_t status;
24 | } WSWriteItem;
25 |
26 |
27 | /**
28 | * This function is responsible for calling the JavaScript 'write' callback function
29 | * that was specified when the ziti_write(...) was called from JavaScript.
30 | */
31 | static void CallJs_on_write(napi_env env, napi_value js_cb, void* context, void* data) {
32 | napi_status status;
33 |
34 | // This parameter is not used.
35 | (void) context;
36 |
37 | // Retrieve the WriteItem created by the worker thread.
38 | WSWriteItem* item = (WSWriteItem*)data;
39 |
40 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
41 | // items are left over from earlier thread-safe calls from the worker thread.
42 | // When env is NULL, we simply skip over the call into Javascript and free the
43 | // items.
44 | if (env != NULL) {
45 |
46 | napi_value undefined;
47 |
48 | // const obj = {}
49 | napi_value js_write_item, js_ws, js_status;
50 | status = napi_create_object(env, &js_write_item);
51 | if (status != napi_ok) {
52 | napi_throw_error(env, NULL, "Unable to napi_create_object");
53 | }
54 |
55 | // obj.ws = ws
56 | ZITI_NODEJS_LOG(DEBUG, "ws=%p", item->ws);
57 | status = napi_create_int64(env, (int64_t)item->ws, &js_ws);
58 | if (status != napi_ok) {
59 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
60 | }
61 | status = napi_set_named_property(env, js_write_item, "ws", js_ws);
62 | if (status != napi_ok) {
63 | napi_throw_error(env, NULL, "Unable to napi_set_named_property");
64 | }
65 |
66 | // obj.status = status
67 | ZITI_NODEJS_LOG(DEBUG, "status=%zd", item->status);
68 | status = napi_create_int64(env, (int64_t)item->status, &js_status);
69 | if (status != napi_ok) {
70 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
71 | }
72 | status = napi_set_named_property(env, js_write_item, "status", js_status);
73 | if (status != napi_ok) {
74 | napi_throw_error(env, NULL, "Unable to napi_set_named_property");
75 | }
76 |
77 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
78 | // value of the JavaScript function call.
79 | status = napi_get_undefined(env, &undefined);
80 | if (status != napi_ok) {
81 | napi_throw_error(env, NULL, "Unable to napi_get_undefined (5)");
82 | }
83 |
84 | // Call the JavaScript function and pass it the WriteItem
85 | status = napi_call_function(
86 | env,
87 | undefined,
88 | js_cb,
89 | 1,
90 | &js_write_item,
91 | NULL);
92 | if (status != napi_ok) {
93 | napi_throw_error(env, NULL, "Unable to napi_call_function");
94 | }
95 |
96 | free(item);
97 | }
98 | }
99 |
100 |
101 | /**
102 | *
103 | */
104 | static void on_write(uv_write_t *req, int status) {
105 | ZITI_NODEJS_LOG(DEBUG, "=========ws_write_cb: req: %p, status: %d", req, status);
106 |
107 | WSAddonData* addon_data = (WSAddonData*) req->data;
108 |
109 | free(req);
110 |
111 | WSWriteItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
112 | item->ws = &(addon_data->ws);
113 | item->status = status;
114 |
115 | // Initiate the call into the JavaScript callback.
116 | // The call into JavaScript will not have happened
117 | // when this function returns, but it will be queued.
118 | napi_status nstatus = napi_call_threadsafe_function(
119 | addon_data->tsfn_on_write,
120 | item,
121 | napi_tsfn_blocking);
122 | if (nstatus != napi_ok) {
123 | ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
124 | }
125 |
126 | }
127 |
128 |
129 | /**
130 | *
131 | */
132 | napi_value _ziti_websocket_write(napi_env env, const napi_callback_info info) {
133 | napi_status status;
134 | size_t argc = 3;
135 | napi_value args[3];
136 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
137 | if (status != napi_ok) {
138 | napi_throw_error(env, NULL, "Failed to parse arguments");
139 | }
140 |
141 | if (argc < 3) {
142 | napi_throw_error(env, "EINVAL", "Too few arguments");
143 | return NULL;
144 | }
145 |
146 | // Obtain websocket
147 | int64_t js_ws;
148 | status = napi_get_value_int64(env, args[0], &js_ws);
149 | if (status != napi_ok) {
150 | napi_throw_error(env, NULL, "Failed to get Conn");
151 | }
152 | tlsuv_websocket_t *ws = (tlsuv_websocket_t*)js_ws;
153 | ZITI_NODEJS_LOG(DEBUG, "========= ws: %p", ws);
154 |
155 | WSAddonData* addon_data = (WSAddonData*) ws->data;
156 | ZITI_NODEJS_LOG(DEBUG, "========= &(addon_data->ws): %p", &(addon_data->ws));
157 |
158 | // Obtain data to write (we expect a Buffer)
159 | void* buffer;
160 | size_t bufferLength;
161 | status = napi_get_buffer_info(env, args[1], &buffer, &bufferLength);
162 | if (status != napi_ok) {
163 | napi_throw_error(env, NULL, "Failed to get Buffer info");
164 | }
165 |
166 | // Since the underlying Buffer's lifetime is not guaranteed if it's managed by the VM, we will copy the chunk into our heap
167 | void* chunk = memset(malloc(bufferLength + 1), 0, bufferLength + 1);
168 | memcpy(chunk, buffer, bufferLength);
169 |
170 | // Obtain ptr to JS 'write' callback function
171 | napi_value js_write_cb = args[2];
172 | napi_value work_name;
173 |
174 | // Create a string to describe this asynchronous operation.
175 | status = napi_create_string_utf8(
176 | env,
177 | "N-API on_write",
178 | NAPI_AUTO_LENGTH,
179 | &work_name);
180 | if (status != napi_ok) {
181 | napi_throw_error(env, NULL, "Failed to napi_create_string_utf8");
182 | }
183 |
184 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
185 | // which we can call from a worker thread.
186 | status = napi_create_threadsafe_function(
187 | env,
188 | js_write_cb,
189 | NULL,
190 | work_name,
191 | 0,
192 | 1,
193 | NULL,
194 | NULL,
195 | NULL,
196 | CallJs_on_write,
197 | &(addon_data->tsfn_on_write));
198 | if (status != napi_ok) {
199 | napi_throw_error(env, NULL, "Failed to napi_create_threadsafe_function");
200 | }
201 |
202 | // Now, call the C-SDK to actually write the data over the websocket
203 |
204 | uv_write_t *wr = malloc(sizeof(uv_write_t));
205 | wr->data = addon_data;
206 | uv_buf_t b;
207 | b.base = chunk;
208 | b.len = bufferLength;
209 |
210 | tlsuv_websocket_write(wr, &(addon_data->ws), &b, on_write);
211 |
212 | return NULL;
213 | }
214 |
215 |
216 |
217 | /**
218 | *
219 | */
220 | void expose_ziti_websocket_write(napi_env env, napi_value exports) {
221 | napi_status status;
222 | napi_value fn;
223 |
224 | status = napi_create_function(env, NULL, 0, _ziti_websocket_write, NULL, &fn);
225 | if (status != napi_ok) {
226 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_websocket_write");
227 | }
228 |
229 | status = napi_set_named_property(env, exports, "ziti_websocket_write", fn);
230 | if (status != napi_ok) {
231 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_websocket_write");
232 | }
233 |
234 | }
235 |
236 |
--------------------------------------------------------------------------------
/src/ziti_write.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright NetFoundry Inc.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "ziti-nodejs.h"
18 | #include
19 |
20 |
21 | // An item that will be generated here and passed into the JavaScript write callback
22 | typedef struct WriteItem {
23 | ziti_connection conn;
24 | ssize_t status;
25 | } WriteItem;
26 |
27 |
28 | /**
29 | * This function is responsible for calling the JavaScript 'write' callback function
30 | * that was specified when the ziti_write(...) was called from JavaScript.
31 | */
32 | static void CallJs_on_write(napi_env env, napi_value js_cb, void* context, void* data) {
33 | napi_status status;
34 |
35 | ZITI_NODEJS_LOG(DEBUG, "CallJs_on_write entered");
36 |
37 | // This parameter is not used.
38 | (void) context;
39 |
40 | // Retrieve the WriteItem created by the worker thread.
41 | WriteItem* item = (WriteItem*)data;
42 |
43 | // env and js_cb may both be NULL if Node.js is in its cleanup phase, and
44 | // items are left over from earlier thread-safe calls from the worker thread.
45 | // When env is NULL, we simply skip over the call into Javascript and free the
46 | // items.
47 | if (env != NULL) {
48 |
49 | napi_value undefined;
50 |
51 | // const obj = {}
52 | napi_value js_write_item, js_conn, js_status;
53 | status = napi_create_object(env, &js_write_item);
54 | if (status != napi_ok) {
55 | napi_throw_error(env, NULL, "Unable to napi_create_object");
56 | }
57 |
58 | // obj.conn = conn
59 | ZITI_NODEJS_LOG(DEBUG, "conn=%p", item->conn);
60 | status = napi_create_int64(env, (int64_t)item->conn, &js_conn);
61 | if (status != napi_ok) {
62 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
63 | }
64 | status = napi_set_named_property(env, js_write_item, "conn", js_conn);
65 | if (status != napi_ok) {
66 | napi_throw_error(env, NULL, "Unable to napi_set_named_property");
67 | }
68 |
69 | // obj.status = status
70 | ZITI_NODEJS_LOG(DEBUG, "status=%zo", item->status);
71 | status = napi_create_int64(env, (int64_t)item->status, &js_status);
72 | if (status != napi_ok) {
73 | napi_throw_error(env, NULL, "Unable to napi_create_int64");
74 | }
75 | status = napi_set_named_property(env, js_write_item, "status", js_status);
76 | if (status != napi_ok) {
77 | napi_throw_error(env, NULL, "Unable to napi_set_named_property");
78 | }
79 |
80 | // Retrieve the JavaScript `undefined` value so we can use it as the `this`
81 | // value of the JavaScript function call.
82 | status = napi_get_undefined(env, &undefined);
83 | if (status != napi_ok) {
84 | napi_throw_error(env, NULL, "Unable to napi_get_undefined (5)");
85 | }
86 |
87 | // Call the JavaScript function and pass it the WriteItem
88 | status = napi_call_function(
89 | env,
90 | undefined,
91 | js_cb,
92 | 1,
93 | &js_write_item,
94 | NULL);
95 | if (status != napi_ok) {
96 | napi_throw_error(env, NULL, "Unable to napi_call_function");
97 | }
98 |
99 | free(item);
100 | }
101 | }
102 |
103 |
104 | /**
105 | *
106 | */
107 | static void on_write(ziti_connection conn, ssize_t status, void *ctx) {
108 |
109 | ConnAddonData* addon_data = (ConnAddonData*) ziti_conn_data(conn);
110 |
111 | ZITI_NODEJS_LOG(DEBUG, "on_write cb entered: addon_data: %p", addon_data);
112 |
113 | WriteItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
114 | item->conn = conn;
115 | item->status = status;
116 |
117 | // Initiate the call into the JavaScript callback.
118 | // The call into JavaScript will not have happened
119 | // when this function returns, but it will be queued.
120 | napi_status nstatus = napi_call_threadsafe_function(
121 | addon_data->tsfn_on_write,
122 | item,
123 | napi_tsfn_blocking);
124 | if (nstatus != napi_ok) {
125 | ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
126 | }
127 | }
128 |
129 |
130 | /**
131 | *
132 | */
133 | napi_value _ziti_write(napi_env env, const napi_callback_info info) {
134 | napi_status status;
135 | size_t argc = 3;
136 | napi_value args[3];
137 | status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
138 | if (status != napi_ok) {
139 | napi_throw_error(env, NULL, "Failed to parse arguments");
140 | }
141 |
142 | if (argc < 3) {
143 | napi_throw_error(env, "EINVAL", "Too few arguments");
144 | return NULL;
145 | }
146 |
147 | // Obtain ziti_connection
148 | int64_t js_conn;
149 | status = napi_get_value_int64(env, args[0], &js_conn);
150 | if (status != napi_ok) {
151 | napi_throw_error(env, NULL, "Failed to get Conn");
152 | }
153 | ziti_connection conn = (ziti_connection)js_conn;
154 |
155 | ConnAddonData* addon_data = (ConnAddonData*) ziti_conn_data(conn);
156 |
157 | // Obtain data to write (we expect a Buffer)
158 | void* buffer;
159 | size_t bufferLength;
160 | status = napi_get_buffer_info(env, args[1], &buffer, &bufferLength);
161 | if (status != napi_ok) {
162 | napi_throw_error(env, NULL, "Failed to get Buffer info");
163 | }
164 |
165 | // Since the underlying Buffer's lifetime is not guaranteed if it's managed by the VM, we will copy the chunk into our heap
166 | void* chunk = memset(malloc(bufferLength), 0, bufferLength);
167 | memcpy(chunk, buffer, bufferLength);
168 |
169 | // Obtain ptr to JS 'write' callback function
170 | napi_value js_write_cb = args[2];
171 | ZITI_NODEJS_LOG(DEBUG, "js_write_cb: %p", js_write_cb);
172 |
173 | napi_value work_name;
174 |
175 | // Create a string to describe this asynchronous operation.
176 | status = napi_create_string_utf8(
177 | env,
178 | "N-API on_write",
179 | NAPI_AUTO_LENGTH,
180 | &work_name);
181 | if (status != napi_ok) {
182 | napi_throw_error(env, NULL, "Failed to napi_create_string_utf8");
183 | }
184 |
185 | // Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
186 | // which we can call from a worker thread.
187 | status = napi_create_threadsafe_function(
188 | env,
189 | js_write_cb,
190 | NULL,
191 | work_name,
192 | 0,
193 | 1,
194 | NULL,
195 | NULL,
196 | NULL,
197 | CallJs_on_write,
198 | &(addon_data->tsfn_on_write));
199 | if (status != napi_ok) {
200 | napi_throw_error(env, NULL, "Failed to napi_create_threadsafe_function");
201 | }
202 |
203 | // Now, call the C-SDK to actually write the data over to the service
204 | ZITI_NODEJS_LOG(DEBUG, "call ziti_write");
205 | ziti_write(conn, chunk, bufferLength, on_write, NULL);
206 | ZITI_NODEJS_LOG(DEBUG, "back from ziti_write");
207 |
208 | return NULL;
209 | }
210 |
211 |
212 |
213 | /**
214 | *
215 | */
216 | void expose_ziti_write(napi_env env, napi_value exports) {
217 | napi_status status;
218 | napi_value fn;
219 |
220 | status = napi_create_function(env, NULL, 0, _ziti_write, NULL, &fn);
221 | if (status != napi_ok) {
222 | napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_write");
223 | }
224 |
225 | status = napi_set_named_property(env, exports, "ziti_write", fn);
226 | if (status != napi_ok) {
227 | napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_write");
228 | }
229 |
230 | }
231 |
232 |
--------------------------------------------------------------------------------
/tests/enroll-test.js:
--------------------------------------------------------------------------------
1 | const bindings = require('bindings')('ziti_sdk_nodejs')
2 |
3 | const result = bindings.ziti_sdk_version();
4 | const binary = require('@mapbox/node-pre-gyp');
5 | const path = require('path')
6 | const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
7 | const ziti = require(binding_path);
8 | require('assert').notEqual(result,"");
9 |
10 | console.log("using ziti version: " + ziti.ziti_sdk_version())
11 |
12 |
13 |
14 | const ziti_Enroll = async (jwt_path) => {
15 | console.log("JS ziti_Enroll() entered ")
16 | return new Promise((resolve, reject) => {
17 | let rc = ziti.ziti_enroll(
18 | jwt_path,
19 | (data) => {
20 | return resolve(data);
21 | }
22 | );
23 | });
24 | };
25 |
26 |
27 | (async () => {
28 |
29 | let jwt_path = process.argv[2];
30 |
31 | let data = await ziti_Enroll(jwt_path).catch((data) => {
32 | console.log('JS ziti_enroll failed with error code (%o/%s)', data.status, data.err);
33 | });
34 |
35 | if (data && data.identity) {
36 | console.log("data.identity is:\n\n%s\n", data.identity);
37 | }
38 |
39 | process.exit(0);
40 |
41 | })();
42 |
--------------------------------------------------------------------------------
/tests/hello.js:
--------------------------------------------------------------------------------
1 |
2 | const bindings = require('bindings')('ziti_sdk_nodejs')
3 |
4 | console.log(bindings)
5 | const result = bindings.ziti_sdk_version();
6 | console.log("ziti_sdk_version() result is: ", result);
7 |
8 |
9 |
10 | const binary = require('@mapbox/node-pre-gyp');
11 | const path = require('path')
12 | // const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: true});
13 | const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
14 | console.log("binding_path is: ", binding_path);
15 | const ziti = require(binding_path);
16 | console.log("ziti native addon is: \n", ziti);
17 | require('assert').notEqual(result,"");
18 | console.log("SUCCESS");
19 |
--------------------------------------------------------------------------------
/tests/https-test.js:
--------------------------------------------------------------------------------
1 |
2 | var binary = require('@mapbox/node-pre-gyp');
3 | var path = require('path')
4 | // var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: true});
5 | var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
6 | var ziti = require(binding_path);
7 | require('assert').equal(ziti.ziti_hello(),"ziti");
8 |
9 |
10 |
11 | const Ziti_http_request = async (url, method, headers) => {
12 | return new Promise((resolve, reject) => {
13 | try {
14 |
15 | console.log('headers (%o)', headers);
16 |
17 | let req = ziti.Ziti_http_request(
18 | url,
19 | method,
20 | headers,
21 | // on_req callback
22 | (obj) => {
23 | console.log('----------- Now inside Ziti_http_request on_req callback ----------, obj is: \n%o', obj);
24 | },
25 | // on_resp callback
26 | (obj) => {
27 | console.log('----------- Now inside Ziti_http_request on_resp callback ----------, obj is: \n%o', obj);
28 | // resolve(obj);
29 | },
30 | // on_resp_data callback
31 | (obj) => {
32 | console.log('----------- Now inside Ziti_http_request on_resp_data callback ----------, obj is: \n%o', obj);
33 | if (obj.body) {
34 | console.log('----------- obj.body is: \n%o', obj.body.toString());
35 | }
36 | },
37 | );
38 |
39 | console.log('inside JS Ziti_http_request(), req is (%o)', req);
40 | resolve(req);
41 |
42 | }
43 | catch (e) {
44 | reject(e);
45 | }
46 | });
47 | }
48 |
49 | const Ziti_http_request_data = async (req, buffer) => {
50 | return new Promise((resolve, reject) => {
51 | ziti.Ziti_http_request_data(
52 | req,
53 | buffer,
54 | // on_req_data callback
55 | (obj) => {
56 | console.log('----------- Now inside Ziti_http_request_data on_req_data callback ----------, obj is: \n%o', obj);
57 | resolve(obj);
58 | }
59 | );
60 | });
61 | }
62 |
63 | const NF_init = async () => {
64 | return new Promise((resolve) => {
65 | ziti.ziti_init(process.argv[2], () => {
66 | resolve();
67 | });
68 | });
69 | };
70 |
71 | let ctr = 0;
72 | const spin = () => {
73 | setTimeout( () => {
74 | ctr++;
75 | console.log("1-sec wait, ctr=%d", ctr);
76 | if (ctr < 60) {
77 | spin();
78 | } else {
79 | process.exit(0);
80 | }
81 | }, 1000);
82 | }
83 |
84 | // let chunkctr = 0;
85 | let chunkBody = process.argv[5];
86 |
87 | // const sendChunk = (req) => {
88 | // setTimeout( (req) => {
89 | // chunkctr++;
90 | // console.log("chunkctr=%d", chunkctr);
91 | // if (chunkctr < 10) {
92 |
93 | // buffer = Buffer.from(chunkBody + "-" + chunkctr);
94 |
95 | // console.log("sending chunk %d", chunkctr);
96 |
97 | // Ziti_http_request_data(req, buffer);
98 |
99 | // sendChunk(req);
100 |
101 | // } else {
102 | // console.log("======== calling Ziti_http_request_end");
103 | // ziti.Ziti_http_request_end( req );
104 | // }
105 | // }, 500, req);
106 | // }
107 |
108 | const sendChunk = (req) => {
109 | setTimeout( (req) => {
110 | buffer = Buffer.from(chunkBody);
111 | console.log("sending chunk");
112 | Ziti_http_request_data(req, buffer);
113 | }, 500, req);
114 | }
115 |
116 |
117 |
118 | (async () => {
119 |
120 | let url = process.argv[3];
121 | let method = process.argv[4];
122 | let body = process.argv[5];
123 | let buffer;
124 | let results;
125 | let headersArray = [
126 | "Content-Length:1",
127 | "Transfer-Encoding:chunked",
128 | ];
129 |
130 |
131 | await NF_init();
132 |
133 | if (typeof body !== 'undefined') {
134 |
135 | buffer = Buffer.from("1");
136 |
137 | console.log("Sending 'body' of: %o", buffer);
138 |
139 | let req = await Ziti_http_request(url, method, headersArray).catch((err) => {
140 | console.log('Ziti_http_request failed with error (%o)', err);
141 | process.exit(-1);
142 | });
143 |
144 | console.log("Ziti_http_request results is:\n\n%o", req);
145 |
146 |
147 | for (let i = 0; i < 10; i++) {
148 | console.log("queueing chunk %d", i);
149 |
150 | results = await Ziti_http_request_data(req, buffer).catch((err) => {
151 | console.log('Ziti_http_request_data failed with error (%o)', err);
152 | process.exit(-1);
153 | });
154 |
155 | }
156 |
157 | console.log('========================================================================================================');
158 | console.log('======================================== Ziti_http_request_end called ==================================');
159 | ziti.Ziti_http_request_end( req );
160 | console.log('========================================================================================================');
161 |
162 | } else {
163 |
164 | console.log("No 'body' will be sent");
165 |
166 |
167 | let req = await Ziti_http_request(url, method, []).catch((err) => {
168 | console.log('Ziti_http_request failed with error (%o)', err);
169 | process.exit(-1);
170 | });
171 |
172 | // console.log('inside JS main(), req is (%o)', req);
173 |
174 |
175 | // setTimeout( async () => {
176 |
177 | // for (let i=0; i<3; i++ ) {
178 |
179 | // let req2 = await Ziti_http_request(url, method, []).catch((err) => {
180 | // console.log('Ziti_http_request failed with error (%o)', err);
181 | // process.exit(-1);
182 | // });
183 |
184 | // console.log('inside JS main() setTimeout(), req is (%o)', req2);
185 |
186 | // }
187 |
188 | // }, 100);
189 |
190 | // let req2 = await Ziti_http_request(url, method, []).catch((err) => {
191 | // console.log('Ziti_http_request failed with error (%o)', err);
192 | // process.exit(-1);
193 | // });
194 |
195 | // console.log("Ziti_http_request results is:\n\n%o", req2);
196 |
197 | // console.log('========================================================================================================');
198 | // console.log('======================================== Ziti_http_request_end called ==================================');
199 | // ziti.Ziti_http_request_end( req );
200 | // console.log('========================================================================================================');
201 |
202 |
203 | }
204 |
205 |
206 | spin();
207 |
208 | })();
209 |
--------------------------------------------------------------------------------
/tests/mattermost-test.js:
--------------------------------------------------------------------------------
1 |
2 | var binary = require('@mapbox/node-pre-gyp');
3 | var path = require('path')
4 | var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
5 | var ziti = require(binding_path);
6 | require('assert').equal(ziti.ziti_hello(),"ziti");
7 |
8 |
9 |
10 | function NF_dial(service) {
11 | console.log('----------- inside NF_dial() ---------- service is: ', service);
12 | return new Promise((resolve, reject) => {
13 | ziti.ziti_dial(
14 | service,
15 | false, // NOT a wabsocket
16 | (conn) => {
17 | console.log('----------- Now inside NF_dial connect callback ----------, conn is: ' + conn);
18 | resolve(conn);
19 | },
20 | (data) => {
21 | console.log('----------- Now inside NF_dial data callback ----------, data is: [===\n%s\n===]', data);
22 | },
23 | );
24 | });
25 | }
26 |
27 | const rand = max => Math.floor(Math.random() * max);
28 | const delay = (ms, value) => new Promise(resolve => setTimeout(resolve, ms, value));
29 |
30 | const NF_init = async () => {
31 | return new Promise((resolve) => {
32 | ziti.ziti_init(process.argv[2], () => {
33 | resolve();
34 | });
35 | });
36 | };
37 |
38 | const NF_service_available = (service) => {
39 | return new Promise((resolve) => {
40 | ziti.ziti_service_available(service, (status) => {
41 | resolve(status);
42 | });
43 | });
44 | };
45 |
46 | const NF_write = (conn, data) => {
47 | return new Promise((resolve) => {
48 | ziti.ziti_write(conn, data, () => {
49 | resolve();
50 | });
51 | });
52 | };
53 |
54 | let ctr = 0;
55 | const spin = () => {
56 | setTimeout( () => {
57 | ctr++;
58 | console.log("1-sec wait, ctr=%d", ctr);
59 | if (ctr < 5) {
60 | spin();
61 | } else {
62 | process.exit(0);
63 | }
64 | }, 1000);
65 | }
66 |
67 |
68 | function NF_write_callback(item) {
69 | if (item.status < 0) {
70 | // console.log("NF_write_callback(): request performed on conn '%o' failed to submit status '%o'", item.conn, item.status);
71 | }
72 | else {
73 | // console.log("NF_write_callback(): request performed on conn '%o' successful: '%o' bytes sent", item.conn, item.status);
74 | }
75 | }
76 |
77 | function NF_dial_connect_callback(conn) {
78 |
79 | console.log("NF_dial_connect_callback(): received connection '%o'; now initiating Write to service", conn);
80 |
81 | let data =
82 | "GET / " +
83 | "HTTP/1.1\r\n" +
84 | "Accept: */*\r\n" +
85 | "Connection: keep-alive\r\n" +
86 | "Host: mattermost.ziti.netfoundry.io\r\n" +
87 | "User-Agent: curl/7.54.0\r\n" +
88 | "\r\n";
89 |
90 | ziti.ziti_write(
91 | conn,
92 | data,
93 | NF_write_callback
94 | );
95 | }
96 |
97 | function NF_dial_data_callback(data) {
98 | console.log("NF_dial_data_callback(): received the following data: \n\n", data);
99 | }
100 |
101 | (async () => {
102 |
103 | await NF_init();
104 |
105 | let status = await NF_service_available('mattermost.ziti.netfoundry.io');
106 |
107 | let conn = await NF_dial('mattermost.ziti.netfoundry.io');
108 |
109 | let data =
110 | "GET / " +
111 | "HTTP/1.1\r\n" +
112 | "Accept: */*\r\n" +
113 | "Connection: keep-alive\r\n" +
114 | "Host: mattermost.ziti.netfoundry.io\r\n" +
115 | "User-Agent: curl/7.54.0\r\n" +
116 | "\r\n";
117 |
118 | let buffer = Buffer.from(data);
119 |
120 | await NF_write(conn, buffer);
121 |
122 | spin();
123 |
124 | })();
125 |
--------------------------------------------------------------------------------
/tests/websocket-test.js:
--------------------------------------------------------------------------------
1 |
2 | var binary = require('@mapbox/node-pre-gyp');
3 | var path = require('path')
4 | var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: true});
5 | // var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
6 | var ziti = require(binding_path);
7 | require('assert').equal(ziti.ziti_hello(),"ziti");
8 |
9 |
10 |
11 | const do_ziti_websocket_connect = async (url) => {
12 | return new Promise((resolve, reject) => {
13 | try {
14 |
15 | console.log('----------- url (%o)', url);
16 |
17 | let rc = ziti.ziti_websocket_connect(
18 | url,
19 |
20 | // on_connect callback
21 | (ws) => {
22 | console.log('----------- Now inside ziti_websocket_connect on_connect callback ----------, ws is: %o', ws);
23 | resolve(ws);
24 | },
25 |
26 | // on_data callback
27 | (obj) => {
28 | console.log('----------- Now inside ziti_websocket_connect on_data callback ----------, obj is: \n%o', obj);
29 | console.log('----------- obj.body is: \n%o', obj.body.toString());
30 | },
31 | );
32 |
33 | // console.log('inside JS Ziti_http_request(), req is (%o)', rc);
34 | // resolve(req);
35 |
36 | }
37 | catch (e) {
38 | reject(e);
39 | }
40 | });
41 | }
42 |
43 |
44 | const do_ziti_websocket_write = async (ws, buffer) => {
45 | return new Promise((resolve, reject) => {
46 | try {
47 |
48 | console.log('----------- ws (%o)', ws);
49 |
50 | let rc = ziti.ziti_websocket_write(
51 | ws,
52 | buffer,
53 |
54 | // on_write callback
55 | (obj) => {
56 | console.log('----------- Now inside ziti_websocket_write on_write callback ----------, obj is: %o', obj);
57 | resolve(obj);
58 | },
59 |
60 | );
61 |
62 | }
63 | catch (e) {
64 | reject(e);
65 | }
66 | });
67 | }
68 |
69 |
70 | const NF_init = async () => {
71 | return new Promise((resolve) => {
72 | ziti.ziti_init(process.argv[2], () => {
73 | resolve();
74 | });
75 | });
76 | };
77 |
78 | let ctr = 0;
79 | const spin = () => {
80 | setTimeout( () => {
81 | ctr++;
82 | console.log("----------- 1-sec wait, ctr=%d", ctr);
83 | if (ctr < 10) {
84 | spin();
85 | } else {
86 | process.exit(0);
87 | }
88 | }, 1000);
89 | }
90 |
91 |
92 |
93 |
94 | (async () => {
95 |
96 | let url = process.argv[3];
97 |
98 | await NF_init();
99 |
100 |
101 | let ws = await do_ziti_websocket_connect(url).catch((err) => {
102 | console.log('----------- do_ziti_websocket_connect failed with error (%o)', err);
103 | process.exit(-1);
104 | });
105 |
106 | console.log('----------- do_ziti_websocket_connect() returned, ws is (%o)', ws);
107 |
108 | let buffer = Buffer.from("this is some data");
109 |
110 | let obj = await do_ziti_websocket_write(ws, buffer).catch((err) => {
111 | console.log('----------- do_ziti_websocket_write failed with error (%o)', err);
112 | process.exit(-1);
113 | });
114 |
115 | console.log('----------- do_ziti_websocket_write() returned, obj is (%o)', obj);
116 |
117 | spin();
118 |
119 | })();
120 |
--------------------------------------------------------------------------------
/toolchains/Linux-arm.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Linux)
2 | set(CMAKE_SYSTEM_PROCESSOR arm)
3 |
4 | set(triple arm-linux-gnueabihf)
5 |
6 | set(CMAKE_C_COMPILER ${triple}-gcc)
7 | set(CMAKE_CXX_COMPILER ${triple}-g++)
8 |
9 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
10 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
11 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
12 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
13 |
--------------------------------------------------------------------------------
/toolchains/Linux-arm64.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Linux)
2 | set(CMAKE_SYSTEM_PROCESSOR arm64)
3 |
4 | set(triple aarch64-linux-gnu)
5 |
6 | set(CMAKE_C_COMPILER ${triple}-gcc)
7 | set(CMAKE_CXX_COMPILER ${triple}-g++)
8 |
9 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
10 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
11 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
12 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
13 |
--------------------------------------------------------------------------------
/toolchains/Windows-arm64-msvc.cmake:
--------------------------------------------------------------------------------
1 | # cross-compile for windows/arm64 on windows/x64 host with visual studio
2 | set(CMAKE_SYSTEM_NAME Windows)
3 | set(CMAKE_SYSTEM_PROCESSOR ARM64)
4 | # setting CMAKE_GENERATOR_PLATFORM should be sufficient if you believe the doc, it results in build files
5 | # that cause msbuild to that the ZERO_CHECK project doesn't contain the "Debug|x64" platform/config
6 | # combination. running cmake with '-A ARCH64' avoids the msbuild failure.
7 | set(CMAKE_GENERATOR_PLATFORM ARM64)
8 | set(CMAKE_C_COMPILER cl.exe)
--------------------------------------------------------------------------------
/toolchains/Windows-x86.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Windows)
2 | set(CMAKE_SYSTEM_PROCESSOR x86)
3 |
4 | set(triple i686-w64-mingw32)
5 |
6 | set(CMAKE_C_COMPILER ${triple}-gcc)
7 | set(CMAKE_CXX_COMPILER ${triple}-g++)
8 |
9 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
10 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
11 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
12 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
13 |
--------------------------------------------------------------------------------
/toolchains/Windows-x86_64.cmake:
--------------------------------------------------------------------------------
1 | set(CMAKE_SYSTEM_NAME Windows)
2 | set(CMAKE_SYSTEM_PROCESSOR x86_64)
3 |
4 | set(triple x86_64-w64-mingw32)
5 |
6 | set(CMAKE_C_COMPILER ${triple}-gcc)
7 | set(CMAKE_CXX_COMPILER ${triple}-g++)
8 |
9 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
10 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
11 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
12 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
13 |
--------------------------------------------------------------------------------
/toolchains/linux-embedded.cmake:
--------------------------------------------------------------------------------
1 | if (NOT DEFINED ENV{TOOLCHAIN})
2 | message(FATAL_ERROR "TOOLCHAIN environment variable is not set")
3 | endif ()
4 |
5 | set(triple mips-openwrt-linux)
6 |
7 | set(CMAKE_SYSTEM_NAME Linux)
8 | set(CMAKE_SYSTEM_PROCESSOR mips)
9 |
10 | set(CMAKE_SYSROOT $ENV{TOOLCHAIN}/)
11 | set(CMAKE_C_COMPILER $ENV{TOOLCHAIN}/bin/${triple}-gcc)
12 | set(CMAKE_CXX_COMPILER $ENV{TOOLCHAIN}/bin/${triple}-g++)
13 |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
17 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
18 |
--------------------------------------------------------------------------------
/toolchains/macOS-arm64.cmake:
--------------------------------------------------------------------------------
1 | # build-macOS-arm64
2 |
3 | if (NOT (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") AND
4 | NOT(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64") )
5 | set(CMAKE_SYSTEM_NAME Darwin)
6 | set(CMAKE_SYSTEM_PROCESSOR arm64)
7 | endif ()
8 |
9 | set(ZITI_BUILD_TESTS OFF CACHE BOOL "" FORCE)
10 |
11 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch arm64")
12 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch arm64")
13 |
14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
17 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
18 |
--------------------------------------------------------------------------------
/toolchains/macOS-x86_64.cmake:
--------------------------------------------------------------------------------
1 | # build-macOS-x86_64
2 |
3 | set(CMAKE_SYSTEM_NAME Darwin)
4 | set(CMAKE_SYSTEM_PROCESSOR x86_64)
5 |
6 | set(ZITI_BUILD_TESTS OFF CACHE BOOL "" FORCE)
7 |
8 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch x86_64")
9 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -arch x86_64")
10 |
11 | # for libsodium
12 | set(triple x86_64-apple-macos11)
13 | execute_process(COMMAND /usr/bin/xcrun -sdk macosx --show-sdk-path
14 | OUTPUT_VARIABLE CMAKE_OSX_SYSROOT
15 | OUTPUT_STRIP_TRAILING_WHITESPACE)
16 |
17 | set(ENV{CFLAGS} "-arch x86_64 -isysroot ${CMAKE_OSX_SYSROOT}")
18 | set(ENV{LDFLAGS} "-arch x86_64 -isysroot ${CMAKE_OSX_SYSROOT}")
19 |
20 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
21 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
22 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
23 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
24 |
--------------------------------------------------------------------------------
/vcpkg.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ziti",
3 | "version-semver": "1.0.0",
4 | "dependencies": [
5 | {
6 | "name": "libuv",
7 | "platform": "!windows",
8 | "$comment": "on windows we link against node binary and Cmake.js provides libuv headers"
9 | },
10 | "openssl",
11 | "zlib",
12 | "llhttp",
13 | "libsodium",
14 | "json-c",
15 | "protobuf-c"
16 | ],
17 | "features": {
18 | },
19 | "builtin-baseline": "b322364f06308bdd24823f9d8f03fe0cc86fd46f"
20 | }
--------------------------------------------------------------------------------
/ziti.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/ziti');
--------------------------------------------------------------------------------
/ziti.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openziti/ziti-sdk-nodejs/53f2a339ffb16e8a11939618877e4590b982a8f7/ziti.png
--------------------------------------------------------------------------------