diff options
Diffstat (limited to 'Emby.Common.Implementations/Net')
| -rw-r--r-- | Emby.Common.Implementations/Net/DisposableManagedObjectBase.cs | 74 | ||||
| -rw-r--r-- | Emby.Common.Implementations/Net/NetAcceptSocket.cs | 154 | ||||
| -rw-r--r-- | Emby.Common.Implementations/Net/SocketAcceptor.cs | 127 | ||||
| -rw-r--r-- | Emby.Common.Implementations/Net/SocketFactory.cs | 297 | ||||
| -rw-r--r-- | Emby.Common.Implementations/Net/UdpSocket.cs | 258 |
5 files changed, 0 insertions, 910 deletions
diff --git a/Emby.Common.Implementations/Net/DisposableManagedObjectBase.cs b/Emby.Common.Implementations/Net/DisposableManagedObjectBase.cs deleted file mode 100644 index 8476cea32..000000000 --- a/Emby.Common.Implementations/Net/DisposableManagedObjectBase.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Emby.Common.Implementations.Net -{ - /// <summary> - /// Correclty implements the <see cref="IDisposable"/> interface and pattern for an object containing only managed resources, and adds a few common niceities not on the interface such as an <see cref="IsDisposed"/> property. - /// </summary> - public abstract class DisposableManagedObjectBase : IDisposable - { - - #region Public Methods - - /// <summary> - /// Override this method and dispose any objects you own the lifetime of if disposing is true; - /// </summary> - /// <param name="disposing">True if managed objects should be disposed, if false, only unmanaged resources should be released.</param> - protected abstract void Dispose(bool disposing); - - /// <summary> - /// Throws and <see cref="System.ObjectDisposedException"/> if the <see cref="IsDisposed"/> property is true. - /// </summary> - /// <seealso cref="IsDisposed"/> - /// <exception cref="System.ObjectDisposedException">Thrown if the <see cref="IsDisposed"/> property is true.</exception> - /// <seealso cref="Dispose()"/> - protected virtual void ThrowIfDisposed() - { - if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().FullName); - } - - #endregion - - #region Public Properties - - /// <summary> - /// Sets or returns a boolean indicating whether or not this instance has been disposed. - /// </summary> - /// <seealso cref="Dispose()"/> - public bool IsDisposed - { - get; - private set; - } - - #endregion - - #region IDisposable Members - - /// <summary> - /// Disposes this object instance and all internally managed resources. - /// </summary> - /// <remarks> - /// <para>Sets the <see cref="IsDisposed"/> property to true. Does not explicitly throw an exception if called multiple times, but makes no promises about behaviour of derived classes.</para> - /// </remarks> - /// <seealso cref="IsDisposed"/> - public void Dispose() - { - try - { - IsDisposed = true; - - Dispose(true); - } - finally - { - GC.SuppressFinalize(this); - } - } - - #endregion - } -} diff --git a/Emby.Common.Implementations/Net/NetAcceptSocket.cs b/Emby.Common.Implementations/Net/NetAcceptSocket.cs deleted file mode 100644 index 5e831ac7a..000000000 --- a/Emby.Common.Implementations/Net/NetAcceptSocket.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using Emby.Common.Implementations.Networking; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Logging; - -namespace Emby.Common.Implementations.Net -{ - public class NetAcceptSocket : IAcceptSocket - { - public Socket Socket { get; private set; } - private readonly ILogger _logger; - - public bool DualMode { get; private set; } - - public NetAcceptSocket(Socket socket, ILogger logger, bool isDualMode) - { - if (socket == null) - { - throw new ArgumentNullException("socket"); - } - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - Socket = socket; - _logger = logger; - DualMode = isDualMode; - } - - public IpEndPointInfo LocalEndPoint - { - get - { - return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint); - } - } - - public IpEndPointInfo RemoteEndPoint - { - get - { - return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.RemoteEndPoint); - } - } - - public void Connect(IpEndPointInfo endPoint) - { - var nativeEndpoint = NetworkManager.ToIPEndPoint(endPoint); - - Socket.Connect(nativeEndpoint); - } - - public void Close() - { -#if NET46 - Socket.Close(); -#else - Socket.Dispose(); -#endif - } - - public void Shutdown(bool both) - { - if (both) - { - Socket.Shutdown(SocketShutdown.Both); - } - else - { - // Change interface if ever needed - throw new NotImplementedException(); - } - } - - public void Listen(int backlog) - { - Socket.Listen(backlog); - } - - public void Bind(IpEndPointInfo endpoint) - { - var nativeEndpoint = NetworkManager.ToIPEndPoint(endpoint); - - Socket.Bind(nativeEndpoint); - } - - private SocketAcceptor _acceptor; - public void StartAccept(Action<IAcceptSocket> onAccept, Func<bool> isClosed) - { - _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode); - - _acceptor.StartAccept(); - } - - public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken) - { - var options = TransmitFileOptions.UseDefaultWorkerThread; - - var completionSource = new TaskCompletionSource<bool>(); - - var result = Socket.BeginSendFile(path, preBuffer, postBuffer, options, new AsyncCallback(FileSendCallback), new Tuple<Socket, string, TaskCompletionSource<bool>>(Socket, path, completionSource)); - - return completionSource.Task; - } - - public IAsyncResult BeginSendFile(string path, byte[] preBuffer, byte[] postBuffer, AsyncCallback callback, object state) - { - var options = TransmitFileOptions.UseDefaultWorkerThread; - - return Socket.BeginSendFile(path, preBuffer, postBuffer, options, new AsyncCallback(FileSendCallback), state); - } - - public void EndSendFile(IAsyncResult result) - { - Socket.EndSendFile(result); - } - - private void FileSendCallback(IAsyncResult ar) - { - // Retrieve the socket from the state object. - Tuple<Socket, string, TaskCompletionSource<bool>> data = (Tuple<Socket, string, TaskCompletionSource<bool>>)ar.AsyncState; - - var client = data.Item1; - var path = data.Item2; - var taskCompletion = data.Item3; - - // Complete sending the data to the remote device. - try - { - client.EndSendFile(ar); - taskCompletion.TrySetResult(true); - } - catch (SocketException ex) - { - _logger.Info("Socket.SendFile failed for {0}. error code {1}", path, ex.SocketErrorCode); - taskCompletion.TrySetException(ex); - } - catch (Exception ex) - { - taskCompletion.TrySetException(ex); - } - } - - public void Dispose() - { - Socket.Dispose(); - } - } -} diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs deleted file mode 100644 index 11a8e5381..000000000 --- a/Emby.Common.Implementations/Net/SocketAcceptor.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Net.Sockets; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; - -namespace Emby.Common.Implementations.Net -{ - public class SocketAcceptor - { - private readonly ILogger _logger; - private readonly Socket _originalSocket; - private readonly Func<bool> _isClosed; - private readonly Action<IAcceptSocket> _onAccept; - private readonly bool _isDualMode; - - public SocketAcceptor(ILogger logger, Socket originalSocket, Action<IAcceptSocket> onAccept, Func<bool> isClosed, bool isDualMode) - { - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - if (originalSocket == null) - { - throw new ArgumentNullException("originalSocket"); - } - if (onAccept == null) - { - throw new ArgumentNullException("onAccept"); - } - if (isClosed == null) - { - throw new ArgumentNullException("isClosed"); - } - - _logger = logger; - _originalSocket = originalSocket; - _isClosed = isClosed; - _isDualMode = isDualMode; - _onAccept = onAccept; - } - - public void StartAccept() - { - Socket dummy = null; - StartAccept(null, ref dummy); - } - - public void StartAccept(SocketAsyncEventArgs acceptEventArg, ref Socket accepted) - { - if (acceptEventArg == null) - { - acceptEventArg = new SocketAsyncEventArgs(); - acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed); - } - else - { - // acceptSocket must be cleared since the context object is being reused - acceptEventArg.AcceptSocket = null; - } - - try - { - bool willRaiseEvent = _originalSocket.AcceptAsync(acceptEventArg); - - if (!willRaiseEvent) - { - ProcessAccept(acceptEventArg); - } - } - catch (Exception ex) - { - if (accepted != null) - { - try - { -#if NET46 - accepted.Close(); -#else - accepted.Dispose(); -#endif - } - catch - { - } - accepted = null; - } - } - } - - // This method is the callback method associated with Socket.AcceptAsync - // operations and is invoked when an accept operation is complete - // - void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) - { - ProcessAccept(e); - } - - private void ProcessAccept(SocketAsyncEventArgs e) - { - if (_isClosed()) - { - return; - } - - // http://msdn.microsoft.com/en-us/library/system.net.sockets.acceptSocket.acceptasync%28v=vs.110%29.aspx - // Under certain conditions ConnectionReset can occur - // Need to attept to re-accept - if (e.SocketError == SocketError.ConnectionReset) - { - _logger.Error("SocketError.ConnectionReset reported. Attempting to re-accept."); - Socket dummy = null; - StartAccept(e, ref dummy); - return; - } - - var acceptSocket = e.AcceptSocket; - if (acceptSocket != null) - { - //ProcessAccept(acceptSocket); - _onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode)); - } - - // Accept the next connection request - StartAccept(e, ref acceptSocket); - } - } -} diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs deleted file mode 100644 index 0a1232a40..000000000 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ /dev/null @@ -1,297 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; -using Emby.Common.Implementations.Networking; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; - -namespace Emby.Common.Implementations.Net -{ - public class SocketFactory : ISocketFactory - { - // THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS - // Be careful to check any changes compile and work for all platform projects it is shared in. - - // Not entirely happy with this. Would have liked to have done something more generic/reusable, - // but that wasn't really the point so kept to YAGNI principal for now, even if the - // interfaces are a bit ugly, specific and make assumptions. - - private readonly ILogger _logger; - - public SocketFactory(ILogger logger) - { - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - _logger = logger; - } - - public IAcceptSocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) - { - try - { - var addressFamily = family == IpAddressFamily.InterNetwork - ? AddressFamily.InterNetwork - : AddressFamily.InterNetworkV6; - - var socket = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); - - if (dualMode) - { - socket.DualMode = true; - } - - return new NetAcceptSocket(socket, _logger, dualMode); - } - catch (SocketException ex) - { - throw new SocketCreateException(ex.SocketErrorCode.ToString(), ex); - } - catch (ArgumentException ex) - { - if (dualMode) - { - // Mono for BSD incorrectly throws ArgumentException instead of SocketException - throw new SocketCreateException("AddressFamilyNotSupported", ex); - } - else - { - throw; - } - } - } - - public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort) - { - if (remotePort < 0) throw new ArgumentException("remotePort cannot be less than zero.", "remotePort"); - - var addressFamily = remoteAddress.AddressFamily == IpAddressFamily.InterNetwork - ? AddressFamily.InterNetwork - : AddressFamily.InterNetworkV6; - - var retVal = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); - - try - { - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - } - catch (SocketException) - { - // This is not supported on all operating systems (qnap) - } - - try - { - return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); - } - catch - { - if (retVal != null) - retVal.Dispose(); - - throw; - } - } - - /// <summary> - /// Creates a new UDP acceptSocket and binds it to the specified local port. - /// </summary> - /// <param name="localPort">An integer specifying the local port to bind the acceptSocket to.</param> - public ISocket CreateUdpSocket(int localPort) - { - if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - - var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); - try - { - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - return new UdpSocket(retVal, localPort, IPAddress.Any); - } - catch - { - if (retVal != null) - retVal.Dispose(); - - throw; - } - } - - public ISocket CreateUdpBroadcastSocket(int localPort) - { - if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - - var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); - try - { - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); - - return new UdpSocket(retVal, localPort, IPAddress.Any); - } - catch - { - if (retVal != null) - retVal.Dispose(); - - throw; - } - } - - /// <summary> - /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. - /// </summary> - /// <returns>An implementation of the <see cref="ISocket"/> interface used by RSSDP components to perform acceptSocket operations.</returns> - public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) - { - if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - - var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); - try - { - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); - - var localIp = NetworkManager.ToIPAddress(localIpAddress); - - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp)); - return new UdpSocket(retVal, localPort, localIp); - } - catch - { - if (retVal != null) - retVal.Dispose(); - - throw; - } - } - - /// <summary> - /// Creates a new UDP acceptSocket that is a member of the specified multicast IP address, and binds it to the specified local port. - /// </summary> - /// <param name="ipAddress">The multicast IP address to make the acceptSocket a member of.</param> - /// <param name="multicastTimeToLive">The multicast time to live value for the acceptSocket.</param> - /// <param name="localPort">The number of the local port to bind to.</param> - /// <returns></returns> - public ISocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) - { - if (ipAddress == null) throw new ArgumentNullException("ipAddress"); - if (ipAddress.Length == 0) throw new ArgumentException("ipAddress cannot be an empty string.", "ipAddress"); - if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive"); - if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); - - var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); - - try - { - retVal.ExclusiveAddressUse = false; - //retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive); - - var localIp = IPAddress.Any; - - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), localIp)); - retVal.MulticastLoopback = true; - - return new UdpSocket(retVal, localPort, localIp); - } - catch - { - if (retVal != null) - retVal.Dispose(); - - throw; - } - } - - public Stream CreateNetworkStream(ISocket socket, bool ownsSocket) - { - var netSocket = (UdpSocket)socket; - - return new SocketStream(netSocket.Socket, ownsSocket); - } - } - - public class SocketStream : Stream - { - private readonly Socket _socket; - - public SocketStream(Socket socket, bool ownsSocket) - { - _socket = socket; - } - - public override void Flush() - { - } - - public override bool CanRead - { - get { return true; } - } - public override bool CanSeek - { - get { return false; } - } - public override bool CanWrite - { - get { return true; } - } - public override long Length - { - get { throw new NotImplementedException(); } - } - public override long Position - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - public override void Write(byte[] buffer, int offset, int count) - { - _socket.Send(buffer, offset, count, SocketFlags.None); - } - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) - { - return _socket.BeginSend(buffer, offset, count, SocketFlags.None, callback, state); - } - - public override void EndWrite(IAsyncResult asyncResult) - { - _socket.EndSend(asyncResult); - } - - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotImplementedException(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - return _socket.Receive(buffer, offset, count, SocketFlags.None); - } - - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) - { - return _socket.BeginReceive(buffer, offset, count, SocketFlags.None, callback, state); - } - - public override int EndRead(IAsyncResult asyncResult) - { - return _socket.EndReceive(asyncResult); - } - } - -} diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs deleted file mode 100644 index 542d16d24..000000000 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Security; -using System.Threading; -using System.Threading.Tasks; -using Emby.Common.Implementations.Networking; -using MediaBrowser.Model.Net; - -namespace Emby.Common.Implementations.Net -{ - // THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS - // Be careful to check any changes compile and work for all platform projects it is shared in. - - public sealed class UdpSocket : DisposableManagedObjectBase, ISocket - { - private Socket _Socket; - private int _LocalPort; - - public Socket Socket - { - get { return _Socket; } - } - - private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs() - { - SocketFlags = SocketFlags.None - }; - - private readonly SocketAsyncEventArgs _sendSocketAsyncEventArgs = new SocketAsyncEventArgs() - { - SocketFlags = SocketFlags.None - }; - - private TaskCompletionSource<SocketReceiveResult> _currentReceiveTaskCompletionSource; - private TaskCompletionSource<int> _currentSendTaskCompletionSource; - - public UdpSocket(Socket socket, int localPort, IPAddress ip) - { - if (socket == null) throw new ArgumentNullException("socket"); - - _Socket = socket; - _LocalPort = localPort; - LocalIPAddress = NetworkManager.ToIpAddressInfo(ip); - - _Socket.Bind(new IPEndPoint(ip, _LocalPort)); - - InitReceiveSocketAsyncEventArgs(); - } - - private void InitReceiveSocketAsyncEventArgs() - { - var receiveBuffer = new byte[8192]; - _receiveSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length); - _receiveSocketAsyncEventArgs.Completed += _receiveSocketAsyncEventArgs_Completed; - - var sendBuffer = new byte[8192]; - _sendSocketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length); - _sendSocketAsyncEventArgs.Completed += _sendSocketAsyncEventArgs_Completed; - } - - private void _receiveSocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e) - { - var tcs = _currentReceiveTaskCompletionSource; - if (tcs != null) - { - _currentReceiveTaskCompletionSource = null; - - if (e.SocketError == SocketError.Success) - { - tcs.TrySetResult(new SocketReceiveResult - { - Buffer = e.Buffer, - ReceivedBytes = e.BytesTransferred, - RemoteEndPoint = ToIpEndPointInfo(e.RemoteEndPoint as IPEndPoint), - LocalIPAddress = LocalIPAddress - }); - } - else - { - tcs.TrySetException(new Exception("SocketError: " + e.SocketError)); - } - } - } - - private void _sendSocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e) - { - var tcs = _currentSendTaskCompletionSource; - if (tcs != null) - { - _currentSendTaskCompletionSource = null; - - if (e.SocketError == SocketError.Success) - { - tcs.TrySetResult(e.BytesTransferred); - } - else - { - tcs.TrySetException(new Exception("SocketError: " + e.SocketError)); - } - } - } - - public UdpSocket(Socket socket, IpEndPointInfo endPoint) - { - if (socket == null) throw new ArgumentNullException("socket"); - - _Socket = socket; - _Socket.Connect(NetworkManager.ToIPEndPoint(endPoint)); - - InitReceiveSocketAsyncEventArgs(); - } - - public IpAddressInfo LocalIPAddress - { - get; - private set; - } - - public IAsyncResult BeginReceive(byte[] buffer, int offset, int count, AsyncCallback callback) - { - EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0); - - return _Socket.BeginReceiveFrom(buffer, offset, count, SocketFlags.None, ref receivedFromEndPoint, callback, buffer); - } - - public int Receive(byte[] buffer, int offset, int count) - { - return _Socket.Receive(buffer, 0, buffer.Length, SocketFlags.None); - } - - public SocketReceiveResult EndReceive(IAsyncResult result) - { - IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); - EndPoint remoteEndPoint = (EndPoint)sender; - - var receivedBytes = _Socket.EndReceiveFrom(result, ref remoteEndPoint); - - var buffer = (byte[]) result.AsyncState; - - return new SocketReceiveResult - { - ReceivedBytes = receivedBytes, - RemoteEndPoint = ToIpEndPointInfo((IPEndPoint)remoteEndPoint), - Buffer = buffer, - LocalIPAddress = LocalIPAddress - }; - } - - public Task<SocketReceiveResult> ReceiveAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - var taskCompletion = new TaskCompletionSource<SocketReceiveResult>(); - - Action<IAsyncResult> callback = callbackResult => - { - try - { - taskCompletion.TrySetResult(EndReceive(callbackResult)); - } - catch (Exception ex) - { - taskCompletion.TrySetException(ex); - } - }; - - var result = BeginReceive(buffer, offset, count, new AsyncCallback(callback)); - - if (result.CompletedSynchronously) - { - callback(result); - } - - cancellationToken.Register(() => taskCompletion.TrySetCanceled()); - - return taskCompletion.Task; - } - - public Task<SocketReceiveResult> ReceiveAsync(CancellationToken cancellationToken) - { - var buffer = new byte[8192]; - - return ReceiveAsync(buffer, 0, buffer.Length, cancellationToken); - } - - public Task SendToAsync(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken) - { - var taskCompletion = new TaskCompletionSource<int>(); - - Action<IAsyncResult> callback = callbackResult => - { - try - { - taskCompletion.TrySetResult(EndSendTo(callbackResult)); - } - catch (Exception ex) - { - taskCompletion.TrySetException(ex); - } - }; - - var result = BeginSendTo(buffer, offset, size, endPoint, new AsyncCallback(callback), null); - - if (result.CompletedSynchronously) - { - callback(result); - } - - cancellationToken.Register(() => taskCompletion.TrySetCanceled()); - - return taskCompletion.Task; - } - - public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, AsyncCallback callback, object state) - { - var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint); - - return _Socket.BeginSendTo(buffer, offset, size, SocketFlags.None, ipEndPoint, callback, state); - } - - public int EndSendTo(IAsyncResult result) - { - return _Socket.EndSendTo(result); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - var socket = _Socket; - if (socket != null) - socket.Dispose(); - - var tcs = _currentReceiveTaskCompletionSource; - if (tcs != null) - { - tcs.TrySetCanceled(); - } - var sendTcs = _currentSendTaskCompletionSource; - if (sendTcs != null) - { - sendTcs.TrySetCanceled(); - } - } - } - - private static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint) - { - if (endpoint == null) - { - return null; - } - - return NetworkManager.ToIpEndPointInfo(endpoint); - } - } -} |
