Mercurial > hg > orthanc
comparison Core/DicomNetworking/DicomStoreUserConnection.cpp @ 3831:83ea6939293d
starting DicomStoreUserConnection::Store()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 10 Apr 2020 17:56:12 +0200 |
parents | e82bd07c384e |
children | 594263db316a |
comparison
equal
deleted
inserted
replaced
3830:447880856ce8 | 3831:83ea6939293d |
---|---|
32 | 32 |
33 | 33 |
34 #include "../PrecompiledHeaders.h" | 34 #include "../PrecompiledHeaders.h" |
35 #include "DicomStoreUserConnection.h" | 35 #include "DicomStoreUserConnection.h" |
36 | 36 |
37 #include "DicomAssociation.h" | 37 #include "../DicomParsing/FromDcmtkBridge.h" |
38 | 38 #include "../DicomParsing/ParsedDicomFile.h" |
39 #include "../Logging.h" | 39 #include "../Logging.h" |
40 #include "../OrthancException.h" | 40 #include "../OrthancException.h" |
41 #include "DicomAssociation.h" | |
42 | |
43 #include <dcmtk/dcmdata/dcdeftag.h> | |
44 | |
41 | 45 |
42 namespace Orthanc | 46 namespace Orthanc |
43 { | 47 { |
44 bool DicomStoreUserConnection::ProposeStorageClass(const std::string& sopClassUid, | 48 bool DicomStoreUserConnection::ProposeStorageClass(const std::string& sopClassUid, |
45 const std::set<DicomTransferSyntax>& syntaxes) | 49 const std::set<DicomTransferSyntax>& syntaxes) |
235 **/ | 239 **/ |
236 | 240 |
237 association_->Open(parameters_); | 241 association_->Open(parameters_); |
238 return LookupPresentationContext(presentationContextId, sopClassUid, transferSyntax); | 242 return LookupPresentationContext(presentationContextId, sopClassUid, transferSyntax); |
239 } | 243 } |
244 | |
245 | |
246 void DicomStoreUserConnection::Store(std::string& sopClassUid, | |
247 std::string& sopInstanceUid, | |
248 DcmDataset& dataset, | |
249 const std::string& moveOriginatorAET, | |
250 uint16_t moveOriginatorID) | |
251 { | |
252 OFString a, b; | |
253 if (!dataset.findAndGetOFString(DCM_SOPClassUID, a).good() || | |
254 !dataset.findAndGetOFString(DCM_SOPInstanceUID, b).good()) | |
255 { | |
256 throw OrthancException(ErrorCode_NoSopClassOrInstance, | |
257 "Unable to determine the SOP class/instance for C-STORE with AET " + | |
258 parameters_.GetRemoteApplicationEntityTitle()); | |
259 } | |
260 | |
261 sopClassUid.assign(a.c_str()); | |
262 sopInstanceUid.assign(b.c_str()); | |
263 | |
264 DicomTransferSyntax transferSyntax; | |
265 if (!FromDcmtkBridge::LookupOrthancTransferSyntax( | |
266 transferSyntax, dataset.getOriginalXfer())) | |
267 { | |
268 throw OrthancException(ErrorCode_InternalError, | |
269 "Unknown transfer syntax from DCMTK"); | |
270 } | |
271 | |
272 // Figure out which accepted presentation context should be used | |
273 uint8_t presID; | |
274 if (!NegotiatePresentationContext(presID, sopClassUid.c_str(), transferSyntax)) | |
275 { | |
276 throw OrthancException(ErrorCode_InternalError, | |
277 "No valid presentation context was negotiated upfront"); | |
278 } | |
279 | |
280 // Prepare the transmission of data | |
281 T_DIMSE_C_StoreRQ request; | |
282 memset(&request, 0, sizeof(request)); | |
283 request.MessageID = association_->GetDcmtkAssociation().nextMsgID++; | |
284 strncpy(request.AffectedSOPClassUID, sopClassUid.c_str(), DIC_UI_LEN); | |
285 request.Priority = DIMSE_PRIORITY_MEDIUM; | |
286 request.DataSetType = DIMSE_DATASET_PRESENT; | |
287 strncpy(request.AffectedSOPInstanceUID, sopInstanceUid.c_str(), DIC_UI_LEN); | |
288 | |
289 if (!moveOriginatorAET.empty()) | |
290 { | |
291 strncpy(request.MoveOriginatorApplicationEntityTitle, | |
292 moveOriginatorAET.c_str(), DIC_AE_LEN); | |
293 request.opts = O_STORE_MOVEORIGINATORAETITLE; | |
294 | |
295 request.MoveOriginatorID = moveOriginatorID; // The type DIC_US is an alias for uint16_t | |
296 request.opts |= O_STORE_MOVEORIGINATORID; | |
297 } | |
298 | |
299 // Finally conduct transmission of data | |
300 T_DIMSE_C_StoreRSP response; | |
301 DcmDataset* statusDetail = NULL; | |
302 DicomAssociation::CheckCondition( | |
303 DIMSE_storeUser(&association_->GetDcmtkAssociation(), presID, &request, | |
304 NULL, &dataset, /*progressCallback*/ NULL, NULL, | |
305 /*opt_blockMode*/ (GetParameters().HasTimeout() ? DIMSE_NONBLOCKING : DIMSE_BLOCKING), | |
306 /*opt_dimse_timeout*/ GetParameters().GetTimeout(), | |
307 &response, &statusDetail, NULL), | |
308 GetParameters(), "C-STORE"); | |
309 | |
310 if (statusDetail != NULL) | |
311 { | |
312 delete statusDetail; | |
313 } | |
314 | |
315 /** | |
316 * New in Orthanc 1.6.0: Deal with failures during C-STORE. | |
317 * http://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.2.3.html#table_B.2-1 | |
318 **/ | |
319 | |
320 if (response.DimseStatus != 0x0000 && // Success | |
321 response.DimseStatus != 0xB000 && // Warning - Coercion of Data Elements | |
322 response.DimseStatus != 0xB007 && // Warning - Data Set does not match SOP Class | |
323 response.DimseStatus != 0xB006) // Warning - Elements Discarded | |
324 { | |
325 char buf[16]; | |
326 sprintf(buf, "%04X", response.DimseStatus); | |
327 throw OrthancException(ErrorCode_NetworkProtocol, | |
328 "C-STORE SCU to AET \"" + | |
329 GetParameters().GetRemoteApplicationEntityTitle() + | |
330 "\" has failed with DIMSE status 0x" + buf); | |
331 } | |
332 } | |
333 | |
334 | |
335 void DicomStoreUserConnection::Store(std::string& sopClassUid, | |
336 std::string& sopInstanceUid, | |
337 ParsedDicomFile& parsed, | |
338 const std::string& moveOriginatorAET, | |
339 uint16_t moveOriginatorID) | |
340 { | |
341 Store(sopClassUid, sopInstanceUid, *parsed.GetDcmtkObject().getDataset(), | |
342 moveOriginatorAET, moveOriginatorID); | |
343 } | |
344 | |
345 | |
346 void DicomStoreUserConnection::Store(std::string& sopClassUid, | |
347 std::string& sopInstanceUid, | |
348 const void* buffer, | |
349 size_t size, | |
350 const std::string& moveOriginatorAET, | |
351 uint16_t moveOriginatorID) | |
352 { | |
353 std::unique_ptr<DcmFileFormat> dicom( | |
354 FromDcmtkBridge::LoadFromMemoryBuffer(buffer, size)); | |
355 | |
356 Store(sopClassUid, sopInstanceUid, *dicom->getDataset(), | |
357 moveOriginatorAET, moveOriginatorID); | |
358 } | |
240 } | 359 } |