3
* $Id: dicomstoreassociation.cpp 3784 2011-04-27 12:07:33Z tovar $
6
* Copyright 2008-10 MetaEmotion S.L. All rights reserved.
7
* http://ginkgo-cadx.com
9
* This file is licensed under LGPL v3 license.
10
* See License.txt for details
12
* Code adapted from OsiriX
15
#define LOGGER "C-STORE"
16
#include <api/icontroladorlog.h>
17
#include <main/controllers/controladorlog.h>
18
#include <api/icontextoestudio.h>
22
#define MACRO_QUE_ESTORBA verify
26
#include "dicomstoreassociation.h"
27
#include <api/idicommanager.h>
28
#include <api/internacionalizacion.h>
29
#include <api/iproxynotificadorprogreso.h>
30
#include <main/controllers/controladorpermisos.h>
31
#include <main/entorno.h>
34
#include <main/controllers/dcmtk/dicomservers.h>
36
#include <dcmtk/ofstd/ofstring.h>
37
#include <dcmtk/dcmnet/dimse.h>
38
#include <dcmtk/dcmnet/diutil.h>
39
#include <dcmtk/dcmdata/dcdatset.h>
40
#include <dcmtk/dcmdata/dcmetinf.h>
41
#include <dcmtk/dcmdata/dcfilefo.h>
42
//#include <dcmtk/dcmdata/dcdebug.h>
43
#include <dcmtk/dcmdata/dcuid.h>
44
#include <dcmtk/dcmdata/dcdict.h>
45
#include <dcmtk/dcmdata/dcdeftag.h>
46
//#include "cmdlnarg.h"
47
#include <dcmtk/ofstd/ofconapp.h>
48
#include <dcmtk/dcmdata/dcuid.h> /* for dcmtk version name */
49
#include <dcmtk/dcmnet/dicom.h> /* for DICOM_APPLICATION_REQUESTOR */
50
#include <dcmtk/dcmdata/dcostrmz.h> /* for dcmZlibCompressionLevel */
51
#include <dcmtk/dcmnet/dcasccfg.h> /* for class DcmAssociationConfiguration */
52
#include <dcmtk/dcmnet/dcasccff.h> /* for class DcmAssociationConfigurationFile */
54
#include <dcmtk/dcmjpeg/djencode.h> /* for dcmjpeg encoders */
55
#include <dcmtk/dcmjpeg/djdecode.h> /* for dcmjpeg encoders */
56
#include <dcmtk/dcmdata/dcrledrg.h> /* for DcmRLEDecoderRegistration */
57
#include <dcmtk/dcmdata/dcrleerg.h> /* for DcmRLEEncoderRegistration */
58
#include <dcmtk/dcmjpeg/djrploss.h>
59
#include <dcmtk/dcmjpeg/djrplol.h>
60
#include <dcmtk/dcmdata/dcpixel.h>
61
#include <dcmtk/dcmdata/dcrlerp.h>
64
#include "tls/gtlslayer.h"
65
#include <dcmtk/dcmtls/tlstrans.h>
67
#include "helpercompresion.h"
69
#ifdef MACRO_QUE_ESTORBA
70
#define verify MACRO_QUE_ESTORBA
73
#include <wx/filename.h>
76
/////////////////////-------------------------DEFINES--------------------/////////////////
81
/* default application titles */
82
#define APPLICATIONTITLE "GINKGO"
83
#define PEERAPPLICATIONTITLE "DCM4CHEE"
85
static OFBool opt_verbose = OFTrue;
86
static OFBool opt_showPresentationContexts = OFTrue;
87
static OFBool opt_debug = OFTrue;
88
static OFBool opt_abortAssociation = OFFalse;
89
static OFCmdUnsignedInt opt_maxReceivePDULength = ASC_DEFAULTMAXPDU;
90
//static OFCmdUnsignedInt opt_maxSendPDULength = 0;
91
static E_TransferSyntax opt_networkTransferSyntax = EXS_LittleEndianExplicit;
93
//static OFBool opt_haltOnUnsuccessfulStore = OFTrue;
94
static OFBool opt_haltOnUnsuccessfulStore = OFFalse;
95
static OFBool unsuccessfulStoreEncountered = OFFalse;
96
static std::string errorEncontrado;
97
int lastStatusCode = STATUS_Success;
99
static OFBool opt_proposeOnlyRequiredPresentationContexts = OFFalse;
100
static OFBool opt_combineProposedTransferSyntaxes = OFFalse;
102
static OFCmdUnsignedInt opt_repeatCount = 1;
103
static OFCmdUnsignedInt opt_inventPatientCount = 25;
104
static OFCmdUnsignedInt opt_inventStudyCount = 50;
105
static OFCmdUnsignedInt opt_inventSeriesCount = 100;
106
static OFBool opt_inventSOPInstanceInformation = OFFalse;
107
static OFBool opt_correctUIDPadding = OFFalse;
108
static OFString patientNamePrefix("OFFIS^TEST_PN_"); // PatientName is PN (maximum 16 chars)
109
static OFString patientIDPrefix("PID_"); // PatientID is LO (maximum 64 chars)
110
static OFString studyIDPrefix("SID_"); // StudyID is SH (maximum 16 chars)
111
static OFString accessionNumberPrefix; // AccessionNumber is SH (maximum 16 chars)
112
//static OFBool opt_secureConnection = OFFalse; /* default: no secure connection */
113
//static const char *opt_configFile = NULL;
114
//static const char *opt_profileName = NULL;
115
T_DIMSE_BlockingMode opt_blockMode = DIMSE_NONBLOCKING;
116
int opt_dimse_timeout = 0;
117
int opt_acse_timeout = 30;
118
int opt_Quality = 100;
122
typedef struct _StoreCallbackInfo {
123
T_ASC_Association* assoc;
127
static GNC::IProxyNotificadorProgreso* m_pNotificadorProgreso = NULL;
128
static std::string m_mensaje("");
129
typedef struct TMedida{
131
int bytesDescargados;
134
m_instante = time(NULL);
135
bytesDescargados = 0;
139
static TMedida m_medida;
141
float TasaTransferencia(int bytesDescargados)
143
time_t nuevoInstante = time(NULL);
144
const double tiempo = difftime(nuevoInstante,m_medida.m_instante);
146
if(bytesDescargados > m_medida.bytesDescargados) {
147
const double bytesRecibidosPeriodo = bytesDescargados - m_medida.bytesDescargados;
148
m_medida.oldTasa = ( ((float)bytesRecibidosPeriodo/1024.0f)/tiempo );
149
m_medida.bytesDescargados = bytesDescargados;
150
m_medida.m_instante = nuevoInstante;
153
return m_medida.oldTasa;
156
void ResetearMedida(bool clearTasa = false) {
157
m_medida.bytesDescargados =-1;
158
m_medida.m_instante = time(NULL);
160
m_medida.oldTasa=0.0f;
164
static void errmsg(const std::string& mensaje, bool parar)
166
LOG_ERROR(LOGGER,mensaje);
168
throw GIL::DICOM::PACSException(mensaje);
174
errmsg(const OFString& message, bool parar)
176
std::string mensaje(message.c_str());
177
errmsg(mensaje,parar);
181
static OFBool isaListMember(OFList<OFString>& lst, OFString& s)
183
OFListIterator(OFString) cur = lst.begin();
184
OFListIterator(OFString) end = lst.end();
186
OFBool found = OFFalse;
188
while (cur != end && !found) {
198
static OFCondition addPresentationContext(T_ASC_Parameters *params,
199
int presentationContextId, const OFString& abstractSyntax,
200
const OFString& transferSyntax,
201
T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT)
203
const char* c_p = transferSyntax.c_str();
204
OFCondition cond = ASC_addPresentationContext(params, presentationContextId,
205
abstractSyntax.c_str(), &c_p, 1, proposedRole);
209
static OFCondition addPresentationContext(T_ASC_Parameters *params,
210
int presentationContextId, const OFString& abstractSyntax,
211
const OFList<OFString>& transferSyntaxList,
212
T_ASC_SC_ROLE proposedRole = ASC_SC_ROLE_DEFAULT)
214
// create an array of supported/possible transfer syntaxes
215
const char** transferSyntaxes = new const char*[transferSyntaxList.size()];
216
int transferSyntaxCount = 0;
217
OFListConstIterator(OFString) s_cur = transferSyntaxList.begin();
218
OFListConstIterator(OFString) s_end = transferSyntaxList.end();
219
while (s_cur != s_end) {
220
transferSyntaxes[transferSyntaxCount++] = (*s_cur).c_str();
224
OFCondition cond = ASC_addPresentationContext(params, presentationContextId,
225
abstractSyntax.c_str(), transferSyntaxes, transferSyntaxCount, proposedRole);
227
delete[] transferSyntaxes;
231
static OFCondition addStoragePresentationContexts(T_ASC_Parameters *params, OFList<OFString>& sopClasses)
234
* Each SOP Class will be proposed in two presentation contexts (unless
235
* the opt_combineProposedTransferSyntaxes global variable is true).
236
* The command line specified a preferred transfer syntax to use.
237
* This prefered transfer syntax will be proposed in one
238
* presentation context and a set of alternative (fallback) transfer
239
* syntaxes will be proposed in a different presentation context.
241
* Generally, we prefer to use Explicitly encoded transfer syntaxes
242
* and if running on a Little Endian machine we prefer
243
* LittleEndianExplicitTransferSyntax to BigEndianTransferSyntax.
244
* Some SCP implementations will just select the first transfer
245
* syntax they support (this is not part of the standard) so
246
* organise the proposed transfer syntaxes to take advantage
250
// Which transfer syntax was preferred on the command line
251
OFString preferredTransferSyntax;
252
if (opt_networkTransferSyntax == EXS_Unknown) {
253
/* gLocalByteOrder is defined in dcxfer.h */
254
if (gLocalByteOrder == EBO_LittleEndian) {
255
/* we are on a little endian machine */
256
preferredTransferSyntax = UID_LittleEndianExplicitTransferSyntax;
258
/* we are on a big endian machine */
259
preferredTransferSyntax = UID_BigEndianExplicitTransferSyntax;
262
DcmXfer xfer(opt_networkTransferSyntax);
263
preferredTransferSyntax = xfer.getXferID();
266
OFListIterator(OFString) s_cur;
267
OFListIterator(OFString) s_end;
270
OFList<OFString> fallbackSyntaxes;
271
fallbackSyntaxes.push_back(UID_LittleEndianExplicitTransferSyntax);
272
fallbackSyntaxes.push_back(UID_BigEndianExplicitTransferSyntax);
273
fallbackSyntaxes.push_back(UID_LittleEndianImplicitTransferSyntax);
274
// Remove the preferred syntax from the fallback list
275
fallbackSyntaxes.remove(preferredTransferSyntax);
276
// If little endian implicit is preferred then we don't need any fallback syntaxes
277
// because it is the default transfer syntax and all applications must support it.
278
if (opt_networkTransferSyntax == EXS_LittleEndianImplicit) {
279
fallbackSyntaxes.clear();
282
// created a list of transfer syntaxes combined from the preferred and fallback syntaxes
283
OFList<OFString> combinedSyntaxes;
284
s_cur = fallbackSyntaxes.begin();
285
s_end = fallbackSyntaxes.end();
286
combinedSyntaxes.push_back(preferredTransferSyntax);
287
while (s_cur != s_end)
289
if (!isaListMember(combinedSyntaxes, *s_cur)) combinedSyntaxes.push_back(*s_cur);
293
if (!opt_proposeOnlyRequiredPresentationContexts) {
294
// add the (short list of) known storage sop classes to the list
295
// the array of Storage SOP Class UIDs comes from dcuid.h
297
//FIXME: ĆAPA HECHA PARA QUE PUEDA SUBIR VIDEOS(EL -1 Y EL PUSH DE DESPUES)
298
for (int i=0; i<numberOfDcmShortSCUStorageSOPClassUIDs-1; i++) {
299
sopClasses.push_back(dcmShortSCUStorageSOPClassUIDs[i]);
301
// UID_VideoPhotographicImageStorage
302
sopClasses.push_back("1.2.840.10008.5.1.4.1.1.77.1.4.1");
305
// thin out the sop classes to remove any duplicates.
306
OFList<OFString> sops;
307
s_cur = sopClasses.begin();
308
s_end = sopClasses.end();
309
while (s_cur != s_end) {
310
if (!isaListMember(sops, *s_cur)) {
311
sops.push_back(*s_cur);
316
// add a presentations context for each sop class / transfer syntax pair
317
OFCondition cond = EC_Normal;
318
int pid = 1; // presentation context id
319
s_cur = sops.begin();
321
while (s_cur != s_end && cond.good()) {
324
//errmsg("Demasiados contextos de presentacion");
325
return ASC_BADPRESENTATIONCONTEXTID;
328
if (opt_combineProposedTransferSyntaxes) {
329
cond = addPresentationContext(params, pid, *s_cur, combinedSyntaxes);
330
pid += 2; /* only odd presentation context id's */
333
// sop class with preferred transfer syntax
334
cond = addPresentationContext(params, pid, *s_cur, preferredTransferSyntax);
335
pid += 2; /* only odd presentation context id's */
337
if (fallbackSyntaxes.size() > 0) {
339
//errmsg("Demasiados contextos de presentacion");
340
return ASC_BADPRESENTATIONCONTEXTID;
343
// sop class with fallback transfer syntax
344
cond = addPresentationContext(params, pid, *s_cur, fallbackSyntaxes);
345
pid += 2; /* only odd presentation context id's */
354
static int secondsSince1970()
356
time_t t = time(NULL);
360
static OFString intToString(int i)
363
sprintf(numbuf, "%d", i);
367
static OFString makeUID(OFString basePrefix, int counter)
369
OFString prefix = basePrefix + "." + intToString(counter);
371
OFString uid = dcmGenerateUniqueIdentifier(uidbuf, prefix.c_str());
375
static OFBool updateStringAttributeValue(DcmItem* dataset, const DcmTagKey& key, OFString& value)
380
OFCondition cond = EC_Normal;
381
cond = dataset->search(key, stack, ESM_fromHere, OFFalse);
382
if (cond != EC_Normal) {
383
LOG_DEBUG(LOGGER,"error: updateStringAttributeValue: cannot find: " << tag.getTagName() << " " << key << ": "<< cond.text());
387
DcmElement* elem = (DcmElement*) stack.top();
389
DcmVR vr(elem->ident());
390
if (elem->getLength() > vr.getMaxValueLength()) {
391
LOG_DEBUG(LOGGER,"error: updateStringAttributeValue: INTERNAL ERROR: " << tag.getTagName()<< " " << key << ": value too large (max "<< vr.getMaxValueLength() << ") for " << vr.getVRName() << " value: " << value );
395
cond = elem->putOFStringArray(value);
396
if (cond != EC_Normal) {
397
LOG_DEBUG(LOGGER, "error: updateStringAttributeValue: cannot put string in attribute: " << tag.getTagName()<< " " << key << ": "<< cond.text());
404
static void replaceSOPInstanceInformation(DcmDataset* dataset)
406
static OFCmdUnsignedInt patientCounter = 0;
407
static OFCmdUnsignedInt studyCounter = 0;
408
static OFCmdUnsignedInt seriesCounter = 0;
409
static OFCmdUnsignedInt imageCounter = 0;
410
static OFString seriesInstanceUID;
411
static OFString seriesNumber;
412
static OFString studyInstanceUID;
413
static OFString studyID;
414
static OFString accessionNumber;
415
static OFString patientID;
416
static OFString patientName;
418
if (seriesInstanceUID.length() == 0) seriesInstanceUID=makeUID(SITE_SERIES_UID_ROOT, (int)seriesCounter);
419
if (seriesNumber.length() == 0) seriesNumber = intToString((int)seriesCounter);
420
if (studyInstanceUID.length() == 0) studyInstanceUID = makeUID(SITE_STUDY_UID_ROOT, (int)studyCounter);
421
if (studyID.length() == 0) studyID = studyIDPrefix + intToString((int)secondsSince1970()) + intToString((int)studyCounter);
422
if (accessionNumber.length() == 0) accessionNumber = accessionNumberPrefix + intToString(secondsSince1970()) + intToString((int)studyCounter);
423
if (patientID.length() == 0) patientID = patientIDPrefix + intToString(secondsSince1970()) + intToString((int)patientCounter);
424
if (patientName.length() == 0) patientName = patientNamePrefix + intToString(secondsSince1970()) + intToString((int)patientCounter);
426
if (imageCounter >= opt_inventSeriesCount) {
429
seriesInstanceUID = makeUID(SITE_SERIES_UID_ROOT, (int)seriesCounter);
430
seriesNumber = intToString((int)seriesCounter);
432
if (seriesCounter >= opt_inventStudyCount) {
435
studyInstanceUID = makeUID(SITE_STUDY_UID_ROOT, (int)studyCounter);
436
studyID = studyIDPrefix + intToString(secondsSince1970()) + intToString((int)studyCounter);
437
accessionNumber = accessionNumberPrefix + intToString(secondsSince1970()) + intToString((int)studyCounter);
439
if (studyCounter >= opt_inventPatientCount) {
440
// we create as many patients as necessary */
443
patientID = patientIDPrefix + intToString(secondsSince1970()) + intToString((int)patientCounter);
444
patientName = patientNamePrefix + intToString(secondsSince1970()) + intToString((int)patientCounter);
447
OFString sopInstanceUID = makeUID(SITE_INSTANCE_UID_ROOT, (int)imageCounter);
448
OFString imageNumber = intToString((int)imageCounter);
451
LOG_DEBUG(LOGGER, "Inventing Identifying Information (" <<
452
"pa" << patientCounter << ", st" << studyCounter <<
453
", se" << seriesCounter << ", im" << imageCounter << "): " << std::endl
454
<< " PatientName=" << patientName << std::endl
455
<< " PatientID=" << patientID << std::endl
456
<< " StudyInstanceUID=" << studyInstanceUID << std::endl
457
<< " StudyID=" << studyID << std::endl
458
<< " SeriesInstanceUID=" << seriesInstanceUID << std::endl
459
<< " SeriesNumber=" << seriesNumber << std::endl
460
<< " SOPInstanceUID=" << sopInstanceUID << std::endl
461
<< " ImageNumber=" << imageNumber << std::endl);
464
updateStringAttributeValue(dataset, DCM_PatientName, patientName);
465
updateStringAttributeValue(dataset, DCM_PatientID, patientID);
466
updateStringAttributeValue(dataset, DCM_StudyInstanceUID, studyInstanceUID);
467
updateStringAttributeValue(dataset, DCM_StudyID, studyID);
468
updateStringAttributeValue(dataset, DCM_SeriesInstanceUID, seriesInstanceUID);
469
updateStringAttributeValue(dataset, DCM_SeriesNumber, seriesNumber);
470
updateStringAttributeValue(dataset, DCM_SOPInstanceUID, sopInstanceUID);
471
updateStringAttributeValue(dataset, DCM_InstanceNumber, imageNumber);
476
// ConversiĆ³n de transferencias
477
static OFBool decompressFile(DcmFileFormat fileformat, const char * fname, const char *outfname)
479
OFBool status = true;
481
DcmXfer filexfer(fileformat.getDataset()->getOriginalXfer());
483
if (filexfer.getXfer() == EXS_JPEG2000LosslessOnly || filexfer.getXfer() == EXS_JPEG2000)
485
status = DecompressJPEG2000(fname, outfname);
486
LOG_WARN(LOGGER,"Se ha descomprimido desde JPEG2000, podrĆan perderse algunos tags");
490
DcmDataset *dataset = fileformat.getDataset();
492
// decompress data set if compressed
493
dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
495
// check if everything went well
496
if (dataset->canWriteXfer(EXS_LittleEndianExplicit))
498
fileformat.loadAllDataIntoMemory();
500
cond = fileformat.saveFile( outfname, EXS_LittleEndianExplicit);
501
status = (cond.good()) ? true : false;
511
static OFBool compressFile(DcmFileFormat fileformat, const char * fname, const char *outfname)
514
OFBool status = true;
515
DcmXfer filexfer(fileformat.getDataset()->getOriginalXfer());
518
if (opt_networkTransferSyntax == EXS_JPEG2000)
520
status = CompressJPEG2000(fname, outfname);
521
LOG_WARN(LOGGER,"Se ha comprimido a JPEG2000, podrĆan perderse algunos tags");
523
else if (opt_networkTransferSyntax == EXS_JPEG2000LosslessOnly)
525
status = CompressJPEG2000(fname, outfname);
526
LOG_WARN(LOGGER,"Se ha comprimido a JPEG2000, podrĆan perderse algunos tags");
530
DcmDataset *dataset = fileformat.getDataset();
531
DcmItem *metaInfo = fileformat.getMetaInfo();
532
DcmRepresentationParameter *params;
533
DJ_RPLossy lossyParams(opt_Quality);
534
DcmRLERepresentationParameter rleParams;
535
DJ_RPLossless losslessParams; // codec parameters, we use the defaults
536
if (opt_networkTransferSyntax == EXS_JPEGProcess14SV1TransferSyntax)
537
params = &losslessParams;
538
else if (opt_networkTransferSyntax == EXS_JPEGProcess2_4TransferSyntax)
539
params = &lossyParams;
540
else if (opt_networkTransferSyntax == EXS_RLELossless)
543
params = &losslessParams;
546
// this causes the lossless JPEG version of the dataset to be created
547
dataset->chooseRepresentation(opt_networkTransferSyntax, params);
549
// check if everything went well
550
if (dataset->canWriteXfer(opt_networkTransferSyntax))
552
// force the meta-header UIDs to be re-generated when storing the file
553
// since the UIDs in the data set may have changed
554
delete metaInfo->remove(DCM_MediaStorageSOPClassUID);
555
delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID);
557
// store in lossless JPEG format
559
fileformat.loadAllDataIntoMemory();
563
cond = fileformat.saveFile( outfname, opt_networkTransferSyntax);
564
status = (cond.good()) ? true : false;
575
static long seed = 0;
578
static OFCondition storeSCU(T_ASC_Association * assoc, const char *fname)
580
* This function will read all the information from the given file,
581
* figure out a corresponding presentation context which will be used
582
* to transmit the information over the network to the SCP, and it
583
* will finally initiate the transmission of all data to the SCP.
586
* assoc - [in] The association (network connection to another DICOM application).
587
* fname - [in] Name of the file which shall be processed.
590
DIC_US msgId = assoc->nextMsgID++;
591
T_ASC_PresentationContextID presId;
592
T_DIMSE_C_StoreRQ req;
593
T_DIMSE_C_StoreRSP rsp;
596
std::ostringstream outfnameStringStream;
597
_StoreCallbackInfo storeCallbackData;
599
outfnameStringStream << GNC::Entorno::Instance()->GetGinkgoTempDir().c_str() << (char) wxFileName::GetPathSeparator(wxPATH_NATIVE) << seed++ << ".dcm";
601
std::string outfname = outfnameStringStream.str();
603
LOG_DEBUG(LOGGER, "tempfile: [" << outfname.c_str() << "]" );
605
//sprintf( outfname, "%s%ld.dcm", "D:\\temp\\", seed++);
607
unsuccessfulStoreEncountered = OFTrue; // assumption
610
LOG_DEBUG(LOGGER, "--------------------------\nSending file: "<< fname);
613
/* read information from file. After the call to DcmFileFormat::loadFile(...) the information */
614
/* which is encapsulated in the file will be available through the DcmFileFormat object. */
615
/* In detail, it will be available through calls to DcmFileFormat::getMetaInfo() (for */
616
/* meta header information) and DcmFileFormat::getDataset() (for data set information). */
618
OFCondition cond = dcmff.loadFile(fname);
620
/* NO LO PONEMOS A FUEGO COMPRIMIMOS Y DESCOMPRIMIMOS
621
opt_networkTransferSyntax = dcmff.getDataset()->getOriginalXfer();
624
/* figure out if an error occured while the file was read*/
626
LOG_DEBUG(LOGGER, "Bad DICOM file " << fname);
630
/* if required, invent new SOP instance information for the current data set (user option) */
631
if (opt_inventSOPInstanceInformation) {
632
replaceSOPInstanceInformation(dcmff.getDataset());
635
/* figure out which SOP class and SOP instance is encapsulated in the file */
636
if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(),
637
sopClass, sopInstance, opt_correctUIDPadding)) {
638
LOG_DEBUG(LOGGER, "No SOP Class & Instance UIDs in file " << fname);
639
return DIMSE_BADDATA;
642
/* figure out which of the accepted presentation contexts should be used */
643
DcmXfer filexfer(dcmff.getDataset()->getOriginalXfer());
645
/* special case: if the file uses an unencapsulated transfer syntax (uncompressed
646
* or deflated explicit VR) and we prefer deflated explicit VR, then try
647
* to find a presentation context for deflated explicit VR first.
649
if (filexfer.isNotEncapsulated() &&
650
opt_networkTransferSyntax == EXS_DeflatedLittleEndianExplicit)
652
filexfer = EXS_DeflatedLittleEndianExplicit;
656
/************* do on the fly conversion here*********************/
658
//printf("on the fly conversion\n");
659
//we have a valid presentation ID,.Chaeck and see if file is consistent with it
660
DcmXfer preferredXfer(opt_networkTransferSyntax);
662
OFBool status = false;
663
presId = ASC_findAcceptedPresentationContextID(assoc, sopClass, preferredXfer.getXferID());
664
T_ASC_PresentationContext pc;
665
ASC_findAcceptedPresentationContext(assoc->params, presId, &pc);
666
DcmXfer proposedTransfer(pc.acceptedTransferSyntax);
672
if (filexfer.isNotEncapsulated() && proposedTransfer.isNotEncapsulated()) {
676
else if (filexfer.isEncapsulated() && proposedTransfer.isNotEncapsulated()) {
677
status = decompressFile(dcmff, fname, outfname.c_str());
679
else if (filexfer.isNotEncapsulated() && proposedTransfer.isEncapsulated()) {
680
status = compressFile(dcmff, fname, outfname.c_str());
682
else if (filexfer.getXfer() != opt_networkTransferSyntax)
684
// The file is already compressed, we will re-compress the file.....
685
//E_TransferSyntax fileTS = filexfer.getXfer();
687
if( (filexfer.getXfer() == EXS_JPEG2000LosslessOnly && preferredXfer.getXfer() == EXS_JPEG2000) ||
688
(filexfer.getXfer() == EXS_JPEG2000 && preferredXfer.getXfer() == EXS_JPEG2000LosslessOnly))
692
LOG_WARN(LOGGER,"Recompressing files that are already compressed, you should optimize your ts parameters to avoid this: presentation for syntax:" << dcmFindNameOfUID(filexfer.getXferID()) << " -> " << dcmFindNameOfUID(preferredXfer.getXferID()));
694
status = compressFile(dcmff, fname, outfname.c_str());
703
cond = dcmff.loadFile( outfname.c_str());
704
filexfer = dcmff.getDataset()->getOriginalXfer();
706
/* figure out which SOP class and SOP instance is encapsulated in the file */
707
if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(),
708
sopClass, sopInstance, opt_correctUIDPadding)) {
709
LOG_DEBUG(LOGGER, "No SOP Class & Instance UIDs in file " << outfname);
710
return DIMSE_BADDATA;
713
fname = outfname.c_str();
715
const char *modalityName = dcmSOPClassUIDToModality(sopClass);
716
if (!modalityName) modalityName = dcmFindNameOfUID(sopClass);
717
if (!modalityName) modalityName = "unknown SOP class";
718
LOG_DEBUG(LOGGER, "No presentation context for: " << modalityName << " "<< sopClass);
719
std::ostringstream ostr;
720
ostr << _Std("Ginkgo CADx is unable to compress from ") << filexfer.getXferName() << _Std(" to ") << proposedTransfer.getXferName();
721
errmsg(ostr.str(),true);
722
return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
725
if (filexfer.getXfer() != EXS_Unknown)
726
presId = ASC_findAcceptedPresentationContextID(assoc, sopClass, filexfer.getXferID());
728
presId = ASC_findAcceptedPresentationContextID(assoc, sopClass);
731
const char *modalityName = dcmSOPClassUIDToModality(sopClass);
732
if (!modalityName) modalityName = dcmFindNameOfUID(sopClass);
733
if (!modalityName) modalityName = "unknown SOP class";
734
LOG_DEBUG(LOGGER, "No presentation context for: " << modalityName << " "<< sopClass);
735
return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
738
/* if required, dump general information concerning transfer syntaxes */
740
DcmXfer fileTransfer(dcmff.getDataset()->getOriginalXfer());
741
T_ASC_PresentationContext pc;
742
ASC_findAcceptedPresentationContext(assoc->params, presId, &pc);
743
DcmXfer netTransfer(pc.acceptedTransferSyntax);
744
LOG_DEBUG(LOGGER,"Transfer " << dcmFindNameOfUID(fileTransfer.getXferID()) << " -> " << dcmFindNameOfUID(netTransfer.getXferID()));
747
/* prepare the transmission of data */
748
bzero((char*)&req, sizeof(req));
749
req.MessageID = msgId;
750
strcpy(req.AffectedSOPClassUID, sopClass);
751
strcpy(req.AffectedSOPInstanceUID, sopInstance);
752
req.DataSetType = DIMSE_DATASET_PRESENT;
753
req.Priority = DIMSE_PRIORITY_LOW;
755
/* if required, dump some more general information */
757
LOG_DEBUG(LOGGER,"Store SCU RQ: MsgID (" <<msgId <<") "<< dcmSOPClassUIDToModality(sopClass));
760
/* finally conduct transmission of data */
762
storeCallbackData.assoc = assoc;
763
DcmDataset *statusDetail = NULL;
764
cond = DIMSE_storeUser(assoc, presId, &req,
765
NULL, dcmff.getDataset(), GIL::DICOM::DicomStoreAssociation::progressCallback, &storeCallbackData,
766
opt_blockMode, opt_dimse_timeout,
767
&rsp, &statusDetail, NULL, OFStandard::getFileSize(fname));
770
* If store command completed normally, with a status
771
* of success or some warning then the image was accepted.
773
if (cond == EC_Normal && (rsp.DimseStatus == STATUS_Success || DICOM_WARNING_STATUS(rsp.DimseStatus))) {
774
unsuccessfulStoreEncountered = OFFalse;
775
/* dump status detail information if there is some */
776
if (statusDetail != NULL) {
777
LOG_DEBUG(LOGGER, "DIMSE_storeUser(): Estado: " << std::endl << DumpDataset(statusDetail));
782
std::stringstream os;
783
os<< "Error al enviar el archivo";
784
if(statusDetail!=NULL)
785
statusDetail->print(os);
786
errorEncontrado = os.str();
787
LOG_ERROR(LOGGER, errorEncontrado);
792
/* remember the response's status for later transmissions of data */
793
lastStatusCode = rsp.DimseStatus;
795
/* dump some more general information */
796
if (cond == EC_Normal)
799
LOG_DEBUG(LOGGER,"Fichero Subido Correctamente " << fname);
804
LOG_DEBUG(LOGGER,"Store failed: " << fname);
805
DimseCondition::dump(cond);
810
// We created a temporary file. Delete it now.
812
unlink( outfname.c_str());
820
static OFCondition cstore(T_ASC_Association * assoc, const OFString& fname)
822
* This function will process the given file as often as is specified by opt_repeatCount.
823
* "Process" in this case means "read file, send C-STORE-RQ, receive C-STORE-RSP".
826
* assoc - [in] The association (network connection to another DICOM application).
827
* fname - [in] Name of the file which shall be processed.
830
OFCondition cond = EC_Normal;
832
/* opt_repeatCount specifies how many times a certain file shall be processed */
833
int n = (int)opt_repeatCount;
835
/* as long as no error occured and the counter does not equal 0 */
836
while ((cond.good()) && n-- && !(opt_haltOnUnsuccessfulStore && unsuccessfulStoreEncountered))
838
/* process file (read file, send C-STORE-RQ, receive C-STORE-RSP) */
839
cond = storeSCU(assoc, fname.c_str());
842
// we don't want to return an error code if --no-halt was specified.
843
if (! opt_haltOnUnsuccessfulStore)
848
/* return result value */
852
DicomStoreAssociation::DicomStoreAssociation()
854
std::cout << std::endl;
856
m_UseUserPass = false;
861
DicomStoreAssociation::~DicomStoreAssociation()
866
//no limpiamos no sea que los haya registrado otro que no seamos nosotros!!!
870
void DicomStoreAssociation::Store(ListaRutas listaFicheros, DicomServer* server, std::string nombreAETLocal,GNC::IProxyNotificadorProgreso* pNotificador, GIL::DICOM::TipoTransferSyntaxEnvio transferSyntax)
872
if (listaFicheros.size() == 0)
875
m_pNotificadorProgreso = pNotificador;
878
std::string nombreAETPar = server->AET;
879
opt_maxReceivePDULength = server->PDU;
880
std::string host = server->HostName;
881
unsigned int puerto = server->Port;
882
//TIMEOUT 15 SEGUNDOS
883
unsigned int dicomtimeout = 15;
884
bool _shouldAbort=false;
885
DcmFileFormat fileformat;
888
E_TransferSyntax transferSyntaxFichero;
893
cond = dcmff.loadFile(listaFicheros[0].c_str(),EXS_Unknown,EGL_noChange,DCM_TagInfoLength);
894
dcmff.loadAllDataIntoMemory();
896
errmsg(std::string("no se ha podido leer el dicom"),true);
898
DcmElement* elemento;
899
cond = dcmff.getDataset()->findAndGetElement(DcmTagKey(0x0010,0x0020),elemento);
901
std::stringstream strStream;
902
strStream << "Es necesario que este establecido el nombre y el ID del paciente";
903
errmsg(strStream.str(),true);
904
LOG_ERROR("C-STORE", strStream.str().c_str());
906
cond = dcmff.getDataset()->findAndGetElement(DcmTagKey(0x0010,0x0010),elemento);
908
std::stringstream strStream;
909
strStream << "Es necesario que este establecido el nombre y el ID del paciente";
910
errmsg(strStream.str(),true);
911
LOG_ERROR("C-STORE", strStream.str().c_str());
914
transferSyntaxFichero = dcmff.getDataset()->getOriginalXfer();
918
//se pilla el nombre del estudio y dlpaciente... ahora se comienza
920
const char *opt_peer = NULL;
921
OFCmdUnsignedInt opt_port = 104;
922
const char *opt_peerTitle = PEERAPPLICATIONTITLE;
923
const char *opt_ourTitle = APPLICATIONTITLE;
925
if(nombreAETPar.size()>0){
926
opt_peerTitle = nombreAETPar.c_str();
929
if(nombreAETLocal.size()>0){
930
opt_ourTitle = nombreAETLocal.c_str();
933
OFList<OFString> fileNameList; // list of files to transfer to SCP
934
OFList<OFString> sopClassUIDList; // the list of sop classes
935
OFList<OFString> sopInstanceUIDList; // the list of sop instances
937
T_ASC_Parameters *params;
938
DIC_NODENAME localHost;
939
DIC_NODENAME peerHost;
940
DcmAssociationConfiguration asccfg; // handler for association configuration profiles
942
opt_peer = host.c_str();
945
//verbose option set to true for now
946
opt_showPresentationContexts = OFFalse;
948
//debug code off for now
949
opt_debug = GNC::GCS::ControladorLog::Instance()->GetActiveLogLevel() == GNC::GCS::ControladorLog::DebugLog;
951
switch (transferSyntax) {
952
case SendExplicitLittleEndian:
953
opt_networkTransferSyntax = EXS_LittleEndianExplicit;
955
case SendJPEG2000Lossless:
956
opt_networkTransferSyntax = EXS_JPEG2000LosslessOnly;
959
case SendJPEG2000Lossy10:
960
opt_networkTransferSyntax = EXS_JPEG2000;
963
case SendJPEG2000Lossy20:
964
opt_networkTransferSyntax = EXS_JPEG2000;
967
case SendJPEG2000Lossy50:
968
opt_networkTransferSyntax = EXS_JPEG2000;
971
case SendJPEGLossless:
972
opt_networkTransferSyntax = EXS_JPEGProcess14SV1TransferSyntax;
975
opt_networkTransferSyntax = EXS_JPEGProcess2_4TransferSyntax;
979
opt_networkTransferSyntax = EXS_JPEGProcess2_4TransferSyntax;
983
opt_networkTransferSyntax = EXS_JPEGProcess2_4TransferSyntax;
986
case SendImplicitLittleEndian:
987
opt_networkTransferSyntax = EXS_LittleEndianImplicit;
990
opt_networkTransferSyntax = EXS_RLELossless;
992
case SendExplicitBigEndian:
993
opt_networkTransferSyntax = EXS_BigEndianExplicit;
996
opt_networkTransferSyntax = EXS_DeflatedLittleEndianExplicit;
999
opt_networkTransferSyntax = transferSyntaxFichero;
1000
//FIXME esta Ʊapa es necesaria porque el pacs de IRE no acepta baseline
1001
if (GNC::GCS::ControladorPermisos::Instance()->Get("core.pacs.limits","force_lossless")) {
1002
if (opt_networkTransferSyntax == EXS_JPEGProcess1TransferSyntax)
1004
opt_networkTransferSyntax = EXS_JPEGProcess14SV1TransferSyntax;
1011
opt_proposeOnlyRequiredPresentationContexts = OFFalse;
1013
dcmEnableUnknownVRGeneration.set(OFTrue);
1014
dcmEnableUnlimitedTextVRGeneration.set(OFTrue);
1017
dcmEnableUnknownVRGeneration.set(OFTrue);
1018
dcmEnableUnlimitedTextVRGeneration.set(OFTrue);
1021
OFCmdSignedInt opt_timeout = dicomtimeout;
1022
dcmConnectionTimeout.set((Sint32) opt_timeout);
1025
opt_acse_timeout = OFstatic_cast(int, opt_timeout);
1028
opt_dimse_timeout = OFstatic_cast(int, opt_timeout);
1029
opt_blockMode = DIMSE_NONBLOCKING;
1032
int paramCount = listaFicheros.size();
1033
const char *currentFilename = NULL;
1034
char sopClassUID[128];
1035
char sopInstanceUID[128];
1038
for (int i=0; i < paramCount; i++)
1040
ignoreName = OFFalse;
1041
currentFilename = listaFicheros[i].c_str();
1043
if (access(currentFilename, R_OK) < 0)
1045
std::stringstream strStream;
1046
strStream << "No se puede acceder al fichero: " << currentFilename;
1047
errmsg(strStream.str(), opt_haltOnUnsuccessfulStore);
1048
LOG_ERROR("C-STORE", strStream.str().c_str());
1052
if (opt_proposeOnlyRequiredPresentationContexts)
1054
if (!DU_findSOPClassAndInstanceInFile(currentFilename, sopClassUID, sopInstanceUID))
1056
ignoreName = OFTrue;
1057
std::stringstream strStream;
1058
strStream << "SOP class (o instance) no establecido en fichero: " << currentFilename;
1059
errmsg(strStream.str(), opt_haltOnUnsuccessfulStore);
1060
LOG_ERROR("C-STORE", strStream.str().c_str());
1062
else if (!dcmIsaStorageSOPClassUID(sopClassUID))
1064
ignoreName = OFTrue;
1065
std::stringstream strStream;
1066
strStream << "Storage sop class desconocido en fichero: " << currentFilename << ": " << sopClassUID;
1067
errmsg(strStream.str(), opt_haltOnUnsuccessfulStore);
1068
LOG_ERROR("C-STORE", strStream.str().c_str());
1072
sopClassUIDList.push_back(sopClassUID);
1073
sopInstanceUIDList.push_back(sopInstanceUID);
1076
if (!ignoreName) fileNameList.push_back(currentFilename);
1080
/* make sure data dictionary is loaded */
1081
if (!dcmDataDict.isDictionaryLoaded()) {
1082
LOG_WARN(LOGGER, "Warning: no data dictionary loaded, check environment variable");
1086
WORD wVersionRequested;
1089
wVersionRequested = MAKEWORD(1, 1);
1091
WSAStartup(wVersionRequested, &wsaData);
1094
/* initialize network, i.e. create an instance of T_ASC_Network*. */
1096
cond = ASC_initializeNetwork(NET_REQUESTOR, puerto, opt_acse_timeout, &net);
1099
DimseCondition::dump(cond);
1100
std::stringstream strStream;
1101
strStream << "DICOM Network Failure (storescu) ASC_initializeNetwork; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1102
LOG_ERROR("C-STORE", strStream.str().c_str());
1103
errmsg(strStream.str(),true);
1106
GTLSTransportLayer *tLayer = NULL;
1111
tLayer = new GTLSTransportLayer(DICOM_APPLICATION_REQUESTOR, NULL);
1114
DimseCondition::dump(cond);
1115
std::stringstream strStream;
1116
strStream << "Unable to create TLS transport layer";
1117
errmsg(strStream.str(),true);
1118
LOG_ERROR("C-STORE", strStream.str().c_str());
1120
tLayer->setCertificateFromString(GetCliCert());
1121
tLayer->setPrivateKeyFromString(GetCliKey());
1123
if (! tLayer->checkPrivateKeyMatchesCertificate())
1125
std::stringstream strStream;
1126
strStream << "private key and certificate do not match";
1127
errmsg(strStream.str(),true);
1128
LOG_ERROR("C-STORE", strStream.str().c_str());
1131
tLayer->addSystemTrustedCertificates();
1133
if (GetValidate()) {
1134
tLayer->setCertificateVerification(DCV_requireCertificate);
1137
tLayer->setCertificateVerification(DCV_ignoreCertificate);
1140
if (opt_dhparam && ! (tLayer->setTempDHParameters(opt_dhparam)))
1142
LOG_WARN(assoc->ambitolog, "unable to load temporary DH parameters. Ignoring");
1146
cond = ASC_setTransportLayer(net, tLayer, 0);
1149
LOG_ERROR("C-STORE", "Error al insertar capa de transporte segura: " << cond.text());
1153
/* initialize asscociation parameters, i.e. create an instance of T_ASC_Parameters*. */
1154
cond = ASC_createAssociationParameters(¶ms, opt_maxReceivePDULength);
1155
DimseCondition::dump(cond);
1158
DimseCondition::dump(cond);
1159
std::stringstream strStream;
1160
strStream << "DICOM Network Failure (storescu) ASC_createAssociationParameters; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1161
errmsg(strStream.str(),true);
1162
LOG_ERROR("C-STORE", strStream.str().c_str());
1165
if (UseUserPass()) {
1166
cond = ASC_setIdentRQUserPassword(params, GetUser().c_str(), GetPass().c_str());
1167
DimseCondition::dump(cond);
1171
std::stringstream strStream;
1172
strStream << "DICOM Network Failure (storescu) ASC_createAssociationParameters; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1173
errmsg(strStream.str(),true);
1174
LOG_ERROR("C-STORE", strStream.str().c_str());
1177
/* sets this application's title and the called application's title in the params */
1178
/* structure. The default values to be set here are "STORESCU" and "ANY-SCP". */
1179
ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL);
1181
/* Set the transport layer type (type of network connection) in the params */
1182
/* strucutre. The default is an insecure connection; where OpenSSL is */
1183
/* available the user is able to request an encrypted,secure connection. */
1184
cond = ASC_setTransportLayerType(params, IsSecure());
1186
DimseCondition::dump(cond);
1187
std::stringstream strStream;
1188
strStream << "DICOM Network Failure (storescu) ASC_setTransportLayerType; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1189
errmsg(strStream.str(),true);
1190
LOG_ERROR("C-STORE", strStream.str().c_str());
1193
/* Figure out the presentation addresses and copy the */
1194
/* corresponding values into the association parameters.*/
1195
gethostname(localHost, sizeof(localHost) - 1);
1196
sprintf(peerHost, "%s:%d", opt_peer, (int)opt_port);
1197
//NSLog(@"peer host: %s", peerHost);
1198
cond = ASC_setPresentationAddresses(params, localHost, peerHost);
1200
DimseCondition::dump(cond);
1201
std::stringstream strStream;
1202
strStream << "DICOM Network Failure (storescu) ASC_setPresentationAddresses; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1203
errmsg(strStream.str(),true);
1204
LOG_ERROR("C-STORE", strStream.str().c_str());
1207
/* Set the presentation contexts which will be negotiated */
1208
/* when the network connection will be established */
1209
cond = addStoragePresentationContexts(params, sopClassUIDList);
1211
DimseCondition::dump(cond);
1212
std::stringstream strStream;
1213
strStream << "DICOM Network Failure (storescu) addStoragePresentationContexts; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1214
errmsg(strStream.str(),true);
1215
LOG_ERROR("C-STORE", strStream.str().c_str());
1219
/* dump presentation contexts if required */
1221
std::stringstream strStream;
1222
strStream << "Request Parameters:\n";
1223
ASC_dumpParameters(params, strStream);
1224
LOG_DEBUG(LOGGER,strStream.str());
1227
/* create association, i.e. try to establish a network connection to another */
1228
/* DICOM application. This call creates an instance of T_ASC_Association*. */
1229
LOG_DEBUG(LOGGER,"Requesting Association");
1230
cond = ASC_requestAssociation(net, params, &assoc);
1232
if (cond == DUL_ASSOCIATIONREJECTED) {
1233
T_ASC_RejectParameters rej;
1234
ASC_getRejectParameters(params, &rej);
1235
ASC_printRejectParameters(stderr, &rej);
1236
DimseCondition::dump(cond);
1237
std::stringstream strStream;
1238
strStream << "DICOM Network Failure (storescu) ASC_requestAssociation[DUL_ASSOCIATIONREJECTED]; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1239
errmsg(strStream.str(),true);
1240
LOG_ERROR("C-STORE", strStream.str().c_str());
1242
DimseCondition::dump(cond);
1243
std::stringstream strStream;
1244
strStream << "DICOM Network Failure (storescu) ASC_requestAssociation[Unknown]; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1245
errmsg(strStream.str(),true);
1246
LOG_ERROR("C-STORE", strStream.str().c_str());
1250
/* dump the connection parameters if in debug mode*/
1253
std::stringstream strStream;
1254
strStream << "Connection Parameters:\n";
1255
ASC_dumpConnectionParameters(assoc, strStream);
1256
LOG_DEBUG(LOGGER,strStream.str());
1259
/* dump the presentation contexts which have been accepted/refused */
1261
std::stringstream strStream;
1262
strStream << "Association Parameters Negotiated:\n";
1263
ASC_dumpParameters(params, strStream);
1264
LOG_DEBUG(LOGGER,strStream.str());
1267
/* count the presentation contexts which have been accepted by the SCP */
1268
/* If there are none, finish the execution */
1269
if (ASC_countAcceptedPresentationContexts(params) == 0) {
1270
std::stringstream strStream;
1271
strStream << "DICOM Network Failure (storescu) Contextos de presentacion no aceptados";
1272
errmsg(strStream.str(),true);
1273
LOG_WARN("C-STORE", strStream.str().c_str());
1276
/* dump general information concerning the establishment of the network connection if required */
1278
std::stringstream strStream;
1279
strStream << "Association Accepted (Max Send PDV: "<< assoc->sendPDVLength;
1280
LOG_DEBUG(LOGGER,strStream.str());
1283
/* do the real work, i.e. for all files which were specified in the */
1284
/* command line, transmit the encapsulated DICOM objects to the SCP. */
1286
OFListIterator(OFString) iter = fileNameList.begin();
1287
OFListIterator(OFString) enditer = fileNameList.end();
1290
//int _numberOfFiles =0;
1291
//int _numberErrors =0;
1294
ResetearMedida(true);
1295
while ((iter != enditer) && (cond == EC_Normal) && !_shouldAbort) // compare with EC_Normal since DUL_PEERREQUESTEDRELEASE is also good()
1297
wxString msg = wxString::Format(_("Uploading file %d of %d"),(_numberSent+1), listaFicheros.size());
1298
m_mensaje = std::string(msg.ToUTF8());
1299
pNotificador->NotificarProgreso(0.0f, m_mensaje);
1301
cond = cstore(assoc, *iter);
1303
if (!unsuccessfulStoreEncountered)
1306
//error cerramos las conexiones...
1310
//TODO CONFIGURACION MAXIMO NUMERO DFICHEROS Q SEPUEDE SUBIR, MAXIMO NUMERO DE ERRORES...
1314
/* tear down association, i.e. terminate network connection to SCP */
1315
if (cond == EC_Normal)
1317
if (opt_abortAssociation)
1319
cond = ASC_abortAssociation(assoc);
1322
LOG_DEBUG(LOGGER,"Abortando Asociacion: \n");
1323
DimseCondition::dump(cond);
1324
std::stringstream strStream;
1325
strStream << "DICOM Network Failure (storescu) Association Abort Failed; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1326
errmsg(strStream.str(),true);
1327
LOG_ERROR("C-STORE", strStream.str().c_str());
1331
/* release association */
1332
LOG_DEBUG(LOGGER,"Abortando Asociacion: \n");
1333
cond = ASC_releaseAssociation(assoc);
1336
ASC_dropAssociation(assoc);
1337
DimseCondition::dump(cond);
1338
std::stringstream strStream;
1339
strStream << "DICOM Network Failure (storescu) Association Abort Failed; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1340
errmsg(strStream.str(),true);
1341
LOG_ERROR("C-STORE", strStream.str().c_str());
1345
else if (cond == DUL_PEERREQUESTEDRELEASE)
1347
LOG_DEBUG(LOGGER,"Abortando Asociacion [PEERREQUESTEDRELEASE]");
1349
cond = ASC_abortAssociation(assoc);
1352
std::stringstream strStream;
1353
strStream << "DICOM Network Failure (storescu) Association Abort Failed; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1354
errmsg(strStream.str(),true);
1355
LOG_ERROR("C-STORE", strStream.str().c_str());
1358
else if (cond == DUL_PEERABORTEDASSOCIATION)
1360
std::stringstream strStream;
1361
strStream << "Fallo en la red DICOM (storescu) El servidor ha cerrado la conexion ";
1362
errmsg(strStream.str(),true);
1363
LOG_ERROR("C-STORE", strStream.str().c_str());
1367
DimseCondition::dump(cond);
1368
LOG_DEBUG(LOGGER,"Abortando Asociacion");
1370
cond = ASC_abortAssociation(assoc);
1373
DimseCondition::dump(cond);
1374
std::stringstream strStream;
1375
strStream << "DICOM Network Failure (storescu) Protocol Error: SCU Failed; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1376
errmsg(strStream.str(),true);
1377
LOG_ERROR("C-STORE", strStream.str().c_str());
1381
if ( unsuccessfulStoreEncountered)
1383
throw GIL::DICOM::PACSException(errorEncontrado);
1387
void DicomStoreAssociation::FreeMemory()
1389
/* destroy the association, i.e. free memory of T_ASC_Association* structure. This */
1390
/* call is the counterpart of ASC_requestAssociation(...) which was called above. */
1391
if (assoc != NULL) {
1392
OFCondition cond = ASC_destroyAssociation(&assoc);
1395
DimseCondition::dump(cond);
1396
std::stringstream strStream;
1397
strStream << "DICOM Network Failure (storescu) Protocol Error: ASC_destroyAssociation; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1398
errmsg(strStream.str(),true);
1399
LOG_ERROR("C-STORE", strStream.str().c_str());
1402
/* drop the network, i.e. free memory of T_ASC_Network* structure. This call */
1403
/* is the counterpart of ASC_initializeNetwork(...) which was called above. */
1406
OFCondition cond = ASC_dropNetwork(&net);
1409
DimseCondition::dump(cond);
1410
std::stringstream strStream;
1411
strStream << "DICOM Network Failure (storescu) Protocol Error: ASC_dropNetwork; Modulo: "<< cond.module() << "; Code:"<< cond.code() << "; " << cond.text();
1412
errmsg(strStream.str(),true);
1413
LOG_ERROR("C-STORE", strStream.str().c_str());
1420
void GIL::DICOM::DicomStoreAssociation::progressCallback(void * callbackData,
1421
T_DIMSE_StoreProgress *progress,
1422
T_DIMSE_C_StoreRQ * /*req*/)
1424
_StoreCallbackInfo *cbdata = (_StoreCallbackInfo*) callbackData;
1426
if (progress->state == DIMSE_StoreProgressing) {
1427
//si ha pasado medio segundo...
1428
std::stringstream ostr;
1430
ostr.setf(std::ios::floatfield, std::ios::fixed );
1432
ostr << " a " << TasaTransferencia(progress->progressBytes) << " kb/s";
1433
std::string msg(ostr.str());
1435
if(!m_pNotificadorProgreso->NotificarProgreso((float)progress->progressBytes/progress->totalBytes,msg))
1437
ASC_abortAssociation(cbdata->assoc);
1440
if (progress->state == DIMSE_StoreEnd) {