From 7cc508670af336ace9f486026efcc4e577434cde Mon Sep 17 00:00:00 2001 From: dovholuknf <46322585+dovholuknf@users.noreply.github.com> Date: Sun, 24 Sep 2023 12:26:20 -0400 Subject: [PATCH] initial round of updates. brings c sdk up to 0.34.x. updates to powershell setups, etc. will iterate on readmes next --- .github/workflows/native-nuget-publish.yml | 6 +- .gitignore | 1 + OpenZiti.NET/OpenZiti.NET.csproj | 62 +- OpenZiti.NET/src/OpenZiti/API.cs | 22 +- OpenZiti.NET/src/OpenZiti/ExtensionMethods.cs | 4 +- OpenZiti.NET/src/OpenZiti/ZitiException.cs | 8 +- OpenZiti.NET/src/OpenZiti/ZitiStatus.cs | 176 +- .../src/OpenZiti/ZitiStatusExtensions.cs | 2 +- OpenZiti.NET/src/OpenZiti/ZitiUtil.cs | 17 +- README.md | 77 +- Samples/Enrollment.cs | 9 +- Samples/HostedService.cs | 14 +- Samples/HostedServiceClient.cs | 14 +- Samples/OpenZitiSamples.csproj | 2 +- Samples/Program.cs | 32 +- Samples/Properties/launchSettings.json | 2 +- Samples/README.md | 18 + Samples/Weather.cs | 15 +- Samples/setup-scripts/enrollment.ps1 | 11 +- Samples/setup-scripts/hosted.ps1 | 51 +- Samples/setup-scripts/weather.ps1 | 51 +- TestProject/Properties/launchSettings.json | 2 +- TestProject/TestProject.csproj | 2 +- Ziti.NuGet.sln | 18 +- ZitiNativeApiForDotnetCore/CMakeLists.txt | 34 +- ZitiNativeApiForDotnetCore/CMakePresets.json | 226 +++ ZitiNativeApiForDotnetCore/README.md | 43 +- .../cmake_deps/CMakeLists.txt | 1 + ZitiNativeApiForDotnetCore/compile-all.bat | 34 - .../generateDotnetStatus.ps1 | 76 + ZitiNativeApiForDotnetCore/git.cmake | 6 +- ZitiNativeApiForDotnetCore/library/ziti.def | 1450 ++++++++--------- ZitiNativeApiForDotnetCore/msvc-build.bat | 138 +- .../toolchains/Windows-win32.cmake | 13 + .../toolchains/Windows-x86.cmake | 11 - ZitiNativeApiForDotnetCore/vcpkg.json | 24 + build-native.bat | 44 - dev-build-native.bat | 67 + native-package.nuspec | 3 +- ziti-v2.png | Bin 0 -> 60274 bytes 40 files changed, 1560 insertions(+), 1226 deletions(-) create mode 100644 Samples/README.md create mode 100644 ZitiNativeApiForDotnetCore/CMakePresets.json delete mode 100644 ZitiNativeApiForDotnetCore/compile-all.bat create mode 100644 ZitiNativeApiForDotnetCore/generateDotnetStatus.ps1 create mode 100644 ZitiNativeApiForDotnetCore/toolchains/Windows-win32.cmake delete mode 100644 ZitiNativeApiForDotnetCore/toolchains/Windows-x86.cmake create mode 100644 ZitiNativeApiForDotnetCore/vcpkg.json delete mode 100644 build-native.bat create mode 100644 dev-build-native.bat create mode 100644 ziti-v2.png diff --git a/.github/workflows/native-nuget-publish.yml b/.github/workflows/native-nuget-publish.yml index e27f18a..8966d66 100644 --- a/.github/workflows/native-nuget-publish.yml +++ b/.github/workflows/native-nuget-publish.yml @@ -103,6 +103,10 @@ jobs: run: | sudo apt update -y sudo apt install -y crossbuild-essential-armhf crossbuild-essential-arm64 + + - uses: lukka/run-vcpkg@v10 + with: + vcpkgGitCommitId: '19af97cba8ca48474e4ad15a24ed50271a9ecdac' - name: setup/build CMake env: @@ -110,7 +114,7 @@ jobs: run: | echo "build number = ${{ env.buildnum }}" cmake -E make_directory ${{ env.TARGETDIR }} - cmake -S ${{ env.BASEDIR }} -B ${{ env.TARGETDIR }} ${{ matrix.cmake_arch_flag }} -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN}" + cmake -S ${{ env.BASEDIR }} -B ${{ env.TARGETDIR }} -DCMAKE_BUILD_TYPE=Debug cmake --build ${{ env.TARGETDIR }} --config Release - name: upload artifacts diff --git a/.gitignore b/.gitignore index 97021d0..781e041 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ cmake-build-debug-mingw/ cmake-build-debug-msvc/ *.jwt +Samples/**/*.json *.snupkg weather.demo.json diff --git a/OpenZiti.NET/OpenZiti.NET.csproj b/OpenZiti.NET/OpenZiti.NET.csproj index 53e5bd7..7e464b3 100644 --- a/OpenZiti.NET/OpenZiti.NET.csproj +++ b/OpenZiti.NET/OpenZiti.NET.csproj @@ -1,46 +1,44 @@ - net6.0 $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + $([System.DateTime]::UtcNow.Year.ToString().Substring(2,2)) $([System.DateTime]::UtcNow.DayOfYear) - $([MSBuild]::Divide($([System.DateTime]::get_Now().get_TimeOfDay().get_TotalSeconds()), 2).ToString('F0')) - $([MSBuild]::Divide($([System.DateTime]::get_UtcNow().get_TimeOfDay().get_TotalSeconds()), 2).ToString('F0')) + $([MSBuild]::Divide($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds), 2).ToString('F0')) 0 - 8 - $(major).$(minor).$(UtcDayOfYear).$(UtcSecondsOfDay) + 9 + $(major).$(minor).$(CurrentYear)$(UtcDayOfYear).$(UtcSecondsOfDay) OpenZiti NetFoundry A .NET standard library which wraps the C SDK and is consumable from .NET © NetFoundry Inc. All rights reserved. 2019_NF TCL EULA.txt false - https://openziti.github.io/ + https://openziti.io/ https://github.com/openziti/ziti-sdk-csharp AnyCPU;x86;x64;ARM64 - ziti.png + ..\ziti-v2.png false true snupkg - - x64 - ZITI_X64;$(DefinedConstants) - - - arm64 - ZITI_X64;$(DefinedConstants) - - - - TRACE;$(DefinedConstants) - + + x64 + ZITI_X64;$(DefinedConstants) + + + arm64 + ZITI_X64;$(DefinedConstants) + + + TRACE;$(DefinedConstants) + - + @@ -61,18 +59,18 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/OpenZiti.NET/src/OpenZiti/API.cs b/OpenZiti.NET/src/OpenZiti/API.cs index e093367..b3da7a1 100644 --- a/OpenZiti.NET/src/OpenZiti/API.cs +++ b/OpenZiti.NET/src/OpenZiti/API.cs @@ -127,8 +127,8 @@ public static string EnrollIdentity(string jwtFile) { public static string EnrollIdentity(byte[] jwt, string key, string cert) { var rtn = nAPI.Ziti_enroll_identity(jwt, key, cert, out var id_json_ptr, out var id_json_len); ZitiStatus status = (ZitiStatus)rtn; - if (status != ZitiStatus.OK) { - throw new ZitiException(status); + if (status != ZitiStatus.ZITI_OK) { + throw ZitiException.Create(rtn); } var id_json = Marshal.PtrToStringUTF8(id_json_ptr); return id_json; @@ -153,7 +153,7 @@ public static int CheckSocket(ZitiSocket socket) { public static ZitiSocket Connect(ZitiSocket socket, ZitiContext ztx, string service, string terminator) { var rtn = nAPI.Ziti_connect(socket.NativeSocket, ztx.NativeContext, service, terminator); if (rtn < 0) { - ZitiStatus s = (ZitiStatus)rtn; + string s = Marshal.PtrToStringAnsi(Native.API.ziti_errorstr(rtn)); throw new ZitiException(s); } return socket; @@ -162,7 +162,7 @@ public static ZitiSocket Connect(ZitiSocket socket, ZitiContext ztx, string serv public static ZitiSocket ConnectByAddress(ZitiSocket socket, string host, UInt16 port) { var rtn = nAPI.Ziti_connect_addr(socket.NativeSocket, host, port); if (rtn < 0) { - ZitiStatus s = (ZitiStatus)rtn; + string s = Marshal.PtrToStringAnsi(Native.API.ziti_errorstr(rtn)); throw new ZitiException(s); } return socket; @@ -171,18 +171,16 @@ public static ZitiSocket ConnectByAddress(ZitiSocket socket, string host, UInt16 public static void Bind(ZitiSocket socket, ZitiContext ztx, string service, string terminator) { var rtn = nAPI.Ziti_bind(socket.NativeSocket, ztx.NativeContext, service, terminator); if (rtn < 0) { - int be = LastError(); - ZitiStatus s = (ZitiStatus)be; - throw new ZitiException(s); + int errNo = LastError(); + throw ZitiException.Create(errNo); } } public static void Listen(ZitiSocket socket, int backlog) { var rtn = nAPI.Ziti_listen(socket.NativeSocket, backlog); if (rtn < 0) { - int le = LastError(); - ZitiStatus s = (ZitiStatus)le; - throw new ZitiException(s); + int errNo = LastError(); + throw ZitiException.Create(errNo); } } @@ -200,9 +198,7 @@ public static ZitiSocket Accept(ZitiSocket socket, out string caller) { if (client_sock.ToInt64() < 0) { int errNo = LastError(); - //string err = Marshal.PtrToStringUTF8(NAPI.ziti_errorstr(errNo)); - ZitiStatus s = (ZitiStatus)errNo; - throw new ZitiException(s); + throw ZitiException.Create(errNo); } caller = Marshal.PtrToStringUTF8(callerBuff); diff --git a/OpenZiti.NET/src/OpenZiti/ExtensionMethods.cs b/OpenZiti.NET/src/OpenZiti/ExtensionMethods.cs index 7ef6941..9981c75 100644 --- a/OpenZiti.NET/src/OpenZiti/ExtensionMethods.cs +++ b/OpenZiti.NET/src/OpenZiti/ExtensionMethods.cs @@ -23,8 +23,8 @@ namespace OpenZiti { /// A class which provides an extension method to get a Description from an enum. The enum must be /// decorated with a /// - public static class EnumHelper { - public const string NO_DESC = "__NO DESCRIPTOIN AVAILABLE__"; + public static class EnumHelpera { + public const string NO_DESC = "__NO DESCRIPTION AVAILABLE__"; /// /// Extension method to return the of the enum. diff --git a/OpenZiti.NET/src/OpenZiti/ZitiException.cs b/OpenZiti.NET/src/OpenZiti/ZitiException.cs index 183b28e..e643c95 100644 --- a/OpenZiti.NET/src/OpenZiti/ZitiException.cs +++ b/OpenZiti.NET/src/OpenZiti/ZitiException.cs @@ -14,6 +14,7 @@ You may obtain a copy of the License at limitations under the License. */ using System; +using System.Runtime.InteropServices; namespace OpenZiti { /// @@ -27,9 +28,12 @@ public class ZitiException : Exception { public ZitiException(string message) : base(message) { } /// - /// The basic constructor for creating a ZitiException + /// A method to create an exception from a Native SDK response code /// /// The message - public ZitiException(ZitiStatus status) : base(status.GetDescription()) { } + public static ZitiException Create(int code) { + string desc = Marshal.PtrToStringAnsi(Native.API.ziti_errorstr(code)); + return new ZitiException(desc); + } } } diff --git a/OpenZiti.NET/src/OpenZiti/ZitiStatus.cs b/OpenZiti.NET/src/OpenZiti/ZitiStatus.cs index 02b2a02..d647675 100644 --- a/OpenZiti.NET/src/OpenZiti/ZitiStatus.cs +++ b/OpenZiti.NET/src/OpenZiti/ZitiStatus.cs @@ -1,126 +1,60 @@ - - - - -/* -Copyright 2019-2020 NetFoundry, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -https://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - - -// @cond - -// @endcond - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* -This file is generated using the C preprocessor. Do not edit -*/ -using System.ComponentModel; +// Copyright (c) NetFoundry Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// THIS FILE WAS GENERATED BY CMAKE AUTOMATICALLY +// +// SEE ZitiNativeApiForDotnetCore\CMakeLists.txt and look for generateDotnetStatus.ps1 namespace OpenZiti { - internal enum err { - _ziti_OK, _ziti_CONFIG_NOT_FOUND, _ziti_JWT_NOT_FOUND, _ziti_JWT_INVALID, _ziti_JWT_INVALID_FORMAT, _ziti_PKCS7_ASN1_PARSING_FAILED, _ziti_JWT_SIGNING_ALG_UNSUPPORTED, _ziti_JWT_VERIFICATION_FAILED, _ziti_ENROLLMENT_METHOD_UNSUPPORTED, _ziti_ENROLLMENT_CERTIFICATE_REQUIRED, _ziti_KEY_GENERATION_FAILED, _ziti_KEY_LOAD_FAILED, _ziti_CSR_GENERATION_FAILED, _ziti_INVALID_CONFIG, _ziti_NOT_AUTHORIZED, _ziti_CONTROLLER_UNAVAILABLE, _ziti_GATEWAY_UNAVAILABLE, _ziti_SERVICE_UNAVAILABLE, _ziti_EOF, _ziti_TIMEOUT, _ziti_CONNABORT, _ziti_INVALID_STATE, _ziti_CRYPTO_FAIL, _ziti_CONN_CLOSED, _ziti_INVALID_POSTURE, _ziti_MFA_EXISTS, _ziti_MFA_INVALID_TOKEN, _ziti_MFA_NOT_ENROLLED, _ziti_NOT_FOUND, _ziti_DISABLED, _ziti_PARTIALLY_AUTHENTICATED, _ziti_INVALID_AUTHENTICATOR_TYPE, _ziti_INVALID_AUTHENTICATOR_CERT, _ziti_INVALID_CERT_KEY_PAIR, _ziti_WTF, - } - - - public enum ZitiStatus { - [Description("OK")] OK = -err._ziti_OK, [Description("Configuration not found")] CONFIG_NOT_FOUND = -err._ziti_CONFIG_NOT_FOUND, [Description("JWT not found")] JWT_NOT_FOUND = -err._ziti_JWT_NOT_FOUND, [Description("JWT not accepted by controller")] JWT_INVALID = -err._ziti_JWT_INVALID, [Description("JWT has invalid format")] JWT_INVALID_FORMAT = -err._ziti_JWT_INVALID_FORMAT, [Description("PKCS7/ASN.1 parsing failed")] PKCS7_ASN1_PARSING_FAILED = -err._ziti_PKCS7_ASN1_PARSING_FAILED, [Description("unsupported JWT signing algorithm")] JWT_SIGNING_ALG_UNSUPPORTED = -err._ziti_JWT_SIGNING_ALG_UNSUPPORTED, [Description("JWT verification failed")] JWT_VERIFICATION_FAILED = -err._ziti_JWT_VERIFICATION_FAILED, [Description("unsupported enrollment method")] ENROLLMENT_METHOD_UNSUPPORTED = -err._ziti_ENROLLMENT_METHOD_UNSUPPORTED, [Description("enrollment method requires certificate")] ENROLLMENT_CERTIFICATE_REQUIRED = -err._ziti_ENROLLMENT_CERTIFICATE_REQUIRED, [Description("error generating private key")] KEY_GENERATION_FAILED = -err._ziti_KEY_GENERATION_FAILED, [Description("error loading TLS key")] KEY_LOAD_FAILED = -err._ziti_KEY_LOAD_FAILED, [Description("error generating a CSR")] CSR_GENERATION_FAILED = -err._ziti_CSR_GENERATION_FAILED, [Description("Configuration is invalid")] INVALID_CONFIG = -err._ziti_INVALID_CONFIG, [Description("Not Authorized")] NOT_AUTHORIZED = -err._ziti_NOT_AUTHORIZED, [Description("Ziti Controller is not available")] CONTROLLER_UNAVAILABLE = -err._ziti_CONTROLLER_UNAVAILABLE, [Description("Ziti Edge Router is not available")] GATEWAY_UNAVAILABLE = -err._ziti_GATEWAY_UNAVAILABLE, [Description("Service not available")] SERVICE_UNAVAILABLE = -err._ziti_SERVICE_UNAVAILABLE, [Description("Connection closed")] EOF = -err._ziti_EOF, [Description("Operation did not complete in time")] TIMEOUT = -err._ziti_TIMEOUT, [Description("Connection to edge router terminated")] CONNABORT = -err._ziti_CONNABORT, [Description("invalid state")] INVALID_STATE = -err._ziti_INVALID_STATE, [Description("crypto failure")] CRYPTO_FAIL = -err._ziti_CRYPTO_FAIL, [Description("connection is closed")] CONN_CLOSED = -err._ziti_CONN_CLOSED, [Description("failed posture check")] INVALID_POSTURE = -err._ziti_INVALID_POSTURE, [Description("an MFA enrollment already exists")] MFA_EXISTS = -err._ziti_MFA_EXISTS, [Description("the token provided was invalid")] MFA_INVALID_TOKEN = -err._ziti_MFA_INVALID_TOKEN, [Description("the current identity has not completed MFA enrollment")] MFA_NOT_ENROLLED = -err._ziti_MFA_NOT_ENROLLED, [Description("entity no longer exists or is no longer accessible")] NOT_FOUND = -err._ziti_NOT_FOUND, [Description("ziti context is disabled")] DISABLED = -err._ziti_DISABLED, [Description("api session is partially authenticated, waiting for auth query resolution")] PARTIALLY_AUTHENTICATED = -err._ziti_PARTIALLY_AUTHENTICATED, [Description("the authenticator could not be extended as it is the incorrect type")] INVALID_AUTHENTICATOR_TYPE = -err._ziti_INVALID_AUTHENTICATOR_TYPE, [Description("the authenticator could not be extended as the current client certificate does not match")] INVALID_AUTHENTICATOR_CERT = -err._ziti_INVALID_AUTHENTICATOR_CERT, [Description("the active certificate and key could not be set, invalid pair, or could not parse")] INVALID_CERT_KEY_PAIR = -err._ziti_INVALID_CERT_KEY_PAIR, [Description("WTF: programming error")] WTF = -err._ziti_WTF, + ZITI_OK = 0, + ZITI_CONFIG_NOT_FOUND = -1, + ZITI_JWT_NOT_FOUND = -2, + ZITI_JWT_INVALID = -3, + ZITI_JWT_INVALID_FORMAT = -4, + ZITI_PKCS7_ASN1_PARSING_FAILED = -5, + ZITI_JWT_SIGNING_ALG_UNSUPPORTED = -6, + ZITI_JWT_VERIFICATION_FAILED = -7, + ZITI_ENROLLMENT_METHOD_UNSUPPORTED = -8, + ZITI_ENROLLMENT_CERTIFICATE_REQUIRED = -9, + ZITI_KEY_GENERATION_FAILED = -10, + ZITI_KEY_LOAD_FAILED = -11, + ZITI_CSR_GENERATION_FAILED = -12, + ZITI_INVALID_CONFIG = -13, + ZITI_AUTHENTICATION_FAILED = -14, + ZITI_NOT_AUTHORIZED = -15, + ZITI_CONTROLLER_UNAVAILABLE = -16, + ZITI_GATEWAY_UNAVAILABLE = -17, + ZITI_SERVICE_UNAVAILABLE = -18, + ZITI_EOF = -19, + ZITI_TIMEOUT = -20, + ZITI_CONNABORT = -21, + ZITI_INVALID_STATE = -22, + ZITI_CRYPTO_FAIL = -23, + ZITI_CONN_CLOSED = -24, + ZITI_INVALID_POSTURE = -25, + ZITI_MFA_EXISTS = -26, + ZITI_MFA_INVALID_TOKEN = -27, + ZITI_MFA_NOT_ENROLLED = -28, + ZITI_NOT_FOUND = -29, + ZITI_DISABLED = -30, + ZITI_PARTIALLY_AUTHENTICATED = -31, + ZITI_INVALID_AUTHENTICATOR_TYPE = -32, + ZITI_INVALID_AUTHENTICATOR_CERT = -33, + ZITI_INVALID_CERT_KEY_PAIR = -34, + ZITI_WTF = -111, + } } + diff --git a/OpenZiti.NET/src/OpenZiti/ZitiStatusExtensions.cs b/OpenZiti.NET/src/OpenZiti/ZitiStatusExtensions.cs index cd455d1..33c3ad9 100644 --- a/OpenZiti.NET/src/OpenZiti/ZitiStatusExtensions.cs +++ b/OpenZiti.NET/src/OpenZiti/ZitiStatusExtensions.cs @@ -17,7 +17,7 @@ limitations under the License. namespace OpenZiti { internal static class ZitiStatusExtensions { public static bool Ok(this ZitiStatus s) { - return s == ZitiStatus.OK; + return s == ZitiStatus.ZITI_OK; } } } diff --git a/OpenZiti.NET/src/OpenZiti/ZitiUtil.cs b/OpenZiti.NET/src/OpenZiti/ZitiUtil.cs index 1b81f05..fc720fd 100644 --- a/OpenZiti.NET/src/OpenZiti/ZitiUtil.cs +++ b/OpenZiti.NET/src/OpenZiti/ZitiUtil.cs @@ -22,24 +22,11 @@ internal static class ZitiUtil { public static readonly GCHandle NO_CONTEXT = GCHandle.Alloc(new object()); public static readonly IntPtr NO_CONTEXT_PTR = GCHandle.ToIntPtr(NO_CONTEXT); - public static void CheckStatus(ZitiContext zitiContext, ZitiStatus status, object initContext) { - status.Check(); - } - public static void CheckStatus(int status) { - if (status < 0) { - CheckStatus((ZitiStatus)status); - } - } - - public static void CheckStatus(ZitiStatus status) { - if (status != ZitiStatus.OK) { - throw new ZitiException(status); + if ((ZitiStatus)status != ZitiStatus.ZITI_OK) { + throw ZitiException.Create(status); } } - public static void Check(this ZitiStatus status) { - ZitiUtil.CheckStatus(status); - } public static object GetTarget(GCHandle handle) { if (handle.IsAllocated) { diff --git a/README.md b/README.md index b16bc0c..d094c2f 100644 --- a/README.md +++ b/README.md @@ -8,43 +8,80 @@ provide easy, secure connectivity over an OpenZiti overlay network to other .NET ## Overview This project provides two nuget packages. One nuget package is a wrapper around the OpenZiti -[C SDK](https://github.com/openziti/ziti-sdk-c) exposing the native SDK in a way easily consumed by .NET projects. -The second package is a .NET native library which consumes the native C SDK package and exposes a more idomatic .NET API. +[C SDK](https://github.com/openziti/ziti-sdk-c) exposing the native C SDK in a way easily +consumed by .NET projects. The second package is a .NET native library which consumes the +Native NuGet package and exposes a more idomatic .NET API. ### Native NuGet Package -The NuGet package providing the native libraries is built and published by GitHub actions. Building the native library is somewhat -complex. If you are interested in learning how the native library is built, see the [github action file](.github/workflows/native-nuget-publish.yml). -The package is built using a [cmake](https://cmake.org/) project found in the repository, in a folder named ZitiNativeApiForDotnetCore. -You can look through that project and [read the readme](./ZitiNativeApiForDotnetCore/README.md) for more detailed information. +The Native NuGet package providing the native libraries is built and published by GitHub actions but can also +be built locally if needed. Building the native library is somewhat complex. If you are interested in learning +how the native library is built, see the [github action file](.github/workflows/native-nuget-publish.yml) or +look at the file [msvc-build.bat](./ZitiNativeApiForDotnetCore/msvc-build.bat). The package is built using +the [cmake](https://cmake.org/) project found in the ZitiNativeApiForDotnetCore directory. You can look through +that project and [read the readme](./ZitiNativeApiForDotnetCore/README.md) for more detailed information. Building a cross-platform .NET library, using a native C library is somewhat complicated. +The Native library is then wrapped by the .NET nuget package for idiomatic consumption. + ### NuGet Package for .NET SDK -The project also provides [a solution file](./Ziti.NuGet.sln) which is designed to create the actual dependency you would add to your .NET -project in the form of another NuGet package. This package will provide idiomatic .NET functions for use in your own project. +The project provides [a solution file](./Ziti.NuGet.sln) which is used to create the actual dependency +most people will use add as a dependency to their projects. This is the idiomatic .NET wrapper around the +native nuget package for use in other .NET projects. ### Samples -The project provides [a solution file](./Ziti.Samples.sln) which contains a suite of samples which you can inspect and draw inspiration -from. +The project provides [a solution file](./Ziti.Samples.sln) which contains a suite of samples which can +inspected and draw inspiration from. This project will consume the idomatic, NuGet package for .NET. + ## For Project Contributors -If you're cloning this package with the intention to make a fix or to update the C SDK used, here's a quick punchlist of things you will -want to review and understand before really digging in. This will take you through just the bullet points of what you need to do to make -sure you can develop/test/debug. +If you're cloning this package with the intention to make a fix or to update the C SDK used, here's a +quick punchlist of things you will want to review and understand before really digging in. This will +take you through just the bullet points of what you need to do to make sure you can develop/test/debug. Things you should do/understand: * Build the native project for x64 -* **If** you're using Windows, also build the native project for x86 -* Package the native dlls into a nuget package. This boils down to putting the dll for YOUR operating system into the proper location, - edit [the nuspec](./native-package.nuspec) and hack out the lines you don't want (or better copy that nuspec to a different one you - don't end up committing). then package it, and publish it to a **local** NuGet repo path and use it locally. - * Once you're ready and you think the native project is "correct" - you should push just the relevant changes and let - [the GitHub Action](https://github.com/openziti/ziti-sdk-csharp/actions/workflows/native-nuget-publish.yml) publish the latest - native nuget package. +* **If** you're using Windows, also build the native project for x86 (win32) +* Package the native dlls into a native nuget package. This boils down to putting the dll for YOUR operating + system into the proper location, edit [the nuspec](./native-package.nuspec) and hack out the lines + you don't want (or better copy that nuspec to a different one you don't end up committing). then package + it, and publish it to a **local** NuGet repo path and use it locally. A convinience script exists at the + checkout root named: `dev-build-native.bat`. It is designed for Windows/Visual Studio development. +* With the Native NuGet package built + + +1 + + + + + + + + + + + + + + + + + + + + + + + + + * Once you're ready and you think the native project is "correct" - you should push just the relevant + changes and let [the GitHub Action](https://github.com/openziti/ziti-sdk-csharp/actions/workflows/native-nuget-publish.yml) + publish the latest native nuget package. * Pull and use the latest native nuget package * Assuming you have 'the latest' nuget package - adapt the C# SDK code and write **IDIOMATIC** C# for the API. * Once the **IDIOMATIC** C# API exists, publish the OpenZiti.NET version to your **LOCAL** NuGet repo. diff --git a/Samples/Enrollment.cs b/Samples/Enrollment.cs index 609cded..7b3e2e0 100644 --- a/Samples/Enrollment.cs +++ b/Samples/Enrollment.cs @@ -22,12 +22,9 @@ limitations under the License. namespace OpenZiti.Samples { public class Enrollment : SampleBase { - public static void Run(string[] args) { - if (args == null || args.Length < 2) { - throw new Exception("This example expects the second paramter to be an unenrolled .jwt"); - } + public static void Run(string jwt) { Console.WriteLine("Enrolling the first time. This is expected to succeed"); - Enroll(args[1], Directory.GetCurrentDirectory() + "/enroll.demo.json"); + Enroll(jwt, Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "enroll.demo.json"); //now enroll the same exact token again and expect an error Console.WriteLine(); @@ -35,7 +32,7 @@ public static void Run(string[] args) { Console.WriteLine(" illustrate that enrollment may fail"); Console.WriteLine(); try { - Enroll(args[1], Directory.GetCurrentDirectory() + "/enroll.demo.json"); + Enroll(jwt, Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "enroll.demo.json"); } catch (Exception ex) { Console.WriteLine($" EXPECTED ERROR: JWT not accepted by controller"); Console.WriteLine($" ERROR RECEIVED: {ex.Message}"); diff --git a/Samples/HostedService.cs b/Samples/HostedService.cs index 85a7915..27d4d35 100644 --- a/Samples/HostedService.cs +++ b/Samples/HostedService.cs @@ -6,13 +6,17 @@ namespace OpenZiti.Samples { public class HostedService : SampleBase { - public static async Task Run(string[] args) { - if (args == null || args.Length < 2) { - throw new Exception("This example expects the second paramter to be an unenrolled .jwt"); + public static async Task Run(string hostedJwt) { + string outputPath = ""; + if (hostedJwt.EndsWith(".jwt")) { + outputPath = hostedJwt.Replace(".jwt", ".json"); + } else { + Console.WriteLine("Please provide a file that ends with .jwt"); + return; } - var outputPath = Directory.GetCurrentDirectory() + "/hosted.demo.json"; + try { - Enroll(args[1], outputPath); + Enroll(hostedJwt, outputPath); } catch (Exception e) { Console.WriteLine($"WARN: the jwt was not enrolled properly: {e.Message}"); } diff --git a/Samples/HostedServiceClient.cs b/Samples/HostedServiceClient.cs index 87b42cc..cc78802 100644 --- a/Samples/HostedServiceClient.cs +++ b/Samples/HostedServiceClient.cs @@ -6,13 +6,17 @@ namespace OpenZiti.Samples { public class HostedServiceClient : SampleBase { - public static async Task Run(string[] args) { - if (args == null || args.Length < 2) { - throw new Exception("This example expects the second paramter to be an unenrolled .jwt"); + public static async Task Run(string clientJwt) { + string outputPath = ""; + if (clientJwt.EndsWith(".jwt")) { + outputPath = clientJwt.Replace(".jwt", ".json"); + } else { + Console.WriteLine("Please provide a file that ends with .jwt"); + return; } - var outputPath = Directory.GetCurrentDirectory() + "/hosted.demo.client.json"; + try { - Enroll(args[1], outputPath); + Enroll(clientJwt, outputPath); } catch(Exception e) { Console.WriteLine($"WARN: the jwt was not enrolled properly: {e.Message}"); } diff --git a/Samples/OpenZitiSamples.csproj b/Samples/OpenZitiSamples.csproj index ab7cd7c..92ca2c7 100644 --- a/Samples/OpenZitiSamples.csproj +++ b/Samples/OpenZitiSamples.csproj @@ -17,7 +17,7 @@ - + diff --git a/Samples/Program.cs b/Samples/Program.cs index 4631eff..a9eb3e1 100644 --- a/Samples/Program.cs +++ b/Samples/Program.cs @@ -5,34 +5,44 @@ using NLog; using System.Threading.Tasks; using System.Collections.Generic; +using NLog.Fluent; namespace OpenZiti.Samples { public class Program { + private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); + static async Task Main(string[] args) { try { - //uncomment these lines to enable logging OpenZiti.Logging.SimpleConsoleLogging(LogLevel.Trace); + OpenZiti.API.NativeLogger = OpenZiti.API.DefaultNativeLogFunction; - + OpenZiti.API.InitializeZiti(); + //to see the logs from the Native SDK, set the log level + OpenZiti.API.SetLogLevel(Logging.ZitiLogLevel.INFO); Console.Clear(); - - if (args == null || args.Length < 1) { - Console.WriteLine("This app expects the first paramter to be the sample to run: {exampleToRun=weather|enroll|hosted|hosted-client} {path-to-identity-file} {other-options}"); - return; + + if (args == null || args.Length < 3) { + Console.WriteLine("These samples expect at least two params to be supplied:"); + Console.WriteLine(" param1: the sample to run: {exampleToRun=weather|enroll|hosted|hosted-client}"); + Console.WriteLine(" param2: the jwt to use: {path-to-identity-file}"); + Console.WriteLine(" then, any other params needed"); + return; } - switch (args[0].ToLower()) { + // reminder to devs that these examples are intended to run from the command line. that means args[0] + // will be the name of the executing assembly. if you "debug" these samples, make sure to add an args[0] + switch (args[1].ToLower()) { case "weather": - Weather.Run(args); + Weather.Run(args[2]); break; case "enroll": - Enrollment.Run(args); + Enrollment.Run(args[2]); break; case "hosted": - await HostedService.Run(args); + await HostedService.Run(args[2]); break; case "hosted-client": - await HostedServiceClient.Run(args); + await HostedServiceClient.Run(args[2]); break; default: Console.WriteLine($"Unexpected sample supplied {args[0]}."); diff --git a/Samples/Properties/launchSettings.json b/Samples/Properties/launchSettings.json index e246de3..32a025e 100644 --- a/Samples/Properties/launchSettings.json +++ b/Samples/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "Console": { "commandName": "Project", - "commandLineArgs": "weather C:\\git\\github\\openziti\\ziti-sdk-csharp\\Samples\\setup-scripts\\weather.demo.jwt", + "commandLineArgs": "arg0 weather C:\\git\\github\\openziti\\ziti-sdk-csharp\\Samples\\setup-scripts/enroll.demo.jwt", "sqlDebugging": false, "nativeDebugging": true } diff --git a/Samples/README.md b/Samples/README.md new file mode 100644 index 0000000..f6d4a2c --- /dev/null +++ b/Samples/README.md @@ -0,0 +1,18 @@ +# OpenZitiSamples + +This project contains sample applications that will work with an OpenZiti overlay. + +You will need a valid identity file for these samples to function properly. The samples +come with setup scripts that leverage the `ziti` CLI to setup the overlay for testing. + +If you do not have the `ziti` CLI, you can quickly install it by running a single +powershell command: +``` +iex(iwr -Uri https://get.openziti.io/quick/getZiti.ps1) +``` + +# Enrollment Demo +To run the enrollment demo, run `setup-scripts\enrollment.ps1` + + + diff --git a/Samples/Weather.cs b/Samples/Weather.cs index 2997734..1adcb43 100644 --- a/Samples/Weather.cs +++ b/Samples/Weather.cs @@ -22,19 +22,8 @@ limitations under the License. namespace OpenZiti.Samples { public class Weather : SampleBase { - public static void Run(string[] args) { - if (args == null || args.Length < 2) { - throw new Exception(@"This example expects the second paramter to be an unenrolled .jwt. - Please login to your controller using 'ziti edge login' then run 'pwsh setup-scripts/weather.ps1'"); - } - string outputPath = Directory.GetCurrentDirectory() + "/weather.demo.json"; - try { - Enroll(args[1], outputPath); - } catch (Exception e) { - Console.WriteLine($"WARN: the jwt was not enrolled properly: {e.Message}"); - } - - var c = new ZitiContext(outputPath); + public static void Run(string identityFile) { + var c = new ZitiContext(identityFile); var zitiSocketHandler = c.NewZitiSocketHandler("weather-svc"); var client = new HttpClient(new LoggingHandler(zitiSocketHandler)); client.DefaultRequestHeaders.Add("User-Agent", "curl/7.59.0"); diff --git a/Samples/setup-scripts/enrollment.ps1 b/Samples/setup-scripts/enrollment.ps1 index df3ea01..af56869 100644 --- a/Samples/setup-scripts/enrollment.ps1 +++ b/Samples/setup-scripts/enrollment.ps1 @@ -1,14 +1,17 @@ $idName="enroll.demo" -$demoId = ziti edge list identities "name=`"${idName}`"" -j | ConvertFrom-Json +$demoId = ziti edge list identities $('name=\"' + ${idName} + '\"') -j | ConvertFrom-Json -if ($demoId.data.id) { - ziti edge delete identity ${idName} +$id = $demoId.Data[0].Id +if (![string]::IsNullOrEmpty($id)) { + echo "removing old identity: ${id}" + ziti edge delete identity -- ${id} } echo "creating identity: ${idName}" -$id = ziti edge create identity user ${idName} -o "${PSScriptRoot}/${idName}.jwt" +$id = ziti edge create identity ${idName} -o "${PSScriptRoot}/${idName}.jwt" echo "=====================================================" echo "Setup for enroll sample is complete " +echo " jwt located at: ${PSScriptRoot}/${idName}.jwt" echo "=====================================================" echo " " \ No newline at end of file diff --git a/Samples/setup-scripts/hosted.ps1 b/Samples/setup-scripts/hosted.ps1 index d1b714f..6833041 100644 --- a/Samples/setup-scripts/hosted.ps1 +++ b/Samples/setup-scripts/hosted.ps1 @@ -1,27 +1,31 @@ +$svcName="hosted-svc" +$demoServerName="${svcName}.server" +$demoClientName="${svcName}.client" + function cleanup() { echo "Cleaning up..." - ziti edge delete config "hosted-svc.host.v1" - ziti edge delete config "hosted-svc.intercept.v1" - ziti edge delete config-type "hosted-config-type" - ziti edge delete service hosted-svc - ziti edge delete service-policy hosted-svc-dial - ziti edge delete service-policy hosted-svc-bind + ziti edge delete service "${svcName}" + ziti edge delete service-policy "${svcName}-dial" + ziti edge delete service-policy "${svcName}-bind" + echo "Clean up complete." } +echo " " $prompt = $true if("$args[1]".ToLower().StartsWith("y")) { $prompt=$false } -$demoId = ziti edge list identities 'name=\"hosted.demo\"' -j | ConvertFrom-Json -if ($demoId.data.id) { +$demoServerId = ziti edge list identities $('name=\"' + ${demoServerName} + '\"') -j | ConvertFrom-Json +if ($demoServerId.data.id) { if($prompt) { - $createId = Read-Host "hosted.demo identity exists. Delete and overwrite?" + $createId = Read-Host "${demoServerName} identity exists. Delete and overwrite?" } else { $createId="yes" } if ("${createId}".ToLower().StartsWith("y")) { - ziti edge delete identity hosted.demo + echo "removing: ${demoServerName}" + ziti edge delete identity ${demoServerName} } else { echo "Not cleaning up identity" @@ -31,19 +35,20 @@ if ($demoId.data.id) { $createId = $true; } if ($createId) { - echo "creating identity: hosted.demo" - $id = ziti edge create identity user hosted.demo -a "hosted-svc.binders" -o "${PSScriptRoot}\hosted.demo.jwt" + echo "creating identity: ${demoServerName}" + $id = ziti edge create identity ${demoServerName} -a "${svcName}.binders" -o "${PSScriptRoot}\${demoServerName}.jwt" } -$demoId = ziti edge list identities 'name=\"hosted.demo.client\"' -j | ConvertFrom-Json -if ($demoId.data.id) { +$demoClientId = ziti edge list identities $('name=\"' + ${demoClientName} + '\"') -j | ConvertFrom-Json +if ($demoClientId.data.id) { if($prompt) { - $createId = Read-Host "hosted.demo.client identity exists. Delete and overwrite?" + $createId = Read-Host "${demoClientName} identity exists. Delete and overwrite?" } else { $createId="yes" } if ("${createId}".ToLower().StartsWith("y")) { - ziti edge delete identity hosted.demo.client + echo "removing: ${demoClientName}" + ziti edge delete identity ${demoClientName} } else { echo "Not cleaning up identity" @@ -53,12 +58,12 @@ if ($demoId.data.id) { $createId = $true; } if ($createId) { - echo "creating identity: hosted.demo.client" - $id = ziti edge create identity user hosted.demo.client -a "hosted-svc.dialers" -o "${PSScriptRoot}\hosted.demo.client.jwt" + echo "creating identity: ${demoClientName}" + $id = ziti edge create identity ${demoClientName} -a "${svcName}.dialers" -o "${PSScriptRoot}\${demoClientName}.jwt" } $createServices = $true -$service = ziti edge list identities 'name=\"hosted.demo\"' -j | ConvertFrom-Json +$service = ziti edge list services $('name=\"' + ${svcName} + '\" limit none') -j | ConvertFrom-Json if($service.data.id) { if($prompt) { $svcCleanUp = Read-Host "Looks like the service already exists. Try to cleanup/start again?" @@ -75,14 +80,12 @@ if($service.data.id) { if ($createServices) { # create the hosted sample example - ziti edge create config 'hosted-svc.host.v1' host.v1 '{\"protocol\":\"tcp\", \"address\":\"hosted.demo.ziti\",\"port\":443}' - ziti edge create config 'hosted-svc.intercept.v1' intercept.v1 '{\"protocols\":[\"tcp\"],\"addresses\":[\"hosted.demo\"],\"portRanges\":[{\"low\":80, \"high\":443}]}' - ziti edge create service 'hosted-svc'--configs 'hosted-svc.intercept.v1,hosted-svc.host.v1' -a "sdk.service" + ziti edge create service "${svcName}" --configs '${svcName}.intercept.v1,${svcName}.host.v1' -a "sdk.service" # authorize sdk clients to dial the sdk example services - ziti edge create service-policy hosted-svc-dial Dial --service-roles "@hosted-svc" --identity-roles "#hosted-svc.dialers" + ziti edge create service-policy ${svcName}-dial Dial --service-roles "@${svcName}" --identity-roles "#${svcName}.dialers" # authorize the edge router to bind services - ziti edge create service-policy hosted-svc-bind Bind --service-roles "@hosted-svc" --identity-roles "#hosted-svc.binders" + ziti edge create service-policy ${svcName}-bind Bind --service-roles "@${svcName}" --identity-roles "#${svcName}.binders" } echo "=====================================================" echo "Setup for hosted.svc is complete " diff --git a/Samples/setup-scripts/weather.ps1 b/Samples/setup-scripts/weather.ps1 index e4adba8..7db7c35 100644 --- a/Samples/setup-scripts/weather.ps1 +++ b/Samples/setup-scripts/weather.ps1 @@ -1,11 +1,14 @@ +$demoIdName="weather.demo" +$svcName="weather-svc" +$EdgeRouter="" + function cleanup() { echo "Cleaning up..." - ziti edge delete config "weather-svc.host.v1" - ziti edge delete config "weather-svc.intercept.v1" - ziti edge delete config-type "weather-config-type" - ziti edge delete service weather-svc - ziti edge delete service-policy weather-svc-dial - ziti edge delete service-policy weather-svc-bind + ziti edge delete config "${svcName}.host.v1" + ziti edge delete config "${svcName}.intercept.v1" + ziti edge delete service "${svcName}" + ziti edge delete service-policy "${svcName}-dial" + ziti edge delete service-policy "${svcName}-bind" echo "Clean up complete." } echo " " @@ -26,9 +29,10 @@ if (!${EdgeRouter}) { } echo "EdgeRouter identity: ${EdgeRouter} will be used as the router to offload traffic for the demo." -$er=ziti edge list identities "name=`"${EdgeRouter}`" limit none" -j | ConvertFrom-Json -$weatherAttr="weather-svc.binders" +$er=ziti edge list identities $('name=\"' + ${EdgeRouter} + '\" limit none') -j | ConvertFrom-Json + +$weatherAttr="${svcName}.binders" if($er.data.id) { $found=$false foreach($attr in $er.data.roleAttributes) { @@ -45,15 +49,15 @@ if($er.data.id) { throw "ERROR: provided edge router identity [${EdgeRouter}] does not exist! Cannot continue." } -$demoId = ziti edge list identities "name=`"weather.demo`"" -j | ConvertFrom-Json +$demoId = ziti edge list identities -j -- $('name=\"' + ${demoIdName} + '\"') | ConvertFrom-Json if ($demoId.data.id) { if($prompt) { - $createId = Read-Host "weather.demo identity exists. Delete and overwrite?" + $createId = Read-Host "${demoIdName} identity exists. Delete and overwrite?" } else { $createId="yes" } if ("${createId}".ToLower().StartsWith("y")) { - ziti edge delete identity weather.demo + ziti edge delete identity ${demoIdName} } else { echo "Not cleaning up identity" @@ -62,13 +66,14 @@ if ($demoId.data.id) { } else { $createId = $true; } + if ($createId) { - echo "creating identity: weather.demo" - $id = ziti edge create identity user weather.demo -a "weather-svc.dialers" -o "${PSScriptRoot}/weather.demo.jwt" + echo "creating identity: ${demoIdName}" + $id = ziti edge create identity ${demoIdName} -a "${svcName}.dialers" -o "${PSScriptRoot}/${demoIdName}.jwt" } $createServices = $true -$service = ziti edge list services "name=`"weather-svc`" limit none" -j | ConvertFrom-Json +$service = ziti edge list services $('name=\"' + ${svcName} + '\" limit none') -j | ConvertFrom-Json if($service.data.id) { if($prompt) { $svcCleanUp = Read-Host "Looks like the service already exists. Try to cleanup/start again?" @@ -85,14 +90,14 @@ if($service.data.id) { if ($createServices) { # create the weather sample example - ziti edge create config "weather-svc.host.v1" host.v1 "{`"protocol`":`"tcp`", `"address`":`"wttr.in`",`"port`":443}" - ziti edge create config "weather-svc.intercept.v1" intercept.v1 "{`"protocols`":[`"tcp`"],`"addresses`":[`"wttr.in`"],`"portRanges`":[{`"low`":80, `"high`":443}]}" - ziti edge create service "weather-svc"--configs "weather-svc.intercept.v1,weather-svc.host.v1" -a "sdk.service" + ziti edge create config "${svcName}.host.v1" host.v1 '{\"protocol\":\"tcp\", \"address\":\"wttr.in\",\"port\":443}' + ziti edge create config "${svcName}.intercept.v1" intercept.v1 '{\"protocols\":[\"tcp\"],\"addresses\":[\"wttr.in\"],\"portRanges\":[{\"low\":443, \"high\":443}]}' + ziti edge create service "${svcName}" --configs "${svcName}.intercept.v1,${svcName}.host.v1" -a "sdk.service" # authorize sdk clients to dial the sdk example services - ziti edge create service-policy weather-svc-dial Dial --service-roles "@weather-svc" --identity-roles "#weather-svc.dialers" + ziti edge create service-policy ${svcName}-dial Dial --service-roles "@${svcName}" --identity-roles "#${svcName}.dialers" # authorize the edge router to bind services - ziti edge create service-policy weather-svc-bind Bind --service-roles "@weather-svc" --identity-roles "#weather-svc.binders" + ziti edge create service-policy ${svcName}-bind Bind --service-roles "@${svcName}" --identity-roles "#${svcName}.binders" } echo " " echo "=====================================================" @@ -102,7 +107,13 @@ echo "time for the services to propegate to the router " echo "before running the sample or you may receive an error" echo "like: no terminators exist for service " echo "" +echo "the identity you use to run this demo will need to " +echo "have an attribute added to it named: ${svcName}.dialers" +echo "for example, if you ran the enroll.demo previously, you" +echo "can run:" +echo " ziti edge update identity enroll.demo -a ${svcName}.dialers" +echo "" echo "then, execute the sample using: " -echo " dotnet run weather setup-scripts/weather.demo.jwt " +echo " dotnet run weather path-to/identity.json " echo "=====================================================" echo " " \ No newline at end of file diff --git a/TestProject/Properties/launchSettings.json b/TestProject/Properties/launchSettings.json index d9ccd45..8a9d312 100644 --- a/TestProject/Properties/launchSettings.json +++ b/TestProject/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "TestProject": { "commandName": "Project", - "commandLineArgs": "weather C:\\git\\github\\openziti\\ziti-sdk-csharp\\Samples\\setup-scripts\\weather.demo.jwt", + "commandLineArgs": "args0 weather c:\\git\\github\\openziti\\ziti-sdk-csharp\\Samples\\setup-scripts\\enroll.demo.json", "nativeDebugging": true }, "WSL": { diff --git a/TestProject/TestProject.csproj b/TestProject/TestProject.csproj index 4f0b52a..72a16f8 100644 --- a/TestProject/TestProject.csproj +++ b/TestProject/TestProject.csproj @@ -54,7 +54,7 @@ - + diff --git a/Ziti.NuGet.sln b/Ziti.NuGet.sln index 52ee2ab..1363007 100644 --- a/Ziti.NuGet.sln +++ b/Ziti.NuGet.sln @@ -8,12 +8,12 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{16F52D05-10CE-47CC-9B52-1F77CAADD252}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - build-native.bat = build-native.bat BUILDING.md = BUILDING.md ZitiNativeApiForDotnetCore\compile-all.bat = ZitiNativeApiForDotnetCore\compile-all.bat create-nuget-package.bat = create-nuget-package.bat ZitiNativeApiForDotnetCore\defgen.bat = ZitiNativeApiForDotnetCore\defgen.bat ZitiNativeApiForDotnetCore\msvc-build.bat = ZitiNativeApiForDotnetCore\msvc-build.bat + dev-build-native.bat = dev-build-native.bat native-package.nuspec = native-package.nuspec README.md = README.md EndProjectSection @@ -29,8 +29,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProject", "TestProject\TestProject.csproj", "{C8E8F477-D948-478C-8FED-5EF33365CAD4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AndroidBindingLib", "AndroidBindingLib\AndroidBindingLib.csproj", "{FA37495C-7070-4558-97A9-864C8DB329E8}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -75,20 +73,6 @@ Global {C8E8F477-D948-478C-8FED-5EF33365CAD4}.Release|x64.Build.0 = Release|x64 {C8E8F477-D948-478C-8FED-5EF33365CAD4}.Release|x86.ActiveCfg = Release|x86 {C8E8F477-D948-478C-8FED-5EF33365CAD4}.Release|x86.Build.0 = Release|x86 - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|ARM64.ActiveCfg = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|x64.ActiveCfg = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|x64.Build.0 = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|x86.ActiveCfg = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Debug|x86.Build.0 = Debug|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|Any CPU.Build.0 = Release|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|ARM64.ActiveCfg = Release|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|x64.ActiveCfg = Release|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|x64.Build.0 = Release|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|x86.ActiveCfg = Release|Any CPU - {FA37495C-7070-4558-97A9-864C8DB329E8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ZitiNativeApiForDotnetCore/CMakeLists.txt b/ZitiNativeApiForDotnetCore/CMakeLists.txt index 8c594b7..052709b 100644 --- a/ZitiNativeApiForDotnetCore/CMakeLists.txt +++ b/ZitiNativeApiForDotnetCore/CMakeLists.txt @@ -6,10 +6,11 @@ set( CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS 1 ) set(WINDOWS_EXPORT_ALL_SYMBOLS ON) set(USING_ZITI_SHARED ON) set(BUILDING_ZITI_SHARED ON) +set(ZITI_SDK_C_BRANCH_DEFAULT "0.34.1") if ("$ENV{ZITI_SDK_C_BRANCH}" STREQUAL "") #allow using a different branch of the CSDK easily - set(ZITI_SDK_C_BRANCH "0.30.8") + set(ZITI_SDK_C_BRANCH "${ZITI_SDK_C_BRANCH_DEFAULT}") message("using default ZITI_SDK_C_BRANCH: ${ZITI_SDK_C_BRANCH}") else() set(ZITI_SDK_C_BRANCH "$ENV{ZITI_SDK_C_BRANCH}") @@ -35,30 +36,13 @@ add_subdirectory(cmake_deps) add_subdirectory(library) #add_subdirectory(programs) -#generate the .cs file that represents the c sdk errors using the preprocessor -if ("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32") - set(ZITI_INCLUDES ${CMAKE_HOME_DIRECTORY}/build/x86/_deps/ziti-sdk-c-src/includes) -else() - set(ZITI_INCLUDES ${CMAKE_HOME_DIRECTORY}/build/x64/_deps/ziti-sdk-c-src/includes) -endif() -message("USING INCLUDES FROM: ${ZITI_INCLUDES}") - -set(OUTPUT_FILE ${CMAKE_HOME_DIRECTORY}/../OpenZiti.NET/src/OpenZiti/ZitiStatus.cs) -set(ZITI_ERR_FILE ${CMAKE_HOME_DIRECTORY}/library/sharp-errors.c) - -if("${GENERATE_ZITI_STATUS}" STREQUAL "YES") -if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") +string(TOLOWER "${GENERATE_ZITI_STATUS}" generate_csharp_enum) + FetchContent_MakeAvailable(ziti-sdk-c) +if("${generate_csharp_enum}" STREQUAL "yes") + set(SourceErrorsFile "${ziti-sdk-c_SOURCE_DIR}/includes/ziti/errors.h") + set(OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../OpenZiti.NET/src/OpenZiti/ZitiStatus.cs") execute_process( - COMMAND cl.exe /C /EP /I ${ZITI_INCLUDES} ${ZITI_ERR_FILE} - COMMAND_ECHO STDOUT - OUTPUT_FILE ${OUTPUT_FILE} + COMMAND powershell -File "${CMAKE_CURRENT_SOURCE_DIR}/generateDotnetStatus.ps1" -SourceFile "${SourceErrorsFile}" -OutputPath ${OUTPUT_FILE} ) -else() - execute_process( - COMMAND gcc -nostdinc -E -CC -P -I${ZITI_INCLUDES} ${ZITI_ERR_FILE} - COMMAND_ECHO STDOUT - OUTPUT_FILE ${OUTPUT_FILE} - ) -endif() -message("sharp-errors output to: ${OUTPUT_FILE}") + message("sharp-errors output to: ${OUTPUT_FILE}") endif() diff --git a/ZitiNativeApiForDotnetCore/CMakePresets.json b/ZitiNativeApiForDotnetCore/CMakePresets.json new file mode 100644 index 0000000..7af61ed --- /dev/null +++ b/ZitiNativeApiForDotnetCore/CMakePresets.json @@ -0,0 +1,226 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 14, + "patch": 0 + }, + "configurePresets": [ + { + "name": "dev-mode", + "hidden": true, + "cacheVariables": { + "VCPKG_MANIFEST_FEATURES": "test" + } + }, + { + "name": "vcpkg", + "hidden": true, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + } + }, + { + "name": "vcpkg-win64-static", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-windows-static-md" + } + }, + { + "name": "ninja", + "hidden": true, + "generator": "Ninja" + }, + { + "name": "ninja-multi-config", + "hidden": true, + "generator": "Ninja Multi-Config" + }, + { + "name": "vs-2022", + "hidden": true, + "generator": "Visual Studio 17 2022" + }, + { + "name": "ci-std", + "description": "This preset makes sure the project actually builds with at least the specified standard", + "hidden": true, + "cacheVariables": { + "CMAKE_C_EXTENSIONS": "ON", + "CMAKE_C_STANDARD": "99", + "CMAKE_C_STANDARD_REQUIRED": "ON", + "CMAKE_CXX_EXTENSIONS": "OFF", + "CMAKE_CXX_STANDARD": "11", + "CMAKE_CXX_STANDARD_REQUIRED": "ON" + } + }, + { + "name": "flags-unix", + "hidden": true, + "cacheVariables": { + "CMAKE_C_FLAGS": "", + "CMAKE_CXX_FLAGS": "" + } + }, + { + "name": "flags-windows", + "description": "Note that all the flags after /W4 are required for MSVC to conform to the language standard", + "hidden": true, + "cacheVariables": { + "CMAKE_C_FLAGS": "/utf-8 /W4 /permissive- /volatile:iso /Zc:preprocessor", + "CMAKE_CXX_FLAGS": "/utf-8 /W4 /permissive- /volatile:iso /Zc:preprocessor /Zc:__cplusplus /Zc:externConstexpr /Zc:throwingNew /EHsc" + } + }, + { + "name": "ci-unix", + "hidden": true, + "inherits": [ + "flags-unix", + "ci-std", + "ninja-multi-config" + ] + }, + { + "name": "ci-win64", + "inherits": [ + "flags-windows", + "ci-std", + "vs-2022" + ], + "architecture": { + "value": "x64", + "strategy": "external" + }, + "hidden": true + }, + { + "name": "ci-win-arm64", + "inherits": [ + "flags-windows", + "ci-std", + "vs-2022" + ], + "architecture": "ARM64", + "hidden": true + }, + { + "name": "ci-build", + "binaryDir": "${sourceDir}/build", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug", + "TLSUV_TLSLIB": "mbedtls" + } + }, + { + "name": "ci-macOS-x64", + "inherits": [ + "ci-build", + "ci-unix", + "dev-mode", + "vcpkg" + ] + }, + { + "name": "ci-macOS-arm64", + "inherits": [ + "ci-build", + "ci-unix", + "dev-mode", + "vcpkg" + ], + "cacheVariables": { + "VCPKG_TARGET_ARCHITECTURE": "arm64", + "VCPKG_TARGET_TRIPLET": "arm64-osx", + "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/macOS-arm64.cmake" + } + }, + { + "name": "ci-linux-x64", + "inherits": [ + "ci-build", + "ci-unix", + "vcpkg", + "dev-mode" + ], + "cacheVariables": { + + } + }, + { + "name": "ci-linux-arm64", + "inherits": "ci-linux-x64", + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm64-linux", + "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/Linux-arm64.cmake" + } + }, + { + "name": "ci-linux-arm", + "inherits": "ci-linux-x64", + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm-linux", + "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/Linux-arm.cmake" + } + }, + { + "name": "ci-linux-static-libssl", + "description": "preset to use static ssl libs provided by vcpkg for broad compatibility of GH release binaries", + "cacheVariables": { + "VCPKG_OVERLAY_PORTS": "${sourceDir}/vcpkg-overlays/linux-syslibs/ubuntu18" + }, + "hidden": true + }, + { + "name": "ci-linux-x64-static-libssl", + "inherits": [ "ci-linux-static-libssl", "ci-linux-x64" ] + }, + { + "name": "ci-linux-arm64-static-libssl", + "inherits": [ "ci-linux-static-libssl", "ci-linux-arm64" ] + }, + { + "name": "ci-linux-arm-static-libssl", + "inherits": [ "ci-linux-static-libssl", "ci-linux-arm" ] + }, + { + "name": "windows", + "inherits": [ + "ci-build", + "ci-win64", + "dev-mode", + "vcpkg" + ] + }, + { + "name": "win64", + "inherits": [ + "windows", + "vcpkg-win64-static" + ] + }, + { + "name": "win32", + "inherits": [ + "windows" + ], + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x86-windows-static-md" + } + }, + { + "name": "ci-windows-arm64", + "inherits": [ + "ci-build", + "ci-win-arm64", + "dev-mode", + "vcpkg" + ], + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm64-windows-static-md", + "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/toolchains/Windows-arm64.cmake" + } + } + ] +} diff --git a/ZitiNativeApiForDotnetCore/README.md b/ZitiNativeApiForDotnetCore/README.md index 37dade5..c2320eb 100644 --- a/ZitiNativeApiForDotnetCore/README.md +++ b/ZitiNativeApiForDotnetCore/README.md @@ -1,23 +1,56 @@ # Native NuGet Package -As mentioned in [the README](../README.md), this project is responsible for creating a nuget package which +As mentioned in [the base README](../README.md), this project is responsible for creating a nuget package which not only exposes the [ziti-sdk-c](https://github.com/openziti/ziti-sdk-c) functions in an easy-to-consume way, but it also layers on helper functions as needed. Often these additional functions will be to do things which dotnet doesn't seem to support, or we haven't discovered how to support it yet. Generally things like iterating a pointer or var args usage. This is a project based on [cmake](https://cmake.org/) which will compile the given C SDK into the native -nuget package. +nuget package. It also now requires [VCPKG](https://github.com/microsoft/vcpkg) in order to build the C SDK. The package should be consumable on Windows AMD x86/x64, AMD MacOS x64 and AMD linux x64 architectures. It does not currently have ARM versions. We currently **do not** support every RID. If your favorite dotnet arch is not covered by the ones mentioned, we'd love help it getting it working for your specific environment. ## Building -If you're considering building this project, you are almost certainly trying to develop the actual dotnet SDK, -or you're just wondering how all this project comes together. By far, the easiest way to learn is to go read -[the helper bat file](../build-native.bat). Assuming you have the project checked out and the needed dependencies +If you're considering building this project, you are almost certainly trying to develop the actual dotnet SDK +and you're trying to update the native NuGet package, or you're just wondering how all this project comes together. + +After installing cmake, gcc/msvc, vcpkg and any other dependencies that are needed, you'll first need to build this +project. Since it uses cmake, and assuming your shell is located in the same directory as this readme, you +should be able to simply issue something like: + +``` +SET TARGETDIR=%CD%\build + +cmake -E make_directory %TARGETDIR% +cmake --preset ci-windows-x64 -S . -B %TARGETDIR% +cmake --build %TARGETDIR% --config Debug +cmake --build %TARGETDIR% --config Release +``` + +When the build completes (shown here using the Windows x64 preset) you'll have two libraries compiled at: +``` +%TARGETDIR%/library/Debug/ziti4dotnet.dll +%TARGETDIR%/library/Release/ziti4dotnet.dll +``` + + + + + + + + + + + + + +By far, the easiest way to learn is to go read +[the helper bat file](../dev-build-native.bat). Assuming you have the project checked out and the needed dependencies on the path: * C compiler (Visual Studio 2019/2022 currently) * cmake diff --git a/ZitiNativeApiForDotnetCore/cmake_deps/CMakeLists.txt b/ZitiNativeApiForDotnetCore/cmake_deps/CMakeLists.txt index 41cacb6..0ca94c2 100644 --- a/ZitiNativeApiForDotnetCore/cmake_deps/CMakeLists.txt +++ b/ZitiNativeApiForDotnetCore/cmake_deps/CMakeLists.txt @@ -6,6 +6,7 @@ FetchContent_Declare(ziti-sdk-c ) set(ZITI_BUILD_TESTS off) set(ZITI_BUILD_PROGRAMS off) +set(TLSUV_TLSLIB "mbedtls") set(BUILDING_ZITI_SHARED 1) FetchContent_MakeAvailable(ziti-sdk-c) diff --git a/ZitiNativeApiForDotnetCore/compile-all.bat b/ZitiNativeApiForDotnetCore/compile-all.bat deleted file mode 100644 index 4abdff6..0000000 --- a/ZitiNativeApiForDotnetCore/compile-all.bat +++ /dev/null @@ -1,34 +0,0 @@ -@echo off - -set NATIVE_LIB_HOME=%~dp0 -set BUILDFOLDER=%NATIVE_LIB_HOME%build-win -if [%1]==[] goto usage -if /i "%1"=="Release" goto ok -if /i "%1"=="Debug" goto ok -goto usage - -:ok -set RELEASE_OR_DEBUG=%1 -REM echo RELEASE_OR_DEBUG=%RELEASE_OR_DEBUG% - -call %NATIVE_LIB_HOME%msvc-build.bat - -echo Building via cmake using: -echo cmake --build %BUILDFOLDER%\x86 --config %RELEASE_OR_DEBUG% -cmake --build %BUILDFOLDER%\x86 --config %RELEASE_OR_DEBUG% > "%BUILDFOLDER%\x86.%RELEASE_OR_DEBUG%.txt" -echo build result saved to: %BUILDFOLDER%\x86.%RELEASE_OR_DEBUG%.txt -echo. - -echo cmake --build %BUILDFOLDER%\x64 --config %RELEASE_OR_DEBUG% -cmake --build %BUILDFOLDER%\x64 --config %RELEASE_OR_DEBUG% > "%BUILDFOLDER%\x64.%RELEASE_OR_DEBUG%.txt" -echo build result saved to: %BUILDFOLDER%\x64.%RELEASE_OR_DEBUG%.txt -echo. -goto end - -:usage -echo. -echo USAGE: -echo compile-all.bat ^[Release^|Debug^] -echo. -:end -echo done \ No newline at end of file diff --git a/ZitiNativeApiForDotnetCore/generateDotnetStatus.ps1 b/ZitiNativeApiForDotnetCore/generateDotnetStatus.ps1 new file mode 100644 index 0000000..d2d39d1 --- /dev/null +++ b/ZitiNativeApiForDotnetCore/generateDotnetStatus.ps1 @@ -0,0 +1,76 @@ +<# +.SYNOPSIS +Generates a dotnet (csharp) enum from the OpenZiti c sdk errors.h file + +.DESCRIPTION +This script will: + - parse the errors.h file finding any #define'd symblols + - apply a regex to find the name of the symbol and the value + - write the values into an enum + +.PARAMETER OutputPath + The path the enum should be written into + +.OUTPUTS +None. + +.EXAMPLE +PS> .\generateDotnetStatus.ps1 +#> +param ( + [Parameter(Mandatory=$true)] [string]$SourceFile, + [Parameter(Mandatory=$true)] [string]$OutputPath +) + +$pattern = '.*#define\s+(\w+)\s+\((-?\d+)\)' +$statuses = $(select-string "#define ZITI_" -Path $SourceFile) + +# Initialize an empty array to store the transformed lines +$transformedLines = @() + +$total=$statuses.Count +# Read the input file line by line +foreach ($line in $statuses) { + # Check if a match was found, -match creates a $Matches automatically (see below) + if ($line -match $pattern) { + # Extract the matched values from the regex groups + $name = $Matches[1] + $value = $Matches[2] + # Create the desired output string + $outputLine = " $name = $value," + + # Add the transformed line to the array + $transformedLines += $outputLine + "`r`n" + } else { + # If no match was found, add the original line to the array + $transformedLines += $line + } +} + +$fileContents = "// Copyright (c) NetFoundry Inc. +// +// Licensed under the Apache License, Version 2.0 (the `"License`"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an `"AS IS`" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// THIS FILE WAS GENERATED BY CMAKE AUTOMATICALLY +// +// SEE ZitiNativeApiForDotnetCore\CMakeLists.txt and look for generateDotnetStatus.ps1 + +namespace OpenZiti { + public enum ZitiStatus { +" + $transformedLines + " + } +} +" + +Set-Content -Path $OutputPath -Value $fileContents +"enum written to $OutputPath" \ No newline at end of file diff --git a/ZitiNativeApiForDotnetCore/git.cmake b/ZitiNativeApiForDotnetCore/git.cmake index 0424c2d..d6b4381 100644 --- a/ZitiNativeApiForDotnetCore/git.cmake +++ b/ZitiNativeApiForDotnetCore/git.cmake @@ -43,10 +43,8 @@ if(${GIT_INFO} MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)$") elseif(${GIT_INFO} MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)-([0-9]+)-[^-]*") string(JOIN "." ver ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}) endif() -message("aaproject version: ${ver} (derived from git)") - - -message("bbproject version: ${ver}") +message("project version: ${ver} (derived from git)") +message("project version: ${ver}") message("git info:") message(" branch : ${GIT_BRANCH}") message(" hash : ${GIT_COMMIT_HASH}") diff --git a/ZitiNativeApiForDotnetCore/library/ziti.def b/ZitiNativeApiForDotnetCore/library/ziti.def index ecb4255..f6c90db 100644 --- a/ZitiNativeApiForDotnetCore/library/ziti.def +++ b/ZitiNativeApiForDotnetCore/library/ziti.def @@ -1,730 +1,724 @@ LIBRARY ziti EXPORTS -ZITI_CONFIG_NOT_FOUND @1 -ZITI_CONNABORT @2 -ZITI_CONN_CLOSED @3 -ZITI_CONTROLLER_UNAVAILABLE @4 -ZITI_CRYPTO_FAIL @5 -ZITI_CSR_GENERATION_FAILED @6 -ZITI_DISABLED @7 -ZITI_ENROLLMENT_CERTIFICATE_REQUIRED @8 -ZITI_ENROLLMENT_METHOD_UNSUPPORTED @9 -ZITI_EOF @10 -ZITI_GATEWAY_UNAVAILABLE @11 -ZITI_INVALID_AUTHENTICATOR_CERT @12 -ZITI_INVALID_AUTHENTICATOR_TYPE @13 -ZITI_INVALID_CERT_KEY_PAIR @14 -ZITI_INVALID_CONFIG @15 -ZITI_INVALID_POSTURE @16 -ZITI_INVALID_STATE @17 -ZITI_JWT_INVALID @18 -ZITI_JWT_INVALID_FORMAT @19 -ZITI_JWT_NOT_FOUND @20 -ZITI_JWT_SIGNING_ALG_UNSUPPORTED @21 -ZITI_JWT_VERIFICATION_FAILED @22 -ZITI_KEY_GENERATION_FAILED @23 -ZITI_KEY_LOAD_FAILED @24 -ZITI_MFA_EXISTS @25 -ZITI_MFA_INVALID_TOKEN @26 -ZITI_MFA_NOT_ENROLLED @27 -ZITI_NOT_AUTHORIZED @28 -ZITI_NOT_FOUND @29 -ZITI_OK @30 -ZITI_PARTIALLY_AUTHENTICATED @31 -ZITI_PKCS7_ASN1_PARSING_FAILED @32 -ZITI_SERVICE_UNAVAILABLE @33 -ZITI_TIMEOUT @34 -ZITI_WTF @35 -Ziti_accept @36 -Ziti_bind @37 -Ziti_connect @38 -Ziti_connect_addr @39 -Ziti_enroll_identity @40 -Ziti_free @41 -Ziti_freeaddrinfo @42 -Ziti_last_error @43 -Ziti_lib_init @44 -Ziti_lib_shutdown @45 -Ziti_lib_thread @46 -Ziti_listen @47 -Ziti_load_context @48 -Ziti_lookup @49 -Ziti_resolve @50 -Ziti_socket @51 -alloc_api_path @52 -alloc_ziti_address @53 -alloc_ziti_api_session @54 -alloc_ziti_api_versions @55 -alloc_ziti_auth_query_mfa @56 -alloc_ziti_auth_req @57 -alloc_ziti_authenticator @58 -alloc_ziti_client_cfg_v1 @59 -alloc_ziti_config @60 -alloc_ziti_edge_router @61 -alloc_ziti_enrollment_jwt @62 -alloc_ziti_enrollment_jwt_header @63 -alloc_ziti_enrollment_resp @64 -alloc_ziti_env_info @65 -alloc_ziti_error @66 -alloc_ziti_extend_cert_authenticator_req @67 -alloc_ziti_extend_cert_authenticator_resp @68 -alloc_ziti_host_cfg_v1 @69 -alloc_ziti_host_cfg_v2 @70 -alloc_ziti_id_cfg @71 -alloc_ziti_identity @72 -alloc_ziti_identity_data @73 -alloc_ziti_intercept_cfg_v1 @74 -alloc_ziti_listen_options @75 -alloc_ziti_mfa_code_req @76 -alloc_ziti_mfa_enrollment @77 -alloc_ziti_mfa_recovery_codes @78 -alloc_ziti_net_session @79 -alloc_ziti_port_range @80 -alloc_ziti_posture_query @81 -alloc_ziti_posture_query_set @82 -alloc_ziti_pr_domain_req @83 -alloc_ziti_pr_endpoint_state_req @84 -alloc_ziti_pr_mac_req @85 -alloc_ziti_pr_os_req @86 -alloc_ziti_pr_process @87 -alloc_ziti_pr_process_req @88 -alloc_ziti_pr_response @89 -alloc_ziti_process @90 -alloc_ziti_sdk_info @91 -alloc_ziti_server_cfg_v1 @92 -alloc_ziti_service @93 -alloc_ziti_service_timer @94 -alloc_ziti_service_update @95 -alloc_ziti_verify_extend_cert_authenticator_req @96 -alloc_ziti_version @97 -api_path_to_json @98 -api_path_to_json_r @99 -cmp_api_path @100 -cmp_ziti_address @101 -cmp_ziti_api_session @102 -cmp_ziti_api_versions @103 -cmp_ziti_auth_query_mfa @104 -cmp_ziti_auth_req @105 -cmp_ziti_authenticator @106 -cmp_ziti_client_cfg_v1 @107 -cmp_ziti_config @108 -cmp_ziti_edge_router @109 -cmp_ziti_enrollment_jwt @110 -cmp_ziti_enrollment_jwt_header @111 -cmp_ziti_enrollment_resp @112 -cmp_ziti_env_info @113 -cmp_ziti_error @114 -cmp_ziti_extend_cert_authenticator_req @115 -cmp_ziti_extend_cert_authenticator_resp @116 -cmp_ziti_host_cfg_v1 @117 -cmp_ziti_host_cfg_v2 @118 -cmp_ziti_id_cfg @119 -cmp_ziti_identity @120 -cmp_ziti_identity_data @121 -cmp_ziti_intercept_cfg_v1 @122 -cmp_ziti_listen_options @123 -cmp_ziti_mfa_code_req @124 -cmp_ziti_mfa_enrollment @125 -cmp_ziti_mfa_recovery_codes @126 -cmp_ziti_net_session @127 -cmp_ziti_port_range @128 -cmp_ziti_posture_query @129 -cmp_ziti_posture_query_set @130 -cmp_ziti_pr_domain_req @131 -cmp_ziti_pr_endpoint_state_req @132 -cmp_ziti_pr_mac_req @133 -cmp_ziti_pr_os_req @134 -cmp_ziti_pr_process @135 -cmp_ziti_pr_process_req @136 -cmp_ziti_pr_response @137 -cmp_ziti_process @138 -cmp_ziti_sdk_info @139 -cmp_ziti_server_cfg_v1 @140 -cmp_ziti_service @141 -cmp_ziti_service_timer @142 -cmp_ziti_service_update @143 -cmp_ziti_verify_extend_cert_authenticator_req @144 -cmp_ziti_version @145 -delete_string_buf @146 -free_api_path @147 -free_api_path_array @148 -free_api_path_ptr @149 -free_ziti_address @150 -free_ziti_address_array @151 -free_ziti_address_ptr @152 -free_ziti_api_session @153 -free_ziti_api_session_array @154 -free_ziti_api_session_ptr @155 -free_ziti_api_versions @156 -free_ziti_api_versions_array @157 -free_ziti_api_versions_ptr @158 -free_ziti_auth_query_mfa @159 -free_ziti_auth_query_mfa_array @160 -free_ziti_auth_query_mfa_ptr @161 -free_ziti_auth_req @162 -free_ziti_auth_req_array @163 -free_ziti_auth_req_ptr @164 -free_ziti_authenticator @165 -free_ziti_authenticator_array @166 -free_ziti_authenticator_ptr @167 -free_ziti_client_cfg_v1 @168 -free_ziti_client_cfg_v1_array @169 -free_ziti_client_cfg_v1_ptr @170 -free_ziti_config @171 -free_ziti_config_array @172 -free_ziti_config_ptr @173 -free_ziti_edge_router @174 -free_ziti_edge_router_array @175 -free_ziti_edge_router_ptr @176 -free_ziti_enrollment_jwt @177 -free_ziti_enrollment_jwt_array @178 -free_ziti_enrollment_jwt_header @179 -free_ziti_enrollment_jwt_header_array @180 -free_ziti_enrollment_jwt_header_ptr @181 -free_ziti_enrollment_jwt_ptr @182 -free_ziti_enrollment_resp @183 -free_ziti_enrollment_resp_array @184 -free_ziti_enrollment_resp_ptr @185 -free_ziti_env_info @186 -free_ziti_env_info_array @187 -free_ziti_env_info_ptr @188 -free_ziti_error @189 -free_ziti_error_array @190 -free_ziti_error_ptr @191 -free_ziti_extend_cert_authenticator_req @192 -free_ziti_extend_cert_authenticator_req_array @193 -free_ziti_extend_cert_authenticator_req_ptr @194 -free_ziti_extend_cert_authenticator_resp @195 -free_ziti_extend_cert_authenticator_resp_array @196 -free_ziti_extend_cert_authenticator_resp_ptr @197 -free_ziti_host_cfg_v1 @198 -free_ziti_host_cfg_v1_array @199 -free_ziti_host_cfg_v1_ptr @200 -free_ziti_host_cfg_v2 @201 -free_ziti_host_cfg_v2_array @202 -free_ziti_host_cfg_v2_ptr @203 -free_ziti_id_cfg @204 -free_ziti_id_cfg_array @205 -free_ziti_id_cfg_ptr @206 -free_ziti_identity @207 -free_ziti_identity_array @208 -free_ziti_identity_data @209 -free_ziti_identity_data_array @210 -free_ziti_identity_data_ptr @211 -free_ziti_identity_ptr @212 -free_ziti_intercept_cfg_v1 @213 -free_ziti_intercept_cfg_v1_array @214 -free_ziti_intercept_cfg_v1_ptr @215 -free_ziti_listen_options @216 -free_ziti_listen_options_array @217 -free_ziti_listen_options_ptr @218 -free_ziti_mfa_code_req @219 -free_ziti_mfa_code_req_array @220 -free_ziti_mfa_code_req_ptr @221 -free_ziti_mfa_enrollment @222 -free_ziti_mfa_enrollment_array @223 -free_ziti_mfa_enrollment_ptr @224 -free_ziti_mfa_recovery_codes @225 -free_ziti_mfa_recovery_codes_array @226 -free_ziti_mfa_recovery_codes_ptr @227 -free_ziti_net_session @228 -free_ziti_net_session_array @229 -free_ziti_net_session_ptr @230 -free_ziti_port_range @231 -free_ziti_port_range_array @232 -free_ziti_port_range_ptr @233 -free_ziti_posture_query @234 -free_ziti_posture_query_array @235 -free_ziti_posture_query_ptr @236 -free_ziti_posture_query_set @237 -free_ziti_posture_query_set_array @238 -free_ziti_posture_query_set_ptr @239 -free_ziti_pr_domain_req @240 -free_ziti_pr_domain_req_array @241 -free_ziti_pr_domain_req_ptr @242 -free_ziti_pr_endpoint_state_req @243 -free_ziti_pr_endpoint_state_req_array @244 -free_ziti_pr_endpoint_state_req_ptr @245 -free_ziti_pr_mac_req @246 -free_ziti_pr_mac_req_array @247 -free_ziti_pr_mac_req_ptr @248 -free_ziti_pr_os_req @249 -free_ziti_pr_os_req_array @250 -free_ziti_pr_os_req_ptr @251 -free_ziti_pr_process @252 -free_ziti_pr_process_array @253 -free_ziti_pr_process_ptr @254 -free_ziti_pr_process_req @255 -free_ziti_pr_process_req_array @256 -free_ziti_pr_process_req_ptr @257 -free_ziti_pr_response @258 -free_ziti_pr_response_array @259 -free_ziti_pr_response_ptr @260 -free_ziti_process @261 -free_ziti_process_array @262 -free_ziti_process_ptr @263 -free_ziti_sdk_info @264 -free_ziti_sdk_info_array @265 -free_ziti_sdk_info_ptr @266 -free_ziti_server_cfg_v1 @267 -free_ziti_server_cfg_v1_array @268 -free_ziti_server_cfg_v1_ptr @269 -free_ziti_service @270 -free_ziti_service_array @271 -free_ziti_service_ptr @272 -free_ziti_service_timer @273 -free_ziti_service_timer_array @274 -free_ziti_service_timer_ptr @275 -free_ziti_service_update @276 -free_ziti_service_update_array @277 -free_ziti_service_update_ptr @278 -free_ziti_verify_extend_cert_authenticator_req @279 -free_ziti_verify_extend_cert_authenticator_req_array @280 -free_ziti_verify_extend_cert_authenticator_req_ptr @281 -free_ziti_version @282 -free_ziti_version_array @283 -free_ziti_version_ptr @284 -get_api_path_meta @285 -get_bool_meta @286 -get_duration_meta @287 -get_int_meta @288 -get_json_meta @289 -get_model_map_meta @290 -get_string_meta @291 -get_tag_meta @292 -get_timestamp_meta @293 -get_ziti_address_meta @294 -get_ziti_api_session_meta @295 -get_ziti_api_versions_meta @296 -get_ziti_auth_query_mfa_meta @297 -get_ziti_auth_req_meta @298 -get_ziti_authenticator_meta @299 -get_ziti_client_cfg_v1_meta @300 -get_ziti_config_meta @301 -get_ziti_edge_router_meta @302 -get_ziti_enrollment_jwt_header_meta @303 -get_ziti_enrollment_jwt_meta @304 -get_ziti_enrollment_resp_meta @305 -get_ziti_env_info_meta @306 -get_ziti_error_meta @307 -get_ziti_extend_cert_authenticator_req_meta @308 -get_ziti_extend_cert_authenticator_resp_meta @309 -get_ziti_host_cfg_v1_meta @310 -get_ziti_host_cfg_v2_meta @311 -get_ziti_id_cfg_meta @312 -get_ziti_identity_data_meta @313 -get_ziti_identity_meta @314 -get_ziti_intercept_cfg_v1_meta @315 -get_ziti_listen_options_meta @316 -get_ziti_mfa_code_req_meta @317 -get_ziti_mfa_enrollment_meta @318 -get_ziti_mfa_recovery_codes_meta @319 -get_ziti_net_session_meta @320 -get_ziti_port_range_meta @321 -get_ziti_posture_query_meta @322 -get_ziti_posture_query_set_meta @323 -get_ziti_pr_domain_req_meta @324 -get_ziti_pr_endpoint_state_req_meta @325 -get_ziti_pr_mac_req_meta @326 -get_ziti_pr_os_req_meta @327 -get_ziti_pr_process_meta @328 -get_ziti_pr_process_req_meta @329 -get_ziti_pr_response_meta @330 -get_ziti_process_meta @331 -get_ziti_protocol_meta @332 -get_ziti_sdk_info_meta @333 -get_ziti_server_cfg_v1_meta @334 -get_ziti_service_meta @335 -get_ziti_service_timer_meta @336 -get_ziti_service_update_meta @337 -get_ziti_session_type_meta @338 -get_ziti_verify_extend_cert_authenticator_req_meta @339 -get_ziti_version_meta @340 -json_enum @341 -model_cmp @342 -model_free @343 -model_free_array @344 -model_list_append @345 -model_list_clear @346 -model_list_head @347 -model_list_it_element @348 -model_list_it_next @349 -model_list_it_remove @350 -model_list_iterator @351 -model_list_pop @352 -model_list_size @353 -model_map_clear @354 -model_map_get @355 -model_map_get_key @356 -model_map_getl @357 -model_map_it_key @358 -model_map_it_key_s @359 -model_map_it_lkey @360 -model_map_it_next @361 -model_map_it_remove @362 -model_map_it_value @363 -model_map_iterator @364 -model_map_remove @365 -model_map_remove_key @366 -model_map_removel @367 -model_map_set @368 -model_map_set_key @369 -model_map_setl @370 -model_map_size @371 -model_parse @372 -model_parse_array @373 -model_parse_list @374 -model_to_json @375 -model_to_json_r @376 -new_fixed_string_buf @377 -new_string_buf @378 -parse_api_path @379 -parse_api_path_array @380 -parse_api_path_list @381 -parse_api_path_ptr @382 -parse_enum @383 -parse_ziti_address @384 -parse_ziti_address_array @385 -parse_ziti_address_list @386 -parse_ziti_address_ptr @387 -parse_ziti_address_str @388 -parse_ziti_api_session @389 -parse_ziti_api_session_array @390 -parse_ziti_api_session_list @391 -parse_ziti_api_session_ptr @392 -parse_ziti_api_versions @393 -parse_ziti_api_versions_array @394 -parse_ziti_api_versions_list @395 -parse_ziti_api_versions_ptr @396 -parse_ziti_auth_query_mfa @397 -parse_ziti_auth_query_mfa_array @398 -parse_ziti_auth_query_mfa_list @399 -parse_ziti_auth_query_mfa_ptr @400 -parse_ziti_auth_req @401 -parse_ziti_auth_req_array @402 -parse_ziti_auth_req_list @403 -parse_ziti_auth_req_ptr @404 -parse_ziti_authenticator @405 -parse_ziti_authenticator_array @406 -parse_ziti_authenticator_list @407 -parse_ziti_authenticator_ptr @408 -parse_ziti_client_cfg_v1 @409 -parse_ziti_client_cfg_v1_array @410 -parse_ziti_client_cfg_v1_list @411 -parse_ziti_client_cfg_v1_ptr @412 -parse_ziti_config @413 -parse_ziti_config_array @414 -parse_ziti_config_list @415 -parse_ziti_config_ptr @416 -parse_ziti_edge_router @417 -parse_ziti_edge_router_array @418 -parse_ziti_edge_router_list @419 -parse_ziti_edge_router_ptr @420 -parse_ziti_enrollment_jwt @421 -parse_ziti_enrollment_jwt_array @422 -parse_ziti_enrollment_jwt_header @423 -parse_ziti_enrollment_jwt_header_array @424 -parse_ziti_enrollment_jwt_header_list @425 -parse_ziti_enrollment_jwt_header_ptr @426 -parse_ziti_enrollment_jwt_list @427 -parse_ziti_enrollment_jwt_ptr @428 -parse_ziti_enrollment_resp @429 -parse_ziti_enrollment_resp_array @430 -parse_ziti_enrollment_resp_list @431 -parse_ziti_enrollment_resp_ptr @432 -parse_ziti_env_info @433 -parse_ziti_env_info_array @434 -parse_ziti_env_info_list @435 -parse_ziti_env_info_ptr @436 -parse_ziti_error @437 -parse_ziti_error_array @438 -parse_ziti_error_list @439 -parse_ziti_error_ptr @440 -parse_ziti_extend_cert_authenticator_req @441 -parse_ziti_extend_cert_authenticator_req_array @442 -parse_ziti_extend_cert_authenticator_req_list @443 -parse_ziti_extend_cert_authenticator_req_ptr @444 -parse_ziti_extend_cert_authenticator_resp @445 -parse_ziti_extend_cert_authenticator_resp_array @446 -parse_ziti_extend_cert_authenticator_resp_list @447 -parse_ziti_extend_cert_authenticator_resp_ptr @448 -parse_ziti_host_cfg_v1 @449 -parse_ziti_host_cfg_v1_array @450 -parse_ziti_host_cfg_v1_list @451 -parse_ziti_host_cfg_v1_ptr @452 -parse_ziti_host_cfg_v2 @453 -parse_ziti_host_cfg_v2_array @454 -parse_ziti_host_cfg_v2_list @455 -parse_ziti_host_cfg_v2_ptr @456 -parse_ziti_id_cfg @457 -parse_ziti_id_cfg_array @458 -parse_ziti_id_cfg_list @459 -parse_ziti_id_cfg_ptr @460 -parse_ziti_identity @461 -parse_ziti_identity_array @462 -parse_ziti_identity_data @463 -parse_ziti_identity_data_array @464 -parse_ziti_identity_data_list @465 -parse_ziti_identity_data_ptr @466 -parse_ziti_identity_list @467 -parse_ziti_identity_ptr @468 -parse_ziti_intercept_cfg_v1 @469 -parse_ziti_intercept_cfg_v1_array @470 -parse_ziti_intercept_cfg_v1_list @471 -parse_ziti_intercept_cfg_v1_ptr @472 -parse_ziti_listen_options @473 -parse_ziti_listen_options_array @474 -parse_ziti_listen_options_list @475 -parse_ziti_listen_options_ptr @476 -parse_ziti_mfa_code_req @477 -parse_ziti_mfa_code_req_array @478 -parse_ziti_mfa_code_req_list @479 -parse_ziti_mfa_code_req_ptr @480 -parse_ziti_mfa_enrollment @481 -parse_ziti_mfa_enrollment_array @482 -parse_ziti_mfa_enrollment_list @483 -parse_ziti_mfa_enrollment_ptr @484 -parse_ziti_mfa_recovery_codes @485 -parse_ziti_mfa_recovery_codes_array @486 -parse_ziti_mfa_recovery_codes_list @487 -parse_ziti_mfa_recovery_codes_ptr @488 -parse_ziti_net_session @489 -parse_ziti_net_session_array @490 -parse_ziti_net_session_list @491 -parse_ziti_net_session_ptr @492 -parse_ziti_port_range @493 -parse_ziti_port_range_array @494 -parse_ziti_port_range_list @495 -parse_ziti_port_range_ptr @496 -parse_ziti_posture_query @497 -parse_ziti_posture_query_array @498 -parse_ziti_posture_query_list @499 -parse_ziti_posture_query_ptr @500 -parse_ziti_posture_query_set @501 -parse_ziti_posture_query_set_array @502 -parse_ziti_posture_query_set_list @503 -parse_ziti_posture_query_set_ptr @504 -parse_ziti_pr_domain_req @505 -parse_ziti_pr_domain_req_array @506 -parse_ziti_pr_domain_req_list @507 -parse_ziti_pr_domain_req_ptr @508 -parse_ziti_pr_endpoint_state_req @509 -parse_ziti_pr_endpoint_state_req_array @510 -parse_ziti_pr_endpoint_state_req_list @511 -parse_ziti_pr_endpoint_state_req_ptr @512 -parse_ziti_pr_mac_req @513 -parse_ziti_pr_mac_req_array @514 -parse_ziti_pr_mac_req_list @515 -parse_ziti_pr_mac_req_ptr @516 -parse_ziti_pr_os_req @517 -parse_ziti_pr_os_req_array @518 -parse_ziti_pr_os_req_list @519 -parse_ziti_pr_os_req_ptr @520 -parse_ziti_pr_process @521 -parse_ziti_pr_process_array @522 -parse_ziti_pr_process_list @523 -parse_ziti_pr_process_ptr @524 -parse_ziti_pr_process_req @525 -parse_ziti_pr_process_req_array @526 -parse_ziti_pr_process_req_list @527 -parse_ziti_pr_process_req_ptr @528 -parse_ziti_pr_response @529 -parse_ziti_pr_response_array @530 -parse_ziti_pr_response_list @531 -parse_ziti_pr_response_ptr @532 -parse_ziti_process @533 -parse_ziti_process_array @534 -parse_ziti_process_list @535 -parse_ziti_process_ptr @536 -parse_ziti_sdk_info @537 -parse_ziti_sdk_info_array @538 -parse_ziti_sdk_info_list @539 -parse_ziti_sdk_info_ptr @540 -parse_ziti_server_cfg_v1 @541 -parse_ziti_server_cfg_v1_array @542 -parse_ziti_server_cfg_v1_list @543 -parse_ziti_server_cfg_v1_ptr @544 -parse_ziti_service @545 -parse_ziti_service_array @546 -parse_ziti_service_list @547 -parse_ziti_service_ptr @548 -parse_ziti_service_timer @549 -parse_ziti_service_timer_array @550 -parse_ziti_service_timer_list @551 -parse_ziti_service_timer_ptr @552 -parse_ziti_service_update @553 -parse_ziti_service_update_array @554 -parse_ziti_service_update_list @555 -parse_ziti_service_update_ptr @556 -parse_ziti_verify_extend_cert_authenticator_req @557 -parse_ziti_verify_extend_cert_authenticator_req_array @558 -parse_ziti_verify_extend_cert_authenticator_req_list @559 -parse_ziti_verify_extend_cert_authenticator_req_ptr @560 -parse_ziti_version @561 -parse_ziti_version_array @562 -parse_ziti_version_list @563 -parse_ziti_version_ptr @564 -string_buf_append @565 -string_buf_append_byte @566 -string_buf_appendn @567 -string_buf_fmt @568 -string_buf_size @569 -string_buf_to_string @570 -uv_mbed_logger @571 -ziti_accept @572 -ziti_address_match @573 -ziti_address_match_array @574 -ziti_address_match_list @575 -ziti_address_match_s @576 -ziti_address_print @577 -ziti_address_to_json @578 -ziti_address_to_json_r @579 -ziti_addrstr_match_list @580 -ziti_api_session_to_json @581 -ziti_api_session_to_json_r @582 -ziti_api_versions_to_json @583 -ziti_api_versions_to_json_r @584 -ziti_app_ctx @585 -ziti_auth_query_mfa_to_json @586 -ziti_auth_query_mfa_to_json_r @587 -ziti_auth_req_to_json @588 -ziti_auth_req_to_json_r @589 -ziti_authenticator_to_json @590 -ziti_authenticator_to_json_r @591 -ziti_client_cfg_v1_to_json @592 -ziti_client_cfg_v1_to_json_r @593 -ziti_close @594 -ziti_close_write @595 -ziti_config_to_json @596 -ziti_config_to_json_r @597 -ziti_conn_bridge @598 -ziti_conn_bridge_fds @599 -ziti_conn_context @600 -ziti_conn_data @601 -ziti_conn_init @602 -ziti_conn_set_data @603 -ziti_conn_set_data_cb @604 -ziti_conn_source_identity @605 -ziti_dial @606 -ziti_dial_with_options @607 -ziti_dump @608 -ziti_edge_router_to_json @609 -ziti_edge_router_to_json_r @610 -ziti_endpoint_state_change @611 -ziti_enroll @612 -ziti_enrollment_jwt_header_to_json @613 -ziti_enrollment_jwt_header_to_json_r @614 -ziti_enrollment_jwt_to_json @615 -ziti_enrollment_jwt_to_json_r @616 -ziti_enrollment_resp_to_json @617 -ziti_enrollment_resp_to_json_r @618 -ziti_env_info_to_json @619 -ziti_env_info_to_json_r @620 -ziti_error_to_json @621 -ziti_error_to_json_r @622 -ziti_errorstr @623 -ziti_extend_cert_authenticator @624 -ziti_extend_cert_authenticator_req_to_json @625 -ziti_extend_cert_authenticator_req_to_json_r @626 -ziti_extend_cert_authenticator_resp_to_json @627 -ziti_extend_cert_authenticator_resp_to_json_r @628 -ziti_get_appdata @629 -ziti_get_appdata_raw @630 -ziti_get_controller @631 -ziti_get_controller_version @632 -ziti_get_identity @633 -ziti_get_transfer_rates @634 -ziti_get_version @635 -ziti_host_cfg_v1_to_json @636 -ziti_host_cfg_v1_to_json_r @637 -ziti_host_cfg_v2_to_json @638 -ziti_host_cfg_v2_to_json_r @639 -ziti_id_cfg_to_json @640 -ziti_id_cfg_to_json_r @641 -ziti_identity_data_to_json @642 -ziti_identity_data_to_json_r @643 -ziti_identity_to_json @644 -ziti_identity_to_json_r @645 -ziti_init @646 -ziti_init_opts @647 -ziti_intercept_cfg_v1_to_json @648 -ziti_intercept_cfg_v1_to_json_r @649 -ziti_intercept_from_client_cfg @650 -ziti_intercept_match @651 -ziti_intercept_match2 @652 -ziti_is_enabled @653 -ziti_listen @654 -ziti_listen_options_to_json @655 -ziti_listen_options_to_json_r @656 -ziti_listen_with_options @657 -ziti_log_init @658 -ziti_log_level @659 -ziti_log_level_label @660 -ziti_log_set_level @661 -ziti_log_set_level_by_label @662 -ziti_log_set_logger @663 -ziti_logger @664 -ziti_mfa_auth @665 -ziti_mfa_code_req_to_json @666 -ziti_mfa_code_req_to_json_r @667 -ziti_mfa_enroll @668 -ziti_mfa_enrollment_to_json @669 -ziti_mfa_enrollment_to_json_r @670 -ziti_mfa_get_recovery_codes @671 -ziti_mfa_new_recovery_codes @672 -ziti_mfa_recovery_codes_to_json @673 -ziti_mfa_recovery_codes_to_json_r @674 -ziti_mfa_remove @675 -ziti_mfa_verify @676 -ziti_net_session_to_json @677 -ziti_net_session_to_json_r @678 -ziti_port_match @679 -ziti_port_range_to_json @680 -ziti_port_range_to_json_r @681 -ziti_posture_query_set_to_json @682 -ziti_posture_query_set_to_json_r @683 -ziti_posture_query_to_json @684 -ziti_posture_query_to_json_r @685 -ziti_pr_domain_req_to_json @686 -ziti_pr_domain_req_to_json_r @687 -ziti_pr_endpoint_state_req_to_json @688 -ziti_pr_endpoint_state_req_to_json_r @689 -ziti_pr_mac_req_to_json @690 -ziti_pr_mac_req_to_json_r @691 -ziti_pr_os_req_to_json @692 -ziti_pr_os_req_to_json_r @693 -ziti_pr_process_req_to_json @694 -ziti_pr_process_req_to_json_r @695 -ziti_pr_process_to_json @696 -ziti_pr_process_to_json_r @697 -ziti_pr_response_to_json @698 -ziti_pr_response_to_json_r @699 -ziti_process_to_json @700 -ziti_process_to_json_r @701 -ziti_protocol_match @702 -ziti_sdk_info_to_json @703 -ziti_sdk_info_to_json_r @704 -ziti_server_cfg_v1_to_json @705 -ziti_server_cfg_v1_to_json_r @706 -ziti_service_available @707 -ziti_service_for_addr @708 -ziti_service_for_addr_str @709 -ziti_service_get_config @710 -ziti_service_get_raw_config @711 -ziti_service_timer_to_json @712 -ziti_service_timer_to_json_r @713 -ziti_service_to_json @714 -ziti_service_to_json_r @715 -ziti_service_update_to_json @716 -ziti_service_update_to_json_r @717 -ziti_set_app_info @718 -ziti_set_client_cert @719 -ziti_set_enabled @720 -ziti_set_timeout @721 -ziti_shutdown @722 -ziti_verify_extend_cert_authenticator @723 -ziti_verify_extend_cert_authenticator_req_to_json @724 -ziti_verify_extend_cert_authenticator_req_to_json_r @725 -ziti_version_to_json @726 -ziti_version_to_json_r @727 -ziti_write @728 +Ziti_accept @1 +Ziti_bind @2 +Ziti_check_socket @3 +Ziti_close @4 +Ziti_connect @5 +Ziti_connect_addr @6 +Ziti_enroll_identity @7 +Ziti_free @8 +Ziti_freeaddrinfo @9 +Ziti_last_error @10 +Ziti_lib_init @11 +Ziti_lib_shutdown @12 +Ziti_lib_thread @13 +Ziti_listen @14 +Ziti_load_context @15 +Ziti_lookup @16 +Ziti_resolve @17 +Ziti_socket @18 +alloc_api_path @19 +alloc_ziti_address @20 +alloc_ziti_api_session @21 +alloc_ziti_api_versions @22 +alloc_ziti_auth_query_mfa @23 +alloc_ziti_auth_req @24 +alloc_ziti_authenticator @25 +alloc_ziti_client_cfg_v1 @26 +alloc_ziti_config @27 +alloc_ziti_create_api_cert_req @28 +alloc_ziti_create_api_cert_resp @29 +alloc_ziti_edge_router @30 +alloc_ziti_enrollment_jwt @31 +alloc_ziti_enrollment_jwt_header @32 +alloc_ziti_enrollment_resp @33 +alloc_ziti_env_info @34 +alloc_ziti_error @35 +alloc_ziti_extend_cert_authenticator_req @36 +alloc_ziti_extend_cert_authenticator_resp @37 +alloc_ziti_host_cfg_v1 @38 +alloc_ziti_host_cfg_v2 @39 +alloc_ziti_id_cfg @40 +alloc_ziti_identity @41 +alloc_ziti_identity_data @42 +alloc_ziti_intercept_cfg_v1 @43 +alloc_ziti_listen_options @44 +alloc_ziti_mfa_code_req @45 +alloc_ziti_mfa_enrollment @46 +alloc_ziti_mfa_recovery_codes @47 +alloc_ziti_net_session @48 +alloc_ziti_port_range @49 +alloc_ziti_posture_query @50 +alloc_ziti_posture_query_set @51 +alloc_ziti_pr_domain_req @52 +alloc_ziti_pr_endpoint_state_req @53 +alloc_ziti_pr_mac_req @54 +alloc_ziti_pr_os_req @55 +alloc_ziti_pr_process @56 +alloc_ziti_pr_process_req @57 +alloc_ziti_pr_response @58 +alloc_ziti_process @59 +alloc_ziti_sdk_info @60 +alloc_ziti_server_cfg_v1 @61 +alloc_ziti_service @62 +alloc_ziti_service_timer @63 +alloc_ziti_service_update @64 +alloc_ziti_verify_extend_cert_authenticator_req @65 +alloc_ziti_version @66 +api_path_to_json @67 +api_path_to_json_r @68 +cmp_api_path @69 +cmp_ziti_address @70 +cmp_ziti_api_session @71 +cmp_ziti_api_versions @72 +cmp_ziti_auth_query_mfa @73 +cmp_ziti_auth_req @74 +cmp_ziti_authenticator @75 +cmp_ziti_client_cfg_v1 @76 +cmp_ziti_config @77 +cmp_ziti_create_api_cert_req @78 +cmp_ziti_create_api_cert_resp @79 +cmp_ziti_edge_router @80 +cmp_ziti_enrollment_jwt @81 +cmp_ziti_enrollment_jwt_header @82 +cmp_ziti_enrollment_resp @83 +cmp_ziti_env_info @84 +cmp_ziti_error @85 +cmp_ziti_extend_cert_authenticator_req @86 +cmp_ziti_extend_cert_authenticator_resp @87 +cmp_ziti_host_cfg_v1 @88 +cmp_ziti_host_cfg_v2 @89 +cmp_ziti_id_cfg @90 +cmp_ziti_identity @91 +cmp_ziti_identity_data @92 +cmp_ziti_intercept_cfg_v1 @93 +cmp_ziti_listen_options @94 +cmp_ziti_mfa_code_req @95 +cmp_ziti_mfa_enrollment @96 +cmp_ziti_mfa_recovery_codes @97 +cmp_ziti_net_session @98 +cmp_ziti_port_range @99 +cmp_ziti_posture_query @100 +cmp_ziti_posture_query_set @101 +cmp_ziti_pr_domain_req @102 +cmp_ziti_pr_endpoint_state_req @103 +cmp_ziti_pr_mac_req @104 +cmp_ziti_pr_os_req @105 +cmp_ziti_pr_process @106 +cmp_ziti_pr_process_req @107 +cmp_ziti_pr_response @108 +cmp_ziti_process @109 +cmp_ziti_sdk_info @110 +cmp_ziti_server_cfg_v1 @111 +cmp_ziti_service @112 +cmp_ziti_service_timer @113 +cmp_ziti_service_update @114 +cmp_ziti_verify_extend_cert_authenticator_req @115 +cmp_ziti_version @116 +delete_string_buf @117 +free_api_path @118 +free_api_path_array @119 +free_api_path_ptr @120 +free_ziti_address @121 +free_ziti_address_array @122 +free_ziti_address_ptr @123 +free_ziti_api_session @124 +free_ziti_api_session_array @125 +free_ziti_api_session_ptr @126 +free_ziti_api_versions @127 +free_ziti_api_versions_array @128 +free_ziti_api_versions_ptr @129 +free_ziti_auth_query_mfa @130 +free_ziti_auth_query_mfa_array @131 +free_ziti_auth_query_mfa_ptr @132 +free_ziti_auth_req @133 +free_ziti_auth_req_array @134 +free_ziti_auth_req_ptr @135 +free_ziti_authenticator @136 +free_ziti_authenticator_array @137 +free_ziti_authenticator_ptr @138 +free_ziti_client_cfg_v1 @139 +free_ziti_client_cfg_v1_array @140 +free_ziti_client_cfg_v1_ptr @141 +free_ziti_config @142 +free_ziti_config_array @143 +free_ziti_config_ptr @144 +free_ziti_create_api_cert_req @145 +free_ziti_create_api_cert_req_array @146 +free_ziti_create_api_cert_req_ptr @147 +free_ziti_create_api_cert_resp @148 +free_ziti_create_api_cert_resp_array @149 +free_ziti_create_api_cert_resp_ptr @150 +free_ziti_edge_router @151 +free_ziti_edge_router_array @152 +free_ziti_edge_router_ptr @153 +free_ziti_enrollment_jwt @154 +free_ziti_enrollment_jwt_array @155 +free_ziti_enrollment_jwt_header @156 +free_ziti_enrollment_jwt_header_array @157 +free_ziti_enrollment_jwt_header_ptr @158 +free_ziti_enrollment_jwt_ptr @159 +free_ziti_enrollment_resp @160 +free_ziti_enrollment_resp_array @161 +free_ziti_enrollment_resp_ptr @162 +free_ziti_env_info @163 +free_ziti_env_info_array @164 +free_ziti_env_info_ptr @165 +free_ziti_error @166 +free_ziti_error_array @167 +free_ziti_error_ptr @168 +free_ziti_extend_cert_authenticator_req @169 +free_ziti_extend_cert_authenticator_req_array @170 +free_ziti_extend_cert_authenticator_req_ptr @171 +free_ziti_extend_cert_authenticator_resp @172 +free_ziti_extend_cert_authenticator_resp_array @173 +free_ziti_extend_cert_authenticator_resp_ptr @174 +free_ziti_host_cfg_v1 @175 +free_ziti_host_cfg_v1_array @176 +free_ziti_host_cfg_v1_ptr @177 +free_ziti_host_cfg_v2 @178 +free_ziti_host_cfg_v2_array @179 +free_ziti_host_cfg_v2_ptr @180 +free_ziti_id_cfg @181 +free_ziti_id_cfg_array @182 +free_ziti_id_cfg_ptr @183 +free_ziti_identity @184 +free_ziti_identity_array @185 +free_ziti_identity_data @186 +free_ziti_identity_data_array @187 +free_ziti_identity_data_ptr @188 +free_ziti_identity_ptr @189 +free_ziti_intercept_cfg_v1 @190 +free_ziti_intercept_cfg_v1_array @191 +free_ziti_intercept_cfg_v1_ptr @192 +free_ziti_listen_options @193 +free_ziti_listen_options_array @194 +free_ziti_listen_options_ptr @195 +free_ziti_mfa_code_req @196 +free_ziti_mfa_code_req_array @197 +free_ziti_mfa_code_req_ptr @198 +free_ziti_mfa_enrollment @199 +free_ziti_mfa_enrollment_array @200 +free_ziti_mfa_enrollment_ptr @201 +free_ziti_mfa_recovery_codes @202 +free_ziti_mfa_recovery_codes_array @203 +free_ziti_mfa_recovery_codes_ptr @204 +free_ziti_net_session @205 +free_ziti_net_session_array @206 +free_ziti_net_session_ptr @207 +free_ziti_port_range @208 +free_ziti_port_range_array @209 +free_ziti_port_range_ptr @210 +free_ziti_posture_query @211 +free_ziti_posture_query_array @212 +free_ziti_posture_query_ptr @213 +free_ziti_posture_query_set @214 +free_ziti_posture_query_set_array @215 +free_ziti_posture_query_set_ptr @216 +free_ziti_pr_domain_req @217 +free_ziti_pr_domain_req_array @218 +free_ziti_pr_domain_req_ptr @219 +free_ziti_pr_endpoint_state_req @220 +free_ziti_pr_endpoint_state_req_array @221 +free_ziti_pr_endpoint_state_req_ptr @222 +free_ziti_pr_mac_req @223 +free_ziti_pr_mac_req_array @224 +free_ziti_pr_mac_req_ptr @225 +free_ziti_pr_os_req @226 +free_ziti_pr_os_req_array @227 +free_ziti_pr_os_req_ptr @228 +free_ziti_pr_process @229 +free_ziti_pr_process_array @230 +free_ziti_pr_process_ptr @231 +free_ziti_pr_process_req @232 +free_ziti_pr_process_req_array @233 +free_ziti_pr_process_req_ptr @234 +free_ziti_pr_response @235 +free_ziti_pr_response_array @236 +free_ziti_pr_response_ptr @237 +free_ziti_process @238 +free_ziti_process_array @239 +free_ziti_process_ptr @240 +free_ziti_sdk_info @241 +free_ziti_sdk_info_array @242 +free_ziti_sdk_info_ptr @243 +free_ziti_server_cfg_v1 @244 +free_ziti_server_cfg_v1_array @245 +free_ziti_server_cfg_v1_ptr @246 +free_ziti_service @247 +free_ziti_service_array @248 +free_ziti_service_ptr @249 +free_ziti_service_timer @250 +free_ziti_service_timer_array @251 +free_ziti_service_timer_ptr @252 +free_ziti_service_update @253 +free_ziti_service_update_array @254 +free_ziti_service_update_ptr @255 +free_ziti_verify_extend_cert_authenticator_req @256 +free_ziti_verify_extend_cert_authenticator_req_array @257 +free_ziti_verify_extend_cert_authenticator_req_ptr @258 +free_ziti_version @259 +free_ziti_version_array @260 +free_ziti_version_ptr @261 +get_api_path_meta @262 +get_bool_meta @263 +get_duration_meta @264 +get_int_meta @265 +get_json_meta @266 +get_model_map_meta @267 +get_string_meta @268 +get_tag_meta @269 +get_timestamp_meta @270 +get_ziti_address_meta @271 +get_ziti_api_session_meta @272 +get_ziti_api_versions_meta @273 +get_ziti_auth_query_mfa_meta @274 +get_ziti_auth_req_meta @275 +get_ziti_authenticator_meta @276 +get_ziti_client_cfg_v1_meta @277 +get_ziti_config_meta @278 +get_ziti_create_api_cert_req_meta @279 +get_ziti_create_api_cert_resp_meta @280 +get_ziti_edge_router_meta @281 +get_ziti_enrollment_jwt_header_meta @282 +get_ziti_enrollment_jwt_meta @283 +get_ziti_enrollment_method_meta @284 +get_ziti_enrollment_resp_meta @285 +get_ziti_env_info_meta @286 +get_ziti_error_meta @287 +get_ziti_extend_cert_authenticator_req_meta @288 +get_ziti_extend_cert_authenticator_resp_meta @289 +get_ziti_host_cfg_v1_meta @290 +get_ziti_host_cfg_v2_meta @291 +get_ziti_id_cfg_meta @292 +get_ziti_identity_data_meta @293 +get_ziti_identity_meta @294 +get_ziti_intercept_cfg_v1_meta @295 +get_ziti_listen_options_meta @296 +get_ziti_mfa_code_req_meta @297 +get_ziti_mfa_enrollment_meta @298 +get_ziti_mfa_recovery_codes_meta @299 +get_ziti_net_session_meta @300 +get_ziti_port_range_meta @301 +get_ziti_posture_query_meta @302 +get_ziti_posture_query_set_meta @303 +get_ziti_pr_domain_req_meta @304 +get_ziti_pr_endpoint_state_req_meta @305 +get_ziti_pr_mac_req_meta @306 +get_ziti_pr_os_req_meta @307 +get_ziti_pr_process_meta @308 +get_ziti_pr_process_req_meta @309 +get_ziti_pr_response_meta @310 +get_ziti_process_meta @311 +get_ziti_protocol_meta @312 +get_ziti_sdk_info_meta @313 +get_ziti_server_cfg_v1_meta @314 +get_ziti_service_meta @315 +get_ziti_service_timer_meta @316 +get_ziti_service_update_meta @317 +get_ziti_session_type_meta @318 +get_ziti_verify_extend_cert_authenticator_req_meta @319 +get_ziti_version_meta @320 +json_enum @321 +model_cmp @322 +model_free @323 +model_free_array @324 +model_list_append @325 +model_list_clear @326 +model_list_head @327 +model_list_it_element @328 +model_list_it_next @329 +model_list_it_remove @330 +model_list_iterator @331 +model_list_pop @332 +model_list_size @333 +model_map_clear @334 +model_map_get @335 +model_map_get_key @336 +model_map_getl @337 +model_map_it_key @338 +model_map_it_key_s @339 +model_map_it_lkey @340 +model_map_it_next @341 +model_map_it_remove @342 +model_map_it_value @343 +model_map_iterator @344 +model_map_remove @345 +model_map_remove_key @346 +model_map_removel @347 +model_map_set @348 +model_map_set_key @349 +model_map_setl @350 +model_map_size @351 +model_parse @352 +model_parse_array @353 +model_parse_list @354 +model_to_json @355 +model_to_json_r @356 +new_fixed_string_buf @357 +new_string_buf @358 +parse_api_path @359 +parse_api_path_array @360 +parse_api_path_list @361 +parse_api_path_ptr @362 +parse_enum @363 +parse_ziti_address @364 +parse_ziti_address_array @365 +parse_ziti_address_list @366 +parse_ziti_address_ptr @367 +parse_ziti_address_str @368 +parse_ziti_api_session @369 +parse_ziti_api_session_array @370 +parse_ziti_api_session_list @371 +parse_ziti_api_session_ptr @372 +parse_ziti_api_versions @373 +parse_ziti_api_versions_array @374 +parse_ziti_api_versions_list @375 +parse_ziti_api_versions_ptr @376 +parse_ziti_auth_query_mfa @377 +parse_ziti_auth_query_mfa_array @378 +parse_ziti_auth_query_mfa_list @379 +parse_ziti_auth_query_mfa_ptr @380 +parse_ziti_auth_req @381 +parse_ziti_auth_req_array @382 +parse_ziti_auth_req_list @383 +parse_ziti_auth_req_ptr @384 +parse_ziti_authenticator @385 +parse_ziti_authenticator_array @386 +parse_ziti_authenticator_list @387 +parse_ziti_authenticator_ptr @388 +parse_ziti_client_cfg_v1 @389 +parse_ziti_client_cfg_v1_array @390 +parse_ziti_client_cfg_v1_list @391 +parse_ziti_client_cfg_v1_ptr @392 +parse_ziti_config @393 +parse_ziti_config_array @394 +parse_ziti_config_list @395 +parse_ziti_config_ptr @396 +parse_ziti_create_api_cert_req @397 +parse_ziti_create_api_cert_req_array @398 +parse_ziti_create_api_cert_req_list @399 +parse_ziti_create_api_cert_req_ptr @400 +parse_ziti_create_api_cert_resp @401 +parse_ziti_create_api_cert_resp_array @402 +parse_ziti_create_api_cert_resp_list @403 +parse_ziti_create_api_cert_resp_ptr @404 +parse_ziti_edge_router @405 +parse_ziti_edge_router_array @406 +parse_ziti_edge_router_list @407 +parse_ziti_edge_router_ptr @408 +parse_ziti_enrollment_jwt @409 +parse_ziti_enrollment_jwt_array @410 +parse_ziti_enrollment_jwt_header @411 +parse_ziti_enrollment_jwt_header_array @412 +parse_ziti_enrollment_jwt_header_list @413 +parse_ziti_enrollment_jwt_header_ptr @414 +parse_ziti_enrollment_jwt_list @415 +parse_ziti_enrollment_jwt_ptr @416 +parse_ziti_enrollment_resp @417 +parse_ziti_enrollment_resp_array @418 +parse_ziti_enrollment_resp_list @419 +parse_ziti_enrollment_resp_ptr @420 +parse_ziti_env_info @421 +parse_ziti_env_info_array @422 +parse_ziti_env_info_list @423 +parse_ziti_env_info_ptr @424 +parse_ziti_error @425 +parse_ziti_error_array @426 +parse_ziti_error_list @427 +parse_ziti_error_ptr @428 +parse_ziti_extend_cert_authenticator_req @429 +parse_ziti_extend_cert_authenticator_req_array @430 +parse_ziti_extend_cert_authenticator_req_list @431 +parse_ziti_extend_cert_authenticator_req_ptr @432 +parse_ziti_extend_cert_authenticator_resp @433 +parse_ziti_extend_cert_authenticator_resp_array @434 +parse_ziti_extend_cert_authenticator_resp_list @435 +parse_ziti_extend_cert_authenticator_resp_ptr @436 +parse_ziti_host_cfg_v1 @437 +parse_ziti_host_cfg_v1_array @438 +parse_ziti_host_cfg_v1_list @439 +parse_ziti_host_cfg_v1_ptr @440 +parse_ziti_host_cfg_v2 @441 +parse_ziti_host_cfg_v2_array @442 +parse_ziti_host_cfg_v2_list @443 +parse_ziti_host_cfg_v2_ptr @444 +parse_ziti_id_cfg @445 +parse_ziti_id_cfg_array @446 +parse_ziti_id_cfg_list @447 +parse_ziti_id_cfg_ptr @448 +parse_ziti_identity @449 +parse_ziti_identity_array @450 +parse_ziti_identity_data @451 +parse_ziti_identity_data_array @452 +parse_ziti_identity_data_list @453 +parse_ziti_identity_data_ptr @454 +parse_ziti_identity_list @455 +parse_ziti_identity_ptr @456 +parse_ziti_intercept_cfg_v1 @457 +parse_ziti_intercept_cfg_v1_array @458 +parse_ziti_intercept_cfg_v1_list @459 +parse_ziti_intercept_cfg_v1_ptr @460 +parse_ziti_listen_options @461 +parse_ziti_listen_options_array @462 +parse_ziti_listen_options_list @463 +parse_ziti_listen_options_ptr @464 +parse_ziti_mfa_code_req @465 +parse_ziti_mfa_code_req_array @466 +parse_ziti_mfa_code_req_list @467 +parse_ziti_mfa_code_req_ptr @468 +parse_ziti_mfa_enrollment @469 +parse_ziti_mfa_enrollment_array @470 +parse_ziti_mfa_enrollment_list @471 +parse_ziti_mfa_enrollment_ptr @472 +parse_ziti_mfa_recovery_codes @473 +parse_ziti_mfa_recovery_codes_array @474 +parse_ziti_mfa_recovery_codes_list @475 +parse_ziti_mfa_recovery_codes_ptr @476 +parse_ziti_net_session @477 +parse_ziti_net_session_array @478 +parse_ziti_net_session_list @479 +parse_ziti_net_session_ptr @480 +parse_ziti_port_range @481 +parse_ziti_port_range_array @482 +parse_ziti_port_range_list @483 +parse_ziti_port_range_ptr @484 +parse_ziti_posture_query @485 +parse_ziti_posture_query_array @486 +parse_ziti_posture_query_list @487 +parse_ziti_posture_query_ptr @488 +parse_ziti_posture_query_set @489 +parse_ziti_posture_query_set_array @490 +parse_ziti_posture_query_set_list @491 +parse_ziti_posture_query_set_ptr @492 +parse_ziti_pr_domain_req @493 +parse_ziti_pr_domain_req_array @494 +parse_ziti_pr_domain_req_list @495 +parse_ziti_pr_domain_req_ptr @496 +parse_ziti_pr_endpoint_state_req @497 +parse_ziti_pr_endpoint_state_req_array @498 +parse_ziti_pr_endpoint_state_req_list @499 +parse_ziti_pr_endpoint_state_req_ptr @500 +parse_ziti_pr_mac_req @501 +parse_ziti_pr_mac_req_array @502 +parse_ziti_pr_mac_req_list @503 +parse_ziti_pr_mac_req_ptr @504 +parse_ziti_pr_os_req @505 +parse_ziti_pr_os_req_array @506 +parse_ziti_pr_os_req_list @507 +parse_ziti_pr_os_req_ptr @508 +parse_ziti_pr_process @509 +parse_ziti_pr_process_array @510 +parse_ziti_pr_process_list @511 +parse_ziti_pr_process_ptr @512 +parse_ziti_pr_process_req @513 +parse_ziti_pr_process_req_array @514 +parse_ziti_pr_process_req_list @515 +parse_ziti_pr_process_req_ptr @516 +parse_ziti_pr_response @517 +parse_ziti_pr_response_array @518 +parse_ziti_pr_response_list @519 +parse_ziti_pr_response_ptr @520 +parse_ziti_process @521 +parse_ziti_process_array @522 +parse_ziti_process_list @523 +parse_ziti_process_ptr @524 +parse_ziti_sdk_info @525 +parse_ziti_sdk_info_array @526 +parse_ziti_sdk_info_list @527 +parse_ziti_sdk_info_ptr @528 +parse_ziti_server_cfg_v1 @529 +parse_ziti_server_cfg_v1_array @530 +parse_ziti_server_cfg_v1_list @531 +parse_ziti_server_cfg_v1_ptr @532 +parse_ziti_service @533 +parse_ziti_service_array @534 +parse_ziti_service_list @535 +parse_ziti_service_ptr @536 +parse_ziti_service_timer @537 +parse_ziti_service_timer_array @538 +parse_ziti_service_timer_list @539 +parse_ziti_service_timer_ptr @540 +parse_ziti_service_update @541 +parse_ziti_service_update_array @542 +parse_ziti_service_update_list @543 +parse_ziti_service_update_ptr @544 +parse_ziti_verify_extend_cert_authenticator_req @545 +parse_ziti_verify_extend_cert_authenticator_req_array @546 +parse_ziti_verify_extend_cert_authenticator_req_list @547 +parse_ziti_verify_extend_cert_authenticator_req_ptr @548 +parse_ziti_version @549 +parse_ziti_version_array @550 +parse_ziti_version_list @551 +parse_ziti_version_ptr @552 +string_buf_append @553 +string_buf_append_byte @554 +string_buf_appendn @555 +string_buf_fmt @556 +string_buf_size @557 +string_buf_to_string @558 +tlsuv_logger @559 +ziti_accept @560 +ziti_address_match @561 +ziti_address_match_array @562 +ziti_address_match_list @563 +ziti_address_match_s @564 +ziti_address_print @565 +ziti_address_to_json @566 +ziti_address_to_json_r @567 +ziti_addrstr_match_list @568 +ziti_api_session_to_json @569 +ziti_api_session_to_json_r @570 +ziti_api_versions_to_json @571 +ziti_api_versions_to_json_r @572 +ziti_app_ctx @573 +ziti_auth_query_mfa_to_json @574 +ziti_auth_query_mfa_to_json_r @575 +ziti_auth_req_to_json @576 +ziti_auth_req_to_json_r @577 +ziti_authenticator_to_json @578 +ziti_authenticator_to_json_r @579 +ziti_client_cfg_v1_to_json @580 +ziti_client_cfg_v1_to_json_r @581 +ziti_close @582 +ziti_close_write @583 +ziti_config_to_json @584 +ziti_config_to_json_r @585 +ziti_conn_bridge @586 +ziti_conn_bridge_fds @587 +ziti_conn_bridge_idle_timeout @588 +ziti_conn_context @589 +ziti_conn_data @590 +ziti_conn_init @591 +ziti_conn_set_data @592 +ziti_conn_set_data_cb @593 +ziti_conn_source_identity @594 +ziti_create_api_cert_req_to_json @595 +ziti_create_api_cert_req_to_json_r @596 +ziti_create_api_cert_resp_to_json @597 +ziti_create_api_cert_resp_to_json_r @598 +ziti_dial @599 +ziti_dial_with_options @600 +ziti_dump @601 +ziti_edge_router_to_json @602 +ziti_edge_router_to_json_r @603 +ziti_endpoint_state_change @604 +ziti_enroll @605 +ziti_enrollment_jwt_header_to_json @606 +ziti_enrollment_jwt_header_to_json_r @607 +ziti_enrollment_jwt_to_json @608 +ziti_enrollment_jwt_to_json_r @609 +ziti_enrollment_resp_to_json @610 +ziti_enrollment_resp_to_json_r @611 +ziti_env_info_to_json @612 +ziti_env_info_to_json_r @613 +ziti_error_to_json @614 +ziti_error_to_json_r @615 +ziti_errorstr @616 +ziti_extend_cert_authenticator @617 +ziti_extend_cert_authenticator_req_to_json @618 +ziti_extend_cert_authenticator_req_to_json_r @619 +ziti_extend_cert_authenticator_resp_to_json @620 +ziti_extend_cert_authenticator_resp_to_json_r @621 +ziti_get_appdata @622 +ziti_get_appdata_raw @623 +ziti_get_controller @624 +ziti_get_controller_version @625 +ziti_get_identity @626 +ziti_get_transfer_rates @627 +ziti_get_version @628 +ziti_host_cfg_v1_to_json @629 +ziti_host_cfg_v1_to_json_r @630 +ziti_host_cfg_v2_to_json @631 +ziti_host_cfg_v2_to_json_r @632 +ziti_id_cfg_to_json @633 +ziti_id_cfg_to_json_r @634 +ziti_identity_data_to_json @635 +ziti_identity_data_to_json_r @636 +ziti_identity_to_json @637 +ziti_identity_to_json_r @638 +ziti_init @639 +ziti_init_opts @640 +ziti_intercept_cfg_v1_to_json @641 +ziti_intercept_cfg_v1_to_json_r @642 +ziti_intercept_from_client_cfg @643 +ziti_intercept_match @644 +ziti_intercept_match2 @645 +ziti_is_enabled @646 +ziti_listen @647 +ziti_listen_options_to_json @648 +ziti_listen_options_to_json_r @649 +ziti_listen_with_options @650 +ziti_log_init @651 +ziti_log_level @652 +ziti_log_level_label @653 +ziti_log_set_level @654 +ziti_log_set_level_by_label @655 +ziti_log_set_logger @656 +ziti_logger @657 +ziti_mfa_auth @658 +ziti_mfa_code_req_to_json @659 +ziti_mfa_code_req_to_json_r @660 +ziti_mfa_enroll @661 +ziti_mfa_enrollment_to_json @662 +ziti_mfa_enrollment_to_json_r @663 +ziti_mfa_get_recovery_codes @664 +ziti_mfa_new_recovery_codes @665 +ziti_mfa_recovery_codes_to_json @666 +ziti_mfa_recovery_codes_to_json_r @667 +ziti_mfa_remove @668 +ziti_mfa_verify @669 +ziti_net_session_to_json @670 +ziti_net_session_to_json_r @671 +ziti_port_match @672 +ziti_port_range_to_json @673 +ziti_port_range_to_json_r @674 +ziti_posture_query_set_to_json @675 +ziti_posture_query_set_to_json_r @676 +ziti_posture_query_to_json @677 +ziti_posture_query_to_json_r @678 +ziti_pr_domain_req_to_json @679 +ziti_pr_domain_req_to_json_r @680 +ziti_pr_endpoint_state_req_to_json @681 +ziti_pr_endpoint_state_req_to_json_r @682 +ziti_pr_mac_req_to_json @683 +ziti_pr_mac_req_to_json_r @684 +ziti_pr_os_req_to_json @685 +ziti_pr_os_req_to_json_r @686 +ziti_pr_process_req_to_json @687 +ziti_pr_process_req_to_json_r @688 +ziti_pr_process_to_json @689 +ziti_pr_process_to_json_r @690 +ziti_pr_response_to_json @691 +ziti_pr_response_to_json_r @692 +ziti_process_to_json @693 +ziti_process_to_json_r @694 +ziti_protocol_match @695 +ziti_sdk_info_to_json @696 +ziti_sdk_info_to_json_r @697 +ziti_server_cfg_v1_to_json @698 +ziti_server_cfg_v1_to_json_r @699 +ziti_service_available @700 +ziti_service_for_addr @701 +ziti_service_for_addr_str @702 +ziti_service_get_config @703 +ziti_service_get_raw_config @704 +ziti_service_has_permission @705 +ziti_service_timer_to_json @706 +ziti_service_timer_to_json_r @707 +ziti_service_to_json @708 +ziti_service_to_json_r @709 +ziti_service_update_to_json @710 +ziti_service_update_to_json_r @711 +ziti_set_app_info @712 +ziti_set_client_cert @713 +ziti_set_enabled @714 +ziti_set_timeout @715 +ziti_shutdown @716 +ziti_verify_extend_cert_authenticator @717 +ziti_verify_extend_cert_authenticator_req_to_json @718 +ziti_verify_extend_cert_authenticator_req_to_json_r @719 +ziti_version_to_json @720 +ziti_version_to_json_r @721 +ziti_write @722 diff --git a/ZitiNativeApiForDotnetCore/msvc-build.bat b/ZitiNativeApiForDotnetCore/msvc-build.bat index aa14ff8..2029d64 100644 --- a/ZitiNativeApiForDotnetCore/msvc-build.bat +++ b/ZitiNativeApiForDotnetCore/msvc-build.bat @@ -1,58 +1,80 @@ -@echo off - -REM a stupid env var JUST to allow a space to be set into an environment variable using substring... -set ZITI_SPACES=: : - -if "%ZITI_SDK_C_BRANCH%"=="" ( - echo ZITI_SDK_C_BRANCH is not set - ZITI_SDK_C_BRANCH_CMD will be empty - SET ZITI_SDK_C_BRANCH_CMD=%ZITI_SPACES:~2,1% -) else ( - echo SETTING ZITI_SDK_C_BRANCH_CMD to: -DZITI_SDK_C_BRANCH^=%ZITI_SDK_C_BRANCH% - SET ZITI_SDK_C_BRANCH_CMD=-DZITI_SDK_C_BRANCH=%ZITI_SDK_C_BRANCH% -) -REM echo "================ %ZITI_SDK_C_BRANCH_CMD%" - -IF "%ZITI_DEBUG%"=="" ( - REM clear out if debug was run in the past - SET ZITI_DEBUG_CMAKE= -) else ( - SET ZITI_DEBUG_CMAKE=-DCMAKE_BUILD_TYPE=Debug - echo ZITI_DEBUG detected. will run cmake with: %ZITI_DEBUG_CMAKE% -) - -set CSDK_HOME=%~dp0 - -set BUILDFOLDER=%CSDK_HOME%build-win - -mkdir %BUILDFOLDER% 2> NUL -mkdir %BUILDFOLDER%\x86 2> NUL -mkdir %BUILDFOLDER%\x64 2> NUL - -cmake -S %CSDK_HOME% -B %BUILDFOLDER%\x86 -G "Visual Studio 16 2019" -A Win32 -DCMAKE_INSTALL_INCLUDEDIR=include -DCMAKE_INSTALL_LIBDIR=lib %ZITI_SDK_C_BRANCH_CMD% %ZITI_DEBUG_CMAKE% -cmake -S %CSDK_HOME% -B %BUILDFOLDER%\x64 -G "Visual Studio 16 2019" -A x64 -DCMAKE_INSTALL_INCLUDEDIR=include -DCMAKE_INSTALL_LIBDIR=lib %ZITI_SDK_C_BRANCH_CMD% %ZITI_DEBUG_CMAKE% - -REM run the below commands from microsoft developer command prompt -REM uncomment to generate a new ziti.def -REM defgen 32 build-win\x86\_deps\ziti-sdk-c-build\library\Release\ziti.dll -REM copy ziti.def library -REM cl /C /EP /I build-win/x86/_deps/ziti-sdk-c-src/includes /c library/sharp-errors.c > library/ZitiStatus.cs -REM copy library/ZitiStatus.cs ../OpenZiti.NET/src/OpenZiti - -ECHO Build from cmake using: -ECHO cmake --build %BUILDFOLDER%\x86 --config Debug -ECHO cmake --build %BUILDFOLDER%\x86 --config Release -cmake --build %BUILDFOLDER%\x86 --config Debug -ECHO. -ECHO cmake --build %BUILDFOLDER%\x64 --config Debug -ECHO cmake --build %BUILDFOLDER%\x64 --config Release -cmake --build %BUILDFOLDER%\x64 --config Debug -ECHO. -ECHO Or open %BUILDFOLDER%\ziti-sdk.sln - -goto end - -:abnormalend -echo TERMINATED UNEXPECTEDLY - -:end - +@echo off + +REM a stupid env var JUST to allow a space to be set into an environment variable using substring... +set ZITI_SPACES=: : +set NATIVE_CODE_DIR=%~dp0 +set BUILDFOLDER=%NATIVE_CODE_DIR%build-win + +IF /i "%1"=="help" ( + goto print_help +) +IF /i "%1"=="defgen" ( + goto defgen +) + +if "%ZITI_SDK_C_BRANCH%"=="" ( + echo ZITI_SDK_C_BRANCH is not set - ZITI_SDK_C_BRANCH_CMD will be empty + SET ZITI_SDK_C_BRANCH_CMD=%ZITI_SPACES:~2,1% +) else ( + echo SETTING ZITI_SDK_C_BRANCH_CMD to: -DZITI_SDK_C_BRANCH^=%ZITI_SDK_C_BRANCH% + SET ZITI_SDK_C_BRANCH_CMD=-DZITI_SDK_C_BRANCH=%ZITI_SDK_C_BRANCH% +) + +IF "%ZITI_DEBUG%"=="" ( + REM clear out if debug was run in the past + SET ZITI_DEBUG_CMAKE= +) else ( + SET ZITI_DEBUG_CMAKE=-DCMAKE_BUILD_TYPE=Debug + echo ZITI_DEBUG detected. will run cmake with: %ZITI_DEBUG_CMAKE% +) + +cmake -E make_directory %BUILDFOLDER% + +echo. +echo. +echo "Building 32-bit" +cmake --preset win32 -S %NATIVE_CODE_DIR% -B %BUILDFOLDER%\win32 -A Win32 +cmake --build %BUILDFOLDER%\win32 +cmake --build %BUILDFOLDER%\win32 --config Release + +echo. +echo. +echo "Building 64-bit" +cmake --preset win64 -S %NATIVE_CODE_DIR% -B %BUILDFOLDER%\win64 +cmake --build %BUILDFOLDER%\win64 +cmake --build %BUILDFOLDER%\win64 --config Release +goto end + +:print_help +echo. +echo To build the project issue the following commands (or execute this script with no parameters: msvc-build.bat) +echo. +echo :Build 32-bit: +echo cmake --preset win32 -S %NATIVE_CODE_DIR% -B %BUILDFOLDER%\win32 -A Win32 +echo cmake --build %BUILDFOLDER%\win32 +echo cmake --build %BUILDFOLDER%\win32 --config Release +echo. +echo. +echo :Build 64-bit: +echo cmake --preset win64 -S %NATIVE_CODE_DIR% -B %BUILDFOLDER%\win64 +echo cmake --build %BUILDFOLDER%\win64 +echo cmake --build %BUILDFOLDER%\win64 --config Release +echo. +echo. +goto end + +:defgen +cmake --preset win64 -S %NATIVE_CODE_DIR% -B %BUILDFOLDER%\win64 -DGENERATE_ZITI_STATUS=yes +REM run the below commands from microsoft developer command prompt +REM uncomment to generate a new ziti.def +REM defgen 32 build-win\x86\_deps\ziti-sdk-c-build\library\Release\ziti.dll +REM copy ziti.def library +REM cl /C /EP /I build-win/x86/_deps/ziti-sdk-c-src/includes /c library/sharp-errors.c > library/ZitiStatus.cs +REM copy library/ZitiStatus.cs ../OpenZiti.NET/src/OpenZiti +goto end + +:abnormalend +echo TERMINATED UNEXPECTEDLY + +:end + diff --git a/ZitiNativeApiForDotnetCore/toolchains/Windows-win32.cmake b/ZitiNativeApiForDotnetCore/toolchains/Windows-win32.cmake new file mode 100644 index 0000000..a81201e --- /dev/null +++ b/ZitiNativeApiForDotnetCore/toolchains/Windows-win32.cmake @@ -0,0 +1,13 @@ +#set(CMAKE_SYSTEM_NAME Windows) +#set(CMAKE_SYSTEM_PROCESSOR Win32) +#set(CMAKE_GENERATOR_PLATFORM:INTERNAL Win32) +set(CMAKE_GENERATOR_PLATFORM "win32") + +#set(triple i686-w64-mingw32) +#set(CMAKE_C_COMPILER ${triple}-gcc) +#set(CMAKE_CXX_COMPILER ${triple}-g++) +# +#set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +#set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +#set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +#set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/ZitiNativeApiForDotnetCore/toolchains/Windows-x86.cmake b/ZitiNativeApiForDotnetCore/toolchains/Windows-x86.cmake deleted file mode 100644 index a583973..0000000 --- a/ZitiNativeApiForDotnetCore/toolchains/Windows-x86.cmake +++ /dev/null @@ -1,11 +0,0 @@ -set(CMAKE_SYSTEM_NAME Windows) -set(CMAKE_SYSTEM_PROCESSOR x86) - -#set(triple i686-w64-mingw32) -#set(CMAKE_C_COMPILER ${triple}-gcc) -#set(CMAKE_CXX_COMPILER ${triple}-g++) - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/ZitiNativeApiForDotnetCore/vcpkg.json b/ZitiNativeApiForDotnetCore/vcpkg.json new file mode 100644 index 0000000..7ae9dfa --- /dev/null +++ b/ZitiNativeApiForDotnetCore/vcpkg.json @@ -0,0 +1,24 @@ +{ + "name": "ziti", + "version-semver": "1.0.0", + "dependencies": [ + "libuv", + "zlib", + "llhttp", + "libsodium", + "getopt", + "mbedtls" + ], + "features": { + "test": { + "description": "Dependencies for testing", + "dependencies": [ + { + "version>=": "3.3.1", + "name": "catch2" + } + ] + } + }, + "builtin-baseline": "f14984af3738e69f197bf0e647a8dca12de92996" +} diff --git a/build-native.bat b/build-native.bat deleted file mode 100644 index 59a7a84..0000000 --- a/build-native.bat +++ /dev/null @@ -1,44 +0,0 @@ -echo off -REM this bat file is a convinience script for local development. It is meant to build an entire -REM local native nuget package for use while testing/local dev. It's frequently necessary to add -REM functions around the C SDK for helping dotnet with something that's better done in C or for -REM testing the blitting of types when structs change. This script should build both x86 and x64 -REM for windows, and produce a nuget package ONLY usable by windows for development. -REM -REM After executing, there should be a nuget package located at local-nuget-packages named after -REM the year.month.day.hourminute.nupkg and should look something like these: -REM -REM local-nuget-packages\OpenZiti.NET.native.2022.11.1.14.nupkg -REM local-nuget-packages\OpenZiti.NET.native.2022.11.1.946.nupkg -REM -set CODE_ROOT=%~dp0 -set NATIVE_ROOT=%CODE_ROOT%ZitiNativeApiForDotnetCore\ -set LOCAL_NUGET_PACKAGES=%CODE_ROOT%local-nuget-packages -cd %NATIVE_ROOT% - -del /s %NATIVE_ROOT%build-win\x64\library\Debug\ziti4dotnet.* -del /s %NATIVE_ROOT%build-win\x86\library\Debug\ziti4dotnet.* -echo REMOVED OLD DLLS - -call msvc-build.bat - -cd %CODE_ROOT% -copy /y %NATIVE_ROOT%build-win\x64\library\Debug\ziti4dotnet.* runtimes\win-x64\native -copy /y %NATIVE_ROOT%build-win\x86\library\Debug\ziti4dotnet.* runtimes\win-x86\native - -if not exist %LOCAL_NUGET_PACKAGES% mkdir %LOCAL_NUGET_PACKAGES% - -set yearstr=%date:~10,4% -set daystr=%date:~7,2% -set monthstr=%date:~4,2% - -SET HOUR=%TIME:~0,2% -IF "%HOUR:~0,1%" == " " SET HOUR=0%HOUR:~1,1% - -set timenow=%TIME: =0% -set minstr=%timenow:~3,2% - -set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2% -echo %datestr% %yearstr% %monthstr% %daystr% %HOUR% %minstr% -nuget pack -version %yearstr%.%monthstr%.%daystr%.%HOUR%%minstr% -OutputDirectory %LOCAL_NUGET_PACKAGES% native-package.nuspec - diff --git a/dev-build-native.bat b/dev-build-native.bat new file mode 100644 index 0000000..e47c596 --- /dev/null +++ b/dev-build-native.bat @@ -0,0 +1,67 @@ +echo off +REM this bat file is a convinience script for local development. It is meant to build an entire +REM local native nuget package for use while testing/local dev. It's frequently necessary to add +REM functions around the C SDK for helping dotnet with something that's better done in C or for +REM testing the blitting of types when structs change. This script should build both x86 and x64 +REM for windows, and produce a nuget package ONLY usable by windows for development. +REM +REM After executing, there should be a nuget package located at local-nuget-packages named after +REM the year.month.day.hourminute.nupkg and should look something like these: +REM +REM local-nuget-packages\OpenZiti.NET.native.2022.11.1.14.nupkg +REM local-nuget-packages\OpenZiti.NET.native.2022.11.1.946.nupkg +REM +set CODE_ROOT=%~dp0 +set NATIVE_ROOT=%CODE_ROOT%ZitiNativeApiForDotnetCore +set LOCAL_NUGET_PACKAGES=%CODE_ROOT%local-nuget-packages +cd %NATIVE_ROOT% + +del /s %NATIVE_ROOT%\build-win\win32\library\Debug\ziti4dotnet.* +del /s %NATIVE_ROOT%\build-win\win64\library\Debug\ziti4dotnet.* +del /s %NATIVE_ROOT%\build-win\win32\library\Release\ziti4dotnet.* +del /s %NATIVE_ROOT%\build-win\win64\library\Release\ziti4dotnet.* +echo REMOVED OLD DLLS + +call %NATIVE_ROOT%\msvc-build.bat + +del /s /q %CODE_ROOT%runtimes + +mkdir %CODE_ROOT%\runtimes +mkdir %CODE_ROOT%\runtimes\win-x86\native +mkdir %CODE_ROOT%\runtimes\win-x64\native + +mkdir %CODE_ROOT%\runtimes\osx-x64\native +mkdir %CODE_ROOT%\runtimes\ios-arm64\native +mkdir %CODE_ROOT%\runtimes\osx-arm64\native + +mkdir %CODE_ROOT%\runtimes\linux-arm64\native +mkdir %CODE_ROOT%\runtimes\linux-arm\native +mkdir %CODE_ROOT%\runtimes\linux-x64\native + +echo "dummy" > %CODE_ROOT%\runtimes/osx-x64/native/libziti4dotnet.dylib +echo "dummy" > %CODE_ROOT%\runtimes/ios-arm64/native/libziti4dotnet.dylib +echo "dummy" > %CODE_ROOT%\runtimes/osx-arm64/native/libziti4dotnet.dylib + +echo "dummy" > %CODE_ROOT%\runtimes/linux-arm64/native/libziti4dotnet.so +echo "dummy" > %CODE_ROOT%\runtimes/linux-arm/native/libziti4dotnet.so +echo "dummy" > %CODE_ROOT%\runtimes/linux-x64/native/libziti4dotnet.so + +copy /y %NATIVE_ROOT%\build-win\win32\library\Debug\ziti4dotnet.* %CODE_ROOT%runtimes\win-x86\native +copy /y %NATIVE_ROOT%\build-win\win64\library\Debug\ziti4dotnet.* %CODE_ROOT%runtimes\win-x64\native + +if not exist %LOCAL_NUGET_PACKAGES% mkdir %LOCAL_NUGET_PACKAGES% + +set yearstr=%date:~10,4% +set daystr=%date:~7,2% +set monthstr=%date:~4,2% + +SET HOUR=%TIME:~0,2% +IF "%HOUR:~0,1%" == " " SET HOUR=0%HOUR:~1,1% + +set timenow=%TIME: =0% +set minstr=%timenow:~3,2% + +set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2% +echo %datestr% %yearstr% %monthstr% %daystr% %HOUR% %minstr% +nuget pack -version %yearstr%.%monthstr%.%daystr%.%HOUR%%minstr% -OutputDirectory %LOCAL_NUGET_PACKAGES% %CODE_ROOT%native-package.nuspec + diff --git a/native-package.nuspec b/native-package.nuspec index 8fa8fe5..8e11e95 100644 --- a/native-package.nuspec +++ b/native-package.nuspec @@ -8,7 +8,7 @@ OpenZiti Maintainers Apache-2.0 https://openziti.github.io/ziti-sdk-csharp - https://openziti.github.io/favicon.ico + ziti-v2.png false A nuget package which wraps the native ziti C SDK into a package easily consumable from .NET Copyright NetFoundry Inc. All rights reserved. @@ -16,6 +16,7 @@ This nuget package contains native libraries compiled for the targeted platforms. Expected targets are Windows x86 and x64, linux x64, MacOS x64 + diff --git a/ziti-v2.png b/ziti-v2.png new file mode 100644 index 0000000000000000000000000000000000000000..a66ef5eb4931076f008f510f4931a5cd1bf9b40e GIT binary patch literal 60274 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�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 Wqr9<^X>S24;L*|0zgKq08uMSJd~nGC literal 0 HcmV?d00001