changeset 4518:cb8fcecf1b02

new option "Timeout" in "DicomModalities" to set DICOM SCU timeout on a per-modality basis
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 22 Feb 2021 16:32:11 +0100
parents c494ee5d0101
children a3c6678aa7b1
files NEWS OrthancFramework/Sources/DicomNetworking/DicomAssociationParameters.cpp OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.cpp OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h OrthancFramework/UnitTestsSources/JobsTests.cpp OrthancServer/Resources/Configuration.json
diffstat 6 files changed, 70 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Feb 22 15:27:25 2021 +0100
+++ b/NEWS	Mon Feb 22 16:32:11 2021 +0100
@@ -8,6 +8,8 @@
 * If the storage area doesn't support range reading, or if "StorageCompression"
   is enabled, a new type of attachment "dicom-until-pixel-data" is generated.
 * New metadata automatically computed at the instance level: "PixelDataOffset"
+* New configuration option related to networking:
+  - "Timeout" in "DicomModalities" to set DICOM SCU timeout on a per-modality basis
 
 REST API
 --------
--- a/OrthancFramework/Sources/DicomNetworking/DicomAssociationParameters.cpp	Mon Feb 22 15:27:25 2021 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/DicomAssociationParameters.cpp	Mon Feb 22 16:32:11 2021 +0100
@@ -78,8 +78,8 @@
     timeout_(0),  // Will be set by SetDefaultParameters()
     maximumPduLength_(0)  // Will be set by SetDefaultParameters()
   {
+    SetDefaultParameters();
     remote_.SetApplicationEntityTitle("ANY-SCP");
-    SetDefaultParameters();
   }
 
     
@@ -89,8 +89,8 @@
     timeout_(0),  // Will be set by SetDefaultParameters()
     maximumPduLength_(0)  // Will be set by SetDefaultParameters()
   {
+    SetDefaultParameters();
     SetRemoteModality(remote);
-    SetDefaultParameters();
   }
 
   const std::string &DicomAssociationParameters::GetLocalApplicationEntityTitle() const
@@ -113,6 +113,12 @@
   {
     CheckHost(remote.GetHost());
     remote_ = remote;
+
+    if (remote.HasTimeout())
+    {
+      timeout_ = remote.GetTimeout();
+      assert(timeout_ != 0);
+    }
   }
 
   void DicomAssociationParameters::SetRemoteApplicationEntityTitle(const std::string &aet)
--- a/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.cpp	Mon Feb 22 15:27:25 2021 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.cpp	Mon Feb 22 16:32:11 2021 +0100
@@ -46,6 +46,7 @@
 static const char* KEY_PORT = "Port";
 static const char* KEY_USE_DICOM_TLS = "UseDicomTls";
 static const char* KEY_LOCAL_AET = "LocalAet";
+static const char* KEY_TIMEOUT = "Timeout";
 
 
 namespace Orthanc
@@ -66,6 +67,7 @@
     allowTranscoding_ = true;
     useDicomTls_ = false;
     localAet_.clear();
+    timeout_ = 0;
   }
 
 
@@ -293,6 +295,11 @@
     {
       localAet_ = SerializationToolbox::ReadString(serialized, KEY_LOCAL_AET);
     }
+
+    if (serialized.isMember(KEY_TIMEOUT))
+    {
+      timeout_ = SerializationToolbox::ReadUnsignedInteger(serialized, KEY_TIMEOUT);
+    }
   }
 
 
@@ -402,6 +409,7 @@
       target[KEY_ALLOW_TRANSCODING] = allowTranscoding_;
       target[KEY_USE_DICOM_TLS] = useDicomTls_;
       target[KEY_LOCAL_AET] = localAet_;
+      target[KEY_TIMEOUT] = timeout_;
     }
     else
     {
@@ -481,4 +489,19 @@
       localAet_ = aet;
     }
   }
+
+  void RemoteModalityParameters::SetTimeout(uint32_t seconds)
+  {
+    timeout_ = seconds;
+  }
+
+  uint32_t RemoteModalityParameters::GetTimeout() const
+  {
+    return timeout_;
+  }
+
+  bool RemoteModalityParameters::HasTimeout() const
+  {
+    return timeout_ != 0;
+  }
 }
--- a/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h	Mon Feb 22 15:27:25 2021 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h	Mon Feb 22 16:32:11 2021 +0100
@@ -47,6 +47,7 @@
     bool                  allowTranscoding_;
     bool                  useDicomTls_;
     std::string           localAet_;
+    uint32_t              timeout_;
     
     void Clear();
 
@@ -107,5 +108,12 @@
     const std::string& GetLocalAet() const;
 
     void SetLocalAet(const std::string& aet);
+
+    // Setting it to "0" will use "DicomAssociationParameters::GetDefaultTimeout()"
+    void SetTimeout(uint32_t seconds);
+
+    uint32_t GetTimeout() const;
+
+    bool HasTimeout() const;    
   };
 }
--- a/OrthancFramework/UnitTestsSources/JobsTests.cpp	Mon Feb 22 15:27:25 2021 +0100
+++ b/OrthancFramework/UnitTestsSources/JobsTests.cpp	Mon Feb 22 16:32:11 2021 +0100
@@ -1271,6 +1271,8 @@
     modality.Serialize(s, false);
     ASSERT_EQ(Json::arrayValue, s.type());
     ASSERT_FALSE(modality.IsDicomTlsEnabled());
+    ASSERT_FALSE(modality.HasTimeout());
+    ASSERT_EQ(0u, modality.GetTimeout());
   }
 
   {
@@ -1291,6 +1293,8 @@
     ASSERT_FALSE(modality.IsDicomTlsEnabled());
     ASSERT_FALSE(modality.HasLocalAet());
     ASSERT_THROW(modality.GetLocalAet(), OrthancException);
+    ASSERT_FALSE(modality.HasTimeout());
+    ASSERT_EQ(0u, modality.GetTimeout());
   }
 
   s = Json::nullValue;
@@ -1307,6 +1311,8 @@
     modality.Serialize(s, true);
     ASSERT_EQ(Json::objectValue, s.type());
     ASSERT_FALSE(modality.HasLocalAet());
+    ASSERT_FALSE(modality.HasTimeout());
+    ASSERT_EQ(0u, modality.GetTimeout());
   }
 
   {
@@ -1325,6 +1331,8 @@
     ASSERT_TRUE(modality.IsTranscodingAllowed());
     ASSERT_FALSE(modality.IsDicomTlsEnabled());
     ASSERT_FALSE(modality.HasLocalAet());
+    ASSERT_FALSE(modality.HasTimeout());
+    ASSERT_EQ(0u, modality.GetTimeout());
   }
 
   s["Port"] = "46";
@@ -1382,16 +1390,21 @@
   {
     RemoteModalityParameters modality;
     modality.SetLocalAet("hello");
+    modality.SetTimeout(42);
     ASSERT_TRUE(modality.IsAdvancedFormatNeeded());
     modality.Serialize(s, true);
     ASSERT_EQ(Json::objectValue, s.type());
     ASSERT_TRUE(modality.HasLocalAet());
+    ASSERT_TRUE(modality.HasTimeout());
+    ASSERT_EQ(42u, modality.GetTimeout());
   }
 
   {
     RemoteModalityParameters modality(s);
     ASSERT_TRUE(modality.HasLocalAet());
     ASSERT_EQ("hello", modality.GetLocalAet());
+    ASSERT_TRUE(modality.HasTimeout());
+    ASSERT_EQ(42u, modality.GetTimeout());
   }
 
   {
@@ -1412,6 +1425,8 @@
     ASSERT_FALSE(modality.IsDicomTlsEnabled());
     ASSERT_FALSE(modality.HasLocalAet());
     ASSERT_THROW(modality.GetLocalAet(), OrthancException);
+    ASSERT_FALSE(modality.HasTimeout());
+    ASSERT_EQ(0u, modality.GetTimeout());
   }
 
   {
@@ -1424,6 +1439,7 @@
     t["AllowTranscoding"] = false;
     t["UseDicomTls"] = true;
     t["LocalAet"] = "world";
+    t["Timeout"] = 20;
     
     RemoteModalityParameters modality(t);
     ASSERT_TRUE(modality.IsAdvancedFormatNeeded());
@@ -1436,6 +1452,8 @@
     ASSERT_TRUE(modality.IsDicomTlsEnabled());
     ASSERT_TRUE(modality.HasLocalAet());
     ASSERT_EQ("world", modality.GetLocalAet());
+    ASSERT_TRUE(modality.HasTimeout());
+    ASSERT_EQ(20u, modality.GetTimeout());
   }
 
   {
@@ -1487,6 +1505,8 @@
     ASSERT_FALSE(b.GetRemoteModality().IsDicomTlsEnabled());
     ASSERT_FALSE(b.GetRemoteModality().HasLocalAet());
     ASSERT_THROW(b.GetRemoteModality().GetLocalAet(), OrthancException);
+    ASSERT_FALSE(b.GetRemoteModality().HasTimeout());
+    ASSERT_EQ(0u, b.GetRemoteModality().GetTimeout());
   }
 
   {
@@ -1495,6 +1515,7 @@
     p.SetPortNumber(4242);
     p.SetHost("hello.world.com");
     p.SetDicomTlsEnabled(true);
+    p.SetTimeout(42);
     
     DicomAssociationParameters a("HELLO", p);
     a.SetOwnCertificatePath("key", "crt");
@@ -1521,5 +1542,7 @@
     ASSERT_EQ("crt", b.GetOwnCertificatePath());
     ASSERT_EQ("trusted", b.GetTrustedCertificatesPath());
     ASSERT_EQ(131072u, b.GetMaximumPduLength());
+    ASSERT_TRUE(b.GetRemoteModality().HasTimeout());
+    ASSERT_EQ(42u, b.GetRemoteModality().GetTimeout());
   }  
 }
--- a/OrthancServer/Resources/Configuration.json	Mon Feb 22 15:27:25 2021 +0100
+++ b/OrthancServer/Resources/Configuration.json	Mon Feb 22 16:32:11 2021 +0100
@@ -355,9 +355,11 @@
      * used when opening a SCU connection from Orthanc to this remote
      * modality. By default, DICOM TLS is not enabled.
      *
-     * The "LocalAet" allows to overwrite the global "DicomAet"
-     * configuration option in order to specify another AET for
-     * Orthanc when initiating an SCU to this very specific modality.
+     * The "LocalAet" option allows one to overwrite the global
+     * "DicomAet" configuration option in order to specify another AET
+     * for Orthanc when initiating an SCU to this very specific
+     * modality. Similarly, "Timeout" allows one to overwrite the
+     * global value "DicomScuTimeout" on a per-modality basis.
      **/
     //"untrusted" : {
     //  "AET" : "ORTHANC",
@@ -373,6 +375,7 @@
     //  "AllowTranscoding" : true,         // new in 1.7.0
     //  "UseDicomTls" : false              // new in 1.9.0
     //  "LocalAet" : "HELLO"               // new in 1.9.0
+    //  "Timeout" : 60                     // new in 1.9.1
     //}
   },