SocketAcceptor.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System;
  2. using System.Net.Sockets;
  3. using MediaBrowser.Model.Logging;
  4. using MediaBrowser.Model.Net;
  5. namespace Emby.Common.Implementations.Net
  6. {
  7. public class SocketAcceptor
  8. {
  9. private readonly ILogger _logger;
  10. private readonly Socket _originalSocket;
  11. private readonly Func<bool> _isClosed;
  12. private readonly Action<IAcceptSocket> _onAccept;
  13. private readonly bool _isDualMode;
  14. public SocketAcceptor(ILogger logger, Socket originalSocket, Action<IAcceptSocket> onAccept, Func<bool> isClosed, bool isDualMode)
  15. {
  16. if (logger == null)
  17. {
  18. throw new ArgumentNullException("logger");
  19. }
  20. if (originalSocket == null)
  21. {
  22. throw new ArgumentNullException("originalSocket");
  23. }
  24. if (onAccept == null)
  25. {
  26. throw new ArgumentNullException("onAccept");
  27. }
  28. if (isClosed == null)
  29. {
  30. throw new ArgumentNullException("isClosed");
  31. }
  32. _logger = logger;
  33. _originalSocket = originalSocket;
  34. _isClosed = isClosed;
  35. _isDualMode = isDualMode;
  36. _onAccept = onAccept;
  37. }
  38. public void StartAccept()
  39. {
  40. Socket dummy = null;
  41. StartAccept(null, ref dummy);
  42. }
  43. public void StartAccept(SocketAsyncEventArgs acceptEventArg, ref Socket accepted)
  44. {
  45. if (acceptEventArg == null)
  46. {
  47. acceptEventArg = new SocketAsyncEventArgs();
  48. acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
  49. }
  50. else
  51. {
  52. // acceptSocket must be cleared since the context object is being reused
  53. acceptEventArg.AcceptSocket = null;
  54. }
  55. try
  56. {
  57. bool willRaiseEvent = _originalSocket.AcceptAsync(acceptEventArg);
  58. if (!willRaiseEvent)
  59. {
  60. ProcessAccept(acceptEventArg);
  61. }
  62. }
  63. catch (Exception ex)
  64. {
  65. if (accepted != null)
  66. {
  67. try
  68. {
  69. #if NET46
  70. accepted.Close();
  71. #else
  72. accepted.Dispose();
  73. #endif
  74. }
  75. catch
  76. {
  77. }
  78. accepted = null;
  79. }
  80. }
  81. }
  82. // This method is the callback method associated with Socket.AcceptAsync
  83. // operations and is invoked when an accept operation is complete
  84. //
  85. void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
  86. {
  87. ProcessAccept(e);
  88. }
  89. private void ProcessAccept(SocketAsyncEventArgs e)
  90. {
  91. if (_isClosed())
  92. {
  93. return;
  94. }
  95. // http://msdn.microsoft.com/en-us/library/system.net.sockets.acceptSocket.acceptasync%28v=vs.110%29.aspx
  96. // Under certain conditions ConnectionReset can occur
  97. // Need to attept to re-accept
  98. if (e.SocketError == SocketError.ConnectionReset)
  99. {
  100. _logger.Error("SocketError.ConnectionReset reported. Attempting to re-accept.");
  101. Socket dummy = null;
  102. StartAccept(e, ref dummy);
  103. return;
  104. }
  105. var acceptSocket = e.AcceptSocket;
  106. if (acceptSocket != null)
  107. {
  108. //ProcessAccept(acceptSocket);
  109. _onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode));
  110. }
  111. // Accept the next connection request
  112. StartAccept(e, ref acceptSocket);
  113. }
  114. }
  115. }