/usr/include/dcmtk/dcmnet/dstorscu.h is in libdcmtk-dev 3.6.1~20150924-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | /*
*
* Copyright (C) 2011-2014, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* OFFIS e.V.
* R&D Division Health
* Escherweg 2
* D-26121 Oldenburg, Germany
*
*
* Module: dcmnet
*
* Author: Joerg Riesmeier
*
* Purpose: DICOM Storage Service Class User (SCU)
*
*/
#ifndef DSTORSCU_H
#define DSTORSCU_H
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmnet/scu.h" /* for base class DcmSCU */
/*---------------------*
* class declaration *
*---------------------*/
/** Interface class for a Storage Service Class User (SCU).
* This class supports C-STORE messages as an SCU. In a first step, the SOP instances to be
* sent are added to a transfer list. In a second step, the association negotiation takes
* place where the required presentation contexts are proposed, i.e. it is checked which SOP
* classes and transfer syntaxes are needed for transferring the SOP instances. Finally, the
* SOP instances are sent to the SCP (if possible).
* \note
* \li The current implementation does not sort the transfer list according to the SOP
* Class UID and Transfer Syntax UID of the SOP instances and, therefore, might propose
* more presentation contexts than required for the transfer of all SOP instances. A
* simple optimization that is performed internally is to check whether the current SOP
* instance can be sent using a presentation context that has previously been added for
* another SOP instance (of the same kind). This approach also makes sure that studies
* and series are not mixed up, assuming that they have been added to the transfer list
* in the "correct" order.
* \li Another limitation of the current implementation is the handling of the "Default
* Transfer Syntax" in case of compression. According to the DICOM standard, the
* default transfer syntax for "Lossless JPEG Compression", "Lossy JPEG Compression"
* and so on has to be proposed in at least one presentation context for the particular
* SOP class. This is not (yet) implemented since the re-encoding of compressed
* datasets is not supported. Nevertheless, depending on the options used, the default
* transfer syntax for the uncompressed case is always proposed (if possible).
*/
class DCMTK_DCMNET_EXPORT DcmStorageSCU
: public DcmSCU
{
public:
/** dataset decompression modes
*/
enum E_DecompressionMode
{
/// never decompress datasets
DM_never,
/// decompress lossless only
DM_losslessOnly,
/// default value: decompress lossless only
DM_default = DM_losslessOnly,
/// decompress both lossy and lossless
DM_lossyAndLossless
};
/** dataset handling modes
*/
enum E_HandlingMode
{
/// do nothing with the dataset
HM_doNothing,
/// compact the dataset after it has been sent
HM_compactAfterSend,
/// delete the dataset after it has been sent
HM_deleteAfterSend,
/// delete the dataset after it has been removed from the transfer list
HM_deleteAfterRemove
};
/** default constructor
*/
DcmStorageSCU();
/** destructor
*/
virtual ~DcmStorageSCU();
/** clear the internal member variables
*/
virtual void clear();
/** get value of the association counter. This counter is initialized with 0 (that means
* no association exists) and increased by 1 for every new association. The counter is
* only reset when clear() is called.
* @return value of the association counter
*/
unsigned long getAssociationCounter() const;
/** get number of SOP instances stored in the transfer list
* @return number of SOP instances stored in the transfer list
*/
size_t getNumberOfSOPInstances() const;
/** get number of SOP instances that are to be sent (i.e.\ that are not yet sent). Please
* note that internally the transfer list is iterated to determine this number, so
* depending on the size of the list it might take some time.
* @return number of SOP instances that are to be sent
*/
size_t getNumberOfSOPInstancesToBeSent() const;
/** get mode that specifies whether or not compressed datasets are decompressed if needed,
* i.e.\ whether the transfer syntax of the dataset is changed for network transmission.
* @return decompression mode. See definition of DcmStorageSCU::E_DecompressionMode for
* possible values.
*/
E_DecompressionMode getDecompressionMode() const;
/** get mode that specifies whether to halt if an invalid file is encountered during batch
* processing (e.g.\ when adding SOP instances from a DICOMDIR) or whether to continue
* with the next SOP instance.
* @return mode indicating whether to halt on invalid file or not
*/
OFBool getHaltOnInvalidFileMode() const;
/** get mode that specifies whether to halt if unsuccessful store encountered or whether
* to continue with the next SOP instance.
* @return mode indicating whether to halt on unsuccessful store or not
*/
OFBool getHaltOnUnsuccessfulStoreMode() const;
/** get mode that specifies whether to propose presentation contexts that do not contain
* the default transfer syntax although it is needed, which might result in a violation
* of the DICOM standard.
* @return mode indicating whether illegal proposals are allowed or not
*/
OFBool getAllowIllegalProposalMode() const;
/** get mode that specifies whether to read information on SOP instances to be sent from
* the DICOMDIR files that are added to the transfer list.
* @return mode indicating whether to read from DICOMDIR files or not
*/
OFBool getReadFromDICOMDIRMode() const;
/** get C-MOVE originator information (if set)
* @param aeTitle the AE title of the originating C-MOVE client. Empty if not set.
* @param messageID the message ID used within the originating C-MOVE request. 0 if
* not set.
* @return OFTrue if either of both parameters is set
*/
OFBool getMOVEOriginatorInfo(OFString &aeTitle,
Uint16 &messageID) const;
/** set mode that specifies whether or not compressed datasets are decompressed if needed,
* i.e.\ whether the transfer syntax of the dataset is changed for network transmission.
* @param decompressionMode decompression mode. See definition of
* DcmStorageSCU::E_DecompressionMode for both possible values
* and the default value.
*/
void setDecompressionMode(const E_DecompressionMode decompressionMode);
/** set mode that specifies whether to halt if an invalid file is encountered during batch
* processing (e.g.\ when adding SOP instances from a DICOMDIR) or whether to continue
* with the next SOP instance.
* @param haltMode mode indicating whether to halt or not (default: OFTrue, i.e.\ halt)
*/
void setHaltOnInvalidFileMode(const OFBool haltMode);
/** set mode that specifies whether to halt if unsuccessful store encountered or whether
* to continue with the next SOP instance.
* @param haltMode mode indicating whether to halt or not (default: OFTrue, i.e.\ halt)
*/
void setHaltOnUnsuccessfulStoreMode(const OFBool haltMode);
/** set mode that specifies whether to propose presentation contexts that do not contain
* the default transfer syntax, although it is needed, which might result in a violation
* of the DICOM standard. For example, if a lossless compressed SOP instance is to be
* sent, there should be at least one presentation context for this SOP class that also
* proposes the default transfer syntax (Implicit VR Little Endian).
* @param allowMode mode indicating whether illegal proposals are allowed or not
* (default: OFTrue, i.e.\ allowed)
*/
void setAllowIllegalProposalMode(const OFBool allowMode);
/** set mode that specifies whether to read information on SOP instances to be sent from
* the DICOMDIR files that are added to the transfer list. If this mode is disabled, a
* DICOMDIR file is treated like any other input file. If this mode is enabled, a
* DICOMDIR file is not added to the transfer list, but the DICOM files referenced from
* it are.
* @param readMode mode indicating whether to read from DICOMDIR files or not
* (default: OFFalse, i.e.\ do not read)
*/
void setReadFromDICOMDIRMode(const OFBool readMode);
/** set C-MOVE originator information.
* If the C-STORE operation was initiated by a client's C-MOVE request, it is possible
* to convey the C-MOVE originating information (AE title and the message ID of the
* corresponding C-MOVE message) as part of the C-STORE messages in order to inform the
* C-STORE receiver (Storage SCP) about the original sender (Move SCU).
* @param aeTitle the AE title of the originating C-MOVE client. If empty, none is
* sent.
* @param messageID message ID of the originating C-MOVE request. If 0, none is sent.
*/
void setMOVEOriginatorInfo(const OFString &aeTitle = "",
const Uint16 messageID = 0);
/** reset the sent status for all SOP instances in the transfer list. This allows for
* sending the same SOP instances again - on the same or a different association.
* @param sameAssociation flag indicating whether the same association will be used for
* the transfer as last time. If a different association will
* be used, also the presentation context IDs are set to 0
* (undefined), which means that addPresentationContexts() has
* to be called again. Please make sure that all dataset
* pointers in the transfer list are still valid, i.e. the
* datasets have not been deleted.
*/
void resetSentStatus(const OFBool sameAssociation = OFFalse);
/** remove all SOP instances from the transfer list. If an entry contains a reference to
* a DICOM dataset, this dataset is deleted if the handling mode HM_deleteAfterRemove was
* used to add it to the transfer list.
*/
void removeAllSOPInstances();
/** remove a particular SOP instance from the transfer list. If the corresponding entry
* contains a reference to a DICOM dataset, this dataset is deleted if the handling mode
* HM_deleteAfterRemove was used to add it to the transfer list.
* @param sopClassUID SOP Class UID of the SOP instance to be removed
* @param sopInstanceUID SOP Instance UID of the SOP instance to be removed
* @param allOccurrences flag specifying whether to delete all occurrences of the
* SOP instance if it has been added to the list multiple times.
* If OFFalse, only the first occurrence is removed.
* @return status, EC_Normal if successful, an error code otherwise
*/
OFCondition removeSOPInstance(const OFString &sopClassUID,
const OFString &sopInstanceUID,
const OFBool allOccurrences = OFTrue);
/** add a SOP instance stored as a DICOM file or a number of SOP instances referenced from
* a DICOMDIR to the list of instances to be transferred. Before adding a SOP instance
* to the list, it is checked for validity and conformance to the DICOM standard
* (see checkSOPInstance() for details). However, duplicate instances are not
* recognized, i.e. they are added to the list and later on transferred to the storage
* SCP when calling sendSOPInstances(). If the specified DICOM file is a DICOMDIR and
* the 'ReadFromDICOMDIRMode' is enabled, the referenced SOP instances are added to the
* transfer list (using the relevant information from the DICOMDIR) and not the DICOMDIR
* itself, which is not meant to be transferred anyway. Please note that it is not
* checked whether the referenced files really exist.
* @param filename name of the DICOM file that contains the SOP instance or name of
* the DICOMDIR file that references the SOP instances to be sent
* @param readMode read mode passed to the DcmFileFormat::loadFile() method. If
* ERM_fileOnly, only the file meta information header is loaded,
* i.e. the behavior is identical to using ERM_metaOnly.
* @param checkValues flag indicating whether to check the UID values for validity and
* conformance. If OFFalse, only empty values are rejected.
* @return status, EC_Normal if successful, an error code otherwise
*/
OFCondition addDicomFile(const OFString &filename,
const E_FileReadMode readMode = ERM_fileOnly,
const OFBool checkValues = OFTrue);
/** add a SOP instance from a given DICOM dataset to the list of instances to be
* transferred. Before adding the SOP instance to the list, it is checked for validity
* and conformance to the DICOM standard (see checkSOPInstance() for details). However,
* duplicate instances are not recognized, i.e. they are added to the list and later on
* transferred to the storage SCP when calling sendSOPInstances().
* @param dataset DICOM dataset that contains the SOP instance to be sent
* @param datasetXfer transfer syntax of the dataset (determined automatically if
* unknown, which is also the default)
* @param handlingMode mode specifying what to do with the dataset if no longer needed.
* HM_xxxAfterSend has no effect if the C-STORE request could not
* be sent.
* Please do not add the same dataset multiple times with a mode of
* HM_deleteAfterXXX, since it will result in deleting the same
* object multiple times!
* @param checkValues flag indicating whether to check the UID values for validity and
* conformance. If OFFalse, only empty values are rejected.
* @return status, EC_Normal if successful, an error code otherwise
*/
OFCondition addDataset(DcmDataset *dataset,
const E_TransferSyntax datasetXfer = EXS_Unknown,
const E_HandlingMode handlingMode = HM_compactAfterSend,
const OFBool checkValues = OFTrue);
/** add presentation contexts for all SOP instances in the transfer list, which were not
* yet sent (either successfully or unsuccessfully). Initially, the internal list of
* presentation contexts is cleared. Then, the transfer list is iterated and a new
* presentation context is added for each SOP instance that cannot be sent using any of
* the previously added presentation contexts. If the maximum of 128 presentation
* contexts, which can be negotiated during a single association, is reached, this method
* returns and any subsequent call adds the next bunch of presentation contexts needed.
* @return status, EC_Normal if successful, an error code otherwise. If no presentation
* contexts have been added, NET_EC_NoPresentationContextsDefined is returned. This
* code can, therefore, be used to check that all SOP instances from the transfer list
* have been negotiated and sent in previous calls.
*/
OFCondition addPresentationContexts();
/** negotiate association by using presentation contexts and parameters as defined by
* earlier method calls. If negotiation fails, there is no need to close the
* association or to do anything else with this class.
* In addition to the implementation inherited from the base class DcmSCU, this method
* also handles the case that none of the proposed presentation contexts was accepted.
* And, it also increases the association counter by 1 for each new association
* (including the ones that are not successful).
* @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition negotiateAssociation();
/** send SOP instances to be transferred to the specified peer. After the presentation
* contexts for the current association have been added and negotiated, the SOP instances
* that are to be sent on this association can be transferred with this method. Unless
* the corresponding mode is disabled using setHaltOnUnsuccessfulStoreMode(), the
* transfer is stopped on the first SOP instance that could not be "stored" successfully.
* Please note, however, that the DIMSE status is not checked for this purpose, i.e. the
* transfer is never stopped when the DIMSE status is different from 0x0000 (success).
* Each time a SOP instance from the transfer list has been processed, the virtual method
* notifySOPInstanceSent() is called, which can be overwritten by a derived class.
* The sending process can be stopped by overwriting shouldStopAfterCurrentSOPInstance()
* in a derived class. The sending process can be continued with the next SOP instance
* by calling sendSOPInstances() again.
* @return status, EC_Normal if successful, an error code otherwise
*/
OFCondition sendSOPInstances();
/** get some status information on the overall sending process. This text can for example
* be output to the logger (on the level at the user's option).
* @param summary reference to a string in which the summary is stored
*/
void getStatusSummary(OFString &summary) const;
/** create a text file with a detailed report on the transfer of DICOM SOP instances. In
* addition to a general header and some status information at the end (as generated by
* getStatusSummary()), a couple of basic details on each SOP instance in the transfer
* list are written to the file:
* - Consecutive number
* - Name of the DICOM file
* - SOP Instance UID
* - SOP Class UID (and associated name)
* - Transfer Syntax UID (and associated name)
* - Number of the association (that was used to transfer the instance)
* - Presentation Context ID (that was used to transfer the instance)
* - DIMSE Status (if instance was sent) or reason why it was not sent
* @param filename name of the text file in which the report is stored
* @return status, EC_Normal if successful, an error code otherwise
*/
OFCondition createReportFile(const OFString &filename) const;
protected:
/** internal class/struct for a single transfer entry
*/
struct DCMTK_DCMNET_EXPORT TransferEntry
{
/** constructor. Initializes member variables with reasonable values.
* @param filename filename of the SOP instance to be transferred
* @param readMode mode to read the given SOP instance from file
* @param sopClassUID SOP Class UID of the SOP instance to be transferred
* @param sopInstanceUID SOP Instance UID of the SOP instance to be transferred
* @param transferSyntaxUID Transfer Syntax UID of the SOP instance to be
* transferred
*/
TransferEntry(const OFString &filename,
const E_FileReadMode readMode,
const OFString &sopClassUID,
const OFString &sopInstanceUID,
const OFString &transferSyntaxUID);
/** constructor. Initializes member variables with reasonable values.
* @param dataset pointer to the dataset of the SOP instance to be
* transferred
* @param handlingMode mode specifying what to do with the dataset if no
* longer needed
* @param sopClassUID SOP Class UID of the SOP instance to be transferred
* @param sopInstanceUID SOP Instance UID of the SOP instance to be transferred
* @param transferSyntaxUID Transfer Syntax UID of the SOP instance to be
* transferred
*/
TransferEntry(DcmDataset *dataset,
const E_HandlingMode handlingMode,
const OFString &sopClassUID,
const OFString &sopInstanceUID,
const OFString &transferSyntaxUID);
/** destructor
*/
~TransferEntry();
/// filename of the SOP instance to be transferred (if no 'Dataset' given)
const OFString Filename;
/// read mode that should be used to read the given SOP instance from file
const E_FileReadMode FileReadMode;
/// dataset of the SOP instance to be transferred (if no 'Filename' given)
DcmDataset *Dataset;
/// handling mode specifying what to do with the dataset if no longer needed
const E_HandlingMode DatasetHandlingMode;
/// SOP Class UID of the SOP instance to be transferred
const OFString SOPClassUID;
/// SOP Instance UID of the SOP instance to be transferred
const OFString SOPInstanceUID;
/// Transfer Syntax UID of the SOP instance to be transferred
const OFString TransferSyntaxUID;
/// transfer syntax that was used to send this SOP instance
E_TransferSyntax NetworkTransferSyntax;
/// flag indicating whether the SOP instance is uncompressed, i.e.\ uses any of the
/// three uncompressed transfer syntaxes
OFBool Uncompressed;
/// association number that was used to send this SOP instance (0 = not sent)
unsigned long AssociationNumber;
/// presentation context ID to be used for sending this SOP instance
T_ASC_PresentationContextID PresentationContextID;
/// flag indicating whether the C-STORE request has been sent (OFTrue = sent)
OFBool RequestSent;
/// DIMSE status of the C-STORE response (0x0000 = success)
Uint16 ResponseStatusCode;
private:
/** initialize further member variables
*/
void Init();
// private undefined copy constructor
TransferEntry(const TransferEntry &);
// private undefined assignment operator
TransferEntry &operator=(const TransferEntry &);
};
/** add SOP instances referenced from a given DICOMDIR to the list of instances to be
* transferred. Please note that the referenced DICOM files are not loaded during this
* process. Only the relevant information contained in the DICOMDIR is used.
* @param filename name of the DICOMDIR file that contains the references to SOP
* instances to be sent
* @param readMode read mode passed to the DcmFileFormat::loadFile() method when
* reading the referenced DICOM files. Not used for the DICOMDIR.
* @param checkValues flag indicating whether to check the UID values of the SOP
* instances to be added for validity and conformance. If OFFalse,
* only empty values are rejected.
* @return status, EC_Normal if successful, an error code otherwise
*/
OFCondition addDicomFilesFromDICOMDIR(const OFString &filename,
const E_FileReadMode readMode,
const OFBool checkValues);
// --- static methods ---
/** check given SOP Class UID, SOP Instance UID and Transfer Syntax UID for validity and
* conformance to the DICOM standard. For all UID values, the compliance with the
* requirements of the value representation "Unique Identifier" (UI) and value
* multiplicity is checked. For the SOP Class UID, it is also checked whether it is a
* known or at least a possible storage SOP class (either a standard or a private one).
* For the Transfer Syntax UID, it is checked whether it is known and generally
* supported. Further checks will be performed when the list of presentation contexts is
* created for the association negotiation.
* @param sopClassUID value of the SOP Class UID to be checked
* @param sopInstanceUID value of the SOP Instance UID to be checked
* @param transferSyntaxUID value of the Transfer Syntax UID to be checked
* @param checkValues flag indicating whether to check the UID values for
* validity and conformance. If OFFalse, only empty values
* are rejected.
* @return status, EC_Normal if successful, an error code otherwise
*/
static OFCondition checkSOPInstance(const OFString &sopClassUID,
const OFString &sopInstanceUID,
const OFString &transferSyntaxUID,
const OFBool checkValues);
/** This method is called each time a SOP instance is sent to a peer. Since it is called
* after the SOP instance has been processed, the transfer entry passed to this method
* contains current information, e.g. the DIMSE status of the C-STORE response. This
* also allows for counting the number of successful and failed transfers.
* @param transferEntry reference to current transfer entry that has been processed
*/
virtual void notifySOPInstanceSent(const TransferEntry &transferEntry);
/** This method is called each time after a SOP instance is sent to a peer. If the
* return value is OFTrue, the SCU will stop the sending process after the current SOP
* instance. This could for example make sense when transferring SOP instances due to
* a C-MOVE request, which is externally canceled by a C-CANCEL message. The default
* implementation always returns OFFalse. A derived class may change this behavior.
* @return OFTrue if sending should stop after current SOP instance, OFFalse otherwise.
*/
virtual OFBool shouldStopAfterCurrentSOPInstance();
private:
/// association counter
unsigned long AssociationCounter;
/// presentation context counter
unsigned long PresentationContextCounter;
/// decompression mode, i.e.\ whether a dataset is decompressed for transmission
E_DecompressionMode DecompressionMode;
/// flag indicating whether to halt on invalid file
OFBool HaltOnInvalidFileMode;
/// flag indicating whether to halt on unsuccessful store
OFBool HaltOnUnsuccessfulStoreMode;
/// flag indicating whether to allow illegal proposals
OFBool AllowIllegalProposalMode;
/// flag indicating whether to read from DICOMDIR files
OFBool ReadFromDICOMDIRMode;
/// AE title of the C-MOVE client that initiated the C-STORE operation (if applicable)
OFString MoveOriginatorAETitle;
/// message ID of the C-MOVE message that initiated the C-STORE operation (if applicable)
Uint16 MoveOriginatorMsgID;
/// list of SOP instances to be transferred
OFList<TransferEntry *> TransferList;
/// iterator pointing to the current entry in the list of SOP instances to be transferred
OFListIterator(TransferEntry *) CurrentTransferEntry;
// private undefined copy constructor
DcmStorageSCU(const DcmStorageSCU &);
// private undefined assignment operator
DcmStorageSCU &operator=(const DcmStorageSCU &);
};
#endif // DSTORSCU_H
|