jellyfin-server/Emby.Server.Implementations/Net/SocketAcceptor.cs

128 lines
3.8 KiB
C#
Raw Normal View History

2016-11-08 18:44:23 +00:00
using System;
using System.Net.Sockets;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
namespace Emby.Server.Implementations.Net
2016-11-08 18:44:23 +00:00
{
public class SocketAcceptor
{
private readonly ILogger _logger;
private readonly Socket _originalSocket;
private readonly Func<bool> _isClosed;
2017-03-02 20:50:09 +00:00
private readonly Action<IAcceptSocket> _onAccept;
2016-12-07 20:02:34 +00:00
private readonly bool _isDualMode;
2016-11-08 18:44:23 +00:00
2017-03-02 20:50:09 +00:00
public SocketAcceptor(ILogger logger, Socket originalSocket, Action<IAcceptSocket> onAccept, Func<bool> isClosed, bool isDualMode)
2016-11-08 18:44:23 +00:00
{
2016-11-13 21:04:21 +00:00
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");
}
2016-11-08 18:44:23 +00:00
_logger = logger;
_originalSocket = originalSocket;
_isClosed = isClosed;
2016-12-07 20:02:34 +00:00
_isDualMode = isDualMode;
2016-11-08 18:44:23 +00:00
_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
{
2017-03-02 20:50:09 +00:00
// acceptSocket must be cleared since the context object is being reused
2016-11-08 18:44:23 +00:00
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;
}
2017-03-02 20:50:09 +00:00
// http://msdn.microsoft.com/en-us/library/system.net.sockets.acceptSocket.acceptasync%28v=vs.110%29.aspx
2016-11-08 18:44:23 +00:00
// 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);
2017-03-02 20:50:09 +00:00
_onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode));
2016-11-08 18:44:23 +00:00
}
2016-11-13 21:04:21 +00:00
// Accept the next connection request
StartAccept(e, ref acceptSocket);
2016-11-08 18:44:23 +00:00
}
}
}