Mercurial > hg > orthanc-stone
comparison Framework/Oracle/WebAssemblyOracle.cpp @ 975:e75fd08d6c75 toa2019083101
Cleaning in ICallable + changed fingerprint to plain char array to allow for
dead object examination + additional check in FetchContext callback to avoid
the unexplained rogue callbacks I have seen + protection in LoaderStateMachine::HandleSuccessMessage
in case things go wrong anyway
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Sat, 31 Aug 2019 13:45:04 +0200 |
parents | 38409549db43 |
children | 262a0244e9b2 |
comparison
equal
deleted
inserted
replaced
974:e4b028c1ede1 | 975:e75fd08d6c75 |
---|---|
97 class WebAssemblyOracle::FetchContext : public boost::noncopyable | 97 class WebAssemblyOracle::FetchContext : public boost::noncopyable |
98 { | 98 { |
99 private: | 99 private: |
100 Emitter emitter_; | 100 Emitter emitter_; |
101 const IObserver& receiver_; | 101 const IObserver& receiver_; |
102 std::string receiverFingerprint_; | |
103 std::auto_ptr<IOracleCommand> command_; | 102 std::auto_ptr<IOracleCommand> command_; |
104 std::string expectedContentType_; | 103 std::string expectedContentType_; |
105 | 104 |
106 public: | 105 public: |
107 FetchContext(WebAssemblyOracle& oracle, | 106 FetchContext(WebAssemblyOracle& oracle, |
108 const IObserver& receiver, | 107 const IObserver& receiver, |
109 IOracleCommand* command, | 108 IOracleCommand* command, |
110 const std::string& expectedContentType) : | 109 const std::string& expectedContentType) : |
111 emitter_(oracle), | 110 emitter_(oracle), |
112 receiver_(receiver), | 111 receiver_(receiver), |
113 receiverFingerprint_(receiver.GetFingerprint()), | |
114 command_(command), | 112 command_(command), |
115 expectedContentType_(expectedContentType) | 113 expectedContentType_(expectedContentType) |
116 { | 114 { |
117 if (command == NULL) | 115 if (command == NULL) |
118 { | 116 { |
119 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | 117 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); |
120 } | 118 } |
121 } | |
122 | |
123 bool IsFingerprintOK() const | |
124 { | |
125 bool ok = receiverFingerprint_ == receiver_.GetFingerprint(); | |
126 if (!ok) | |
127 { | |
128 LOG(TRACE) << "IsFingerprintOK returned false. receiverFingerprint_ = " << receiverFingerprint_ << " | receiver_(" << std::hex << (&receiver_) << std::dec << ").GetFingerprint() = " << receiver_.GetFingerprint(); | |
129 } | |
130 return ok; | |
131 } | 119 } |
132 | 120 |
133 const std::string& GetExpectedContentType() const | 121 const std::string& GetExpectedContentType() const |
134 { | 122 { |
135 return expectedContentType_; | 123 return expectedContentType_; |
205 * Firstly, make a local copy of the fetched information, and | 193 * Firstly, make a local copy of the fetched information, and |
206 * free data associated with the fetch. | 194 * free data associated with the fetch. |
207 **/ | 195 **/ |
208 | 196 |
209 std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData)); | 197 std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData)); |
198 | |
199 // an UUID is 36 chars : 32 hex chars + 4 hyphens: char #0 --> char #35 | |
200 // char #36 is \0. | |
201 | |
202 // TODO: remove this line because we are NOT allowed to call methods on GetReceiver that is maybe a dangling ref | |
203 if (context->GetReceiver().DoesFingerprintLookGood()) { | |
204 LOG(TRACE) << "SuccessCallback for object at address (" << std::hex << &(context->GetReceiver()) << std::dec << " with current fingerprint = " << context->GetReceiver().GetFingerprint(); | |
205 } | |
206 else { | |
207 LOG(TRACE) << "SuccessCallback for object at address (" << std::hex << &(context->GetReceiver()) << std::dec << " with current fingerprint is XXXXX -- NOT A VALID FINGERPRINT! OBJECT IS READ ! CALLBACK WILL NOT BE CALLED!"; | |
208 } | |
209 | |
210 | 210 |
211 if (fetch->userData == NULL) | 211 if (fetch->userData == NULL) |
212 { | 212 { |
213 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!"; | 213 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!"; |
214 } | 214 } |
241 if (context->GetCommand().GetType() == IOracleCommand::Type_OrthancRestApi) { | 241 if (context->GetCommand().GetType() == IOracleCommand::Type_OrthancRestApi) { |
242 //if (logbgo115) | 242 //if (logbgo115) |
243 DumpCommand(fetch, answer); | 243 DumpCommand(fetch, answer); |
244 } | 244 } |
245 #endif | 245 #endif |
246 LOG(TRACE) << "About to call emscripten_fetch_close"; | |
246 emscripten_fetch_close(fetch); | 247 emscripten_fetch_close(fetch); |
248 LOG(TRACE) << "Successfully called emscripten_fetch_close"; | |
247 | 249 |
248 /** | 250 /** |
249 * Secondly, use the retrieved data. | 251 * Secondly, use the retrieved data. |
250 * We only use the receiver if its fingerprint matches the one stored | 252 * IMPORTANT NOTE: the receiver might be dead. This is prevented |
251 * at command creation. | 253 * by the object responsible for zombie check, later on. |
252 **/ | 254 **/ |
253 if (!context->IsFingerprintOK()) | 255 try |
254 { | 256 { |
255 LOG(WARNING) << "FetchContext::SuccessCallback -- the initial request initiator has been destroyed. Response will be discarded."; | 257 if (context.get() == NULL) |
256 } | |
257 else | |
258 { | |
259 try | |
260 { | 258 { |
261 if (context.get() == NULL) | 259 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback: (context.get() == NULL)"; |
262 { | 260 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); |
263 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | 261 } |
264 } | 262 else |
265 else | 263 { |
266 { | 264 if (context->GetReceiver().DoesFingerprintLookGood()) { |
267 switch (context->GetCommand().GetType()) | 265 switch (context->GetCommand().GetType()) |
268 { | 266 { |
269 case IOracleCommand::Type_OrthancRestApi: | 267 case IOracleCommand::Type_OrthancRestApi: |
270 { | 268 { |
271 OrthancRestApiCommand::SuccessMessage message | 269 OrthancRestApiCommand::SuccessMessage message |
292 LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: " | 290 LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: " |
293 << context->GetCommand().GetType(); | 291 << context->GetCommand().GetType(); |
294 } | 292 } |
295 } | 293 } |
296 } | 294 } |
297 catch (Orthanc::OrthancException& e) | 295 } |
298 { | 296 catch (Orthanc::OrthancException& e) |
299 LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What(); | 297 { |
300 } | 298 LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What(); |
301 } | 299 } |
302 } | 300 } |
303 | 301 |
304 static void FailureCallback(emscripten_fetch_t *fetch) | 302 static void FailureCallback(emscripten_fetch_t *fetch) |
305 { | 303 { |