ctkDICOMFindSCP.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include "ctkDICOMFindSCP.h"
  2. // DCMTK includes
  3. #include <dcmtk/dcmdata/dcdatset.h>
  4. #include <dcmtk/dcmdata/dcdeftag.h>
  5. #include <dcmtk/dcmnet/diutil.h>
  6. #include <dcmtk/dcmqrdb/dcmqrcbf.h>
  7. #include <dcmtk/dcmqrdb/dcmqrdbs.h>
  8. // ctk includes
  9. #include "ctkDICOMFindContext.h"
  10. #include "ctkLogger.h"
  11. static ctkLogger logger ("org.commontk.dicom.DcmFindSCP");
  12. class ctkDICOMFindSCPPrivate{
  13. public:
  14. ctkDICOMFindSCPPrivate(ctkDICOMFindSCP* parent);
  15. ~ctkDICOMFindSCPPrivate();
  16. OFCondition findProvider(T_ASC_Association *assoc,
  17. T_ASC_PresentationContextID presIdCmd,
  18. T_DIMSE_C_FindRQ *request,
  19. ctkDICOMFindContext* context,
  20. T_DIMSE_BlockingMode blockMode, int timeout);
  21. private:
  22. ctkDICOMFindSCP* q_ptr;
  23. Q_DECLARE_PUBLIC(ctkDICOMFindSCP);
  24. };
  25. //------------------------------------------------------------------------------
  26. // ctkDICOMFindSCPPrivate class methods
  27. //------------------------------------------------------------------------------
  28. //------------------------------------------------------------------------------
  29. ctkDICOMFindSCPPrivate::ctkDICOMFindSCPPrivate(ctkDICOMFindSCP *parent):
  30. q_ptr(parent)
  31. {
  32. }
  33. //------------------------------------------------------------------------------
  34. OFCondition ctkDICOMFindSCPPrivate::findProvider(T_ASC_Association *assoc,
  35. T_ASC_PresentationContextID presIdCmd,
  36. T_DIMSE_C_FindRQ *request,
  37. ctkDICOMFindContext *context,
  38. T_DIMSE_BlockingMode blockMode,
  39. int timeout)
  40. {
  41. T_ASC_PresentationContextID presIdData;
  42. T_DIMSE_C_FindRSP rsp;
  43. DcmDataset *statusDetail = NULL;
  44. DcmDataset *reqIds = NULL;
  45. DcmDataset *rspIds = NULL;
  46. OFBool cancelled = OFFalse;
  47. OFBool normal = OFTrue;
  48. int responseCount = 0;
  49. /* receive data (i.e. the search mask) and store it in memory */
  50. OFCondition cond = DIMSE_receiveDataSetInMemory(assoc, blockMode, timeout, &presIdData, &reqIds, NULL, NULL);
  51. /* if no error occured while receiving data */
  52. if (cond.good())
  53. {
  54. /* check if the presentation context IDs of the C-FIND-RQ and */
  55. /* the search mask data are the same; if not, return an error */
  56. if (presIdData != presIdCmd)
  57. {
  58. cond = makeDcmnetCondition(DIMSEC_INVALIDPRESENTATIONCONTEXTID, OF_error, "DIMSE: Presentation Contexts of Command and Data Differ");
  59. }
  60. else
  61. {
  62. /* if the IDs are the same go ahead */
  63. /* initialize the C-FIND-RSP message variable */
  64. bzero((char*)&rsp, sizeof(rsp));
  65. rsp.DimseStatus = STATUS_Pending;
  66. /* as long as no error occured and the status of the C-FIND-RSP message which will */
  67. /* be/was sent is pending, perform this loop in which records that match the search */
  68. /* mask are selected (whithin the execution of the callback function) and sent over */
  69. /* the network to the other DICOM application using C-FIND-RSP messages. */
  70. while (cond.good() && DICOM_PENDING_STATUS(rsp.DimseStatus) && normal)
  71. {
  72. /* increase the counter that counts the number of response messages */
  73. responseCount++;
  74. /* check if a C-CANCEL-RQ is received */
  75. cond = DIMSE_checkForCancelRQ(assoc, presIdCmd, request->MessageID);
  76. if (cond.good())
  77. {
  78. /* if a C-CANCEL-RQ was received, we need to set status and an indicator variable */
  79. rsp.DimseStatus = STATUS_FIND_Cancel_MatchingTerminatedDueToCancelRequest;
  80. cancelled = OFTrue;
  81. } else if (cond == DIMSE_NODATAAVAILABLE)
  82. {
  83. /* timeout */
  84. }
  85. else
  86. {
  87. /* some execption condition occured, bail out */
  88. normal = OFFalse;
  89. }
  90. /* if everything is still ok */
  91. if (normal)
  92. {
  93. /* execute callback function (note that this function always determines the next record */
  94. /* which matches the search mask. This record will be available here through rspIds) */
  95. context->callbackHandler(cancelled, request, reqIds,responseCount, &rsp, &rspIds, &statusDetail);
  96. /* if we encountered a C-CANCEL-RQ earlier, set a variable and possibly delete the search mask */
  97. if (cancelled) {
  98. /* make sure */
  99. rsp.DimseStatus =
  100. STATUS_FIND_Cancel_MatchingTerminatedDueToCancelRequest;
  101. if (rspIds != NULL) {
  102. delete reqIds;
  103. reqIds = NULL;
  104. }
  105. }
  106. /* send a C-FIND-RSP message over the network to the other DICOM application */
  107. cond = DIMSE_sendFindResponse(assoc, presIdCmd, request,
  108. &rsp, rspIds, statusDetail);
  109. /* if there are search results, delete them */
  110. if (rspIds != NULL) {
  111. delete rspIds;
  112. rspIds = NULL;
  113. }
  114. /* if there is status detail information, delete it */
  115. if (statusDetail != NULL) {
  116. delete statusDetail;
  117. statusDetail = NULL;
  118. }
  119. }
  120. }
  121. }
  122. }
  123. /* delete search mask */
  124. delete reqIds;
  125. /* delete latest search result */
  126. delete rspIds;
  127. /* return result value */
  128. return cond;
  129. }
  130. //------------------------------------------------------------------------------
  131. ctkDICOMFindSCPPrivate::~ctkDICOMFindSCPPrivate()
  132. {
  133. }
  134. //------------------------------------------------------------------------------
  135. // ctkDICOMFindSCP class methods
  136. //------------------------------------------------------------------------------
  137. //------------------------------------------------------------------------------
  138. ctkDICOMFindSCP::ctkDICOMFindSCP(QObject *parent) :
  139. ctkDICOMSCP(parent),
  140. d_ptr(new ctkDICOMFindSCPPrivate(this))
  141. {
  142. this->dimseCommand = DIMSE_C_FIND_RQ;
  143. }
  144. //------------------------------------------------------------------------------
  145. ctkDICOMFindSCP::~ctkDICOMFindSCP()
  146. {
  147. delete d_ptr;
  148. }
  149. //------------------------------------------------------------------------------
  150. OFCondition ctkDICOMFindSCP::handleRequest(T_ASC_Association *assoc, T_DIMSE_Message &message, T_ASC_PresentationContextID presId)
  151. {
  152. Q_D(ctkDICOMFindSCP);
  153. OFCondition cond = EC_Normal;
  154. T_DIMSE_C_FindRQ * request = &message.msg.CFindRQ;
  155. ctkDICOMFindContext* context = this->createContext();
  156. DIC_AE aeTitle;
  157. aeTitle[0] = '\0';
  158. ASC_getAPTitles(assoc->params, NULL, aeTitle, NULL);
  159. context->setOurAETitle(aeTitle);
  160. OFString temp_str;
  161. DIMSE_dumpMessage(temp_str, *request, DIMSE_INCOMING);
  162. logger.info(QString("Received Find SCP:\n") + temp_str.c_str());
  163. cond = d->findProvider(assoc, presId, request,
  164. context, DIMSE_BLOCKING, 30);
  165. if (cond.bad()) {
  166. DimseCondition::dump(temp_str, cond);
  167. logger.error(QString("Find SCP Failed: ") + temp_str.c_str());
  168. }
  169. context->deleteLater();
  170. return cond;
  171. }
  172. //------------------------------------------------------------------------------
  173. ctkDICOMFindContext* ctkDICOMFindSCP::createContext()
  174. {
  175. return new ctkDICOMFindContext(STATUS_Pending);
  176. }