Update C# bindings to 1.4.0 API

This commit is contained in:
Joseph Henry
2021-04-30 21:54:34 -07:00
parent 3e304cb25a
commit 6f42338f6e
19 changed files with 4679 additions and 3143 deletions

View File

@@ -9,9 +9,6 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v2
- name: Install clang-format
run: sudo apt-get install clang-format
- name: Format code
run: ./build.sh format-code

View File

@@ -408,6 +408,28 @@ host-pinvoke()
cp -f $CACHE_DIR/lib/libzt.* $LIB_OUTPUT_DIR
echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n"
$TREE $TARGET_BUILD_DIR
# Test C#
if [[ $2 = *"test"* ]]; then
if [[ -z "${alice_path}" ]]; then
echo "Please set necessary environment variables for test"
exit 0
fi
# TODO: This should eventually be converted to a proper dotnet project
# Build C# managed API library
# -doc:$LIB_OUTPUT_DIR/ZeroTier.Sockets.xml
csc -target:library -out:$LIB_OUTPUT_DIR/ZeroTier.Sockets.dll src/bindings/csharp/*.cs
# Build selftest
mkdir -p $BIN_OUTPUT_DIR
csc -out:$BIN_OUTPUT_DIR/selftest.exe -reference:$LIB_OUTPUT_DIR/ZeroTier.Sockets.dll test/selftest.cs
# Copy shared libraries into bin directory so they can be discovered by dlopen
cp $LIB_OUTPUT_DIR/* $BIN_OUTPUT_DIR
# Start Alice as server
MONO_THREADS_SUSPEND=preemptive; mono --debug "$BIN_OUTPUT_DIR/selftest.exe" server $alice_path $testnet $port4 &
sleep 5
# Start Bob as client
MONO_THREADS_SUSPEND=preemptive; mono --debug "$BIN_OUTPUT_DIR/selftest.exe" client $bob_path $testnet $alice_ip4 $port4 &
fi
}
# Build shared library with Java JNI wrapper symbols exported (.jar)
@@ -560,7 +582,7 @@ format-code()
if [[ ! $(which clang-format) = "" ]];
then
# Eventually: find . -path ./ext -prune -false -o -type f \( -iname \*.c -o -iname \*.h -o -iname \*.cpp -o -iname \*.hpp \) -exec clang-format -i {} \;
clang-format -i include/*.h \
clang-format-11 -i include/*.h \
src/*.c \
src/*.cpp \
src/*.hpp \
@@ -597,37 +619,6 @@ test-c()
"$BIN_OUTPUT_DIR/selftest-c" $bob_path $testnet $port4 $alice_ip4 $port6 $alice_ip6 &
}
# Test C# API
test-cs()
{
if [[ -z "${alice_path}" ]]; then
echo "Please set necessary environment variables for test"
exit 0
fi
ARTIFACT="pinvoke"
# Default to debug so asserts aren't optimized out
BUILD_TYPE=${1:-debug}
TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE
LIB_OUTPUT_DIR=$TARGET_BUILD_DIR/lib
BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin
rm -rf $TARGET_BUILD_DIR
# Build C shared library exporting C# symbols
host-pinvoke $1
# TODO: This should eventually be converted to a proper dotnet project
# Build C# managed API library
csc -target:library -doc:$LIB_OUTPUT_DIR/ZeroTier.Sockets.xml -out:$LIB_OUTPUT_DIR/ZeroTier.Sockets.dll src/bindings/csharp/*.cs
# Build selftest
mkdir -p $BIN_OUTPUT_DIR
csc -out:$BIN_OUTPUT_DIR/selftest.exe -reference:$LIB_OUTPUT_DIR/ZeroTier.Sockets.dll test/selftest.cs
# Copy shared libraries into bin directory so they can be discovered by dlopen
cp $LIB_OUTPUT_DIR/* $BIN_OUTPUT_DIR
# Start Alice as server
mono --debug "$BIN_OUTPUT_DIR/selftest.exe" $alice_path $testnet $port4 $port6 &
sleep 10
# Start Bob as client
mono --debug "$BIN_OUTPUT_DIR/selftest.exe" $bob_path $testnet $port4 $alice_ip4 $port6 $alice_ip6 &
}
# Recursive deep clean
clean()
{

View File

@@ -2,265 +2,265 @@
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets; // For SocketType, etc
using System.Text; // For Encoding
using System.Net.Sockets;
using System.Text;
/**
*
* Namespaces explained:
*
* ZeroTier.Core (API to control a ZeroTier Node)
* -> class ZeroTier.Core.Node
* -> class ZeroTier.Core.Event
*
* ZeroTier.Sockets (Socket API similar to System.Net.Sockets)
* -> class ZeroTier.Sockets.Socket
* -> class ZeroTier.Sockets.SocketException
*
* ZeroTier.Central (upcoming)
*
*/
using ZeroTier;
public class ExampleApp {
// ZeroTier Node instance
ZeroTier.Core.Node node;
ZeroTier.Core.Node node;
/**
* Initialize and start ZeroTier
*/
public void StartZeroTier(string configFilePath, ushort servicePort, ulong networkId)
{
node = new ZeroTier.Core.Node(configFilePath, OnZeroTierEvent, servicePort);
node.Start(); // Network activity only begins after calling Start()
// Initialize and start ZeroTier
/* How you do this next part is up to you, but essentially we're waiting for the node
to signal to us via OnZeroTierEvent(ZeroTier.Core.Event) that it has access to the
internet and is able to talk to one of our root servers. As a convenience you can just
periodically check Node.IsOnline() instead of looking for the event via the callback. */
while (!node.IsOnline()) { Thread.Sleep(100); }
public void StartZeroTier(string configFilePath, ulong networkId)
{
node = new ZeroTier.Core.Node();
/* After the node comes online you may now join/leave networks. You will receive
notifications via the callback function regarding the status of your join request as well
as any subsequent network-related events such as the assignment of an IP address, added
or removed routes, etc. */
node.Join(networkId);
// (OPTIONAL) Initialize node
/* Note that ZeroTier.Sockets.Socket calls will fail if there are no routes available, for this
reason we should wait to make those calls until the node has indicated to us that at
least one network has been joined successfully. */
while (!node.HasRoutes()) { Thread.Sleep(100); }
}
node.InitFromStorage(configFilePath);
node.InitAllowNetworkCaching(false);
node.InitAllowPeerCaching(true);
// node.InitAllowIdentityCaching(true);
// node.InitAllowWorldCaching(false);
node.InitSetEventHandler(OnZeroTierEvent);
node.InitSetPort(0); // Will randomly attempt ports if set to 0
/**
* Stop ZeroTier
*/
public void StopZeroTier()
{
node.Stop();
}
// (OPTIONAL) Set custom signed roots
/**
* Your application should process event messages and return control as soon as possible. Blocking
* or otherwise time-consuming operations are not reccomended here.
*/
public void OnZeroTierEvent(ZeroTier.Core.Event e)
{
Console.WriteLine("Event.eventCode = {0} ({1})", e.EventCode, e.EventName);
// In this case we only allow ZeroTier to contact our Amsterdam root server
// To see examples of how to generate and sign roots definitions see docs.zerotier.com
if (e.EventCode == ZeroTier.Constants.EVENT_NODE_ONLINE) {
Console.WriteLine("Node is online");
Console.WriteLine(" - Address (NodeId): " + node.NodeId.ToString("x16"));
}
var rootsData = new byte[] {
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xea, 0xc9, 0x0a, 0x00, 0x00, 0x01, 0x6c, 0xe3, 0xe2, 0x39, 0x55, 0x74,
0xeb, 0x27, 0x9d, 0xc9, 0xe7, 0x5a, 0x52, 0xbb, 0x91, 0x8f, 0xf7, 0x43, 0x3c, 0xbf, 0x77, 0x5a, 0x4b, 0x57,
0xb4, 0xe1, 0xe9, 0xa1, 0x01, 0x61, 0x3d, 0x25, 0x35, 0x60, 0xcb, 0xe3, 0x30, 0x18, 0x1e, 0x6e, 0x44, 0xef,
0x93, 0x89, 0xa0, 0x19, 0xb8, 0x7b, 0x36, 0x0b, 0x92, 0xff, 0x0f, 0x1b, 0xbe, 0x56, 0x5a, 0x46, 0x91, 0x36,
0xf1, 0xd4, 0x5c, 0x09, 0x05, 0xe5, 0xf5, 0xfb, 0xba, 0xe8, 0x13, 0x2d, 0x47, 0xa8, 0xe4, 0x1b, 0xa5, 0x1c,
0xcf, 0xb0, 0x2f, 0x27, 0x7e, 0x95, 0xa0, 0xdd, 0x49, 0xe1, 0x7d, 0xc0, 0x7e, 0x6d, 0xe3, 0x25, 0x91, 0x96,
0xc2, 0x55, 0xf9, 0x20, 0x6d, 0x2a, 0x5e, 0x1b, 0x41, 0xcb, 0x1f, 0x8d, 0x57, 0x27, 0x69, 0x3e, 0xcc, 0x7f,
0x0b, 0x36, 0x54, 0x6b, 0xd3, 0x80, 0x78, 0xf6, 0xd0, 0xec, 0xb4, 0x31, 0x6b, 0x87, 0x1b, 0x50, 0x08, 0xe4,
0x0b, 0xa9, 0xd4, 0xfd, 0x37, 0x79, 0x14, 0x6a, 0xf5, 0x12, 0xf2, 0x45, 0x39, 0xca, 0x23, 0x00, 0x39, 0xbc,
0xa3, 0x1e, 0xa8, 0x4e, 0x23, 0x2d, 0xc8, 0xdb, 0x9b, 0x0e, 0x52, 0x1b, 0x8d, 0x02, 0x72, 0x01, 0x99, 0x2f,
0xcf, 0x1d, 0xb7, 0x00, 0x20, 0x6e, 0xd5, 0x93, 0x50, 0xb3, 0x19, 0x16, 0xf7, 0x49, 0xa1, 0xf8, 0x5d, 0xff,
0xb3, 0xa8, 0x78, 0x7d, 0xcb, 0xf8, 0x3b, 0x8c, 0x6e, 0x94, 0x48, 0xd4, 0xe3, 0xea, 0x0e, 0x33, 0x69, 0x30,
0x1b, 0xe7, 0x16, 0xc3, 0x60, 0x93, 0x44, 0xa9, 0xd1, 0x53, 0x38, 0x50, 0xfb, 0x44, 0x60, 0xc5, 0x0a, 0xf4,
0x33, 0x22, 0xbc, 0xfc, 0x8e, 0x13, 0xd3, 0x30, 0x1a, 0x1f, 0x10, 0x03, 0xce, 0xb6, 0x00, 0x02, 0x04, 0xc3,
0xb5, 0xad, 0x9f, 0x27, 0x09, 0x06, 0x2a, 0x02, 0x6e, 0xa0, 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x27, 0x09
};
node.InitSetRoots(rootsData, rootsData.Length);
if (e.EventCode == ZeroTier.Constants.EVENT_NETWORK_OK) {
Console.WriteLine(" - Network ID: " + e.networkDetails.networkId.ToString("x16"));
}
}
node.Start(); // Network activity only begins after calling Start()
while (! node.Online) {
Thread.Sleep(50);
}
/**
* Example server
*/
public void YourServer(IPEndPoint localEndPoint) {
string data = null;
Console.WriteLine("Id : " + node.IdString);
Console.WriteLine("Version : " + node.Version);
Console.WriteLine("PrimaryPort : " + node.PrimaryPort);
Console.WriteLine("SecondaryPort : " + node.SecondaryPort);
Console.WriteLine("TertiaryPort : " + node.TertiaryPort);
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
node.Join(networkId);
Console.WriteLine("Waiting for join to complete...");
while (node.Networks.Count == 0) {
Thread.Sleep(50);
}
Console.WriteLine(localEndPoint.ToString());
ZeroTier.Sockets.Socket listener = new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Wait until we've joined the network and we have routes + addresses
Console.WriteLine("Waiting for network to become transport ready...");
while (! node.IsNetworkTransportReady(networkId)) {
Thread.Sleep(50);
}
// Bind the socket to the local endpoint and
// listen for incoming connections.
Console.WriteLine("Num of assigned addresses : " + node.GetNetworkAddresses(networkId).Count);
foreach (IPAddress addr in node.GetNetworkAddresses(networkId)) {
Console.WriteLine(" - Address: " + addr);
}
try {
listener.Bind(localEndPoint);
listener.Listen(10);
Console.WriteLine("Num of routes : " + node.GetNetworkRoutes(networkId).Count);
foreach (ZeroTier.Core.RouteInfo route in node.GetNetworkRoutes(networkId)) {
Console.WriteLine(
" - Route: target={0} via={1} flags={2} metric={3}",
route.Target.ToString(),
route.Via.ToString(),
route.Flags,
route.Metric);
}
}
// Start listening for connections.
while (true) {
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
bool nonblocking = true;
/**
* Stop ZeroTier
*/
public void StopZeroTier()
{
node.Free();
}
ZeroTier.Sockets.Socket handler;
/**
* (OPTIONAL)
*
* Your application should process event messages and return control as soon as possible. Blocking
* or otherwise time-consuming operations are not recommended here.
*/
public void OnZeroTierEvent(ZeroTier.Core.Event e)
{
Console.WriteLine("Event.Code = {0} ({1})", e.Code, e.Name);
/*
if (e.Code == ZeroTier.Constants.EVENT_NODE_ONLINE) {
Console.WriteLine("Node is online");
Console.WriteLine(" - Address (NodeId): " + node.Id.ToString("x16"));
}
if (nonblocking) { // Non-blocking style Accept() loop using Poll()
Console.WriteLine("Starting non-blocking Accept() loop...");
listener.Blocking = false;
// loop
int timeout = 100000; // microseconds (1 second)
while (true) {
Console.WriteLine("Polling... (for data or incoming connections)");
if (listener.Poll(timeout, SelectMode.SelectRead)) {
Console.WriteLine("Detected event (SelectRead). Accepting...");
handler = listener.Accept();
break;
}
//Thread.Sleep(5);
}
}
else { // Blocking style
Console.WriteLine("Starting blocking Accept() call...");
handler = listener.Accept();
}
data = null;
Console.WriteLine("Accepted connection from: " + handler.RemoteEndPoint.ToString());
if (e.Code == ZeroTier.Constants.EVENT_NETWORK_OK) {
Console.WriteLine(" - Network ID: " + e.NetworkInfo.Id.ToString("x16"));
}
*/
}
// handler.ReceiveTimeout = 1000;
/**
* Example server
*/
public void SocketServer(IPEndPoint localEndPoint)
{
string data = null;
// An incoming connection needs to be processed.
while (true) {
int bytesRec = 0;
try {
Console.WriteLine("Receiving...");
bytesRec = handler.Receive(bytes);
}
catch (ZeroTier.Sockets.SocketException e)
{
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}",
e.ServiceErrorCode, e.SocketErrorCode);
}
if (bytesRec > 0) {
Console.WriteLine("Bytes received: {0}", bytesRec);
data = Encoding.ASCII.GetString(bytes,0,bytesRec);
Console.WriteLine( "Text received : {0}", data);
//break;
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
}
else
{
System.GC.Collect();
Console.WriteLine("No data...");
}
}
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
Console.WriteLine(localEndPoint.ToString());
ZeroTier.Sockets.Socket listener =
new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
} catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(e);
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}",
e.ServiceErrorCode, e.SocketErrorCode);
}
// Bind the socket to the local endpoint and
// listen for incoming connections.
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
try {
listener.Bind(localEndPoint);
listener.Listen(10);
ZeroTier.Sockets.Socket handler;
Console.WriteLine("Server: Accepting...");
handler = listener.Accept();
/**
* Example client
*/
public void YourClient(IPEndPoint remoteServerEndPoint) {
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
data = null;
Console.WriteLine("Server: Accepted connection from: " + handler.RemoteEndPoint.ToString());
// Connect to a remote device.
try {
// Create a TCP/IP socket.
ZeroTier.Sockets.Socket sender = new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
for (int i = 0; i < 4; i++) {
int bytesRec = 0;
try {
Console.WriteLine("Server: Receiving...");
bytesRec = handler.Receive(bytes);
}
catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(
"ServiceErrorCode={0} SocketErrorCode={1}",
e.ServiceErrorCode,
e.SocketErrorCode);
}
if (bytesRec > 0) {
Console.WriteLine("Server: Bytes received: {0}", bytesRec);
data = Encoding.ASCII.GetString(bytes, 0, bytesRec);
Console.WriteLine("Server: Text received : {0}", data);
Thread.Sleep(1000);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
Thread.Sleep(1000);
}
}
// Release the socket.
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(e);
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
}
}
// Connect the socket to the remote endpoint. Catch any errors.
try {
Console.WriteLine("Socket connecting to {0}...",
remoteServerEndPoint.ToString());
/**
* Example client
*/
public void SocketClient(IPEndPoint remoteServerEndPoint)
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
sender.Connect(remoteServerEndPoint);
// Connect to a remote device.
try {
// Create a TCP/IP socket.
ZeroTier.Sockets.Socket sender =
new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
try {
Console.WriteLine("Client: Connecting to {0}...", remoteServerEndPoint.ToString());
sender.Connect(remoteServerEndPoint);
Console.WriteLine("Client: Connected to {0}", sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes("This is a test");
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes,0,bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
} catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(e);
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
}
} catch (Exception e) {
Console.WriteLine( e.ToString());
}
}
// Encode the data string into a byte array.
for (int i = 0; i < 4; i++) {
byte[] msg = Encoding.ASCII.GetBytes("This is a test");
int bytesSent = sender.Send(msg);
Console.WriteLine("Client: Sent ({0}) bytes", bytesSent);
Thread.Sleep(1000);
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Client: Echoing {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
Thread.Sleep(1000);
}
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(e);
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
}
}
catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
public class example
{
static int Main(string[] args)
{
if (args.Length < 5 || args.Length > 6)
{
Console.WriteLine("\nPlease specify either client or server mode and required arguments:");
Console.WriteLine(" Usage: example server <config_path> <ztServicePort> <nwid> <serverPort>");
Console.WriteLine(" Usage: example client <config_path> <ztServicePort> <nwid> <remoteServerIp> <remoteServerPort>\n");
return 1;
}
string configFilePath = args[1];
ushort servicePort = (ushort)Int16.Parse(args[2]);
ulong networkId = (ulong)Int64.Parse(args[3], System.Globalization.NumberStyles.HexNumber);
public class example {
static int Main(string[] args)
{
if (args.Length < 4 || args.Length > 5) {
Console.WriteLine("\nPlease specify either client or server mode and required arguments:");
Console.WriteLine(" Usage: example server <config_path> <nwid> <localPort>");
Console.WriteLine(" Usage: example client <config_path> <nwid> <remoteAddress> <remotePort>\n");
return 1;
}
string configFilePath = args[1];
ulong networkId = (ulong)Int64.Parse(args[2], System.Globalization.NumberStyles.HexNumber);
ExampleApp exampleApp = new ExampleApp();
ExampleApp exampleApp = new ExampleApp();
if (args[0].Equals("server"))
{
Console.WriteLine("Server mode...");
ushort serverPort = (ushort)Int16.Parse(args[4]);
exampleApp.StartZeroTier(configFilePath, servicePort, networkId);
IPAddress ipAddress = IPAddress.Parse("0.0.0.0");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, serverPort);
exampleApp.YourServer(localEndPoint);
}
if (args[0].Equals("server")) {
Console.WriteLine("Server mode...");
ushort serverPort = (ushort)Int16.Parse(args[3]);
exampleApp.StartZeroTier(configFilePath, networkId);
IPAddress ipAddress = IPAddress.Parse("0.0.0.0");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, serverPort);
exampleApp.SocketServer(localEndPoint);
}
if (args[0].Equals("client"))
{
Console.WriteLine("Client mode...");
string serverIP = args[4];
int port = Int16.Parse(args[5]);
IPAddress ipAddress = IPAddress.Parse(serverIP);
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, port);
exampleApp.StartZeroTier(configFilePath, servicePort, networkId);
exampleApp.YourClient(remoteEndPoint);
}
exampleApp.StopZeroTier();
return 0;
}
if (args[0].Equals("client")) {
Console.WriteLine("Client mode...");
string serverIP = args[3];
int port = Int16.Parse(args[4]);
IPAddress ipAddress = IPAddress.Parse(serverIP);
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, port);
exampleApp.StartZeroTier(configFilePath, networkId);
exampleApp.SocketClient(remoteEndPoint);
}
exampleApp.StopZeroTier();
return 0;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
using System.Net;
using ZeroTier;
namespace ZeroTier.Core
{
public class AddressInfo {
public AddressInfo(IPAddress addr, ulong net_id)
{
_addr = addr;
_net_id = net_id;
}
public ulong _net_id;
public IPAddress _addr;
public IPAddress Address
{
get {
return _addr;
}
}
public ulong NetworkId
{
get {
return _net_id;
}
}
}
}

File diff suppressed because it is too large Load Diff

537
src/bindings/csharp/Constants.cs Normal file → Executable file
View File

@@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2025-01-01
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
@@ -13,341 +13,246 @@
using ZeroTier;
namespace ZeroTier
{
public class Constants
{
// General error codes
public static readonly int ERR_OK = 0;
public static readonly int ERR_SOCKET = -1;
public static readonly int ERR_SERVICE = -2;
public static readonly int ERR_ARG = -3;
public static readonly int ERR_NO_RESULT = -4;
public static readonly int ERR_GENERAL = -5;
namespace ZeroTier {
public class Constants {
public static readonly short ERR_OK = 0;
public static readonly short ERR_SOCKET = -1;
public static readonly short ERR_SERVICE = -2;
public static readonly short ERR_ARG = -3;
public static readonly short ERR_NO_RESULT = -4;
public static readonly short ERR_GENERAL = -5;
// Node events
public static readonly short EVENT_NODE_UP = 200;
public static readonly short EVENT_NODE_ONLINE = 201;
public static readonly short EVENT_NODE_OFFLINE = 202;
public static readonly short EVENT_NODE_DOWN = 203;
public static readonly short EVENT_NODE_IDENTITY_COLLISION = 204;
public static readonly short EVENT_NODE_UNRECOVERABLE_ERROR = 205;
public static readonly short EVENT_NODE_NORMAL_TERMINATION = 206;
public static readonly short EVENT_NODE_UP = 200;
public static readonly short EVENT_NODE_ONLINE = 201;
public static readonly short EVENT_NODE_OFFLINE = 202;
public static readonly short EVENT_NODE_DOWN = 203;
public static readonly short ZTS_EVENT_NODE_FATAL_ERROR = 204;
// Network events
public static readonly short EVENT_NETWORK_NOT_FOUND = 210;
public static readonly short EVENT_NETWORK_CLIENT_TOO_OLD = 211;
public static readonly short EVENT_NETWORK_REQ_CONFIG = 212;
public static readonly short EVENT_NETWORK_OK = 213;
public static readonly short EVENT_NETWORK_ACCESS_DENIED = 214;
public static readonly short EVENT_NETWORK_READY_IP4 = 215;
public static readonly short EVENT_NETWORK_READY_IP6 = 216;
public static readonly short EVENT_NETWORK_READY_IP4_IP6 = 217;
public static readonly short EVENT_NETWORK_DOWN = 218;
public static readonly short EVENT_NETWORK_UPDATE = 219;
public static readonly short EVENT_NETWORK_NOT_FOUND = 210;
public static readonly short EVENT_NETWORK_CLIENT_TOO_OLD = 211;
public static readonly short EVENT_NETWORK_REQ_CONFIG = 212;
public static readonly short EVENT_NETWORK_OK = 213;
public static readonly short EVENT_NETWORK_ACCESS_DENIED = 214;
public static readonly short EVENT_NETWORK_READY_IP4 = 215;
public static readonly short EVENT_NETWORK_READY_IP6 = 216;
public static readonly short EVENT_NETWORK_READY_IP4_IP6 = 217;
public static readonly short EVENT_NETWORK_DOWN = 218;
public static readonly short EVENT_NETWORK_UPDATE = 219;
// Network Stack events
public static readonly short EVENT_STACK_UP = 220;
public static readonly short EVENT_STACK_DOWN = 221;
public static readonly short EVENT_STACK_UP = 220;
public static readonly short EVENT_STACK_DOWN = 221;
// lwIP netif events
public static readonly short EVENT_NETIF_UP = 230;
public static readonly short EVENT_NETIF_DOWN = 231;
public static readonly short EVENT_NETIF_REMOVED = 232;
public static readonly short EVENT_NETIF_LINK_UP = 233;
public static readonly short EVENT_NETIF_LINK_DOWN = 234;
public static readonly short EVENT_NETIF_UP = 230;
public static readonly short EVENT_NETIF_DOWN = 231;
public static readonly short EVENT_NETIF_REMOVED = 232;
public static readonly short EVENT_NETIF_LINK_UP = 233;
public static readonly short EVENT_NETIF_LINK_DOWN = 234;
// Peer events
public static readonly short EVENT_PEER_DIRECT = 240;
public static readonly short EVENT_PEER_RELAY = 241;
public static readonly short EVENT_PEER_UNREACHABLE = 242;
public static readonly short EVENT_PEER_PATH_DISCOVERED = 243;
public static readonly short EVENT_PEER_PATH_DEAD = 244;
public static readonly short EVENT_PEER_DIRECT = 240;
public static readonly short EVENT_PEER_RELAY = 241;
public static readonly short EVENT_PEER_UNREACHABLE = 242;
public static readonly short EVENT_PEER_PATH_DISCOVERED = 243;
public static readonly short EVENT_PEER_PATH_DEAD = 244;
// Route events
public static readonly short EVENT_ROUTE_ADDED = 250;
public static readonly short EVENT_ROUTE_REMOVED = 251;
public static readonly short EVENT_ROUTE_ADDED = 250;
public static readonly short EVENT_ROUTE_REMOVED = 251;
// Address events
public static readonly short EVENT_ADDR_ADDED_IP4 = 260;
public static readonly short EVENT_ADDR_REMOVED_IP4 = 261;
public static readonly short EVENT_ADDR_ADDED_IP6 = 262;
public static readonly short EVENT_ADDR_REMOVED_IP6 = 263;
public static readonly short EVENT_ADDR_ADDED_IP4 = 260;
public static readonly short EVENT_ADDR_REMOVED_IP4 = 261;
public static readonly short EVENT_ADDR_ADDED_IP6 = 262;
public static readonly short EVENT_ADDR_REMOVED_IP6 = 263;
// Socket error codes
public static readonly short EPERM = 1; /* Operation not permitted */
public static readonly short ENOENT = 2; /* No such file or directory */
public static readonly short ESRCH = 3; /* No such process */
public static readonly short EINTR = 4; /* Interrupted system call */
public static readonly short EIO = 5; /* I/O error */
public static readonly short ENXIO = 6; /* No such device or address */
public static readonly short E2BIG = 7; /* Arg list too long */
public static readonly short ENOEXEC = 8; /* Exec format error */
public static readonly short EBADF = 9; /* Bad file number */
public static readonly short ECHILD = 10; /* No child processes */
public static readonly short EAGAIN = 11; /* Try again */
public static readonly short ENOMEM = 12; /* Out of memory */
public static readonly short EACCES = 13; /* Permission denied */
public static readonly short EFAULT = 14; /* Bad address */
public static readonly short ENOTBLK = 15; /* Block device required */
public static readonly short EBUSY = 16; /* Device or resource busy */
public static readonly short EEXIST = 17; /* File exists */
public static readonly short EXDEV = 18; /* Cross-device link */
public static readonly short ENODEV = 19; /* No such device */
public static readonly short ENOTDIR = 20; /* Not a directory */
public static readonly short EISDIR = 21; /* Is a directory */
public static readonly short EINVAL = 22; /* Invalid argument */
public static readonly short ENFILE = 23; /* File table overflow */
public static readonly short EMFILE = 24; /* Too many open files */
public static readonly short ENOTTY = 25; /* Not a typewriter */
public static readonly short ETXTBSY = 26; /* Text file busy */
public static readonly short EFBIG = 27; /* File too large */
public static readonly short ENOSPC = 28; /* No space left on device */
public static readonly short ESPIPE = 29; /* Illegal seek */
public static readonly short EROFS = 30; /* Read-only file system */
public static readonly short EMLINK = 31; /* Too many links */
public static readonly short EPIPE = 32; /* Broken pipe */
public static readonly short EDOM = 33; /* Math argument out of domain of func */
public static readonly short ERANGE = 34; /* Math result not representable */
public static readonly short EDEADLK = 35; /* Resource deadlock would occur */
public static readonly short ENAMETOOLONG = 36; /* File name too long */
public static readonly short ENOLCK = 37; /* No record locks available */
public static readonly short ENOSYS = 38; /* Function not implemented */
public static readonly short ENOTEMPTY = 39; /* Directory not empty */
public static readonly short ELOOP = 40; /* Too many symbolic links encountered */
public static readonly short EWOULDBLOCK = EAGAIN; /* Operation would block */
public static readonly short ENOMSG = 42; /* No message of desired type */
public static readonly short EIDRM = 43; /* Identifier removed */
public static readonly short ECHRNG = 44; /* Channel number out of range */
public static readonly short EL2NSYNC = 45; /* Level 2 not synchronized */
public static readonly short EL3HLT = 46; /* Level 3 halted */
public static readonly short EL3RST = 47; /* Level 3 reset */
public static readonly short ELNRNG = 48; /* Link number out of range */
public static readonly short EUNATCH = 49; /* Protocol driver not attached */
public static readonly short ENOCSI = 50; /* No CSI structure available */
public static readonly short EL2HLT = 51; /* Level 2 halted */
public static readonly short EBADE = 52; /* Invalid exchange */
public static readonly short EBADR = 53; /* Invalid request descriptor */
public static readonly short EXFULL = 54; /* Exchange full */
public static readonly short ENOANO = 55; /* No anode */
public static readonly short EBADRQC = 56; /* Invalid request code */
public static readonly short EBADSLT = 57; /* Invalid slot */
public static readonly short EVENT_STORE_IDENTITY_SECRET = 270;
public static readonly short EVENT_STORE_IDENTITY_PUBLIC = 271;
public static readonly short EVENT_STORE_PLANET = 272;
public static readonly short EVENT_STORE_PEER = 273;
public static readonly short EVENT_STORE_NETWORK = 274;
public static readonly short EDEADLOCK = EDEADLK;
// Socket error codes
public static readonly short EPERM = 1;
public static readonly short ENOENT = 2;
public static readonly short ESRCH = 3;
public static readonly short EINTR = 4;
public static readonly short EIO = 5;
public static readonly short ENXIO = 6;
public static readonly short EBADF = 9;
public static readonly short EAGAIN = 11;
public static readonly short EWOULDBLOCK = 11;
public static readonly short ENOMEM = 12;
public static readonly short EACCES = 13;
public static readonly short EFAULT = 14;
public static readonly short EBUSY = 16;
public static readonly short EEXIST = 17;
public static readonly short ENODEV = 19;
public static readonly short EINVAL = 22;
public static readonly short ENFILE = 23;
public static readonly short EMFILE = 24;
public static readonly short ENOSYS = 38;
public static readonly short ENOTSOCK = 88;
public static readonly short EDESTADDRREQ = 89;
public static readonly short EMSGSIZE = 90;
public static readonly short EPROTOTYPE = 91;
public static readonly short ENOPROTOOPT = 92;
public static readonly short EPROTONOSUPPORT = 93;
public static readonly short ESOCKTNOSUPPORT = 94;
public static readonly short EOPNOTSUPP = 95;
public static readonly short EPFNOSUPPORT = 96;
public static readonly short EAFNOSUPPORT = 97;
public static readonly short EADDRINUSE = 98;
public static readonly short EADDRNOTAVAIL = 99;
public static readonly short ENETDOWN = 100;
public static readonly short ENETUNREACH = 101;
public static readonly short ECONNABORTED = 103;
public static readonly short ECONNRESET = 104;
public static readonly short ENOBUFS = 105;
public static readonly short EISCONN = 106;
public static readonly short ENOTCONN = 107;
public static readonly short ETIMEDOUT = 110;
public static readonly short EHOSTUNREACH = 113;
public static readonly short EALREADY = 114;
public static readonly short EINPROGRESS = 115;
public static readonly short EBFONT = 59; /* Bad font file format */
public static readonly short ENOSTR = 60; /* Device not a stream */
public static readonly short ENODATA = 61; /* No data available */
public static readonly short ETIME = 62; /* Timer expired */
public static readonly short ENOSR = 63; /* Out of streams resources */
public static readonly short ENONET = 64; /* Machine is not on the network */
public static readonly short ENOPKG = 65; /* Package not installed */
public static readonly short EREMOTE = 66; /* Object is remote */
public static readonly short ENOLINK = 67; /* Link has been severed */
public static readonly short EADV = 68; /* Advertise error */
public static readonly short ESRMNT = 69; /* Srmount error */
public static readonly short ECOMM = 70; /* Communication error on send */
public static readonly short EPROTO = 71; /* Protocol error */
public static readonly short EMULTIHOP = 72; /* Multihop attempted */
public static readonly short EDOTDOT = 73; /* RFS specific error */
public static readonly short EBADMSG = 74; /* Not a data message */
public static readonly short EOVERFLOW = 75; /* Value too large for defined data type */
public static readonly short ENOTUNIQ = 76; /* Name not unique on network */
public static readonly short EBADFD = 77; /* File descriptor in bad state */
public static readonly short EREMCHG = 78; /* Remote address changed */
public static readonly short ELIBACC = 79; /* Can not access a needed shared library */
public static readonly short ELIBBAD = 80; /* Accessing a corrupted shared library */
public static readonly short ELIBSCN = 81; /* .lib section in a.out corrupted */
public static readonly short ELIBMAX = 82; /* Attempting to link in too many shared libraries */
public static readonly short ELIBEXEC = 83; /* Cannot exec a shared library directly */
public static readonly short EILSEQ = 84; /* Illegal byte sequence */
public static readonly short ERESTART = 85; /* Interrupted system call should be restarted */
public static readonly short ESTRPIPE = 86; /* Streams pipe error */
public static readonly short EUSERS = 87; /* Too many users */
public static readonly short ENOTSOCK = 88; /* Socket operation on non-socket */
public static readonly short EDESTADDRREQ = 89; /* Destination address required */
public static readonly short EMSGSIZE = 90; /* Message too long */
public static readonly short EPROTOTYPE = 91; /* Protocol wrong type for socket */
public static readonly short ENOPROTOOPT = 92; /* Protocol not available */
public static readonly short EPROTONOSUPPORT = 93; /* Protocol not supported */
public static readonly short ESOCKTNOSUPPORT = 94; /* Socket type not supported */
public static readonly short EOPNOTSUPP = 95; /* Operation not supported on transport endpoint */
public static readonly short EPFNOSUPPORT = 96; /* Protocol family not supported */
public static readonly short EAFNOSUPPORT = 97; /* Address family not supported by protocol */
public static readonly short EADDRINUSE = 98; /* Address already in use */
public static readonly short EADDRNOTAVAIL = 99; /* Cannot assign requested address */
public static readonly short ENETDOWN = 100; /* Network is down */
public static readonly short ENETUNREACH = 101; /* Network is unreachable */
public static readonly short ENETRESET = 102; /* Network dropped connection because of reset */
public static readonly short ECONNABORTED = 103; /* Software caused connection abort */
public static readonly short ECONNRESET = 104; /* Connection reset by peer */
public static readonly short ENOBUFS = 105; /* No buffer space available */
public static readonly short EISCONN = 106; /* Transport endpoint is already connected */
public static readonly short ENOTCONN = 107; /* Transport endpoint is not connected */
public static readonly short ESHUTDOWN = 108; /* Cannot send after transport endpoint shutdown */
public static readonly short ETOOMANYREFS = 109; /* Too many references: cannot splice */
public static readonly short ETIMEDOUT = 110; /* Connection timed out */
public static readonly short ECONNREFUSED = 111; /* Connection refused */
public static readonly short EHOSTDOWN = 112; /* Host is down */
public static readonly short EHOSTUNREACH = 113; /* No route to host */
public static readonly short EALREADY = 114; /* Operation already in progress */
public static readonly short EINPROGRESS = 115; /* Operation now in progress */
public static readonly short ESTALE = 116; /* Stale NFS file handle */
public static readonly short EUCLEAN = 117; /* Structure needs cleaning */
public static readonly short ENOTNAM = 118; /* Not a XENIX named type file */
public static readonly short ENAVAIL = 119; /* No XENIX semaphores available */
public static readonly short EISNAM = 120; /* Is a named type file */
public static readonly short EREMOTEIO = 121; /* Remote I/O error */
public static readonly short EDQUOT = 122; /* Quota exceeded */
public static readonly short ENOMEDIUM = 123; /* No medium found */
public static readonly short EMEDIUMTYPE = 124; /* Wrong medium type */
// Common constants
public static readonly short MAC_ADDRSTRLEN = 18;
public static readonly short INET_ADDRSTRLEN = 16;
public static readonly short INET6_ADDRSTRLEN = 46;
public static readonly short IP_MAX_STR_LEN = 46;
public static readonly short STORE_DATA_LEN = 4096;
public static readonly short MAX_NETWORK_SHORT_NAME_LENGTH = 127;
public static readonly short MAX_NETWORK_ROUTES = 32;
public static readonly short MAX_ASSIGNED_ADDRESSES = 16;
public static readonly short MAX_PEER_NETWORK_PATHS = 16;
public static readonly short MAX_MULTICAST_SUBSCRIPTIONS = 1024;
public static readonly short INET_ADDRSTRLEN = 16;
public static readonly short INET6_ADDRSTRLEN = 46;
// Peer roles
public static readonly byte PEER_ROLE_LEAF = 0;
public static readonly byte PEER_ROLE_MOON = 1;
public static readonly byte PEER_ROLE_PLANET = 2;
/** 255.255.255.255 */
//public static readonly uint IPADDR_NONE =((uint32_t)0xffffffffUL);
/** 127.0.0.1 */
//public static readonly uint IPADDR_LOOPBACK =((uint32_t)0x7f000001UL);
/** 0.0.0.0 */
//public static readonly uint IPADDR_ANY =((uint32_t)0x00000000UL);
/** 255.255.255.255 */
//public static readonly uint IPADDR_BROADCAST =((uint32_t)0xffffffffUL);
// Network status codes
public static readonly byte NETWORK_STATUS_REQUESTING_CONFIGURATION = 0;
public static readonly byte NETWORK_STATUS_OK = 1;
public static readonly byte NETWORK_STATUS_ACCESS_DENIED = 2;
public static readonly byte NETWORK_STATUS_NOT_FOUND = 3;
public static readonly byte NETWORK_STATUS_PORT_ERROR = 4;
public static readonly byte NETWORK_STATUS_CLIENT_TOO_OLD = 5;
/** 255.255.255.255 */
//public static readonly uint INADDR_NONE =IPADDR_NONE;
/** 127.0.0.1 */
//public static readonly uint INADDR_LOOPBACK =IPADDR_LOOPBACK;
/** 0.0.0.0 */
//public static readonly uint INADDR_ANY =IPADDR_ANY;
/** 255.255.255.255 */
//public static readonly uint INADDR_BROADCAST =IPADDR_BROADCAST;
//
public static readonly byte NETWORK_TYPE_PRIVATE = 0;
public static readonly byte NETWORK_TYPE_PUBLIC = 1;
// Socket protocol types
public static readonly short SOCK_STREAM = 0x0001;
public static readonly short SOCK_DGRAM = 0x0002;
public static readonly short SOCK_RAW = 0x0003;
// Socket family types
public static readonly short AF_UNSPEC = 0x0000;
public static readonly short AF_INET = 0x0002;
public static readonly short AF_INET6 = 0x000a;
public static readonly short PF_INET = AF_INET;
public static readonly short PF_INET6 = AF_INET6;
public static readonly short PF_UNSPEC = AF_UNSPEC;
// Protocol command types
public static readonly short IPPROTO_IP = 0x0000;
public static readonly short IPPROTO_ICMP = 0x0001;
public static readonly short IPPROTO_TCP = 0x0006;
public static readonly short IPPROTO_UDP = 0x0011;
public static readonly short IPPROTO_IPV6 = 0x0029;
public static readonly short IPPROTO_ICMPV6 = 0x003a;
public static readonly short IPPROTO_UDPLITE = 0x0088;
public static readonly short IPPROTO_RAW = 0x00ff;
// send() and recv() flags
public static readonly short MSG_PEEK = 0x0001;
public static readonly short MSG_WAITALL = 0x0002; // NOT YET SUPPORTED
public static readonly short MSG_OOB = 0x0004; // NOT YET SUPPORTED
public static readonly short MSG_DONTWAIT = 0x0008;
public static readonly short MSG_MORE = 0x0010;
// Socket protocol types
public static readonly short SOCK_STREAM = 0x0001;
public static readonly short SOCK_DGRAM = 0x0002;
public static readonly short SOCK_RAW = 0x0003;
// Socket family types
public static readonly short AF_UNSPEC = 0x0000;
public static readonly short AF_INET = 0x0002;
public static readonly short AF_INET6 = 0x000a;
public static readonly short PF_INET = AF_INET;
public static readonly short PF_INET6 = AF_INET6;
public static readonly short PF_UNSPEC = AF_UNSPEC;
// Protocol command types
public static readonly short IPPROTO_IP = 0x0000;
public static readonly short IPPROTO_ICMP = 0x0001;
public static readonly short IPPROTO_TCP = 0x0006;
public static readonly short IPPROTO_UDP = 0x0011;
public static readonly short IPPROTO_IPV6 = 0x0029;
public static readonly short IPPROTO_ICMPV6 = 0x003a;
public static readonly short IPPROTO_UDPLITE = 0x0088;
public static readonly short IPPROTO_RAW = 0x00ff;
// send() and recv() flags
public static readonly short MSG_PEEK = 0x0001;
public static readonly short MSG_WAITALL = 0x0002; // NOT YET SUPPORTED
public static readonly short MSG_OOB = 0x0004; // NOT YET SUPPORTED
public static readonly short MSG_DONTWAIT = 0x0008;
public static readonly short MSG_MORE = 0x0010;
// Macros for defining ioctl() command values
/*
public static readonly ulong IOCPARM_MASK = 0x7fU;
public static readonly ulong IOC_VOID = 0x20000000UL;
public static readonly ulong IOC_OUT = 0x40000000UL;
public static readonly ulong IOC_IN = 0x80000000UL;
public static readonly ulong IOC_INOUT = (IOC_IN | IOC_OUT);
public static readonly ulong IO(x,y) = (IOC_VOID | ((x)<<8)|(y));
public static readonly ulong IOR(x,y,t) = (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK)<<16) | ((x)<<8) | (y));
public static readonly ulong IOW(x,y,t) = (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK)<<16) | ((x)<<8) | (y));
// ioctl() commands
public static readonly ulong FIONREAD = IOR('f', 127, unsigned long);
public static readonly ulong FIONBIO = IOW('f', 126, unsigned long);
*/
// Socket level option number
public static readonly short SOL_SOCKET = 0x0fff;
// Socket options
public static readonly short SO_DEBUG = 0x0001; // NOT YET SUPPORTED
public static readonly short SO_ACCEPTCONN = 0x0002;
public static readonly short SO_REUSEADDR = 0x0004;
public static readonly short SO_KEEPALIVE = 0x0008;
public static readonly short SO_DONTROUTE = 0x0010; // NOT YET SUPPORTED
public static readonly short SO_BROADCAST = 0x0020;
public static readonly short SO_USELOOPBACK = 0x0040; // NOT YET SUPPORTED
public static readonly short SO_LINGER = 0x0080;
public static readonly short SO_DONTLINGER = ((short)(~SO_LINGER));
public static readonly short SO_OOBINLINE = 0x0100; // NOT YET SUPPORTED
public static readonly short SO_REUSEPORT = 0x0200; // NOT YET SUPPORTED
public static readonly short SO_SNDBUF = 0x1001; // NOT YET SUPPORTED
public static readonly short SO_RCVBUF = 0x1002;
public static readonly short SO_SNDLOWAT = 0x1003; // NOT YET SUPPORTED
public static readonly short SO_RCVLOWAT = 0x1004; // NOT YET SUPPORTED
public static readonly short SO_SNDTIMEO = 0x1005;
public static readonly short SO_RCVTIMEO = 0x1006;
public static readonly short SO_ERROR = 0x1007;
public static readonly short SO_TYPE = 0x1008;
public static readonly short SO_CONTIMEO = 0x1009;
public static readonly short SO_NO_CHECK = 0x100a;
public static readonly short SO_BINDTODEVICE = 0x100b;
// IPPROTO_IP options
public static readonly short IP_TOS = 0x0001;
public static readonly short IP_TTL = 0x0002;
public static readonly short IP_PKTINFO = 0x0008;
// IPPROTO_TCP options
public static readonly short TCP_NODELAY = 0x0001;
public static readonly short TCP_KEEPALIVE = 0x0002;
public static readonly short TCP_KEEPIDLE = 0x0003;
public static readonly short TCP_KEEPINTVL = 0x0004;
public static readonly short TCP_KEEPCNT = 0x0005;
// IPPROTO_IPV6 options
public static readonly short IPV6_CHECKSUM =
0x0007; // RFC3542: calculate and insert the ICMPv6 checksum for raw sockets.
public static readonly short IPV6_V6ONLY =
0x001b; // RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only.
// UDPLITE options
public static readonly short UDPLITE_SEND_CSCOV = 0x01; // sender checksum coverage
public static readonly short UDPLITE_RECV_CSCOV = 0x02; // minimal receiver checksum coverage
// UDPLITE options
public static readonly short IP_MULTICAST_TTL = 5;
public static readonly short IP_MULTICAST_IF = 6;
public static readonly short IP_MULTICAST_LOOP = 7;
// Socket level option number
public static readonly short SOL_SOCKET = 0x0fff;
// Socket options
public static readonly short SO_DEBUG = 0x0001; // NOT YET SUPPORTED
public static readonly short SO_ACCEPTCONN = 0x0002;
public static readonly short SO_REUSEADDR = 0x0004;
public static readonly short SO_KEEPALIVE = 0x0008;
public static readonly short SO_DONTROUTE = 0x0010; // NOT YET SUPPORTED
public static readonly short SO_BROADCAST = 0x0020;
public static readonly short SO_USELOOPBACK = 0x0040; // NOT YET SUPPORTED
public static readonly short SO_LINGER = 0x0080;
public static readonly short SO_DONTLINGER = ((short)(~SO_LINGER));
public static readonly short SO_OOBINLINE = 0x0100; // NOT YET SUPPORTED
public static readonly short SO_REUSEPORT = 0x0200; // NOT YET SUPPORTED
public static readonly short SO_SNDBUF = 0x1001; // NOT YET SUPPORTED
public static readonly short SO_RCVBUF = 0x1002;
public static readonly short SO_SNDLOWAT = 0x1003; // NOT YET SUPPORTED
public static readonly short SO_RCVLOWAT = 0x1004; // NOT YET SUPPORTED
public static readonly short SO_SNDTIMEO = 0x1005;
public static readonly short SO_RCVTIMEO = 0x1006;
public static readonly short SO_ERROR = 0x1007;
public static readonly short SO_TYPE = 0x1008;
public static readonly short SO_CONTIMEO = 0x1009;
public static readonly short SO_NO_CHECK = 0x100a;
public static readonly short SO_BINDTODEVICE = 0x100b;
// IPPROTO_IP options
public static readonly short IP_TOS = 0x0001;
public static readonly short IP_TTL = 0x0002;
public static readonly short IP_PKTINFO = 0x0008;
// IPPROTO_TCP options
public static readonly short TCP_NODELAY = 0x0001;
public static readonly short TCP_KEEPALIVE = 0x0002;
public static readonly short TCP_KEEPIDLE = 0x0003;
public static readonly short TCP_KEEPINTVL = 0x0004;
public static readonly short TCP_KEEPCNT = 0x0005;
// IPPROTO_IPV6 options
public static readonly short IPV6_CHECKSUM = 0x0007; // RFC3542: calculate and insert the ICMPv6 checksum for raw sockets.
public static readonly short IPV6_V6ONLY = 0x001b; // RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only.
// UDPLITE options
public static readonly short UDPLITE_SEND_CSCOV = 0x01; // sender checksum coverage
public static readonly short UDPLITE_RECV_CSCOV = 0x02; // minimal receiver checksum coverage
// UDPLITE options
public static readonly short IP_MULTICAST_TTL = 5;
public static readonly short IP_MULTICAST_IF = 6;
public static readonly short IP_MULTICAST_LOOP = 7;
// Multicast options
public static readonly short IP_ADD_MEMBERSHIP = 3;
public static readonly short IP_DROP_MEMBERSHIP = 4;
// Multicast options
public static readonly short IP_ADD_MEMBERSHIP = 3;
public static readonly short IP_DROP_MEMBERSHIP = 4;
public static readonly short IPV6_JOIN_GROUP = 12;
public static readonly short IPV6_ADD_MEMBERSHIP = IPV6_JOIN_GROUP;
public static readonly short IPV6_LEAVE_GROUP = 13;
public static readonly short IPV6_DROP_MEMBERSHIP = IPV6_LEAVE_GROUP;
public static readonly short IPV6_JOIN_GROUP = 12;
public static readonly short IPV6_ADD_MEMBERSHIP = IPV6_JOIN_GROUP;
public static readonly short IPV6_LEAVE_GROUP = 13;
public static readonly short IPV6_DROP_MEMBERSHIP = IPV6_LEAVE_GROUP;
// Polling options
public static readonly short POLLIN = 0x001;
public static readonly short POLLOUT = 0x002;
public static readonly short POLLERR = 0x004;
public static readonly short POLLNVAL = 0x008;
// Below values are unimplemented
public static readonly short POLLRDNORM = 0x010;
public static readonly short POLLRDBAND = 0x020;
public static readonly short POLLPRI = 0x040;
public static readonly short POLLWRNORM = 0x080;
public static readonly short POLLWRBAND = 0x100;
public static readonly short POLLHUP = 0x200;
// Polling options
public static readonly short POLLIN = 0x001;
public static readonly short POLLOUT = 0x002;
public static readonly short POLLERR = 0x004;
public static readonly short POLLNVAL = 0x008;
// Below values are unimplemented
public static readonly short POLLRDNORM = 0x010;
public static readonly short POLLRDBAND = 0x020;
public static readonly short POLLPRI = 0x040;
public static readonly short POLLWRNORM = 0x080;
public static readonly short POLLWRBAND = 0x100;
public static readonly short POLLHUP = 0x200;
public static readonly short F_GETFL = 0x0003;
public static readonly short F_SETFL = 0x0004;
public static readonly short F_GETFL = 0x0003;
public static readonly short F_SETFL = 0x0004;
// File status flags and file access modes for fnctl, these are bits in an int.
public static readonly short O_NONBLOCK = 1;
public static readonly short O_NDELAY = O_NONBLOCK;
public static readonly short O_RDONLY = 2;
public static readonly short O_WRONLY = 4;
public static readonly short O_RDWR = (short)(O_RDONLY | O_WRONLY);
// File status flags and file access modes for fnctl, these are bits in an int.
public static readonly short O_NONBLOCK = 1;
public static readonly short O_NDELAY = O_NONBLOCK;
public static readonly short O_RDONLY = 2;
public static readonly short O_WRONLY = 4;
public static readonly short O_RDWR = (short)(O_RDONLY|O_WRONLY);
public static readonly short MSG_TRUNC = 0x04;
public static readonly short MSG_CTRUNC = 0x08;
public static readonly short MSG_TRUNC = 0x04;
public static readonly short MSG_CTRUNC = 0x08;
public static readonly short SHUT_RD = 0x0;
public static readonly short SHUT_WR = 0x1;
public static readonly short SHUT_RDWR = 0x2;
}
public static readonly short SHUT_RD = 0x0;
public static readonly short SHUT_WR = 0x1;
public static readonly short SHUT_RDWR = 0x2;
}
}

147
src/bindings/csharp/Event.cs Normal file → Executable file
View File

@@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2025-01-01
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
@@ -17,140 +17,13 @@ using ZeroTier;
namespace ZeroTier.Core
{
/* Convenience structures for exposing lower level operational details to the user.
These structures do not have the same memory layout or content as those found in
include/ZeroTierSockets.h */
/// <summary>
/// Structure containing information about the local Node.
/// </summary>
public class NodeDetails
{
// Node ID
public ulong nodeId;
/**
* The port used by the service to send and receive
* all encapsulated traffic
*/
public ushort primaryPort;
public ushort secondaryPort;
public ushort tertiaryPort;
/**
* ZT version
*/
public byte versionMajor;
public byte versionMinor;
public byte versionRev;
}
public class MulticastSubscription
{
ulong macAddress;
uint AdditionalDistinguishingInformation;
}
/// <summary>
/// Structure containing information about virtual networks.
/// </summary>
public class NetworkDetails
{
public ulong networkId;
public ulong macAddress;
public string networkName;
//public byte status;
public byte type;
public ushort mtu;
public bool bridgingAllowed;
public bool broadcastEnabled;
//public int portError;
public IPAddress[] assignedAddresses;
public IPAddress[] routes;
public MulticastSubscription[] multicastSubscroptions;
}
/// <summary>
/// Structure containing state information about the low-level ethernet driver.
/// </summary>
public class NetifDetails
{
public ulong networkId;
public ulong macAddress;
public int mtu;
}
/// <summary>
/// Structure containing routing information for networks.
/// </summary>
public class RouteDetails
{
public EndPoint target;
public EndPoint via;
public ushort flags;
public ushort metric;
}
/// <summary>
/// Structure containing information about remote peer reachability.
/// </summary>
public class PeerDetails
{
ulong nodeId;
byte versionMajor;
byte versionMinor;
byte versionRev;
int latency;
byte role;
IPAddress[] paths;
}
/// <summary>
/// Structure containing information about assigned addresses.
/// </summary>
public class AddrDetails
{
ulong networkId;
IPAddress address;
}
/// <summary>
/// Class used to convey details of a low-level network event to the user.
/// </summary>
public class Event
{
int _eventCode;
string _eventName;
public NodeDetails nodeDetails;
public NetworkDetails networkDetails;
public NetifDetails netifDetails;
public RouteDetails routeDetails;
public PeerDetails peerDetails;
public AddrDetails addrDetails;
public Event(int eventCode, string eventName)
{
_eventCode = eventCode;
_eventName = eventName;
nodeDetails = null;
networkDetails = null;
netifDetails = null;
routeDetails = null;
peerDetails = null;
addrDetails = null;
}
public int EventCode {
get {
return _eventCode;
}
}
public string EventName {
get {
return _eventName;
}
}
}
public class Event {
public NodeInfo NodeInfo { get; set; }
public NetworkInfo NetworkInfo { get; set; }
public RouteInfo RouteInfo { get; set; }
public PeerInfo PeerInfo { get; set; }
public AddressInfo AddressInfo { get; set; }
public int Code { get; set; }
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
using System.Net;
using ZeroTier;
namespace ZeroTier.Core
{
public class MulticastInfo {
public ulong MACAddress;
public uint additionalDistinguishingInformation;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
using System.Net;
using System.Collections.Concurrent;
using System.Collections.Generic;
using ZeroTier;
namespace ZeroTier.Core
{
public class NetworkInfo {
public ulong Id { get; set; }
public ulong MACAddress;
public string Name;
public int Status;
public int Type;
public uint MTU;
public int DHCP;
public bool Bridge;
public bool BroadcastEnabled;
internal bool transportReady; // Synthetic value
public bool IsPrivate
{
get {
return Type == Constants.NETWORK_TYPE_PRIVATE;
}
}
public bool IsPublic
{
get {
return Type == Constants.NETWORK_TYPE_PUBLIC;
}
}
internal ConcurrentDictionary<string, IPAddress> _addrs = new ConcurrentDictionary<string, IPAddress>();
public ICollection<IPAddress> Addresses
{
get {
return _addrs.Values;
}
}
internal ConcurrentDictionary<string, ZeroTier.Core.RouteInfo> _routes =
new ConcurrentDictionary<string, ZeroTier.Core.RouteInfo>();
public ICollection<ZeroTier.Core.RouteInfo> Routes
{
get {
return _routes.Values;
}
}
}
}

1200
src/bindings/csharp/Node.cs Normal file → Executable file

File diff suppressed because it is too large Load Diff

46
src/bindings/csharp/NodeInfo.cs Executable file
View File

@@ -0,0 +1,46 @@
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
using System.Net;
using ZeroTier;
namespace ZeroTier.Core
{
/* Convenience structures for exposing lower level operational details to the user.
These structures do not have the same memory layout or content as those found in
include/ZeroTierSockets.h */
/// <summary>
/// Structure containing information about the local Node.
/// </summary>
public class NodeInfo {
// Node ID
public ulong Id { get; set; }
/**
* The port used by the service to send and receive
* all encapsulated traffic
*/
public ushort PrimaryPort { get; set; }
public ushort SecondaryPort { get; set; }
public ushort TertiaryPort { get; set; }
/**
* ZT version
*/
public byte VersionMajor { get; set; }
public byte VersionMinor { get; set; }
public byte VersionRev { get; set; }
}
}

68
src/bindings/csharp/PeerInfo.cs Executable file
View File

@@ -0,0 +1,68 @@
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
using System.Net;
using System.Collections.Concurrent;
using System.Collections.Generic;
using ZeroTier;
namespace ZeroTier.Core
{
public class PeerInfo {
public PeerInfo(ulong id, short versionMajor, short versionMinor, short versionRev, byte role)
{
_id = id;
_versionMajor = versionMajor;
_versionMinor = versionMinor;
_versionRev = versionRev;
_role = role;
}
ulong _id;
short _versionMajor;
short _versionMinor;
short _versionRev;
byte _role;
internal ConcurrentDictionary<string, IPEndPoint> _paths = new ConcurrentDictionary<string, IPEndPoint>();
public ICollection<IPEndPoint> Paths
{
get {
return _paths.Values;
}
}
public ulong Id
{
get {
return _id;
}
}
public byte Role
{
get {
return _role;
}
}
public string Version
{
get {
return string.Format("{0}.{1}.{2}", _versionMajor, _versionMinor, _versionRev);
}
}
}
}

0
src/bindings/csharp/README.md Normal file → Executable file
View File

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c)2013-2021 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
*/
/****/
using System.Net;
using ZeroTier;
namespace ZeroTier.Core
{
public class RouteInfo {
public RouteInfo(IPAddress target, IPAddress via, ushort flags, ushort metric)
{
_target = target;
_via = via;
_flags = flags;
_metric = metric;
}
public IPAddress _target;
public IPAddress _via;
public ushort _flags;
public ushort _metric;
public IPAddress Target
{
get {
return _target;
}
}
public IPAddress Via
{
get {
return _via;
}
}
public ushort Flags
{
get {
return _flags;
}
}
public ushort Metric
{
get {
return _metric;
}
}
}
}

1308
src/bindings/csharp/Socket.cs Normal file → Executable file

File diff suppressed because it is too large Load Diff

42
src/bindings/csharp/SocketException.cs Normal file → Executable file
View File

@@ -4,7 +4,7 @@
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 2025-01-01
* Change Date: 2026-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2.0 of the Apache License.
@@ -15,24 +15,26 @@ using System;
namespace ZeroTier.Sockets
{
/// <summary>Exception class for ZeroTier service and low-level socket errors</summary>
public class SocketException : Exception
{
public SocketException(int _serviceErrorCode)
: base(String.Format("ServiceErrorCode={0} (See Constants.cs for error code meanings)", _serviceErrorCode))
{
ServiceErrorCode = _serviceErrorCode;
}
public SocketException(int _serviceErrorCode, int _socketErrorCode)
: base(String.Format("ServiceErrorCode={0}, SocketErrorCode={1} (See Constants.cs for error code meanings)", _serviceErrorCode, _socketErrorCode))
{
ServiceErrorCode = _serviceErrorCode;
SocketErrorCode = _socketErrorCode;
}
/// <value>High-level service error code. See Constants.cs</value>
public int ServiceErrorCode { get; private set; }
/// <summary>Exception class for ZeroTier service and low-level socket errors</summary>
public class SocketException : Exception {
public SocketException(int _serviceErrorCode)
: base(String.Format("ServiceErrorCode={0} (See Constants.cs for error code meanings)", _serviceErrorCode))
{
ServiceErrorCode = _serviceErrorCode;
}
public SocketException(int _serviceErrorCode, int _socketErrorCode)
: base(String.Format(
"ServiceErrorCode={0}, SocketErrorCode={1} (See Constants.cs for error code meanings)",
_serviceErrorCode,
_socketErrorCode))
{
ServiceErrorCode = _serviceErrorCode;
SocketErrorCode = _socketErrorCode;
}
/// <value>High-level service error code. See Constants.cs</value>
public int ServiceErrorCode { get; private set; }
/// <value>Low-level socket error code. See Constants.cs</value>
public int SocketErrorCode { get; private set; }
}
/// <value>Low-level socket error code. See Constants.cs</value>
public int SocketErrorCode { get; private set; }
}
}

20
src/bindings/csharp/zt.i Normal file → Executable file
View File

@@ -27,18 +27,18 @@
%ignore zts_sockaddr_storage;
%ignore zts_sockaddr_in6;
%ignore zts_callback_msg;
%ignore zts_node_details;
%ignore zts_network_details;
%ignore zts_netif_details;
%ignore zts_virtual_network_route;
%ignore zts_peer_details;
%ignore zts_addr_details;
%ignore zts_event_msg_t;
%ignore zts_node_info_t;
%ignore zts_net_info_t;
%ignore zts_netif_info_t;
%ignore zts_route_info_t;
%ignore zts_peer_info_t;
%ignore zts_addr_info_t;
#define ZTS_CSHARP=1
#define ZTS_ENABLE_PINVOKE 1
%{
#include "../../include/ZeroTierSockets.h"
#include "../../../include/ZeroTierSockets.h"
%}
// Typemap for our event callback
@@ -52,4 +52,4 @@
%enddef
%cs_callback(CppCallback, CSharpCallbackWithStruct)
%include "../../include/ZeroTierSockets.h"
%include "../../../include/ZeroTierSockets.h"

File diff suppressed because it is too large Load Diff

266
test/selftest.cs Normal file
View File

@@ -0,0 +1,266 @@
using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using ZeroTier;
public class ExampleApp {
// ZeroTier Node instance
ZeroTier.Core.Node node;
// Initialize and start ZeroTier
public void StartZeroTier(string configFilePath, ulong networkId)
{
node = new ZeroTier.Core.Node();
// (OPTIONAL) Initialize node
node.InitFromStorage(configFilePath);
node.InitAllowNetworkCaching(false);
node.InitAllowPeerCaching(true);
// node.InitAllowIdentityCaching(true);
// node.InitAllowWorldCaching(false);
node.InitSetEventHandler(OnZeroTierEvent);
node.InitSetPort(0); // Will randomly attempt ports if set to 0
// (OPTIONAL) Set custom signed roots
// In this case we only allow ZeroTier to contact our Amsterdam root server
// To see examples of how to generate and sign roots definitions see docs.zerotier.com
var rootsData = new byte[] {
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xea, 0xc9, 0x0a, 0x00, 0x00, 0x01, 0x6c, 0xe3, 0xe2, 0x39, 0x55, 0x74,
0xeb, 0x27, 0x9d, 0xc9, 0xe7, 0x5a, 0x52, 0xbb, 0x91, 0x8f, 0xf7, 0x43, 0x3c, 0xbf, 0x77, 0x5a, 0x4b, 0x57,
0xb4, 0xe1, 0xe9, 0xa1, 0x01, 0x61, 0x3d, 0x25, 0x35, 0x60, 0xcb, 0xe3, 0x30, 0x18, 0x1e, 0x6e, 0x44, 0xef,
0x93, 0x89, 0xa0, 0x19, 0xb8, 0x7b, 0x36, 0x0b, 0x92, 0xff, 0x0f, 0x1b, 0xbe, 0x56, 0x5a, 0x46, 0x91, 0x36,
0xf1, 0xd4, 0x5c, 0x09, 0x05, 0xe5, 0xf5, 0xfb, 0xba, 0xe8, 0x13, 0x2d, 0x47, 0xa8, 0xe4, 0x1b, 0xa5, 0x1c,
0xcf, 0xb0, 0x2f, 0x27, 0x7e, 0x95, 0xa0, 0xdd, 0x49, 0xe1, 0x7d, 0xc0, 0x7e, 0x6d, 0xe3, 0x25, 0x91, 0x96,
0xc2, 0x55, 0xf9, 0x20, 0x6d, 0x2a, 0x5e, 0x1b, 0x41, 0xcb, 0x1f, 0x8d, 0x57, 0x27, 0x69, 0x3e, 0xcc, 0x7f,
0x0b, 0x36, 0x54, 0x6b, 0xd3, 0x80, 0x78, 0xf6, 0xd0, 0xec, 0xb4, 0x31, 0x6b, 0x87, 0x1b, 0x50, 0x08, 0xe4,
0x0b, 0xa9, 0xd4, 0xfd, 0x37, 0x79, 0x14, 0x6a, 0xf5, 0x12, 0xf2, 0x45, 0x39, 0xca, 0x23, 0x00, 0x39, 0xbc,
0xa3, 0x1e, 0xa8, 0x4e, 0x23, 0x2d, 0xc8, 0xdb, 0x9b, 0x0e, 0x52, 0x1b, 0x8d, 0x02, 0x72, 0x01, 0x99, 0x2f,
0xcf, 0x1d, 0xb7, 0x00, 0x20, 0x6e, 0xd5, 0x93, 0x50, 0xb3, 0x19, 0x16, 0xf7, 0x49, 0xa1, 0xf8, 0x5d, 0xff,
0xb3, 0xa8, 0x78, 0x7d, 0xcb, 0xf8, 0x3b, 0x8c, 0x6e, 0x94, 0x48, 0xd4, 0xe3, 0xea, 0x0e, 0x33, 0x69, 0x30,
0x1b, 0xe7, 0x16, 0xc3, 0x60, 0x93, 0x44, 0xa9, 0xd1, 0x53, 0x38, 0x50, 0xfb, 0x44, 0x60, 0xc5, 0x0a, 0xf4,
0x33, 0x22, 0xbc, 0xfc, 0x8e, 0x13, 0xd3, 0x30, 0x1a, 0x1f, 0x10, 0x03, 0xce, 0xb6, 0x00, 0x02, 0x04, 0xc3,
0xb5, 0xad, 0x9f, 0x27, 0x09, 0x06, 0x2a, 0x02, 0x6e, 0xa0, 0xc0, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x27, 0x09
};
node.InitSetRoots(rootsData, rootsData.Length);
node.Start(); // Network activity only begins after calling Start()
while (! node.Online) {
Thread.Sleep(50);
}
Console.WriteLine("Id : " + node.IdString);
Console.WriteLine("Version : " + node.Version);
Console.WriteLine("PrimaryPort : " + node.PrimaryPort);
Console.WriteLine("SecondaryPort : " + node.SecondaryPort);
Console.WriteLine("TertiaryPort : " + node.TertiaryPort);
node.Join(networkId);
Console.WriteLine("Waiting for join to complete...");
while (node.Networks.Count == 0) {
Thread.Sleep(50);
}
// Wait until we've joined the network and we have routes + addresses
Console.WriteLine("Waiting for network to become transport ready...");
while (! node.IsNetworkTransportReady(networkId)) {
Thread.Sleep(50);
}
Console.WriteLine("Num of assigned addresses : " + node.GetNetworkAddresses(networkId).Count);
foreach (IPAddress addr in node.GetNetworkAddresses(networkId)) {
Console.WriteLine(" - Address: " + addr);
}
Console.WriteLine("Num of routes : " + node.GetNetworkRoutes(networkId).Count);
foreach (ZeroTier.Core.RouteInfo route in node.GetNetworkRoutes(networkId)) {
Console.WriteLine(
" - Route: target={0} via={1} flags={2} metric={3}",
route.Target.ToString(),
route.Via.ToString(),
route.Flags,
route.Metric);
}
}
/**
* Stop ZeroTier
*/
public void StopZeroTier()
{
node.Free();
}
/**
* (OPTIONAL)
*
* Your application should process event messages and return control as soon as possible. Blocking
* or otherwise time-consuming operations are not recommended here.
*/
public void OnZeroTierEvent(ZeroTier.Core.Event e)
{
Console.WriteLine("Event.Code = {0} ({1})", e.Code, e.Name);
/*
if (e.Code == ZeroTier.Constants.EVENT_NODE_ONLINE) {
Console.WriteLine("Node is online");
Console.WriteLine(" - Address (NodeId): " + node.Id.ToString("x16"));
}
if (e.Code == ZeroTier.Constants.EVENT_NETWORK_OK) {
Console.WriteLine(" - Network ID: " + e.NetworkInfo.Id.ToString("x16"));
}
*/
}
/**
* Example server
*/
public void SocketServer(IPEndPoint localEndPoint)
{
string data = null;
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
Console.WriteLine(localEndPoint.ToString());
ZeroTier.Sockets.Socket listener =
new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and
// listen for incoming connections.
try {
listener.Bind(localEndPoint);
listener.Listen(10);
ZeroTier.Sockets.Socket handler;
Console.WriteLine("Server: Accepting...");
handler = listener.Accept();
data = null;
Console.WriteLine("Server: Accepted connection from: " + handler.RemoteEndPoint.ToString());
for (int i = 0; i < 4; i++) {
int bytesRec = 0;
try {
Console.WriteLine("Server: Receiving...");
bytesRec = handler.Receive(bytes);
}
catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(
"ServiceErrorCode={0} SocketErrorCode={1}",
e.ServiceErrorCode,
e.SocketErrorCode);
}
if (bytesRec > 0) {
Console.WriteLine("Server: Bytes received: {0}", bytesRec);
data = Encoding.ASCII.GetString(bytes, 0, bytesRec);
Console.WriteLine("Server: Text received : {0}", data);
Thread.Sleep(1000);
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
Thread.Sleep(1000);
}
}
// Release the socket.
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(e);
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
}
}
/**
* Example client
*/
public void SocketClient(IPEndPoint remoteServerEndPoint)
{
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try {
// Create a TCP/IP socket.
ZeroTier.Sockets.Socket sender =
new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try {
Console.WriteLine("Client: Connecting to {0}...", remoteServerEndPoint.ToString());
sender.Connect(remoteServerEndPoint);
Console.WriteLine("Client: Connected to {0}", sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
for (int i = 0; i < 4; i++) {
byte[] msg = Encoding.ASCII.GetBytes("This is a test");
int bytesSent = sender.Send(msg);
Console.WriteLine("Client: Sent ({0}) bytes", bytesSent);
Thread.Sleep(1000);
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Client: Echoing {0}", Encoding.ASCII.GetString(bytes, 0, bytesRec));
Thread.Sleep(1000);
}
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
}
catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
}
catch (ZeroTier.Sockets.SocketException e) {
Console.WriteLine(e);
Console.WriteLine("ServiceErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
}
}
catch (Exception e) {
Console.WriteLine(e.ToString());
}
}
}
public class example {
static int Main(string[] args)
{
if (args.Length < 4 || args.Length > 5) {
Console.WriteLine("\nPlease specify either client or server mode and required arguments:");
Console.WriteLine(" Usage: example server <config_path> <nwid> <localPort>");
Console.WriteLine(" Usage: example client <config_path> <nwid> <remoteAddress> <remotePort>\n");
return 1;
}
string configFilePath = args[1];
ulong networkId = (ulong)Int64.Parse(args[2], System.Globalization.NumberStyles.HexNumber);
ExampleApp exampleApp = new ExampleApp();
if (args[0].Equals("server")) {
Console.WriteLine("Server mode...");
ushort serverPort = (ushort)Int16.Parse(args[3]);
exampleApp.StartZeroTier(configFilePath, networkId);
IPAddress ipAddress = IPAddress.Parse("0.0.0.0");
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, serverPort);
exampleApp.SocketServer(localEndPoint);
}
if (args[0].Equals("client")) {
Console.WriteLine("Client mode...");
string serverIP = args[3];
int port = Int16.Parse(args[4]);
IPAddress ipAddress = IPAddress.Parse(serverIP);
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, port);
exampleApp.StartZeroTier(configFilePath, networkId);
exampleApp.SocketClient(remoteEndPoint);
}
exampleApp.StopZeroTier();
return 0;
}
}