Jelajahi Sumber

iSCSI Server: Improved TSIH related logic

Tal Aloni 8 tahun lalu
induk
melakukan
7d5e8f316f

+ 14 - 11
ISCSI/ISCSI.Server/ISCSIServer.Login.cs

@@ -31,19 +31,11 @@ namespace ISCSI.Server
             response.VersionMax = request.VersionMax;
             response.VersionActive = request.VersionMin;
             response.ISID = request.ISID;
-
-            response.Status = LoginResponseStatusName.Success;
-
+            // TSIH: With the exception of the Login Final-Response in a new session, this field should
+            // be set to the TSIH provided by the initiator in the Login Request.
+            response.TSIH = request.TSIH;
             response.InitiatorTaskTag = request.InitiatorTaskTag;
 
-            if (request.TSIH == 0)
-            {
-                // For a new session, the request TSIH is zero,
-                // As part of the response, the target generates a TSIH.
-                session.TSIH = GetNextTSIH();
-            }
-            response.TSIH = session.TSIH;
-
             if (request.Transit && request.Continue)
             {
                 response.Status = LoginResponseStatusName.InitiatorError;
@@ -55,6 +47,17 @@ namespace ISCSI.Server
                 return response;
             }
 
+            if (request.TSIH == 0)
+            {
+                // For a new session, the request TSIH is zero,
+                // As part of the response, the target generates a TSIH.
+                session.TSIH = m_sessionManager.GetNextTSIH();
+                session.ISID = request.ISID;
+            }
+            response.TSIH = session.TSIH;
+
+            response.Status = LoginResponseStatusName.Success;
+
             // RFC 3720:  The login process proceeds in two stages - the security negotiation
             // stage and the operational parameter negotiation stage.  Both stages are optional
             // but at least one of them has to be present.

+ 0 - 1
ISCSI/ISCSI.Server/ISCSIServer.PDUProcessor.cs

@@ -77,7 +77,6 @@ namespace ISCSI.Server
                     LoginResponsePDU response = GetLoginResponsePDU(request, state.Session, state.ConnectionParameters);
                     if (state.Session.IsFullFeaturePhase)
                     {
-                        state.Session.ISID = request.ISID;
                         state.ConnectionParameters.CID = request.CID;
                         m_connectionManager.AddConnection(state);
                     }

+ 1 - 16
ISCSI/ISCSI.Server/ISCSIServer.cs

@@ -24,10 +24,10 @@ namespace ISCSI.Server
 
         private IPEndPoint m_listenerEP;
         private List<ISCSITarget> m_targets;
-        private ushort m_nextTSIH = 1; // Next Target Session Identifying Handle
 
         private Socket m_listenerSocket;
         private bool m_listening;
+        private SessionManager m_sessionManager = new SessionManager();
         private ConnectionManager m_connectionManager = new ConnectionManager();
 
         public event EventHandler<LogEntry> OnLogEntry;
@@ -346,20 +346,5 @@ namespace ISCSI.Server
         {
             Log(severity, String.Format(message, args));
         }
-
-        public ushort GetNextTSIH()
-        {
-            // The iSCSI Target selects a non-zero value for the TSIH at
-            // session creation (when an initiator presents a 0 value at Login).
-            // After being selected, the same TSIH value MUST be used whenever the
-            // initiator or target refers to the session and a TSIH is required
-            ushort nextTSIH = m_nextTSIH;
-            m_nextTSIH++;
-            if (m_nextTSIH == 0)
-            {
-                m_nextTSIH++;
-            }
-            return nextTSIH;
-        }
     }
 }

+ 37 - 0
ISCSI/ISCSI.Server/SessionManager.cs

@@ -0,0 +1,37 @@
+/* Copyright (C) 2012-2016 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
+ * 
+ * You can redistribute this program and/or modify it under the terms of
+ * the GNU Lesser Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Utilities;
+
+namespace ISCSI.Server
+{
+    internal class SessionManager
+    {
+        private object m_syncLock = new object();
+        private ushort m_nextTSIH = 1; // Next Target Session Identifying Handle
+        
+        public ushort GetNextTSIH()
+        {
+            // The iSCSI Target selects a non-zero value for the TSIH at
+            // session creation (when an initiator presents a 0 value at Login).
+            // After being selected, the same TSIH value MUST be used whenever the
+            // initiator or target refers to the session and a TSIH is required.
+            lock (m_syncLock)
+            {
+                ushort nextTSIH = m_nextTSIH;
+                m_nextTSIH++;
+                if (m_nextTSIH == 0)
+                {
+                    m_nextTSIH++;
+                }
+                return nextTSIH;
+            }
+        }
+    }
+}

+ 1 - 0
ISCSI/ISCSI.csproj

@@ -76,6 +76,7 @@
     <Compile Include="ISCSI.Server\ISCSITarget.cs" />
     <Compile Include="ISCSI.Server\PDUHelper.cs" />
     <Compile Include="ISCSI.Server\ServerResponseHelper.cs" />
+    <Compile Include="ISCSI.Server\SessionManager.cs" />
     <Compile Include="ISCSI.Server\TargetResponseHelper.cs" />
     <Compile Include="SCSI\Enums\AddressingMethod.cs" />
     <Compile Include="SCSI\Enums\ModePageCodeName.cs" />