diff OrthancServer/Plugins/Engine/OrthancPlugins.cpp @ 4845:02d77189d8ba received-instance-callback

added ReceivedInstanceCallback + sample C++ plugin
author Alain Mazy <am@osimis.io>
date Thu, 09 Dec 2021 17:22:40 +0100
parents b55babf15e4f
children 5ec96ada5a53
line wrap: on
line diff
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Tue Dec 07 14:01:17 2021 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Thu Dec 09 17:22:40 2021 +0100
@@ -1168,6 +1168,7 @@
     typedef std::list<OrthancPluginIncomingHttpRequestFilter2>  IncomingHttpRequestFilters2;
     typedef std::list<OrthancPluginIncomingDicomInstanceFilter>  IncomingDicomInstanceFilters;
     typedef std::list<OrthancPluginIncomingCStoreInstanceFilter>  IncomingCStoreInstanceFilters;
+    typedef std::list<OrthancPluginReceivedInstanceCallback>  ReceivedInstanceCallbacks;
     typedef std::list<OrthancPluginDecodeImageCallback>  DecodeImageCallbacks;
     typedef std::list<OrthancPluginTranscoderCallback>  TranscoderCallbacks;
     typedef std::list<OrthancPluginJobsUnserializer>  JobsUnserializers;
@@ -1191,6 +1192,7 @@
     IncomingHttpRequestFilters2 incomingHttpRequestFilters2_;
     IncomingDicomInstanceFilters  incomingDicomInstanceFilters_;
     IncomingCStoreInstanceFilters  incomingCStoreInstanceFilters_;  // New in Orthanc 1.9.8
+    ReceivedInstanceCallbacks  receivedInstanceCallbacks_;  // New in Orthanc 1.9.8
     RefreshMetricsCallbacks refreshMetricsCallbacks_;
     StorageCommitmentScpCallbacks storageCommitmentScpCallbacks_;
     std::unique_ptr<StorageAreaFactory>  storageArea_;
@@ -2295,6 +2297,70 @@
   }
 
 
+  bool OrthancPlugins::ApplyReceivedInstanceCallbacks(const void* receivedDicom,
+                                                      size_t receivedDicomSize,
+                                                      void** modifiedDicomBufferData,
+                                                      size_t& modifiedDicomBufferSize)
+  {
+    uint64_t modifiedDicomSize64 = 0;
+    *modifiedDicomBufferData = NULL;
+
+    boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_);
+    
+    for (PImpl::ReceivedInstanceCallbacks::const_iterator
+           callback = pimpl_->receivedInstanceCallbacks_.begin();
+         callback != pimpl_->receivedInstanceCallbacks_.end(); ++callback)
+    {
+      OrthancPluginReceivedInstanceCallbackResult callbackResult = (*callback) (receivedDicom,
+                                                                                receivedDicomSize,
+                                                                                modifiedDicomBufferData,
+                                                                                &modifiedDicomSize64);
+
+      if (callbackResult == OrthancPluginReceivedInstanceCallbackResult_Discard)
+      {
+        if (modifiedDicomSize64 > 0 || *modifiedDicomBufferData != NULL)
+        {
+          free(modifiedDicomBufferData);
+          throw OrthancException(ErrorCode_Plugin, "The ReceivedInstanceCallback plugin is returning a modified buffer while it has discarded the instance");
+        }
+        return false;
+      }
+      else if (callbackResult == OrthancPluginReceivedInstanceCallbackResult_KeepAsIs)
+      {
+        if (modifiedDicomSize64 > 0 || *modifiedDicomBufferData != NULL)
+        {
+          free(modifiedDicomBufferData);
+          throw OrthancException(ErrorCode_Plugin, "The ReceivedInstanceCallback plugin is returning a modified buffer while it has not modified the instance");
+        }
+        return true; 
+      }
+      else if (callbackResult == OrthancPluginReceivedInstanceCallbackResult_Modified)
+      {
+        if (modifiedDicomSize64 > 0 && modifiedDicomBufferData != NULL)
+        {
+          if (static_cast<size_t>(modifiedDicomSize64) != modifiedDicomSize64)  // Orthanc is running in 32bits and has received a > 4GB buffer
+          {
+            free(modifiedDicomBufferData);
+            throw OrthancException(ErrorCode_Plugin, "The Plugin has returned a > 4GB which is too large for Orthanc running in 32bits");
+          }
+
+          modifiedDicomBufferSize = static_cast<size_t>(modifiedDicomSize64);
+          return true;
+        }
+        else
+        {
+          throw OrthancException(ErrorCode_Plugin, "The ReceivedInstanceCallback plugin is not returning a modified buffer while it has modified the instance");
+        }
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_Plugin, "The ReceivedInstanceCallback has returned an invalid value");
+      }
+    }
+
+    return STATUS_Success;
+  }
+
   void OrthancPlugins::SignalChangeInternal(OrthancPluginChangeType changeType,
                                             OrthancPluginResourceType resourceType,
                                             const char* resource)
@@ -2521,6 +2587,14 @@
     pimpl_->incomingCStoreInstanceFilters_.push_back(p.callback);
   }
 
+  void OrthancPlugins::RegisterReceivedInstanceCallback(const void* parameters)
+  {
+    const _OrthancPluginReceivedInstanceCallback& p = 
+      *reinterpret_cast<const _OrthancPluginReceivedInstanceCallback*>(parameters);
+
+    CLOG(INFO, PLUGINS) << "Plugin has registered a received instance callback";
+    pimpl_->receivedInstanceCallbacks_.push_back(p.callback);
+  }
 
   void OrthancPlugins::RegisterRefreshMetricsCallback(const void* parameters)
   {
@@ -5004,6 +5078,10 @@
         RegisterIncomingCStoreInstanceFilter(parameters);
         return true;
 
+      case _OrthancPluginService_RegisterReceivedInstanceCallback:
+        RegisterReceivedInstanceCallback(parameters);
+        return true;
+
       case _OrthancPluginService_RegisterRefreshMetricsCallback:
         RegisterRefreshMetricsCallback(parameters);
         return true;