changeset 4921:309fb4f02704

fix signature of OrthancPluginIncomingCStoreInstanceFilter
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 23 Feb 2022 11:09:43 +0100
parents ce64d8995a41
children 4dae452af79f 1aea0b217f70
files OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Engine/OrthancPlugins.h OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Sources/IServerListener.h OrthancServer/Sources/LuaScripting.cpp OrthancServer/Sources/LuaScripting.h OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h
diffstat 8 files changed, 103 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Wed Feb 23 11:09:43 2022 +0100
@@ -2260,8 +2260,9 @@
 
 
 
-  uint16_t OrthancPlugins::FilterIncomingCStoreInstance(const DicomInstanceToStore& instance,
-                                                        const Json::Value& simplified)
+  bool OrthancPlugins::FilterIncomingCStoreInstance(uint16_t& dimseStatus,
+                                                    const DicomInstanceToStore& instance,
+                                                    const Json::Value& simplified)
   {
     DicomInstanceFromCallback wrapped(instance);
     
@@ -2271,20 +2272,26 @@
            filter = pimpl_->incomingCStoreInstanceFilters_.begin();
          filter != pimpl_->incomingCStoreInstanceFilters_.end(); ++filter)
     {
-      int32_t filterResult = (*filter) (reinterpret_cast<const OrthancPluginDicomInstance*>(&wrapped));
-
-      if (filterResult >= 0 && filterResult <= 0xFFFF)
-      {
-        return static_cast<uint16_t>(filterResult);
+      int32_t result = (*filter) (&dimseStatus, reinterpret_cast<const OrthancPluginDicomInstance*>(&wrapped));
+
+      if (result == 0)
+      {
+        // The instance must be discarded
+        return false;
+      }
+      else if (result == 1)
+      {
+        // The instance is accepted
+        return true;
       }
       else
       {
-        // The callback is only allowed to answer uint16_t
+        // Error
         throw OrthancException(ErrorCode_Plugin);
       }
     }
 
-    return STATUS_Success;
+    return true;  // By default, the instance is accepted
   }
 
 
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.h	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.h	Wed Feb 23 11:09:43 2022 +0100
@@ -273,8 +273,9 @@
     virtual bool FilterIncomingInstance(const DicomInstanceToStore& instance,
                                         const Json::Value& simplified) ORTHANC_OVERRIDE;
 
-    virtual uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance,
-                                                  const Json::Value& simplified) ORTHANC_OVERRIDE;
+    virtual bool FilterIncomingCStoreInstance(uint16_t& dimseStatus,
+                                              const DicomInstanceToStore& instance,
+                                              const Json::Value& simplified) ORTHANC_OVERRIDE;
 
     OrthancPluginReceivedInstanceAction ApplyReceivedInstanceCallbacks(MallocMemoryBuffer& modified,
                                                                        const void* receivedDicomBuffer,
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Wed Feb 23 11:09:43 2022 +0100
@@ -29,6 +29,7 @@
  *    - Possibly register a callback for Storage Commitment SCP using ::OrthancPluginRegisterStorageCommitmentScpCallback().
  *    - Possibly register a callback to keep/discard/modify incoming DICOM instances using OrthancPluginRegisterReceivedInstanceCallback().
  *    - Possibly register a custom transcoder for DICOM images using OrthancPluginRegisterTranscoderCallback().
+ *    - Possibly register a callback to discard instances received through DICOM C-STORE using OrthancPluginRegisterIncomingCStoreInstanceFilter().
  * -# <tt>void OrthancPluginFinalize()</tt>:
  *    This function is invoked by Orthanc during its shutdown. The plugin
  *    must free all its memory.
@@ -7733,6 +7734,16 @@
    * Note that the metadata information is not available
    * (i.e. GetInstanceMetadata() should not be used on "instance").
    *
+   * @warning Your callback function will be called synchronously with
+   * the core of Orthanc. This implies that deadlocks might emerge if
+   * you call other core primitives of Orthanc in your callback (such
+   * deadlocks are particularly visible in the presence of other plugins
+   * or Lua scripts). It is thus strongly advised to avoid any call to
+   * the REST API of Orthanc in the callback. If you have to call
+   * other primitives of Orthanc, you should make these calls in a
+   * separate thread, passing the pending events to be processed
+   * through a message queue.
+   * 
    * @param instance The received DICOM instance.
    * @return 0 to discard the instance, 1 to store the instance, -1 if error.
    * @ingroup Callback
@@ -7753,21 +7764,10 @@
    * DICOM instances received by Orthanc (either through the REST API
    * or through the DICOM protocol).
    *
-   * @warning Your callback function will be called synchronously with
-   * the core of Orthanc. This implies that deadlocks might emerge if
-   * you call other core primitives of Orthanc in your callback (such
-   * deadlocks are particularly visible in the presence of other plugins
-   * or Lua scripts). It is thus strongly advised to avoid any call to
-   * the REST API of Orthanc in the callback. If you have to call
-   * other primitives of Orthanc, you should make these calls in a
-   * separate thread, passing the pending events to be processed
-   * through a message queue.
-   * 
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
    * @param callback The callback.
    * @return 0 if success, other value if error.
    * @ingroup Callbacks
-   * @deprecated In new plugins, OrthancPluginRegisterReceivedInstanceCallback() should be used
    **/
   ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingDicomInstanceFilter(
     OrthancPluginContext*                     context,
@@ -7785,20 +7785,33 @@
    * Orthanc through C-STORE.
    *
    * Signature of a callback function that is triggered whenever
-   * Orthanc receives a new DICOM instance (through DICOM protocol), 
-   * and that answers whether this DICOM instance should be accepted 
-   * or discarded by Orthanc.  If the instance is discarded, the callback
-   * can specify the C-STORE error code.
+   * Orthanc receives a new DICOM instance using DICOM C-STORE, and
+   * that answers whether this DICOM instance should be accepted or
+   * discarded by Orthanc. If the instance is discarded, the callback
+   * can specify the DIMSE error code answered by the Orthanc C-STORE
+   * SCP.
    *
    * Note that the metadata information is not available
    * (i.e. GetInstanceMetadata() should not be used on "instance").
    *
+   * @warning Your callback function will be called synchronously with
+   * the core of Orthanc. This implies that deadlocks might emerge if
+   * you call other core primitives of Orthanc in your callback (such
+   * deadlocks are particularly visible in the presence of other plugins
+   * or Lua scripts). It is thus strongly advised to avoid any call to
+   * the REST API of Orthanc in the callback. If you have to call
+   * other primitives of Orthanc, you should make these calls in a
+   * separate thread, passing the pending events to be processed
+   * through a message queue.
+   *
+   * @param dimseStatus If the DICOM instance is discarded, 
+   * DIMSE status to be sent by the C-STORE SCP of Orthanc
    * @param instance The received DICOM instance.
-   * @return 0 to accept the instance, any valid C-STORE error code
-   * to reject the instance, -1 if error.
+   * @return 0 to discard the instance, 1 to store the instance, -1 if error.
    * @ingroup Callback
    **/
   typedef int32_t (*OrthancPluginIncomingCStoreInstanceFilter) (
+    uint16_t* dimseStatus /* out */,
     const OrthancPluginDicomInstance* instance);
 
 
@@ -7811,24 +7824,16 @@
    * @brief Register a callback to filter incoming DICOM instances
    * received by Orthanc through C-STORE.
    *
-   *
-   * @warning Your callback function will be called synchronously with
-   * the core of Orthanc. This implies that deadlocks might emerge if
-   * you call other core primitives of Orthanc in your callback (such
-   * deadlocks are particularly visible in the presence of other plugins
-   * or Lua scripts). It is thus strongly advised to avoid any call to
-   * the REST API of Orthanc in the callback. If you have to call
-   * other primitives of Orthanc, you should make these calls in a
-   * separate thread, passing the pending events to be processed
-   * through a message queue.
-   * 
+   * This function registers a custom callback to filter incoming
+   * DICOM instances received by Orthanc through the DICOM protocol.
+   *
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
    * @param callback The callback.
    * @return 0 if success, other value if error.
    * @ingroup Callbacks
    **/
   ORTHANC_PLUGIN_INLINE OrthancPluginErrorCode OrthancPluginRegisterIncomingCStoreInstanceFilter(
-    OrthancPluginContext*                     context,
+    OrthancPluginContext*                      context,
     OrthancPluginIncomingCStoreInstanceFilter  callback)
   {
     _OrthancPluginIncomingCStoreInstanceFilter params;
@@ -7851,12 +7856,22 @@
    * transcoding and before filtering
    * (cf. OrthancPluginRegisterIncomingDicomInstanceFilter()).
    *
-   * @param modifiedDicomBuffer A buffer containing the modified DICOM (output)
-   * @param receivedDicomBuffer A buffer containing the received DICOM (input)
-   * @param receivedDicomBufferSize The size of the received DICOM (input)
-   * @param origin The origin of the DICOM instance (input)
-   * This buffer will be freed by the Orthanc core and must have been allocated 
-   * using OrthancPluginCreateMemoryBuffer64().
+   * @warning Your callback function will be called synchronously with
+   * the core of Orthanc. This implies that deadlocks might emerge if
+   * you call other core primitives of Orthanc in your callback (such
+   * deadlocks are particularly visible in the presence of other plugins
+   * or Lua scripts). It is thus strongly advised to avoid any call to
+   * the REST API of Orthanc in the callback. If you have to call
+   * other primitives of Orthanc, you should make these calls in a
+   * separate thread, passing the pending events to be processed
+   * through a message queue.
+   *
+   * @param modifiedDicomBuffer A buffer containing the modified DICOM (output).
+   * This buffer must be allocated using OrthancPluginCreateMemoryBuffer64()
+   * and will be freed by the Orthanc core.
+   * @param receivedDicomBuffer A buffer containing the received DICOM (input).
+   * @param receivedDicomBufferSize The size of the received DICOM (input).
+   * @param origin The origin of the DICOM instance (input).
    * @return `OrthancPluginReceivedInstanceAction_KeepAsIs` to accept the instance as is,<br/>
    *         `OrthancPluginReceivedInstanceAction_Modify` to store the modified DICOM contained in `modifiedDicomBuffer`,<br/>
    *         `OrthancPluginReceivedInstanceAction_Discard` to tell Orthanc to discard the instance.
@@ -7878,16 +7893,17 @@
    * @brief Register a callback to keep/discard/modify a DICOM instance received
    * by Orthanc from any source (C-STORE or REST API)
    *
-   * @warning Your callback function will be called synchronously with
-   * the core of Orthanc. This implies that deadlocks might emerge if
-   * you call other core primitives of Orthanc in your callback (such
-   * deadlocks are particularly visible in the presence of other plugins
-   * or Lua scripts). It is thus strongly advised to avoid any call to
-   * the REST API of Orthanc in the callback. If you have to call
-   * other primitives of Orthanc, you should make these calls in a
-   * separate thread, passing the pending events to be processed
-   * through a message queue.
-   * 
+   * This function registers a custom callback to keep/discard/modify
+   * incoming DICOM instances received by Orthanc from any source
+   * (C-STORE or REST API).
+   * 
+   * @warning Contrarily to
+   * OrthancPluginRegisterIncomingCStoreInstanceFilter() and
+   * OrthancPluginRegisterIncomingDicomInstanceFilter() that can be
+   * called by multiple plugins,
+   * OrthancPluginRegisterReceivedInstanceCallback() can only be used
+   * by one single plugin.
+   *
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
    * @param callback The callback.
    * @return 0 if success, other value if error.
--- a/OrthancServer/Sources/IServerListener.h	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Sources/IServerListener.h	Wed Feb 23 11:09:43 2022 +0100
@@ -45,8 +45,14 @@
     virtual bool FilterIncomingInstance(const DicomInstanceToStore& instance,
                                         const Json::Value& simplified) = 0;
 
-    virtual uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance,
-                                                  const Json::Value& simplified) = 0;
-
+    /**
+     * Returns "true" iff some DICOM instance received by the DICOM
+     * SCP is to be accepted. If the instance is discarded,
+     * "dimseStatus" must contain the DIMSE status that is sent back
+     * to the DICOM SCU.
+     **/
+    virtual bool FilterIncomingCStoreInstance(uint16_t& dimseStatus,
+                                              const DicomInstanceToStore& instance,
+                                              const Json::Value& simplified) = 0;
   };
 }
--- a/OrthancServer/Sources/LuaScripting.cpp	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Sources/LuaScripting.cpp	Wed Feb 23 11:09:43 2022 +0100
@@ -32,8 +32,6 @@
 #include "../../OrthancFramework/Sources/Logging.h"
 #include "../../OrthancFramework/Sources/Lua/LuaFunctionCall.h"
 
-#include <dcmtk/dcmnet/dimse.h>
-
 #include <OrthancServerResources.h>
 
 
@@ -936,8 +934,9 @@
     return true;
   }
 
-  uint16_t LuaScripting::FilterIncomingCStoreInstance(const DicomInstanceToStore& instance,
-                                                      const Json::Value& simplified)
+  bool LuaScripting::FilterIncomingCStoreInstance(uint16_t& dimseStatus,
+                                                  const DicomInstanceToStore& instance,
+                                                  const Json::Value& simplified)
   {
     static const char* NAME = "ReceivedCStoreInstanceFilter";
 
@@ -968,7 +967,7 @@
       return static_cast<uint16_t>(result);
     }
 
-    return STATUS_Success;
+    return true;
   }
 
 
--- a/OrthancServer/Sources/LuaScripting.h	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Sources/LuaScripting.h	Wed Feb 23 11:09:43 2022 +0100
@@ -118,8 +118,9 @@
     bool FilterIncomingInstance(const DicomInstanceToStore& instance,
                                 const Json::Value& simplifiedTags);
 
-    uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance,
-                                          const Json::Value& simplified);
+    bool FilterIncomingCStoreInstance(uint16_t& dimseStatus,
+                                      const DicomInstanceToStore& instance,
+                                      const Json::Value& simplified);
 
     void Execute(const std::string& command);
 
--- a/OrthancServer/Sources/ServerContext.cpp	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Wed Feb 23 11:09:43 2022 +0100
@@ -554,9 +554,10 @@
 
             if (dicom.GetOrigin().GetRequestOrigin() == Orthanc::RequestOrigin_DicomProtocol)
             {
-              uint16_t filterResult = it->GetListener().FilterIncomingCStoreInstance(dicom, simplifiedTags);
-              if (filterResult != 0x0000)
+              uint16_t filterResult = STATUS_Success;
+              if (!it->GetListener().FilterIncomingCStoreInstance(filterResult, dicom, simplifiedTags))
               {
+                // The instance is to be discarded
                 result.SetStatus(StoreStatus_FilteredOut);
                 result.SetCStoreStatusCode(filterResult);
                 break;
--- a/OrthancServer/Sources/ServerContext.h	Wed Feb 23 09:30:53 2022 +0100
+++ b/OrthancServer/Sources/ServerContext.h	Wed Feb 23 11:09:43 2022 +0100
@@ -144,10 +144,11 @@
         return context_.filterLua_.FilterIncomingInstance(instance, simplified);
       }
 
-      virtual uint16_t FilterIncomingCStoreInstance(const DicomInstanceToStore& instance,
-                                                    const Json::Value& simplified) ORTHANC_OVERRIDE
+      virtual bool FilterIncomingCStoreInstance(uint16_t& dimseStatus,
+                                                const DicomInstanceToStore& instance,
+                                                const Json::Value& simplified) ORTHANC_OVERRIDE
       {
-        return context_.filterLua_.FilterIncomingCStoreInstance(instance, simplified);
+        return context_.filterLua_.FilterIncomingCStoreInstance(dimseStatus, instance, simplified);
       }
     };