ctkDcmSCU.h 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. /*
  2. *
  3. * Copyright (C) 2008-2012, OFFIS e.V.
  4. * All rights reserved. See COPYRIGHT file for details.
  5. *
  6. * This software and supporting documentation were developed by
  7. *
  8. * OFFIS e.V.
  9. * R&D Division Health
  10. * Escherweg 2
  11. * D-26121 Oldenburg, Germany
  12. *
  13. *
  14. * Module: dcmnet
  15. *
  16. * Author: Michael Onken
  17. *
  18. * Purpose: Base class for Service Class Users (SCUs)
  19. *
  20. */
  21. #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
  22. #if ! ( PACKAGE_VERSION_NUMBER == 360 )
  23. #include "dcmtk/dcmnet/scu.h"
  24. #else
  25. #ifndef SCU_H
  26. #define SCU_H
  27. #include "dcmtk/dcmdata/dctk.h" /* Covers most common dcmdata classes */
  28. #include "dcmtk/dcmnet/dcompat.h"
  29. #include "dcmtk/dcmnet/dimse.h" /* DIMSE network layer */
  30. #include "dcmtk/dcmnet/dcasccff.h" /* For reading a association config file */
  31. #include "dcmtk/dcmnet/dcasccfg.h" /* For holding association config file infos */
  32. #include "dcmtk/ofstd/oflist.h"
  33. /* Remove below if changing to more current DCMTK */
  34. const unsigned short ECC_AlreadyConnected = 0x901;
  35. const unsigned short ECC_NoAcceptablePresentationContexts = 0x902;
  36. const unsigned short ECC_NoPresentationContextsDefined = 0x903;
  37. const unsigned short ECC_InvalidSOPInstanceUID = 0x904;
  38. const unsigned short ECC_InvalidSOPClassUID = 0x905;
  39. const unsigned short ECC_UnknownTransferSyntax = 0x906;
  40. const OFConditionConst ECE_NoAcceptablePresentationContexts( OFM_dcmnet, ECC_NoAcceptablePresentationContexts, OF_error, "No Acceptable Presentation Contexts");
  41. const OFConditionConst ECE_NoPresentationContextsDefined( OFM_dcmnet, ECC_NoPresentationContextsDefined, OF_error, "No Presentation Contexts defined");
  42. const OFConditionConst ECE_InvalidSOPClassUID( OFM_dcmnet, ECC_InvalidSOPClassUID, OF_error, "Invalid SOP Class UID");
  43. const OFConditionConst ECE_InvalidSOPInstanceUID( OFM_dcmnet, ECC_InvalidSOPInstanceUID, OF_error, "Invalid SOP Instance UID");
  44. const OFConditionConst ECE_UnknownTransferSyntax( OFM_dcmnet, ECC_UnknownTransferSyntax, OF_error, "Unknown Transfer Syntax");
  45. const OFConditionConst ECE_AlreadyConnected( OFM_dcmnet, ECC_AlreadyConnected, OF_error, "Already Connected");
  46. const OFCondition NET_EC_AlreadyConnected( ECE_AlreadyConnected);
  47. const OFCondition NET_EC_NoAcceptablePresentationContexts( ECE_NoAcceptablePresentationContexts);
  48. const OFCondition NET_EC_NoPresentationContextsDefined( ECE_NoPresentationContextsDefined);
  49. const OFCondition NET_EC_UnknownTransferSyntax( ECE_UnknownTransferSyntax);
  50. const OFCondition NET_EC_InvalidSOPClassUID( ECE_InvalidSOPClassUID);
  51. const OFCondition NET_EC_InvalidSOPInstanceUID( ECE_InvalidSOPInstanceUID);
  52. /* Remove above if changing to more current DCMTK */
  53. /** Different types of closing an association
  54. */
  55. enum DcmCloseAssociationType
  56. {
  57. /// Release the current association
  58. DCMSCU_RELEASE_ASSOCIATION,
  59. /// Abort the current association
  60. DCMSCU_ABORT_ASSOCIATION,
  61. /// Peer requested release (Aborting)
  62. DCMSCU_PEER_REQUESTED_RELEASE,
  63. /// Peer aborted the association
  64. DCMSCU_PEER_ABORTED_ASSOCIATION
  65. };
  66. /** Storage mode used for DICOM objects received via C-STORE
  67. */
  68. enum DcmStorageMode
  69. {
  70. /// Ignore any objects received via C-STORE
  71. DCMSCU_STORAGE_IGNORE,
  72. /// Try to store the objects to disk
  73. DCMSCU_STORAGE_DISK,
  74. /// Try to store to disk in bit-preserving mode. This is especially useful
  75. /// for huge files that cannot fully be received in memory since the
  76. /// data is directly streamed to disk. Originally, this was introduced for
  77. /// DICOM signatures which can be kept valid this way.
  78. DCMSCU_STORAGE_BIT_PRESERVING
  79. };
  80. /** Base class for C-FIND, C-MOVE and C-GET responses
  81. */
  82. class QRResponse
  83. {
  84. public:
  85. /** Standard constructor.
  86. */
  87. QRResponse() :
  88. m_messageIDRespondedTo(0),
  89. m_affectedSOPClassUID(),
  90. m_dataset(NULL),
  91. m_status(0),
  92. m_statusDetail(NULL) {}
  93. /** Destructor, cleans up internal memory (dataset if present).
  94. */
  95. virtual ~QRResponse() { delete m_dataset; delete m_statusDetail; }
  96. /// The message ID responded to (mandatory response field,
  97. /// equals message ID from request)
  98. Uint16 m_messageIDRespondedTo;
  99. /// Optional response field according to part 7 of the standard
  100. /// If present, equals SOP Class UID from request.
  101. OFString m_affectedSOPClassUID;
  102. /// Conditional response field (NULL if absent). From the standard (2009,
  103. /// part 4, C.4.2.1.4.2), for C-MOVE: In Q/R if no C-STORE sub-operation
  104. /// failed, Failed SOP Instance UID List (0008,0058) is absent and
  105. /// therefore no Data Set shall be sent in the C-MOVE response. Further
  106. /// rules: Statuses of Canceled, Failure, Refused, or Warning shall
  107. /// contain the Failed SOP Instance UID List Attribute; status of
  108. /// Pending shall not.
  109. DcmDataset *m_dataset;
  110. /// The returned DIMSE status (mandatory Response Field)
  111. Uint16 m_status;
  112. /// Status detail (NULL if absent). For some DIMSE return status codes,
  113. /// an additional dataset is sent which gives further information (i.e.
  114. /// in case of warnings or errors).
  115. DcmDataset *m_statusDetail;
  116. private:
  117. /** Private undefined copy constructor.
  118. * @param other The find response to copy from
  119. */
  120. QRResponse(const QRResponse &other);
  121. /** Private undefined assignment operator.
  122. * @param other The find response that should be assigned from
  123. * @return Reference to this
  124. */
  125. QRResponse &operator=(const QRResponse &other);
  126. };
  127. /// Base class representing for single C-GET or C-MOVE response
  128. class RetrieveResponse : public QRResponse
  129. {
  130. public:
  131. /** Standard constructor
  132. */
  133. RetrieveResponse() :
  134. m_numberOfRemainingSubops(0),
  135. m_numberOfCompletedSubops(0),
  136. m_numberOfFailedSubops(0),
  137. m_numberOfWarningSubops(0) {}
  138. /** Destructor, cleans up internal memory
  139. */
  140. virtual ~RetrieveResponse() {}
  141. /** Prints response to INFO log level.
  142. */
  143. void print();
  144. /// Number of remaining sub operations (in Q/R: C-STORE calls).
  145. /// For Q/R MOVE and GET, for status of pending this field shall be filled.
  146. /// For others, the field may be filled.
  147. Uint16 m_numberOfRemainingSubops;
  148. /// Number of successfully completed sub operations (in Q/R: C-STORE calls).
  149. /// For Q/R MOVE and GET, for status of pending this field shall be filled.
  150. /// For others, the field may be filled.
  151. Uint16 m_numberOfCompletedSubops;
  152. /// Number of failed sub operations (in Q/R: C-STORE calls).
  153. /// For Q/R MOVE and GET, for status of pending this field shall be filled.
  154. /// For others, the field may be filled.
  155. Uint16 m_numberOfFailedSubops;
  156. /// Number generated warnings generated by sub operations (in Q/R: C-STORE calls).
  157. /// For Q/R MOVE and GET, for status of pending this field shall be filled.
  158. /// For others, the field may be filled.
  159. Uint16 m_numberOfWarningSubops;
  160. private:
  161. /** Private undefined copy constructor
  162. * @param other Response to copy from
  163. */
  164. RetrieveResponse(const RetrieveResponse &other);
  165. /** Private undefined assignment operator
  166. * @param other Response that should be assigned from
  167. * @return Reference to this
  168. */
  169. RetrieveResponse &operator=(const RetrieveResponse &other);
  170. };
  171. /** Base class for implementing DICOM Service Class User functionality. The class offers
  172. * support for negotiating associations and sending and receiving arbitrary DIMSE messages
  173. * on that connection. DcmSCU has built-in C-ECHO support so derived classes do not have to
  174. * implement that capability on their own.
  175. * @warning This class is EXPERIMENTAL. Be careful to use it in production environment.
  176. */
  177. class DcmSCU
  178. {
  179. public:
  180. /** Constructor, just initializes internal class members
  181. */
  182. DcmSCU();
  183. /** Virtual destructor
  184. */
  185. virtual ~DcmSCU();
  186. /** Add presentation context to be used for association negotiation
  187. * @param abstractSyntax [in] Abstract syntax name in UID format
  188. * @param xferSyntaxes [in] List of transfer syntaxes to be added for the given abstract
  189. * syntax
  190. * @param role [in] The role to be negotiated
  191. * @return EC_Normal if adding was successful, otherwise error code
  192. */
  193. OFCondition addPresentationContext(const OFString &abstractSyntax,
  194. const OFList<OFString> &xferSyntaxes,
  195. const T_ASC_SC_ROLE role = ASC_SC_ROLE_DEFAULT);
  196. /** Initialize network, i.e.\ prepare for association negotiation. If the SCU is already
  197. * connected, the call will not be successful and the old connection keeps open.
  198. * @return EC_Normal if initialization was successful, otherwise error code.
  199. * NET_EC_AlreadyConnected if SCU is already connected.
  200. */
  201. virtual OFCondition initNetwork();
  202. /** Negotiate association by using presentation contexts and parameters as defined by
  203. * earlier function calls. If negotiation fails, there is no need to close the association
  204. * or to do anything else with this class.
  205. * @return EC_Normal if negotiation was successful, otherwise error code.
  206. * NET_EC_AlreadyConnected if SCU is already connected.
  207. */
  208. virtual OFCondition negotiateAssociation();
  209. /** After negotiation association, this call returns the first usable presentation context
  210. * given the desired abstract syntax and transfer syntax
  211. * @param abstractSyntax [in] The abstract syntax (UID) to look for
  212. * @param transferSyntax [in] The transfer syntax (UID) to look for. If empty, the transfer
  213. * syntax is not checked.
  214. * @return Adequate Presentation context ID that can be used. 0 if none found.
  215. */
  216. T_ASC_PresentationContextID findPresentationContextID(const OFString &abstractSyntax,
  217. const OFString &transferSyntax);
  218. /** After a successful association negotiation, this function is called to return the
  219. * presentation context ID that best matches the desired abstract syntax and transfer
  220. * syntax (TS). The function tries to do the following:
  221. * - If possible finds a presentation context with matching TS
  222. * - Else then tries to find an explicit VR uncompressed TS presentation context
  223. * - Else then tries to find an implicit VR uncompressed TS presentation context
  224. * - Else finally accepts each matching presentation ctx independent of TS.
  225. * @param abstractSyntax [in] The abstract syntax (UID) to look for
  226. * @param transferSyntax [in] The transfer syntax (UID) to look for. If empty, the transfer
  227. * syntax is not checked.
  228. * @return Adequate Presentation context ID that can be used. 0 if no appropriate
  229. * presentation context could be found at all.
  230. */
  231. T_ASC_PresentationContextID findAnyPresentationContextID(const OFString &abstractSyntax,
  232. const OFString &transferSyntax);
  233. /** This function sends a C-ECHO command via network to another DICOM application
  234. * @param presID [in] Presentation context ID to use. A value of 0 lets SCP class tries
  235. * to choose one on its own.
  236. * @return EC_Normal if echo was successful, an error code otherwise
  237. *
  238. */
  239. virtual OFCondition sendECHORequest(const T_ASC_PresentationContextID presID);
  240. /** This function sends a C-STORE request on the currently opened association and receives
  241. * the corresponding response then. If required and supported, the dataset of the SOP
  242. * instance can be converted automatically to the network transfer syntax that was
  243. * negotiated (and is specified by the parameter 'presID'). However, this feature is
  244. * disabled by default. See setDatasetConversionMode() on how to enable it.
  245. * @param presID [in] Contains in the end the ID of the presentation context which
  246. * was specified in the DIMSE command. If 0 is given, the
  247. * function tries to find an approriate presentation context
  248. * itself (based on SOP class and original transfer syntax of
  249. * the 'dicomFile' or 'dataset').
  250. * @param dicomFile [in] The filename of the DICOM file to be sent. Alternatively, a
  251. * dataset can be given in the next parameter. If both are given
  252. * the dataset from the file name is used.
  253. * @param dataset [in] The dataset to be sent. Alternatively, a filename can be
  254. * specified in the previous parameter. If both are given the
  255. * dataset from the filename is used.
  256. * @param rspStatusCode [out] The response status code received. 0 means success, others
  257. * can be found in the DICOM standard.
  258. * @return EC_Normal if request could be issued and response was received successfully,
  259. * error code otherwise. That means that if the receiver sends a response denoting
  260. * failure of the storage request, EC_Normal will be returned.
  261. */
  262. virtual OFCondition sendSTORERequest(const T_ASC_PresentationContextID presID,
  263. const OFString &dicomFile,
  264. DcmDataset *dataset,
  265. Uint16 &rspStatusCode);
  266. /** Sends a C-MOVE Request on given presentation context and receives list of responses.
  267. * The function receives the first response and then calls the function handleMOVEResponse()
  268. * which gets the relevant presentation context together with the response dataset and
  269. * status information. Then it waits again for the next response, if there are more to
  270. * come (i.e. response status is PENDING). In the end, after receiving all responses, the
  271. * full list of responses is returned to the caller. If he is not interested, he just sets
  272. * responses=NULL when calling the function.
  273. * This function can be overwritten by actual SCU implementations but just should work fine
  274. * for most people.
  275. * @param presID [in] The presentation context ID that should be used.
  276. * Must be an odd number.
  277. * @param moveDestinationAETitle [in] The move destination's AE title, i.e.\ the one that
  278. * is used for connection to the storage server.
  279. * @param dataset [in] The dataset containing the information about the
  280. * object(s) to be retrieved.
  281. * @param responses [out] The incoming C-MOVE responses for this request.
  282. * The caller is responsible for providing a non-NULL
  283. * pointer for this case. After receiving the results,
  284. * the caller is responsible for freeing the memory of
  285. * this variable. If NULL is specified, the responses
  286. * will not bereturned to the caller.
  287. * @return EC_Normal if everything went fine, i.e.\ if request could be send and responses
  288. * (with whatever status) could be received.
  289. */
  290. virtual OFCondition sendMOVERequest(const T_ASC_PresentationContextID presID,
  291. const OFString &moveDestinationAETitle,
  292. DcmDataset *dataset,
  293. OFList<RetrieveResponse*> *responses);
  294. /** This is the standard handler for C-MOVE message responses: It just adds up all responses
  295. * it receives and prints a DEBUG message. Therefore, it is called for each response
  296. * received in sendMOVERequest(). The idea is of course to overwrite this function in a
  297. * derived, actual SCU implementation if required. Thus, after each response, the caller of
  298. * sendMOVERequest() can decide on its own whether he wants to cancel the C-MOVE session,
  299. * terminate the association, do something useful or whatever. Thus this function is a more
  300. * object-oriented kind of callback.
  301. * @param presID [in] The presentation context ID where the response was
  302. * received on.
  303. * @param response [in] The C-MOVE response received.
  304. * @param waitForNextResponse [out] Denotes whether SCU should try to receive another
  305. * response. If set to OFTrue, then sendMOVERequest() will
  306. * continue waiting for responses. The current
  307. * implementation does that for all responses do not have
  308. * status Failed, Warning, Success or unknown. If set to
  309. * OFFalse, sendMOVERequest() will return control to the
  310. * caller.
  311. * @return EC_Normal, if response could be handled. Error code otherwise.
  312. * The current implementation always returns EC_Normal.
  313. */
  314. virtual OFCondition handleMOVEResponse(const T_ASC_PresentationContextID presID,
  315. RetrieveResponse *response,
  316. OFBool &waitForNextResponse);
  317. /** Sends a C-GET Request on given presentation context and receives list of responses. It
  318. * then switches control to the function handleCGETSession().
  319. * The full list of responses is returned to the caller. If he is not interested, he can
  320. * set responses=NULL when calling the function.
  321. * This function can be overwritten by actual SCU implementations but just should work fine
  322. * for most people.
  323. * @param presID [in] The presentation context ID that should be used. Must be an odd
  324. * number.
  325. * @param dataset [in] The dataset containing the information about the
  326. * object(s) to be retrieved
  327. * @param responses [out] The incoming C-GET responses for this request. If the caller
  328. * specifies NULL, no responses will be returned; otherwise there
  329. * should be at least one final C-GET response (mandatory). C-GET
  330. * responses after each DICOM object received are optional and may
  331. * have been ommitted by the server.
  332. * @return EC_Normal if everything went fine, i.e.\ if request could be sent and expected
  333. * responses (with whatever status) could be received.
  334. */
  335. virtual OFCondition sendCGETRequest(const T_ASC_PresentationContextID presID,
  336. DcmDataset *dataset,
  337. OFList<RetrieveResponse*> *responses);
  338. /** Does the logic for switching between C-GET Response and C-STORE Requests. Sends a C-GET
  339. * Request on given presentation context and receives list of responses. Ihe full list of
  340. * responses is returned to the caller. If he is not interested, he can set responses=NULL
  341. * when calling the function. After sending a C-GET Request, there might be two different
  342. * responses coming in: C-GET-RSP (optional after each received object and mandatory after
  343. * the last object) or a mandatory C-STORE for each incoming object that is received due to
  344. * the request. This function therefore either calls handleCGETResponse() or
  345. * handleSTORERequest() in order to deal with the incoming message. All other messages lead
  346. * to an error within this handler.
  347. * This function can be overwritten by actual SCU implementations but just should work fine
  348. * for most people.
  349. * @param presID [in] The presentation context ID that should be used. Must be an odd
  350. * number.
  351. * @param dataset [in] The dataset containing the information about the object(s) to be
  352. * retrieved
  353. * @param responses [out] The incoming C-GET responses for this request. If the caller
  354. * specifies NULL, no responses will be returned; otherwise there
  355. * should be at least one final C-GET response (mandatory). C-GET
  356. * responses after each DICOM object received are optional and may
  357. * have been ommitted by the server.
  358. * @return EC_Normal if everything went fine, i.e.\ if request could be send
  359. * and expected responses (with whatever status) could be received.
  360. */
  361. virtual OFCondition handleCGETSession(const T_ASC_PresentationContextID presID,
  362. DcmDataset *dataset,
  363. OFList<RetrieveResponse*> *responses);
  364. /** Function handling a single C-GET Response. This standard handler reads the status of the
  365. * response and decides whether to receive any further messages related to the original
  366. * C-GET Request or whether the last response was received or an error occured.
  367. * @param presID [in] The presentation context the C-GET Response was
  368. * received on.
  369. * @param response [in] The response received
  370. * @param continueCGETSession [out] Defines whether it is decided to wait for further C-GET
  371. * Responses/C-STORE Requests within this C-GET session
  372. * @return If no errors occur (dataset response NULL, SCU not connected), this method will
  373. * return EC_Normal, otherwise error code.
  374. */
  375. virtual OFCondition handleCGETResponse(const T_ASC_PresentationContextID presID,
  376. RetrieveResponse* response,
  377. OFBool &continueCGETSession);
  378. /** Function handling a single C-STORE Request. If storage mode is set to disk (default),
  379. * this function is called and the incoming object stored to disk.
  380. * @param presID [in] The presentation context the C-STORE Response was
  381. * received on.
  382. * @param incomingObject [in] The dataset (the object) received
  383. * @param continueCGETSession [out] Defines whether it is decided to wait for further
  384. * C-GET Responses/C-STORE requests within this C-GET
  385. * session.
  386. * @param cStoreReturnStatus [out] Denotes the desired C-STORE return status.
  387. * @return If errors occur (incomingObject NULL or SCU not connected or file could not be
  388. * stored), this method will return an error code otherwise EC_Normal.
  389. */
  390. virtual OFCondition handleSTORERequest(const T_ASC_PresentationContextID presID,
  391. DcmDataset *incomingObject,
  392. OFBool &continueCGETSession,
  393. Uint16 &cStoreReturnStatus);
  394. /** Function handling a single C-STORE Request. If storage mode is set to bit preserving,
  395. * this function is called and the incoming object stored directly to disk, i.e. not stored
  396. * fully in memory.
  397. * @param presID [in] The presentation context the C-STORE Response was received on.
  398. * @param filename [in] The filename to store to
  399. * @param request [in] The incoming C-STORE request command set
  400. * @return If errors occur (incomingObject NULL or SCU not connected filename not
  401. * specified), this method will return an error code otherwise EC_Normal.
  402. */
  403. virtual OFCondition handleSTORERequestFile(T_ASC_PresentationContextID *presID,
  404. const OFString &filename,
  405. T_DIMSE_C_StoreRQ *request);
  406. /** Sends a C-FIND Request on given presentation context and receives list of responses.
  407. * The function receives the first response and then calls the function handleFINDResponse
  408. * which gets the relevant presentation context together with the response dataset and
  409. * status information. Then it waits again for the next response, if there are more to
  410. * come (i.e. response status is PENDING). In the end, after receiving all responses, the
  411. * full list of responses is returned to the caller. If he is not interested, he just sets
  412. * responses=NULL when calling the function.
  413. * This function can be overwritten by actual SCU implementations but just should work fine
  414. * for most people.
  415. * @param presID [in] The presentation context ID that should be used. Must be an odd
  416. * number.
  417. * @param queryKeys [in] The dataset containing the query keys to be searched for on the
  418. * server (SCP).
  419. * @param responses [out] The incoming C-FIND responses for this request. The caller is
  420. * responsible for providing a non-NULL pointer for this case.
  421. * After receiving the results, the caller is responsible for
  422. * freeing the memory of this variable. If NULL is specified, the
  423. * responses will be not returned to the caller.
  424. * @return EC_Normal if everything went fine, i.e.\ if request could be send and responses
  425. * (with whatever status) could be received.
  426. */
  427. virtual OFCondition sendFINDRequest(const T_ASC_PresentationContextID presID,
  428. DcmDataset *queryKeys,
  429. OFList<QRResponse*> *responses);
  430. /** This is the standard handler for C-FIND message responses: It just adds up all responses
  431. * it receives and prints a DEBUG message. Therefore, it is called for each response
  432. * received in sendFINDRequest(). The idea is of course to overwrite this function in a
  433. * derived, actual SCU implementation if required. Thus, after each response, the caller of
  434. * sendFINDRequest() can decide on its own whether he wants to cancel the C-FIND session,
  435. * terminate the association, do something useful or whatever. That way this is a more
  436. * object-oriented kind of callback.
  437. * @param presID [in] The presentation context ID where the response was
  438. * received on.
  439. * @param response [in] The C-FIND response received.
  440. * @param waitForNextResponse [out] Denotes whether SCU should try to receive another
  441. * response. If set to OFTrue, then sendFINDRequest()
  442. * will continue waiting for responses. The current
  443. * implementation does that for all responses do not have
  444. * status SUCESSS. If set to OFFalse, sendFINDRequest()
  445. * will return control to the caller.
  446. * @return EC_Normal, if response could be handled. Error code otherwise.
  447. * The current implementation always returns EC_Normal.
  448. */
  449. virtual OFCondition handleFINDResponse(const T_ASC_PresentationContextID presID,
  450. QRResponse *response,
  451. OFBool &waitForNextResponse);
  452. /** Send C-CANCEL and, therefore, ends the C-FIND -GET or -MOVE session, i.e.\ no further
  453. * responses will be handled. A call to this function only makes sense if an association
  454. * is open, the given presentation context represents a valid C-FIND/GET/MOVE-enabled SOP
  455. * class and usually only, if the last command send on that presentation context was a
  456. * C-FIND message.
  457. * @param presID [in] The presentation context ID where the C-CANCEL should be sent on.
  458. * @return The current implementation always returns EC_Normal.
  459. */
  460. virtual OFCondition sendCANCELRequest(const T_ASC_PresentationContextID presID);
  461. /** This function sends a N-ACTION request on the currently opened association and receives
  462. * the corresponding response then
  463. * @param presID [in] The ID of the presentation context to be used for sending
  464. * the request message. Should not be 0.
  465. * @param sopInstanceUID [in] The requested SOP Instance UID
  466. * @param actionTypeID [in] The action type ID to be used
  467. * @param reqDataset [in] The dataset to be sent
  468. * @param rspStatusCode [out] The response status code received. 0 means success,
  469. * others can be found in the DICOM standard.
  470. * @return EC_Normal if request could be issued and response was received successfully,
  471. * an error code otherwise
  472. */
  473. virtual OFCondition sendACTIONRequest(const T_ASC_PresentationContextID presID,
  474. const OFString &sopInstanceUID,
  475. const Uint16 actionTypeID,
  476. DcmDataset *reqDataset,
  477. Uint16 &rspStatusCode);
  478. /** This function sends N-EVENT-REPORT request and receives the corresponding response
  479. * @param presID [in] The ID of the presentation context to be used for sending
  480. * the request message. Should not be 0.
  481. * @param sopInstanceUID [in] The requested SOP Instance UID
  482. * @param eventTypeID [in] The event type ID to be used
  483. * @param reqDataset [in] The request dataset to be sent
  484. * @param rspStatusCode [out] The response status code received. 0 means success,
  485. * others can be found in the DICOM standard.
  486. * @return EC_Normal if request could be issued and response was received successfully,
  487. * an error code otherwise
  488. */
  489. virtual OFCondition sendEVENTREPORTRequest(const T_ASC_PresentationContextID presID,
  490. const OFString &sopInstanceUID,
  491. const Uint16 eventTypeID,
  492. DcmDataset *reqDataset,
  493. Uint16 &rspStatusCode);
  494. /** Receives N-EVENT-REPORT request on the currently opened association and sends a
  495. * corresponding response. Calls checkEVENTREPORTRequest() in order to determine the
  496. * DIMSE status code to be used for the N-EVENT-REPORT response.
  497. * @param reqDataset [out] Pointer to the dataset received
  498. * @param eventTypeID [out] Event Type ID from the command set received
  499. * @param timeout [in] Optional timeout in seconds for receiving data. This value
  500. * (if not 0) overwrites the standard DIMSE timeout and also
  501. * enables the non-blocking mode for receiving the request.
  502. * @return status, EC_Normal if successful, an error code otherwise
  503. */
  504. virtual OFCondition handleEVENTREPORTRequest(DcmDataset *&reqDataset,
  505. Uint16 &eventTypeID,
  506. const int timeout = 0);
  507. /** Closes the association created by this SCU. Also resets the current association.
  508. * @param closeType [in] Define whether to release or abort the association
  509. */
  510. virtual void closeAssociation(const DcmCloseAssociationType closeType);
  511. /* Set methods */
  512. /** Set maximum PDU length (to be received by SCU)
  513. * @param maxRecPDU [in] The maximum PDU size to use in bytes
  514. */
  515. void setMaxReceivePDULength(const unsigned long maxRecPDU);
  516. /** Set whether to send in DIMSE blocking or non-blocking mode
  517. * @param blockingMode [in] Either blocking or non-blocking mode
  518. */
  519. void setDIMSEBlockingMode(const T_DIMSE_BlockingMode blockingMode);
  520. /** Set SCU's AETitle to be used in association negotiation
  521. * @param myAETtitle [in] The SCU's AETitle to be used
  522. */
  523. void setAETitle(const OFString &myAETtitle);
  524. /** Set SCP's host (hostname or IP address) to talk to in association negotiation
  525. * @param peerHostName [in] The SCP's hostname or IP address to be used
  526. */
  527. void setPeerHostName(const OFString &peerHostName);
  528. /** Set SCP's AETitle to talk to in association negotiation
  529. * @param peerAETitle [in] The SCP's AETitle to be used
  530. */
  531. void setPeerAETitle(const OFString &peerAETitle);
  532. /** Set SCP's port number to connect to for association negotiation
  533. * @param peerPort [in] The SCP's port number
  534. */
  535. void setPeerPort(const Uint16 peerPort);
  536. /** Set timeout for receiving DIMSE messages
  537. * @param dimseTimeout [in] DIMSE Timeout in seconds for receiving data. If the blocking
  538. * mode is DIMSE_NONBLOCKING and we are trying to read data from
  539. * the incoming socket stream and no data has been received.
  540. */
  541. void setDIMSETimeout(const Uint32 dimseTimeout);
  542. /** Set timeout for receiving ACSE messages
  543. * @param acseTimeout [in] ACSE Timeout in seconds used by timer for message timeouts
  544. * during association negotiation
  545. */
  546. void setACSETimeout(const Uint32 acseTimeout);
  547. /** Set an association configuration file and profile to be used
  548. * @param filename [in] File name of the association configuration file
  549. * @param profile [in] Profile inside the association negotiation file
  550. */
  551. void setAssocConfigFileAndProfile(const OFString &filename,
  552. const OFString &profile);
  553. /** Set the directory that should be used by the standard C-GET handler to store objects
  554. * that come in with the corresponding C-STORE rqeuests
  555. * @param storeDir [in] The directory to store to. It is checked in handleSTORERequest()
  556. * whether the directory is writeable and readable. Per default, the
  557. * received objects are stored in the current working directory.
  558. */
  559. void setStorageDir(const OFString &storeDir);
  560. /** Set the storage mode to be used. Default is DCMSCU_STORAGE_DISK.
  561. * @param storageMode The storage mode to be used.
  562. */
  563. void setStorageMode(const DcmStorageMode storageMode);
  564. /** Set whether to show presentation contexts in verbose or debug mode
  565. * @param mode [in] Show presentation contexts in verbose mode if OFTrue. By default, the
  566. * presentation contexts are shown in debug mode.
  567. */
  568. void setVerbosePCMode(const OFBool mode);
  569. /** Set the mode that specifies whether the transfer syntax of the dataset can be changed
  570. * for network transmission. This mainly covers the compression/decompression of datasets,
  571. * which is disabled by default.
  572. * @param mode [in] Allow dataset conversion if OFTrue
  573. */
  574. void setDatasetConversionMode(const OFBool mode);
  575. /** Set the mode that specifies whether the progress of sending and receiving DIMSE
  576. * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(),
  577. * respectively. The progress notification is enabled by default.
  578. * @param mode [in] Disable progress notification if OFFalse
  579. */
  580. void setProgressNotificationMode(const OFBool mode);
  581. /* Get methods */
  582. /** Get current connection status
  583. * @return OFTrue if SCU is currently connected, OFFalse otherwise
  584. */
  585. OFBool isConnected() const;
  586. /** Returns maximum PDU length configured to be received by SCU
  587. * @return Maximum PDU length in bytes
  588. */
  589. Uint32 getMaxReceivePDULength() const;
  590. /** Returns whether DIMSE messaging is configured to be blocking or unblocking
  591. * @return The blocking mode configured
  592. */
  593. T_DIMSE_BlockingMode getDIMSEBlockingMode() const;
  594. /** Returns the SCU's own configured AETitle
  595. * @return The AETitle configured for this SCU
  596. */
  597. const OFString &getAETitle() const;
  598. /** Returns the SCP's (peer's) host name configured
  599. * @return The hostname (or IP) configured to be talked to
  600. */
  601. const OFString &getPeerHostName() const;
  602. /** Returns the SCP's (peer's) AETitle configured
  603. * @return The AETitle configured to be talked to
  604. */
  605. const OFString &getPeerAETitle() const;
  606. /** Returns the SCP's (peer's) TCP/IP port configured
  607. * @return The port configured to talked to
  608. */
  609. Uint16 getPeerPort() const;
  610. /** Returns the DIMSE timeout configured defining how long SCU will wait for DIMSE responses
  611. * @return The DIMSE timeout configured
  612. */
  613. Uint32 getDIMSETimeout() const;
  614. /** Returns the timeout configured defining how long SCU will wait for messages during ACSE
  615. * messaging (association negotiation)
  616. * @return The ACSE timeout configured
  617. */
  618. Uint32 getACSETimeout() const;
  619. /** Returns the storage directory used for storing objects received with C-STORE requests
  620. * in the context of C-GET sessions. Default is empty string which refers to the current
  621. * working directory.
  622. * @return The storage directory
  623. */
  624. OFString getStorageDir() const;
  625. /** Returns the storage mode enabled
  626. * @return The storage mode enabled
  627. */
  628. DcmStorageMode getStorageMode() const;
  629. /** Returns the verbose presentation context mode configured specifying whether details
  630. * on the presentation contexts (negotiated during association setup) should be shown in
  631. * verbose or debug mode. The latter is the default.
  632. * @return The current verbose presentation context mode. Show details on the
  633. * presentation contexts on INFO log level (verbose) if OFTrue and on DEBUG
  634. * level if OFFalse.
  635. */
  636. OFBool getVerbosePCMode() const;
  637. /** Returns the mode that specifies whether the transfer syntax of the dataset can be
  638. * changed for network transmission. This mainly covers the compression/decompression
  639. * of datasets, which is disabled by default.
  640. * @return The current dataset conversion mode, enabled if OFTrue
  641. */
  642. OFBool getDatasetConversionMode() const;
  643. /** Returns the mode that specifies whether the progress of sending and receiving DIMSE
  644. * messages is notified by calling notifySENDProgress() and notifyRECEIVEProgress(),
  645. * respectively. The progress notification is enabled by default.
  646. * @return The current progress notification mode, enabled if OFTrue
  647. */
  648. OFBool getProgressNotificationMode() const;
  649. /** Returns whether SCU is configured to create a TLS connection with the SCP
  650. * @return OFFalse for this class but may be overridden by derived classes
  651. */
  652. OFBool getTLSEnabled() const;
  653. /** Deletes internal networking structures from memory */
  654. void freeNetwork();
  655. protected:
  656. /** Sends a DIMSE command and possibly also a dataset from a data object via network to
  657. * another DICOM application
  658. * @param presID [in] Presentation context ID to be used for message
  659. * @param msg [in] Structure that represents a certain DIMSE command which
  660. * shall be sent
  661. * @param dataObject [in] The instance data which shall be sent to the other DICOM
  662. * application; NULL, if there is none
  663. * @param commandSet [out] If this parameter is not NULL it will return a copy of the
  664. * DIMSE command which is sent to the other DICOM application
  665. * @return EC_Normal if sending request was successful, an error code otherwise
  666. */
  667. OFCondition sendDIMSEMessage(const T_ASC_PresentationContextID presID,
  668. T_DIMSE_Message *msg,
  669. DcmDataset *dataObject,
  670. DcmDataset **commandSet = NULL);
  671. /** Returns SOP Class UID, SOP Instance UID and original transfer syntax for a given dataset.
  672. * If the dataset is NULL, all returned values will be undefined (i.e. empty or EXS_Unknown).
  673. * @param dataset [in] The dataset to read from
  674. * @param sopClassUID [out] The value of attribute SOP Class UID if present
  675. * @param sopInstanceUID [out] The value of attribute SOP Instance UID if present
  676. * @param transferSyntax [out] The value of transfer syntax that originally was read from
  677. * disk. Will be unknown if the dataset was created in memory.
  678. * @return EC_Normal if all information could be retrieved and is valid, an error code
  679. * otherwise
  680. */
  681. OFCondition getDatasetInfo(DcmDataset *dataset,
  682. OFString &sopClassUID,
  683. OFString &sopInstanceUID,
  684. E_TransferSyntax &transferSyntax);
  685. /** Tells DcmSCU to use a secure TLS connection described by the given TLS layer
  686. * @param tlayer [in] The TLS transport layer including all TLS parameters
  687. * @return EC_Normal if given transport layer is ok, an error code otherwise
  688. */
  689. OFCondition useSecureConnection(DcmTransportLayer *tlayer);
  690. /** Receive DIMSE command (excluding dataset!) over the currently open association
  691. * @param presID [out] Contains in the end the ID of the presentation context
  692. * which was specified in the DIMSE command received
  693. * @param msg [out] The message received
  694. * @param statusDetail [out] If a non-NULL value is passed this variable will in the end
  695. * contain detailed information with regard to the status
  696. * information which is captured in the status element
  697. * (0000,0900). Note that the value for element (0000,0900) is
  698. * not contained in this return value but in internal msg. For
  699. * details on the structure of this object, see DICOM standard
  700. * part 7, annex C).
  701. * @param commandSet [out] If this parameter is not NULL, it will return a copy of the
  702. * DIMSE command which was received from the other DICOM
  703. * application. The caller is responsible to de-allocate the
  704. * returned object!
  705. * @param timeout [in] If this parameter is not 0, it specifies the timeout (in
  706. * seconds) to be used for receiving the DIMSE command.
  707. * Otherwise, the default timeout value is used (see
  708. * setDIMSETimeout()).
  709. * @return EC_Normal if command could be received successfully, an error code otherwise
  710. */
  711. OFCondition receiveDIMSECommand(T_ASC_PresentationContextID *presID,
  712. T_DIMSE_Message *msg,
  713. DcmDataset **statusDetail,
  714. DcmDataset **commandSet = NULL,
  715. const Uint32 timeout = 0);
  716. /** Receives one dataset (of instance data) via network from another DICOM application
  717. * @param presID [out] Contains in the end the ID of the presentation context which
  718. * was used in the PDVs that were received on the network. If the
  719. * PDVs show different presentation context IDs, this function
  720. * will return an error.
  721. * @param dataObject [out] Contains in the end the information which was received over
  722. * the network
  723. * @return EC_Normal if dataset could be received successfully, an error code otherwise
  724. */
  725. OFCondition receiveDIMSEDataset(T_ASC_PresentationContextID *presID,
  726. DcmDataset **dataObject);
  727. /** clear list of presentation contexts. In addition, any currently selected association
  728. * configuration file is disabled.
  729. */
  730. void clearPresentationContexts();
  731. /** After negotiation association, this call returns the presentation context belonging
  732. * to the given presentation context ID
  733. * @param presID [in] The presentation context ID to look for
  734. * @param abstractSyntax [out] The abstract syntax (UID) for that ID.
  735. * Empty, if such a presentation context does not exist.
  736. * @param transferSyntax [out] The transfer syntax (UID) for that ID.
  737. * Empty, if such a presentation context does not exist.
  738. */
  739. void findPresentationContext(const T_ASC_PresentationContextID presID,
  740. OFString &abstractSyntax,
  741. OFString &transferSyntax);
  742. /* ***********************************************************************
  743. * Functions particularly interesting for overwriting in derived classes
  744. * *********************************************************************** */
  745. /** This function is called if an object was received due to a C-GET request and can be
  746. * overwritten by a user in order to be informed about such an event. The default
  747. * implementation just prints a DEBUG message. Note that this function is not called if
  748. * the SCU is in storage mode DCMSCU_STORAGE_IGNORE.
  749. * @param filename [in] The filename written
  750. * @param sopClassUID [in] The SOP Class UID of the object written
  751. * @param sopInstanceUID [in] The SOP Instance UID of the object written
  752. */
  753. virtual void notifyInstanceStored(const OFString &filename,
  754. const OFString &sopClassUID,
  755. const OFString &sopInstanceUID) const;
  756. /** This function is called while sending DIMSE messages, i.e.\ on each PDV of a dataset.
  757. * The default implementation just prints a TRACE message on the number of bytes sent so
  758. * far. By overwriting this method, the progress of the send process can be shown to the
  759. * user in a more appropriate way. The progress notification can also be disabled
  760. * completely by calling setProgressNotificationMode().
  761. * @param byteCount [in] Number of bytes sent so far
  762. */
  763. virtual void notifySENDProgress(const unsigned long byteCount);
  764. /** This function is called while receiving DIMSE messages, i.e.\ on each PDV of a dataset.
  765. * The default implementation just prints a TRACE message on the number of bytes received
  766. * so far. By overwriting this method, the progress of the receive process can be shown to
  767. * the user in a more appropriate way. The progress notification can also be disabled
  768. * completely by calling setProgressNotificationMode().
  769. * @param byteCount [in] Number of bytes received so far
  770. */
  771. virtual void notifyRECEIVEProgress(const unsigned long byteCount);
  772. /** Check given N-EVENT-REPORT request and dataset for validity. This method is called by
  773. * handleEVENTREPORTRequest() before sending the response in order to determine the
  774. * DIMSE status code to be used for the response message.
  775. * @param request [in] The N-EVENT-REPORT request message data structure
  776. * @param reqDataset [in] The N-EVENT-REPORT request dataset received. Might be NULL.
  777. * @return DIMSE status code to be used for the N-EVENT-REPORT response.
  778. * Always returns STATUS_Success (0). Derived classes should, therefore,
  779. * overwrite this method and return a more appropriate value based on the
  780. * result of the checks performed.
  781. */
  782. virtual Uint16 checkEVENTREPORTRequest(T_DIMSE_N_EventReportRQ &request,
  783. DcmDataset *reqDataset);
  784. /** Sends back a C-STORE response on the given presentation context, with the designated
  785. * status, fitting the corresponding C-STORE request.
  786. * @param presID [in] The presentation context ID to be used.
  787. * @param status [in] The storage DIMSE status to be used.
  788. * @param request [in] The C-STORE request that should be responded to.
  789. * @result EC_Normal if the response could be sent, error otherwise.
  790. */
  791. virtual OFCondition sendSTOREResponse(T_ASC_PresentationContextID presID,
  792. Uint16 status,
  793. const T_DIMSE_C_StoreRQ &request);
  794. /** Helper function that generates a storage filename by extracting SOP Class and SOP
  795. * Instance UID from a dataset and combining that with the configured storage directory.
  796. * The SOP class is used to create an initial two letter abbreviation for the
  797. * corresponding modality, e.g. CT. An example for a storage filename created by this
  798. * function is /storage_dir/CT.1.2.3.4.5 for a CT with SOP Instance UID 1.2.3.4.
  799. * This function might be overwritten to change the filename behaviour completely. This
  800. * function is only called if the SCU is in DCMSCU_STORAGE_DISK mode.
  801. * @param dataset [in] The dataset that should be stored to disk
  802. * @result Non-empty string if successful, otherwise empty string.
  803. */
  804. virtual OFString createStorageFilename(DcmDataset *dataset);
  805. /** Receives a DICOM dataset on a given presentation context ID but does not store it in
  806. * memory or disk, thus ignoring it.
  807. * @param presID [in] The presentation context to be used
  808. * @param request [in] The corresponding C-STORE request
  809. * @return EC_Normal if ignoring worked, error code otherwise.
  810. */
  811. virtual OFCondition ignoreSTORERequest(T_ASC_PresentationContextID presID,
  812. const T_DIMSE_C_StoreRQ &request);
  813. /* Callback functions (static) */
  814. /** Callback function used for sending DIMSE messages.
  815. * @param callbackContext [in] The desired user callback data
  816. * @param byteCount [in] Progress bytes count
  817. */
  818. static void callbackSENDProgress(void *callbackContext,
  819. unsigned long byteCount);
  820. /** Callback function used for receiving DIMSE messages.
  821. * @param callbackContext [in] The desired user callback data
  822. * @param byteCount [in] Progress bytes count
  823. */
  824. static void callbackRECEIVEProgress(void *callbackContext,
  825. unsigned long byteCount);
  826. private:
  827. /** Private undefined copy-constructor. Shall never be called.
  828. * @param src Source object
  829. */
  830. DcmSCU(const DcmSCU &src);
  831. /** Private undefined operator=. Shall never be called.
  832. * @param src Source object
  833. * @return Reference to this
  834. */
  835. DcmSCU &operator=(const DcmSCU &src);
  836. /// Associaton of this SCU. This class only handles 1 association at a time.
  837. T_ASC_Association *m_assoc;
  838. /// The DICOM network the association is based on
  839. T_ASC_Network *m_net;
  840. /// Association parameters
  841. T_ASC_Parameters *m_params;
  842. /// Configuration file for presentation contexts (optional)
  843. OFString m_assocConfigFilename;
  844. /// Profile in configuration file that should be used (optional)
  845. OFString m_assocConfigProfile;
  846. /// Defines presentation context, consisting of one abstract syntax name
  847. /// and a list of transfer syntaxes for this abstract syntax
  848. struct DcmSCUPresContext {
  849. /** Default constructor
  850. */
  851. DcmSCUPresContext()
  852. : abstractSyntaxName()
  853. , transferSyntaxes()
  854. , roleSelect(ASC_SC_ROLE_DEFAULT)
  855. {
  856. }
  857. /// Abstract Syntax Name of Presentation Context
  858. OFString abstractSyntaxName;
  859. /// List of Transfer Syntaxes for Presentation Context
  860. OFList<OFString> transferSyntaxes;
  861. /// Role Selection
  862. T_ASC_SC_ROLE roleSelect;
  863. };
  864. /// List of presentation contexts that should be negotiated
  865. OFList<DcmSCUPresContext> m_presContexts;
  866. /// Configuration file containing association parameters
  867. OFString m_assocConfigFile;
  868. /// The last DIMSE successfully sent, unresponded DIMSE request
  869. T_DIMSE_Message *m_openDIMSERequest;
  870. /// Maximum PDU size
  871. Uint32 m_maxReceivePDULength;
  872. /// DIMSE blocking mode
  873. T_DIMSE_BlockingMode m_blockMode;
  874. /// AEtitle of this application
  875. OFString m_ourAETitle;
  876. /// Peer hostname
  877. OFString m_peer;
  878. /// AEtitle of remote application
  879. OFString m_peerAETitle;
  880. /// Port of remote application entity
  881. Uint16 m_peerPort;
  882. /// DIMSE timeout
  883. Uint32 m_dimseTimeout;
  884. /// ACSE timeout
  885. Uint32 m_acseTimeout;
  886. /// Storage directory for objects received with C-STORE due to a
  887. /// running C-GET session. Per default, the received objects
  888. /// are stored in the current working directory.
  889. OFString m_storageDir;
  890. /// Set whether bit preserving storage should be enabled, i.e.\ any objects
  891. /// retrieved via C-STORE should be written directly to disk without
  892. /// any data correction/re-computation (e.g.\ group length calculations,
  893. /// padding, etc.). This is especially interesting for retaining valid
  894. /// signatures, and also to receive huge files which cannot be fully received
  895. /// in memory. Default is OFFalse (no bit preserving) storage.
  896. DcmStorageMode m_storageMode;
  897. /// Verbose PC mode
  898. OFBool m_verbosePCMode;
  899. /// Dataset conversion mode
  900. OFBool m_datasetConversionMode;
  901. /// Progress notification mode
  902. OFBool m_progressNotificationMode;
  903. /** Returns next available message ID free to be used by SCU
  904. * @return Next free message ID
  905. */
  906. Uint16 nextMessageID();
  907. };
  908. #endif // DCMTK 3.6.0
  909. #endif // SCU_H