using System;
using System.Net;
using System.Net.Sockets;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Common.Net
{
///
/// Provides a Udp Server
///
public class UdpServer : IObservable, IDisposable
{
///
/// The _udp client
///
private readonly UdpClient _udpClient;
///
/// The _stream
///
private readonly IObservable _stream;
///
/// Initializes a new instance of the class.
///
/// The end point.
/// endPoint
public UdpServer(IPEndPoint endPoint)
{
if (endPoint == null)
{
throw new ArgumentNullException("endPoint");
}
_udpClient = new UdpClient(endPoint);
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//_udpClient.ExclusiveAddressUse = false;
_stream = CreateObservable();
}
///
/// Creates the observable.
///
/// IObservable{UdpReceiveResult}.
private IObservable CreateObservable()
{
return Observable.Create(obs =>
Observable.FromAsync(() => _udpClient.ReceiveAsync())
.Subscribe(obs))
.Repeat()
.Retry()
.Publish()
.RefCount();
}
///
/// Subscribes the specified observer.
///
/// The observer.
/// IDisposable.
/// observer
public IDisposable Subscribe(IObserver observer)
{
if (observer == null)
{
throw new ArgumentNullException("observer");
}
return _stream.Subscribe(observer);
}
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
_udpClient.Close();
}
}
///
/// Sends the async.
///
/// The data.
/// The end point.
/// Task{System.Int32}.
/// data
public async Task SendAsync(string data, IPEndPoint endPoint)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
if (endPoint == null)
{
throw new ArgumentNullException("endPoint");
}
var bytes = Encoding.UTF8.GetBytes(data);
return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false);
}
///
/// Sends the async.
///
/// The bytes.
/// The end point.
/// Task{System.Int32}.
/// bytes
public async Task SendAsync(byte[] bytes, IPEndPoint endPoint)
{
if (bytes == null)
{
throw new ArgumentNullException("bytes");
}
if (endPoint == null)
{
throw new ArgumentNullException("endPoint");
}
return await _udpClient.SendAsync(bytes, bytes.Length, endPoint).ConfigureAwait(false);
}
}
}