comparison OrthancServer/OrthancGetRequestHandler.cpp @ 3953:620e87e9e816 c-get

c-get: fixing memory with failedUIDs_
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 20 May 2020 09:19:35 +0200
parents d30bce4bdae9
children 67b457283499
comparison
equal deleted inserted replaced
3952:4f09a6a2b369 3953:620e87e9e816
69 { 69 {
70 return Status_Failure; 70 return Status_Failure;
71 } 71 }
72 72
73 const std::string& id = instances_[position_++]; 73 const std::string& id = instances_[position_++];
74 74
75 std::string dicom; 75 std::string dicom;
76 context_.ReadDicom(dicom, id); 76 context_.ReadDicom(dicom, id);
77 77
78 if(dicom.size() <= 0) 78 if (dicom.size() <= 0)
79 { 79 {
80 return Status_Failure; 80 return Status_Failure;
81 } 81 }
82 82
83 DcmInputBufferStream is; 83 std::unique_ptr<DcmFileFormat> parsed(
84 is.setBuffer(&dicom[0], dicom.size()); 84 FromDcmtkBridge::LoadFromMemoryBuffer(dicom.c_str(), dicom.size()));
85 is.setEos();
86
87 DcmFileFormat dcmff;
88 OFCondition cond = dcmff.read(is, EXS_Unknown, EGL_noChange, DCM_MaxReadLength);
89 if(cond.bad())
90 {
91 return Status_Failure;
92 }
93 85
94 // Determine the storage SOP class UID for this instance 86 // Determine the storage SOP class UID for this instance
95 DIC_UI sopClass; 87 DIC_UI sopClass;
96 DIC_UI sopInstance; 88 DIC_UI sopInstance;
97 89
98 #if DCMTK_VERSION_NUMBER >= 364 90 #if DCMTK_VERSION_NUMBER >= 364
99 if (!DU_findSOPClassAndInstanceInDataSet(static_cast<DcmItem *> (dcmff.getDataset()), 91 if (!DU_findSOPClassAndInstanceInDataSet(static_cast<DcmItem *> (parsed->getDataset()),
100 sopClass, sizeof(sopClass), 92 sopClass, sizeof(sopClass),
101 sopInstance, sizeof(sopInstance))) 93 sopInstance, sizeof(sopInstance)))
102 #else 94 #else
103 if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance)) 95 if (!DU_findSOPClassAndInstanceInDataSet(parsed->getDataset(), sopClass, sopInstance))
104 #endif 96 #endif
105 { 97 {
106 throw OrthancException(ErrorCode_NoSopClassOrInstance, 98 throw OrthancException(ErrorCode_NoSopClassOrInstance,
107 "Unable to determine the SOP class/instance for C-STORE with AET " + 99 "Unable to determine the SOP class/instance for C-STORE with AET " +
108 originatorAet_); 100 originatorAet_);
109 } 101 }
110 102
111 103 OFCondition cond = performGetSubOp(assoc, sopClass, sopInstance, parsed->getDataset());
112 104 if (getCancelled_)
113 105 {
114 cond = performGetSubOp(assoc, sopClass, sopInstance, dcmff.getDataset()); 106 LOG(INFO) << "Get SCP: Received C-Cancel RQ";
115 if (getCancelled_) { 107 }
116 LOG (INFO) << "Get SCP: Received C-Cancel RQ"; 108
117 } 109 if (cond.bad() || getCancelled_)
118
119 if(cond.bad() || getCancelled_)
120 { 110 {
121 return Status_Failure; 111 return Status_Failure;
122 } 112 }
123 113
124 return Status_Success; 114 return Status_Success;
125 } 115 }
116
126 117
127 void OrthancGetRequestHandler::addFailedUIDInstance(const char *sopInstance) 118 void OrthancGetRequestHandler::addFailedUIDInstance(const char *sopInstance)
128 { 119 {
129 size_t len; 120 if (failedUIDs_.empty())
130 121 {
131 if (failedUIDs_ == NULL) { 122 failedUIDs_ = sopInstance;
132 if ((failedUIDs_ = (char*)malloc(DIC_UI_LEN+1)) == NULL) { 123 }
133 LOG (ERROR) << "malloc failure: addFailedUIDInstance"; 124 else
134 return; 125 {
135 } 126 failedUIDs_ += "\\" + std::string(sopInstance);
136 strcpy(failedUIDs_, sopInstance);
137 } else {
138 len = strlen(failedUIDs_);
139 if ((failedUIDs_ = (char*)realloc(failedUIDs_,
140 (len+strlen(sopInstance)+2))) == NULL) {
141 LOG (ERROR) << "realloc failure: addFailedUIDInstance";
142 return;
143 }
144 // tag sopInstance onto end of old with '\' between
145 strcat(failedUIDs_, "\\");
146 strcat(failedUIDs_, sopInstance);
147 } 127 }
148 } 128 }
149 129
150 130
151 OFCondition OrthancGetRequestHandler::performGetSubOp(T_ASC_Association* assoc, 131 OFCondition OrthancGetRequestHandler::performGetSubOp(T_ASC_Association* assoc,
158 T_DIMSE_C_StoreRSP rsp; 138 T_DIMSE_C_StoreRSP rsp;
159 DIC_US msgId; 139 DIC_US msgId;
160 T_ASC_PresentationContextID presId; 140 T_ASC_PresentationContextID presId;
161 DcmDataset *stDetail = NULL; 141 DcmDataset *stDetail = NULL;
162 142
163
164 msgId = assoc->nextMsgID++; 143 msgId = assoc->nextMsgID++;
165 144
166 // which presentation context should be used 145 // which presentation context should be used
167 presId = ASC_findAcceptedPresentationContextID(assoc, 146 presId = ASC_findAcceptedPresentationContextID(assoc, sopClass);
168 sopClass); 147
169 if (presId == 0) { 148 if (presId == 0)
149 {
170 nFailed_++; 150 nFailed_++;
171 addFailedUIDInstance(sopInstance); 151 addFailedUIDInstance(sopInstance);
172 LOG (ERROR) << "Get SCP: storeSCU: No presentation context for: (" 152 LOG(ERROR) << "Get SCP: storeSCU: No presentation context for: ("
173 << dcmSOPClassUIDToModality(sopClass, "OT") << ") " << sopClass; 153 << dcmSOPClassUIDToModality(sopClass, "OT") << ") " << sopClass;
174 return DIMSE_NOVALIDPRESENTATIONCONTEXTID; 154 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
175 } else { 155 }
156 else
157 {
176 // make sure that we can send images in this presentation context 158 // make sure that we can send images in this presentation context
177 T_ASC_PresentationContext pc; 159 T_ASC_PresentationContext pc;
178 ASC_findAcceptedPresentationContext(assoc->params, presId, &pc); 160 ASC_findAcceptedPresentationContext(assoc->params, presId, &pc);
179 // the acceptedRole is the association requestor role 161 // the acceptedRole is the association requestor role
180 if ((pc.acceptedRole != ASC_SC_ROLE_SCP) && (pc.acceptedRole != ASC_SC_ROLE_SCUSCP)) 162 if ((pc.acceptedRole != ASC_SC_ROLE_SCP) && (pc.acceptedRole != ASC_SC_ROLE_SCUSCP))
181 { 163 {
182 // the role is not appropriate 164 // the role is not appropriate
183 nFailed_++; 165 nFailed_++;
184 addFailedUIDInstance(sopInstance); 166 addFailedUIDInstance(sopInstance);
185 LOG (ERROR) <<"Get SCP: storeSCU: [No presentation context with requestor SCP role for: (" 167 LOG(ERROR) <<"Get SCP: storeSCU: [No presentation context with requestor SCP role for: ("
186 << dcmSOPClassUIDToModality(sopClass, "OT") << ") " << sopClass; 168 << dcmSOPClassUIDToModality(sopClass, "OT") << ") " << sopClass;
187 return DIMSE_NOVALIDPRESENTATIONCONTEXTID; 169 return DIMSE_NOVALIDPRESENTATIONCONTEXTID;
188 } 170 }
189 } 171 }
190 172
191 req.MessageID = msgId; 173 req.MessageID = msgId;
193 strcpy(req.AffectedSOPInstanceUID, sopInstance); 175 strcpy(req.AffectedSOPInstanceUID, sopInstance);
194 req.DataSetType = DIMSE_DATASET_PRESENT; 176 req.DataSetType = DIMSE_DATASET_PRESENT;
195 req.Priority = priority_; 177 req.Priority = priority_;
196 req.opts = 0; 178 req.opts = 0;
197 179
198 LOG (INFO) << "Store SCU RQ: MsgID " << msgId << ", (" 180 LOG(INFO) << "Store SCU RQ: MsgID " << msgId << ", ("
199 << dcmSOPClassUIDToModality(sopClass, "OT") << ")"; 181 << dcmSOPClassUIDToModality(sopClass, "OT") << ")";
200 182
201 T_DIMSE_DetectedCancelParameters cancelParameters; 183 T_DIMSE_DetectedCancelParameters cancelParameters;
202 184
203 cond = DIMSE_storeUser(assoc, presId, &req, 185 cond = DIMSE_storeUser(assoc, presId, &req,
204 NULL, dataset, getSubOpProgressCallback, this, DIMSE_BLOCKING, 0, 186 NULL, dataset, getSubOpProgressCallback, this, DIMSE_BLOCKING, 0,
205 &rsp, &stDetail, &cancelParameters); 187 &rsp, &stDetail, &cancelParameters);
206 188
207 if (cond.good()) { 189 if (cond.good())
208 if (cancelParameters.cancelEncountered) { 190 {
191 if (cancelParameters.cancelEncountered)
192 {
209 if (origPresId == cancelParameters.presId && 193 if (origPresId == cancelParameters.presId &&
210 origMsgId == cancelParameters.req.MessageIDBeingRespondedTo) { 194 origMsgId == cancelParameters.req.MessageIDBeingRespondedTo)
195 {
211 getCancelled_ = OFTrue; 196 getCancelled_ = OFTrue;
212 } else {
213 LOG (ERROR) << "Get SCP: Unexpected C-Cancel-RQ encountered: pid=" << (int)cancelParameters.presId
214 << ", mid=" << (int)cancelParameters.req.MessageIDBeingRespondedTo;
215 } 197 }
198 else
199 {
200 LOG(ERROR) << "Get SCP: Unexpected C-Cancel-RQ encountered: pid=" << (int)cancelParameters.presId
201 << ", mid=" << (int)cancelParameters.req.MessageIDBeingRespondedTo;
202 }
216 } 203 }
217 204
218 if (rsp.DimseStatus == STATUS_Success) { 205 if (rsp.DimseStatus == STATUS_Success)
206 {
219 // everything ok 207 // everything ok
220 nCompleted_++; 208 nCompleted_++;
221 } else if ((rsp.DimseStatus & 0xf000) == 0xb000) { 209 }
210 else if ((rsp.DimseStatus & 0xf000) == 0xb000)
211 {
222 // a warning status message 212 // a warning status message
223 warningCount_++; 213 warningCount_++;
224 LOG (ERROR) << "Get SCP: Store Warning: Response Status: " << DU_cstoreStatusString(rsp.DimseStatus); 214 LOG(ERROR) << "Get SCP: Store Warning: Response Status: "
225 } else { 215 << DU_cstoreStatusString(rsp.DimseStatus);
216 }
217 else
218 {
226 nFailed_++; 219 nFailed_++;
227 addFailedUIDInstance(sopInstance); 220 addFailedUIDInstance(sopInstance);
228 // print a status message 221 // print a status message
229 LOG (ERROR) << "Get SCP: Store Failed: Response Status: " 222 LOG(ERROR) << "Get SCP: Store Failed: Response Status: "
230 << DU_cstoreStatusString(rsp.DimseStatus); 223 << DU_cstoreStatusString(rsp.DimseStatus);
231 } 224 }
232 } else { 225 }
226 else
227 {
233 nFailed_++; 228 nFailed_++;
234 addFailedUIDInstance(sopInstance); 229 addFailedUIDInstance(sopInstance);
235 OFString temp_str; 230 OFString temp_str;
236 LOG (ERROR) << "Get SCP: storeSCU: Store Request Failed: " << DimseCondition::dump(temp_str, cond); 231 LOG(ERROR) << "Get SCP: storeSCU: Store Request Failed: " << DimseCondition::dump(temp_str, cond);
237 } 232 }
238 if (stDetail) { 233
239 LOG (INFO) << " Status Detail:" << OFendl << DcmObject::PrintHelper(*stDetail); 234 if (stDetail)
235 {
236 LOG(INFO) << " Status Detail:" << OFendl << DcmObject::PrintHelper(*stDetail);
240 delete stDetail; 237 delete stDetail;
241 } 238 }
239
242 return cond; 240 return cond;
243 } 241 }
244 242
245 bool OrthancGetRequestHandler::LookupIdentifiers(std::vector<std::string>& publicIds, 243 bool OrthancGetRequestHandler::LookupIdentifiers(std::vector<std::string>& publicIds,
246 ResourceType level, 244 ResourceType level,
247 const DicomMap& input) 245 const DicomMap& input)
248 { 246 {
249 DicomTag tag(0, 0); // Dummy initialization 247 DicomTag tag(0, 0); // Dummy initialization
250 248
251 switch (level) 249 switch (level)
252 { 250 {
289 return true; 287 return true;
290 } 288 }
291 } 289 }
292 290
293 291
292 OrthancGetRequestHandler::OrthancGetRequestHandler(ServerContext& context) :
293 context_(context)
294 {
295 position_ = 0;
296 nRemaining_ = 0;
297 nCompleted_ = 0;
298 warningCount_ = 0;
299 nFailed_ = 0;
300 }
301
302
294 bool OrthancGetRequestHandler::Handle(const DicomMap& input, 303 bool OrthancGetRequestHandler::Handle(const DicomMap& input,
295 const std::string& originatorIp, 304 const std::string& originatorIp,
296 const std::string& originatorAet, 305 const std::string& originatorAet,
297 const std::string& calledAet) 306 const std::string& calledAet)
298 { 307 {
340 } 349 }
341 350
342 for (size_t i = 0; i < publicIds.size(); i++) 351 for (size_t i = 0; i < publicIds.size(); i++)
343 { 352 {
344 LOG(INFO) << "Sending resource " << publicIds[i] << " to modality \"" 353 LOG(INFO) << "Sending resource " << publicIds[i] << " to modality \""
345 << originatorAet << "\" in synchronous mode"; 354 << originatorAet << "\" in synchronous mode";
346 355
347 std::list<std::string> tmp; 356 std::list<std::string> tmp;
348 context_.GetIndex().GetChildInstances(tmp, publicIds[i]); 357 context_.GetIndex().GetChildInstances(tmp, publicIds[i]);
349 358
350 instances_.reserve(tmp.size()); 359 instances_.reserve(tmp.size());
351 for (std::list<std::string>::iterator it = tmp.begin(); it != tmp.end(); ++it) 360 for (std::list<std::string>::iterator it = tmp.begin(); it != tmp.end(); ++it)
352 { 361 {
353 instances_.push_back(*it); 362 instances_.push_back(*it);
354 } 363 }
355 } 364 }
356 failedUIDs_ = NULL; 365
366 failedUIDs_.clear();
357 getCancelled_ = OFFalse; 367 getCancelled_ = OFFalse;
358 368
359 nRemaining_ = GetSubOperationCount(); 369 nRemaining_ = GetSubOperationCount();
360 nCompleted_ = 0; 370 nCompleted_ = 0;
361 nFailed_ = 0; 371 nFailed_ = 0;
362 warningCount_ = 0; 372 warningCount_ = 0;
363 373
364 return retVal; 374 return retVal;
365
366
367 } 375 }
368 }; 376 };