changeset 1164:0a55d8eb194e

Configuration/Lua to select the accepted C-Store SCP transfer syntaxes
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 18 Sep 2014 17:18:26 +0200
parents 3db41779d8f9
children 0561f2087cc9
files NEWS OrthancServer/DicomProtocol/IApplicationEntityFilter.h OrthancServer/Internals/CommandDispatcher.cpp OrthancServer/main.cpp Resources/Configuration.json Resources/DicomConformanceStatement.txt Resources/Samples/Lua/TransferSyntaxDisable.lua Resources/Samples/Lua/TransferSyntaxEnable.lua
diffstat 8 files changed, 148 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Sep 17 17:23:08 2014 +0200
+++ b/NEWS	Thu Sep 18 17:18:26 2014 +0200
@@ -1,6 +1,7 @@
 Pending changes in the mainline
 ===============================
 
+* Configuration/Lua to select the accepted C-Store SCP transfer syntaxes
 * Installation of plugin SDK in CMake
 
 
--- a/OrthancServer/DicomProtocol/IApplicationEntityFilter.h	Wed Sep 17 17:23:08 2014 +0200
+++ b/OrthancServer/DicomProtocol/IApplicationEntityFilter.h	Thu Sep 18 17:18:26 2014 +0200
@@ -52,7 +52,8 @@
                                   const std::string& callingAet,
                                   DicomRequestType type) = 0;
 
-    virtual bool IsAllowedTransferSyntax(const std::string& callingAet,
+    virtual bool IsAllowedTransferSyntax(const std::string& callingIp,
+                                         const std::string& callingAet,
                                          TransferSyntax syntax) = 0;
   };
 }
--- a/OrthancServer/Internals/CommandDispatcher.cpp	Wed Sep 17 17:23:08 2014 +0200
+++ b/OrthancServer/Internals/CommandDispatcher.cpp	Thu Sep 18 17:18:26 2014 +0200
@@ -461,16 +461,16 @@
 
       // Retrieve the AET and the IP address of the remote modality
       std::string callingAet;
-      std::string callingIP;
+      std::string callingIp;
       std::string calledAet;
   
       {
         DIC_AE callingAet_C;
         DIC_AE calledAet_C;
-        DIC_AE callingIP_C;
+        DIC_AE callingIp_C;
         DIC_AE calledIP_C;
         if (ASC_getAPTitles(assoc->params, callingAet_C, calledAet_C, NULL).bad() ||
-            ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad())
+            ASC_getPresentationAddresses(assoc->params, callingIp_C, calledIP_C).bad())
         {
           T_ASC_RejectParameters rej =
             {
@@ -483,13 +483,13 @@
           return NULL;
         }
 
-        callingIP = std::string(/*OFSTRING_GUARD*/(callingIP_C));
+        callingIp = std::string(/*OFSTRING_GUARD*/(callingIp_C));
         callingAet = std::string(/*OFSTRING_GUARD*/(callingAet_C));
         calledAet = (/*OFSTRING_GUARD*/(calledAet_C));
       }
 
       LOG(INFO) << "Association Received from AET " << callingAet 
-                << " on IP " << callingIP;
+                << " on IP " << callingIp;
 
 
       std::vector<const char*> transferSyntaxes;
@@ -501,13 +501,13 @@
 
       // New transfer syntaxes supported since Orthanc 0.7.2
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Deflated))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_Deflated))
       {
         transferSyntaxes.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); 
       }
 
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpeg))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_Jpeg))
       {
         transferSyntaxes.push_back(UID_JPEGProcess1TransferSyntax);
         transferSyntaxes.push_back(UID_JPEGProcess2_4TransferSyntax);
@@ -532,14 +532,14 @@
       }
 
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpeg2000))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_Jpeg2000))
       {
         transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax);
         transferSyntaxes.push_back(UID_JPEG2000TransferSyntax);
       }
 
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_JpegLossless))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_JpegLossless))
       {
         transferSyntaxes.push_back(UID_JPEG2000LosslessOnlyTransferSyntax);
         transferSyntaxes.push_back(UID_JPEG2000TransferSyntax);
@@ -548,21 +548,21 @@
       }
 
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Jpip))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_Jpip))
       {
         transferSyntaxes.push_back(UID_JPIPReferencedTransferSyntax);
         transferSyntaxes.push_back(UID_JPIPReferencedDeflateTransferSyntax);
       }
 
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Mpeg2))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_Mpeg2))
       {
         transferSyntaxes.push_back(UID_MPEG2MainProfileAtMainLevelTransferSyntax);
         transferSyntaxes.push_back(UID_MPEG2MainProfileAtHighLevelTransferSyntax);
       }
 
       if (!server.HasApplicationEntityFilter() ||
-          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingAet, TransferSyntax_Rle))
+          server.GetApplicationEntityFilter().IsAllowedTransferSyntax(callingIp, callingAet, TransferSyntax_Rle))
       {
         transferSyntaxes.push_back(UID_RLELosslessTransferSyntax);
       }
@@ -638,9 +638,9 @@
       }
 
       if (server.HasApplicationEntityFilter() &&
-          !server.GetApplicationEntityFilter().IsAllowedConnection(callingIP, callingAet))
+          !server.GetApplicationEntityFilter().IsAllowedConnection(callingIp, callingAet))
       {
-        LOG(WARNING) << "Rejected association for remote AET " << callingAet << " on IP " << callingIP;
+        LOG(WARNING) << "Rejected association for remote AET " << callingAet << " on IP " << callingIp;
         T_ASC_RejectParameters rej =
           {
             ASC_RESULT_REJECTEDPERMANENT,
@@ -687,7 +687,7 @@
       }
 
       IApplicationEntityFilter* filter = server.HasApplicationEntityFilter() ? &server.GetApplicationEntityFilter() : NULL;
-      return new CommandDispatcher(server, assoc, callingIP, callingAet, filter);
+      return new CommandDispatcher(server, assoc, callingIp, callingAet, filter);
     }
 
     bool CommandDispatcher::Step()
--- a/OrthancServer/main.cpp	Wed Sep 17 17:23:08 2014 +0200
+++ b/OrthancServer/main.cpp	Thu Sep 18 17:18:26 2014 +0200
@@ -150,7 +150,14 @@
 
 class OrthancApplicationEntityFilter : public IApplicationEntityFilter
 {
+private:
+  ServerContext& context_;
+
 public:
+  OrthancApplicationEntityFilter(ServerContext& context) : context_(context)
+  {
+  }
+
   virtual bool IsAllowedConnection(const std::string& /*callingIp*/,
                                    const std::string& /*callingAet*/)
   {
@@ -178,11 +185,61 @@
     }
   }
 
-  virtual bool IsAllowedTransferSyntax(const std::string& callingAet,
+  virtual bool IsAllowedTransferSyntax(const std::string& callingIp,
+                                       const std::string& callingAet,
                                        TransferSyntax syntax)
   {
-    // TODO - https://trello.com/c/8GxcTR0n
-    return true;
+    std::string configuration;
+
+    switch (syntax)
+    {
+      case TransferSyntax_Deflated:
+        configuration = "DeflatedTransferSyntaxAccepted";
+        break;
+
+      case TransferSyntax_Jpeg:
+        configuration = "JpegTransferSyntaxAccepted";
+        break;
+
+      case TransferSyntax_Jpeg2000:
+        configuration = "Jpeg2000TransferSyntaxAccepted";
+        break;
+
+      case TransferSyntax_JpegLossless:
+        configuration = "JpegLosslessTransferSyntaxAccepted";
+        break;
+
+      case TransferSyntax_Jpip:
+        configuration = "JpipTransferSyntaxAccepted";
+        break;
+
+      case TransferSyntax_Mpeg2:
+        configuration = "Mpeg2TransferSyntaxAccepted";
+        break;
+
+      case TransferSyntax_Rle:
+        configuration = "RleTransferSyntaxAccepted";
+        break;
+
+      default: 
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+
+    {
+      std::string lua = "Is" + configuration;
+
+      ServerContext::LuaContextLocker locker(context_);
+      
+      if (locker.GetLua().IsExistingFunction(lua.c_str()))
+      {
+        LuaFunctionCall call(locker.GetLua(), lua.c_str());
+        call.PushString(callingAet);
+        call.PushString(callingIp);
+        return call.ExecutePredicate();
+      }
+    }
+
+    return Configuration::GetGlobalBoolParameter(configuration, true);
   }
 };
 
@@ -412,7 +469,7 @@
   {
     // DICOM server
     DicomServer dicomServer;
-    OrthancApplicationEntityFilter dicomFilter;
+    OrthancApplicationEntityFilter dicomFilter(context);
     dicomServer.SetCalledApplicationEntityTitleCheck(Configuration::GetGlobalBoolParameter("DicomCheckCalledAet", false));
     dicomServer.SetStoreRequestHandlerFactory(serverFactory);
     dicomServer.SetMoveRequestHandlerFactory(serverFactory);
--- a/Resources/Configuration.json	Wed Sep 17 17:23:08 2014 +0200
+++ b/Resources/Configuration.json	Thu Sep 18 17:18:26 2014 +0200
@@ -69,6 +69,14 @@
   // and "Chinese".
   "DefaultEncoding" : "Latin1",
 
+  // The transfer syntaxes that are accepted by Orthanc C-Store SCP
+  "DeflatedTransferSyntaxAccepted"     : true,
+  "JpegTransferSyntaxAccepted"         : true,
+  "Jpeg2000TransferSyntaxAccepted"     : true,
+  "JpegLosslessTransferSyntaxAccepted" : true,
+  "JpipTransferSyntaxAccepted"         : true,
+  "Mpeg2TransferSyntaxAccepted"        : true,
+  "RleTransferSyntaxAccepted"          : true,
 
 
   /**
--- a/Resources/DicomConformanceStatement.txt	Wed Sep 17 17:23:08 2014 +0200
+++ b/Resources/DicomConformanceStatement.txt	Thu Sep 18 17:18:26 2014 +0200
@@ -231,6 +231,9 @@
   MPEG2MainProfileAtHighLevelTransferSyntax                             | 1.2.840.10008.1.2.4.101
   RLELosslessTransferSyntax                                             | 1.2.840.10008.1.2.5
 
+It is possible to disable a subset of these transfer syntaxes thanks to the
+"*TransferSyntaxAccepted" options in the Orthanc configuration file.
+
 When possible, Orthanc will prefer the
 LittleEndianImplicitTransferSyntax transfer syntax
 (1.2.840.10008.1.2).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/Lua/TransferSyntaxDisable.lua	Thu Sep 18 17:18:26 2014 +0200
@@ -0,0 +1,29 @@
+function IsDeflatedTransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+function IsJpegTransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+function IsJpeg2000TransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+function IsJpegLosslessTransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+function IsJpipTransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+function IsMpeg2TransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+function IsRleTransferSyntaxAccepted(aet, ip)
+   return false
+end
+
+print('All special transfer syntaxes are now disallowed')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/Lua/TransferSyntaxEnable.lua	Thu Sep 18 17:18:26 2014 +0200
@@ -0,0 +1,29 @@
+function IsDeflatedTransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+function IsJpegTransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+function IsJpeg2000TransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+function IsJpegLosslessTransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+function IsJpipTransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+function IsMpeg2TransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+function IsRleTransferSyntaxAccepted(aet, ip)
+   return true
+end
+
+print('All special transfer syntaxes are now accepted')