changeset 6304:36cd91a53403

merged utf8-branch -> default
author Alain Mazy <am@orthanc.team>
date Tue, 09 Sep 2025 15:35:30 +0200
parents 88b7494557f2 (diff) a933e08efd7f (current diff)
children e6755569b9d2
files NEWS OrthancFramework/Sources/HttpServer/HttpServer.cpp
diffstat 4 files changed, 32 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri Sep 05 16:04:19 2025 +0200
+++ b/NEWS	Tue Sep 09 15:35:30 2025 +0200
@@ -6,7 +6,12 @@
 
 * Under Windows, the console output is now configured to interpret strings as UTF-8.
   This notably allow cyrillic strings to display correctly in the console.
-* Reworked all the paths handling improving general support of non ASCII-only paths on Windows.
+* Improved streaming of HTTP responses under OS pressure.  In some conditions, when the OS
+  was not able to send a full buffer over the network, Orthanc was not retrying 
+  to send the remaining part.  This is now fixed.  
+  (https://discourse.orthanc-server.org/t/incomplete-zip-downloads-from-get-studies-id-media/6046)
+* Reworked all the paths handling, improving general support of non ASCII-only paths on Windows,
+  specifically for the Storage directories and for the configuration files.
   However, on Windows, some features might still not support non ASCII-only paths:
   - Reading a DCMTK dictionary ("ExternalDictionaries" configuration)
   - Using a "TemporaryDirectory" to save zip file or to export DICOMDIR
--- a/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Fri Sep 05 16:04:19 2025 +0200
+++ b/OrthancFramework/Sources/DicomFormat/DicomMap.cpp	Tue Sep 09 15:35:30 2025 +0200
@@ -258,6 +258,16 @@
         throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined", false);
       }
 
+      if (level == ResourceType_Study) // all patients main dicom tags are also copied at study level
+      {
+        std::set<DicomTag>& patientLevelTags = GetMainDicomTagsByLevelInternal(ResourceType_Patient);
+        
+        if (patientLevelTags.find(tag) != patientLevelTags.end())
+        {
+          throw OrthancException(ErrorCode_MainDicomTagsMultiplyDefined, tag.Format() + " is already defined", false);
+        }
+      }
+
       existingLevelTags.insert(tag);
       allMainDicomTags_.insert(tag);
 
--- a/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Fri Sep 05 16:04:19 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/HttpOutput.cpp	Tue Sep 09 15:35:30 2025 +0200
@@ -805,6 +805,8 @@
   void HttpOutput::StateMachine::SendStreamItem(const void* data,
                                                 size_t size)
   {
+    LOG(TRACE) << "SendStreamItem " << size << " bytes";
+
     if (state_ != State_WritingStream)
     {
       throw OrthancException(ErrorCode_BadSequenceOfCalls);
@@ -821,6 +823,8 @@
 
   void HttpOutput::StateMachine::CloseStream()
   {
+    LOG(TRACE) << "CloseStream";
+    
     if (state_ != State_WritingStream)
     {
       throw OrthancException(ErrorCode_BadSequenceOfCalls);
--- a/OrthancFramework/Sources/HttpServer/HttpServer.cpp	Fri Sep 05 16:04:19 2025 +0200
+++ b/OrthancFramework/Sources/HttpServer/HttpServer.cpp	Tue Sep 09 15:35:30 2025 +0200
@@ -120,12 +120,19 @@
           {
             size_t packetSize = std::min(remainingSize, static_cast<size_t>(INT_MAX));
 
-            int status = mg_write(connection_, &(reinterpret_cast<const char*>(buffer)[offset]), packetSize);  
+            // note: mg_write may sometimes only send a part of the buffer e.g. when the OS is not able to send the full buffer -> we might need to iterate a few times
+            size_t totalSent = 0;
+            while (totalSent < packetSize)
+            {
+              int status = mg_write(connection_, &(reinterpret_cast<const char*>(buffer)[offset + totalSent]), packetSize - totalSent);
 
-            if (status != static_cast<int>(packetSize))
-            {
-              // status == 0 when the connection has been closed, -1 on error
-              throw OrthancException(ErrorCode_NetworkProtocol);
+              if (status <= 0)
+              {
+                // status == 0 when the connection has been closed, -1 on error
+                throw OrthancException(ErrorCode_NetworkProtocol);
+              }
+
+              totalSent += status;
             }
 
             offset += packetSize;