diff --git a/src/bindings/csharp/Constants.cs b/src/bindings/csharp/Constants.cs
index 69dcb3a..e7c6882 100644
--- a/src/bindings/csharp/Constants.cs
+++ b/src/bindings/csharp/Constants.cs
@@ -250,7 +250,7 @@ namespace ZeroTier
public static readonly short MSG_DONTWAIT = 0x0008;
public static readonly short MSG_MORE = 0x0010;
- // Macro's for defining ioctl() command values
+ // Macros for defining ioctl() command values
/*
public static readonly ulong IOCPARM_MASK = 0x7fU;
public static readonly ulong IOC_VOID = 0x20000000UL;
diff --git a/src/bindings/csharp/Event.cs b/src/bindings/csharp/Event.cs
index db5e18d..f5ed712 100644
--- a/src/bindings/csharp/Event.cs
+++ b/src/bindings/csharp/Event.cs
@@ -15,7 +15,7 @@ using System.Net;
using ZeroTier;
-namespace ZeroTier
+namespace ZeroTier.Core
{
/* Convenience structures for exposing lower level operational details to the user.
These structures do not have the same memory layout or content as those found in
diff --git a/src/bindings/csharp/Node.cs b/src/bindings/csharp/Node.cs
index 3771af7..1be62b6 100644
--- a/src/bindings/csharp/Node.cs
+++ b/src/bindings/csharp/Node.cs
@@ -14,6 +14,8 @@
using System.Runtime.InteropServices;
using System;
+using ZeroTier;
+
// Prototype of callback used by ZeroTier to signal events to C# application
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void CSharpCallbackWithStruct(IntPtr msgPtr);
@@ -21,9 +23,9 @@ public delegate void CSharpCallbackWithStruct(IntPtr msgPtr);
///
/// ZeroTier SDK
///
-namespace ZeroTier
+namespace ZeroTier.Core
{
- public delegate void ZeroTierManagedEventCallback(ZeroTier.Event nodeEvent);
+ public delegate void ZeroTierManagedEventCallback(ZeroTier.Core.Event nodeEvent);
///
/// ZeroTier Node - Virtual network subsystem
@@ -45,11 +47,11 @@ namespace ZeroTier
zts_callback_msg msg =
(zts_callback_msg)Marshal.PtrToStructure(msgPtr, typeof(zts_callback_msg));
- ZeroTier.Event newEvent = null;
+ ZeroTier.Core.Event newEvent = null;
// Node events
if (msg.eventCode == Constants.EVENT_NODE_UP) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_UP");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NODE_UP");
}
if (msg.eventCode == Constants.EVENT_NODE_ONLINE) {
_isOnline = true;
@@ -57,135 +59,135 @@ namespace ZeroTier
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");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode, "EVENT_NODE_ONLINE");
}
if (msg.eventCode == Constants.EVENT_NODE_OFFLINE) {
_isOnline = false;
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_OFFLINE");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NODE_DOWN");
}
if (msg.eventCode == Constants.EVENT_NODE_IDENTITY_COLLISION) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NODE_IDENTITY_COLLISION");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NETWORK_READY_IP6");
}
if (msg.eventCode == Constants.EVENT_NETWORK_DOWN) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_DOWN");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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 = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NETWORK_READY_IP4_IP6");
}
if (msg.eventCode == Constants.EVENT_NETWORK_UPDATE) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETWORK_UPDATE");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NETWORK_UPDATE");
}
// Stack events
if (msg.eventCode == Constants.EVENT_STACK_UP) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_STACK_UP");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_STACK_UP");
}
if (msg.eventCode == Constants.EVENT_STACK_DOWN) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_STACK_DOWN");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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.Core.Event(msg.eventCode,"EVENT_PEER_RELAY");
}
- // newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_UNREACHABLE");
+ // newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_PEER_UNREACHABLE");
if (msg.eventCode == Constants.EVENT_PEER_PATH_DISCOVERED) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_PEER_PATH_DISCOVERED");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_ROUTE_ADDED");
}
if (msg.eventCode == Constants.EVENT_ROUTE_REMOVED) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_ROUTE_REMOVED");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_ROUTE_REMOVED");
}
// Netif events
if (msg.eventCode == Constants.EVENT_NETIF_UP) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_UP");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NETIF_UP");
}
if (msg.eventCode == Constants.EVENT_NETIF_DOWN) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_DOWN");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NETIF_DOWN");
}
if (msg.eventCode == Constants.EVENT_NETIF_REMOVED) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_REMOVED");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_NETIF_REMOVED");
}
if (msg.eventCode == Constants.EVENT_NETIF_LINK_UP) {
- newEvent = new ZeroTier.Event(msg.eventCode,"EVENT_NETIF_LINK_UP");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.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");
+ newEvent = new ZeroTier.Core.Event(msg.eventCode,"EVENT_ADDR_REMOVED_IP6");
}
// Pass the converted Event to the managed callback (visible to user)
diff --git a/src/bindings/csharp/Socket.cs b/src/bindings/csharp/Socket.cs
index 4de872b..2cce0d1 100644
--- a/src/bindings/csharp/Socket.cs
+++ b/src/bindings/csharp/Socket.cs
@@ -13,7 +13,7 @@
using System; // For ObjectDisposedException
using System.Net; // For IPEndPoint
-using System.Net.Sockets; // For ZeroTier.SocketException
+using System.Net.Sockets; // For ZeroTier.Sockets.SocketException
using System.Runtime.InteropServices;
using ZeroTier;
@@ -21,7 +21,7 @@ using ZeroTier;
///
/// ZeroTier SDK
///
-namespace ZeroTier
+namespace ZeroTier.Sockets
{
///
/// ZeroTier Socket - An lwIP socket mediated over a ZeroTier virtual link
@@ -45,6 +45,8 @@ namespace ZeroTier
bool _isClosed;
bool _isListening;
bool _isBlocking;
+ bool _isBound;
+ bool _isConnected;
AddressFamily _socketFamily;
SocketType _socketType;
@@ -101,7 +103,7 @@ namespace ZeroTier
}
if ((_fd = zts_socket(family, type, protocol)) < 0)
{
- throw new ZeroTier.SocketException((int)_fd);
+ throw new ZeroTier.Sockets.SocketException((int)_fd);
}
_socketFamily = addressFamily;
_socketType = socketType;
@@ -132,13 +134,14 @@ namespace ZeroTier
}
if (_fd < 0) {
// Invalid file descriptor
- throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
}
if (remoteEndPoint == null) {
throw new ArgumentNullException("remoteEndPoint");
}
int err = Constants.ERR_OK;
int addrlen = 0;
+ IntPtr remoteAddrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr)));
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
{
zts_sockaddr_in sa = new zts_sockaddr_in();
@@ -159,10 +162,9 @@ namespace ZeroTier
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);
+ Marshal.StructureToPtr(sa, remoteAddrPtr, false);
+ //zts_sockaddr sAddr = (zts_sockaddr)Marshal.PtrToStructure(remoteAddrPtr, typeof(zts_sockaddr));
+ err = zts_connect(_fd, remoteAddrPtr, (byte)addrlen);
}
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
@@ -179,9 +181,11 @@ namespace ZeroTier
*/
}
if (err < 0) {
- throw new ZeroTier.SocketException(err, ZeroTier.Node.ErrNo);
+ throw new ZeroTier.Sockets.SocketException(err, ZeroTier.Core.Node.ErrNo);
}
+ Marshal.FreeHGlobal(remoteAddrPtr);
_remoteEndPoint = remoteEndPoint;
+ _isConnected = true;
}
public void Bind(IPEndPoint localEndPoint)
@@ -191,13 +195,14 @@ namespace ZeroTier
}
if (_fd < 0) {
// Invalid file descriptor
- throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
}
if (localEndPoint == null) {
throw new ArgumentNullException("localEndPoint");
}
int err = Constants.ERR_OK;
int addrlen = 0;
+ IntPtr localAddrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr)));
if (localEndPoint.AddressFamily == AddressFamily.InterNetwork)
{
zts_sockaddr_in sa = new zts_sockaddr_in();
@@ -217,10 +222,9 @@ namespace ZeroTier
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);
+
+ Marshal.StructureToPtr(sa, localAddrPtr, false);
+ err = zts_bind(_fd, localAddrPtr, (byte)addrlen);
}
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
{
@@ -236,9 +240,11 @@ namespace ZeroTier
*/
}
if (err < 0) {
- throw new ZeroTier.SocketException((int)err);
+ throw new ZeroTier.Sockets.SocketException((int)err);
}
+ Marshal.FreeHGlobal(localAddrPtr);
_localEndPoint = localEndPoint;
+ _isBound = true;
}
public void Listen(int backlog)
@@ -248,12 +254,12 @@ namespace ZeroTier
}
if (_fd < 0) {
// Invalid file descriptor
- throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
}
int err = Constants.ERR_OK;
if ((err = zts_listen(_fd, backlog)) < 0) {
// Invalid backlog value perhaps?
- throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
}
_isListening = true;
}
@@ -265,7 +271,7 @@ namespace ZeroTier
}
if (_fd < 0) {
// Invalid file descriptor
- throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
}
if (_isListening == false) {
throw new InvalidOperationException("Socket is not in a listening state. Call Listen() first");
@@ -281,7 +287,7 @@ namespace ZeroTier
int err = zts_accept(_fd, remoteAddrPtr, addrlenPtr);
if (err < 0) {
- throw new ZeroTier.SocketException(err, ZeroTier.Node.ErrNo);
+ throw new ZeroTier.Sockets.SocketException(err, ZeroTier.Core.Node.ErrNo);
}
in4 = (zts_sockaddr_in)Marshal.PtrToStructure(remoteAddrPtr, typeof(zts_sockaddr_in));
// Convert sockaddr contents to IPEndPoint
@@ -290,6 +296,7 @@ namespace ZeroTier
// Create new socket by providing file descriptor returned from zts_accept call.
Socket clientSocket = new Socket(
err, _socketFamily, _socketType, _socketProtocol, _localEndPoint, clientEndPoint);
+ Marshal.FreeHGlobal(remoteAddrPtr);
return clientSocket;
}
@@ -323,20 +330,6 @@ namespace ZeroTier
_isClosed = true;
}
- public EndPoint RemoteEndPoint
- {
- get {
- return _remoteEndPoint;
- }
- }
-
- public EndPoint LocalEndPoint
- {
- get {
- return _localEndPoint;
- }
- }
-
public bool Blocking
{
get {
@@ -348,18 +341,16 @@ namespace ZeroTier
}
int opts = 0;
if ((opts = zts_fcntl(_fd, (int)(ZeroTier.Constants.F_GETFL), 0)) < 0) {
- throw new ZeroTier.SocketException(opts, ZeroTier.Node.ErrNo);
+ throw new ZeroTier.Sockets.SocketException(opts, ZeroTier.Core.Node.ErrNo);
}
- Console.WriteLine("before.opts={0}", opts);
if (value) { // Blocking
opts = opts & (~(ZeroTier.Constants.O_NONBLOCK));
}
if (!value) { // Non-Blocking
opts = opts | (int)(ZeroTier.Constants.O_NONBLOCK);
}
- Console.WriteLine("after.opts={0}", opts);
if ((opts = zts_fcntl(_fd, ZeroTier.Constants.F_SETFL, (int)opts)) < 0) {
- throw new ZeroTier.SocketException(opts, ZeroTier.Node.ErrNo);
+ throw new ZeroTier.Sockets.SocketException(opts, ZeroTier.Core.Node.ErrNo);
}
_isBlocking = value;
}
@@ -379,7 +370,8 @@ namespace ZeroTier
poll_set.events = (short)((byte)ZeroTier.Constants.POLLOUT);
}
if (mode == SelectMode.SelectError) {
- poll_set.events = (short)((byte)ZeroTier.Constants.POLLERR | (byte)ZeroTier.Constants.POLLNVAL);
+ poll_set.events = (short)((byte)ZeroTier.Constants.POLLERR |
+ (byte)ZeroTier.Constants.POLLNVAL);
}
IntPtr poll_fd_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_pollfd)));
Marshal.StructureToPtr(poll_set, poll_fd_ptr, false);
@@ -387,20 +379,23 @@ namespace ZeroTier
int timeout_ms = (microSeconds / 1000);
uint numfds = 1;
if ((result = zts_poll(poll_fd_ptr, numfds, timeout_ms)) < 0) {
- throw new ZeroTier.SocketException(result, ZeroTier.Node.ErrNo);
+ throw new ZeroTier.Sockets.SocketException(result, ZeroTier.Core.Node.ErrNo);
}
poll_set = (zts_pollfd)Marshal.PtrToStructure(poll_fd_ptr, typeof(zts_pollfd));
- if (result == 0) { return false; } // No events
- if (mode == SelectMode.SelectRead) {
- return ((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLIN) != 0;
+ if (result != 0) {
+ if (mode == SelectMode.SelectRead) {
+ result = Convert.ToInt32(((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLIN) != 0);
+ }
+ if (mode == SelectMode.SelectWrite) {
+ result = Convert.ToInt32(((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLOUT) != 0);
+ }
+ if (mode == SelectMode.SelectError) {
+ result = Convert.ToInt32(((poll_set.revents & (byte)ZeroTier.Constants.POLLERR) != 0) ||
+ ((poll_set.revents & (byte)ZeroTier.Constants.POLLNVAL) != 0));
+ }
}
- if (mode == SelectMode.SelectWrite) {
- return ((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLOUT) != 0;
- }
- if (mode == SelectMode.SelectError) {
- return ((poll_set.revents & (byte)ZeroTier.Constants.POLLERR) != 0) || ((poll_set.revents & (byte)ZeroTier.Constants.POLLNVAL) != 0);
- }
- return false;
+ Marshal.FreeHGlobal(poll_fd_ptr);
+ return result > 0;
}
public Int32 Send(Byte[] buffer)
@@ -409,7 +404,7 @@ namespace ZeroTier
throw new ObjectDisposedException("Socket has been closed");
}
if (_fd < 0) {
- throw new ZeroTier.SocketException((int)ZeroTier.Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)ZeroTier.Constants.ERR_SOCKET);
}
if (buffer == null) {
throw new ArgumentNullException("buffer");
@@ -425,7 +420,7 @@ namespace ZeroTier
throw new ObjectDisposedException("Socket has been closed");
}
if (_fd < 0) {
- throw new ZeroTier.SocketException((int)ZeroTier.Constants.ERR_SOCKET);
+ throw new ZeroTier.Sockets.SocketException((int)ZeroTier.Constants.ERR_SOCKET);
}
if (buffer == null) {
throw new ArgumentNullException("buffer");
@@ -435,6 +430,87 @@ namespace ZeroTier
return zts_recv(_fd, bufferPtr, (uint)Buffer.ByteLength(buffer), (int)flags);
}
+ private void _set_timeout(int timeout_ms, int optname)
+ {
+ zts_timeval tv = new zts_timeval();
+ // Convert milliseconds to timeval struct
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+ IntPtr tv_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_timeval)));
+ Marshal.StructureToPtr(tv, tv_ptr, false);
+ ushort option_size = (ushort)Marshal.SizeOf(typeof(zts_sockaddr_in));
+ int err = 0;
+ if ((err = zts_setsockopt(_fd, ZeroTier.Constants.SOL_SOCKET,
+ ZeroTier.Constants.SO_RCVTIMEO, tv_ptr, option_size)) < 0) {
+ throw new ZeroTier.Sockets.SocketException(err, ZeroTier.Core.Node.ErrNo);
+ }
+ Marshal.FreeHGlobal(tv_ptr);
+ }
+
+ private int _get_timeout(int optname)
+ {
+ zts_timeval tv = new zts_timeval();
+ IntPtr tv_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_timeval)));
+ Marshal.StructureToPtr(tv, tv_ptr, false);
+ ushort optlen = (ushort)Marshal.SizeOf(typeof(zts_timeval));
+ GCHandle optlen_gc_handle = GCHandle.Alloc(optlen, GCHandleType.Pinned);
+ IntPtr optlen_ptr = optlen_gc_handle.AddrOfPinnedObject();
+ int err = 0;
+ if ((err = zts_getsockopt(_fd, ZeroTier.Constants.SOL_SOCKET,
+ ZeroTier.Constants.SO_RCVTIMEO, tv_ptr, optlen_ptr)) < 0) {
+ throw new ZeroTier.Sockets.SocketException(err, ZeroTier.Core.Node.ErrNo);
+ }
+ tv = (zts_timeval)Marshal.PtrToStructure(tv_ptr, typeof(zts_timeval));
+ optlen_gc_handle.Free();
+ Marshal.FreeHGlobal(tv_ptr);
+ // Convert timeval struct to milliseconds
+ return (int)((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
+ }
+
+ public int ReceiveTimeout
+ {
+ get { return _get_timeout(ZeroTier.Constants.SO_RCVTIMEO); }
+ set { _set_timeout(value, ZeroTier.Constants.SO_RCVTIMEO); }
+ }
+
+ public int SendTimeout
+ {
+ get { return _get_timeout(ZeroTier.Constants.SO_SNDTIMEO); }
+ set { _set_timeout(value, ZeroTier.Constants.SO_SNDTIMEO); }
+ }
+
+ /* TODO
+ public int ReceiveBufferSize { get; set; }
+
+ public int SendBufferSize { get; set; }
+
+ public short Ttl { get; set; }
+
+ public LingerOption LingerState { get; set; }
+
+ public bool NoDelay { get; set; }
+ */
+
+ public bool Connected { get { return _isConnected; } }
+
+ public bool IsBound { get { return _isBound; } }
+
+ public AddressFamily AddressFamily { get { return _socketFamily; } }
+
+ public SocketType SocketType { get { return _socketType; } }
+
+ public ProtocolType ProtocolType { get { return _socketProtocol; } }
+
+ /* .NET has moved to OSSupportsIPv* but libzt isn't an OS so we keep this old convention */
+ public static bool SupportsIPv4 { get { return true; } }
+
+ /* .NET has moved to OSSupportsIPv* but libzt isn't an OS so we keep this old convention */
+ public static bool SupportsIPv6 { get { return true; } }
+
+ public EndPoint RemoteEndPoint { get { return _remoteEndPoint; } }
+
+ public EndPoint LocalEndPoint { get { return _localEndPoint; } }
+
/* Structures and functions used internally to communicate with
lower-level C API defined in include/ZeroTierSockets.h */
@@ -587,5 +663,12 @@ namespace ZeroTier
public short events;
public short revents;
}
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct zts_timeval
+ {
+ public long tv_sec;
+ public long tv_usec;
+ }
}
}
diff --git a/src/bindings/csharp/SocketException.cs b/src/bindings/csharp/SocketException.cs
index 40dfc5f..3a15568 100644
--- a/src/bindings/csharp/SocketException.cs
+++ b/src/bindings/csharp/SocketException.cs
@@ -13,7 +13,7 @@
using System;
-namespace ZeroTier
+namespace ZeroTier.Sockets
{
/// Exception class for ZeroTier service and low-level socket errors
public class SocketException : Exception
diff --git a/src/bindings/csharp/zt_wrap.cxx b/src/bindings/csharp/zt_wrap.cxx
index 4d88a87..1e93c3d 100644
--- a/src/bindings/csharp/zt_wrap.cxx
+++ b/src/bindings/csharp/zt_wrap.cxx
@@ -587,7 +587,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_zts_delay_ms(long jarg1) {
zts_delay_ms(arg1);
}
-
+/*
SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_all_stats(void * jarg1) {
int jresult ;
zts_stats *arg1 = (zts_stats *) 0 ;
@@ -612,7 +612,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_protocol_stats(int jarg1, void * jarg2
jresult = result;
return jresult;
}
-
+*/
SWIGEXPORT int SWIGSTDCALL CSharp_zts_socket(int jarg1, int jarg2, int jarg3) {
int jresult ;