diff --git a/Makefile b/Makefile index eedce3a..48c561f 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ xcframework: -framework build/iphoneos.xcarchive/Products/Library/Frameworks/zt.framework \ -framework build/iphonesimulator.xcarchive/Products/Library/Frameworks/zt.framework \ -output lib/zt.xcframework - + rm -rf build/macosx.xcarchive rm -rf build/iphoneos.xcarchive rm -rf build/iphonesimulator.xcarchive @@ -104,6 +104,13 @@ host_jar_debug: host_jar_release: $(DIST_BUILD_SCRIPT) host_jar "release" host_jar: host_jar_debug host_jar_release + +host_pinvoke_release: + $(DIST_BUILD_SCRIPT) host_pinvoke "release" +host_pinvoke_debug: + $(DIST_BUILD_SCRIPT) host_pinvoke "debug" +host_pinvoke: host_pinvoke_release host_pinvoke_debug + host: host_debug host_release # Build every target available on this host diff --git a/dist.sh b/dist.sh index fcaf424..a30efdf 100755 --- a/dist.sh +++ b/dist.sh @@ -263,6 +263,37 @@ host_jar() # java -cp "lib/debug/macos-x86_64/zt.jar:examples/java/src/main/java" ExampleApp } +# Build all ordinary library types for current host +host_pinvoke() +{ + echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" + NORMALIZED_OSNAME=$OSNAME + if [[ $OSNAME = *"darwin"* ]]; then + DYNAMIC_LIB_NAME="libzt.dylib" + NORMALIZED_OSNAME="macos" + fi + if [[ $OSNAME = *"linux"* ]]; then + DYNAMIC_LIB_NAME="libzt.so" + fi + # CMake build files + BUILD_DIR=$(pwd)/tmp/${NORMALIZED_OSNAME}-$(uname -m)-$1 + mkdir -p $BUILD_DIR + # Where to place results + BIN_OUTPUT_DIR=$(pwd)/bin/$1/${NORMALIZED_OSNAME}-$(uname -m) + mkdir -p $BIN_OUTPUT_DIR + rm -rf $BIN_OUTPUT_DIR/* + LIB_OUTPUT_DIR=$(pwd)/lib/$1/${NORMALIZED_OSNAME}-$(uname -m) + mkdir -p $LIB_OUTPUT_DIR + rm -rf $LIB_OUTPUT_DIR/libzt.a $LIB_OUTPUT_DIR/$DYNAMIC_LIB_NAME $LIB_OUTPUT_DIR/libztcore.a + # Build + cmake -DZTS_PINVOKE=True -H. -B$BUILD_DIR -DCMAKE_BUILD_TYPE=$1 + $CMAKE --build $BUILD_DIR $BUILD_CONCURRENCY + # Move and clean up + mv $BUILD_DIR/bin/* $BIN_OUTPUT_DIR + mv $BUILD_DIR/lib/* $LIB_OUTPUT_DIR + clean_post_build +} + # Build all ordinary library types for current host host() { diff --git a/examples/csharp/Constants.cs b/examples/csharp/Constants.cs new file mode 100644 index 0000000..cce07ea --- /dev/null +++ b/examples/csharp/Constants.cs @@ -0,0 +1,353 @@ +/* + * Copyright (c)2013-2020 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: 2024-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 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; + + // 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; + + // 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; + + // Network Stack events + 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; + + // 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; + + // Route events + 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; + + // 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 EDEADLOCK = EDEADLK; + + 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 */ + + public static readonly short INET_ADDRSTRLEN = 16; + public static readonly short INET6_ADDRSTRLEN = 46; + + /** 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); + + /** 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; + + // 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; + + // Macro's 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; + + // 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; + + // 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; + + // 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 SHUT_RD = 0x0; + public static readonly short SHUT_WR = 0x1; + public static readonly short SHUT_RDWR = 0x2; + } +} \ No newline at end of file diff --git a/examples/csharp/Event.cs b/examples/csharp/Event.cs new file mode 100644 index 0000000..e8c24c0 --- /dev/null +++ b/examples/csharp/Event.cs @@ -0,0 +1,156 @@ +/* + * Copyright (c)2013-2020 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: 2024-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 +{ + /* 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 */ + + /// + /// Structure containing information about the local Node. + /// + 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; + } + + /// + /// Structure containing information about virtual networks. + /// + 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; + } + + /// + /// Structure containing state information about the low-level ethernet driver. + /// + public class NetifDetails + { + public ulong networkId; + public ulong macAddress; + public int mtu; + } + + /// + /// Structure containing routing information for networks. + /// + public class RouteDetails + { + public EndPoint target; + public EndPoint via; + public ushort flags; + public ushort metric; + } + + /// + /// Structure containing information about remote peer reachability. + /// + public class PeerDetails + { + ulong nodeId; + byte versionMajor; + byte versionMinor; + byte versionRev; + int latency; + byte role; + IPAddress[] paths; + } + + /// + /// Structure containing information about assigned addresses. + /// + public class AddrDetails + { + ulong networkId; + IPAddress address; + } + + /// + /// Class used to convey details of a low-level network event to the user. + /// + 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; + } + } + } +} \ No newline at end of file diff --git a/examples/csharp/Makefile b/examples/csharp/Makefile new file mode 100644 index 0000000..ad83d2a --- /dev/null +++ b/examples/csharp/Makefile @@ -0,0 +1,12 @@ +debug: + cd ../../ && make host_pinvoke_debug + cp -f ../../lib/debug/linux-x86_64/libzt.so . + mono-csc -out:example.exe *.cs + +release: + cd ../../ && make host_pinvoke_release + cp -f ../../lib/release/linux-x86_64/libzt.so . + mono-csc -out:example.exe *.cs + +clean: + rm -rf libzt.* example.exe \ No newline at end of file diff --git a/examples/csharp/Node.cs b/examples/csharp/Node.cs new file mode 100644 index 0000000..05f4b38 --- /dev/null +++ b/examples/csharp/Node.cs @@ -0,0 +1,492 @@ +/* + * Copyright (c)2013-2020 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: 2024-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.Runtime.InteropServices; +using System; + +// Prototype of callback used by ZeroTier to signal events to C# application +public delegate void CSharpCallbackWithStruct(IntPtr msgPtr); + +/// +/// ZeroTier SDK +/// +namespace ZeroTier +{ + public delegate void ZeroTierManagedEventCallback(ZeroTier.Event nodeEvent); + + /// + /// ZeroTier Node - Virtual network subsystem + /// + public class Node + { + static ulong _nodeId = 0x0; + static bool _isOnline = false; + static bool _joinedAtLeastOneNetwork = false; + static bool _hasBeenFreed = false; + string _configFilePath; + ushort _servicePort; + static ZeroTierManagedEventCallback _managedCallback; + + // Callback used internally to ferry events from the C++ layer + static void myZeroTierEventCallback(IntPtr msgPtr) + { + // Marshal the callback message pointer to a structure that we can inspect + zts_callback_msg msg = + (zts_callback_msg)Marshal.PtrToStructure(msgPtr, typeof(zts_callback_msg)); + + ZeroTier.Event newEvent = null; + + // Node events + if (msg.eventCode == Constants.EVENT_NODE_UP) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_UP"); + } + if (msg.eventCode == Constants.EVENT_NODE_ONLINE) { + _isOnline = true; + // Marshal the node details pointer to a structure + zts_node_details details = + (zts_node_details)Marshal.PtrToStructure(msg.node, typeof(zts_node_details)); + _nodeId = details.address; + newEvent = new ZeroTier.Event(msg.eventCode, "EVENT_NODE_ONLINE"); + } + if (msg.eventCode == Constants.EVENT_NODE_OFFLINE) { + _isOnline = false; + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_OFFLINE"); + } + if (msg.eventCode == Constants.EVENT_NODE_NORMAL_TERMINATION) { + _isOnline = false; + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_NORMAL_TERMINATION"); + } + if (msg.eventCode == Constants.EVENT_NODE_DOWN) { + _isOnline = false; + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_DOWN"); + } + if (msg.eventCode == Constants.EVENT_NODE_IDENTITY_COLLISION) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_IDENTITY_COLLISION"); + _isOnline = false; + } + if (msg.eventCode == Constants.EVENT_NODE_UNRECOVERABLE_ERROR) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_UNRECOVERABLE_ERROR"); + _isOnline = false; + } + + // Network events + if (msg.eventCode == Constants.EVENT_NETWORK_NOT_FOUND) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_NOT_FOUND"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_REQ_CONFIG) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_REQ_CONFIG"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_ACCESS_DENIED) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_ACCESS_DENIED"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP4) { + _joinedAtLeastOneNetwork = true; + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_READY_IP4"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP6) { + _joinedAtLeastOneNetwork = true; + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_READY_IP6"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_DOWN) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_DOWN"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_CLIENT_TOO_OLD) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_CLIENT_TOO_OLD"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_REQ_CONFIG) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_REQ_CONFIG"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_OK) { + zts_network_details unmanagedDetails = + (zts_network_details)Marshal.PtrToStructure(msg.network, typeof(zts_network_details)); + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_OK"); + newEvent.networkDetails = new NetworkDetails(); + newEvent.networkDetails.networkId = unmanagedDetails.nwid; + } + if (msg.eventCode == Constants.EVENT_NETWORK_ACCESS_DENIED) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_ACCESS_DENIED"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP4_IP6) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_READY_IP4_IP6"); + } + if (msg.eventCode == Constants.EVENT_NETWORK_UPDATE) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_UPDATE"); + } + + // Stack events + if (msg.eventCode == Constants.EVENT_STACK_UP) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_STACK_UP"); + } + if (msg.eventCode == Constants.EVENT_STACK_DOWN) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_STACK_DOWN"); + } + + // Address events + if (msg.eventCode == Constants.EVENT_ADDR_ADDED_IP4) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_ADDED_IP4"); + } + if (msg.eventCode == Constants.EVENT_ADDR_ADDED_IP6) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_ADDED_IP6"); + } + if (msg.eventCode == Constants.EVENT_ADDR_REMOVED_IP4) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP4"); + } + if (msg.eventCode == Constants.EVENT_ADDR_REMOVED_IP6) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP6"); + } + // peer events + if (msg.eventCode == Constants.EVENT_PEER_DIRECT) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_DIRECT"); + } + if (msg.eventCode == Constants.EVENT_PEER_RELAY) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_RELAY"); + } + // newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_UNREACHABLE"); + if (msg.eventCode == Constants.EVENT_PEER_PATH_DISCOVERED) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_PATH_DISCOVERED"); + } + if (msg.eventCode == Constants.EVENT_PEER_PATH_DEAD) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_PATH_DEAD"); + } + + // Route events + if (msg.eventCode == Constants.EVENT_ROUTE_ADDED) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ROUTE_ADDED"); + } + if (msg.eventCode == Constants.EVENT_ROUTE_REMOVED) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ROUTE_REMOVED"); + } + + // Netif events + if (msg.eventCode == Constants.EVENT_NETIF_UP) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_UP"); + } + if (msg.eventCode == Constants.EVENT_NETIF_DOWN) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_DOWN"); + } + if (msg.eventCode == Constants.EVENT_NETIF_REMOVED) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_REMOVED"); + } + if (msg.eventCode == Constants.EVENT_NETIF_LINK_UP) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_LINK_UP"); + } + if (msg.eventCode == Constants.EVENT_NETIF_LINK_DOWN) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_LINK_DOWN"); + } + if (msg.eventCode == Constants.EVENT_ADDR_REMOVED_IP6) { + newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP6"); + } + + // Pass the converted Event to the managed callback (visible to user) + if (newEvent != null) { + _managedCallback(newEvent); + } + } + + /// + /// Creates a new Node. Start this object by calling Start(). + /// + /// Where keys and config files will be stored on the filesystem + /// Where you would like to receive ZeroTier event notifications + /// The port ZeroTier will use to send its encrypted + /// + public Node(string configFilePath, ZeroTierManagedEventCallback managedCallback, UInt16 servicePort) + { + if (String.IsNullOrEmpty(configFilePath)) { + throw new ArgumentNullException(nameof(configFilePath)); + } + if (managedCallback == null) { + throw new ArgumentNullException(nameof(managedCallback)); + } + _nodeId = 0x0; + _configFilePath = configFilePath; + _servicePort = servicePort; + _managedCallback = new ZeroTierManagedEventCallback(managedCallback); + } + + /// + /// Starts the ZeroTier node/service + /// + /// + public int Start() + { + if (_hasBeenFreed == true) { + throw new ObjectDisposedException("ZeroTier Node has previously been freed. Restart application to create new instance."); + } + return zts_start(_configFilePath,myZeroTierEventCallback,_servicePort); + } + + /// + /// Frees (most) resources used by ZeroTier. ZeroTier may not be started again after this call. + /// + /// + public int Free() + { + _nodeId = 0x0; + _hasBeenFreed = true; + return zts_free(); + } + + /// + /// Stop all ZeroTier service activity. The service may be started again with Start(). + /// + /// + public int Stop() + { + _nodeId = 0x0; + return zts_stop(); + } + + /// + /// Restarts the ZeroTier service, internal stack and driver. (Mostly used for debugging.) + /// + /// + public int Restart() + { + _nodeId = 0x0; + return zts_restart(); + } + + /// + /// Requests to join a ZeroTier network. Remember to authorize your node/device. + /// + /// Network ID + /// + public int Join(ulong nwid) + { + return zts_join(nwid); + } + + /// + /// Leaves a ZeroTier network. + /// + /// + /// + public int Leave(ulong nwid) + { + return zts_leave(nwid); + } + + /// + /// Returns whether the Node is online (able to reach the internet.) + /// + /// + public bool IsOnline() + { + return _isOnline; + } + + /// + /// Returns whether routing information is available from at least one ZeroTier network. + /// + /// + public bool HasRoutes() + { + return _joinedAtLeastOneNetwork; + } + + public ulong NodeId + { + get { + return _nodeId; + } + } + + /* Structures and functions used internally to communicate with + lower-level C API defined in include/ZeroTierSockets.h */ + + [DllImport("libzt", EntryPoint="CSharp_zts_start")] + static extern int zts_start(string arg1, CSharpCallbackWithStruct arg2, ushort arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_stop")] + static extern int zts_stop(); + + [DllImport("libzt", EntryPoint="CSharp_zts_restart")] + static extern int zts_restart(); + + [DllImport("libzt", EntryPoint="CSharp_zts_free")] + static extern int zts_free(); + + [DllImport("libzt", EntryPoint="CSharp_zts_join")] + static extern int zts_join(ulong arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_leave")] + static extern int zts_leave(ulong arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_allow_network_caching")] + static extern int zts_allow_network_caching(byte arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_allow_peer_caching")] + static extern int zts_allow_peer_caching(byte arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_allow_local_conf")] + static extern int zts_allow_local_conf(byte arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_orbit")] + static extern int zts_orbit(ulong arg1, ulong arg2); + + [DllImport("libzt", EntryPoint="CSharp_zts_deorbit")] + static extern int zts_deorbit(ulong arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_get_6plane_addr")] + static extern int zts_get_6plane_addr(IntPtr arg1, ulong arg2, ulong arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_get_rfc4193_addr")] + static extern int zts_get_rfc4193_addr(IntPtr arg1, ulong arg2, ulong arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_generate_adhoc_nwid_from_range")] + static extern ulong zts_generate_adhoc_nwid_from_range(ushort arg1, ushort arg2); + + [DllImport("libzt", EntryPoint="CSharp_zts_delay_ms")] + static extern void zts_delay_ms(int arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_errno_get")] + static extern int zts_errno_get(); + + [StructLayout(LayoutKind.Sequential)] + struct zts_node_details + { + public ulong address; + } + + /** + * Virtual network configuration + */ + [StructLayout(LayoutKind.Sequential)] + struct zts_network_details + { + /** + * 64-bit ZeroTier network ID + */ + public ulong nwid; + + /** + * Ethernet MAC (48 bits) that should be assigned to port + */ + public ulong mac; + + /** + * Network name (from network configuration master) + */ + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + public byte[] name; + + /** + * Network configuration request status + */ + public byte status; // ? + + /** + * Network type + */ + public byte type; // ? + + /** + * Maximum interface MTU + */ + public uint mtu; + + /** + * If nonzero, the network this port belongs to indicates DHCP availability + * + * This is a suggestion. The underlying implementation is free to ignore it + * for security or other reasons. This is simply a netconf parameter that + * means 'DHCP is available on this network.' + */ + public int dhcp; + + /** + * If nonzero, this port is allowed to bridge to other networks + * + * This is informational. If this is false (0), bridged packets will simply + * be dropped and bridging won't work. + */ + public int bridge; + + /** + * If nonzero, this network supports and allows broadcast (ff:ff:ff:ff:ff:ff) traffic + */ + public int broadcastEnabled; + + /** + * If the network is in PORT_ERROR state, this is the (negative) error code most recently reported + */ + public int portError; + + /** + * Revision number as reported by controller or 0 if still waiting for config + */ + public ulong netconfRevision; + + /** + * Number of assigned addresses + */ + public uint assignedAddressCount; + + /** + * ZeroTier-assigned addresses (in sockaddr_storage structures) + * + * For IP, the port number of the sockaddr_XX structure contains the number + * of bits in the address netmask. Only the IP address and port are used. + * Other fields like interface number can be ignored. + * + * This is only used for ZeroTier-managed address assignments sent by the + * virtual network's configuration master. + */ + //struct zts_sockaddr_storage assignedAddresses[ZTS_MAX_ZT_ASSIGNED_ADDRESSES]; + + /** + * Number of ZT-pushed routes + */ + public uint routeCount; + + /** + * Routes (excluding those implied by assigned addresses and their masks) + */ + //ZTS_VirtualNetworkRoute routes[ZTS_MAX_NETWORK_ROUTES]; + + /** + * Number of multicast groups subscribed + */ + public uint multicastSubscriptionCount; + + /** + * Multicast groups to which this network's device is subscribed + */ + //struct { + // uint64_t mac; /* MAC in lower 48 bits */ + // uint32_t adi; /* Additional distinguishing information, usually zero except for IPv4 ARP groups */ + //} multicastSubscriptions[ZTS_MAX_MULTICAST_SUBSCRIPTIONS]; + } + + [StructLayout(LayoutKind.Sequential)] + struct zts_callback_msg + { + public short eventCode; + [MarshalAs(UnmanagedType.LPStruct, SizeConst = 4)] + public IntPtr node; + public IntPtr network; + } + + + /// + /// Gets the value of errno from the unmanaged region + /// + /// + public static int ErrNo { + get { + return zts_errno_get(); + } + } + } +} diff --git a/examples/csharp/README.md b/examples/csharp/README.md new file mode 100644 index 0000000..6c8bd99 --- /dev/null +++ b/examples/csharp/README.md @@ -0,0 +1,45 @@ +ZeroTier Sockets for C# .NET (Work In Progress) +===== + +This library is a re-implementation of the .NET socket class ([System.Net.Sockets.Socket](https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket)) built atop ZeroTier's SDK using P/INVOKE and is designed to be a direct drop-in replacement. The library consists of three main objects: `ZeroTier.Node`, `ZeroTier.Event`, and `ZeroTier.Socket`. No code change is required in your application beyond a small snippet of startup code, renaming `Socket` to `ZeroTier.Socket` (where applicable) and handling a smattering of events. + + +tl;dr: + +``` +using System.Net.Sockets; +using ZeroTier; + +void myCallback(ZeroTier.Event e) +{ + Console.WriteLine("{0} ({1})", e.EventCode, e.EventName); +} +... + +ZeroTier.Node node = new ZeroTier.Node("path", myCallback, 9991); + +node.Start(); +node.Join(0xc287ac0b42a6fb4c); + +... + +ZeroTier.Socket sock = new ZeroTier.Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + +sock.Connect(remoteEndPoint); + +... + +node.Stop(); +``` +See [example.cs](./example.cs) for a complete client/server implementation. + +## Building and running the example + +``` +make debug|release +./example.exe +``` + +## Development notes + +The SWIG interface file `zt.i` is only present for historical reference purposes. SWIG generates a ton of unnecessary boilerplate code which is hard to completely prevent using hints. You can generate a new wrapper for yourself using `swig -c++ -csharp -dllimport "./libzt.so" zt.i` but I would not recommend doing so unless you know what you're in for. \ No newline at end of file diff --git a/examples/csharp/Socket.cs b/examples/csharp/Socket.cs new file mode 100644 index 0000000..e232710 --- /dev/null +++ b/examples/csharp/Socket.cs @@ -0,0 +1,513 @@ +/* + * Copyright (c)2013-2020 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: 2024-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; // For ObjectDisposedException +using System.Net; // For IPEndPoint +using System.Net.Sockets; // For SocketException +using System.Runtime.InteropServices; + +using ZeroTier; + +/// +/// ZeroTier SDK +/// +namespace ZeroTier +{ + /// + /// ZeroTier Socket - An lwIP socket mediated over a ZeroTier virtual link + /// + public class Socket + { + /// No error. + public static readonly int ZTS_ERR_OK = 0; + /// Socket error, see Socket.ErrNo() for additional context. + public static readonly int ZTS_ERR_SOCKET = -1; + /// You probably did something at the wrong time. + public static readonly int ZTS_ERR_SERVICE = -2; + /// Invalid argument. + public static readonly int ZTS_ERR_ARG = -3; + /// No result. (not necessarily an error.) + public static readonly int ZTS_ERR_NO_RESULT = -4; + /// Consider filing a bug report. + public static readonly int ZTS_ERR_GENERAL = -5; + + int _fd; + bool _isClosed; + bool _isListening; + + AddressFamily _socketFamily; + SocketType _socketType; + ProtocolType _socketProtocol; + + internal EndPoint _localEndPoint; + internal EndPoint _remoteEndPoint; + + public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) + { + int family = -1; + int type = -1; + int protocol = -1; + // Map .NET socket parameters to ZeroTier equivalents + switch (addressFamily) + { + case AddressFamily.InterNetwork: + family = Constants.AF_INET; + break; + case AddressFamily.InterNetworkV6: + family = Constants.AF_INET6; + break; + case AddressFamily.Unknown: + family = Constants.AF_UNSPEC; + break; + } + switch (socketType) + { + case SocketType.Stream: + type = Constants.SOCK_STREAM; + break; + case SocketType.Dgram: + type = Constants.SOCK_DGRAM; + break; + } + switch (protocolType) + { + case ProtocolType.Udp: + protocol = Constants.IPPROTO_TCP; + break; + case ProtocolType.Tcp: + protocol = Constants.IPPROTO_UDP; + break; + case ProtocolType.Unspecified: + protocol = 0; // ? + break; + } + if ((_fd = zts_socket(family, type, protocol)) < 0) + { + throw new SocketException((int)_fd); + } + _socketFamily = addressFamily; + _socketType = socketType; + _socketProtocol = protocolType; + _isClosed = false; + } + + private Socket(int fileDescriptor, + AddressFamily addressFamily, + SocketType socketType, + ProtocolType protocolType, + EndPoint localEndPoint, + EndPoint remoteEndPoint) + { + _socketFamily = addressFamily; + _socketType = socketType; + _socketProtocol = protocolType; + _localEndPoint = localEndPoint; + _remoteEndPoint = remoteEndPoint; + _isClosed = false; + _isListening = false; + _fd = fileDescriptor; + } + + public void Connect(IPEndPoint remoteEndPoint) + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + if (_fd < 0) { + // Invalid file descriptor + throw new SocketException((int)Constants.ERR_SOCKET); + } + if (remoteEndPoint == null) { + throw new ArgumentNullException(nameof(remoteEndPoint)); + } + int err = Constants.ERR_OK; + int addrlen = 0; + if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork) + { + zts_sockaddr_in sa = new zts_sockaddr_in(); + addrlen = Marshal.SizeOf(typeof(zts_sockaddr_in)); + switch (remoteEndPoint.AddressFamily) + { + case AddressFamily.InterNetwork: + sa.sin_family = (byte)Constants.AF_INET; + break; + case AddressFamily.InterNetworkV6: + sa.sin_family = (byte)Constants.AF_INET6; + break; + case AddressFamily.Unknown: + sa.sin_family = (byte)Constants.AF_UNSPEC; + break; + } + sa.sin_port = (short)zts_htons((ushort)remoteEndPoint.Port); + sa.sin_addr = remoteEndPoint.Address.GetAddressBytes(); + sa.sin_len = (byte)addrlen; // lwIP-specific + + IntPtr ptr1 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr))); + Marshal.StructureToPtr(sa, ptr1, false); + //zts_sockaddr sAddr = (zts_sockaddr)Marshal.PtrToStructure(ptr1, typeof(zts_sockaddr)); + err = zts_connect(_fd, ptr1, (byte)addrlen); + + } + if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6) + { + /* + socketAddress.iSockaddrLength = Marshal.SizeOf(typeof(sockaddr_in6)); + socketAddress.lpSockAddr = CriticalAllocHandle.FromSize(socketAddress.iSockaddrLength); + sockaddr_in6 sa = new sockaddr_in6(); + sa.sin6_family = (short)AddressFamily.InterNetworkV6; + sa.sin6_port = (ushort)endpoint.Port; + sa.sin6_addr = endpoint.Address.GetAddressBytes(); + sa.sin6_scope_id = (uint)endpoint.Address.ScopeId; + Marshal.StructureToPtr(sa, (IntPtr)socketAddress.lpSockAddr, false); + */ + } + if (err < 0) { + throw new SocketException((int)err); + } + _remoteEndPoint = remoteEndPoint; + } + + public void Bind(IPEndPoint localEndPoint) + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + if (_fd < 0) { + // Invalid file descriptor + throw new SocketException((int)Constants.ERR_SOCKET); + } + if (localEndPoint == null) { + throw new ArgumentNullException(nameof(localEndPoint)); + } + int err = Constants.ERR_OK; + int addrlen = 0; + if (localEndPoint.AddressFamily == AddressFamily.InterNetwork) + { + zts_sockaddr_in sa = new zts_sockaddr_in(); + addrlen = Marshal.SizeOf(typeof(zts_sockaddr_in)); + switch (localEndPoint.AddressFamily) + { + case AddressFamily.InterNetwork: + sa.sin_family = (byte)Constants.AF_INET; + break; + case AddressFamily.InterNetworkV6: + sa.sin_family = (byte)Constants.AF_INET6; + break; + case AddressFamily.Unknown: + sa.sin_family = (byte)Constants.AF_UNSPEC; + break; + } + sa.sin_port = (short)zts_htons((ushort)localEndPoint.Port); + sa.sin_addr = localEndPoint.Address.GetAddressBytes(); + sa.sin_len = (byte)addrlen; // lwIP-specific + + IntPtr ptr1 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr))); + Marshal.StructureToPtr(sa, ptr1, false); + err = zts_bind(_fd, ptr1, (byte)addrlen); + } + if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6) + { + /* + socketAddress.iSockaddrLength = Marshal.SizeOf(typeof(sockaddr_in6)); + socketAddress.lpSockAddr = CriticalAllocHandle.FromSize(socketAddress.iSockaddrLength); + sockaddr_in6 sa = new sockaddr_in6(); + sa.sin6_family = (short)AddressFamily.InterNetworkV6; + sa.sin6_port = (ushort)endpoint.Port; + sa.sin6_addr = endpoint.Address.GetAddressBytes(); + sa.sin6_scope_id = (uint)endpoint.Address.ScopeId; + Marshal.StructureToPtr(sa, (IntPtr)socketAddress.lpSockAddr, false); + */ + } + if (err < 0) { + throw new SocketException((int)err); + } + _localEndPoint = localEndPoint; + } + + public void Listen(int backlog) + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + if (_fd < 0) { + // Invalid file descriptor + throw new SocketException((int)Constants.ERR_SOCKET); + } + int err = Constants.ERR_OK; + if ((err = zts_listen(_fd, backlog)) < 0) { + // Invalid backlog value perhaps? + throw new SocketException((int)Constants.ERR_SOCKET); + } + _isListening = true; + } + + public Socket Accept() + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + if (_fd < 0) { + // Invalid file descriptor + throw new SocketException((int)Constants.ERR_SOCKET); + } + if (_isListening == false) { + throw new InvalidOperationException("Socket is not in a listening state. Call Listen() first"); + } + // TODO: Rewrite -- Check for memory leaks + // Inform zts_accept of the size of the available address buffer + int addrlen = Marshal.SizeOf(typeof(zts_sockaddr_in)); + IntPtr addrlenPtr = GCHandle.Alloc(addrlen, GCHandleType.Pinned).AddrOfPinnedObject(); + // Allocate space for address buffer and provide pointer to zts_accept + zts_sockaddr_in in4 = new zts_sockaddr_in(); + IntPtr remoteAddrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr_in))); + Marshal.StructureToPtr(in4, remoteAddrPtr, false); + + int err = zts_accept(_fd, remoteAddrPtr, addrlenPtr); + if (err < 0) { + throw new SocketException((int)err); + } + in4 = (zts_sockaddr_in)Marshal.PtrToStructure(remoteAddrPtr, typeof(zts_sockaddr_in)); + // Convert sockaddr contents to IPEndPoint + IPAddress ipAddress = new IPAddress(in4.sin_addr); + IPEndPoint clientEndPoint = new IPEndPoint(ipAddress, zts_ntohs((ushort)in4.sin_port)); + // Create new socket by providing file descriptor returned from zts_accept call. + Socket clientSocket = new Socket( + err, _socketFamily, _socketType, _socketProtocol, _localEndPoint, clientEndPoint); + return clientSocket; + } + + public void Shutdown(SocketShutdown how) + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + int ztHow = 0; + switch (how) + { + case SocketShutdown.Receive: + ztHow = Constants.O_RDONLY; + break; + case SocketShutdown.Send: + ztHow = Constants.O_WRONLY; + break; + case SocketShutdown.Both: + ztHow = Constants.O_RDWR; + break; + } + zts_shutdown(_fd, ztHow); + } + + public void Close() + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has already been closed"); + } + zts_close(_fd); + _isClosed = true; + } + + public EndPoint RemoteEndPoint + { + get { + return _remoteEndPoint; + } + } + + public EndPoint LocalEndPoint + { + get { + return _localEndPoint; + } + } + + public Int32 Send(Byte[] buffer) + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + if (_fd < 0) { + throw new SocketException((int)ZeroTier.Constants.ERR_SOCKET); + } + if (buffer == null) { + throw new ArgumentNullException(nameof(buffer)); + } + int flags = 0; + IntPtr bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); + return zts_send(_fd, bufferPtr, (uint)Buffer.ByteLength(buffer), (int)flags); + } + + public Int32 Receive(Byte[] buffer) + { + if (_isClosed) { + throw new ObjectDisposedException("Socket has been closed"); + } + if (_fd < 0) { + throw new SocketException((int)ZeroTier.Constants.ERR_SOCKET); + } + if (buffer == null) { + throw new ArgumentNullException(nameof(buffer)); + } + int flags = 0; + IntPtr bufferPtr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0); + return zts_recv(_fd, bufferPtr, (uint)Buffer.ByteLength(buffer), (int)flags); + } + + /* Structures and functions used internally to communicate with + lower-level C API defined in include/ZeroTierSockets.h */ + + [DllImport("libzt", EntryPoint="CSharp_zts_get_all_stats")] + static extern int zts_get_all_stats(IntPtr arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_get_protocol_stats")] + static extern int zts_get_protocol_stats(int arg1, IntPtr arg2); + + [DllImport("libzt", EntryPoint="CSharp_zts_socket")] + static extern int zts_socket(int arg1, int arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_connect")] + static extern int zts_connect(int arg1, IntPtr arg2, ushort arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_bind")] + static extern int zts_bind(int arg1, IntPtr arg2, ushort arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_listen")] + static extern int zts_listen(int arg1, int arg2); + + [DllImport("libzt", EntryPoint="CSharp_zts_accept")] + static extern int zts_accept(int arg1, IntPtr arg2, IntPtr arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_setsockopt")] + static extern int zts_setsockopt(int arg1, int arg2, int arg3, IntPtr arg4, ushort arg5); + + [DllImport("libzt", EntryPoint="CSharp_zts_getsockopt")] + static extern int zts_getsockopt(int arg1, int arg2, int arg3, IntPtr arg4, IntPtr arg5); + + [DllImport("libzt", EntryPoint="CSharp_zts_getsockname")] + static extern int zts_getsockname(int arg1, IntPtr arg2, IntPtr arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_getpeername")] + static extern int zts_getpeername(int arg1, IntPtr arg2, IntPtr arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_close")] + static extern int zts_close(int arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_fcntl")] + static extern int zts_fcntl(int arg1, int arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_poll")] + static extern int zts_poll(IntPtr arg1, uint arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_ioctl")] + static extern int zts_ioctl(int arg1, uint arg2, IntPtr arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_send")] + static extern int zts_send(int arg1, IntPtr arg2, uint arg3, int arg4); + + [DllImport("libzt", EntryPoint="CSharp_zts_sendto")] + static extern int zts_sendto(int arg1, IntPtr arg2, uint arg3, int arg4, IntPtr arg5, ushort arg6); + + [DllImport("libzt", EntryPoint="CSharp_zts_sendmsg")] + static extern int zts_sendmsg(int arg1, IntPtr arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_recv")] + static extern int zts_recv(int arg1, IntPtr arg2, uint arg3, int arg4); + + [DllImport("libzt", EntryPoint="CSharp_zts_recvfrom")] + static extern int zts_recvfrom(int arg1, IntPtr arg2, uint arg3, int arg4, IntPtr arg5, IntPtr arg6); + + [DllImport("libzt", EntryPoint="CSharp_zts_recvmsg")] + static extern int zts_recvmsg(int arg1, IntPtr arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_read")] + static extern int zts_read(int arg1, IntPtr arg2, uint arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_readv")] + static extern int zts_readv(int arg1, IntPtr arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_write")] + static extern int zts_write(int arg1, IntPtr arg2, uint arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_writev")] + static extern int zts_writev(int arg1, IntPtr arg2, int arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_shutdown")] + static extern int zts_shutdown(int arg1, int arg2); + + [DllImport("libzt", EntryPoint="CSharp_zts_add_dns_nameserver")] + static extern int zts_add_dns_nameserver(IntPtr arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_del_dns_nameserver")] + static extern int zts_del_dns_nameserver(IntPtr arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_htons")] + static extern ushort zts_htons(ushort arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_htonl")] + static extern ushort zts_htonl(ushort arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_ntohs")] + static extern ushort zts_ntohs(ushort arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_ntohl")] + static extern ushort zts_ntohl(ushort arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_inet_ntop")] + static extern string zts_inet_ntop(int arg1, IntPtr arg2, string arg3, ushort arg4); + + [DllImport("libzt", EntryPoint="CSharp_zts_inet_pton")] + static extern int zts_inet_pton(int arg1, string arg2, IntPtr arg3); + + [DllImport("libzt", EntryPoint="CSharp_zts_inet_addr")] + static extern ushort zts_inet_addr(string arg1); + + [DllImport("libzt", EntryPoint="CSharp_zts_errno_get")] + static extern int zts_errno_get(); + + /// + /// Gets the value of errno from the unmanaged region + /// + /// + public static int ErrNo { + get { + return zts_errno_get(); + } + } + + [StructLayout(LayoutKind.Sequential)] + struct zts_sockaddr + { + public byte sa_len; + public byte sa_family; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] + public byte[] sa_data; + } + + [StructLayout(LayoutKind.Sequential)] + struct zts_in_addr + { + public uint s_addr; + } + + [StructLayout(LayoutKind.Sequential)] + struct zts_sockaddr_in + { + public byte sin_len; + public byte sin_family; + public short sin_port; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] sin_addr; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public char[] sin_zero; // SIN_ZERO_LEN + } + } +} diff --git a/examples/csharp/example.cs b/examples/csharp/example.cs new file mode 100644 index 0000000..4651c59 --- /dev/null +++ b/examples/csharp/example.cs @@ -0,0 +1,201 @@ + +using System; +using System.Threading; +using System.Net; +using System.Net.Sockets; // For SocketType, etc +using System.Text; // For Encoding + +using ZeroTier; // For ZeroTier.Node, ZeroTier.Event, and ZeroTier.Socket + +public class ExampleApp { + + ZeroTier.Node node; + + /** + * Initialize and start ZeroTier + */ + public void StartZeroTier(string configFilePath, ushort servicePort, ulong networkId) + { + node = new ZeroTier.Node(configFilePath, myZeroTierEventCallback, servicePort); + node.Start(); // Network activity only begins after calling Start() + + /* How you do this next part is up to you, but essentially we're waiting for the node + to signal to us (via a ZeroTierEvent) 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 + IsOnline() instead of looking for the event via the callback. */ + while (!node.IsOnline()) { Thread.Sleep(100); } + + /* 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); + + /* Note that ZeroTierSocket 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); } + } + + /** + * Stop ZeroTier + */ + public void StopZeroTier() + { + node.Stop(); + } + + /** + * 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 myZeroTierEventCallback(ZeroTier.Event e) + { + Console.WriteLine("Event.eventCode = {0} ({1})", e.EventCode, e.EventName); + + if (e.EventCode == ZeroTier.Constants.EVENT_NODE_ONLINE) { + Console.WriteLine("Node is online"); + Console.WriteLine(" - Address (NodeId): " + node.NodeId); + } + + if (e.EventCode == ZeroTier.Constants.EVENT_NETWORK_OK) { + Console.WriteLine(" - Network ID: " + e.networkDetails.networkId.ToString("x16")); + } + } + + /** + * Example server + */ + public void YourServer() { + string data = null; + + // Data buffer for incoming data. + byte[] bytes = new Byte[1024]; + + string serverIP = "0.0.0.0"; + int port = 8000; + IPAddress ipAddress = IPAddress.Parse(serverIP); + IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port); + + Console.WriteLine(localEndPoint.ToString()); + ZeroTier.Socket listener = new ZeroTier.Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp ); + + // Bind the socket to the local endpoint and + // listen for incoming connections. + + try { + listener.Bind(localEndPoint); + listener.Listen(10); + + // Start listening for connections. + while (true) { + Console.WriteLine("Waiting for a connection..."); + // Program is suspended while waiting for an incoming connection. + Console.WriteLine("accepting..."); + ZeroTier.Socket handler = listener.Accept(); + data = null; + + Console.WriteLine("accepted connection from: " + handler.RemoteEndPoint.ToString()); + + // An incoming connection needs to be processed. + while (true) { + int bytesRec = handler.Receive(bytes); + data += Encoding.ASCII.GetString(bytes,0,bytesRec); + if (data.IndexOf("") > -1) { + break; + } + } + + // Show the data on the console. + Console.WriteLine( "Text received : {0}", data); + + // Echo the data back to the client. + byte[] msg = Encoding.ASCII.GetBytes(data); + + handler.Send(msg); + handler.Shutdown(SocketShutdown.Both); + handler.Close(); + } + + } catch (Exception e) { + Console.WriteLine(e.ToString()); + } + + Console.WriteLine("\nPress ENTER to continue..."); + Console.Read(); + } + + /** + * Example client + */ + public void YourClient() { + // Data buffer for incoming data. + byte[] bytes = new byte[1024]; + + // Connect to a remote device. + try { + string serverIP = "10.244.180.7"; + int port = 8000; + IPAddress ipAddress = IPAddress.Parse(serverIP); + IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, port); + + // Create a TCP/IP socket. + ZeroTier.Socket sender = new ZeroTier.Socket(ipAddress.AddressFamily, + SocketType.Stream, ProtocolType.Tcp ); + + // Connect the socket to the remote endpoint. Catch any errors. + try { + + Console.WriteLine("Socket connecting to {0}...", + remoteEndPoint.ToString()); + + sender.Connect(remoteEndPoint); + + Console.WriteLine("Socket 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 (SocketException se) { + Console.WriteLine("SocketException : {0}",se.ToString()); + } catch (Exception e) { + Console.WriteLine("Unexpected exception : {0}", e.ToString()); + } + + } catch (Exception e) { + Console.WriteLine( e.ToString()); + } + } +} + +public class example +{ + static void Main() + { + ExampleApp exampleApp = new ExampleApp(); + + ulong networkId = 0x8216ab0a47c622a1; + ushort servicePort = 9991; + string configFilePath = "path"; + + exampleApp.StartZeroTier(configFilePath, servicePort, networkId); + exampleApp.YourClient(); + exampleApp.StopZeroTier(); + } +} + diff --git a/examples/csharp/zt.i b/examples/csharp/zt.i new file mode 100644 index 0000000..b2e752c --- /dev/null +++ b/examples/csharp/zt.i @@ -0,0 +1,55 @@ +%module zt + +%include +%include +%include + +// Prevent SWIG from doing anything funny with our types +%apply unsigned char { uint8_t }; +%apply char { int8_t }; +%apply unsigned short { uint16_t }; +%apply int { int16_t }; +%apply unsigned short { uint32_t }; +%apply int { int32_t }; +%apply unsigned long long { uint64_t }; +%apply long long { int64_t }; + +%typemap(ctype) zts_sockaddr* "zts_sockaddr*" + +// Ignore all classes/structs (We'll define these manually in C#) +// %rename($ignore, %$isclass) ""; + +%ignore zts_in6_addr; + +%ignore zts_sockaddr; +%ignore zts_in_addr; +%ignore zts_sockaddr_in; +%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; + +#define ZTS_CSHARP=1 + +%{ +#include "../../include/ZeroTierSockets.h" +%} + +// Typemap for our event callback +%define %cs_callback(TYPE, CSTYPE) + %typemap(ctype) TYPE, TYPE& "void *" + %typemap(in) TYPE %{ $1 = ($1_type)$input; %} + %typemap(in) TYPE& %{ $1 = ($1_type)&$input; %} + %typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE" + %typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE" + %typemap(csin) TYPE, TYPE& "$csinput" +%enddef +%cs_callback(CppCallback, CSharpCallbackWithStruct) + +%include "../../include/ZeroTierSockets.h" diff --git a/examples/csharp/zt_wrap.cxx b/examples/csharp/zt_wrap.cxx new file mode 100644 index 0000000..4d88a87 --- /dev/null +++ b/examples/csharp/zt_wrap.cxx @@ -0,0 +1,1143 @@ +/* + * Copyright (c)2013-2020 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: 2024-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. + */ +/****/ + +#ifndef SWIGCSHARP +#define SWIGCSHARP +#endif + + + +#ifdef __cplusplus +/* SwigValueWrapper is described in swig.swg */ +template class SwigValueWrapper { + struct SwigMovePointer { + T *ptr; + SwigMovePointer(T *p) : ptr(p) { } + ~SwigMovePointer() { delete ptr; } + SwigMovePointer& operator=(SwigMovePointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } + } pointer; + SwigValueWrapper& operator=(const SwigValueWrapper& rhs); + SwigValueWrapper(const SwigValueWrapper& rhs); +public: + SwigValueWrapper() : pointer(0) { } + SwigValueWrapper& operator=(const T& t) { SwigMovePointer tmp(new T(t)); pointer = tmp; return *this; } + operator T&() const { return *pointer.ptr; } + T *operator&() { return pointer.ptr; } +}; + +template T SwigValueInit() { + return T(); +} +#endif + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + + +#include +#include +#include + + +/* Support for throwing C# exceptions from C/C++. There are two types: + * Exceptions that take a message and ArgumentExceptions that take a message and a parameter name. */ +typedef enum { + SWIG_CSharpApplicationException, + SWIG_CSharpArithmeticException, + SWIG_CSharpDivideByZeroException, + SWIG_CSharpIndexOutOfRangeException, + SWIG_CSharpInvalidCastException, + SWIG_CSharpInvalidOperationException, + SWIG_CSharpIOException, + SWIG_CSharpNullReferenceException, + SWIG_CSharpOutOfMemoryException, + SWIG_CSharpOverflowException, + SWIG_CSharpSystemException +} SWIG_CSharpExceptionCodes; + +typedef enum { + SWIG_CSharpArgumentException, + SWIG_CSharpArgumentNullException, + SWIG_CSharpArgumentOutOfRangeException +} SWIG_CSharpExceptionArgumentCodes; + +typedef void (SWIGSTDCALL* SWIG_CSharpExceptionCallback_t)(const char *); +typedef void (SWIGSTDCALL* SWIG_CSharpExceptionArgumentCallback_t)(const char *, const char *); + +typedef struct { + SWIG_CSharpExceptionCodes code; + SWIG_CSharpExceptionCallback_t callback; +} SWIG_CSharpException_t; + +typedef struct { + SWIG_CSharpExceptionArgumentCodes code; + SWIG_CSharpExceptionArgumentCallback_t callback; +} SWIG_CSharpExceptionArgument_t; + +static SWIG_CSharpException_t SWIG_csharp_exceptions[] = { + { SWIG_CSharpApplicationException, NULL }, + { SWIG_CSharpArithmeticException, NULL }, + { SWIG_CSharpDivideByZeroException, NULL }, + { SWIG_CSharpIndexOutOfRangeException, NULL }, + { SWIG_CSharpInvalidCastException, NULL }, + { SWIG_CSharpInvalidOperationException, NULL }, + { SWIG_CSharpIOException, NULL }, + { SWIG_CSharpNullReferenceException, NULL }, + { SWIG_CSharpOutOfMemoryException, NULL }, + { SWIG_CSharpOverflowException, NULL }, + { SWIG_CSharpSystemException, NULL } +}; + +static SWIG_CSharpExceptionArgument_t SWIG_csharp_exceptions_argument[] = { + { SWIG_CSharpArgumentException, NULL }, + { SWIG_CSharpArgumentNullException, NULL }, + { SWIG_CSharpArgumentOutOfRangeException, NULL } +}; + +static void SWIGUNUSED SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code, const char *msg) { + SWIG_CSharpExceptionCallback_t callback = SWIG_csharp_exceptions[SWIG_CSharpApplicationException].callback; + if ((size_t)code < sizeof(SWIG_csharp_exceptions)/sizeof(SWIG_CSharpException_t)) { + callback = SWIG_csharp_exceptions[code].callback; + } + callback(msg); +} + +static void SWIGUNUSED SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpExceptionArgumentCodes code, const char *msg, const char *param_name) { + SWIG_CSharpExceptionArgumentCallback_t callback = SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentException].callback; + if ((size_t)code < sizeof(SWIG_csharp_exceptions_argument)/sizeof(SWIG_CSharpExceptionArgument_t)) { + callback = SWIG_csharp_exceptions_argument[code].callback; + } + callback(msg, param_name); +} + + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionCallbacks_zt( + SWIG_CSharpExceptionCallback_t applicationCallback, + SWIG_CSharpExceptionCallback_t arithmeticCallback, + SWIG_CSharpExceptionCallback_t divideByZeroCallback, + SWIG_CSharpExceptionCallback_t indexOutOfRangeCallback, + SWIG_CSharpExceptionCallback_t invalidCastCallback, + SWIG_CSharpExceptionCallback_t invalidOperationCallback, + SWIG_CSharpExceptionCallback_t ioCallback, + SWIG_CSharpExceptionCallback_t nullReferenceCallback, + SWIG_CSharpExceptionCallback_t outOfMemoryCallback, + SWIG_CSharpExceptionCallback_t overflowCallback, + SWIG_CSharpExceptionCallback_t systemCallback) { + SWIG_csharp_exceptions[SWIG_CSharpApplicationException].callback = applicationCallback; + SWIG_csharp_exceptions[SWIG_CSharpArithmeticException].callback = arithmeticCallback; + SWIG_csharp_exceptions[SWIG_CSharpDivideByZeroException].callback = divideByZeroCallback; + SWIG_csharp_exceptions[SWIG_CSharpIndexOutOfRangeException].callback = indexOutOfRangeCallback; + SWIG_csharp_exceptions[SWIG_CSharpInvalidCastException].callback = invalidCastCallback; + SWIG_csharp_exceptions[SWIG_CSharpInvalidOperationException].callback = invalidOperationCallback; + SWIG_csharp_exceptions[SWIG_CSharpIOException].callback = ioCallback; + SWIG_csharp_exceptions[SWIG_CSharpNullReferenceException].callback = nullReferenceCallback; + SWIG_csharp_exceptions[SWIG_CSharpOutOfMemoryException].callback = outOfMemoryCallback; + SWIG_csharp_exceptions[SWIG_CSharpOverflowException].callback = overflowCallback; + SWIG_csharp_exceptions[SWIG_CSharpSystemException].callback = systemCallback; +} + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterExceptionArgumentCallbacks_zt( + SWIG_CSharpExceptionArgumentCallback_t argumentCallback, + SWIG_CSharpExceptionArgumentCallback_t argumentNullCallback, + SWIG_CSharpExceptionArgumentCallback_t argumentOutOfRangeCallback) { + SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentException].callback = argumentCallback; + SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentNullException].callback = argumentNullCallback; + SWIG_csharp_exceptions_argument[SWIG_CSharpArgumentOutOfRangeException].callback = argumentOutOfRangeCallback; +} + + +/* Callback for returning strings to C# without leaking memory */ +typedef char * (SWIGSTDCALL* SWIG_CSharpStringHelperCallback)(const char *); +static SWIG_CSharpStringHelperCallback SWIG_csharp_string_callback = NULL; + + +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterStringCallback_zt(SWIG_CSharpStringHelperCallback callback) { + SWIG_csharp_string_callback = callback; +} + + +/* Contract support */ + +#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, msg, ""); return nullreturn; } else + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + + +#include +#include + + +#include + + +#include +#include +#include + + +#include +#include +#include + + +SWIGINTERN void SWIG_CSharpException(int code, const char *msg) { + if (code == SWIG_ValueError) { + SWIG_CSharpExceptionArgumentCodes exception_code = SWIG_CSharpArgumentOutOfRangeException; + SWIG_CSharpSetPendingExceptionArgument(exception_code, msg, 0); + } else { + SWIG_CSharpExceptionCodes exception_code = SWIG_CSharpApplicationException; + switch(code) { + case SWIG_MemoryError: + exception_code = SWIG_CSharpOutOfMemoryException; + break; + case SWIG_IndexError: + exception_code = SWIG_CSharpIndexOutOfRangeException; + break; + case SWIG_DivisionByZero: + exception_code = SWIG_CSharpDivideByZeroException; + break; + case SWIG_IOError: + exception_code = SWIG_CSharpIOException; + break; + case SWIG_OverflowError: + exception_code = SWIG_CSharpOverflowException; + break; + case SWIG_RuntimeError: + case SWIG_TypeError: + case SWIG_SyntaxError: + case SWIG_SystemError: + case SWIG_UnknownError: + default: + exception_code = SWIG_CSharpApplicationException; + break; + } + SWIG_CSharpSetPendingException(exception_code, msg); + } +} + + +#include +#include + + +#include + + +#include "../../include/ZeroTierSockets.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +SWIGEXPORT void SWIGSTDCALL CSharp_zts_errno_set(int jarg1) { + int arg1 ; + + arg1 = (int)jarg1; + zts_errno = arg1; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_errno_get() { + int jresult ; + int result; + + result = (int)zts_errno; + jresult = result; + return jresult; +} + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_allow_network_caching(unsigned char jarg1) { + int jresult ; + uint8_t arg1 ; + int result; + + arg1 = (uint8_t)jarg1; + result = (int)zts_allow_network_caching(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_allow_peer_caching(unsigned char jarg1) { + int jresult ; + uint8_t arg1 ; + int result; + + arg1 = (uint8_t)jarg1; + result = (int)zts_allow_peer_caching(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_allow_local_conf(unsigned char jarg1) { + int jresult ; + uint8_t arg1 ; + int result; + + arg1 = (uint8_t)jarg1; + result = (int)zts_allow_local_conf(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_start(char * jarg1, void * jarg2, unsigned short jarg3) { + int jresult ; + char *arg1 = (char *) 0 ; + CppCallback arg2 = (CppCallback) 0 ; + uint16_t arg3 ; + int result; + + arg1 = (char *)jarg1; + arg2 = (CppCallback)jarg2; + arg3 = (uint16_t)jarg3; + result = (int)zts_start((char const *)arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_stop() { + int jresult ; + int result; + + result = (int)zts_stop(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_restart() { + int jresult ; + int result; + + result = (int)zts_restart(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_free() { + int jresult ; + int result; + + result = (int)zts_free(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_join(unsigned long long jarg1) { + int jresult ; + uint64_t arg1 ; + int result; + + arg1 = (uint64_t)jarg1; + result = (int)zts_join(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_leave(unsigned long long jarg1) { + int jresult ; + uint64_t arg1 ; + int result; + + arg1 = (uint64_t)jarg1; + result = (int)zts_leave(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_orbit(unsigned long long jarg1, unsigned long long jarg2) { + int jresult ; + uint64_t arg1 ; + uint64_t arg2 ; + int result; + + arg1 = (uint64_t)jarg1; + arg2 = (uint64_t)jarg2; + result = (int)zts_orbit(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_deorbit(unsigned long long jarg1) { + int jresult ; + uint64_t arg1 ; + int result; + + arg1 = (uint64_t)jarg1; + result = (int)zts_deorbit(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_6plane_addr(void * jarg1, unsigned long long jarg2, unsigned long long jarg3) { + int jresult ; + zts_sockaddr_storage *arg1 = (zts_sockaddr_storage *) 0 ; + uint64_t arg2 ; + uint64_t arg3 ; + int result; + + arg1 = (zts_sockaddr_storage *)jarg1; + arg2 = (uint64_t)jarg2; + arg3 = (uint64_t)jarg3; + result = (int)zts_get_6plane_addr(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_rfc4193_addr(void * jarg1, unsigned long long jarg2, unsigned long long jarg3) { + int jresult ; + zts_sockaddr_storage *arg1 = (zts_sockaddr_storage *) 0 ; + uint64_t arg2 ; + uint64_t arg3 ; + int result; + + arg1 = (zts_sockaddr_storage *)jarg1; + arg2 = (uint64_t)jarg2; + arg3 = (uint64_t)jarg3; + result = (int)zts_get_rfc4193_addr(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT unsigned long long SWIGSTDCALL CSharp_zts_generate_adhoc_nwid_from_range(unsigned short jarg1, unsigned short jarg2) { + unsigned long long jresult ; + uint16_t arg1 ; + uint16_t arg2 ; + uint64_t result; + + arg1 = (uint16_t)jarg1; + arg2 = (uint16_t)jarg2; + result = zts_generate_adhoc_nwid_from_range(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_zts_delay_ms(long jarg1) { + long arg1 ; + + arg1 = (long)jarg1; + zts_delay_ms(arg1); +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_all_stats(void * jarg1) { + int jresult ; + zts_stats *arg1 = (zts_stats *) 0 ; + int result; + + arg1 = (zts_stats *)jarg1; + result = (int)zts_get_all_stats(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_protocol_stats(int jarg1, void * jarg2) { + int jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + result = (int)zts_get_protocol_stats(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_socket(int jarg1, int jarg2, int jarg3) { + int jresult ; + int arg1 ; + int arg2 ; + int arg3 ; + int result; + + arg1 = (int)jarg1; + arg2 = (int)jarg2; + arg3 = (int)jarg3; + result = (int)zts_socket(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_connect(int jarg1, zts_sockaddr* jarg2, unsigned short jarg3) { + int jresult ; + int arg1 ; + zts_sockaddr *arg2 = (zts_sockaddr *) 0 ; + zts_socklen_t arg3 ; + int result; + + arg1 = (int)jarg1; + arg2 = (zts_sockaddr *)jarg2; + arg3 = (zts_socklen_t)jarg3; + result = (int)zts_connect(arg1,(zts_sockaddr const *)arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_bind(int jarg1, zts_sockaddr* jarg2, unsigned short jarg3) { + int jresult ; + int arg1 ; + zts_sockaddr *arg2 = (zts_sockaddr *) 0 ; + zts_socklen_t arg3 ; + int result; + + arg1 = (int)jarg1; + arg2 = (zts_sockaddr *)jarg2; + arg3 = (zts_socklen_t)jarg3; + result = (int)zts_bind(arg1,(zts_sockaddr const *)arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_listen(int jarg1, int jarg2) { + int jresult ; + int arg1 ; + int arg2 ; + int result; + + arg1 = (int)jarg1; + arg2 = (int)jarg2; + result = (int)zts_listen(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_accept(int jarg1, zts_sockaddr* jarg2, int * jarg3) { + int jresult ; + int arg1 ; + zts_sockaddr *arg2 = (zts_sockaddr *) 0 ; + zts_socklen_t *arg3 = (zts_socklen_t *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (zts_sockaddr *)jarg2; + arg3 = (zts_socklen_t *)jarg3; + result = (int)zts_accept(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_setsockopt(int jarg1, int jarg2, int jarg3, void * jarg4, unsigned short jarg5) { + int jresult ; + int arg1 ; + int arg2 ; + int arg3 ; + void *arg4 = (void *) 0 ; + zts_socklen_t arg5 ; + int result; + + arg1 = (int)jarg1; + arg2 = (int)jarg2; + arg3 = (int)jarg3; + arg4 = (void *)jarg4; + arg5 = (zts_socklen_t)jarg5; + result = (int)zts_setsockopt(arg1,arg2,arg3,(void const *)arg4,arg5); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_getsockopt(int jarg1, int jarg2, int jarg3, void * jarg4, void * jarg5) { + int jresult ; + int arg1 ; + int arg2 ; + int arg3 ; + void *arg4 = (void *) 0 ; + zts_socklen_t *arg5 = (zts_socklen_t *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (int)jarg2; + arg3 = (int)jarg3; + arg4 = (void *)jarg4; + arg5 = (zts_socklen_t *)jarg5; + result = (int)zts_getsockopt(arg1,arg2,arg3,arg4,arg5); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_getsockname(int jarg1, zts_sockaddr* jarg2, void * jarg3) { + int jresult ; + int arg1 ; + zts_sockaddr *arg2 = (zts_sockaddr *) 0 ; + zts_socklen_t *arg3 = (zts_socklen_t *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (zts_sockaddr *)jarg2; + arg3 = (zts_socklen_t *)jarg3; + result = (int)zts_getsockname(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_getpeername(int jarg1, zts_sockaddr* jarg2, void * jarg3) { + int jresult ; + int arg1 ; + zts_sockaddr *arg2 = (zts_sockaddr *) 0 ; + zts_socklen_t *arg3 = (zts_socklen_t *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (zts_sockaddr *)jarg2; + arg3 = (zts_socklen_t *)jarg3; + result = (int)zts_getpeername(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_close(int jarg1) { + int jresult ; + int arg1 ; + int result; + + arg1 = (int)jarg1; + result = (int)zts_close(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_select(int jarg1, void * jarg2, void * jarg3, void * jarg4, void * jarg5) { + int jresult ; + int arg1 ; + zts_fd_set *arg2 = (zts_fd_set *) 0 ; + zts_fd_set *arg3 = (zts_fd_set *) 0 ; + zts_fd_set *arg4 = (zts_fd_set *) 0 ; + zts_timeval *arg5 = (zts_timeval *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (zts_fd_set *)jarg2; + arg3 = (zts_fd_set *)jarg3; + arg4 = (zts_fd_set *)jarg4; + arg5 = (zts_timeval *)jarg5; + result = (int)zts_select(arg1,arg2,arg3,arg4,arg5); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_fcntl(int jarg1, int jarg2, int jarg3) { + int jresult ; + int arg1 ; + int arg2 ; + int arg3 ; + int result; + + arg1 = (int)jarg1; + arg2 = (int)jarg2; + arg3 = (int)jarg3; + result = (int)zts_fcntl(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_poll(void * jarg1, unsigned int jarg2, int jarg3) { + int jresult ; + zts_pollfd *arg1 = (zts_pollfd *) 0 ; + zts_nfds_t arg2 ; + int arg3 ; + int result; + + arg1 = (zts_pollfd *)jarg1; + arg2 = (zts_nfds_t)jarg2; + arg3 = (int)jarg3; + result = (int)zts_poll(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_ioctl(int jarg1, unsigned long jarg2, void * jarg3) { + int jresult ; + int arg1 ; + unsigned long arg2 ; + void *arg3 = (void *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (unsigned long)jarg2; + arg3 = (void *)jarg3; + result = (int)zts_ioctl(arg1,arg2,arg3); + jresult = result; + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_send(int jarg1, void * jarg2, unsigned long jarg3, int jarg4) { + void * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + int arg4 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (size_t)jarg3; + arg4 = (int)jarg4; + result = zts_send(arg1,(void const *)arg2,arg3,arg4); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_sendto(int jarg1, void * jarg2, unsigned long jarg3, int jarg4, zts_sockaddr* jarg5, unsigned short jarg6) { + void * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + int arg4 ; + zts_sockaddr *arg5 = (zts_sockaddr *) 0 ; + zts_socklen_t arg6 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (size_t)jarg3; + arg4 = (int)jarg4; + arg5 = (zts_sockaddr *)jarg5; + arg6 = (zts_socklen_t)jarg6; + result = zts_sendto(arg1,(void const *)arg2,arg3,arg4,(zts_sockaddr const *)arg5,arg6); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_sendmsg(int jarg1, void * jarg2, int jarg3) { + void * jresult ; + int arg1 ; + msghdr *arg2 = (msghdr *) 0 ; + int arg3 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (msghdr *)jarg2; + arg3 = (int)jarg3; + result = zts_sendmsg(arg1,(msghdr const *)arg2,arg3); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_recv(int jarg1, void * jarg2, unsigned long jarg3, int jarg4) { + void * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + int arg4 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (size_t)jarg3; + arg4 = (int)jarg4; + result = zts_recv(arg1,arg2,arg3,arg4); + return result; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_recvfrom(int jarg1, void * jarg2, unsigned long jarg3, int jarg4, zts_sockaddr* jarg5, void * jarg6) { + void * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + int arg4 ; + zts_sockaddr *arg5 = (zts_sockaddr *) 0 ; + zts_socklen_t *arg6 = (zts_socklen_t *) 0 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (size_t)jarg3; + arg4 = (int)jarg4; + arg5 = (zts_sockaddr *)jarg5; + arg6 = (zts_socklen_t *)jarg6; + result = zts_recvfrom(arg1,arg2,arg3,arg4,arg5,arg6); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_recvmsg(int jarg1, void * jarg2, int jarg3) { + void * jresult ; + int arg1 ; + msghdr *arg2 = (msghdr *) 0 ; + int arg3 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (msghdr *)jarg2; + arg3 = (int)jarg3; + result = zts_recvmsg(arg1,arg2,arg3); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_read(int jarg1, void * jarg2, unsigned long jarg3) { + void * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (size_t)jarg3; + result = zts_read(arg1,arg2,arg3); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_readv(int jarg1, void * jarg2, int jarg3) { + void * jresult ; + int arg1 ; + zts_iovec *arg2 = (zts_iovec *) 0 ; + int arg3 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (zts_iovec *)jarg2; + arg3 = (int)jarg3; + result = zts_readv(arg1,(zts_iovec const *)arg2,arg3); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_write(int jarg1, void * jarg2, unsigned long jarg3) { + void * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + size_t arg3 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (size_t)jarg3; + result = zts_write(arg1,(void const *)arg2,arg3); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT void * SWIGSTDCALL CSharp_zts_writev(int jarg1, void * jarg2, int jarg3) { + void * jresult ; + int arg1 ; + zts_iovec *arg2 = (zts_iovec *) 0 ; + int arg3 ; + ssize_t result; + + arg1 = (int)jarg1; + arg2 = (zts_iovec *)jarg2; + arg3 = (int)jarg3; + result = zts_writev(arg1,(zts_iovec const *)arg2,arg3); + jresult = new ssize_t((const ssize_t &)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_shutdown(int jarg1, int jarg2) { + int jresult ; + int arg1 ; + int arg2 ; + int result; + + arg1 = (int)jarg1; + arg2 = (int)jarg2; + result = (int)zts_shutdown(arg1,arg2); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_add_dns_nameserver(zts_sockaddr* jarg1) { + int jresult ; + zts_sockaddr *arg1 = (zts_sockaddr *) 0 ; + int result; + + arg1 = (zts_sockaddr *)jarg1; + result = (int)zts_add_dns_nameserver(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_del_dns_nameserver(zts_sockaddr* jarg1) { + int jresult ; + zts_sockaddr *arg1 = (zts_sockaddr *) 0 ; + int result; + + arg1 = (zts_sockaddr *)jarg1; + result = (int)zts_del_dns_nameserver(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT unsigned short SWIGSTDCALL CSharp_zts_htons(unsigned short jarg1) { + unsigned short jresult ; + uint16_t arg1 ; + uint16_t result; + + arg1 = (uint16_t)jarg1; + result = zts_htons(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT unsigned short SWIGSTDCALL CSharp_zts_htonl(unsigned short jarg1) { + unsigned short jresult ; + uint32_t arg1 ; + uint32_t result; + + arg1 = (uint32_t)jarg1; + result = zts_htonl(arg1); + jresult = result; + return jresult; +} + +SWIGEXPORT unsigned short SWIGSTDCALL CSharp_zts_ntohs(unsigned short jarg1) { + unsigned short jresult ; + uint16_t arg1 ; + uint16_t result; + + arg1 = (uint16_t)jarg1; + result = zts_ntohs(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT unsigned short SWIGSTDCALL CSharp_zts_ntohl(unsigned short jarg1) { + unsigned short jresult ; + uint32_t arg1 ; + uint32_t result; + + arg1 = (uint32_t)jarg1; + result = zts_ntohl(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT char * SWIGSTDCALL CSharp_zts_inet_ntop(int jarg1, void * jarg2, char * jarg3, unsigned short jarg4) { + char * jresult ; + int arg1 ; + void *arg2 = (void *) 0 ; + char *arg3 = (char *) 0 ; + zts_socklen_t arg4 ; + char *result = 0 ; + + arg1 = (int)jarg1; + arg2 = (void *)jarg2; + arg3 = (char *)jarg3; + arg4 = (zts_socklen_t)jarg4; + result = (char *)zts_inet_ntop(arg1,(void const *)arg2,arg3,arg4); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_zts_inet_pton(int jarg1, char * jarg2, void * jarg3) { + int jresult ; + int arg1 ; + char *arg2 = (char *) 0 ; + void *arg3 = (void *) 0 ; + int result; + + arg1 = (int)jarg1; + arg2 = (char *)jarg2; + arg3 = (void *)jarg3; + result = (int)zts_inet_pton(arg1,(char const *)arg2,arg3); + jresult = result; + return jresult; +} + +#ifdef __cplusplus +} +#endif + diff --git a/src/Controls.cpp b/src/Controls.cpp index 125e935..808fb7a 100644 --- a/src/Controls.cpp +++ b/src/Controls.cpp @@ -93,7 +93,11 @@ int zts_allow_local_conf(uint8_t allowed = 1) return ZTS_ERR_SERVICE; } +#ifdef ZTS_PINVOKE +int zts_start(const char *path, CppCallback callback, uint16_t port) +#else int zts_start(const char *path, void (*callback)(void *), uint16_t port) +#endif { Mutex::Lock _l(serviceLock); _lwip_driver_init();