Mercurial > hg > orthanc
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 }; |