changeset 3870:09798f2b985f transcoding

added a Timeout argument to every DICOM command + 'TargetAet' not mandatory anymore in /retrieve
author Alain Mazy <alain@mazy.be>
date Wed, 29 Apr 2020 12:26:51 +0200
parents c23ef85c7d9c
children 5797d184de67 37cf1889667a
files Core/DicomNetworking/DicomControlUserConnection.cpp Core/DicomNetworking/DicomControlUserConnection.h Core/DicomNetworking/DicomStoreUserConnection.h Core/SerializationToolbox.cpp Core/SerializationToolbox.h NEWS OrthancServer/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/ServerJobs/DicomModalityStoreJob.cpp OrthancServer/ServerJobs/DicomModalityStoreJob.h OrthancServer/ServerJobs/DicomMoveScuJob.cpp OrthancServer/ServerJobs/DicomMoveScuJob.h Resources/CMake/OrthancFrameworkParameters.cmake
diffstat 12 files changed, 113 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomNetworking/DicomControlUserConnection.cpp	Tue Apr 28 16:46:04 2020 +0200
+++ b/Core/DicomNetworking/DicomControlUserConnection.cpp	Wed Apr 29 12:26:51 2020 +0200
@@ -669,6 +669,10 @@
     MoveInternal(targetAet, ResourceType_Instance, query);
   }
 
+  void DicomControlUserConnection::SetTimeout(uint32_t seconds)
+  {
+    parameters_.SetTimeout(seconds);
+  }
 
   void DicomControlUserConnection::FindWorklist(DicomFindAnswers& result,
                                                 ParsedDicomFile& query)
--- a/Core/DicomNetworking/DicomControlUserConnection.h	Tue Apr 28 16:46:04 2020 +0200
+++ b/Core/DicomNetworking/DicomControlUserConnection.h	Wed Apr 29 12:26:51 2020 +0200
@@ -108,5 +108,7 @@
 
     void FindWorklist(DicomFindAnswers& result,
                       ParsedDicomFile& query);
+
+    void SetTimeout(uint32_t seconds); // 0 = no timeout
   };
 }
--- a/Core/DicomNetworking/DicomStoreUserConnection.h	Tue Apr 28 16:46:04 2020 +0200
+++ b/Core/DicomNetworking/DicomStoreUserConnection.h	Wed Apr 29 12:26:51 2020 +0200
@@ -95,6 +95,11 @@
       return parameters_;
     }
 
+    void SetTimeout(int timeout)
+    {
+      parameters_.SetTimeout(timeout);
+    }
+
     void SetCommonClassesProposed(bool proposed)
     {
       proposeCommonClasses_ = proposed;
--- a/Core/SerializationToolbox.cpp	Tue Apr 28 16:46:04 2020 +0200
+++ b/Core/SerializationToolbox.cpp	Wed Apr 29 12:26:51 2020 +0200
@@ -98,6 +98,21 @@
     }
 
 
+    int ReadInteger(const Json::Value& value,
+                    const std::string& field,
+                    int defaultValue)
+    {
+      if (value.isMember(field.c_str()))
+      {
+        return ReadInteger(value, field);
+      }
+      else
+      {
+        return defaultValue;
+      }
+    }
+
+
     unsigned int ReadUnsignedInteger(const Json::Value& value,
                                      const std::string& field)
     {
--- a/Core/SerializationToolbox.h	Tue Apr 28 16:46:04 2020 +0200
+++ b/Core/SerializationToolbox.h	Wed Apr 29 12:26:51 2020 +0200
@@ -49,6 +49,10 @@
     int ReadInteger(const Json::Value& value,
                     const std::string& field);
 
+    int ReadInteger(const Json::Value& value,
+                    const std::string& field,
+                    int defaultValue);
+
     unsigned int ReadUnsignedInteger(const Json::Value& value,
                                      const std::string& field);
 
--- a/NEWS	Tue Apr 28 16:46:04 2020 +0200
+++ b/NEWS	Wed Apr 29 12:26:51 2020 +0200
@@ -4,9 +4,13 @@
 REST API
 --------
 
+* API version has been upgraded to 7
 * Improved:
   - "/instances/../modify": it is now possible to "Keep" the "SOPInstanceUID".  
     Note that it was already possible to "Replace" it.
+  - added "Timeout" parameter to every DICOM operation
+  - "/queries/.../answers/../retrieve": "TargetAet" not mandatory anymore
+    (defaults to the local AET)
 
 
 
--- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Tue Apr 28 16:46:04 2020 +0200
+++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Wed Apr 29 12:26:51 2020 +0200
@@ -80,10 +80,20 @@
     RemoteModalityParameters remote =
       MyGetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
 
+    Json::Value request;
+    call.ParseJsonRequest(request);
+    int timeout = Toolbox::GetJsonIntegerField(request, "Timeout", -1);
+
     try
     {
       DicomControlUserConnection connection(localAet, remote);
-      
+
+      // New in Orthanc 1.7.0
+      if (timeout != -1)
+      {
+        connection.SetTimeout(timeout);
+      }
+
       if (connection.Echo())
       {
         // Echo has succeeded
@@ -605,16 +615,25 @@
     ServerContext& context = OrthancRestApi::GetContext(call);
 
     std::string targetAet;
+    int timeout = -1;
     
     Json::Value body;
     if (call.ParseJsonRequest(body))
     {
-      targetAet = SerializationToolbox::ReadString(body, "TargetAet");
+      targetAet = Toolbox::GetJsonStringField(body, "TargetAet", context.GetDefaultLocalApplicationEntityTitle());
+      timeout = Toolbox::GetJsonIntegerField(body, "Timeout", -1);
     }
     else
     {
       body = Json::objectValue;
-      call.BodyToString(targetAet);
+      if (call.GetBodySize() > 0)
+      {
+        call.BodyToString(targetAet);
+      }
+      else
+      {
+        targetAet = context.GetDefaultLocalApplicationEntityTitle();
+      }
     }
     
     std::unique_ptr<DicomMoveScuJob> job(new DicomMoveScuJob(context));
@@ -624,6 +643,7 @@
       job->SetTargetAet(targetAet);
       job->SetLocalAet(query.GetHandler().GetLocalAet());
       job->SetRemoteModality(query.GetHandler().GetRemoteModality());
+      job->SetTimeout(timeout);
 
       LOG(WARNING) << "Driving C-Move SCU on remote modality "
                    << query.GetHandler().GetRemoteModality().GetApplicationEntityTitle()
@@ -953,6 +973,8 @@
       (request, "MoveOriginatorAet", context.GetDefaultLocalApplicationEntityTitle());
     int moveOriginatorID = Toolbox::GetJsonIntegerField
       (request, "MoveOriginatorID", 0 /* By default, not a C-MOVE */);
+    int timeout = Toolbox::GetJsonIntegerField
+      (request, "Timeout", -1);
 
     job->SetLocalAet(localAet);
     job->SetRemoteModality(MyGetModalityUsingSymbolicName(remote));
@@ -968,6 +990,9 @@
       job->EnableStorageCommitment(true);
     }
 
+    // New in Orthanc 1.7.0
+    job->SetTimeout(timeout);
+
     OrthancRestApi::GetApi(call).SubmitCommandsJob
       (call, job.release(), true /* synchronous by default */, request);
   }
@@ -1022,11 +1047,18 @@
       (request, "LocalAet", context.GetDefaultLocalApplicationEntityTitle());
     std::string targetAet = Toolbox::GetJsonStringField
       (request, "TargetAet", context.GetDefaultLocalApplicationEntityTitle());
+    int timeout = Toolbox::GetJsonIntegerField
+      (request, "Timeout", -1);
 
     const RemoteModalityParameters source =
       MyGetModalityUsingSymbolicName(call.GetUriComponent("id", ""));
 
     DicomControlUserConnection connection(localAet, source);
+
+    if (timeout > -1)
+    {
+      connection.SetTimeout(timeout);
+    }
     
     for (Json::Value::ArrayIndex i = 0; i < request[KEY_RESOURCES].size(); i++)
     {
--- a/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp	Tue Apr 28 16:46:04 2020 +0200
+++ b/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp	Wed Apr 29 12:26:51 2020 +0200
@@ -49,6 +49,11 @@
     if (connection_.get() == NULL)
     {
       connection_.reset(new DicomStoreUserConnection(localAet_, remote_));
+
+      if (timeout_ > -1)
+      {
+        connection_->SetTimeout(timeout_);
+      }
     }
   }
 
@@ -276,6 +281,7 @@
   static const char* MOVE_ORIGINATOR_AET = "MoveOriginatorAet";
   static const char* MOVE_ORIGINATOR_ID = "MoveOriginatorId";
   static const char* STORAGE_COMMITMENT = "StorageCommitment";
+  static const char* TIMEOUT = "Timeout";
   
 
   DicomModalityStoreJob::DicomModalityStoreJob(ServerContext& context,
@@ -289,6 +295,9 @@
     moveOriginatorId_ = static_cast<uint16_t>
       (SerializationToolbox::ReadUnsignedInteger(serialized, MOVE_ORIGINATOR_ID));
     EnableStorageCommitment(SerializationToolbox::ReadBoolean(serialized, STORAGE_COMMITMENT));
+
+    // New in Orthanc in 1.7.0
+    timeout_ = SerializationToolbox::ReadInteger(serialized, TIMEOUT, -1);
   }
 
 
@@ -305,6 +314,7 @@
       target[MOVE_ORIGINATOR_AET] = moveOriginatorAet_;
       target[MOVE_ORIGINATOR_ID] = moveOriginatorId_;
       target[STORAGE_COMMITMENT] = storageCommitment_;
+      target[TIMEOUT] = timeout_;
       return true;
     }
   }  
--- a/OrthancServer/ServerJobs/DicomModalityStoreJob.h	Tue Apr 28 16:46:04 2020 +0200
+++ b/OrthancServer/ServerJobs/DicomModalityStoreJob.h	Wed Apr 29 12:26:51 2020 +0200
@@ -49,6 +49,7 @@
     ServerContext&                             context_;
     std::string                                localAet_;
     RemoteModalityParameters                   remote_;
+    int                                        timeout_;
     std::string                                moveOriginatorAet_;
     uint16_t                                   moveOriginatorId_;
     std::unique_ptr<DicomStoreUserConnection>  connection_;
@@ -88,6 +89,16 @@
 
     void SetRemoteModality(const RemoteModalityParameters& remote);
 
+    void SetTimeout(int timeout)
+    {
+      timeout_ = timeout;
+    }
+
+    int GetTimeout() const
+    {
+      return timeout_;
+    }
+
     bool HasMoveOriginator() const
     {
       return moveOriginatorId_ != 0;
--- a/OrthancServer/ServerJobs/DicomMoveScuJob.cpp	Tue Apr 28 16:46:04 2020 +0200
+++ b/OrthancServer/ServerJobs/DicomMoveScuJob.cpp	Wed Apr 29 12:26:51 2020 +0200
@@ -40,6 +40,7 @@
 static const char* const TARGET_AET = "TargetAet";
 static const char* const REMOTE = "Remote";
 static const char* const QUERY = "Query";
+static const char* const TIMEOUT = "Timeout";
 
 namespace Orthanc
 {
@@ -99,6 +100,11 @@
       connection_.reset(new DicomControlUserConnection(localAet_, remote_));
     }
     
+    if (timeout_ > -1)
+    {
+      connection_->SetTimeout(timeout_);
+    }
+
     connection_->Move(targetAet_, findAnswer);
   }
 
@@ -214,6 +220,9 @@
     {
       query_ = serialized[QUERY];
     }
+
+    // New in Orthanc in 1.7.0
+    timeout_ = SerializationToolbox::ReadInteger(serialized, TIMEOUT, -1);
   }
 
   
@@ -228,6 +237,7 @@
       target[LOCAL_AET] = localAet_;
       target[TARGET_AET] = targetAet_;
       target[QUERY] = query_;
+      target[TIMEOUT] = timeout_;
       remote_.Serialize(target[REMOTE], true /* force advanced format */);
       return true;
     }
--- a/OrthancServer/ServerJobs/DicomMoveScuJob.h	Tue Apr 28 16:46:04 2020 +0200
+++ b/OrthancServer/ServerJobs/DicomMoveScuJob.h	Wed Apr 29 12:26:51 2020 +0200
@@ -53,6 +53,7 @@
     std::string               localAet_;
     std::string               targetAet_;
     RemoteModalityParameters  remote_;
+    int                       timeout_;
     Json::Value               query_;
 
     std::unique_ptr<DicomControlUserConnection>  connection_;
@@ -95,6 +96,17 @@
 
     void SetRemoteModality(const RemoteModalityParameters& remote);
 
+    void SetTimeout(int timeout)
+    {
+      timeout_ = timeout;
+    }
+
+    int GetTimeout() const
+    {
+      return timeout_;
+    }
+
+
     virtual void Stop(JobStopReason reason);
 
     virtual void GetJobType(std::string& target)
--- a/Resources/CMake/OrthancFrameworkParameters.cmake	Tue Apr 28 16:46:04 2020 +0200
+++ b/Resources/CMake/OrthancFrameworkParameters.cmake	Wed Apr 29 12:26:51 2020 +0200
@@ -17,7 +17,7 @@
 # Version of the Orthanc API, can be retrieved from "/system" URI in
 # order to check whether new URI endpoints are available even if using
 # the mainline version of Orthanc
-set(ORTHANC_API_VERSION "6")
+set(ORTHANC_API_VERSION "7")
 
 
 #####################################################################