Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Udp Sockets to be specified as exclusive #153

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
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
58 changes: 40 additions & 18 deletions Sockets/Sockets.Implementation.NET/UdpSocketClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,46 @@ public class UdpSocketClient : UdpSocketBase, IUdpSocketClient
{
private CancellationTokenSource _messageCanceller;

/// <summary>
/// Default constructor for <code>UdpSocketClient.</code>
/// </summary>
public UdpSocketClient()
{
try
{
_backingUdpClient = new UdpClient
{
EnableBroadcast = true
};
ProtectAgainstICMPUnreachable(_backingUdpClient);
}
catch (PlatformSocketException ex)
{
throw new PclSocketException(ex);
}
}
/// <summary>
/// Default constructor for <code>UdpSocketClient.</code>
/// </summary>
public UdpSocketClient()
{
try
{
_backingUdpClient = new UdpClient
{
EnableBroadcast = true
};
ProtectAgainstICMPUnreachable(_backingUdpClient);
}
catch (PlatformSocketException ex)
{
throw new PclSocketException(ex);
}
}

/// <summary>
/// Constructor for <code>UdpSocketClient.</code>
/// </summary>
/// <param name="exclusive">Should address use be exclusive?</param>
public UdpSocketClient(bool exclusive)
{
try
{
_backingUdpClient = new UdpClient
{
EnableBroadcast = true,
ExclusiveAddressUse = exclusive
};
_backingUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, !exclusive);
ProtectAgainstICMPUnreachable(_backingUdpClient);
}
catch (PlatformSocketException ex)
{
throw new PclSocketException(ex);
}
}

/// <summary>
/// Sets the endpoint at the specified address/port pair as the 'default' target of sent data.
Expand Down
90 changes: 52 additions & 38 deletions Sockets/Sockets.Implementation.NET/UdpSocketMulticastClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,58 @@

namespace Sockets.Plugin
{
/// <summary>
/// Sends and recieves data in a UDP multicast group.
/// Join a UDP multicast address using <code>JoinMulticastGroupAsync</code>, then send data using
/// <code>SendMulticastAsync</code>.
/// </summary>
public class UdpSocketMulticastClient : UdpSocketBase, IUdpSocketMulticastClient
{
private string _multicastAddress;
private int _multicastPort;

private CancellationTokenSource _messageCanceller;
private int _ttl = 1;

/// <summary>
/// Joins the multicast group at the specified endpoint.
/// </summary>
/// <param name="multicastAddress">The address for the multicast group.</param>
/// <param name="port">The port for the multicast group.</param>
/// <param name="multicastOn">The <code>CommsInterface</code> to multicast on. If unspecified, all interfaces will be bound.</param>
/// <returns></returns>
public async Task JoinMulticastGroupAsync(string multicastAddress, int port, ICommsInterface multicastOn = null)
{
if (multicastOn != null && !multicastOn.IsUsable)
throw new InvalidOperationException("Cannot multicast on an unusable interface. Check the IsUsable property before attemping to connect.");

var bindingIp = multicastOn != null ? ((CommsInterface)multicastOn).NativeIpAddress : IPAddress.Any;
var bindingEp = new IPEndPoint(bindingIp, port);

var multicastIp = IPAddress.Parse(multicastAddress);

try
{
_backingUdpClient = new UdpClient(bindingEp)
{
EnableBroadcast = true
};
ProtectAgainstICMPUnreachable(_backingUdpClient);
}
/// <summary>
/// Sends and recieves data in a UDP multicast group.
/// Join a UDP multicast address using <code>JoinMulticastGroupAsync</code>, then send data using
/// <code>SendMulticastAsync</code>.
/// </summary>
public class UdpSocketMulticastClient : UdpSocketBase, IUdpSocketMulticastClient
{
private string _multicastAddress;
private int _multicastPort;

private CancellationTokenSource _messageCanceller;
private int _ttl = 1;

/// <summary>
/// Joins the multicast group at the specified endpoint.
/// </summary>
/// <param name="multicastAddress">The address for the multicast group.</param>
/// <param name="port">The port for the multicast group.</param>
/// <param name="multicastOn">The <code>CommsInterface</code> to multicast on. If unspecified, all interfaces will be bound.</param>
/// <param name="exclusive">Should address use be exclusive?</param>
/// <returns></returns>
public async Task JoinMulticastGroupAsync(string multicastAddress, int port, ICommsInterface multicastOn = null, bool? exclusive = null)
{
if (multicastOn != null && !multicastOn.IsUsable)
throw new InvalidOperationException("Cannot multicast on an unusable interface. Check the IsUsable property before attemping to connect.");

var bindingIp = multicastOn != null ? ((CommsInterface)multicastOn).NativeIpAddress : IPAddress.Any;
var bindingEp = new IPEndPoint(bindingIp, port);

var multicastIp = IPAddress.Parse(multicastAddress);

try
{
if (exclusive == null)
{
_backingUdpClient = new UdpClient(bindingEp)
{
EnableBroadcast = true
};
ProtectAgainstICMPUnreachable(_backingUdpClient);
}
else
{
_backingUdpClient = new UdpClient
{
EnableBroadcast = true,
ExclusiveAddressUse = exclusive.Value
};
_backingUdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, !exclusive.Value);
ProtectAgainstICMPUnreachable(_backingUdpClient);
}
}
catch (PlatformSocketException ex)
{
throw new PclSocketException(ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ public interface IUdpSocketMulticastClient : IDisposable
/// <param name="multicastAddress">The address for the multicast group.</param>
/// <param name="port">The port for the multicast group.</param>
/// <param name="multicastOn">The <code>CommsInterface</code> to multicast on. If unspecified, all interfaces will be bound.</param>
/// <param name="exclusive">Should port use be exclusive?</param>
// <returns></returns>
Task JoinMulticastGroupAsync(string multicastAddress, int port, ICommsInterface multicastOn);
Task JoinMulticastGroupAsync(string multicastAddress, int port, ICommsInterface multicastOn, bool? exclusive = null);

/// <summary>
/// Removes the <code>UdpSocketMulticastClient</code> from a joined multicast group.
Expand Down
9 changes: 9 additions & 0 deletions Sockets/Sockets.Plugin/UdpSocketClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ namespace Sockets.Plugin
/// </summary>
public class UdpSocketClient : UdpSocketBase, IUdpSocketClient
{
/// <summary>
/// Constructor for <code>UdpSocketClient.</code>
/// </summary>
/// <param name="exclusive">Should address use be exclusive?</param>
public UdpSocketClient(bool exclusive)
{
throw new NotImplementedException(PCL.BaitWithoutSwitchMessage);
}

/// <summary>
/// Sets the endpoint at the specified address/port pair as the 'default' target of sent data.
/// After calling <code>ConnectAsync</code>, use <code>SendAsync</code> to send data to the default target.
Expand Down
3 changes: 2 additions & 1 deletion Sockets/Sockets.Plugin/UdpSocketMulticastClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public class UdpSocketMulticastClient : UdpSocketBase, IUdpSocketMulticastClient
/// <param name="multicastAddress">The address for the multicast group.</param>
/// <param name="port">The port for the multicast group.</param>
/// <param name="multicastOn">The <code>CommsInterface</code> to multicast on. If unspecified, all interfaces will be bound.</param>
/// <param name="exclusive">Should address use be exclusive?</param>
/// <returns></returns>
public Task JoinMulticastGroupAsync(string multicastAddress, int port, ICommsInterface multicastOn = null)
public Task JoinMulticastGroupAsync(string multicastAddress, int port, ICommsInterface multicastOn = null, bool? exclusive = null)
{
throw new NotImplementedException(PCL.BaitWithoutSwitchMessage);
}
Expand Down