Mercurial > hg > orthanc
changeset 6735:8594adfe25e2
Fix and standardize usage of LocalAet
| author | Alain Mazy <am@orthanc.team> |
|---|---|
| date | Mon, 27 Apr 2026 16:02:50 +0200 |
| parents | cba457078ce8 |
| children | f3ef0c4ee0b9 |
| files | NEWS OrthancFramework/Sources/DicomNetworking/DicomAssociation.cpp OrthancServer/Sources/OrthancMoveRequestHandler.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/QueryRetrieveHandler.cpp OrthancServer/Sources/ServerJobs/DicomGetScuJob.cpp OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp |
| diffstat | 7 files changed, 63 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Wed Apr 22 13:09:28 2026 +0200 +++ b/NEWS Mon Apr 27 16:02:50 2026 +0200 @@ -17,9 +17,12 @@ -------- * API version upgraded to 31 -* new fields reported in the /system route: +* New fields reported in the /system route: - "OverwriteInstancesMode" (note, the boolean "OverwriteInstances" field is kept for backward compatibility) +* The "LocalAet" field of the payload to "/modalities/../move", "/modalities/../store", + "/modalities/../get", "queries/../answers/../retrieve" now always overwrites the "DicomAet" + and the "DicomModalities.LocalAet" configurations. Maintenance @@ -29,6 +32,7 @@ (bug introduced in 1.12.10) * Fix OrthancPeerStore jobs that was using the loader threads only if transcoding was required. +* Fix usage of "LocalAet" in C-Find and "queries/../answers/../retrieve". * Fix Orthanc::ImageAccessor that was broken in Orthanc Framework 1.12.11
--- a/OrthancFramework/Sources/DicomNetworking/DicomAssociation.cpp Wed Apr 22 13:09:28 2026 +0200 +++ b/OrthancFramework/Sources/DicomNetworking/DicomAssociation.cpp Mon Apr 27 16:02:50 2026 +0200 @@ -265,10 +265,6 @@ } std::string localAet = parameters.GetLocalApplicationEntityTitle(); - if (parameters.GetRemoteModality().HasLocalAet()) - { - localAet = parameters.GetRemoteModality().GetLocalAet(); - } CLOG(INFO, DICOM) << "Opening a DICOM SCU connection " << (parameters.GetRemoteModality().IsDicomTlsEnabled() ? "using DICOM TLS" : "without DICOM TLS")
--- a/OrthancServer/Sources/OrthancMoveRequestHandler.cpp Wed Apr 22 13:09:28 2026 +0200 +++ b/OrthancServer/Sources/OrthancMoveRequestHandler.cpp Mon Apr 27 16:02:50 2026 +0200 @@ -46,7 +46,7 @@ { private: ServerContext& context_; - const std::string& localAet_; + std::string localAet_; std::vector<std::string> instancesIds_; // std::vector<FileInfo> filesInfo_; std::unique_ptr<ThreadedInstancesLoader> instancesLoader_; @@ -64,7 +64,7 @@ const std::string& originatorAet, uint16_t originatorId) : context_(context), - localAet_(context.GetDefaultLocalApplicationEntityTitle()), + localAet_(context.GetDefaultLocalApplicationEntityTitle()), // from the global config position_(0), originatorAet_(originatorAet), originatorId_(originatorId) @@ -77,6 +77,11 @@ loaderThreads = lock.GetConfiguration().GetLoaderThreads(); } + if (remote_.HasLocalAet()) + { + localAet_ = remote_.GetLocalAet(); // from the DicomModalities config + } + instancesLoader_.reset(new ThreadedInstancesLoader(context_, loaderThreads, false, DicomTransferSyntax_BigEndianExplicit /* dummy value*/, 0, "CSTO")); std::vector<FileInfo> filesInfo; @@ -150,13 +155,21 @@ job_->SetDescription("C-MOVE"); //job_->SetPermissive(true); // This was the behavior of Orthanc < 1.6.0 job_->SetPermissive(false); - job_->SetLocalAet(context.GetDefaultLocalApplicationEntityTitle()); + + std::string localAet = context.GetDefaultLocalApplicationEntityTitle(); // from the global configuration { OrthancConfiguration::ReaderLock lock; - job_->SetRemoteModality(lock.GetConfiguration().GetModalityUsingAet(targetAet)); + Orthanc::RemoteModalityParameters remoteModality = lock.GetConfiguration().GetModalityUsingAet(targetAet); + job_->SetRemoteModality(remoteModality); + if (remoteModality.HasLocalAet()) + { + localAet = remoteModality.GetLocalAet(); // from the DicomModalities config + } } + job_->SetLocalAet(localAet); + if (originatorId != 0) { job_->SetMoveOriginator(originatorAet, originatorId);
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp Wed Apr 22 13:09:28 2026 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp Mon Apr 27 16:02:50 2026 +0200 @@ -681,8 +681,7 @@ "Whether to normalize the query, i.e. whether to wipe out from the query, the DICOM tags " "that are not applicable for the query-retrieve level of interest", false) .SetRequestField(KEY_LOCAL_AET, RestApiCallDocumentation::Type_String, - "Local AET that is used for this commands, defaults to `DicomAet` configuration option. " - "Ignored if `DicomModalities` already sets `LocalAet` for this modality.", false) + "Local AET that is used for this commands, defaults to `DicomAet` configuration option or `LocalAet` in the `DicomModalities`. ", false) .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number, "Timeout for the C-FIND command and subsequent C-GET/C-MOVE retrievals, in seconds (new in Orthanc 1.9.1). Orthanc will close the related DICOM associations if no DICOM messages are received within this time period.", false) .SetAnswerField("ID", RestApiCallDocumentation::Type_String, @@ -920,20 +919,26 @@ size_t index) { ServerContext& context = OrthancRestApi::GetContext(call); - - std::string targetAet; + QueryAccessor query(call); + RemoteModalityParameters remoteModality = query.GetHandler().GetRemoteModality(); + + std::string targetAet = context.GetDefaultLocalApplicationEntityTitle(); // from the global configuration + if (remoteModality.HasLocalAet()) + { + targetAet = remoteModality.GetLocalAet(); + } + int timeout = -1; - QueryAccessor query(call); - - RetrieveMethod retrieveMethod = query.GetHandler().GetRemoteModality().GetRetrieveMethod(); + RetrieveMethod retrieveMethod = remoteModality.GetRetrieveMethod(); Json::Value body; if (call.ParseJsonRequest(body)) { OrthancConfiguration::ReaderLock lock; - targetAet = Toolbox::GetJsonStringField(body, KEY_TARGET_AET, context.GetDefaultLocalApplicationEntityTitle()); + targetAet = Toolbox::GetJsonStringField(body, KEY_TARGET_AET, targetAet); + timeout = Toolbox::GetJsonIntegerField(body, KEY_TIMEOUT, -1); std::string strRetrieveMethod = SerializationToolbox::ReadString(body, KEY_RETRIEVE_METHOD, ""); @@ -950,10 +955,6 @@ { call.BodyToString(targetAet); } - else - { - targetAet = context.GetDefaultLocalApplicationEntityTitle(); - } } if (retrieveMethod == RetrieveMethod_SystemDefault) @@ -1484,8 +1485,7 @@ .SetRequestField(KEY_RESOURCES, RestApiCallDocumentation::Type_JsonListOfStrings, "List of the Orthanc identifiers of all the DICOM resources to be sent", true) .SetRequestField(KEY_LOCAL_AET, RestApiCallDocumentation::Type_String, - "Local AET that is used for this commands, defaults to `DicomAet` configuration option. " - "Ignored if `DicomModalities` already sets `LocalAet` for this modality.", false) + "Local AET that is used for this commands, defaults to `DicomAet` configuration option or `LocalAet` in the `DicomModalities`. ", false) .SetRequestField(KEY_CALLED_AET, RestApiCallDocumentation::Type_String, "Called AET that is used for this commands, defaults to `AET` configuration option. " "Allows you to overwrite the destination AET for a specific operation.", false) @@ -1517,15 +1517,20 @@ GetInstancesToExport(request, *job, remote, call); - std::string localAet = Toolbox::GetJsonStringField - (request, KEY_LOCAL_AET, context.GetDefaultLocalApplicationEntityTitle()); + RemoteModalityParameters remoteModality = MyGetModalityUsingSymbolicName(remote); + + std::string localAet = context.GetDefaultLocalApplicationEntityTitle(); // from the global configuration file + if (remoteModality.HasLocalAet()) // from the DicomModalities configuration + { + localAet = remoteModality.GetLocalAet(); + } + localAet = Toolbox::GetJsonStringField(request, KEY_LOCAL_AET, localAet); // from the payload + std::string moveOriginatorAET = Toolbox::GetJsonStringField (request, KEY_MOVE_ORIGINATOR_AET, context.GetDefaultLocalApplicationEntityTitle()); int moveOriginatorID = Toolbox::GetJsonIntegerField (request, KEY_MOVE_ORIGINATOR_ID, 0 /* By default, not a C-MOVE */); - RemoteModalityParameters remoteModality = MyGetModalityUsingSymbolicName(remote); - remoteModality.SetApplicationEntityTitle(Toolbox::GetJsonStringField (request, KEY_CALLED_AET, remoteModality.GetApplicationEntityTitle())); remoteModality.SetHost(Toolbox::GetJsonStringField @@ -1609,16 +1614,21 @@ } ResourceType level = StringToResourceType(request[KEY_LEVEL].asCString()); - - std::string localAet = Toolbox::GetJsonStringField - (request, KEY_LOCAL_AET, context.GetDefaultLocalApplicationEntityTitle()); - - const RemoteModalityParameters source = + + const RemoteModalityParameters sourceModality = MyGetModalityUsingSymbolicName(call.GetUriComponent("id", "")); + std::string localAet = context.GetDefaultLocalApplicationEntityTitle(); // from the global configuration file + if (sourceModality.HasLocalAet()) // from the DicomModalities configuration + { + localAet = sourceModality.GetLocalAet(); + } + localAet = Toolbox::GetJsonStringField(request, KEY_LOCAL_AET, localAet); // from the payload + + job.SetQueryFormat(DicomToJsonFormat_Short); job.SetLocalAet(localAet); - job.SetRemoteModality(source); + job.SetRemoteModality(sourceModality); if (request.isMember(KEY_TIMEOUT)) { @@ -1656,8 +1666,7 @@ .SetRequestField(KEY_LEVEL, RestApiCallDocumentation::Type_String, "Level of the query (`Patient`, `Study`, `Series` or `Instance`)", true) .SetRequestField(KEY_LOCAL_AET, RestApiCallDocumentation::Type_String, - "Local AET that is used for this commands, defaults to `DicomAet` configuration option. " - "Ignored if `DicomModalities` already sets `LocalAet` for this modality.", false) + "Local AET that is used for this commands, defaults to `DicomAet` configuration option or `LocalAet` in the `DicomModalities`. ", false) .SetRequestField(KEY_TARGET_AET, RestApiCallDocumentation::Type_String, "Target AET that will be used by the remote DICOM modality as a target for its C-STORE SCU " "commands, defaults to `DicomAet` configuration option in order to do a simple query/retrieve", false) @@ -1709,8 +1718,7 @@ .SetRequestField(KEY_LEVEL, RestApiCallDocumentation::Type_String, "Level of the query (`Patient`, `Study`, `Series` or `Instance`)", true) .SetRequestField(KEY_LOCAL_AET, RestApiCallDocumentation::Type_String, - "Local AET that is used for this commands, defaults to `DicomAet` configuration option. " - "Ignored if `DicomModalities` already sets `LocalAet` for this modality.", false) + "Local AET that is used for this commands, defaults to `DicomAet` configuration option or `LocalAet` in the `DicomModalities`. ", false) .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number, "Timeout for the C-GET command, in seconds. Orthanc will close the DICOM association if no DICOM messages are received within this time period.", false) .SetUriArgument("id", "Identifier of the modality of interest");
--- a/OrthancServer/Sources/QueryRetrieveHandler.cpp Wed Apr 22 13:09:28 2026 +0200 +++ b/OrthancServer/Sources/QueryRetrieveHandler.cpp Mon Apr 27 16:02:50 2026 +0200 @@ -108,6 +108,11 @@ { OrthancConfiguration::ReaderLock lock; lock.GetConfiguration().GetDicomModalityUsingSymbolicName(modality_, symbolicName); + + if (modality_.HasLocalAet()) + { + SetLocalAet(modality_.GetLocalAet()); + } } }
--- a/OrthancServer/Sources/ServerJobs/DicomGetScuJob.cpp Wed Apr 22 13:09:28 2026 +0200 +++ b/OrthancServer/Sources/ServerJobs/DicomGetScuJob.cpp Mon Apr 27 16:02:50 2026 +0200 @@ -30,11 +30,6 @@ #include <dcmtk/dcmnet/dimse.h> #include <algorithm> -static const char* const LOCAL_AET = "LocalAet"; -static const char* const QUERY = "Query"; -static const char* const QUERY_FORMAT = "QueryFormat"; // New in 1.9.5 -static const char* const REMOTE = "Remote"; -static const char* const TIMEOUT = "Timeout"; namespace Orthanc {
--- a/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp Wed Apr 22 13:09:28 2026 +0200 +++ b/OrthancServer/Sources/ServerJobs/DicomMoveScuJob.cpp Mon Apr 27 16:02:50 2026 +0200 @@ -27,12 +27,7 @@ #include "../../../OrthancFramework/Sources/SerializationToolbox.h" #include "../ServerContext.h" -static const char* const LOCAL_AET = "LocalAet"; -static const char* const QUERY = "Query"; -static const char* const QUERY_FORMAT = "QueryFormat"; // New in 1.9.5 -static const char* const REMOTE = "Remote"; static const char* const TARGET_AET = "TargetAet"; -static const char* const TIMEOUT = "Timeout"; namespace Orthanc {
