Mercurial > hg > orthanc
diff OrthancFramework/Sources/DicomNetworking/Internals/GetScp.cpp @ 4258:6f5d4bfb2c90
C-GET SCP: Fix responses and handling of cancel
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 26 Oct 2020 12:23:36 +0100 |
parents | 7112a8af0b63 |
children | 756126cd2219 |
line wrap: on
line diff
--- a/OrthancFramework/Sources/DicomNetworking/Internals/GetScp.cpp Tue Oct 20 09:52:42 2020 +0200 +++ b/OrthancFramework/Sources/DicomNetworking/Internals/GetScp.cpp Mon Oct 26 12:23:36 2020 +0100 @@ -99,12 +99,14 @@ std::string remoteAet_; std::string calledAet_; int timeout_; + bool canceled_; GetScpData() : handler_(NULL), lastRequest_(NULL), assoc_(NULL), - timeout_(0) + timeout_(0), + canceled_(false) { }; }; @@ -129,6 +131,56 @@ } } + + static void FillResponse(T_DIMSE_C_GetRSP& response, + DcmDataset** failedIdentifiers, + const IGetRequestHandler& handler) + { + response.DimseStatus = STATUS_Success; + + size_t processedCount = (handler.GetCompletedCount() + + handler.GetFailedCount() + + handler.GetWarningCount()); + + if (processedCount > handler.GetSubOperationCount()) + { + throw OrthancException(ErrorCode_InternalError); + } + + response.NumberOfRemainingSubOperations = (handler.GetSubOperationCount() - processedCount); + response.NumberOfCompletedSubOperations = handler.GetCompletedCount(); + response.NumberOfFailedSubOperations = handler.GetFailedCount(); + response.NumberOfWarningSubOperations = handler.GetWarningCount(); + + // http://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_C.4.3.3.html + + if (handler.GetFailedCount() > 0 || + handler.GetWarningCount() > 0) + { + /** + * "Warning if one or more sub-operations were successfully + * completed and one or more sub-operations were unsuccessful + * or had a status of warning. Warning if all sub-operations + * had a status of Warning" + **/ + response.DimseStatus = STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures; + } + + if (handler.GetFailedCount() > 0 && + handler.GetFailedCount() == handler.GetSubOperationCount()) + { + /** + * "Failure or Refused if all sub-operations were + * unsuccessful." => We choose to generate a "Refused - Out + * of Resources - Unable to perform suboperations" status. + */ + response.DimseStatus = STATUS_GET_Refused_OutOfResourcesSubOperations; + } + + *failedIdentifiers = BuildFailedInstanceList(handler.GetFailedUids()); + } + + static void GetScpCallback( /* in */ void *callbackData, @@ -141,6 +193,9 @@ DcmDataset **responseIdentifiers, DcmDataset **statusDetail) { + assert(response != NULL); + assert(responseIdentifiers != NULL); + bzero(response, sizeof(T_DIMSE_C_GetRSP)); *statusDetail = NULL; *responseIdentifiers = NULL; @@ -180,68 +235,52 @@ return; } - if (data.handler_->GetRemainingCount() == 0) + if (data.canceled_) { - response->DimseStatus = STATUS_Success; + LOG(ERROR) << "IGetRequestHandler Failed: Cannot pursue a request that was canceled by the SCU"; + response->DimseStatus = STATUS_GET_Failed_UnableToProcess; + return; + } + + if (data.handler_->GetSubOperationCount() == + data.handler_->GetCompletedCount() + + data.handler_->GetFailedCount() + + data.handler_->GetWarningCount()) + { + // We're all done + FillResponse(*response, responseIdentifiers, *data.handler_); } else { - IGetRequestHandler::Status status; - + bool isContinue; + try { - status = data.handler_->DoNext(data.assoc_); + isContinue = data.handler_->DoNext(data.assoc_); } catch (OrthancException& e) { // Internal error! LOG(ERROR) << "IGetRequestHandler Failed: " << e.What(); + FillResponse(*response, responseIdentifiers, *data.handler_); + + // Fix the status code that is computed by "FillResponse()" response->DimseStatus = STATUS_GET_Failed_UnableToProcess; return; } - - if (status == STATUS_Success) + + FillResponse(*response, responseIdentifiers, *data.handler_); + + if (isContinue) { - if (responseCount < static_cast<int>(data.handler_->GetRemainingCount())) - { - response->DimseStatus = STATUS_Pending; - } - else - { - response->DimseStatus = STATUS_Success; - } + response->DimseStatus = STATUS_Pending; } else { - response->DimseStatus = STATUS_GET_Failed_UnableToProcess; - - if (data.handler_->GetFailedCount() > 0 || - data.handler_->GetWarningCount() > 0) - { - response->DimseStatus = STATUS_GET_Warning_SubOperationsCompleteOneOrMoreFailures; - } - - /* - * if all the sub-operations failed then we need to generate - * a failed or refused status. cf. DICOM part 4, C.4.3.3.1 - * we choose to generate a "Refused - Out of Resources - - * Unable to perform suboperations" status. - */ - if ((data.handler_->GetFailedCount() > 0) && - ((data.handler_->GetCompletedCount() + - data.handler_->GetWarningCount()) == 0)) - { - response->DimseStatus = STATUS_GET_Refused_OutOfResourcesSubOperations; - } - - *responseIdentifiers = BuildFailedInstanceList(data.handler_->GetFailedUids()); + response->DimseStatus = STATUS_GET_Cancel_SubOperationsTerminatedDueToCancelIndication; + data.canceled_ = true; } } - - response->NumberOfRemainingSubOperations = data.handler_->GetRemainingCount(); - response->NumberOfCompletedSubOperations = data.handler_->GetCompletedCount(); - response->NumberOfFailedSubOperations = data.handler_->GetFailedCount(); - response->NumberOfWarningSubOperations = data.handler_->GetWarningCount(); } }