@@ -18,8 +18,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Providers", "Providers", "{ | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Providers.WS4Net", "src\Discord.Net.Providers.WS4Net\Discord.Net.Providers.WS4Net.csproj", "{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Providers.UdpClient", "src\Discord.Net.Providers.UdpClient\Discord.Net.Providers.UdpClient.csproj", "{ABC9F4B9-2452-4725-B522-754E0A02E282}" | |||
EndProject | |||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}" | |||
EndProject | |||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests", "test\Discord.Net.Tests\Discord.Net.Tests.csproj", "{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}" | |||
@@ -108,18 +106,6 @@ Global | |||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}.Release|x64.Build.0 = Release|Any CPU | |||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}.Release|x86.ActiveCfg = Release|Any CPU | |||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}.Release|x86.Build.0 = Release|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Debug|x64.ActiveCfg = Debug|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Debug|x64.Build.0 = Debug|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Debug|x86.ActiveCfg = Debug|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Debug|x86.Build.0 = Debug|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Release|x64.ActiveCfg = Release|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Release|x64.Build.0 = Release|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Release|x86.ActiveCfg = Release|Any CPU | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282}.Release|x86.Build.0 = Release|Any CPU | |||
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|x64.ActiveCfg = Debug|Any CPU | |||
@@ -154,7 +140,6 @@ Global | |||
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} | |||
{688FD1D8-7F01-4539-B2E9-F473C5D699C7} = {288C363D-A636-4EAE-9AC1-4698B641B26E} | |||
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7} = {B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012} | |||
{ABC9F4B9-2452-4725-B522-754E0A02E282} = {B0657AAE-DCC5-4FBF-8E5D-1FB578CF3012} | |||
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30} = {CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A} | |||
EndGlobalSection | |||
EndGlobal |
@@ -1,12 +0,0 @@ | |||
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="../../Discord.Net.targets" /> | |||
<PropertyGroup> | |||
<AssemblyName>Discord.Net.Providers.UDPClient</AssemblyName> | |||
<RootNamespace>Discord.Providers.UDPClient</RootNamespace> | |||
<Description>An optional UDP client provider for Discord.Net using System.Net.UdpClient</Description> | |||
<TargetFramework>net45</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\Discord.Net.Core\Discord.Net.Core.csproj" /> | |||
</ItemGroup> | |||
</Project> |
@@ -1,131 +0,0 @@ | |||
using Discord.Net.Udp; | |||
using System; | |||
using System.Net; | |||
using System.Threading; | |||
using System.Threading.Tasks; | |||
using UdpSocket = System.Net.Sockets.UdpClient; | |||
namespace Discord.Net.Providers.UDPClient | |||
{ | |||
internal class UDPClient : IUdpSocket, IDisposable | |||
{ | |||
public event Func<byte[], int, int, Task> ReceivedDatagram; | |||
private readonly SemaphoreSlim _lock; | |||
private UdpSocket _udp; | |||
private IPEndPoint _destination; | |||
private CancellationTokenSource _cancelTokenSource; | |||
private CancellationToken _cancelToken, _parentToken; | |||
private Task _task; | |||
private bool _isDisposed; | |||
public ushort Port => (ushort)((_udp?.Client.LocalEndPoint as IPEndPoint)?.Port ?? 0); | |||
public UDPClient() | |||
{ | |||
_lock = new SemaphoreSlim(1, 1); | |||
_cancelTokenSource = new CancellationTokenSource(); | |||
} | |||
private void Dispose(bool disposing) | |||
{ | |||
if (!_isDisposed) | |||
{ | |||
if (disposing) | |||
StopInternalAsync(true).GetAwaiter().GetResult(); | |||
_isDisposed = true; | |||
} | |||
} | |||
public void Dispose() | |||
{ | |||
Dispose(true); | |||
} | |||
public async Task StartAsync() | |||
{ | |||
await _lock.WaitAsync().ConfigureAwait(false); | |||
try | |||
{ | |||
await StartInternalAsync(_cancelToken).ConfigureAwait(false); | |||
} | |||
finally | |||
{ | |||
_lock.Release(); | |||
} | |||
} | |||
public async Task StartInternalAsync(CancellationToken cancelToken) | |||
{ | |||
await StopInternalAsync().ConfigureAwait(false); | |||
_cancelTokenSource = new CancellationTokenSource(); | |||
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token; | |||
_udp = new UdpSocket(); | |||
_task = RunAsync(_cancelToken); | |||
} | |||
public async Task StopAsync() | |||
{ | |||
await _lock.WaitAsync().ConfigureAwait(false); | |||
try | |||
{ | |||
await StopInternalAsync().ConfigureAwait(false); | |||
} | |||
finally | |||
{ | |||
_lock.Release(); | |||
} | |||
} | |||
public async Task StopInternalAsync(bool isDisposing = false) | |||
{ | |||
try { _cancelTokenSource.Cancel(false); } catch { } | |||
if (!isDisposing) | |||
await (_task ?? Task.Delay(0)).ConfigureAwait(false); | |||
if (_udp != null) | |||
{ | |||
try { _udp.Close(); } | |||
catch { } | |||
_udp = null; | |||
} | |||
} | |||
public void SetDestination(string host, int port) | |||
{ | |||
var entry = Dns.GetHostEntryAsync(host).GetAwaiter().GetResult(); | |||
_destination = new IPEndPoint(entry.AddressList[0], port); | |||
} | |||
public void SetCancelToken(CancellationToken cancelToken) | |||
{ | |||
_parentToken = cancelToken; | |||
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token; | |||
} | |||
public async Task SendAsync(byte[] data, int index, int count) | |||
{ | |||
if (index != 0) //Should never happen? | |||
{ | |||
var newData = new byte[count]; | |||
Buffer.BlockCopy(data, index, newData, 0, count); | |||
data = newData; | |||
} | |||
await _udp.SendAsync(data, count, _destination).ConfigureAwait(false); | |||
} | |||
private async Task RunAsync(CancellationToken cancelToken) | |||
{ | |||
var closeTask = Task.Delay(-1, cancelToken); | |||
while (!cancelToken.IsCancellationRequested) | |||
{ | |||
var receiveTask = _udp.ReceiveAsync(); | |||
var task = await Task.WhenAny(closeTask, receiveTask).ConfigureAwait(false); | |||
if (task == closeTask) | |||
break; | |||
var result = receiveTask.Result; | |||
await ReceivedDatagram(result.Buffer, 0, result.Buffer.Length).ConfigureAwait(false); | |||
} | |||
} | |||
} | |||
} |
@@ -1,9 +0,0 @@ | |||
using Discord.Net.Udp; | |||
namespace Discord.Net.Providers.UDPClient | |||
{ | |||
public static class UDPClientProvider | |||
{ | |||
public static readonly UdpSocketProvider Instance = () => new UDPClient(); | |||
} | |||
} |