123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- #include "ctkDICOMSCP.h"
- // DCMTK includes
- #include <dcmtk/dcmqrdb/dcmqrsrv.h>
- // Qt includes
- #include <QtConcurrentRun>
- // CTK includes
- #include "ctkLogger.h"
- static ctkLogger logger ( "org.commontk.dicom.DcmSCP" );
- class ctkDICOMSCPPrivate
- {
- public:
- ctkDICOMSCPPrivate(ctkDICOMSCP* parent);
- ~ctkDICOMSCPPrivate();
- QString aeTitle;
- int port;
- int maxPDU;
- int maxAssociation;
- int acseTimeout;
- bool isGetEnabled;
- bool isPatientRootEnabled;
- bool isStudyRootEnabled;
- bool isPatientStudyOnlyEnabled;
- bool isShutdownAllowed;
- bool isThreadingEnabled;
- bool terminateRequested;
- /** wait for incoming A-ASSOCIATE requests, perform association negotiation
- * and serve the requests. May fork child processes depending on availability
- * of the fork() system function and configuration options.
- * @param theNet network structure for listen socket
- * @return EC_Normal if successful, an error code otherwise
- */
- OFCondition waitForAssociation(T_ASC_Network *theNet);
- OFCondition negotiateAssociation(T_ASC_Association * assoc);
- OFCondition refuseAssociation(T_ASC_Association ** assoc, CTN_RefuseReason reason);
- OFCondition handleAssociation(T_ASC_Association * assoc, OFBool correctUIDPadding);
- OFCondition dispatch(T_ASC_Association *assoc, OFBool correctUIDPadding);
- void threadedStartServer();
- void threadedHandleAssociation(T_ASC_Association * assoc,
- OFBool correctUIDPadding);
- QMap<T_DIMSE_Command, ctkDICOMSCP*> registeredSCPs;
- T_ASC_Network* network;
- private:
- ctkDICOMSCP* q_ptr;
- Q_DECLARE_PUBLIC(ctkDICOMSCP);
- };
- //------------------------------------------------------------------------------
- // ctkDICOMSCPPrivate class methods
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- ctkDICOMSCPPrivate::ctkDICOMSCPPrivate(ctkDICOMSCP *parent):
- q_ptr(parent)
- {
- this->aeTitle = "AETitle";
- this->port = 104;
- this->maxPDU = 100000;
- this->maxAssociation = 20;
- this->acseTimeout = 30;
- this->isGetEnabled = false;
- this->isPatientRootEnabled = false;
- this->isStudyRootEnabled = true;
- this->isPatientStudyOnlyEnabled = false;
- this->isShutdownAllowed = true;
- this->terminateRequested = false;
- this->isThreadingEnabled = true;
- this->network = new T_ASC_Network();
- }
- //------------------------------------------------------------------------------
- ctkDICOMSCPPrivate::~ctkDICOMSCPPrivate()
- {
- delete this->network;
- }
- //------------------------------------------------------------------------------
- OFCondition ctkDICOMSCPPrivate::waitForAssociation(T_ASC_Network * theNet)
- {
- Q_Q(ctkDICOMSCP);
- OFCondition cond = EC_Normal;
- OFString temp_str;
- T_ASC_Association *assoc;
- char buf[BUFSIZ];
- int timeout = 1000;
- OFBool go_cleanup = OFFalse;
- if (ASC_associationWaiting(theNet, timeout))
- {
- cond = ASC_receiveAssociation(theNet, &assoc, this->maxPDU);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.debug(QString("Failed to receive association: ") + temp_str.c_str());
- go_cleanup = OFTrue;
- }
- } else return EC_Normal;
- if (! go_cleanup)
- {
- logger.info(QString("Association Received (") + assoc->params->DULparams.callingPresentationAddress
- + ":" + assoc->params->DULparams.callingAPTitle + " -> "
- + assoc->params->DULparams.calledAPTitle + ")");
- ASC_dumpParameters(temp_str, assoc->params, ASC_ASSOC_RQ);
- logger.debug(QString("Parameters:") + temp_str.c_str());
- }
- if (! go_cleanup)
- {
- /* Application Context Name */
- cond = ASC_getApplicationContextName(assoc->params, buf);
- if (cond.bad() || strcmp(buf, DICOM_STDAPPLICATIONCONTEXT) != 0)
- {
- /* reject: the application context name is not supported */
- logger.info(QString("Bad AppContextName: ") + buf);
- cond = this->refuseAssociation(&assoc, CTN_BadAppContext);
- go_cleanup = OFTrue;
- }
- }
- if (! go_cleanup)
- {
- /* Implementation Class UID */
- if (strlen(assoc->params->theirImplementationClassUID) == 0)
- {
- /* reject: no implementation Class UID provided */
- logger.info(QString("No implementation Class UID provided"));
- cond = this->refuseAssociation(&assoc, CTN_NoReason);
- go_cleanup = OFTrue;
- }
- }
- // TODO: Check whether peer is in AETitle list
- /*
- if (! go_cleanup)
- {
- // Does peer AE have access to required service ??
- if (! config_->peerInAETitle(assoc->params->DULparams.calledAPTitle,
- assoc->params->DULparams.callingAPTitle,
- assoc->params->DULparams.callingPresentationAddress))
- {
- DCMQRDB_DEBUG("Peer "
- << assoc->params->DULparams.callingPresentationAddress << ":"
- << assoc->params->DULparams.callingAPTitle << " is not not permitted to access "
- << assoc->params->DULparams.calledAPTitle << " (see configuration file)");
- cond = refuseAssociation(&assoc, CTN_BadAEService);
- go_cleanup = OFTrue;
- }
- }
- */
- // TODO: Check if the number of associations exceeds the maximum number of associations
- /*
- if (! go_cleanup)
- {
- // too many concurrent associations ??
- if (processtable_.countChildProcesses() >= OFstatic_cast(size_t, d->maxAssociation))
- {
- cond = d->refuseAssociation(&assoc, CTN_TooManyAssociations);
- go_cleanup = OFTrue;
- }
- }
- */
- if (! go_cleanup)
- {
- cond = this->negotiateAssociation(assoc);
- if (cond.bad()) go_cleanup = OFTrue;
- }
- if (! go_cleanup)
- {
- cond = ASC_acknowledgeAssociation(assoc);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString(temp_str.c_str()));
- go_cleanup = OFTrue;
- }
- }
- if (! go_cleanup)
- {
- logger.debug(QString("Association Acknowledged (Max Send PDV: ") + QString::number(assoc->sendPDVLength) + ")");
- QtConcurrent::run(this, &ctkDICOMSCPPrivate::threadedHandleAssociation, assoc, false);
- return EC_Normal;
- }
- // cleanup code
- OFCondition oldcond = cond; /* store condition flag for later use */
- if (cond != ASC_SHUTDOWNAPPLICATION)
- {
- /* the child will handle the association, we can drop it */
- cond = ASC_dropAssociation(assoc);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot Drop Association: ") + temp_str.c_str());
- }
- cond = ASC_destroyAssociation(&assoc);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot Destroy Association: ") + temp_str.c_str());
- }
- }
- if (oldcond == ASC_SHUTDOWNAPPLICATION) cond = oldcond; /* abort flag is reported to top-level wait loop */
- return cond;
- }
- //------------------------------------------------------------------------------
- OFCondition ctkDICOMSCPPrivate::negotiateAssociation(T_ASC_Association * assoc)
- {
- OFCondition cond = EC_Normal;
- int i;
- OFString temp_str;
- struct { const char *moveSyntax, *findSyntax; } queryRetrievePairs[] =
- {
- { UID_MOVEPatientRootQueryRetrieveInformationModel,
- UID_FINDPatientRootQueryRetrieveInformationModel },
- { UID_MOVEStudyRootQueryRetrieveInformationModel,
- UID_FINDStudyRootQueryRetrieveInformationModel },
- { UID_RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel,
- UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel }
- };
- DIC_AE calledAETitle;
- ASC_getAPTitles(assoc->params, NULL, calledAETitle, NULL);
- const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
- transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax;
- transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax;
- transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax;
- int numTransferSyntaxes = 3;
- const char * const nonStorageSyntaxes[] =
- {
- UID_VerificationSOPClass,
- UID_FINDPatientRootQueryRetrieveInformationModel,
- UID_MOVEPatientRootQueryRetrieveInformationModel,
- UID_GETPatientRootQueryRetrieveInformationModel,
- #ifndef NO_PATIENTSTUDYONLY_SUPPORT
- UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel,
- UID_RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel,
- UID_RETIRED_GETPatientStudyOnlyQueryRetrieveInformationModel,
- #endif
- UID_FINDStudyRootQueryRetrieveInformationModel,
- UID_MOVEStudyRootQueryRetrieveInformationModel,
- UID_GETStudyRootQueryRetrieveInformationModel,
- UID_PrivateShutdownSOPClass
- };
- const int numberOfNonStorageSyntaxes = DIM_OF(nonStorageSyntaxes);
- const char *selectedNonStorageSyntaxes[DIM_OF(nonStorageSyntaxes)];
- int numberOfSelectedNonStorageSyntaxes = 0;
- for (i = 0; i < numberOfNonStorageSyntaxes; i++)
- {
- if (0 == strcmp(nonStorageSyntaxes[i], UID_FINDPatientRootQueryRetrieveInformationModel))
- {
- if (this->isPatientRootEnabled) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_MOVEPatientRootQueryRetrieveInformationModel))
- {
- if (this->isPatientRootEnabled) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_GETPatientRootQueryRetrieveInformationModel))
- {
- if (this->isPatientRootEnabled && (this->isGetEnabled)) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_RETIRED_FINDPatientStudyOnlyQueryRetrieveInformationModel))
- {
- if (this->isPatientStudyOnlyEnabled) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_RETIRED_MOVEPatientStudyOnlyQueryRetrieveInformationModel))
- {
- if (this->isPatientStudyOnlyEnabled) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_RETIRED_GETPatientStudyOnlyQueryRetrieveInformationModel))
- {
- if (this->isPatientStudyOnlyEnabled && (this->isGetEnabled)) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_FINDStudyRootQueryRetrieveInformationModel))
- {
- if (this->isStudyRootEnabled) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_MOVEStudyRootQueryRetrieveInformationModel))
- {
- if (this->isStudyRootEnabled) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_GETStudyRootQueryRetrieveInformationModel))
- {
- if (this->isStudyRootEnabled && (this->isGetEnabled)) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- else if (0 == strcmp(nonStorageSyntaxes[i], UID_PrivateShutdownSOPClass))
- {
- if (this->isShutdownAllowed) selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- } else {
- selectedNonStorageSyntaxes[numberOfSelectedNonStorageSyntaxes++] = nonStorageSyntaxes[i];
- }
- }
- /* accept any of the non-storage syntaxes */
- cond = ASC_acceptContextsWithPreferredTransferSyntaxes(
- assoc->params,
- (const char**)selectedNonStorageSyntaxes, numberOfSelectedNonStorageSyntaxes,
- (const char**)transferSyntaxes, numTransferSyntaxes);
- if (cond.bad()) {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot accept presentation contexts: ") + temp_str.c_str());
- }
- /* accept any of the storage syntaxes */
- if (!this->isGetEnabled)
- {
- /* accept storage syntaxes with default role only */
- cond = ASC_acceptContextsWithPreferredTransferSyntaxes(
- assoc->params,
- dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs,
- (const char**)transferSyntaxes, DIM_OF(transferSyntaxes));
- if (cond.bad()) {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot accept presentation contexts: ") + temp_str.c_str());
- }
- } else {
- /* accept storage syntaxes with proposed role */
- T_ASC_PresentationContext pc;
- T_ASC_SC_ROLE role;
- int npc = ASC_countPresentationContexts(assoc->params);
- for (i = 0; i < npc; i++)
- {
- ASC_getPresentationContext(assoc->params, i, &pc);
- if (dcmIsaStorageSOPClassUID(pc.abstractSyntax))
- {
- /*
- ** We are prepared to accept whatever role he proposes.
- ** Normally we can be the SCP of the Storage Service Class.
- ** When processing the C-GET operation we can be the SCU of the Storage Service Class.
- */
- role = pc.proposedRole;
- /*
- ** Accept in the order "least wanted" to "most wanted" transfer
- ** syntax. Accepting a transfer syntax will override previously
- ** accepted transfer syntaxes.
- */
- for (int k = numTransferSyntaxes - 1; k >= 0; k--)
- {
- for (int j = 0; j < (int)pc.transferSyntaxCount; j++)
- {
- /* if the transfer syntax was proposed then we can accept it
- * appears in our supported list of transfer syntaxes
- */
- if (strcmp(pc.proposedTransferSyntaxes[j], transferSyntaxes[k]) == 0)
- {
- cond = ASC_acceptPresentationContext(
- assoc->params, pc.presentationContextID, transferSyntaxes[k], role);
- if (cond.bad()) return cond;
- }
- }
- }
- }
- } /* for */
- } /* else */
- /*
- * check if we have negotiated the private "shutdown" SOP Class
- */
- if (0 != ASC_findAcceptedPresentationContextID(assoc, UID_PrivateShutdownSOPClass))
- {
- logger.info(QString("Shutting down server ... (negotiated private \"shut down\" SOP class)"));
- this->refuseAssociation(&assoc, CTN_NoReason);
- return ASC_SHUTDOWNAPPLICATION;
- }
- return cond;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCPPrivate::threadedStartServer()
- {
- OFCondition cond = ASC_initializeNetwork(NET_ACCEPTORREQUESTOR, this->port, this->acseTimeout, &this->network);
- if(cond.bad()) {
- logger.error(QString("Failed to initialize network"));
- }
- while(!this->terminateRequested && cond.good())
- {
- cond = this->waitForAssociation(this->network);
- }
- cond = ASC_dropNetwork(&this->network);
- if(cond.bad()) {
- logger.debug(QString("Cannot drop network"));
- }
- this->terminateRequested = false;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCPPrivate::threadedHandleAssociation(T_ASC_Association *assoc, bool correctUIDPadding)
- {
- this->handleAssociation(assoc, correctUIDPadding);
- }
- //------------------------------------------------------------------------------
- OFCondition ctkDICOMSCPPrivate::refuseAssociation(T_ASC_Association ** assoc, CTN_RefuseReason reason)
- {
- OFCondition cond = EC_Normal;
- T_ASC_RejectParameters rej;
- OFString temp_str;
- const char *reason_string;
- switch (reason)
- {
- case CTN_TooManyAssociations:
- reason_string = "TooManyAssociations";
- break;
- case CTN_CannotFork:
- reason_string = "CannotFork";
- break;
- case CTN_BadAppContext:
- reason_string = "BadAppContext";
- break;
- case CTN_BadAEPeer:
- reason_string = "BadAEPeer";
- break;
- case CTN_BadAEService:
- reason_string = "BadAEService";
- break;
- case CTN_NoReason:
- reason_string = "NoReason";
- break;
- default:
- reason_string = "???";
- break;
- }
- logger.info(QString("Refusing Association (") + reason_string + ")");
- switch (reason)
- {
- case CTN_TooManyAssociations:
- rej.result = ASC_RESULT_REJECTEDTRANSIENT;
- rej.source = ASC_SOURCE_SERVICEPROVIDER_PRESENTATION_RELATED;
- rej.reason = ASC_REASON_SP_PRES_LOCALLIMITEXCEEDED;
- break;
- case CTN_CannotFork:
- rej.result = ASC_RESULT_REJECTEDPERMANENT;
- rej.source = ASC_SOURCE_SERVICEPROVIDER_PRESENTATION_RELATED;
- rej.reason = ASC_REASON_SP_PRES_TEMPORARYCONGESTION;
- break;
- case CTN_BadAppContext:
- rej.result = ASC_RESULT_REJECTEDTRANSIENT;
- rej.source = ASC_SOURCE_SERVICEUSER;
- rej.reason = ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED;
- break;
- case CTN_BadAEPeer:
- rej.result = ASC_RESULT_REJECTEDPERMANENT;
- rej.source = ASC_SOURCE_SERVICEUSER;
- rej.reason = ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED;
- break;
- case CTN_BadAEService:
- rej.result = ASC_RESULT_REJECTEDPERMANENT;
- rej.source = ASC_SOURCE_SERVICEUSER;
- rej.reason = ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED;
- break;
- case CTN_NoReason:
- default:
- rej.result = ASC_RESULT_REJECTEDPERMANENT;
- rej.source = ASC_SOURCE_SERVICEUSER;
- rej.reason = ASC_REASON_SU_NOREASON;
- break;
- }
- cond = ASC_rejectAssociation(*assoc, &rej);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Association Reject Failed: ") + temp_str.c_str());
- }
- cond = ASC_dropAssociation(*assoc);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot Drop Association: ") + temp_str.c_str());
- }
- cond = ASC_destroyAssociation(assoc);
- if (cond.bad())
- {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot Destroy Association: ") + temp_str.c_str());
- }
- return cond;
- }
- //------------------------------------------------------------------------------
- OFCondition ctkDICOMSCPPrivate::handleAssociation(T_ASC_Association * assoc, OFBool correctUIDPadding)
- {
- OFCondition cond = EC_Normal;
- DIC_NODENAME peerHostName;
- DIC_AE peerAETitle;
- DIC_AE myAETitle;
- OFString temp_str;
- ASC_getPresentationAddresses(assoc->params, peerHostName, NULL);
- ASC_getAPTitles(assoc->params, peerAETitle, myAETitle, NULL);
- /* now do the real work */
- cond = dispatch(assoc, correctUIDPadding);
- /* clean up on association termination */
- if (cond == DUL_PEERREQUESTEDRELEASE) {
- logger.info("Association Release");
- cond = ASC_acknowledgeRelease(assoc);
- ASC_dropSCPAssociation(assoc);
- } else if (cond == DUL_PEERABORTEDASSOCIATION) {
- logger.info("Association Aborted");
- } else {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("DIMSE Failure (aborting association): ") + temp_str.c_str());
- /* some kind of error so abort the association */
- cond = ASC_abortAssociation(assoc);
- }
- cond = ASC_dropAssociation(assoc);
- if (cond.bad()) {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot Drop Association: ") + temp_str.c_str());
- }
- cond = ASC_destroyAssociation(&assoc);
- if (cond.bad()) {
- DimseCondition::dump(temp_str, cond);
- logger.error(QString("Cannot Destroy Association: ") + temp_str.c_str());
- }
- return cond;
- }
- //------------------------------------------------------------------------------
- OFCondition ctkDICOMSCPPrivate::dispatch(T_ASC_Association *assoc, OFBool correctUIDPadding)
- {
- OFCondition cond = EC_Normal;
- T_DIMSE_Message msg;
- T_ASC_PresentationContextID presID;
- // this while loop is executed exactly once unless the "keepDBHandleDuringAssociation_"
- // flag is not set, in which case the inner loop is executed only once and this loop
- // repeats for each incoming DIMSE command. In this case, the DB handle is created
- // and released for each DIMSE command.
- while (cond.good())
- {
- // this while loop is executed exactly once unless the "keepDBHandleDuringAssociation_"
- // flag is set, in which case the DB handle remains open until something goes wrong
- // or the remote peer closes the association
- while (cond.good())
- {
- cond = DIMSE_receiveCommand(assoc, DIMSE_BLOCKING, 0, &presID, &msg, NULL);
- /* did peer release, abort, or do we have a valid message ? */
- if (cond.good())
- {
- /* process command */
- if(msg.CommandField == DIMSE_C_CANCEL_RQ)
- {
- logger.info("dispatch: late C-CANCEL-RQ, ignoring");
- }
- else
- {
- if(this->registeredSCPs.contains(msg.CommandField))
- {
- cond = this->registeredSCPs[msg.CommandField]->handleRequest(assoc, msg, presID);
- }
- else
- {
- /* we cannot handle this kind of message */
- cond = DIMSE_BADCOMMANDTYPE;
- logger.error(QString("Cannot handle command: ") + (unsigned)msg.CommandField);
- }
- }
- }
- else if ((cond == DUL_PEERREQUESTEDRELEASE)||(cond == DUL_PEERABORTEDASSOCIATION))
- {
- // association gone
- }
- else
- {
- // the condition will be returned, the caller will abort the assosiation.
- }
- }
- }
- // Association done
- return cond;
- }
- //------------------------------------------------------------------------------
- // ctkDICOMSCP class methods
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- ctkDICOMSCP::ctkDICOMSCP(QObject *parent) :
- QObject(parent),
- d_ptr(new ctkDICOMSCPPrivate(this))
- {
- this->dimseCommand = DIMSE_NOTHING;
- }
- //------------------------------------------------------------------------------
- ctkDICOMSCP::~ctkDICOMSCP()
- {
- delete d_ptr;
- }
- //------------------------------------------------------------------------------
- T_DIMSE_Command ctkDICOMSCP::getDimseCommand()
- {
- return this->dimseCommand;
- }
- //------------------------------------------------------------------------------
- bool ctkDICOMSCP::registerSCP(ctkDICOMSCP *scp)
- {
- Q_D(ctkDICOMSCP);
- if(!scp)
- {
- return false;
- }
- T_DIMSE_Command command = scp->getDimseCommand();
- if(d->registeredSCPs.contains(command))
- {
- return false;
- }
- scp->setParent(this);
- d->registeredSCPs[command] = scp;
- return true;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setAETitle(const QString& aeTitle)
- {
- Q_D(ctkDICOMSCP);
- d->aeTitle = aeTitle;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setPort(int port)
- {
- Q_D(ctkDICOMSCP);
- d->port = port;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setEnableThreading(bool flag)
- {
- Q_D(ctkDICOMSCP);
- d->isThreadingEnabled = flag;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setMaxPDU(int size)
- {
- Q_D(ctkDICOMSCP);
- d->maxPDU = size;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setMaxAssociations(int count)
- {
- Q_D(ctkDICOMSCP);
- d->maxAssociation = count;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setEnableGetSupport(bool flag)
- {
- Q_D(ctkDICOMSCP);
-
- d->isGetEnabled = flag;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setEnablePatientRoot(bool flag)
- {
- Q_D(ctkDICOMSCP);
- d->isPatientRootEnabled = flag;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::setEnableStudyRoot(bool flag)
- {
- Q_D(ctkDICOMSCP);
- d->isStudyRootEnabled = flag;
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::start()
- {
- Q_D(ctkDICOMSCP);
- if(d->isThreadingEnabled)
- {
- QtConcurrent::run(d, &ctkDICOMSCPPrivate::threadedStartServer);
- }
- else
- {
- d->threadedStartServer();
- }
- }
- //------------------------------------------------------------------------------
- void ctkDICOMSCP::stop()
- {
- Q_D(ctkDICOMSCP);
- d->terminateRequested = true;
- }
|