changeset 5911:bfae0fc2ea1b get-scu-test

Started to work on handling errors as warnings when trying to store instances whose SOPClassUID has not been accepted during the negotiation. Work to be finalized later
author Alain Mazy <am@orthanc.team>
date Mon, 09 Dec 2024 10:07:19 +0100
parents 866defb5f95a
children 641dad7eace2
files OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.h OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp OrthancServer/Sources/OrthancGetRequestHandler.cpp OrthancServer/Sources/OrthancMoveRequestHandler.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/ServerContext.cpp OrthancServer/Sources/ServerContext.h OrthancServer/Sources/ServerJobs/DicomModalityStoreJob.cpp OrthancServer/Sources/ServerJobs/Operations/StoreScuOperation.cpp
diffstat 10 files changed, 60 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -377,7 +377,8 @@
                                        DcmFileFormat& dicom,
                                        bool hasMoveOriginator,
                                        const std::string& moveOriginatorAET,
-                                       uint16_t moveOriginatorID)
+                                       uint16_t moveOriginatorID,
+                                       bool ignoreErrors)
   {
     DicomTransferSyntax transferSyntax;
     LookupParameters(sopClassUid, sopInstanceUid, transferSyntax, dicom);
@@ -388,12 +389,21 @@
     if (!NegotiatePresentationContext(presID, sopClassUid, transferSyntax, proposeUncompressedSyntaxes_,
                                       DicomTransferSyntax_LittleEndianExplicit))
     {
-      throw OrthancException(ErrorCode_NetworkProtocol,
-                             "No valid presentation context was negotiated for "
-                             "SOP class UID [" + sopClassUid + "] and transfer "
-                             "syntax [" + GetTransferSyntaxUid(transferSyntax) + "] "
-                             "while sending to modality [" +
-                             parameters_.GetRemoteModality().GetApplicationEntityTitle() + "]");
+      if (ignoreErrors)
+      {
+        LOG(INFO) << "No valid presentation context was negotiated for SOP class UID [" << sopClassUid << "] and transfer "
+                      "syntax [" << GetTransferSyntaxUid(transferSyntax) << "] "
+                      "while sending to modality [" << parameters_.GetRemoteModality().GetApplicationEntityTitle() << "]";
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_NetworkProtocol,
+                              "No valid presentation context was negotiated for "
+                              "SOP class UID [" + sopClassUid + "] and transfer "
+                              "syntax [" + GetTransferSyntaxUid(transferSyntax) + "] "
+                              "while sending to modality [" +
+                              parameters_.GetRemoteModality().GetApplicationEntityTitle() + "]");
+      }
     }
     
     // Prepare the transmission of data
@@ -469,7 +479,8 @@
                                        size_t size,
                                        bool hasMoveOriginator,
                                        const std::string& moveOriginatorAET,
-                                       uint16_t moveOriginatorID)
+                                       uint16_t moveOriginatorID,
+                                       bool ignoreErrors)
   {
     std::unique_ptr<DcmFileFormat> dicom(
       FromDcmtkBridge::LoadFromMemoryBuffer(buffer, size));
@@ -479,7 +490,7 @@
       throw OrthancException(ErrorCode_InternalError);
     }
     
-    Store(sopClassUid, sopInstanceUid, *dicom, hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+    Store(sopClassUid, sopInstanceUid, *dicom, hasMoveOriginator, moveOriginatorAET, moveOriginatorID, ignoreErrors);
   }
 
 
@@ -523,7 +534,8 @@
                                            DicomTransferSyntax preferredTransferSyntax,
                                            bool hasMoveOriginator,
                                            const std::string& moveOriginatorAET,
-                                           uint16_t moveOriginatorID)
+                                           uint16_t moveOriginatorID,
+                                           bool ignoreErrors)
   {
     std::unique_ptr<DcmFileFormat> dicom(FromDcmtkBridge::LoadFromMemoryBuffer(buffer, size));
     if (dicom.get() == NULL ||
@@ -540,15 +552,24 @@
 
     if (accepted.size() == 0)
     {
-      throw OrthancException(ErrorCode_NoPresentationContext, "Cannot C-Store an instance of SOPClassUID " + 
-                             sopClassUid + ", the destination has not accepted any TransferSyntax for this SOPClassUID.");
+      if (ignoreErrors)
+      {
+        LOG(WARNING) << "Cannot C-Store an instance of SOPClassUID " << 
+                      sopClassUid + ", the destination has not accepted any TransferSyntax for this SOPClassUID.";  // TODO: add an option to enable/disable this warning
+        return;
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_NoPresentationContext, "Cannot C-Store an instance of SOPClassUID " + 
+                               sopClassUid + ", the destination has not accepted any TransferSyntax for this SOPClassUID.");
+      }
     }
 
     if (accepted.find(sourceSyntax) != accepted.end())
     {
       // No need for transcoding
       Store(sopClassUid, sopInstanceUid, *dicom,
-            hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+            hasMoveOriginator, moveOriginatorAET, moveOriginatorID, ignoreErrors);
     }
     else
     {
@@ -639,7 +660,7 @@
         else
         {
           Store(sopClassUid, sopInstanceUid, transcoded.GetParsed(),
-                hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+                hasMoveOriginator, moveOriginatorAET, moveOriginatorID, ignoreErrors);
         }
       }
       else
@@ -669,10 +690,11 @@
                                            size_t size,
                                            bool hasMoveOriginator,
                                            const std::string& moveOriginatorAET,
-                                           uint16_t moveOriginatorID)
+                                           uint16_t moveOriginatorID,
+                                           bool ignoreErrors)
   {
     Transcode(sopClassUid, sopInstanceUid, transcoder, buffer, size, DicomTransferSyntax_LittleEndianExplicit,
-              hasMoveOriginator, moveOriginatorAET, moveOriginatorID);
+              hasMoveOriginator, moveOriginatorAET, moveOriginatorID, ignoreErrors);
   }
 #endif
 }
--- a/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.h	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/DicomStoreUserConnection.h	Mon Dec 09 10:07:19 2024 +0100
@@ -130,7 +130,8 @@
                DcmFileFormat& dicom,
                bool hasMoveOriginator,
                const std::string& moveOriginatorAET,
-               uint16_t moveOriginatorID);
+               uint16_t moveOriginatorID,
+               bool ignoreErrors);
 
     void Store(std::string& sopClassUid,
                std::string& sopInstanceUid,
@@ -138,7 +139,8 @@
                size_t size,
                bool hasMoveOriginator,
                const std::string& moveOriginatorAET,
-               uint16_t moveOriginatorID);
+               uint16_t moveOriginatorID,
+               bool ignoreErrors);
 
     void LookupParameters(std::string& sopClassUid,
                           std::string& sopInstanceUid,
@@ -154,7 +156,8 @@
                    DicomTransferSyntax preferredTransferSyntax,
                    bool hasMoveOriginator,
                    const std::string& moveOriginatorAET,
-                   uint16_t moveOriginatorID);
+                   uint16_t moveOriginatorID,
+                   bool errorsAsWarning);
 #endif
     
 #if ORTHANC_ENABLE_DCMTK_TRANSCODING == 1
@@ -165,7 +168,8 @@
                    size_t size,
                    bool hasMoveOriginator,
                    const std::string& moveOriginatorAET,
-                   uint16_t moveOriginatorID);
+                   uint16_t moveOriginatorID,
+                   bool errorsAsWarning);
 #endif
   };
 }
--- a/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancFramework/UnitTestsSources/FromDcmtkTests.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -3583,7 +3583,7 @@
         try
         {
           scu.Transcode(c, k, transcoder, source.c_str(), source.size(),
-                        DicomTransferSyntax_LittleEndianExplicit, false, "", 0);
+                        DicomTransferSyntax_LittleEndianExplicit, false, "", 0, false);
         }
         catch (OrthancException& e)
         {
--- a/OrthancServer/Sources/OrthancGetRequestHandler.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/OrthancGetRequestHandler.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -250,10 +250,9 @@
     {
       failedCount_++;
       AddFailedUIDInstance(sopInstanceUid);
-      throw OrthancException(ErrorCode_NetworkProtocol,
-                             "C-GET SCP: storeSCU: No presentation context for: (" +
-                             std::string(dcmSOPClassUIDToModality(sopClassUid.c_str(), "OT")) +
-                             ") " + sopClassUid);
+      LOG(WARNING) << "C-GET SCP: storeSCU: No presentation context for: (" 
+                   << dcmSOPClassUIDToModality(sopClassUid.c_str(), "OT") << ") " << sopClassUid;
+      return true;
     }
     else
     {
--- a/OrthancServer/Sources/OrthancMoveRequestHandler.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/OrthancMoveRequestHandler.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -110,7 +110,7 @@
 
         std::string sopClassUid, sopInstanceUid;  // Unused
         context_.StoreWithTranscoding(sopClassUid, sopInstanceUid, *connection_, dicom,
-                                      true, originatorAet_, originatorId_);
+                                      true, originatorAet_, originatorId_, false); // TODO: ignoreErrors
 
         return Status_Success;
       }
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -1577,7 +1577,7 @@
     connection.Store(sopClassUid, sopInstanceUid, call.GetBodyData(),
                      call.GetBodySize(), 
                      false /* Not a C-MOVE */, 
-                     "", 0);
+                     "", 0, false);
 
     Json::Value answer = Json::objectValue;
     answer[SOP_CLASS_UID] = sopClassUid;
--- a/OrthancServer/Sources/ServerContext.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/ServerContext.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -2007,7 +2007,8 @@
                                            const std::string& dicom,
                                            bool hasMoveOriginator,
                                            const std::string& moveOriginatorAet,
-                                           uint16_t moveOriginatorId)
+                                           uint16_t moveOriginatorId,
+                                           bool ignoreErrors)
   {
     const void* data = dicom.empty() ? NULL : dicom.c_str();
     const RemoteModalityParameters& modality = connection.GetParameters().GetRemoteModality();
@@ -2016,12 +2017,12 @@
         !modality.IsTranscodingAllowed())
     {
       connection.Store(sopClassUid, sopInstanceUid, data, dicom.size(),
-                       hasMoveOriginator, moveOriginatorAet, moveOriginatorId);
+                       hasMoveOriginator, moveOriginatorAet, moveOriginatorId, ignoreErrors);
     }
     else
     {
       connection.Transcode(sopClassUid, sopInstanceUid, *this, data, dicom.size(), preferredTransferSyntax_,
-                           hasMoveOriginator, moveOriginatorAet, moveOriginatorId);
+                           hasMoveOriginator, moveOriginatorAet, moveOriginatorId, ignoreErrors);
     }
   }
 
--- a/OrthancServer/Sources/ServerContext.h	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/ServerContext.h	Mon Dec 09 10:07:19 2024 +0100
@@ -577,7 +577,8 @@
                               const std::string& dicom,
                               bool hasMoveOriginator,
                               const std::string& moveOriginatorAet,
-                              uint16_t moveOriginatorId);
+                              uint16_t moveOriginatorId,
+                              bool ignoreErrors);
 
     // This method can be used even if the global option
     // "TranscodeDicomProtocol" is set to "false"
--- a/OrthancServer/Sources/ServerJobs/DicomModalityStoreJob.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/ServerJobs/DicomModalityStoreJob.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -65,7 +65,7 @@
 
     std::string sopClassUid, sopInstanceUid;
     context_.StoreWithTranscoding(sopClassUid, sopInstanceUid, *connection_, dicom,
-                                  HasMoveOriginator(), moveOriginatorAet_, moveOriginatorId_);
+                                  HasMoveOriginator(), moveOriginatorAet_, moveOriginatorId_, IsPermissive());
 
     if (storageCommitment_)
     {
--- a/OrthancServer/Sources/ServerJobs/Operations/StoreScuOperation.cpp	Mon Dec 09 10:04:34 2024 +0100
+++ b/OrthancServer/Sources/ServerJobs/Operations/StoreScuOperation.cpp	Mon Dec 09 10:07:19 2024 +0100
@@ -56,7 +56,7 @@
 
       std::string sopClassUid, sopInstanceUid;  // Unused
       context_.StoreWithTranscoding(sopClassUid, sopInstanceUid, lock.GetConnection(), dicom,
-                                    false /* Not a C-MOVE */, "", 0);
+                                    false /* Not a C-MOVE */, "", 0, false);  // TODO: get "permissive from job"
     }
     catch (OrthancException& e)
     {