# HG changeset patch # User Sebastien Jodogne # Date 1579199092 -3600 # Node ID 33ba63637d48acf2a9b5b237815943cd06bd1f87 # Parent 05872838ebf3256cc7b608be21b191e7a270297d DicomUserConnection: sending N-EVENT-REPORT-RQ diff -r 05872838ebf3 -r 33ba63637d48 Core/DicomNetworking/DicomUserConnection.cpp --- a/Core/DicomNetworking/DicomUserConnection.cpp Thu Jan 16 18:26:47 2020 +0100 +++ b/Core/DicomNetworking/DicomUserConnection.cpp Thu Jan 16 19:24:52 2020 +0100 @@ -1369,8 +1369,39 @@ } - void DicomUserConnection::ReportStorageCommitment() + static void FillSopSequence(DcmDataset& dataset, + const DcmTagKey& tag, + const std::vector& sopClassUids, + const std::vector& sopInstanceUids) { + for (size_t i = 0; i < sopClassUids.size(); i++) + { + std::auto_ptr item(new DcmItem); + if (!item->putAndInsertString(DCM_ReferencedSOPClassUID, sopClassUids[i].c_str()).good() || + !item->putAndInsertString(DCM_ReferencedSOPInstanceUID, sopInstanceUids[i].c_str()).good() || + !dataset.insertSequenceItem(tag, item.release()).good()) + { + throw OrthancException(ErrorCode_InternalError); + } + } + } + + + + + void DicomUserConnection::ReportStorageCommitment( + const std::string& transactionUid, + const std::vector& successSopClassUids, + const std::vector& successSopInstanceUids, + const std::vector& failureSopClassUids, + const std::vector& failureSopInstanceUids) + { + if (successSopClassUids.size() != successSopInstanceUids.size() || + failureSopClassUids.size() != failureSopInstanceUids.size()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + if (IsOpen()) { Close(); @@ -1389,7 +1420,54 @@ * http://dicom.nema.org/medical/dicom/2019a/output/chtml/part07/chapter_10.html#sect_10.1.1.1.8 **/ - // TODO + T_DIMSE_Message response; + memset(&response, 0, sizeof(response)); + response.CommandField = DIMSE_N_EVENT_REPORT_RQ; + + T_DIMSE_N_EventReportRQ& content = response.msg.NEventReportRQ; + content.MessageID = pimpl_->assoc_->nextMsgID; + strncpy(content.AffectedSOPClassUID, UID_StorageCommitmentPushModelSOPClass, DIC_UI_LEN); + strncpy(content.AffectedSOPInstanceUID, UID_StorageCommitmentPushModelSOPInstance, DIC_UI_LEN); + content.DataSetType = DIMSE_DATASET_PRESENT; + + DcmDataset dataset; + if (!dataset.putAndInsertString(DCM_TransactionUID, transactionUid.c_str()).good()) + { + throw OrthancException(ErrorCode_InternalError); + } + + FillSopSequence(dataset, DCM_ReferencedSOPSequence, successSopClassUids, successSopInstanceUids); + + // http://dicom.nema.org/medical/dicom/2019a/output/chtml/part04/sect_J.3.3.html + if (failureSopClassUids.empty()) + { + content.EventTypeID = 1; // "Storage Commitment Request Successful" + } + else + { + content.EventTypeID = 2; // "Storage Commitment Request Complete - Failures Exist" + FillSopSequence(dataset, DCM_FailedSOPSequence, failureSopClassUids, failureSopInstanceUids); + } + + dataset.writeXML(std::cout); + + int presID = ASC_findAcceptedPresentationContextID( + pimpl_->assoc_, UID_StorageCommitmentPushModelSOPClass); + if (presID == 0) + { + throw OrthancException(ErrorCode_NetworkProtocol, "Storage commitment - " + "Unable to send N-EVENT-REPORT to AET: " + remoteAet_); + } + + if (!DIMSE_sendMessageUsingMemoryData( + pimpl_->assoc_, presID, &response, NULL /* status detail */, + &dataset, NULL /* callback */, NULL /* callback context */, + NULL /* commandSet */).good()) + { + throw OrthancException(ErrorCode_NetworkProtocol); + } + + // TODO - Read answer Close(); } diff -r 05872838ebf3 -r 33ba63637d48 Core/DicomNetworking/DicomUserConnection.h --- a/Core/DicomNetworking/DicomUserConnection.h Thu Jan 16 18:26:47 2020 +0100 +++ b/Core/DicomNetworking/DicomUserConnection.h Thu Jan 16 19:24:52 2020 +0100 @@ -225,6 +225,11 @@ bool IsSameAssociation(const std::string& localAet, const RemoteModalityParameters& remote) const; - void ReportStorageCommitment(); + void ReportStorageCommitment( + const std::string& transactionUid, + const std::vector& successSopClassUids, + const std::vector& successSopInstanceUids, + const std::vector& failureSopClassUids, + const std::vector& failureSopInstanceUids); }; } diff -r 05872838ebf3 -r 33ba63637d48 OrthancServer/main.cpp --- a/OrthancServer/main.cpp Thu Jan 16 18:26:47 2020 +0100 +++ b/OrthancServer/main.cpp Thu Jan 16 19:24:52 2020 +0100 @@ -96,6 +96,24 @@ private: ServerContext& server_; + // TODO - Remove this + static void Toto() + { + printf("Sleeping\n"); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + printf("Connect back\n"); + + RemoteModalityParameters p("STGCMTSCU", "localhost", 11114, ModalityManufacturer_Generic); + DicomUserConnection scu("ORTHANC", p); + + std::vector a, b, c, d; + a.push_back("a"); b.push_back("b"); + a.push_back("c"); b.push_back("d"); + + //scu.ReportStorageCommitment("transaction", a, b, c, d); + scu.ReportStorageCommitment("transaction", a, b, a, b); + } + public: OrthancStorageCommitmentRequestHandler(ServerContext& context) : server_(context) @@ -110,6 +128,8 @@ const std::string& calledAet) { // TODO - Enqueue a Storage commitment job + + boost::thread t(Toto); } };