changeset 2222:21713ce8717b

Fix handling of Move Originator AET and ID in C-MOVE SCP
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 13 Dec 2016 14:34:33 +0100
parents e7beca979562
children 29689b30f9ae
files Core/DicomFormat/DicomTag.h NEWS OrthancServer/DicomProtocol/DicomUserConnection.cpp OrthancServer/DicomProtocol/DicomUserConnection.h OrthancServer/DicomProtocol/IMoveRequestHandler.h OrthancServer/Internals/MoveScp.cpp OrthancServer/LuaScripting.cpp OrthancServer/OrthancMoveRequestHandler.cpp OrthancServer/OrthancMoveRequestHandler.h OrthancServer/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Scheduler/StoreScuCommand.cpp OrthancServer/Scheduler/StoreScuCommand.h Plugins/Engine/OrthancPlugins.cpp Plugins/Include/orthanc/OrthancCPlugin.h UnitTestsSources/MultiThreadingTests.cpp
diffstat 15 files changed, 145 insertions(+), 89 deletions(-) [+]
line wrap: on
line diff
--- a/Core/DicomFormat/DicomTag.h	Tue Dec 13 12:13:12 2016 +0100
+++ b/Core/DicomFormat/DicomTag.h	Tue Dec 13 14:34:33 2016 +0100
@@ -128,6 +128,7 @@
   static const DicomTag DICOM_TAG_TEMPORAL_POSITION_IDENTIFIER(0x0020, 0x0100);
 
   // Tags for C-FIND and C-MOVE
+  static const DicomTag DICOM_TAG_MESSAGE_ID(0x0000, 0x0110);
   static const DicomTag DICOM_TAG_SPECIFIC_CHARACTER_SET(0x0008, 0x0005);
   static const DicomTag DICOM_TAG_QUERY_RETRIEVE_LEVEL(0x0008, 0x0052);
   static const DicomTag DICOM_TAG_MODALITIES_IN_STUDY(0x0008, 0x0061);
--- a/NEWS	Tue Dec 13 12:13:12 2016 +0100
+++ b/NEWS	Tue Dec 13 14:34:33 2016 +0100
@@ -13,7 +13,7 @@
 
 * "/tools/invalidate-tags" to invalidate the JSON summary of all the DICOM files
   (useful if private tags are registered, or if changing the default encoding)
-* "Permissive" flag for URI "/modalities/{...}/store" to ignore C-Store transfer errors
+* "Permissive" flag for URI "/modalities/{...}/store" to ignore C-STORE transfer errors
 * "Asynchronous" flag for URIs "/modalities/{...}/store" and "/peers/{...}/store"
   to avoid waiting for the completion of image transfers
 * Possibility to DELETE "dicom-as-json" attachments to reconstruct the JSON summaries
@@ -29,7 +29,7 @@
 * New function: "OrthancPluginRegisterPrivateDictionaryTag()" to register private tags
 * More control over client cache in the ServeFolders plugin
 * New C++ help wrappers in "Plugins/Samples/Common/" to read DICOM datasets from REST API
-* New data structure: "OrthancPluginFindMatcher" to match DICOM against C-Find queries
+* New data structure: "OrthancPluginFindMatcher" to match DICOM against C-FIND queries
 
 Maintenance
 -----------
@@ -46,6 +46,7 @@
 * Content-Type for JSON documents is now "application/json; charset=utf-8"
 * Ignore "Group Length" tags in C-FIND queries
 * Fix handling of worklist SCP with ReferencedStudySequence and ReferencedPatientSequence
+* Fix handling of Move Originator AET and ID in C-MOVE SCP
 
 
 Version 1.1.0 (2016/06/27)
@@ -63,23 +64,23 @@
 --------
 
 * New URI: "/instances/.../frames/.../raw" to access the raw frames (bypass image decoding)
-* New URI "/modalities/.../move" to issue C-Move SCU requests
+* New URI "/modalities/.../move" to issue C-MOVE SCU requests
 * "MoveOriginatorID" can be specified for "/modalities/.../store"
 
 Dicom protocol
 --------------
 
-* Support of optional tags for counting resources in C-Find:
+* Support of optional tags for counting resources in C-FIND:
   0008-0061, 0008-0062, 0020-1200, 0020-1202, 0020-1204, 0020-1206, 0020-1208, 0020-1209
-* Support of Move Originator Message ID (0000,1031) in C-Store responses driven by C-Move
+* Support of Move Originator Message ID (0000,1031) in C-STORE responses driven by C-MOVE
 
 Plugins
 -------
 
 * Speedup in plugins by removing unnecessary locks
 * New callback to filter incoming HTTP requests: OrthancPluginRegisterIncomingHttpRequestFilter()
-* New callback to handle non-worklists C-Find requests: OrthancPluginRegisterFindCallback()
-* New callback to handle C-Move requests: OrthancPluginRegisterMoveCallback()
+* New callback to handle non-worklists C-FIND requests: OrthancPluginRegisterFindCallback()
+* New callback to handle C-MOVE requests: OrthancPluginRegisterMoveCallback()
 * New function: "OrthancPluginHttpClient()" to do HTTP requests with full control
 * New function: "OrthancPluginGenerateUuid()" to generate a UUID
 * More than one custom image decoder can be installed (e.g. to handle different transfer syntaxes)
@@ -87,7 +88,7 @@
 Lua
 ---
 
-* Possibility to dynamically fix outgoing C-Find requests using "OutgoingFindRequestFilter()"
+* Possibility to dynamically fix outgoing C-FIND requests using "OutgoingFindRequestFilter()"
 * Access to the HTTP headers in the "IncomingHttpRequestFilter()" callback
 
 Image decoding
@@ -122,7 +123,7 @@
 Version 1.0.0 (2015/12/15)
 ==========================
 
-* Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-Find requests
+* Lua: "IncomingFindRequestFilter()" to apply filters to incoming C-FIND requests
 * New function in plugin SDK: "OrthancPluginSendMultipartItem2()"
 * Fix of DICOMDIR generation with DCMTK 3.6.1, support of encodings
 * Fix range search if the lower or upper limit is absent
--- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -154,6 +154,7 @@
 
     void Store(DcmInputStream& is, 
                DicomUserConnection& connection,
+               const std::string& moveOriginatorAET,
                uint16_t moveOriginatorID);
   };
 
@@ -259,6 +260,7 @@
 
   void DicomUserConnection::PImpl::Store(DcmInputStream& is, 
                                          DicomUserConnection& connection,
+                                         const std::string& moveOriginatorAET,
                                          uint16_t moveOriginatorID)
   {
     CheckIsOpen();
@@ -341,12 +343,12 @@
     request.DataSetType = DIMSE_DATASET_PRESENT;
     strncpy(request.AffectedSOPInstanceUID, sopInstance, DIC_UI_LEN);
 
-    strncpy(request.MoveOriginatorApplicationEntityTitle, 
-            connection.GetLocalApplicationEntityTitle().c_str(), DIC_AE_LEN);
-    request.opts = O_STORE_MOVEORIGINATORAETITLE;
+    if (!moveOriginatorAET.empty())
+    {
+      strncpy(request.MoveOriginatorApplicationEntityTitle, 
+              moveOriginatorAET.c_str(), DIC_AE_LEN);
+      request.opts = O_STORE_MOVEORIGINATORAETITLE;
 
-    if (moveOriginatorID != 0)
-    {
       request.MoveOriginatorID = moveOriginatorID;  // The type DIC_US is an alias for uint16_t
       request.opts |= O_STORE_MOVEORIGINATORID;
     }
@@ -961,6 +963,7 @@
 
   void DicomUserConnection::Store(const char* buffer, 
                                   size_t size,
+                                  const std::string& moveOriginatorAET,
                                   uint16_t moveOriginatorID)
   {
     // Prepare an input stream for the memory buffer
@@ -969,24 +972,26 @@
       is.setBuffer(buffer, size);
     is.setEos();
       
-    pimpl_->Store(is, *this, moveOriginatorID);
+    pimpl_->Store(is, *this, moveOriginatorAET, moveOriginatorID);
   }
 
   void DicomUserConnection::Store(const std::string& buffer,
+                                  const std::string& moveOriginatorAET,
                                   uint16_t moveOriginatorID)
   {
     if (buffer.size() > 0)
-      Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size(), moveOriginatorID);
+      Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size(), moveOriginatorAET, moveOriginatorID);
     else
-      Store(NULL, 0, moveOriginatorID);
+      Store(NULL, 0, moveOriginatorAET, moveOriginatorID);
   }
 
   void DicomUserConnection::StoreFile(const std::string& path,
+                                      const std::string& moveOriginatorAET,
                                       uint16_t moveOriginatorID)
   {
     // Prepare an input stream for the file
     DcmInputFileStream is(path.c_str());
-    pimpl_->Store(is, *this, moveOriginatorID);
+    pimpl_->Store(is, *this, moveOriginatorAET, moveOriginatorID);
   }
 
   bool DicomUserConnection::Echo()
--- a/OrthancServer/DicomProtocol/DicomUserConnection.h	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/DicomProtocol/DicomUserConnection.h	Tue Dec 13 14:34:33 2016 +0100
@@ -135,14 +135,33 @@
 
     void Store(const char* buffer, 
                size_t size,
+               const std::string& moveOriginatorAET,
                uint16_t moveOriginatorID);
 
+    void Store(const char* buffer, 
+               size_t size)
+    {
+      Store(buffer, size, "", 0);  // Not a C-Move
+    }
+
     void Store(const std::string& buffer,
+               const std::string& moveOriginatorAET,
                uint16_t moveOriginatorID);
 
+    void Store(const std::string& buffer)
+    {
+      Store(buffer, "", 0);  // Not a C-Move
+    }
+
     void StoreFile(const std::string& path,
+                   const std::string& moveOriginatorAET,
                    uint16_t moveOriginatorID);
 
+    void StoreFile(const std::string& path)
+    {
+      StoreFile(path, "", 0);  // Not a C-Move
+    }
+
     void Find(DicomFindAnswers& result,
               ResourceType level,
               const DicomMap& fields);
--- a/OrthancServer/DicomProtocol/IMoveRequestHandler.h	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/DicomProtocol/IMoveRequestHandler.h	Tue Dec 13 14:34:33 2016 +0100
@@ -67,12 +67,12 @@
     {
     }
 
-    virtual IMoveRequestIterator* Handle(const std::string& target,
+    virtual IMoveRequestIterator* Handle(const std::string& targetAet,
                                          const DicomMap& input,
-                                         const std::string& remoteIp,
-                                         const std::string& remoteAet,
+                                         const std::string& originatorIp,
+                                         const std::string& originatorAet,
                                          const std::string& calledAet,
-                                         uint16_t messageId) = 0;
+                                         uint16_t originatorId) = 0;
   };
 
 }
--- a/OrthancServer/Internals/MoveScp.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/Internals/MoveScp.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -90,6 +90,8 @@
 #include "../../Core/Logging.h"
 #include "../../Core/OrthancException.h"
 
+#include <boost/lexical_cast.hpp>
+
 
 namespace Orthanc
 {
@@ -110,6 +112,42 @@
     };
 
 
+
+    static uint16_t GetMessageId(const DicomMap& message)
+    {
+      /**
+       * Retrieve the Message ID (0000,0110) for this C-MOVE request, if
+       * any. If present, this Message ID will be stored in the Move
+       * Originator Message ID (0000,1031) field of the C-MOVE response.
+       * http://dicom.nema.org/dicom/2013/output/chtml/part07/chapter_E.html
+       **/
+
+      const DicomValue* value = message.TestAndGetValue(DICOM_TAG_MESSAGE_ID);
+
+      if (value != NULL &&
+          !value->IsNull() &&
+          !value->IsBinary())
+      {
+        try
+        {
+          int tmp = boost::lexical_cast<int>(value->GetContent());
+          if (tmp >= 0 && tmp <= 0xffff)
+          {
+            return static_cast<uint16_t>(tmp);
+          }
+        }
+        catch (boost::bad_lexical_cast&)
+        {
+          LOG(WARNING) << "Cannot convert the Message ID (\"" << value->GetContent()
+                       << "\") of an incoming C-MOVE request to an integer, assuming zero";
+        }
+      }
+
+      return 0;
+    }
+
+
+
     void MoveScpCallback(
       /* in */ 
       void *callbackData,  
@@ -134,9 +172,8 @@
 
         try
         {
-          data.iterator_.reset(data.handler_->Handle(data.target_, input,
-                                                     *data.remoteIp_, *data.remoteAet_,
-                                                     *data.calledAet_, request->MessageID));
+          data.iterator_.reset(data.handler_->Handle(data.target_, input, *data.remoteIp_, *data.remoteAet_,
+                                                     *data.calledAet_, GetMessageId(input)));
 
           if (data.iterator_.get() == NULL)
           {
--- a/OrthancServer/LuaScripting.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/LuaScripting.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -252,9 +252,10 @@
       std::string modality = parameters["Modality"].asString();
       LOG(INFO) << "Lua script to send resource " << parameters["Resource"].asString()
                 << " to modality " << modality << " using Store-SCU";
+
+      // This is not a C-MOVE: No need to call "StoreScuCommand::SetMoveOriginator()"
       return new StoreScuCommand(context_, localAet,
-                                 Configuration::GetModalityUsingSymbolicName(modality), 
-                                 true, 0 /* not a C-MOVE */);
+                                 Configuration::GetModalityUsingSymbolicName(modality), true);
     }
 
     if (operation == "store-peer")
--- a/OrthancServer/OrthancMoveRequestHandler.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/OrthancMoveRequestHandler.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -52,17 +52,20 @@
       std::vector<std::string> instances_;
       size_t position_;
       RemoteModalityParameters remote_;
-      uint16_t moveRequestID_;
+      std::string originatorAet_;
+      uint16_t originatorId_;
 
     public:
       OrthancMoveRequestIterator(ServerContext& context,
                                  const std::string& aet,
                                  const std::string& publicId,
-                                 uint16_t moveRequestID) :
+                                 const std::string& originatorAet,
+                                 uint16_t originatorId) :
         context_(context),
         localAet_(context.GetDefaultLocalApplicationEntityTitle()),
         position_(0),
-        moveRequestID_(moveRequestID)
+        originatorAet_(originatorAet),
+        originatorId_(originatorId)
       {
         LOG(INFO) << "Sending resource " << publicId << " to modality \"" << aet << "\"";
 
@@ -98,7 +101,7 @@
         {
           ReusableDicomUserConnection::Locker locker
             (context_.GetReusableDicomUserConnection(), localAet_, remote_);
-          locker.GetConnection().Store(dicom, moveRequestID_);
+          locker.GetConnection().Store(dicom, originatorAet_, originatorId_);
         }
 
         return Status_Success;
@@ -167,10 +170,10 @@
 
   IMoveRequestIterator* OrthancMoveRequestHandler::Handle(const std::string& targetAet,
                                                           const DicomMap& input,
-                                                          const std::string& remoteIp,
-                                                          const std::string& remoteAet,
+                                                          const std::string& originatorIp,
+                                                          const std::string& originatorAet,
                                                           const std::string& calledAet,
-                                                          uint16_t messageId)
+                                                          uint16_t originatorId)
   {
     LOG(WARNING) << "Move-SCU request received for AET \"" << targetAet << "\"";
 
@@ -188,36 +191,6 @@
     }
 
 
-#if 0
-    /**
-     * Retrieve the Message ID (0000,0110) for this C-MOVE request, if
-     * any. If present, this Message ID will be stored in the Move
-     * Originator Message ID (0000,1031) field of the C-MOVE response.
-     * http://dicom.nema.org/medical/dicom/current/output/html/part07.html#sect_9.3.1
-     **/
-
-    static const DicomTag MESSAGE_ID(0x0000, 0x0110);
-    const DicomValue* messageIdTmp = input.TestAndGetValue(MESSAGE_ID);
-
-    messageId = 0;
-
-    if (messageIdTmp != NULL &&
-        !messageIdTmp->IsNull() &&
-        !messageIdTmp->IsBinary())
-    {
-      try
-      {
-        messageId = boost::lexical_cast<uint16_t>(messageIdTmp->GetContent());
-      }
-      catch (boost::bad_lexical_cast&)
-      {
-        LOG(WARNING) << "Cannot convert the Message ID (\"" << messageIdTmp ->GetContent()
-                     << "\") of an incoming C-MOVE request to an integer, assuming zero";
-      }
-    }
-#endif
-
-
     /**
      * Retrieve the query level.
      **/
@@ -241,7 +214,7 @@
           LookupIdentifier(publicId, ResourceType_Study, input) ||
           LookupIdentifier(publicId, ResourceType_Patient, input))
       {
-        return new OrthancMoveRequestIterator(context_, targetAet, publicId, messageId);
+        return new OrthancMoveRequestIterator(context_, targetAet, publicId, originatorAet, originatorId);
       }
       else
       {
@@ -262,7 +235,7 @@
 
     if (LookupIdentifier(publicId, level, input))
     {
-      return new OrthancMoveRequestIterator(context_, targetAet, publicId, messageId);
+      return new OrthancMoveRequestIterator(context_, targetAet, publicId, originatorAet, originatorId);
     }
     else
     {
--- a/OrthancServer/OrthancMoveRequestHandler.h	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/OrthancMoveRequestHandler.h	Tue Dec 13 14:34:33 2016 +0100
@@ -53,9 +53,9 @@
 
     virtual IMoveRequestIterator* Handle(const std::string& targetAet,
                                          const DicomMap& input,
-                                         const std::string& remoteIp,
-                                         const std::string& remoteAet,
+                                         const std::string& originatorIp,
+                                         const std::string& originatorAet,
                                          const std::string& calledAet,
-                                         uint16_t messageId);
+                                         uint16_t originatorId);
   };
 }
--- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -686,6 +686,7 @@
     std::string localAet = Toolbox::GetJsonStringField(request, "LocalAet", context.GetDefaultLocalApplicationEntityTitle());
     bool permissive = Toolbox::GetJsonBooleanField(request, "Permissive", false);
     bool asynchronous = Toolbox::GetJsonBooleanField(request, "Asynchronous", false);
+    std::string moveOriginatorAET = Toolbox::GetJsonStringField(request, "MoveOriginatorAet", context.GetDefaultLocalApplicationEntityTitle());
     int moveOriginatorID = Toolbox::GetJsonIntegerField(request, "MoveOriginatorID", 0 /* By default, not a C-MOVE */);
 
     if (moveOriginatorID < 0 || 
@@ -700,8 +701,14 @@
     for (std::list<std::string>::const_iterator 
            it = instances.begin(); it != instances.end(); ++it)
     {
-      job.AddCommand(new StoreScuCommand(context, localAet, p, permissive,
-                                         static_cast<uint16_t>(moveOriginatorID))).AddInput(*it);
+      std::auto_ptr<StoreScuCommand> command(new StoreScuCommand(context, localAet, p, permissive));
+
+      if (moveOriginatorID != 0)
+      {
+        command->SetMoveOriginator(moveOriginatorAET, static_cast<uint16_t>(moveOriginatorID));
+      }
+
+      job.AddCommand(command.release()).AddInput(*it);
     }
 
     job.SetDescription("HTTP request: Store-SCU to peer \"" + remote + "\"");
--- a/OrthancServer/Scheduler/StoreScuCommand.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/Scheduler/StoreScuCommand.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -40,16 +40,24 @@
   StoreScuCommand::StoreScuCommand(ServerContext& context,
                                    const std::string& localAet,
                                    const RemoteModalityParameters& modality,
-                                   bool ignoreExceptions,
-                                   uint16_t moveOriginatorID) : 
+                                   bool ignoreExceptions) : 
     context_(context),
     modality_(modality),
     ignoreExceptions_(ignoreExceptions),
     localAet_(localAet),
-    moveOriginatorID_(moveOriginatorID)
+    moveOriginatorID_(0)
   {
   }
 
+
+  void StoreScuCommand::SetMoveOriginator(const std::string& aet,
+                                          uint16_t id)
+  {
+    moveOriginatorAET_ = aet;
+    moveOriginatorID_ = id;
+  }
+
+
   bool StoreScuCommand::Apply(ListOfStrings& outputs,
                              const ListOfStrings& inputs)
   {
@@ -66,7 +74,7 @@
         std::string dicom;
         context_.ReadDicom(dicom, *it);
 
-        locker.GetConnection().Store(dicom, moveOriginatorID_);
+        locker.GetConnection().Store(dicom, moveOriginatorAET_, moveOriginatorID_);
 
         // Only chain with other commands if this command succeeds
         outputs.push_back(*it);
--- a/OrthancServer/Scheduler/StoreScuCommand.h	Tue Dec 13 12:13:12 2016 +0100
+++ b/OrthancServer/Scheduler/StoreScuCommand.h	Tue Dec 13 14:34:33 2016 +0100
@@ -44,15 +44,17 @@
     RemoteModalityParameters modality_;
     bool ignoreExceptions_;
     std::string localAet_;
+    std::string moveOriginatorAET_;
     uint16_t moveOriginatorID_;
 
   public:
     StoreScuCommand(ServerContext& context,
                     const std::string& localAet,
                     const RemoteModalityParameters& modality,
-                    bool ignoreExceptions,
-                    uint16_t moveOriginatorID /* only makes sense if this 
-                                                 command results from a C-MOVE */);
+                    bool ignoreExceptions);
+
+    void SetMoveOriginator(const std::string& aet,
+                           uint16_t id);
 
     virtual bool Apply(ListOfStrings& outputs,
                        const ListOfStrings& inputs);
--- a/Plugins/Engine/OrthancPlugins.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/Plugins/Engine/OrthancPlugins.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -687,10 +687,10 @@
 
     virtual IMoveRequestIterator* Handle(const std::string& targetAet,
                                          const DicomMap& input,
-                                         const std::string& remoteIp,
-                                         const std::string& remoteAet,
+                                         const std::string& originatorIp,
+                                         const std::string& originatorAet,
                                          const std::string& calledAet,
-                                         uint16_t messageId)
+                                         uint16_t originatorId)
     {
       std::string levelString = ReadTag(input, DICOM_TAG_QUERY_RETRIEVE_LEVEL);
       std::string patientId = ReadTag(input, DICOM_TAG_PATIENT_ID);
@@ -712,10 +712,10 @@
                                       studyInstanceUid.empty() ? NULL : studyInstanceUid.c_str(),
                                       seriesInstanceUid.empty() ? NULL : seriesInstanceUid.c_str(),
                                       sopInstanceUid.empty() ? NULL : sopInstanceUid.c_str(),
-                                      remoteAet.c_str(),
+                                      originatorAet.c_str(),
                                       calledAet.c_str(),
                                       targetAet.c_str(),
-                                      messageId);
+                                      originatorId);
 
       if (driver == NULL)
       {
--- a/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Dec 13 12:13:12 2016 +0100
+++ b/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Dec 13 14:34:33 2016 +0100
@@ -1059,18 +1059,20 @@
    * @param resourceType The type of the resource of interest. Note
    * that this might be set to ResourceType_None if the
    * QueryRetrieveLevel (0008,0052) tag was not provided by the
-   * issuer.
+   * issuer (i.e. the originator modality).
    * @param patientId Content of the PatientID (0x0010, 0x0020) tag of the resource of interest. Might be NULL.
    * @param accessionNumber Content of the AccessionNumber (0x0008, 0x0050) tag. Might be NULL.
    * @param studyInstanceUid Content of the StudyInstanceUID (0x0020, 0x000d) tag. Might be NULL.
    * @param seriesInstanceUid Content of the SeriesInstanceUID (0x0020, 0x000e) tag. Might be NULL.
    * @param sopInstanceUid Content of the SOPInstanceUID (0x0008, 0x0018) tag. Might be NULL.
-   * @param issuerAet The Application Entity Title (AET) of the
+   * @param originatorAet The Application Entity Title (AET) of the
    * modality from which the request originates.
    * @param sourceAet The Application Entity Title (AET) of the
    * modality that should send its DICOM files to another modality.
    * @param targetAet The Application Entity Title (AET) of the
    * modality that should receive the DICOM files.
+   * @param originatorId The Message ID issued by the originator modality,
+   * as found in tag (0000,0110) of the DICOM query emitted by the issuer.
    *
    * @return The NULL value if the plugin cannot deal with this query,
    * or a pointer to the driver object that is responsible for
@@ -1086,10 +1088,10 @@
     const char*                studyInstanceUid,
     const char*                seriesInstanceUid,
     const char*                sopInstanceUid,
-    const char*                issuerAet,
+    const char*                originatorAet,
     const char*                sourceAet,
     const char*                targetAet,
-    uint16_t                   moveOriginatorId);
+    uint16_t                   originatorId);
     
 
   /**
--- a/UnitTestsSources/MultiThreadingTests.cpp	Tue Dec 13 12:13:12 2016 +0100
+++ b/UnitTestsSources/MultiThreadingTests.cpp	Tue Dec 13 14:34:33 2016 +0100
@@ -139,7 +139,7 @@
   {
     RemoteModalityParameters remote("STORESCP", "localhost", 2000, ModalityManufacturer_Generic);
     ReusableDicomUserConnection::Locker lock(c, "ORTHANC", remote);
-    lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676281", 0);
+    lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676281");
   }
 
   printf("**\n"); fflush(stdout);
@@ -149,7 +149,7 @@
   {
     RemoteModalityParameters remote("STORESCP", "localhost", 2000, ModalityManufacturer_Generic);
     ReusableDicomUserConnection::Locker lock(c, "ORTHANC", remote);
-    lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676277", 0);
+    lock.GetConnection().StoreFile("/home/jodogne/DICOM/Cardiac/MR.X.1.2.276.0.7230010.3.1.4.2831157719.2256.1336386844.676277");
   }
 
   SystemToolbox::ServerBarrier();