Update C# wrapper (Namespace restructure, API additions, memory leak fix)
This commit is contained in:
@@ -5,24 +5,39 @@ using System.Net;
|
|||||||
using System.Net.Sockets; // For SocketType, etc
|
using System.Net.Sockets; // For SocketType, etc
|
||||||
using System.Text; // For Encoding
|
using System.Text; // For Encoding
|
||||||
|
|
||||||
using ZeroTier; // For ZeroTier.Node, ZeroTier.Event, and ZeroTier.Socket
|
/**
|
||||||
|
*
|
||||||
|
* Namespaces explained:
|
||||||
|
*
|
||||||
|
* ZeroTier.Core (API to control a ZeroTier Node)
|
||||||
|
* -> class ZeroTier.Core.Node
|
||||||
|
* -> class ZeroTier.Core.Event
|
||||||
|
*
|
||||||
|
* ZeroTier.Sockets (Socket API similar to System.Net.Sockets)
|
||||||
|
* -> class ZeroTier.Sockets.Socket
|
||||||
|
* -> class ZeroTier.Sockets.SocketException
|
||||||
|
*
|
||||||
|
* ZeroTier.Central (upcoming)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
using ZeroTier;
|
||||||
|
|
||||||
public class ExampleApp {
|
public class ExampleApp {
|
||||||
|
|
||||||
ZeroTier.Node node;
|
ZeroTier.Core.Node node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize and start ZeroTier
|
* Initialize and start ZeroTier
|
||||||
*/
|
*/
|
||||||
public void StartZeroTier(string configFilePath, ushort servicePort, ulong networkId)
|
public void StartZeroTier(string configFilePath, ushort servicePort, ulong networkId)
|
||||||
{
|
{
|
||||||
node = new ZeroTier.Node(configFilePath, OnZeroTierEvent, servicePort);
|
node = new ZeroTier.Core.Node(configFilePath, OnZeroTierEvent, servicePort);
|
||||||
node.Start(); // Network activity only begins after calling Start()
|
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
|
/* How you do this next part is up to you, but essentially we're waiting for the node
|
||||||
to signal to us (via a ZeroTier.Event) that it has access to the internet and is
|
to signal to us via OnZeroTierEvent(ZeroTier.Core.Event) that it has access to the
|
||||||
able to talk to one of our root servers. As a convenience you can just periodically check
|
internet and is able to talk to one of our root servers. As a convenience you can just
|
||||||
IsOnline() instead of looking for the event via the callback. */
|
periodically check Node.IsOnline() instead of looking for the event via the callback. */
|
||||||
while (!node.IsOnline()) { Thread.Sleep(100); }
|
while (!node.IsOnline()) { Thread.Sleep(100); }
|
||||||
|
|
||||||
/* After the node comes online you may now join/leave networks. You will receive
|
/* After the node comes online you may now join/leave networks. You will receive
|
||||||
@@ -31,7 +46,7 @@ public class ExampleApp {
|
|||||||
or removed routes, etc. */
|
or removed routes, etc. */
|
||||||
node.Join(networkId);
|
node.Join(networkId);
|
||||||
|
|
||||||
/* Note that ZeroTier.Socket calls will fail if there are no routes available, for this
|
/* Note that ZeroTier.Sockets.Socket calls will fail if there are no routes available, for this
|
||||||
reason we should wait to make those calls until the node has indicated to us that at
|
reason we should wait to make those calls until the node has indicated to us that at
|
||||||
least one network has been joined successfully. */
|
least one network has been joined successfully. */
|
||||||
while (!node.HasRoutes()) { Thread.Sleep(100); }
|
while (!node.HasRoutes()) { Thread.Sleep(100); }
|
||||||
@@ -49,7 +64,7 @@ public class ExampleApp {
|
|||||||
* Your application should process event messages and return control as soon as possible. Blocking
|
* Your application should process event messages and return control as soon as possible. Blocking
|
||||||
* or otherwise time-consuming operations are not reccomended here.
|
* or otherwise time-consuming operations are not reccomended here.
|
||||||
*/
|
*/
|
||||||
public void OnZeroTierEvent(ZeroTier.Event e)
|
public void OnZeroTierEvent(ZeroTier.Core.Event e)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Event.eventCode = {0} ({1})", e.EventCode, e.EventName);
|
Console.WriteLine("Event.eventCode = {0} ({1})", e.EventCode, e.EventName);
|
||||||
|
|
||||||
@@ -73,7 +88,7 @@ public class ExampleApp {
|
|||||||
byte[] bytes = new Byte[1024];
|
byte[] bytes = new Byte[1024];
|
||||||
|
|
||||||
Console.WriteLine(localEndPoint.ToString());
|
Console.WriteLine(localEndPoint.ToString());
|
||||||
ZeroTier.Socket listener = new ZeroTier.Socket(AddressFamily.InterNetwork,
|
ZeroTier.Sockets.Socket listener = new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork,
|
||||||
SocketType.Stream, ProtocolType.Tcp );
|
SocketType.Stream, ProtocolType.Tcp );
|
||||||
|
|
||||||
// Bind the socket to the local endpoint and
|
// Bind the socket to the local endpoint and
|
||||||
@@ -89,13 +104,13 @@ public class ExampleApp {
|
|||||||
// Program is suspended while waiting for an incoming connection.
|
// Program is suspended while waiting for an incoming connection.
|
||||||
bool nonblocking = true;
|
bool nonblocking = true;
|
||||||
|
|
||||||
ZeroTier.Socket handler;
|
ZeroTier.Sockets.Socket handler;
|
||||||
|
|
||||||
if (nonblocking) { // Non-blocking style Accept() loop using Poll()
|
if (nonblocking) { // Non-blocking style Accept() loop using Poll()
|
||||||
Console.WriteLine("Starting non-blocking Accept() loop...");
|
Console.WriteLine("Starting non-blocking Accept() loop...");
|
||||||
listener.Blocking = false;
|
listener.Blocking = false;
|
||||||
// loop
|
// loop
|
||||||
int timeout = 1000000; // microseconds (1 second)
|
int timeout = 100000; // microseconds (1 second)
|
||||||
while (true) {
|
while (true) {
|
||||||
Console.WriteLine("Polling... (for data or incoming connections)");
|
Console.WriteLine("Polling... (for data or incoming connections)");
|
||||||
if (listener.Poll(timeout, SelectMode.SelectRead)) {
|
if (listener.Poll(timeout, SelectMode.SelectRead)) {
|
||||||
@@ -103,7 +118,7 @@ public class ExampleApp {
|
|||||||
handler = listener.Accept();
|
handler = listener.Accept();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Thread.Sleep(1000);
|
//Thread.Sleep(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // Blocking style
|
else { // Blocking style
|
||||||
@@ -113,26 +128,40 @@ public class ExampleApp {
|
|||||||
data = null;
|
data = null;
|
||||||
Console.WriteLine("Accepted connection from: " + handler.RemoteEndPoint.ToString());
|
Console.WriteLine("Accepted connection from: " + handler.RemoteEndPoint.ToString());
|
||||||
|
|
||||||
|
// handler.ReceiveTimeout = 1000;
|
||||||
|
|
||||||
// An incoming connection needs to be processed.
|
// An incoming connection needs to be processed.
|
||||||
while (true) {
|
while (true) {
|
||||||
int bytesRec = handler.Receive(bytes);
|
int bytesRec = 0;
|
||||||
Console.WriteLine("Bytes received: {0}", bytesRec);
|
try {
|
||||||
data += Encoding.ASCII.GetString(bytes,0,bytesRec);
|
Console.WriteLine("Receiving...");
|
||||||
|
bytesRec = handler.Receive(bytes);
|
||||||
|
}
|
||||||
|
catch (ZeroTier.Sockets.SocketException e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("ServiveErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
|
||||||
|
}
|
||||||
if (bytesRec > 0) {
|
if (bytesRec > 0) {
|
||||||
|
Console.WriteLine("Bytes received: {0}", bytesRec);
|
||||||
|
data = Encoding.ASCII.GetString(bytes,0,bytesRec);
|
||||||
Console.WriteLine( "Text received : {0}", data);
|
Console.WriteLine( "Text received : {0}", data);
|
||||||
break;
|
//break;
|
||||||
}
|
|
||||||
}
|
|
||||||
// Echo the data back to the client.
|
// Echo the data back to the client.
|
||||||
byte[] msg = Encoding.ASCII.GetBytes(data);
|
byte[] msg = Encoding.ASCII.GetBytes(data);
|
||||||
|
|
||||||
handler.Send(msg);
|
handler.Send(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.GC.Collect();
|
||||||
|
Console.WriteLine("No data...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handler.Shutdown(SocketShutdown.Both);
|
handler.Shutdown(SocketShutdown.Both);
|
||||||
handler.Close();
|
handler.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ZeroTier.SocketException e) {
|
} catch (ZeroTier.Sockets.SocketException e) {
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
Console.WriteLine("ServiveErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
|
Console.WriteLine("ServiveErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
|
||||||
}
|
}
|
||||||
@@ -151,7 +180,7 @@ public class ExampleApp {
|
|||||||
// Connect to a remote device.
|
// Connect to a remote device.
|
||||||
try {
|
try {
|
||||||
// Create a TCP/IP socket.
|
// Create a TCP/IP socket.
|
||||||
ZeroTier.Socket sender = new ZeroTier.Socket(AddressFamily.InterNetwork,
|
ZeroTier.Sockets.Socket sender = new ZeroTier.Sockets.Socket(AddressFamily.InterNetwork,
|
||||||
SocketType.Stream, ProtocolType.Tcp );
|
SocketType.Stream, ProtocolType.Tcp );
|
||||||
|
|
||||||
// Connect the socket to the remote endpoint. Catch any errors.
|
// Connect the socket to the remote endpoint. Catch any errors.
|
||||||
@@ -181,7 +210,7 @@ public class ExampleApp {
|
|||||||
|
|
||||||
} catch (ArgumentNullException ane) {
|
} catch (ArgumentNullException ane) {
|
||||||
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
|
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
|
||||||
} catch (ZeroTier.SocketException e) {
|
} catch (ZeroTier.Sockets.SocketException e) {
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
Console.WriteLine("ServiveErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
|
Console.WriteLine("ServiveErrorCode={0} SocketErrorCode={1}", e.ServiceErrorCode, e.SocketErrorCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<license type="file">LICENSE.txt</license>
|
<license type="file">LICENSE.txt</license>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<releaseNotes>Initial release</releaseNotes>
|
<releaseNotes>Namespace adjustments, additions to Socket API, memory leak fixes.</releaseNotes>
|
||||||
<description>Encrypted P2P SD-WAN networking layer (Managed C# API) [x64]</description>
|
<description>Encrypted P2P SD-WAN networking layer (Managed C# API) [x64]</description>
|
||||||
<title>Encrypted P2P SD-WAN networking layer (Managed C# API) [x64]</title>
|
<title>Encrypted P2P SD-WAN networking layer (Managed C# API) [x64]</title>
|
||||||
<copyright>Copyright 2021 ZeroTier, Inc.</copyright>
|
<copyright>Copyright 2021 ZeroTier, Inc.</copyright>
|
||||||
|
|||||||
29
pkg/nuget/ZeroTier.Sockets/nuget.org.md
Normal file
29
pkg/nuget/ZeroTier.Sockets/nuget.org.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
[ZeroTier](https://www.zerotier.com) SDK
|
||||||
|
=====
|
||||||
|
|
||||||
|
Connect physical devices, virtual devices, and application instances as if everything is on a single LAN.
|
||||||
|
|
||||||
|
ZeroTier brings your network into user-space. We've paired our network hypervisor core with a TCP/UDP/IP stack [(lwIP)](https://en.wikipedia.org/wiki/LwIP) to provide your application with an exclusive and private virtual network interface. All traffic on this interface is end-to-end encrypted between each peer and we provide an easy-to-use socket interface similar to [Berkeley Sockets](https://en.wikipedia.org/wiki/Berkeley_sockets). Since we aren't using the kernel's IP stack that means no drivers, no root, and no host configuration requirements.
|
||||||
|
|
||||||
|
- Website: https://www.zerotier.com/
|
||||||
|
- ZeroTier Manual: https://www.zerotier.com/manual/
|
||||||
|
- ZeroTier Repo: https://github.com/zerotier/zerotierone
|
||||||
|
- SDK Repo: https://github.com/zerotier/libzt
|
||||||
|
- Forum: https://discuss.zerotier.com
|
||||||
|
|
||||||
|
## 1.3.3-alpha.2 Release Notes
|
||||||
|
|
||||||
|
### New namespace structure:
|
||||||
|
- `ZeroTier.Core` (API to control a ZeroTier Node)
|
||||||
|
- `class ZeroTier.Core.Node`
|
||||||
|
- `class ZeroTier.Core.Event`
|
||||||
|
- `ZeroTier.Sockets`
|
||||||
|
- `class ZeroTier.Sockets.Socket`
|
||||||
|
- `class ZeroTier.Sockets.SocketException`
|
||||||
|
- `ZeroTier.Central` (upcoming)
|
||||||
|
|
||||||
|
### Added to Socket API
|
||||||
|
- `Socket.ReceiveTimeout`, `Socket.SendTimeout`, etc.
|
||||||
|
|
||||||
|
### Bugs
|
||||||
|
- Fixed memory leak caused by unmanaged resources not being released.
|
||||||
@@ -250,7 +250,7 @@ namespace ZeroTier
|
|||||||
public static readonly short MSG_DONTWAIT = 0x0008;
|
public static readonly short MSG_DONTWAIT = 0x0008;
|
||||||
public static readonly short MSG_MORE = 0x0010;
|
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 IOCPARM_MASK = 0x7fU;
|
||||||
public static readonly ulong IOC_VOID = 0x20000000UL;
|
public static readonly ulong IOC_VOID = 0x20000000UL;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using System.Net;
|
|||||||
|
|
||||||
using ZeroTier;
|
using ZeroTier;
|
||||||
|
|
||||||
namespace ZeroTier
|
namespace ZeroTier.Core
|
||||||
{
|
{
|
||||||
/* Convenience structures for exposing lower level operational details to the user.
|
/* 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
|
These structures do not have the same memory layout or content as those found in
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
|
using ZeroTier;
|
||||||
|
|
||||||
// Prototype of callback used by ZeroTier to signal events to C# application
|
// Prototype of callback used by ZeroTier to signal events to C# application
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void CSharpCallbackWithStruct(IntPtr msgPtr);
|
public delegate void CSharpCallbackWithStruct(IntPtr msgPtr);
|
||||||
@@ -21,9 +23,9 @@ public delegate void CSharpCallbackWithStruct(IntPtr msgPtr);
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZeroTier SDK
|
/// ZeroTier SDK
|
||||||
/// </summary>
|
/// </summary>
|
||||||
namespace ZeroTier
|
namespace ZeroTier.Core
|
||||||
{
|
{
|
||||||
public delegate void ZeroTierManagedEventCallback(ZeroTier.Event nodeEvent);
|
public delegate void ZeroTierManagedEventCallback(ZeroTier.Core.Event nodeEvent);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZeroTier Node - Virtual network subsystem
|
/// ZeroTier Node - Virtual network subsystem
|
||||||
@@ -45,11 +47,11 @@ namespace ZeroTier
|
|||||||
zts_callback_msg msg =
|
zts_callback_msg msg =
|
||||||
(zts_callback_msg)Marshal.PtrToStructure(msgPtr, typeof(zts_callback_msg));
|
(zts_callback_msg)Marshal.PtrToStructure(msgPtr, typeof(zts_callback_msg));
|
||||||
|
|
||||||
ZeroTier.Event newEvent = null;
|
ZeroTier.Core.Event newEvent = null;
|
||||||
|
|
||||||
// Node events
|
// Node events
|
||||||
if (msg.eventCode == Constants.EVENT_NODE_UP) {
|
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) {
|
if (msg.eventCode == Constants.EVENT_NODE_ONLINE) {
|
||||||
_isOnline = true;
|
_isOnline = true;
|
||||||
@@ -57,135 +59,135 @@ namespace ZeroTier
|
|||||||
zts_node_details details =
|
zts_node_details details =
|
||||||
(zts_node_details)Marshal.PtrToStructure(msg.node, typeof(zts_node_details));
|
(zts_node_details)Marshal.PtrToStructure(msg.node, typeof(zts_node_details));
|
||||||
_nodeId = details.address;
|
_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) {
|
if (msg.eventCode == Constants.EVENT_NODE_OFFLINE) {
|
||||||
_isOnline = false;
|
_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) {
|
if (msg.eventCode == Constants.EVENT_NODE_NORMAL_TERMINATION) {
|
||||||
_isOnline = false;
|
_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) {
|
if (msg.eventCode == Constants.EVENT_NODE_DOWN) {
|
||||||
_isOnline = false;
|
_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) {
|
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;
|
_isOnline = false;
|
||||||
}
|
}
|
||||||
if (msg.eventCode == Constants.EVENT_NODE_UNRECOVERABLE_ERROR) {
|
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;
|
_isOnline = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Network events
|
// Network events
|
||||||
if (msg.eventCode == Constants.EVENT_NETWORK_NOT_FOUND) {
|
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) {
|
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) {
|
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) {
|
if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP4) {
|
||||||
_joinedAtLeastOneNetwork = true;
|
_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) {
|
if (msg.eventCode == Constants.EVENT_NETWORK_READY_IP6) {
|
||||||
_joinedAtLeastOneNetwork = true;
|
_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) {
|
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) {
|
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) {
|
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) {
|
if (msg.eventCode == Constants.EVENT_NETWORK_OK) {
|
||||||
zts_network_details unmanagedDetails =
|
zts_network_details unmanagedDetails =
|
||||||
(zts_network_details)Marshal.PtrToStructure(msg.network, typeof(zts_network_details));
|
(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 = new NetworkDetails();
|
||||||
newEvent.networkDetails.networkId = unmanagedDetails.nwid;
|
newEvent.networkDetails.networkId = unmanagedDetails.nwid;
|
||||||
}
|
}
|
||||||
if (msg.eventCode == Constants.EVENT_NETWORK_ACCESS_DENIED) {
|
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) {
|
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) {
|
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
|
// Stack events
|
||||||
if (msg.eventCode == Constants.EVENT_STACK_UP) {
|
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) {
|
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
|
// Address events
|
||||||
if (msg.eventCode == Constants.EVENT_ADDR_ADDED_IP4) {
|
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) {
|
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) {
|
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) {
|
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
|
// peer events
|
||||||
if (msg.eventCode == Constants.EVENT_PEER_DIRECT) {
|
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) {
|
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) {
|
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) {
|
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
|
// Route events
|
||||||
if (msg.eventCode == Constants.EVENT_ROUTE_ADDED) {
|
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) {
|
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
|
// Netif events
|
||||||
if (msg.eventCode == Constants.EVENT_NETIF_UP) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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)
|
// Pass the converted Event to the managed callback (visible to user)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
using System; // For ObjectDisposedException
|
using System; // For ObjectDisposedException
|
||||||
using System.Net; // For IPEndPoint
|
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 System.Runtime.InteropServices;
|
||||||
|
|
||||||
using ZeroTier;
|
using ZeroTier;
|
||||||
@@ -21,7 +21,7 @@ using ZeroTier;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZeroTier SDK
|
/// ZeroTier SDK
|
||||||
/// </summary>
|
/// </summary>
|
||||||
namespace ZeroTier
|
namespace ZeroTier.Sockets
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ZeroTier Socket - An lwIP socket mediated over a ZeroTier virtual link
|
/// ZeroTier Socket - An lwIP socket mediated over a ZeroTier virtual link
|
||||||
@@ -45,6 +45,8 @@ namespace ZeroTier
|
|||||||
bool _isClosed;
|
bool _isClosed;
|
||||||
bool _isListening;
|
bool _isListening;
|
||||||
bool _isBlocking;
|
bool _isBlocking;
|
||||||
|
bool _isBound;
|
||||||
|
bool _isConnected;
|
||||||
|
|
||||||
AddressFamily _socketFamily;
|
AddressFamily _socketFamily;
|
||||||
SocketType _socketType;
|
SocketType _socketType;
|
||||||
@@ -101,7 +103,7 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
if ((_fd = zts_socket(family, type, protocol)) < 0)
|
if ((_fd = zts_socket(family, type, protocol)) < 0)
|
||||||
{
|
{
|
||||||
throw new ZeroTier.SocketException((int)_fd);
|
throw new ZeroTier.Sockets.SocketException((int)_fd);
|
||||||
}
|
}
|
||||||
_socketFamily = addressFamily;
|
_socketFamily = addressFamily;
|
||||||
_socketType = socketType;
|
_socketType = socketType;
|
||||||
@@ -132,13 +134,14 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
if (_fd < 0) {
|
if (_fd < 0) {
|
||||||
// Invalid file descriptor
|
// Invalid file descriptor
|
||||||
throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
|
throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
|
||||||
}
|
}
|
||||||
if (remoteEndPoint == null) {
|
if (remoteEndPoint == null) {
|
||||||
throw new ArgumentNullException("remoteEndPoint");
|
throw new ArgumentNullException("remoteEndPoint");
|
||||||
}
|
}
|
||||||
int err = Constants.ERR_OK;
|
int err = Constants.ERR_OK;
|
||||||
int addrlen = 0;
|
int addrlen = 0;
|
||||||
|
IntPtr remoteAddrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr)));
|
||||||
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
|
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
|
||||||
{
|
{
|
||||||
zts_sockaddr_in sa = new zts_sockaddr_in();
|
zts_sockaddr_in sa = new zts_sockaddr_in();
|
||||||
@@ -159,10 +162,9 @@ namespace ZeroTier
|
|||||||
sa.sin_addr = remoteEndPoint.Address.GetAddressBytes();
|
sa.sin_addr = remoteEndPoint.Address.GetAddressBytes();
|
||||||
sa.sin_len = (byte)addrlen; // lwIP-specific
|
sa.sin_len = (byte)addrlen; // lwIP-specific
|
||||||
|
|
||||||
IntPtr ptr1 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr)));
|
Marshal.StructureToPtr(sa, remoteAddrPtr, false);
|
||||||
Marshal.StructureToPtr(sa, ptr1, false);
|
//zts_sockaddr sAddr = (zts_sockaddr)Marshal.PtrToStructure(remoteAddrPtr, typeof(zts_sockaddr));
|
||||||
//zts_sockaddr sAddr = (zts_sockaddr)Marshal.PtrToStructure(ptr1, typeof(zts_sockaddr));
|
err = zts_connect(_fd, remoteAddrPtr, (byte)addrlen);
|
||||||
err = zts_connect(_fd, ptr1, (byte)addrlen);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
|
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
@@ -179,9 +181,11 @@ namespace ZeroTier
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (err < 0) {
|
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;
|
_remoteEndPoint = remoteEndPoint;
|
||||||
|
_isConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind(IPEndPoint localEndPoint)
|
public void Bind(IPEndPoint localEndPoint)
|
||||||
@@ -191,13 +195,14 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
if (_fd < 0) {
|
if (_fd < 0) {
|
||||||
// Invalid file descriptor
|
// Invalid file descriptor
|
||||||
throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
|
throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
|
||||||
}
|
}
|
||||||
if (localEndPoint == null) {
|
if (localEndPoint == null) {
|
||||||
throw new ArgumentNullException("localEndPoint");
|
throw new ArgumentNullException("localEndPoint");
|
||||||
}
|
}
|
||||||
int err = Constants.ERR_OK;
|
int err = Constants.ERR_OK;
|
||||||
int addrlen = 0;
|
int addrlen = 0;
|
||||||
|
IntPtr localAddrPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr)));
|
||||||
if (localEndPoint.AddressFamily == AddressFamily.InterNetwork)
|
if (localEndPoint.AddressFamily == AddressFamily.InterNetwork)
|
||||||
{
|
{
|
||||||
zts_sockaddr_in sa = new zts_sockaddr_in();
|
zts_sockaddr_in sa = new zts_sockaddr_in();
|
||||||
@@ -218,9 +223,8 @@ namespace ZeroTier
|
|||||||
sa.sin_addr = localEndPoint.Address.GetAddressBytes();
|
sa.sin_addr = localEndPoint.Address.GetAddressBytes();
|
||||||
sa.sin_len = (byte)addrlen; // lwIP-specific
|
sa.sin_len = (byte)addrlen; // lwIP-specific
|
||||||
|
|
||||||
IntPtr ptr1 = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_sockaddr)));
|
Marshal.StructureToPtr(sa, localAddrPtr, false);
|
||||||
Marshal.StructureToPtr(sa, ptr1, false);
|
err = zts_bind(_fd, localAddrPtr, (byte)addrlen);
|
||||||
err = zts_bind(_fd, ptr1, (byte)addrlen);
|
|
||||||
}
|
}
|
||||||
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
|
if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
@@ -236,9 +240,11 @@ namespace ZeroTier
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
throw new ZeroTier.SocketException((int)err);
|
throw new ZeroTier.Sockets.SocketException((int)err);
|
||||||
}
|
}
|
||||||
|
Marshal.FreeHGlobal(localAddrPtr);
|
||||||
_localEndPoint = localEndPoint;
|
_localEndPoint = localEndPoint;
|
||||||
|
_isBound = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Listen(int backlog)
|
public void Listen(int backlog)
|
||||||
@@ -248,12 +254,12 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
if (_fd < 0) {
|
if (_fd < 0) {
|
||||||
// Invalid file descriptor
|
// 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;
|
int err = Constants.ERR_OK;
|
||||||
if ((err = zts_listen(_fd, backlog)) < 0) {
|
if ((err = zts_listen(_fd, backlog)) < 0) {
|
||||||
// Invalid backlog value perhaps?
|
// Invalid backlog value perhaps?
|
||||||
throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
|
throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
|
||||||
}
|
}
|
||||||
_isListening = true;
|
_isListening = true;
|
||||||
}
|
}
|
||||||
@@ -265,7 +271,7 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
if (_fd < 0) {
|
if (_fd < 0) {
|
||||||
// Invalid file descriptor
|
// Invalid file descriptor
|
||||||
throw new ZeroTier.SocketException((int)Constants.ERR_SOCKET);
|
throw new ZeroTier.Sockets.SocketException((int)Constants.ERR_SOCKET);
|
||||||
}
|
}
|
||||||
if (_isListening == false) {
|
if (_isListening == false) {
|
||||||
throw new InvalidOperationException("Socket is not in a listening state. Call Listen() first");
|
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);
|
int err = zts_accept(_fd, remoteAddrPtr, addrlenPtr);
|
||||||
if (err < 0) {
|
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));
|
in4 = (zts_sockaddr_in)Marshal.PtrToStructure(remoteAddrPtr, typeof(zts_sockaddr_in));
|
||||||
// Convert sockaddr contents to IPEndPoint
|
// Convert sockaddr contents to IPEndPoint
|
||||||
@@ -290,6 +296,7 @@ namespace ZeroTier
|
|||||||
// Create new socket by providing file descriptor returned from zts_accept call.
|
// Create new socket by providing file descriptor returned from zts_accept call.
|
||||||
Socket clientSocket = new Socket(
|
Socket clientSocket = new Socket(
|
||||||
err, _socketFamily, _socketType, _socketProtocol, _localEndPoint, clientEndPoint);
|
err, _socketFamily, _socketType, _socketProtocol, _localEndPoint, clientEndPoint);
|
||||||
|
Marshal.FreeHGlobal(remoteAddrPtr);
|
||||||
return clientSocket;
|
return clientSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,20 +330,6 @@ namespace ZeroTier
|
|||||||
_isClosed = true;
|
_isClosed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EndPoint RemoteEndPoint
|
|
||||||
{
|
|
||||||
get {
|
|
||||||
return _remoteEndPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EndPoint LocalEndPoint
|
|
||||||
{
|
|
||||||
get {
|
|
||||||
return _localEndPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Blocking
|
public bool Blocking
|
||||||
{
|
{
|
||||||
get {
|
get {
|
||||||
@@ -348,18 +341,16 @@ namespace ZeroTier
|
|||||||
}
|
}
|
||||||
int opts = 0;
|
int opts = 0;
|
||||||
if ((opts = zts_fcntl(_fd, (int)(ZeroTier.Constants.F_GETFL), 0)) < 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
|
if (value) { // Blocking
|
||||||
opts = opts & (~(ZeroTier.Constants.O_NONBLOCK));
|
opts = opts & (~(ZeroTier.Constants.O_NONBLOCK));
|
||||||
}
|
}
|
||||||
if (!value) { // Non-Blocking
|
if (!value) { // Non-Blocking
|
||||||
opts = opts | (int)(ZeroTier.Constants.O_NONBLOCK);
|
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) {
|
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;
|
_isBlocking = value;
|
||||||
}
|
}
|
||||||
@@ -379,7 +370,8 @@ namespace ZeroTier
|
|||||||
poll_set.events = (short)((byte)ZeroTier.Constants.POLLOUT);
|
poll_set.events = (short)((byte)ZeroTier.Constants.POLLOUT);
|
||||||
}
|
}
|
||||||
if (mode == SelectMode.SelectError) {
|
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)));
|
IntPtr poll_fd_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(zts_pollfd)));
|
||||||
Marshal.StructureToPtr(poll_set, poll_fd_ptr, false);
|
Marshal.StructureToPtr(poll_set, poll_fd_ptr, false);
|
||||||
@@ -387,20 +379,23 @@ namespace ZeroTier
|
|||||||
int timeout_ms = (microSeconds / 1000);
|
int timeout_ms = (microSeconds / 1000);
|
||||||
uint numfds = 1;
|
uint numfds = 1;
|
||||||
if ((result = zts_poll(poll_fd_ptr, numfds, timeout_ms)) < 0) {
|
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));
|
poll_set = (zts_pollfd)Marshal.PtrToStructure(poll_fd_ptr, typeof(zts_pollfd));
|
||||||
if (result == 0) { return false; } // No events
|
if (result != 0) {
|
||||||
if (mode == SelectMode.SelectRead) {
|
if (mode == SelectMode.SelectRead) {
|
||||||
return ((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLIN) != 0;
|
result = Convert.ToInt32(((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLIN) != 0);
|
||||||
}
|
}
|
||||||
if (mode == SelectMode.SelectWrite) {
|
if (mode == SelectMode.SelectWrite) {
|
||||||
return ((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLOUT) != 0;
|
result = Convert.ToInt32(((byte)poll_set.revents & (byte)ZeroTier.Constants.POLLOUT) != 0);
|
||||||
}
|
}
|
||||||
if (mode == SelectMode.SelectError) {
|
if (mode == SelectMode.SelectError) {
|
||||||
return ((poll_set.revents & (byte)ZeroTier.Constants.POLLERR) != 0) || ((poll_set.revents & (byte)ZeroTier.Constants.POLLNVAL) != 0);
|
result = Convert.ToInt32(((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)
|
public Int32 Send(Byte[] buffer)
|
||||||
@@ -409,7 +404,7 @@ namespace ZeroTier
|
|||||||
throw new ObjectDisposedException("Socket has been closed");
|
throw new ObjectDisposedException("Socket has been closed");
|
||||||
}
|
}
|
||||||
if (_fd < 0) {
|
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) {
|
if (buffer == null) {
|
||||||
throw new ArgumentNullException("buffer");
|
throw new ArgumentNullException("buffer");
|
||||||
@@ -425,7 +420,7 @@ namespace ZeroTier
|
|||||||
throw new ObjectDisposedException("Socket has been closed");
|
throw new ObjectDisposedException("Socket has been closed");
|
||||||
}
|
}
|
||||||
if (_fd < 0) {
|
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) {
|
if (buffer == null) {
|
||||||
throw new ArgumentNullException("buffer");
|
throw new ArgumentNullException("buffer");
|
||||||
@@ -435,6 +430,87 @@ namespace ZeroTier
|
|||||||
return zts_recv(_fd, bufferPtr, (uint)Buffer.ByteLength(buffer), (int)flags);
|
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
|
/* Structures and functions used internally to communicate with
|
||||||
lower-level C API defined in include/ZeroTierSockets.h */
|
lower-level C API defined in include/ZeroTierSockets.h */
|
||||||
|
|
||||||
@@ -587,5 +663,12 @@ namespace ZeroTier
|
|||||||
public short events;
|
public short events;
|
||||||
public short revents;
|
public short revents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
struct zts_timeval
|
||||||
|
{
|
||||||
|
public long tv_sec;
|
||||||
|
public long tv_usec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ZeroTier
|
namespace ZeroTier.Sockets
|
||||||
{
|
{
|
||||||
/// <summary>Exception class for ZeroTier service and low-level socket errors</summary>
|
/// <summary>Exception class for ZeroTier service and low-level socket errors</summary>
|
||||||
public class SocketException : Exception
|
public class SocketException : Exception
|
||||||
|
|||||||
@@ -587,7 +587,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_zts_delay_ms(long jarg1) {
|
|||||||
zts_delay_ms(arg1);
|
zts_delay_ms(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_all_stats(void * jarg1) {
|
SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_all_stats(void * jarg1) {
|
||||||
int jresult ;
|
int jresult ;
|
||||||
zts_stats *arg1 = (zts_stats *) 0 ;
|
zts_stats *arg1 = (zts_stats *) 0 ;
|
||||||
@@ -612,7 +612,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_zts_get_protocol_stats(int jarg1, void * jarg2
|
|||||||
jresult = result;
|
jresult = result;
|
||||||
return jresult;
|
return jresult;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
SWIGEXPORT int SWIGSTDCALL CSharp_zts_socket(int jarg1, int jarg2, int jarg3) {
|
SWIGEXPORT int SWIGSTDCALL CSharp_zts_socket(int jarg1, int jarg2, int jarg3) {
|
||||||
int jresult ;
|
int jresult ;
|
||||||
|
|||||||
Reference in New Issue
Block a user