# HG changeset patch # User Sebastien Jodogne # Date 1439368990 -7200 # Node ID 096a8af528c9c174516f56d8c8fd7eef143fbf8c # Parent f9b0169eb6bbbba77c09c37b8dae14b6cd3b613d fix streams, initialization/finalization of libcurl and openssl diff -r f9b0169eb6bb -r 096a8af528c9 Core/HttpServer/HttpStreamTranscoder.cpp --- a/Core/HttpServer/HttpStreamTranscoder.cpp Tue Aug 11 17:50:38 2015 +0200 +++ b/Core/HttpServer/HttpStreamTranscoder.cpp Wed Aug 12 10:43:10 2015 +0200 @@ -39,8 +39,6 @@ #include // For memcpy() #include -#include - namespace Orthanc { void HttpStreamTranscoder::ReadSource(std::string& buffer) @@ -73,50 +71,59 @@ } + HttpCompression HttpStreamTranscoder::SetupZlibCompression(bool deflateAllowed) + { + uint64_t size = source_.GetContentLength(); + + if (size == 0) + { + return HttpCompression_None; + } + + if (size < sizeof(uint64_t)) + { + throw OrthancException(ErrorCode_CorruptedFile); + } + + if (deflateAllowed) + { + bytesToSkip_ = sizeof(uint64_t); + + return HttpCompression_Deflate; + } + else + { + // TODO Use stream-based zlib decoding to reduce memory usage + std::string compressed; + ReadSource(compressed); + + uncompressed_.reset(new BufferHttpSender); + + ZlibCompressor compressor; + IBufferCompressor::Uncompress(uncompressed_->GetBuffer(), compressor, compressed); + + return HttpCompression_None; + } + } + + HttpCompression HttpStreamTranscoder::SetupHttpCompression(bool gzipAllowed, bool deflateAllowed) { + if (ready_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + + ready_ = true; + switch (sourceCompression_) { case CompressionType_None: - { return HttpCompression_None; - } case CompressionType_ZlibWithSize: - { - uint64_t size = source_.GetContentLength(); - - if (size == 0) - { - return HttpCompression_None; - } - - if (size < sizeof(uint64_t)) - { - throw OrthancException(ErrorCode_CorruptedFile); - } - - if (deflateAllowed) - { - bytesToSkip_ = sizeof(uint64_t); - return HttpCompression_Deflate; - } - else - { - std::string compressed; - ReadSource(compressed); - - uncompressed_.reset(new BufferHttpSender); - - ZlibCompressor compressor; - IBufferCompressor::Uncompress(uncompressed_->GetBuffer(), compressor, compressed); - - return HttpCompression_None; - } - - break; - } + return SetupZlibCompression(deflateAllowed); default: throw OrthancException(ErrorCode_NotImplemented); @@ -126,6 +133,11 @@ uint64_t HttpStreamTranscoder::GetContentLength() { + if (!ready_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + if (uncompressed_.get() != NULL) { return uncompressed_->GetContentLength(); @@ -145,6 +157,11 @@ bool HttpStreamTranscoder::ReadNextChunk() { + if (!ready_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + if (uncompressed_.get() != NULL) { return uncompressed_->ReadNextChunk(); @@ -162,7 +179,6 @@ for (;;) { assert(skipped_ < bytesToSkip_); - printf("[%d %d] ", skipped_, bytesToSkip_); fflush(stdout); bool ok = source_.ReadNextChunk(); if (!ok) @@ -182,14 +198,13 @@ // We have skipped enough bytes, but we must read a new chunk currentChunkOffset_ = 0; skipped_ = bytesToSkip_; - return source_.GetChunkSize(); + return source_.ReadNextChunk(); } else { + // We have skipped enough bytes, and we have enough data in the current chunk assert(s > remaining); - - // We have skipped enough bytes, and we have enough data in the current chunk - currentChunkOffset_ = s - remaining; + currentChunkOffset_ = remaining; skipped_ = bytesToSkip_; return true; } @@ -199,6 +214,11 @@ const char* HttpStreamTranscoder::GetChunkContent() { + if (!ready_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + if (uncompressed_.get() != NULL) { return uncompressed_->GetChunkContent(); @@ -211,6 +231,11 @@ size_t HttpStreamTranscoder::GetChunkSize() { + if (!ready_) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + if (uncompressed_.get() != NULL) { return uncompressed_->GetChunkSize(); diff -r f9b0169eb6bb -r 096a8af528c9 Core/HttpServer/HttpStreamTranscoder.h --- a/Core/HttpServer/HttpStreamTranscoder.h Tue Aug 11 17:50:38 2015 +0200 +++ b/Core/HttpServer/HttpStreamTranscoder.h Wed Aug 12 10:43:10 2015 +0200 @@ -46,18 +46,22 @@ uint64_t bytesToSkip_; uint64_t skipped_; uint64_t currentChunkOffset_; + bool ready_; std::auto_ptr uncompressed_; void ReadSource(std::string& buffer); + HttpCompression SetupZlibCompression(bool deflateAllowed); + public: HttpStreamTranscoder(IHttpStreamAnswer& source, CompressionType compression) : source_(source), sourceCompression_(compression), bytesToSkip_(0), - skipped_(0) + skipped_(0), + ready_(false) { } diff -r f9b0169eb6bb -r 096a8af528c9 OrthancServer/OrthancInitialization.cpp --- a/OrthancServer/OrthancInitialization.cpp Tue Aug 11 17:50:38 2015 +0200 +++ b/OrthancServer/OrthancInitialization.cpp Wed Aug 12 10:43:10 2015 +0200 @@ -49,6 +49,16 @@ #include +#if ORTHANC_SSL_ENABLED == 1 +// For OpenSSL initialization and finalization +#include +#include +#include +#include +#include +#endif + + #if ORTHANC_JPEG_ENABLED == 1 #include #endif @@ -259,6 +269,18 @@ { boost::mutex::scoped_lock lock(globalMutex_); +#if ORTHANC_SSL_ENABLED == 1 + // https://wiki.openssl.org/index.php/Library_Initialization + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + curl_global_init(CURL_GLOBAL_ALL); +#else + curl_global_init(CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL); +#endif + InitializeServerEnumerations(); // Read the user-provided configuration @@ -298,6 +320,20 @@ // Unregister JPEG codecs DJDecoderRegistration::cleanup(); #endif + + curl_global_cleanup(); + +#if ORTHANC_SSL_ENABLED == 1 + // Finalize OpenSSL + // https://wiki.openssl.org/index.php/Library_Initialization#Cleanup + FIPS_mode_set(0); + ENGINE_cleanup(); + CONF_modules_unload(1); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_state(0); + ERR_free_strings(); +#endif } diff -r f9b0169eb6bb -r 096a8af528c9 UnitTestsSources/StreamTests.cpp --- a/UnitTestsSources/StreamTests.cpp Tue Aug 11 17:50:38 2015 +0200 +++ b/UnitTestsSources/StreamTests.cpp Wed Aug 12 10:43:10 2015 +0200 @@ -181,9 +181,9 @@ bool allowGzip = false, bool allowDeflate = false) { - result.resize(stream.GetContentLength()); + stream.SetupHttpCompression(allowGzip, allowDeflate); - stream.SetupHttpCompression(allowGzip, allowDeflate); + result.resize(stream.GetContentLength()); size_t pos = 0; while (stream.ReadNextChunk()) @@ -209,38 +209,15 @@ { BufferHttpSender sender; - sender.SetChunkSize(0); - sender.GetBuffer() = s; - ASSERT_TRUE(ReadAllStream(t, sender)); - ASSERT_EQ(s, t); - } - - { - BufferHttpSender sender; - sender.SetChunkSize(1); - sender.GetBuffer() = s; - ASSERT_TRUE(ReadAllStream(t, sender)); - ASSERT_EQ(s, t); - } - - { - BufferHttpSender sender; sender.SetChunkSize(1); ASSERT_TRUE(ReadAllStream(t, sender)); ASSERT_EQ(0u, t.size()); } + for (int cs = 0; cs < 5; cs++) { BufferHttpSender sender; - sender.SetChunkSize(3); - sender.GetBuffer() = s; - ASSERT_TRUE(ReadAllStream(t, sender)); - ASSERT_EQ(s, t); - } - - { - BufferHttpSender sender; - sender.SetChunkSize(300); + sender.SetChunkSize(cs); sender.GetBuffer() = s; ASSERT_TRUE(ReadAllStream(t, sender)); ASSERT_EQ(s, t); @@ -279,7 +256,7 @@ std::string t; IBufferCompressor::Compress(t, compressor, s); - for (int cs = 0; cs < 3; cs++) + for (int cs = 0; cs < 5; cs++) { BufferHttpSender sender; sender.SetChunkSize(cs); @@ -293,7 +270,7 @@ } // Pass-through test, no decompression occurs - for (int cs = 0; cs < 3; cs++) + for (int cs = 0; cs < 5; cs++) { BufferHttpSender sender; sender.SetChunkSize(cs); @@ -308,7 +285,7 @@ } // Pass-through test, decompression occurs - for (int cs = 0; cs < 3; cs++) + for (int cs = 0; cs < 5; cs++) { BufferHttpSender sender; sender.SetChunkSize(cs); @@ -323,7 +300,7 @@ } // Pass-through test with zlib, no decompression occurs but deflate is sent - for (int cs = 0; cs < 3; cs++) + for (int cs = 0; cs < 16; cs++) { BufferHttpSender sender; sender.SetChunkSize(cs); @@ -337,4 +314,16 @@ ASSERT_EQ(t.size() - sizeof(uint64_t), u.size()); ASSERT_EQ(t.substr(sizeof(uint64_t)), u); } + + for (int cs = 0; cs < 3; cs++) + { + BufferHttpSender sender; + sender.SetChunkSize(cs); + + HttpStreamTranscoder transcode(sender, CompressionType_ZlibWithSize); + std::string u; + ASSERT_TRUE(ReadAllStream(u, transcode, false, true)); + + ASSERT_EQ(0u, u.size()); + } }