# HG changeset patch # User Sebastien Jodogne # Date 1588596571 -7200 # Node ID ea1d32861cfc73ae53bc06127a16d016f7ec1ffd # Parent 2effa961f67f66a81709c7f6b9af5bdc6ad51bd0 moving timeout from DicomAssocation to DicomAssociationParameters diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomAssociation.cpp --- a/Core/DicomNetworking/DicomAssociation.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomAssociation.cpp Mon May 04 14:49:31 2020 +0200 @@ -259,10 +259,10 @@ LOG(INFO) << "Opening a DICOM SCU connection from AET \"" << parameters.GetLocalApplicationEntityTitle() - << "\" to AET \"" << parameters.GetRemoteApplicationEntityTitle() - << "\" on host " << parameters.GetRemoteHost() - << ":" << parameters.GetRemotePort() - << " (manufacturer: " << EnumerationToString(parameters.GetRemoteManufacturer()) << ")"; + << "\" to AET \"" << parameters.GetRemoteModality().GetApplicationEntityTitle() + << "\" on host " << parameters.GetRemoteModality().GetHost() + << ":" << parameters.GetRemoteModality().GetPortNumber() + << " (manufacturer: " << EnumerationToString(parameters.GetRemoteModality().GetManufacturer()) << ")"; CheckConnecting(parameters, ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ acseTimeout, &net_)); CheckConnecting(parameters, ASC_createAssociationParameters(¶ms_, /*opt_maxReceivePDULength*/ ASC_DEFAULTMAXPDU)); @@ -270,7 +270,7 @@ // Set this application's title and the called application's title in the params CheckConnecting(parameters, ASC_setAPTitles( params_, parameters.GetLocalApplicationEntityTitle().c_str(), - parameters.GetRemoteApplicationEntityTitle().c_str(), NULL)); + parameters.GetRemoteModality().GetApplicationEntityTitle().c_str(), NULL)); // Set the network addresses of the local and remote entities char localHost[HOST_NAME_MAX]; @@ -284,7 +284,8 @@ snprintf #endif (remoteHostAndPort, HOST_NAME_MAX - 1, "%s:%d", - parameters.GetRemoteHost().c_str(), parameters.GetRemotePort()); + parameters.GetRemoteModality().GetHost().c_str(), + parameters.GetRemoteModality().GetPortNumber()); CheckConnecting(parameters, ASC_setPresentationAddresses(params_, localHost, remoteHostAndPort)); @@ -339,7 +340,7 @@ else { LOG(WARNING) << "Unknown transfer syntax received from AET \"" - << parameters.GetRemoteApplicationEntityTitle() + << parameters.GetRemoteModality().GetApplicationEntityTitle() << "\": " << pc->acceptedTransferSyntax; } } @@ -352,7 +353,7 @@ { throw OrthancException(ErrorCode_NoPresentationContext, "Unable to negotiate a presentation context with AET \"" + - parameters.GetRemoteApplicationEntityTitle() + "\""); + parameters.GetRemoteModality().GetApplicationEntityTitle() + "\""); } } @@ -517,7 +518,7 @@ throw OrthancException(ErrorCode_NetworkProtocol, "DicomAssociation - " + command + " to AET \"" + - parameters.GetRemoteApplicationEntityTitle() + + parameters.GetRemoteModality().GetApplicationEntityTitle() + "\": " + info); } } @@ -604,7 +605,7 @@ **/ LOG(INFO) << "Reporting modality \"" - << parameters.GetRemoteApplicationEntityTitle() + << parameters.GetRemoteModality().GetApplicationEntityTitle() << "\" about storage commitment transaction: " << transactionUid << " (" << successSopClassUids.size() << " successes, " << failedSopClassUids.size() << " failures)"; @@ -654,7 +655,7 @@ { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "Unable to send N-EVENT-REPORT request to AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } if (!DIMSE_sendMessageUsingMemoryData( @@ -682,7 +683,7 @@ { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "Unable to read N-EVENT-REPORT response from AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } const T_DIMSE_N_EventReportRSP& content = message.msg.NEventReportRSP; @@ -696,14 +697,14 @@ { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "Badly formatted N-EVENT-REPORT response from AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } if (content.DimseStatus != 0 /* success */) { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "The request cannot be handled by remote AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } } @@ -767,7 +768,7 @@ **/ LOG(INFO) << "Request to modality \"" - << parameters.GetRemoteApplicationEntityTitle() + << parameters.GetRemoteModality().GetApplicationEntityTitle() << "\" about storage commitment for " << sopClassUids.size() << " instances, with transaction UID: " << transactionUid; const DIC_US messageId = association.GetDcmtkAssociation().nextMsgID++; @@ -801,7 +802,7 @@ { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "Unable to send N-ACTION request to AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } if (!DIMSE_sendMessageUsingMemoryData( @@ -829,7 +830,7 @@ { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "Unable to read N-ACTION response from AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } const T_DIMSE_N_ActionRSP& content = message.msg.NActionRSP; @@ -843,14 +844,14 @@ { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "Badly formatted N-ACTION response from AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } if (content.DimseStatus != 0 /* success */) { throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " "The request cannot be handled by remote AET: " + - parameters.GetRemoteApplicationEntityTitle()); + parameters.GetRemoteModality().GetApplicationEntityTitle()); } } diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomAssociationParameters.cpp --- a/Core/DicomNetworking/DicomAssociationParameters.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomAssociationParameters.cpp Mon May 04 14:49:31 2020 +0200 @@ -37,6 +37,7 @@ #include "../Compatibility.h" #include "../Logging.h" #include "../OrthancException.h" +#include "../SerializationToolbox.h" #include "NetworkingCompatibility.h" #include @@ -48,68 +49,111 @@ namespace Orthanc { - void DicomAssociationParameters::ReadDefaultTimeout() + void DicomAssociationParameters::CheckHost(const std::string& host) + { + if (host.size() > HOST_NAME_MAX - 10) + { + throw OrthancException(ErrorCode_ParameterOutOfRange, + "Invalid host name (too long): " + host); + } + } + + + uint32_t DicomAssociationParameters::GetDefaultTimeout() { boost::mutex::scoped_lock lock(defaultTimeoutMutex_); - timeout_ = defaultTimeout_; + return defaultTimeout_; } DicomAssociationParameters::DicomAssociationParameters() : - localAet_("STORESCU"), - remoteAet_("ANY-SCP"), - remoteHost_("127.0.0.1"), - remotePort_(104), - manufacturer_(ModalityManufacturer_Generic) + localAet_("ORTHANC"), + timeout_(GetDefaultTimeout()) { - ReadDefaultTimeout(); + remote_.SetApplicationEntityTitle("ANY-SCP"); } DicomAssociationParameters::DicomAssociationParameters(const std::string& localAet, const RemoteModalityParameters& remote) : localAet_(localAet), - remoteAet_(remote.GetApplicationEntityTitle()), - remoteHost_(remote.GetHost()), - remotePort_(remote.GetPortNumber()), - manufacturer_(remote.GetManufacturer()), - timeout_(defaultTimeout_) + timeout_(GetDefaultTimeout()) { - ReadDefaultTimeout(); + SetRemoteModality(remote); } - void DicomAssociationParameters::SetRemoteHost(const std::string& host) + void DicomAssociationParameters::SetRemoteModality(const RemoteModalityParameters& remote) { - if (host.size() > HOST_NAME_MAX - 10) - { - throw OrthancException(ErrorCode_ParameterOutOfRange, - "Invalid host name (too long): " + host); - } - - remoteHost_ = host; + CheckHost(remote.GetHost()); + remote_ = remote; } - void DicomAssociationParameters::SetRemoteModality(const RemoteModalityParameters& parameters) + void DicomAssociationParameters::SetRemoteHost(const std::string& host) { - SetRemoteApplicationEntityTitle(parameters.GetApplicationEntityTitle()); - SetRemoteHost(parameters.GetHost()); - SetRemotePort(parameters.GetPortNumber()); - SetRemoteManufacturer(parameters.GetManufacturer()); + CheckHost(host); + remote_.SetHost(host); + } + + + void DicomAssociationParameters::SetTimeout(uint32_t seconds) + { + assert(seconds != -1); + timeout_ = seconds; } bool DicomAssociationParameters::IsEqual(const DicomAssociationParameters& other) const { return (localAet_ == other.localAet_ && - remoteAet_ == other.remoteAet_ && - remoteHost_ == other.remoteHost_ && - remotePort_ == other.remotePort_ && - manufacturer_ == other.manufacturer_); + remote_.GetApplicationEntityTitle() == other.remote_.GetApplicationEntityTitle() && + remote_.GetHost() == other.remote_.GetHost() && + remote_.GetPortNumber() == other.remote_.GetPortNumber() && + remote_.GetManufacturer() == other.remote_.GetManufacturer() && + timeout_ == other.timeout_); } + + static const char* const LOCAL_AET = "LocalAet"; + static const char* const REMOTE = "Remote"; + static const char* const TIMEOUT = "Timeout"; // New in Orthanc in 1.7.0 + + + void DicomAssociationParameters::SerializeJob(Json::Value& target) const + { + if (target.type() != Json::objectValue) + { + throw OrthancException(ErrorCode_InternalError); + } + else + { + target[LOCAL_AET] = localAet_; + remote_.Serialize(target[REMOTE], true /* force advanced format */); + target[TIMEOUT] = timeout_; + } + } + + + DicomAssociationParameters DicomAssociationParameters::UnserializeJob(const Json::Value& serialized) + { + if (serialized.type() == Json::objectValue) + { + DicomAssociationParameters result; + result.remote_ = RemoteModalityParameters(serialized[REMOTE]); + result.localAet_ = SerializationToolbox::ReadString(serialized, LOCAL_AET); + result.timeout_ = SerializationToolbox::ReadInteger(serialized, TIMEOUT, GetDefaultTimeout()); + + return result; + } + else + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + + void DicomAssociationParameters::SetDefaultTimeout(uint32_t seconds) { LOG(INFO) << "Default timeout for DICOM connections if Orthanc acts as SCU (client): " diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomAssociationParameters.h --- a/Core/DicomNetworking/DicomAssociationParameters.h Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomAssociationParameters.h Mon May 04 14:49:31 2020 +0200 @@ -35,6 +35,8 @@ #include "RemoteModalityParameters.h" +#include + class OFCondition; // From DCMTK namespace Orthanc @@ -42,14 +44,13 @@ class DicomAssociationParameters { private: - std::string localAet_; - std::string remoteAet_; - std::string remoteHost_; - uint16_t remotePort_; - ModalityManufacturer manufacturer_; - uint32_t timeout_; + std::string localAet_; + RemoteModalityParameters remote_; + uint32_t timeout_; - void ReadDefaultTimeout(); + static void CheckHost(const std::string& host); + + static uint32_t GetDefaultTimeout(); public: DicomAssociationParameters(); @@ -62,56 +63,39 @@ return localAet_; } - const std::string& GetRemoteApplicationEntityTitle() const - { - return remoteAet_; - } - - const std::string& GetRemoteHost() const - { - return remoteHost_; - } - - uint16_t GetRemotePort() const - { - return remotePort_; - } - - ModalityManufacturer GetRemoteManufacturer() const - { - return manufacturer_; - } - void SetLocalApplicationEntityTitle(const std::string& aet) { localAet_ = aet; } + const RemoteModalityParameters& GetRemoteModality() const + { + return remote_; + } + + void SetRemoteModality(const RemoteModalityParameters& parameters); + void SetRemoteApplicationEntityTitle(const std::string& aet) { - remoteAet_ = aet; + remote_.SetApplicationEntityTitle(aet); } void SetRemoteHost(const std::string& host); void SetRemotePort(uint16_t port) { - remotePort_ = port; + remote_.SetPortNumber(port); } void SetRemoteManufacturer(ModalityManufacturer manufacturer) { - manufacturer_ = manufacturer; + remote_.SetManufacturer(manufacturer); } - void SetRemoteModality(const RemoteModalityParameters& parameters); - bool IsEqual(const DicomAssociationParameters& other) const; - void SetTimeout(uint32_t seconds) - { - timeout_ = seconds; - } + // Setting it to "0" disables the timeout (infinite wait) + void SetTimeout(uint32_t seconds); uint32_t GetTimeout() const { @@ -122,6 +106,10 @@ { return timeout_ != 0; } + + void SerializeJob(Json::Value& target) const; + + static DicomAssociationParameters UnserializeJob(const Json::Value& serialized); static void SetDefaultTimeout(uint32_t seconds); }; diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomControlUserConnection.cpp --- a/Core/DicomNetworking/DicomControlUserConnection.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomControlUserConnection.cpp Mon May 04 14:49:31 2020 +0200 @@ -257,7 +257,7 @@ if (presID == 0) { throw OrthancException(ErrorCode_DicomFindUnavailable, - "Remote AET is " + parameters_.GetRemoteApplicationEntityTitle()); + "Remote AET is " + parameters_.GetRemoteModality().GetApplicationEntityTitle()); } T_DIMSE_C_FindRQ request; @@ -309,14 +309,14 @@ throw OrthancException(ErrorCode_NetworkProtocol, HttpStatus_422_UnprocessableEntity, "C-FIND SCU to AET \"" + - parameters_.GetRemoteApplicationEntityTitle() + + parameters_.GetRemoteModality().GetApplicationEntityTitle() + "\" has failed with DIMSE status 0x" + buf + " (unable to process - invalid query ?)"); } else { throw OrthancException(ErrorCode_NetworkProtocol, "C-FIND SCU to AET \"" + - parameters_.GetRemoteApplicationEntityTitle() + + parameters_.GetRemoteModality().GetApplicationEntityTitle() + "\" has failed with DIMSE status 0x" + buf); } } @@ -331,7 +331,7 @@ association_->Open(parameters_); std::unique_ptr query( - ConvertQueryFields(fields, parameters_.GetRemoteManufacturer())); + ConvertQueryFields(fields, parameters_.GetRemoteModality().GetManufacturer())); DcmDataset* dataset = query->GetDcmtkObject().getDataset(); const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel; @@ -362,7 +362,7 @@ if (presID == 0) { throw OrthancException(ErrorCode_DicomMoveUnavailable, - "Remote AET is " + parameters_.GetRemoteApplicationEntityTitle()); + "Remote AET is " + parameters_.GetRemoteModality().GetApplicationEntityTitle()); } T_DIMSE_C_MoveRQ request; @@ -412,14 +412,14 @@ throw OrthancException(ErrorCode_NetworkProtocol, HttpStatus_422_UnprocessableEntity, "C-MOVE SCU to AET \"" + - parameters_.GetRemoteApplicationEntityTitle() + + parameters_.GetRemoteModality().GetApplicationEntityTitle() + "\" has failed with DIMSE status 0x" + buf + " (unable to process - resource not found ?)"); } else { throw OrthancException(ErrorCode_NetworkProtocol, "C-MOVE SCU to AET \"" + - parameters_.GetRemoteApplicationEntityTitle() + + parameters_.GetRemoteModality().GetApplicationEntityTitle() + "\" has failed with DIMSE status 0x" + buf); } } @@ -470,7 +470,7 @@ { DicomMap fields; NormalizeFindQuery(fields, level, originalFields); - query.reset(ConvertQueryFields(fields, parameters_.GetRemoteManufacturer())); + query.reset(ConvertQueryFields(fields, parameters_.GetRemoteModality().GetManufacturer())); } else { @@ -516,7 +516,7 @@ const char* universal; - if (parameters_.GetRemoteManufacturer() == ModalityManufacturer_GE) + if (parameters_.GetRemoteModality().GetManufacturer() == ModalityManufacturer_GE) { universal = "*"; } @@ -660,10 +660,6 @@ MoveInternal(targetAet, ResourceType_Instance, query); } - void DicomControlUserConnection::SetTimeout(uint32_t seconds) - { - parameters_.SetTimeout(seconds); - } void DicomControlUserConnection::FindWorklist(DicomFindAnswers& result, ParsedDicomFile& query) diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomControlUserConnection.h --- a/Core/DicomNetworking/DicomControlUserConnection.h Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomControlUserConnection.h Mon May 04 14:49:31 2020 +0200 @@ -105,7 +105,5 @@ void FindWorklist(DicomFindAnswers& result, ParsedDicomFile& query); - - void SetTimeout(uint32_t seconds); // 0 = no timeout }; } diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomStoreUserConnection.cpp --- a/Core/DicomNetworking/DicomStoreUserConnection.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomStoreUserConnection.cpp Mon May 04 14:49:31 2020 +0200 @@ -179,7 +179,7 @@ { throw OrthancException(ErrorCode_NoSopClassOrInstance, "Unable to determine the SOP class/instance for C-STORE with AET " + - parameters_.GetRemoteApplicationEntityTitle()); + parameters_.GetRemoteModality().GetApplicationEntityTitle()); } sopClassUid.assign(a.c_str()); @@ -213,7 +213,7 @@ if (association_->IsOpen()) { LOG(INFO) << "Re-negociating DICOM association with " - << parameters_.GetRemoteApplicationEntityTitle(); + << parameters_.GetRemoteModality().GetApplicationEntityTitle(); } association_->ClearPresentationContexts(); @@ -312,7 +312,7 @@ "SOP class UID [" + sopClassUid + "] and transfer " "syntax [" + GetTransferSyntaxUid(transferSyntax) + "] " "while sending to modality [" + - parameters_.GetRemoteApplicationEntityTitle() + "]"); + parameters_.GetRemoteModality().GetApplicationEntityTitle() + "]"); } // Prepare the transmission of data @@ -364,7 +364,7 @@ sprintf(buf, "%04X", response.DimseStatus); throw OrthancException(ErrorCode_NetworkProtocol, "C-STORE SCU to AET \"" + - GetParameters().GetRemoteApplicationEntityTitle() + + GetParameters().GetRemoteModality().GetApplicationEntityTitle() + "\" has failed with DIMSE status 0x" + buf); } } diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/DicomStoreUserConnection.h --- a/Core/DicomNetworking/DicomStoreUserConnection.h Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/DicomStoreUserConnection.h Mon May 04 14:49:31 2020 +0200 @@ -90,11 +90,6 @@ return parameters_; } - void SetTimeout(int timeout) - { - parameters_.SetTimeout(timeout); - } - void SetCommonClassesProposed(bool proposed) { proposeCommonClasses_ = proposed; diff -r 2effa961f67f -r ea1d32861cfc Core/DicomNetworking/TimeoutDicomConnectionManager.cpp --- a/Core/DicomNetworking/TimeoutDicomConnectionManager.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/Core/DicomNetworking/TimeoutDicomConnectionManager.cpp Mon May 04 14:49:31 2020 +0200 @@ -103,7 +103,7 @@ if (connection_.get() != NULL) { LOG(INFO) << "Closing inactive DICOM association with modality: " - << connection_->GetParameters().GetRemoteApplicationEntityTitle(); + << connection_->GetParameters().GetRemoteModality().GetApplicationEntityTitle(); connection_.reset(NULL); } diff -r 2effa961f67f -r ea1d32861cfc OrthancServer/OrthancRestApi/OrthancRestModalities.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/OrthancServer/OrthancRestApi/OrthancRestModalities.cpp Mon May 04 14:49:31 2020 +0200 @@ -87,14 +87,15 @@ try { DicomAssociationParameters params(localAet, remote); - DicomControlUserConnection connection(params); // New in Orthanc 1.7.0 - if (timeout != -1) + if (timeout >= 0) { - connection.SetTimeout(timeout); + params.SetTimeout(static_cast(timeout)); } + DicomControlUserConnection connection(params); + if (connection.Echo()) { // Echo has succeeded @@ -649,7 +650,11 @@ job->SetTargetAet(targetAet); job->SetLocalAet(query.GetHandler().GetLocalAet()); job->SetRemoteModality(query.GetHandler().GetRemoteModality()); - job->SetTimeout(timeout); + + if (timeout >= 0) + { + job->SetTimeout(static_cast(timeout)); + } LOG(WARNING) << "Driving C-Move SCU on remote modality " << query.GetHandler().GetRemoteModality().GetApplicationEntityTitle() @@ -997,7 +1002,10 @@ } // New in Orthanc 1.7.0 - job->SetTimeout(timeout); + if (timeout >= 0) + { + job->SetTimeout(static_cast(timeout)); + } OrthancRestApi::GetApi(call).SubmitCommandsJob (call, job.release(), true /* synchronous by default */, request); @@ -1061,13 +1069,15 @@ MyGetModalityUsingSymbolicName(call.GetUriComponent("id", "")); DicomAssociationParameters params(localAet, source); + + // New in Orthanc 1.7.0 + if (timeout >= 0) + { + params.SetTimeout(static_cast(timeout)); + } + DicomControlUserConnection connection(params); - if (timeout > -1) - { - connection.SetTimeout(timeout); - } - for (Json::Value::ArrayIndex i = 0; i < request[KEY_RESOURCES].size(); i++) { DicomMap resource; diff -r 2effa961f67f -r ea1d32861cfc OrthancServer/ServerJobs/DicomModalityStoreJob.cpp --- a/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/OrthancServer/ServerJobs/DicomModalityStoreJob.cpp Mon May 04 14:49:31 2020 +0200 @@ -48,13 +48,7 @@ { if (connection_.get() == NULL) { - DicomAssociationParameters params(localAet_, remote_); - connection_.reset(new DicomStoreUserConnection(params)); - - if (timeout_ > -1) - { - connection_->SetTimeout(timeout_); - } + connection_.reset(new DicomStoreUserConnection(parameters_)); } } @@ -65,7 +59,7 @@ OpenConnection(); LOG(INFO) << "Sending instance " << instance << " to modality \"" - << remote_.GetApplicationEntityTitle() << "\""; + << parameters_.GetRemoteModality().GetApplicationEntityTitle() << "\""; std::string dicom; @@ -109,7 +103,7 @@ assert(IsStarted()); connection_.reset(NULL); - const std::string& remoteAet = remote_.GetApplicationEntityTitle(); + const std::string& remoteAet = parameters_.GetRemoteModality().GetApplicationEntityTitle(); LOG(INFO) << "Sending storage commitment request to modality: " << remoteAet; @@ -121,8 +115,7 @@ std::vector a(sopClassUids_.begin(), sopClassUids_.end()); std::vector b(sopInstanceUids_.begin(), sopInstanceUids_.end()); - DicomAssociationParameters parameters(localAet_, remote_); - DicomAssociation::RequestStorageCommitment(parameters, transactionUid_, a, b); + DicomAssociation::RequestStorageCommitment(parameters_, transactionUid_, a, b); } } @@ -140,8 +133,6 @@ DicomModalityStoreJob::DicomModalityStoreJob(ServerContext& context) : context_(context), - localAet_("ORTHANC"), - timeout_(-1), moveOriginatorId_(0), // By default, not a C-MOVE storageCommitment_(false) // By default, no storage commitment { @@ -157,7 +148,7 @@ } else { - localAet_ = aet; + parameters_.SetLocalApplicationEntityTitle(aet); } } @@ -170,11 +161,24 @@ } else { - remote_ = remote; + parameters_.SetRemoteModality(remote); } } + void DicomModalityStoreJob::SetTimeout(uint32_t seconds) + { + if (IsStarted()) + { + throw OrthancException(ErrorCode_BadSequenceOfCalls); + } + else + { + parameters_.SetTimeout(seconds); + } + } + + const std::string& DicomModalityStoreJob::GetMoveOriginatorAet() const { if (HasMoveOriginator()) @@ -262,8 +266,8 @@ { SetOfInstancesJob::GetPublicContent(value); - value["LocalAet"] = localAet_; - value["RemoteAet"] = remote_.GetApplicationEntityTitle(); + value["LocalAet"] = parameters_.GetLocalApplicationEntityTitle(); + value["RemoteAet"] = parameters_.GetRemoteModality().GetApplicationEntityTitle(); if (HasMoveOriginator()) { @@ -278,12 +282,9 @@ } - static const char* LOCAL_AET = "LocalAet"; - static const char* REMOTE = "Remote"; static const char* MOVE_ORIGINATOR_AET = "MoveOriginatorAet"; static const char* MOVE_ORIGINATOR_ID = "MoveOriginatorId"; static const char* STORAGE_COMMITMENT = "StorageCommitment"; - static const char* TIMEOUT = "Timeout"; DicomModalityStoreJob::DicomModalityStoreJob(ServerContext& context, @@ -291,15 +292,12 @@ SetOfInstancesJob(serialized), context_(context) { - localAet_ = SerializationToolbox::ReadString(serialized, LOCAL_AET); - remote_ = RemoteModalityParameters(serialized[REMOTE]); moveOriginatorAet_ = SerializationToolbox::ReadString(serialized, MOVE_ORIGINATOR_AET); moveOriginatorId_ = static_cast (SerializationToolbox::ReadUnsignedInteger(serialized, MOVE_ORIGINATOR_ID)); EnableStorageCommitment(SerializationToolbox::ReadBoolean(serialized, STORAGE_COMMITMENT)); - // New in Orthanc in 1.7.0 - timeout_ = SerializationToolbox::ReadInteger(serialized, TIMEOUT, -1); + parameters_ = DicomAssociationParameters::UnserializeJob(serialized); } @@ -311,12 +309,10 @@ } else { - target[LOCAL_AET] = localAet_; - remote_.Serialize(target[REMOTE], true /* force advanced format */); + parameters_.SerializeJob(target); target[MOVE_ORIGINATOR_AET] = moveOriginatorAet_; target[MOVE_ORIGINATOR_ID] = moveOriginatorId_; target[STORAGE_COMMITMENT] = storageCommitment_; - target[TIMEOUT] = timeout_; return true; } } diff -r 2effa961f67f -r ea1d32861cfc OrthancServer/ServerJobs/DicomModalityStoreJob.h --- a/OrthancServer/ServerJobs/DicomModalityStoreJob.h Thu Apr 30 15:00:20 2020 +0200 +++ b/OrthancServer/ServerJobs/DicomModalityStoreJob.h Mon May 04 14:49:31 2020 +0200 @@ -47,9 +47,7 @@ { private: ServerContext& context_; - std::string localAet_; - RemoteModalityParameters remote_; - int timeout_; + DicomAssociationParameters parameters_; std::string moveOriginatorAet_; uint16_t moveOriginatorId_; std::unique_ptr connection_; @@ -75,29 +73,16 @@ DicomModalityStoreJob(ServerContext& context, const Json::Value& serialized); - const std::string& GetLocalAet() const + const DicomAssociationParameters& GetParameters() const { - return localAet_; + return parameters_; } void SetLocalAet(const std::string& aet); - const RemoteModalityParameters& GetRemoteModality() const - { - return remote_; - } - void SetRemoteModality(const RemoteModalityParameters& remote); - void SetTimeout(int timeout) - { - timeout_ = timeout; - } - - int GetTimeout() const - { - return timeout_; - } + void SetTimeout(uint32_t seconds); bool HasMoveOriginator() const { diff -r 2effa961f67f -r ea1d32861cfc OrthancServer/ServerJobs/DicomMoveScuJob.cpp --- a/OrthancServer/ServerJobs/DicomMoveScuJob.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/OrthancServer/ServerJobs/DicomMoveScuJob.cpp Mon May 04 14:49:31 2020 +0200 @@ -98,14 +98,15 @@ if (connection_.get() == NULL) { DicomAssociationParameters params(localAet_, remote_); + + if (timeout_ >= 0) + { + params.SetTimeout(static_cast(timeout_)); + } + connection_.reset(new DicomControlUserConnection(params)); } - if (timeout_ > -1) - { - connection_->SetTimeout(timeout_); - } - connection_->Move(targetAet_, findAnswer); } diff -r 2effa961f67f -r ea1d32861cfc UnitTestsSources/MultiThreadingTests.cpp --- a/UnitTestsSources/MultiThreadingTests.cpp Thu Apr 30 15:00:20 2020 +0200 +++ b/UnitTestsSources/MultiThreadingTests.cpp Mon May 04 14:49:31 2020 +0200 @@ -1514,11 +1514,11 @@ job.reset(unserializer.UnserializeJob(s)); DicomModalityStoreJob& tmp = dynamic_cast(*job); - ASSERT_EQ("LOCAL", tmp.GetLocalAet()); - ASSERT_EQ("REMOTE", tmp.GetRemoteModality().GetApplicationEntityTitle()); - ASSERT_EQ("192.168.1.1", tmp.GetRemoteModality().GetHost()); - ASSERT_EQ(1000, tmp.GetRemoteModality().GetPortNumber()); - ASSERT_EQ(ModalityManufacturer_StoreScp, tmp.GetRemoteModality().GetManufacturer()); + ASSERT_EQ("LOCAL", tmp.GetParameters().GetLocalApplicationEntityTitle()); + ASSERT_EQ("REMOTE", tmp.GetParameters().GetRemoteModality().GetApplicationEntityTitle()); + ASSERT_EQ("192.168.1.1", tmp.GetParameters().GetRemoteModality().GetHost()); + ASSERT_EQ(1000, tmp.GetParameters().GetRemoteModality().GetPortNumber()); + ASSERT_EQ(ModalityManufacturer_StoreScp, tmp.GetParameters().GetRemoteModality().GetManufacturer()); ASSERT_TRUE(tmp.HasMoveOriginator()); ASSERT_EQ("MOVESCU", tmp.GetMoveOriginatorAet()); ASSERT_EQ(42, tmp.GetMoveOriginatorId());