Mercurial > hg > orthanc
diff OrthancServer/main.cpp @ 1364:111e23bb4904 query-retrieve
integration mainline->query-retrieve
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 21 May 2015 16:58:30 +0200 |
parents | c2c28dd17e87 b7351ecb79b4 |
children | a3559b66fba7 |
line wrap: on
line diff
--- a/OrthancServer/main.cpp Wed Jun 25 15:34:40 2014 +0200 +++ b/OrthancServer/main.cpp Thu May 21 16:58:30 2015 +0200 @@ -1,7 +1,7 @@ /** * Orthanc - A Lightweight, RESTful DICOM Store - * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, - * Belgium + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -37,6 +37,7 @@ #include <glog/logging.h> #include <boost/algorithm/string/predicate.hpp> +#include "../Core/Uuid.h" #include "../Core/HttpServer/EmbeddedResourceHttpHandler.h" #include "../Core/HttpServer/FilesystemHttpHandler.h" #include "../Core/Lua/LuaFunctionCall.h" @@ -48,10 +49,14 @@ #include "OrthancFindRequestHandler.h" #include "OrthancMoveRequestHandler.h" #include "ServerToolbox.h" +#include "../Plugins/Engine/PluginsManager.h" +#include "../Plugins/Engine/OrthancPlugins.h" using namespace Orthanc; +#define ENABLE_PLUGINS 1 + class OrthancStoreRequestHandler : public IStoreRequestHandler { @@ -67,11 +72,20 @@ virtual void Handle(const std::string& dicomFile, const DicomMap& dicomSummary, const Json::Value& dicomJson, - const std::string& remoteAet) + const std::string& remoteAet, + const std::string& calledAet) { if (dicomFile.size() > 0) { - server_.Store(&dicomFile[0], dicomFile.size(), dicomSummary, dicomJson, remoteAet); + DicomInstanceToStore toStore; + toStore.SetBuffer(dicomFile); + toStore.SetSummary(dicomSummary); + toStore.SetJson(dicomJson); + toStore.SetRemoteAet(remoteAet); + toStore.SetCalledAet(calledAet); + + std::string id; + server_.Store(id, toStore); } } }; @@ -139,7 +153,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*/) { @@ -166,6 +187,63 @@ return true; } } + + virtual bool IsAllowedTransferSyntax(const std::string& callingIp, + const std::string& callingAet, + TransferSyntax syntax) + { + 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); + } }; @@ -186,10 +264,12 @@ { static const char* HTTP_FILTER = "IncomingHttpRequestFilter"; + ServerContext::LuaContextLocker locker(context_); + // Test if the instance must be filtered out - if (context_.GetLuaContext().IsExistingFunction(HTTP_FILTER)) + if (locker.GetLua().IsExistingFunction(HTTP_FILTER)) { - LuaFunctionCall call(context_.GetLuaContext(), HTTP_FILTER); + LuaFunctionCall call(locker.GetLua(), HTTP_FILTER); switch (method) { @@ -229,7 +309,7 @@ }; -void PrintHelp(char* path) +static void PrintHelp(char* path) { std::cout << "Usage: " << path << " [OPTION]... [CONFIGURATION]" << std::endl @@ -256,11 +336,11 @@ } -void PrintVersion(char* path) +static void PrintVersion(char* path) { std::cout << path << " " << ORTHANC_VERSION << std::endl - << "Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege (Belgium) " << std::endl + << "Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics Department, University Hospital of Liege (Belgium)" << std::endl << "Licensing GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>, with OpenSSL exception." << std::endl << "This is free software: you are free to change and redistribute it." << std::endl << "There is NO WARRANTY, to the extent permitted by law." << std::endl @@ -269,6 +349,221 @@ } + +static void LoadLuaScripts(ServerContext& context) +{ + std::list<std::string> luaScripts; + Configuration::GetGlobalListOfStringsParameter(luaScripts, "LuaScripts"); + for (std::list<std::string>::const_iterator + it = luaScripts.begin(); it != luaScripts.end(); ++it) + { + std::string path = Configuration::InterpretStringParameterAsPath(*it); + LOG(WARNING) << "Installing the Lua scripts from: " << path; + std::string script; + Toolbox::ReadFile(script, path); + + ServerContext::LuaContextLocker locker(context); + locker.GetLua().Execute(script); + } +} + + +static void LoadPlugins(PluginsManager& pluginsManager) +{ + std::list<std::string> plugins; + Configuration::GetGlobalListOfStringsParameter(plugins, "Plugins"); + for (std::list<std::string>::const_iterator + it = plugins.begin(); it != plugins.end(); ++it) + { + std::string path = Configuration::InterpretStringParameterAsPath(*it); + LOG(WARNING) << "Loading plugin(s) from: " << path; + pluginsManager.RegisterPlugin(path); + } +} + + + +static bool StartOrthanc(int argc, char *argv[]) +{ +#if ENABLE_PLUGINS == 1 + OrthancPlugins orthancPlugins; + orthancPlugins.SetCommandLineArguments(argc, argv); + PluginsManager pluginsManager; + pluginsManager.RegisterServiceProvider(orthancPlugins); + LoadPlugins(pluginsManager); +#endif + + // "storage" and "database" must be declared BEFORE "ServerContext + // context", to avoid mess in the invokation order of the destructors. + std::auto_ptr<IDatabaseWrapper> database; + std::auto_ptr<IStorageArea> storage; + std::auto_ptr<ServerContext> context; + + if (orthancPlugins.HasDatabase()) + { + context.reset(new ServerContext(orthancPlugins.GetDatabase())); + } + else + { + database.reset(Configuration::CreateDatabaseWrapper()); + context.reset(new ServerContext(*database)); + } + + context->SetCompressionEnabled(Configuration::GetGlobalBoolParameter("StorageCompression", false)); + context->SetStoreMD5ForAttachments(Configuration::GetGlobalBoolParameter("StoreMD5ForAttachments", true)); + + LoadLuaScripts(*context); + + try + { + context->GetIndex().SetMaximumPatientCount(Configuration::GetGlobalIntegerParameter("MaximumPatientCount", 0)); + } + catch (...) + { + context->GetIndex().SetMaximumPatientCount(0); + } + + try + { + uint64_t size = Configuration::GetGlobalIntegerParameter("MaximumStorageSize", 0); + context->GetIndex().SetMaximumStorageSize(size * 1024 * 1024); + } + catch (...) + { + context->GetIndex().SetMaximumStorageSize(0); + } + + MyDicomServerFactory serverFactory(*context); + bool isReset = false; + + { + // DICOM server + DicomServer dicomServer; + OrthancApplicationEntityFilter dicomFilter(*context); + dicomServer.SetCalledApplicationEntityTitleCheck(Configuration::GetGlobalBoolParameter("DicomCheckCalledAet", false)); + dicomServer.SetStoreRequestHandlerFactory(serverFactory); + dicomServer.SetMoveRequestHandlerFactory(serverFactory); + dicomServer.SetFindRequestHandlerFactory(serverFactory); + dicomServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("DicomPort", 4242)); + dicomServer.SetApplicationEntityTitle(Configuration::GetGlobalStringParameter("DicomAet", "ORTHANC")); + dicomServer.SetApplicationEntityFilter(dicomFilter); + + // HTTP server + MyIncomingHttpRequestFilter httpFilter(*context); + MongooseServer httpServer; + httpServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("HttpPort", 8042)); + httpServer.SetRemoteAccessAllowed(Configuration::GetGlobalBoolParameter("RemoteAccessAllowed", false)); + httpServer.SetKeepAliveEnabled(Configuration::GetGlobalBoolParameter("KeepAlive", false)); + httpServer.SetIncomingHttpRequestFilter(httpFilter); + + httpServer.SetAuthenticationEnabled(Configuration::GetGlobalBoolParameter("AuthenticationEnabled", false)); + Configuration::SetupRegisteredUsers(httpServer); + + if (Configuration::GetGlobalBoolParameter("SslEnabled", false)) + { + std::string certificate = Configuration::InterpretStringParameterAsPath( + Configuration::GetGlobalStringParameter("SslCertificate", "certificate.pem")); + httpServer.SetSslEnabled(true); + httpServer.SetSslCertificate(certificate.c_str()); + } + else + { + httpServer.SetSslEnabled(false); + } + + OrthancRestApi restApi(*context); + +#if ORTHANC_STANDALONE == 1 + EmbeddedResourceHttpHandler staticResources("/app", EmbeddedResources::ORTHANC_EXPLORER); +#else + FilesystemHttpHandler staticResources("/app", ORTHANC_PATH "/OrthancExplorer"); +#endif + +#if ENABLE_PLUGINS == 1 + orthancPlugins.SetServerContext(*context); + httpServer.RegisterHandler(orthancPlugins); + context->SetOrthancPlugins(pluginsManager, orthancPlugins); +#endif + + httpServer.RegisterHandler(staticResources); + httpServer.RegisterHandler(restApi); + + +#if ENABLE_PLUGINS == 1 + // Prepare the storage area + if (orthancPlugins.HasStorageArea()) + { + LOG(WARNING) << "Using a custom storage area from plugins"; + storage.reset(orthancPlugins.GetStorageArea()); + } + else +#endif + { + storage.reset(Configuration::CreateStorageArea()); + } + + context->SetStorageArea(*storage); + + + // GO !!! Start the requested servers + if (Configuration::GetGlobalBoolParameter("HttpServerEnabled", true)) + { +#if ENABLE_PLUGINS == 1 + orthancPlugins.SetOrthancRestApi(restApi); +#endif + + httpServer.Start(); + LOG(WARNING) << "HTTP server listening on port: " << httpServer.GetPortNumber(); + } + else + { + LOG(WARNING) << "The HTTP server is disabled"; + } + + if (Configuration::GetGlobalBoolParameter("DicomServerEnabled", true)) + { + dicomServer.Start(); + LOG(WARNING) << "DICOM server listening on port: " << dicomServer.GetPortNumber(); + } + else + { + LOG(WARNING) << "The DICOM server is disabled"; + } + + LOG(WARNING) << "Orthanc has started"; + Toolbox::ServerBarrier(restApi.ResetRequestReceivedFlag()); + isReset = restApi.ResetRequestReceivedFlag(); + + if (isReset) + { + LOG(WARNING) << "Reset request received, restarting Orthanc"; + } + + // We're done + LOG(WARNING) << "Orthanc is stopping"; + +#if ENABLE_PLUGINS == 1 + context->ResetOrthancPlugins(); + orthancPlugins.Stop(); + orthancPlugins.ResetOrthancRestApi(); + LOG(WARNING) << " Plugins have stopped"; +#endif + + dicomServer.Stop(); + LOG(WARNING) << " DICOM server has stopped"; + + httpServer.Stop(); + LOG(WARNING) << " HTTP server has stopped"; + } + + serverFactory.Done(); + + return isReset; +} + + + + int main(int argc, char* argv[]) { // Initialize Google's logging library. @@ -327,178 +622,78 @@ google::InitGoogleLogging("Orthanc"); + const char* configurationFile = NULL; + for (int i = 1; i < argc; i++) + { + // Use the first argument that does not start with a "-" as + // the configuration file + if (argv[i][0] != '-') + { + configurationFile = argv[i]; + } + } + + LOG(WARNING) << "Orthanc version: " << ORTHANC_VERSION; + int status = 0; try { - bool isInitialized = false; - if (argc >= 2) + if (1) { - for (int i = 1; i < argc; i++) - { - // Use the first argument that does not start with a "-" as - // the configuration file - if (argv[i][0] != '-') - { - OrthancInitialize(argv[i]); - isInitialized = true; - } - } - } - - if (!isInitialized) - { - OrthancInitialize(); - } + DicomUserConnection c; + c.SetLocalApplicationEntityTitle("ORTHANC"); + c.SetRemoteApplicationEntityTitle("ORTHANC"); + c.SetRemoteHost("localhost"); + c.SetRemotePort(4343); + c.Open(); - std::string storageDirectoryStr = Configuration::GetGlobalStringParameter("StorageDirectory", "OrthancStorage"); - boost::filesystem::path storageDirectory = Configuration::InterpretStringParameterAsPath(storageDirectoryStr); - boost::filesystem::path indexDirectory = Configuration::InterpretStringParameterAsPath( - Configuration::GetGlobalStringParameter("IndexDirectory", storageDirectoryStr)); - ServerContext context(storageDirectory, indexDirectory); - - LOG(WARNING) << "Storage directory: " << storageDirectory; - LOG(WARNING) << "Index directory: " << indexDirectory; + DicomMap m; // Delphine + m.SetValue(DICOM_TAG_PATIENT_ID, "5423962"); + m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1.2.840.113845.11.1000000001951524609.20121203131451.1457891"); + m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "1.2.840.113619.2.278.3.262930758.589.1354512768.115"); + m.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "1.3.12.2.1107.5.2.33.37097.2012041613043195815872177"); - context.SetCompressionEnabled(Configuration::GetGlobalBoolParameter("StorageCompression", false)); - context.SetStoreMD5ForAttachments(Configuration::GetGlobalBoolParameter("StoreMD5ForAttachments", true)); + DicomFindAnswers fnd; + c.FindInstance(fnd, m); + //c.FindSeries(fnd, m); - std::list<std::string> luaScripts; - Configuration::GetGlobalListOfStringsParameter(luaScripts, "LuaScripts"); - for (std::list<std::string>::const_iterator - it = luaScripts.begin(); it != luaScripts.end(); ++it) - { - std::string path = Configuration::InterpretStringParameterAsPath(*it); - LOG(WARNING) << "Installing the Lua scripts from: " << path; - std::string script; - Toolbox::ReadFile(script, path); - context.GetLuaContext().Execute(script); + printf("ok %d\n", fnd.GetSize()); } - try - { - context.GetIndex().SetMaximumPatientCount(Configuration::GetGlobalIntegerParameter("MaximumPatientCount", 0)); - } - catch (...) - { - context.GetIndex().SetMaximumPatientCount(0); - } - - try - { - uint64_t size = Configuration::GetGlobalIntegerParameter("MaximumStorageSize", 0); - context.GetIndex().SetMaximumStorageSize(size * 1024 * 1024); - } - catch (...) - { - context.GetIndex().SetMaximumStorageSize(0); - } - - MyDicomServerFactory serverFactory(context); - + for (;;) { - // DICOM server - DicomServer dicomServer; - OrthancApplicationEntityFilter dicomFilter; - dicomServer.SetCalledApplicationEntityTitleCheck(Configuration::GetGlobalBoolParameter("DicomCheckCalledAet", false)); - dicomServer.SetStoreRequestHandlerFactory(serverFactory); - dicomServer.SetMoveRequestHandlerFactory(serverFactory); - dicomServer.SetFindRequestHandlerFactory(serverFactory); - dicomServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("DicomPort", 4242)); - dicomServer.SetApplicationEntityTitle(Configuration::GetGlobalStringParameter("DicomAet", "ORTHANC")); - dicomServer.SetApplicationEntityFilter(dicomFilter); + OrthancInitialize(configurationFile); - // HTTP server - MyIncomingHttpRequestFilter httpFilter(context); - MongooseServer httpServer; - httpServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("HttpPort", 8042)); - httpServer.SetRemoteAccessAllowed(Configuration::GetGlobalBoolParameter("RemoteAccessAllowed", false)); - httpServer.SetIncomingHttpRequestFilter(httpFilter); - - httpServer.SetAuthenticationEnabled(Configuration::GetGlobalBoolParameter("AuthenticationEnabled", false)); - Configuration::SetupRegisteredUsers(httpServer); - - if (Configuration::GetGlobalBoolParameter("SslEnabled", false)) + bool reset = StartOrthanc(argc, argv); + if (reset) { - std::string certificate = Configuration::InterpretStringParameterAsPath( - Configuration::GetGlobalStringParameter("SslCertificate", "certificate.pem")); - httpServer.SetSslEnabled(true); - httpServer.SetSslCertificate(certificate.c_str()); + OrthancFinalize(); } else { - httpServer.SetSslEnabled(false); - } - -#if ORTHANC_STANDALONE == 1 - httpServer.RegisterHandler(new EmbeddedResourceHttpHandler("/app", EmbeddedResources::ORTHANC_EXPLORER)); -#else - httpServer.RegisterHandler(new FilesystemHttpHandler("/app", ORTHANC_PATH "/OrthancExplorer")); -#endif - - httpServer.RegisterHandler(new OrthancRestApi(context)); - - // GO !!! Start the requested servers - if (Configuration::GetGlobalBoolParameter("HttpServerEnabled", true)) - { - httpServer.Start(); - LOG(WARNING) << "HTTP server listening on port: " << httpServer.GetPortNumber(); - } - else - { - LOG(WARNING) << "The HTTP server is disabled"; - } - - if (Configuration::GetGlobalBoolParameter("DicomServerEnabled", true)) - { - dicomServer.Start(); - LOG(WARNING) << "DICOM server listening on port: " << dicomServer.GetPortNumber(); - } - else - { - LOG(WARNING) << "The DICOM server is disabled"; + break; } - - - { - DicomUserConnection c; - c.SetLocalApplicationEntityTitle("ORTHANC"); - c.SetDistantApplicationEntityTitle("ORTHANC"); - c.SetDistantHost("localhost"); - c.SetDistantPort(4343); - c.Open(); - - DicomMap m; // Delphine - m.SetValue(DICOM_TAG_PATIENT_ID, "5423962"); - m.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, "1.2.840.113845.11.1000000001951524609.20121203131451.1457891"); - m.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, "1.2.840.113619.2.278.3.262930758.589.1354512768.115"); - m.SetValue(DICOM_TAG_SOP_INSTANCE_UID, "1.3.12.2.1107.5.2.33.37097.2012041613043195815872177"); - - DicomFindAnswers fnd; - c.FindInstance(fnd, m); - //c.FindSeries(fnd, m); - - printf("ok %d\n", fnd.GetSize()); - } - - - LOG(WARNING) << "Orthanc has started"; - Toolbox::ServerBarrier(); - - // We're done - LOG(WARNING) << "Orthanc is stopping"; } - - serverFactory.Done(); + } + catch (const OrthancException& e) + { + LOG(ERROR) << "Uncaught exception, stopping now: [" << e.What() << "]"; + status = -1; } - catch (OrthancException& e) + catch (const std::exception& e) { - LOG(ERROR) << "EXCEPTION [" << e.What() << "]"; + LOG(ERROR) << "Uncaught exception, stopping now: [" << e.what() << "]"; + status = -1; + } + catch (const std::string& s) + { + LOG(ERROR) << "Uncaught exception, stopping now: [" << s << "]"; status = -1; } catch (...) { - LOG(ERROR) << "NATIVE EXCEPTION"; + LOG(ERROR) << "Native exception, stopping now. Check your plugins, if any."; status = -1; }