OFCondition Association::Drop(OFCondition cond) { // tear down association if (cond == EC_Normal) { /* release association */ cond = ASC_releaseAssociation(assoc); } else if (cond == DUL_PEERREQUESTEDRELEASE) { cond = ASC_acknowledgeRelease(assoc); if (cond.good()) { cond = ASC_abortAssociation(assoc); if (cond.good()) { return cond; } } } else if (cond == DUL_PEERABORTEDASSOCIATION) { return cond; } else { cond = ASC_abortAssociation(assoc); if (cond.good()) { return cond; } } Destroy(); return cond; }
void Association ::drop() { if(!this->is_associated()) { throw Exception("Not associated"); } ASC_acknowledgeRelease(this->_association); ASC_dropSCPAssociation(this->_association); ASC_destroyAssociation(&this->_association); this->_association = NULL; }
bool CommandDispatcher::Step() /* * This function receives DIMSE commmands over the network connection * and handles these commands correspondingly. Note that in case of * storscp only C-ECHO-RQ and C-STORE-RQ commands can be processed. */ { bool finished = false; // receive a DIMSE command over the network, with a timeout of 1 second DcmDataset *statusDetail = NULL; T_ASC_PresentationContextID presID = 0; T_DIMSE_Message msg; OFCondition cond = DIMSE_receiveCommand(assoc_, DIMSE_NONBLOCKING, 1, &presID, &msg, &statusDetail); elapsedTimeSinceLastCommand_++; // if the command which was received has extra status // detail information, dump this information if (statusDetail != NULL) { //LOG4CPP_WARN(Internals::GetLogger(), "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); delete statusDetail; } if (cond == DIMSE_OUTOFRESOURCES) { finished = true; } else if (cond == DIMSE_NODATAAVAILABLE) { // Timeout due to DIMSE_NONBLOCKING if (clientTimeout_ != 0 && elapsedTimeSinceLastCommand_ >= clientTimeout_) { // This timeout is actually a client timeout finished = true; } } else if (cond == EC_Normal) { // Reset the client timeout counter elapsedTimeSinceLastCommand_ = 0; // in case we received a valid message, process this command // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ switch (msg.CommandField) { case DIMSE_C_ECHO_RQ: // process C-ECHO-Request cond = EchoScp(assoc_, &msg, presID); break; case DIMSE_C_STORE_RQ: // process C-STORE-Request if (server_.HasStoreRequestHandlerFactory()) { std::auto_ptr<IStoreRequestHandler> handler (server_.GetStoreRequestHandlerFactory().ConstructStoreRequestHandler()); cond = Internals::storeScp(assoc_, &msg, presID, *handler); } else cond = DIMSE_BADCOMMANDTYPE; // Should never happen break; case DIMSE_C_MOVE_RQ: // process C-MOVE-Request if (server_.HasMoveRequestHandlerFactory()) { std::auto_ptr<IMoveRequestHandler> handler (server_.GetMoveRequestHandlerFactory().ConstructMoveRequestHandler()); cond = Internals::moveScp(assoc_, &msg, presID, *handler); } else cond = DIMSE_BADCOMMANDTYPE; // Should never happen break; case DIMSE_C_FIND_RQ: // process C-FIND-Request if (server_.HasFindRequestHandlerFactory()) { std::auto_ptr<IFindRequestHandler> handler (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler()); cond = Internals::findScp(assoc_, &msg, presID, *handler); } else cond = DIMSE_BADCOMMANDTYPE; // Should never happen break; default: // we cannot handle this kind of message cond = DIMSE_BADCOMMANDTYPE; LOG(ERROR) << "cannot handle command: 0x" << std::hex << msg.CommandField; break; } } else { // Bad status, which indicates the closing of the connection by // the peer or a network error finished = true; } if (finished) { if (cond == DUL_PEERREQUESTEDRELEASE) { LOG(INFO) << "Association Release"; ASC_acknowledgeRelease(assoc_); } else if (cond == DUL_PEERABORTEDASSOCIATION) { LOG(INFO) << "Association Aborted"; } else { OFString temp_str; LOG(ERROR) << "DIMSE failure (aborting association): " << cond.text(); /* some kind of error so abort the association */ ASC_abortAssociation(assoc_); } } return !finished; }
OFCondition RetrieveDICOMFilesFromPACS::subOperationSCP(T_ASC_Association **subAssociation) { // Ens convertim com en un servei. El PACS ens fa peticions que nosaltres hem de respondre, ens pot demanar descarregar una imatge o fer un echo T_DIMSE_Message dimseMessage; T_ASC_PresentationContextID presentationContextID; if (!ASC_dataWaiting(*subAssociation, 0)) { return DIMSE_NODATAAVAILABLE; } OFCondition condition = DIMSE_receiveCommand(*subAssociation, DIMSE_BLOCKING, 0, &presentationContextID, &dimseMessage, NULL); if (condition == EC_Normal) { switch (dimseMessage.CommandField) { case DIMSE_C_STORE_RQ: condition = storeSCP(*subAssociation, &dimseMessage, presentationContextID); break; case DIMSE_C_ECHO_RQ: condition = echoSCP(*subAssociation, &dimseMessage, presentationContextID); break; default: ERROR_LOG("El PACS ens ha sol.licitat un tipus d'operacio invalida"); condition = DIMSE_BADCOMMANDTYPE; break; } } // Clean up on association termination if (condition == DUL_PEERREQUESTEDRELEASE) { INFO_LOG("El PACS sol.licita tancar la connexio per on ens ha enviat els fitxers"); condition = ASC_acknowledgeRelease(*subAssociation); ASC_dropSCPAssociation(*subAssociation); ASC_destroyAssociation(subAssociation); return condition; } else if (condition == DUL_PEERABORTEDASSOCIATION) { INFO_LOG("El PACS ha abortat la connexió"); } else if (condition != EC_Normal) { ERROR_LOG("S'ha produit un error reben la peticio d'una suboperacio, descripcio error: " + QString(condition.text())); condition = ASC_abortAssociation(*subAssociation); } else if (m_abortIsRequested) { INFO_LOG("Abortarem les connexions amb el PACS, perque han sol.licitant cancel.lar la descarrega"); condition = ASC_abortAssociation(*subAssociation); if (!condition.good()) { ERROR_LOG("Error al abortar la connexio pel qual rebem les imatges" + QString(condition.text())); } // Tanquem la connexió amb el PACS perquè segons indica la documentació DICOM al PS 3.4 (Baseline Behavior of SCP) C.4.2.3.1 si abortem // la connexió per la qual rebem les imatges, el comportament del PACS és desconegut, per exemple DCM4CHEE tanca la connexió amb el PACS, però // el RAIM_Server no la tanca i la manté fent que no sortim mai d'aquesta classe. Degut a que no es pot saber en aquesta situació com actuaran // els PACS es tanca aquí la connexió amb el PACS. condition = ASC_abortAssociation(m_pacsConnection->getConnection()); if (!condition.good()) { ERROR_LOG("Error al abortar la connexio pel amb el PACS" + QString(condition.text())); } else { INFO_LOG("Abortada la connexio amb el PACS"); } } if (condition != EC_Normal) { ASC_dropAssociation(*subAssociation); ASC_destroyAssociation(subAssociation); } return condition; }