Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions SharpOSC.Tests/SharpOSC.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
Expand Down
19 changes: 17 additions & 2 deletions SharpOSC.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31727.386
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpOSC", "SharpOSC\SharpOSC.csproj", "{9B922B0B-5595-4E05-8270-F63FAAA6C299}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpOSC.Tests", "SharpOSC.Tests\SharpOSC.Tests.csproj", "{50823D59-3602-4213-9F4B-4E57A11AEE4C}"
Expand All @@ -9,34 +11,47 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|x64.ActiveCfg = Debug|x64
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|x64.Build.0 = Debug|x64
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Debug|x86.ActiveCfg = Debug|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|Any CPU.Build.0 = Release|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|x64.ActiveCfg = Release|x64
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|x64.Build.0 = Release|x64
{9B922B0B-5595-4E05-8270-F63FAAA6C299}.Release|x86.ActiveCfg = Release|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|x64.ActiveCfg = Debug|x64
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|x64.Build.0 = Debug|x64
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Debug|x86.ActiveCfg = Debug|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|Any CPU.Build.0 = Release|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|x64.ActiveCfg = Release|x64
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|x64.Build.0 = Release|x64
{50823D59-3602-4213-9F4B-4E57A11AEE4C}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4C3BF275-D8D1-4122-BA4D-81708999B509}
EndGlobalSection
EndGlobal
19 changes: 19 additions & 0 deletions SharpOSC/SharpOSC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand All @@ -47,6 +65,7 @@
<Compile Include="RGBA.cs" />
<Compile Include="Symbol.cs" />
<Compile Include="Timetag.cs" />
<Compile Include="UDProxy.cs" />
<Compile Include="UDPListener.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Extensions.cs" />
Expand Down
206 changes: 206 additions & 0 deletions SharpOSC/UDProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace SharpOSC
{
public delegate void ProxyOscPacket(OscPacket packet);
public delegate void ProxyBytePacket(byte[] packet);

/// <summary>
/// UDP connection for bidirectional use cases.
/// </summary>
public class UDProxy : IDisposable
{
public int remote_Port { get; private set; }
public int local_Port { get; private set; }

object callbackLock;

UdpClient proxyUdpClient;
IPEndPoint RemoteIpEndPoint;
IPEndPoint RemoteIpRxEndPoint;

ProxyBytePacket BytePacketCallback = null;
ProxyOscPacket OscPacketCallback = null;

Queue<byte[]> queue;
ManualResetEvent ClosingEvent;

public UDProxy(string remote_address, int remote_port, int listening_port)
{
remote_Port = remote_port;
local_Port = listening_port;

queue = new Queue<byte[]>();
ClosingEvent = new ManualResetEvent(false);
callbackLock = new object();

// try to open the port 10 times, else fail
for (int i = 0; i < 10; i++)
{
try
{
proxyUdpClient = new UdpClient(listening_port);
break;
}
catch (Exception)
{
// Failed in ten tries, throw the exception and give up
if (i >= 9)
throw;

Thread.Sleep(5);
}
}

IPAddress[] addresses = Dns.GetHostAddresses(remote_address);

RemoteIpEndPoint = new IPEndPoint(addresses[0], remote_port);
RemoteIpRxEndPoint = new IPEndPoint(addresses[0], 0);

//proxyUdpClient.Connect(RemoteIpEndPoint);

// setup first async event
AsyncCallback callBack = new AsyncCallback(ReceiveCallback);
proxyUdpClient.BeginReceive(callBack, null);
}

public UDProxy(string remote_address, int remote_port, int listening_port, ProxyOscPacket callback) : this(remote_address, remote_port, listening_port)
{
this.OscPacketCallback = callback;
}

public UDProxy(string remote_address, int remote_port, int listening_port, ProxyBytePacket callback) : this(remote_address, remote_port, listening_port)
{
this.BytePacketCallback = callback;
}

void ReceiveCallback(IAsyncResult result)
{
Monitor.Enter(callbackLock);
Byte[] bytes = null;

try
{
bytes = proxyUdpClient.EndReceive(result, ref RemoteIpRxEndPoint);
}
catch (ObjectDisposedException e)
{
// Ignore if disposed. This happens when closing the listener
return;
} catch (SocketException e)
{
// Ignore. This happens when at this moment no remote receiver exists.
return;
}

// Process bytes
if (bytes != null && bytes.Length > 0)
{
if (BytePacketCallback != null)
{
BytePacketCallback(bytes);
}
else if (OscPacketCallback != null)
{
OscPacket packet = null;
try
{
packet = OscPacket.GetPacket(bytes);
}
catch (Exception e)
{
// If there is an error reading the packet, null is sent to the callback
}

OscPacketCallback(packet);
}
else
{
lock (queue)
{
queue.Enqueue(bytes);
}
}
}

if (closing)
ClosingEvent.Set();
else
{
// Setup next async event
AsyncCallback callBack = new AsyncCallback(ReceiveCallback);
proxyUdpClient.BeginReceive(callBack, null);
}
Monitor.Exit(callbackLock);
}

public void Send(byte[] message)
{
proxyUdpClient.Send(message, message.Length, RemoteIpEndPoint);
}

public void Send(OscPacket packet)
{
byte[] data = packet.GetBytes();
Send(data);
}

bool closing = false;
public void Close()
{
lock (callbackLock)
{
ClosingEvent.Reset();
closing = true;
proxyUdpClient.Close();
}
ClosingEvent.WaitOne();

}

public void Dispose()
{
this.Close();
}

public OscPacket Receive()
{
if (closing) throw new Exception("UDPListener has been closed.");

lock (queue)
{
if (queue.Count() > 0)
{
byte[] bytes = queue.Dequeue();
var packet = OscPacket.GetPacket(bytes);
return packet;
}
else
return null;
}
}

public byte[] ReceiveBytes()
{
if (closing) throw new Exception("UDPListener has been closed.");

lock (queue)
{
if (queue.Count() > 0)
{
byte[] bytes = queue.Dequeue();
return bytes;
}
else
return null;
}
}

}
}
10 changes: 4 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ SharpOSC is a small library designed to make interacting with Open Sound Control
Download
--------

If you don't want to build SharpOSC from source you can download compiled versions.

__[Download Binaries Here](https://github.com/ValdemarOrn/SharpOSC/tree/master/Binaries)__
If you don't want to build SharpOSC from source you can download the compiled dll from releases.


Supported Types
Expand Down Expand Up @@ -47,14 +45,14 @@ Supported Types
License
-------

SharpOSC is licensed under the MIT license.
SharpOSC is licensed under the MIT license.

See License.txt

Using The Library
-----------------

To use the library add a reference to SharpOSC.dll in your .NET project. SharpOSC should now be available to use in your code under that namespace "SharpOSC".
To use the library add a reference to SharpOSC.dll in your .NET project. SharpOSC should now be available to use in your code under that namespace "SharpOSC".

Example: Sending a message
--------------------------
Expand Down Expand Up @@ -118,4 +116,4 @@ By giving UDPListener a callback you don't have to periodically check for incomi
Contribute
----------

I would love to get some feedback. Use the Issue tracker on Github to send bug reports and feature requests, or just if you have something to say about the project. If you have code changes that you would like to have integrated into the main repository, send me a pull request or a patch. I will try my best to integrate them and make sure SharpOSC improves and matures.
I would love to get some feedback. Use the Issue tracker on Github to send bug reports and feature requests, or just if you have something to say about the project. If you have code changes that you would like to have integrated into the main repository, send me a pull request or a patch. I will try my best to integrate them and make sure SharpOSC improves and matures.