changeset 5438:7a20ee948676 debug-telemis

Added a new 'Telemis' manufacturer for DicomModalities
author Alain Mazy <am@osimis.io>
date Wed, 22 Nov 2023 12:57:07 +0100
parents 85da6dcd0e08
children 54b717b1d27e
files NEWS OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.h OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.cpp OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h OrthancFramework/Sources/Enumerations.cpp OrthancFramework/Sources/Enumerations.h OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/ServerContext.cpp
diffstat 9 files changed, 60 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Wed Nov 22 09:39:35 2023 +0100
+++ b/NEWS	Wed Nov 22 12:57:07 2023 +0100
@@ -63,6 +63,8 @@
   https://discourse.orthanc-server.org/t/c-find-fails-on-unknown-specific-character-set-iso-2022-ir-6-iso-2022-ir-100/3947
 * When exporting a study archive, make sure to use the PatientName from the study and not from the patient
   in case of PatientID collision.
+* Added a new 'Telemis' manufacturer for DicomModalities.  This forces a new DICOM renegociation in case the
+  SopClassUid+TransferSyntax was rejected in the current association.
 * Upgraded dependencies for static builds:
   - boost 1.83.0
 * Upgraded minizip library to stay away from CVE-2023-45853 although Orthanc is likely not affected since zip
--- a/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp	Wed Nov 22 12:57:07 2023 +0100
@@ -253,7 +253,8 @@
     const std::string& sopClassUid,
     DicomTransferSyntax transferSyntax,
     bool hasPreferred,
-    DicomTransferSyntax preferred)
+    DicomTransferSyntax preferred,
+    bool alwaysRenegotiate)
   {
     /**
      * Step 1: Check whether this presentation context is already
@@ -273,8 +274,8 @@
 
       // Don't renegociate if we know that the remote modality was
       // already proposed this individual transfer syntax (**)
-      if (proposedOriginalClasses_.find(std::make_pair(sopClassUid, transferSyntax)) !=
-          proposedOriginalClasses_.end())
+      if (!alwaysRenegotiate &&
+          proposedOriginalClasses_.find(std::make_pair(sopClassUid, transferSyntax)) != proposedOriginalClasses_.end())
       {
         CLOG(INFO, DICOM) << "The remote modality has already rejected SOP class UID \""
                           << sopClassUid << "\" with transfer syntax \""
@@ -369,14 +370,15 @@
                                        DcmFileFormat& dicom,
                                        bool hasMoveOriginator,
                                        const std::string& moveOriginatorAET,
-                                       uint16_t moveOriginatorID)
+                                       uint16_t moveOriginatorID,
+                                       bool alwaysRenegotiate)
   {
     DicomTransferSyntax transferSyntax;
     LookupParameters(sopClassUid, sopInstanceUid, transferSyntax, dicom);
 
     uint8_t presID;
     if (!NegotiatePresentationContext(presID, sopClassUid, transferSyntax, proposeUncompressedSyntaxes_,
-                                      DicomTransferSyntax_LittleEndianExplicit))
+                                      DicomTransferSyntax_LittleEndianExplicit, alwaysRenegotiate))
     {
       throw OrthancException(ErrorCode_NetworkProtocol,
                              "No valid presentation context was negotiated for "
@@ -458,7 +460,8 @@
                                        size_t size,
                                        bool hasMoveOriginator,
                                        const std::string& moveOriginatorAET,
-                                       uint16_t moveOriginatorID)
+                                       uint16_t moveOriginatorID,
+                                       bool alwaysRenegotiate)
   {
     std::unique_ptr<DcmFileFormat> dicom(
       FromDcmtkBridge::LoadFromMemoryBuffer(buffer, size));
@@ -468,7 +471,7 @@
       throw OrthancException(ErrorCode_InternalError);
     }
     
-    Store(sopClassUid, sopInstanceUid, *dicom, hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+    Store(sopClassUid, sopInstanceUid, *dicom, hasMoveOriginator, moveOriginatorAET, moveOriginatorID, alwaysRenegotiate);
   }
 
 
@@ -477,7 +480,8 @@
                                                    const std::string& sopClassUid,
                                                    DicomTransferSyntax sourceSyntax,
                                                    bool hasPreferred,
-                                                   DicomTransferSyntax preferred)
+                                                   DicomTransferSyntax preferred,
+                                                   bool alwaysRenegotiate)
   {
     acceptedSyntaxes.clear();
 
@@ -485,7 +489,7 @@
     // syntax. We don't use the return code: Transcoding is possible
     // even if the "sourceSyntax" is not supported.
     uint8_t presID;
-    NegotiatePresentationContext(presID, sopClassUid, sourceSyntax, hasPreferred, preferred);
+    NegotiatePresentationContext(presID, sopClassUid, sourceSyntax, hasPreferred, preferred, alwaysRenegotiate);
 
     std::map<DicomTransferSyntax, uint8_t> contexts;
     if (association_->LookupAcceptedPresentationContext(contexts, sopClassUid))
@@ -509,7 +513,8 @@
                                            DicomTransferSyntax preferredTransferSyntax,
                                            bool hasMoveOriginator,
                                            const std::string& moveOriginatorAET,
-                                           uint16_t moveOriginatorID)
+                                           uint16_t moveOriginatorID,
+                                           bool alwaysRenegotiate)
   {
     std::unique_ptr<DcmFileFormat> dicom(FromDcmtkBridge::LoadFromMemoryBuffer(buffer, size));
     if (dicom.get() == NULL ||
@@ -522,13 +527,13 @@
     LookupParameters(sopClassUid, sopInstanceUid, sourceSyntax, *dicom);
 
     std::set<DicomTransferSyntax> accepted;
-    LookupTranscoding(accepted, sopClassUid, sourceSyntax, true, preferredTransferSyntax);
+    LookupTranscoding(accepted, sopClassUid, sourceSyntax, true, preferredTransferSyntax, alwaysRenegotiate);
 
     if (accepted.find(sourceSyntax) != accepted.end())
     {
       // No need for transcoding
       Store(sopClassUid, sopInstanceUid, *dicom,
-            hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+            hasMoveOriginator, moveOriginatorAET, moveOriginatorID, alwaysRenegotiate);
     }
     else
     {
@@ -617,7 +622,7 @@
         else
         {
           Store(sopClassUid, sopInstanceUid, transcoded.GetParsed(),
-                hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+                hasMoveOriginator, moveOriginatorAET, moveOriginatorID, alwaysRenegotiate);
         }
       }
       else
@@ -646,10 +651,11 @@
                                            size_t size,
                                            bool hasMoveOriginator,
                                            const std::string& moveOriginatorAET,
-                                           uint16_t moveOriginatorID)
+                                           uint16_t moveOriginatorID,
+                                           bool alwaysRenegotiate)
   {
     Transcode(sopClassUid, sopInstanceUid, transcoder, buffer, size, DicomTransferSyntax_LittleEndianExplicit,
-              hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+              hasMoveOriginator, moveOriginatorAET, moveOriginatorID, alwaysRenegotiate);
   }
 #endif
 }
--- a/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.h	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.h	Wed Nov 22 12:57:07 2023 +0100
@@ -94,14 +94,16 @@
                                       const std::string& sopClassUid,
                                       DicomTransferSyntax transferSyntax,
                                       bool hasPreferred,
-                                      DicomTransferSyntax preferred);
+                                      DicomTransferSyntax preferred,
+                                      bool alwaysRenegotiate);
 
 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1
     void LookupTranscoding(std::set<DicomTransferSyntax>& acceptedSyntaxes,
                            const std::string& sopClassUid,
                            DicomTransferSyntax sourceSyntax,
                            bool hasPreferred,
-                           DicomTransferSyntax preferred);
+                           DicomTransferSyntax preferred,
+                           bool alwaysRenegotiate);
 #endif
 
   public:
@@ -129,7 +131,8 @@
                DcmFileFormat& dicom,
                bool hasMoveOriginator,
                const std::string& moveOriginatorAET,
-               uint16_t moveOriginatorID);
+               uint16_t moveOriginatorID,
+               bool alwaysRenegotiate);
 
     void Store(std::string& sopClassUid,
                std::string& sopInstanceUid,
@@ -137,7 +140,8 @@
                size_t size,
                bool hasMoveOriginator,
                const std::string& moveOriginatorAET,
-               uint16_t moveOriginatorID);
+               uint16_t moveOriginatorID,
+               bool alwaysRenegotiate);
 
     void LookupParameters(std::string& sopClassUid,
                           std::string& sopInstanceUid,
@@ -153,7 +157,8 @@
                    DicomTransferSyntax preferredTransferSyntax,
                    bool hasMoveOriginator,
                    const std::string& moveOriginatorAET,
-                   uint16_t moveOriginatorID);
+                   uint16_t moveOriginatorID,
+                   bool alwaysRenegotiate);
 #endif
     
 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1
@@ -164,7 +169,8 @@
                    size_t size,
                    bool hasMoveOriginator,
                    const std::string& moveOriginatorAET,
-                   uint16_t moveOriginatorID);
+                   uint16_t moveOriginatorID,
+                   bool alwaysRenegotiate);
 #endif
   };
 }
--- a/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.cpp	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.cpp	Wed Nov 22 12:57:07 2023 +0100
@@ -186,6 +186,11 @@
     manufacturer_ = StringToModalityManufacturer(manufacturer);
   }
 
+  bool RemoteModalityParameters::IsAlwaysRenegotiate() const
+  {
+    return manufacturer_ == ModalityManufacturer_Telemis;
+  }
+
 
   void RemoteModalityParameters::UnserializeArray(const Json::Value& serialized)
   {
--- a/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/RemoteModalityParameters.h	Wed Nov 22 12:57:07 2023 +0100
@@ -85,6 +85,8 @@
 
     void SetManufacturer(const std::string& manufacturer);
 
+    bool IsAlwaysRenegotiate() const;
+
     bool IsRequestAllowed(DicomRequestType type) const;
 
     void SetRequestAllowed(DicomRequestType type,
--- a/OrthancFramework/Sources/Enumerations.cpp	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancFramework/Sources/Enumerations.cpp	Wed Nov 22 12:57:07 2023 +0100
@@ -807,6 +807,9 @@
       case ModalityManufacturer_GE:
         return "GE";
       
+      case ModalityManufacturer_Telemis:
+        return "Telemis";
+
       default:
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
@@ -1586,6 +1589,10 @@
     {
       return ModalityManufacturer_GE;
     }
+    else if (manufacturer == "Telemis")
+    {
+      return ModalityManufacturer_Telemis;
+    }
     else if (manufacturer == "AgfaImpax" ||
              manufacturer == "SyngoVia")
     {
--- a/OrthancFramework/Sources/Enumerations.h	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancFramework/Sources/Enumerations.h	Wed Nov 22 12:57:07 2023 +0100
@@ -660,7 +660,8 @@
     ModalityManufacturer_GenericNoWildcardInDates,
     ModalityManufacturer_GenericNoUniversalWildcard,
     ModalityManufacturer_Vitrea,
-    ModalityManufacturer_GE
+    ModalityManufacturer_GE,
+    ModalityManufacturer_Telemis
   };
 
   enum DicomRequestType
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Wed Nov 22 12:57:07 2023 +0100
@@ -1520,7 +1520,10 @@
 
     std::string sopClassUid, sopInstanceUid;
     connection.Store(sopClassUid, sopInstanceUid, call.GetBodyData(),
-                     call.GetBodySize(), false /* Not a C-MOVE */, "", 0);
+                     call.GetBodySize(), 
+                     false /* Not a C-MOVE */, 
+                     "", 0, 
+                     false /* AlwaysRenegotiate: no need to renegotiate since there is only a single file*/);
 
     Json::Value answer = Json::objectValue;
     answer[SOP_CLASS_UID] = sopClassUid;
--- a/OrthancServer/Sources/ServerContext.cpp	Wed Nov 22 09:39:35 2023 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Wed Nov 22 12:57:07 2023 +0100
@@ -1952,17 +1952,18 @@
                                            uint16_t moveOriginatorId)
   {
     const void* data = dicom.empty() ? NULL : dicom.c_str();
-    
+    const RemoteModalityParameters& modality = connection.GetParameters().GetRemoteModality();
+
     if (!transcodeDicomProtocol_ ||
-        !connection.GetParameters().GetRemoteModality().IsTranscodingAllowed())
+        !modality.IsTranscodingAllowed())
     {
       connection.Store(sopClassUid, sopInstanceUid, data, dicom.size(),
-                       hasMoveOriginator, moveOriginatorAet, moveOriginatorId);
+                       hasMoveOriginator, moveOriginatorAet, moveOriginatorId, modality.IsAlwaysRenegotiate());
     }
     else
     {
       connection.Transcode(sopClassUid, sopInstanceUid, *this, data, dicom.size(), preferredTransferSyntax_,
-                           hasMoveOriginator, moveOriginatorAet, moveOriginatorId);
+                           hasMoveOriginator, moveOriginatorAet, moveOriginatorId, modality.IsAlwaysRenegotiate());
     }
   }