changeset 1285:5730f374e4e6

Access to called AET and remote AET from Lua scripts
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 03 Feb 2015 15:00:42 +0100
parents 21ea32170764
children b4acdb37e43b
files NEWS OrthancServer/DicomInstanceToStore.h OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/DicomProtocol/DicomUserConnection.h OrthancServer/DicomProtocol/IStoreRequestHandler.h OrthancServer/DicomProtocol/ReusableDicomUserConnection.cpp OrthancServer/Internals/StoreScp.cpp OrthancServer/ServerContext.cpp OrthancServer/ServerContext.h OrthancServer/main.cpp Resources/Samples/Lua/AutoroutingConditional.lua
diffstat 11 files changed, 95 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Feb 03 14:07:07 2015 +0100
+++ b/NEWS	Tue Feb 03 15:00:42 2015 +0100
@@ -15,6 +15,7 @@
 * More flexible "/modify" and "/anonymize" for single instance
 * Code refactorings
 * Option "DicomAssociationCloseDelay" to set delay before closing DICOM association
+* Access to called AET and remote AET from Lua scripts ("OnStoredInstance")
 
 Plugins
 -------
--- a/OrthancServer/DicomInstanceToStore.h	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/DicomInstanceToStore.h	Tue Feb 03 15:00:42 2015 +0100
@@ -144,6 +144,7 @@
     SmartContainer<Json::Value>  json_;
 
     std::string remoteAet_;
+    std::string calledAet_;
     ServerIndex::MetadataMap metadata_;
 
     void ComputeMissingInformation();
@@ -169,7 +170,7 @@
       json_.SetConstReference(json);
     }
 
-    const std::string GetRemoteAet() const
+    const std::string& GetRemoteAet() const
     {
       return remoteAet_;
     }
@@ -179,6 +180,16 @@
       remoteAet_ = aet;
     }
 
+    const std::string& GetCalledAet() const
+    {
+      return calledAet_;
+    }
+
+    void SetCalledAet(const std::string& aet)
+    {
+      calledAet_ = aet;
+    }
+
     void AddMetadata(ResourceType level,
                      MetadataType metadata,
                      const std::string& value);
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Tue Feb 03 15:00:42 2015 +0100
@@ -454,7 +454,7 @@
     int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass);
     if (presID == 0)
     {
-      throw OrthancException("DicomUserConnection: The C-FIND command is not supported by the distant AET");
+      throw OrthancException("DicomUserConnection: The C-FIND command is not supported by the remote AET");
     }
 
     T_DIMSE_C_FindRQ request;
@@ -546,7 +546,7 @@
     int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass);
     if (presID == 0)
     {
-      throw OrthancException("DicomUserConnection: The C-MOVE command is not supported by the distant AET");
+      throw OrthancException("DicomUserConnection: The C-MOVE command is not supported by the remote AET");
     }
 
     T_DIMSE_C_MoveRQ request;
@@ -614,10 +614,10 @@
     pimpl_(new PImpl),
     preferredTransferSyntax_(DEFAULT_PREFERRED_TRANSFER_SYNTAX),
     localAet_("STORESCU"),
-    distantAet_("ANY-SCP"),
-    distantHost_("127.0.0.1")
+    remoteAet_("ANY-SCP"),
+    remoteHost_("127.0.0.1")
   {
-    distantPort_ = 104;
+    remotePort_ = 104;
     manufacturer_ = ModalityManufacturer_Generic;
 
     SetTimeout(10); 
@@ -642,10 +642,10 @@
 
   void DicomUserConnection::Connect(const RemoteModalityParameters& parameters)
   {
-    SetDistantApplicationEntityTitle(parameters.GetApplicationEntityTitle());
-    SetDistantHost(parameters.GetHost());
-    SetDistantPort(parameters.GetPort());
-    SetDistantManufacturer(parameters.GetManufacturer());
+    SetRemoteApplicationEntityTitle(parameters.GetApplicationEntityTitle());
+    SetRemoteHost(parameters.GetHost());
+    SetRemotePort(parameters.GetPort());
+    SetRemoteManufacturer(parameters.GetManufacturer());
   }
 
 
@@ -658,16 +658,16 @@
     }
   }
 
-  void DicomUserConnection::SetDistantApplicationEntityTitle(const std::string& aet)
+  void DicomUserConnection::SetRemoteApplicationEntityTitle(const std::string& aet)
   {
-    if (distantAet_ != aet)
+    if (remoteAet_ != aet)
     {
       Close();
-      distantAet_ = aet;
+      remoteAet_ = aet;
     }
   }
 
-  void DicomUserConnection::SetDistantManufacturer(ModalityManufacturer manufacturer)
+  void DicomUserConnection::SetRemoteManufacturer(ModalityManufacturer manufacturer)
   {
     if (manufacturer_ != manufacturer)
     {
@@ -691,26 +691,26 @@
   }
 
 
-  void DicomUserConnection::SetDistantHost(const std::string& host)
+  void DicomUserConnection::SetRemoteHost(const std::string& host)
   {
-    if (distantHost_ != host)
+    if (remoteHost_ != host)
     {
       if (host.size() > HOST_NAME_MAX - 10)
       {
-        throw OrthancException("Distant host name is too long");
+        throw OrthancException("Remote host name is too long");
       }
 
       Close();
-      distantHost_ = host;
+      remoteHost_ = host;
     }
   }
 
-  void DicomUserConnection::SetDistantPort(uint16_t port)
+  void DicomUserConnection::SetRemotePort(uint16_t port)
   {
-    if (distantPort_ != port)
+    if (remotePort_ != port)
     {
       Close();
-      distantPort_ = port;
+      remotePort_ = port;
     }
   }
 
@@ -723,30 +723,30 @@
     }
 
     LOG(INFO) << "Opening a DICOM SCU connection from AET \"" << GetLocalApplicationEntityTitle() 
-              << "\" to AET \"" << GetDistantApplicationEntityTitle() << "\" on host "
-              << GetDistantHost() << ":" << GetDistantPort() 
-              << " (manufacturer: " << EnumerationToString(GetDistantManufacturer()) << ")";
+              << "\" to AET \"" << GetRemoteApplicationEntityTitle() << "\" on host "
+              << GetRemoteHost() << ":" << GetRemotePort() 
+              << " (manufacturer: " << EnumerationToString(GetRemoteManufacturer()) << ")";
 
     Check(ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ pimpl_->acseTimeout_, &pimpl_->net_));
     Check(ASC_createAssociationParameters(&pimpl_->params_, /*opt_maxReceivePDULength*/ ASC_DEFAULTMAXPDU));
 
     // Set this application's title and the called application's title in the params
-    Check(ASC_setAPTitles(pimpl_->params_, localAet_.c_str(), distantAet_.c_str(), NULL));
+    Check(ASC_setAPTitles(pimpl_->params_, localAet_.c_str(), remoteAet_.c_str(), NULL));
 
-    // Set the network addresses of the local and distant entities
+    // Set the network addresses of the local and remote entities
     char localHost[HOST_NAME_MAX];
     gethostname(localHost, HOST_NAME_MAX - 1);
 
-    char distantHostAndPort[HOST_NAME_MAX];
+    char remoteHostAndPort[HOST_NAME_MAX];
 
 #ifdef _MSC_VER
     _snprintf
 #else
       snprintf
 #endif
-      (distantHostAndPort, HOST_NAME_MAX - 1, "%s:%d", distantHost_.c_str(), distantPort_);
+      (remoteHostAndPort, HOST_NAME_MAX - 1, "%s:%d", remoteHost_.c_str(), remotePort_);
 
-    Check(ASC_setPresentationAddresses(pimpl_->params_, localHost, distantHostAndPort));
+    Check(ASC_setPresentationAddresses(pimpl_->params_, localHost, remoteHostAndPort));
 
     // Set various options
     Check(ASC_setTransportLayerType(pimpl_->params_, /*opt_secureConnection*/ false));
--- a/OrthancServer/DicomProtocol/DicomUserConnection.h	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.h	Tue Feb 03 15:00:42 2015 +0100
@@ -60,9 +60,9 @@
     // Connection parameters
     std::string preferredTransferSyntax_;
     std::string localAet_;
-    std::string distantAet_;
-    std::string distantHost_;
-    uint16_t distantPort_;
+    std::string remoteAet_;
+    std::string remoteHost_;
+    uint16_t remotePort_;
     ModalityManufacturer manufacturer_;
     std::set<std::string> storageSOPClasses_;
     std::list<std::string> reservedStorageSOPClasses_;
@@ -97,30 +97,30 @@
       return localAet_;
     }
 
-    void SetDistantApplicationEntityTitle(const std::string& aet);
+    void SetRemoteApplicationEntityTitle(const std::string& aet);
 
-    const std::string& GetDistantApplicationEntityTitle() const
+    const std::string& GetRemoteApplicationEntityTitle() const
     {
-      return distantAet_;
+      return remoteAet_;
     }
 
-    void SetDistantHost(const std::string& host);
+    void SetRemoteHost(const std::string& host);
 
-    const std::string& GetDistantHost() const
+    const std::string& GetRemoteHost() const
     {
-      return distantHost_;
+      return remoteHost_;
     }
 
-    void SetDistantPort(uint16_t port);
+    void SetRemotePort(uint16_t port);
 
-    uint16_t GetDistantPort() const
+    uint16_t GetRemotePort() const
     {
-      return distantPort_;
+      return remotePort_;
     }
 
-    void SetDistantManufacturer(ModalityManufacturer manufacturer);
+    void SetRemoteManufacturer(ModalityManufacturer manufacturer);
 
-    ModalityManufacturer GetDistantManufacturer() const
+    ModalityManufacturer GetRemoteManufacturer() const
     {
       return manufacturer_;
     }
--- a/OrthancServer/DicomProtocol/IStoreRequestHandler.h	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/DicomProtocol/IStoreRequestHandler.h	Tue Feb 03 15:00:42 2015 +0100
@@ -50,6 +50,7 @@
     virtual void Handle(const std::string& dicomFile,
                         const DicomMap& dicomSummary,
                         const Json::Value& dicomJson,
-                        const std::string& distantAet) = 0;
+                        const std::string& remoteAet,
+                        const std::string& calledAet) = 0;
   };
 }
--- a/OrthancServer/DicomProtocol/ReusableDicomUserConnection.cpp	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/DicomProtocol/ReusableDicomUserConnection.cpp	Tue Feb 03 15:00:42 2015 +0100
@@ -50,10 +50,10 @@
                                          ModalityManufacturer manufacturer)
   {
     if (connection_ != NULL &&
-        connection_->GetDistantApplicationEntityTitle() == remoteAet &&
-        connection_->GetDistantHost() == address &&
-        connection_->GetDistantPort() == port &&
-        connection_->GetDistantManufacturer() == manufacturer)
+        connection_->GetRemoteApplicationEntityTitle() == remoteAet &&
+        connection_->GetRemoteHost() == address &&
+        connection_->GetRemotePort() == port &&
+        connection_->GetRemoteManufacturer() == manufacturer)
     {
       // The current connection can be reused
       LOG(INFO) << "Reusing the previous SCU connection";
@@ -64,10 +64,10 @@
 
     connection_ = new DicomUserConnection();
     connection_->SetLocalApplicationEntityTitle(localAet_);
-    connection_->SetDistantApplicationEntityTitle(remoteAet);
-    connection_->SetDistantHost(address);
-    connection_->SetDistantPort(port);
-    connection_->SetDistantManufacturer(manufacturer);
+    connection_->SetRemoteApplicationEntityTitle(remoteAet);
+    connection_->SetRemoteHost(address);
+    connection_->SetRemotePort(port);
+    connection_->SetRemoteManufacturer(manufacturer);
     connection_->Open();
   }
     
@@ -179,7 +179,7 @@
   void ReusableDicomUserConnection::Unlock()
   {
     if (connection_ != NULL &&
-        connection_->GetDistantManufacturer() == ModalityManufacturer_StoreScp)
+        connection_->GetRemoteManufacturer() == ModalityManufacturer_StoreScp)
     {
       // "storescp" from DCMTK has problems when reusing a
       // connection. Always close.
--- a/OrthancServer/Internals/StoreScp.cpp	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/Internals/StoreScp.cpp	Tue Feb 03 15:00:42 2015 +0100
@@ -102,7 +102,8 @@
     struct StoreCallbackData
     {
       IStoreRequestHandler* handler;
-      const char* distantAET;
+      const char* remoteAET;
+      const char* calledAET;
       const char* modality;
       const char* affectedSOPInstanceUID;
       uint32_t messageID;
@@ -201,7 +202,7 @@
             {
               try
               {
-                cbdata->handler->Handle(buffer, summary, dicomJson, cbdata->distantAET);
+                cbdata->handler->Handle(buffer, summary, dicomJson, cbdata->remoteAET, cbdata->calledAET);
               }
               catch (OrthancException& e)
               {
@@ -255,11 +256,13 @@
     callbackData.messageID = req->MessageID;
     if (assoc && assoc->params)
     {
-      callbackData.distantAET = assoc->params->DULparams.callingAPTitle;
+      callbackData.remoteAET = assoc->params->DULparams.callingAPTitle;
+      callbackData.calledAET = assoc->params->DULparams.calledAPTitle;
     }
     else
     {
-      callbackData.distantAET = "";
+      callbackData.remoteAET = "";
+      callbackData.calledAET = "";
     }
 
     DcmFileFormat dcmff;
--- a/OrthancServer/ServerContext.cpp	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/ServerContext.cpp	Tue Feb 03 15:00:42 2015 +0100
@@ -211,7 +211,9 @@
 
   void ServerContext::ApplyLuaOnStoredInstance(const std::string& instanceId,
                                                const Json::Value& simplifiedDicom,
-                                               const Json::Value& metadata)
+                                               const Json::Value& metadata,
+                                               const std::string& remoteAet,
+                                               const std::string& calledAet)
   {
     LuaContextLocker locker(*this);
 
@@ -223,6 +225,8 @@
       call.PushString(instanceId);
       call.PushJson(simplifiedDicom);
       call.PushJson(metadata);
+      call.PushJson(remoteAet);
+      call.PushJson(calledAet);
       call.Execute();
 
       Json::Value operations;
@@ -360,11 +364,12 @@
 
         try
         {
-          ApplyLuaOnStoredInstance(resultPublicId, simplified, metadata);
+          ApplyLuaOnStoredInstance(resultPublicId, simplified, metadata, 
+                                   dicom.GetRemoteAet(), dicom.GetCalledAet());
         }
         catch (OrthancException& e)
         {
-          LOG(ERROR) << "Error in OnStoredInstance callback (Lua): " << e.What();
+          LOG(ERROR) << "Error in " << ON_STORED_INSTANCE << " callback (Lua): " << e.What();
         }
 
         if (plugins_ != NULL)
@@ -375,7 +380,7 @@
           }
           catch (OrthancException& e)
           {
-            LOG(ERROR) << "Error in OnStoredInstance callback (plugins): " << e.What();
+            LOG(ERROR) << "Error in " << ON_STORED_INSTANCE << " callback (plugins): " << e.What();
           }
         }
       }
--- a/OrthancServer/ServerContext.h	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/ServerContext.h	Tue Feb 03 15:00:42 2015 +0100
@@ -77,7 +77,9 @@
 
     void ApplyLuaOnStoredInstance(const std::string& instanceId,
                                   const Json::Value& simplifiedDicom,
-                                  const Json::Value& metadata);
+                                  const Json::Value& metadata,
+                                  const std::string& remoteAet,
+                                  const std::string& calledAet);
 
     ServerIndex index_;
     CompressedFileStorageAccessor accessor_;
--- a/OrthancServer/main.cpp	Tue Feb 03 14:07:07 2015 +0100
+++ b/OrthancServer/main.cpp	Tue Feb 03 15:00:42 2015 +0100
@@ -72,7 +72,8 @@
   virtual void Handle(const std::string& dicomFile,
                       const DicomMap& dicomSummary,
                       const Json::Value& dicomJson,
-                      const std::string& remoteAet)
+                      const std::string& remoteAet,
+                      const std::string& calledAet)
   {
     if (dicomFile.size() > 0)
     {
@@ -81,6 +82,7 @@
       toStore.SetSummary(dicomSummary);
       toStore.SetJson(dicomJson);
       toStore.SetRemoteAet(remoteAet);
+      toStore.SetCalledAet(calledAet);
 
       std::string id;
       server_.Store(id, toStore);
--- a/Resources/Samples/Lua/AutoroutingConditional.lua	Tue Feb 03 14:07:07 2015 +0100
+++ b/Resources/Samples/Lua/AutoroutingConditional.lua	Tue Feb 03 15:00:42 2015 +0100
@@ -1,4 +1,10 @@
-function OnStoredInstance(instanceId, tags, metadata)
+function OnStoredInstance(instanceId, tags, metadata, remoteAet, calledAet)
+   -- The "remoteAet" and "calledAet" arguments are only available
+   -- since Orthanc 0.8.6
+   if remoteAet ~=nil and calledAet ~= nil then
+      print ("Source AET: " .. remoteAet .. " => Called AET: " .. calledAet)
+   end
+
    -- Extract the value of the "PatientName" DICOM tag
    local patientName = string.lower(tags['PatientName'])