ConnectionManager.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* Copyright (C) 2012-2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace ISCSI.Server
  12. {
  13. internal class ConnectionManager
  14. {
  15. private List<ConnectionState> m_activeConnections = new List<ConnectionState>();
  16. public void AddConnection(ConnectionState connection)
  17. {
  18. lock (m_activeConnections)
  19. {
  20. m_activeConnections.Add(connection);
  21. }
  22. }
  23. public bool RemoveConnection(ConnectionState connection)
  24. {
  25. lock (m_activeConnections)
  26. {
  27. int connectionIndex = GetConnectionStateIndex(connection.Session, connection.ConnectionParameters.CID);
  28. if (connectionIndex >= 0)
  29. {
  30. m_activeConnections.RemoveAt(connectionIndex);
  31. return true;
  32. }
  33. return false;
  34. }
  35. }
  36. public void ReleaseConnection(ConnectionState connection)
  37. {
  38. // Wait for pending I/O to complete.
  39. connection.RunningSCSICommands.WaitUntilZero();
  40. connection.SendQueue.Stop();
  41. SocketUtils.ReleaseSocket(connection.ClientSocket);
  42. if (connection.Session != null)
  43. {
  44. RemoveConnection(connection);
  45. }
  46. }
  47. public ConnectionState FindConnection(ISCSISession session, ushort cid)
  48. {
  49. lock (m_activeConnections)
  50. {
  51. int index = GetConnectionStateIndex(session, cid);
  52. if (index >= 0)
  53. {
  54. return m_activeConnections[index];
  55. }
  56. return null;
  57. }
  58. }
  59. public List<ConnectionState> GetSessionConnections(ISCSISession session)
  60. {
  61. List<ConnectionState> result = new List<ConnectionState>();
  62. lock (m_activeConnections)
  63. {
  64. for (int index = 0; index < m_activeConnections.Count; index++)
  65. {
  66. if (String.Equals(m_activeConnections[index].Session.InitiatorName, session.InitiatorName, StringComparison.OrdinalIgnoreCase) &&
  67. m_activeConnections[index].Session.ISID == session.ISID &&
  68. m_activeConnections[index].Session.TSIH == session.TSIH)
  69. {
  70. result.Add(m_activeConnections[index]);
  71. }
  72. }
  73. }
  74. return result;
  75. }
  76. /// <summary>
  77. /// This method will check for dead peers (initiators).
  78. /// Because TCP broken connections can only be detected by sending data, we send a NOP-In PDU,
  79. /// If the connection is dead, the send failure will trigger the necessary connection termination logic.
  80. /// See: http://blog.stephencleary.com/2009/05/detection-of-half-open-dropped.html
  81. /// </summary>
  82. public void SendKeepAlive()
  83. {
  84. lock (m_activeConnections)
  85. {
  86. foreach (ConnectionState connection in m_activeConnections)
  87. {
  88. connection.SendQueue.Enqueue(ServerResponseHelper.GetKeepAlivePDU());
  89. }
  90. }
  91. }
  92. private int GetConnectionStateIndex(ISCSISession session, ushort cid)
  93. {
  94. for (int index = 0; index < m_activeConnections.Count; index++)
  95. {
  96. if (String.Equals(m_activeConnections[index].Session.InitiatorName, session.InitiatorName, StringComparison.OrdinalIgnoreCase) &&
  97. m_activeConnections[index].Session.ISID == session.ISID &&
  98. m_activeConnections[index].Session.TSIH == session.TSIH &&
  99. m_activeConnections[index].ConnectionParameters.CID == cid)
  100. {
  101. return index;
  102. }
  103. }
  104. return -1;
  105. }
  106. }
  107. }