Mercurial > hg > orthanc
diff Plugins/Engine/OrthancPlugins.cpp @ 1995:f0acfa753973
New callback to handle non-worklists C-Find requests: OrthancPluginRegisterCFindCallback()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 24 May 2016 17:45:56 +0200 |
parents | ce90d109bb64 |
children | 364cc624eb65 |
line wrap: on
line diff
--- a/Plugins/Engine/OrthancPlugins.cpp Tue May 17 15:45:49 2016 +0200 +++ b/Plugins/Engine/OrthancPlugins.cpp Tue May 24 17:45:56 2016 +0200 @@ -39,6 +39,7 @@ #include "../../Core/ChunkedBuffer.h" +#include "../../Core/DicomFormat/DicomArray.h" #include "../../Core/HttpServer/HttpToolbox.h" #include "../../Core/Logging.h" #include "../../Core/OrthancException.h" @@ -107,6 +108,27 @@ } + static char* CopyString(const std::string& str) + { + char *result = reinterpret_cast<char*>(malloc(str.size() + 1)); + if (result == NULL) + { + throw OrthancException(ErrorCode_NotEnoughMemory); + } + + if (str.size() == 0) + { + result[0] = '\0'; + } + else + { + memcpy(result, &str[0], str.size() + 1); + } + + return result; + } + + namespace { class PluginStorageArea : public IStorageArea @@ -291,6 +313,7 @@ RestCallbacks restCallbacks_; OnStoredCallbacks onStoredCallbacks_; OnChangeCallbacks onChangeCallbacks_; + OrthancPluginFindCallback findCallback_; OrthancPluginWorklistCallback worklistCallback_; OrthancPluginDecodeImageCallback decodeImageCallback_; IncomingHttpRequestFilters incomingHttpRequestFilters_; @@ -298,6 +321,7 @@ boost::recursive_mutex restCallbackMutex_; boost::recursive_mutex storedCallbackMutex_; boost::recursive_mutex changeCallbackMutex_; + boost::mutex findCallbackMutex_; boost::mutex worklistCallbackMutex_; boost::mutex decodeImageCallbackMutex_; boost::recursive_mutex invokeServiceMutex_; @@ -309,6 +333,7 @@ PImpl() : context_(NULL), + findCallback_(NULL), worklistCallback_(NULL), decodeImageCallback_(NULL), argc_(1), @@ -345,12 +370,13 @@ const std::string& calledAet) { bool caseSensitivePN = Configuration::GetGlobalBoolParameter("CaseSensitivePN", false); - matcher_.reset(new HierarchicalMatcher(query, caseSensitivePN)); - currentQuery_ = &query; { boost::mutex::scoped_lock lock(that_.pimpl_->worklistCallbackMutex_); + matcher_.reset(new HierarchicalMatcher(query, caseSensitivePN)); + currentQuery_ = &query; + if (that_.pimpl_->worklistCallback_) { OrthancPluginErrorCode error = that_.pimpl_->worklistCallback_ @@ -366,14 +392,18 @@ throw OrthancException(static_cast<ErrorCode>(error)); } } + + Reset(); } - - Reset(); } void GetDicomQuery(OrthancPluginMemoryBuffer& target) const { - assert(currentQuery_ != NULL); + if (currentQuery_ == NULL) + { + throw OrthancException(ErrorCode_Plugin); + } + std::string dicom; currentQuery_->SaveToMemoryBuffer(dicom); CopyToMemoryBuffer(target, dicom.c_str(), dicom.size()); @@ -382,7 +412,11 @@ bool IsMatch(const void* dicom, size_t size) const { - assert(matcher_.get() != NULL); + if (matcher_.get() == NULL) + { + throw OrthancException(ErrorCode_Plugin); + } + ParsedDicomFile f(dicom, size); return matcher_->Match(f); } @@ -391,7 +425,11 @@ const void* dicom, size_t size) const { - assert(matcher_.get() != NULL); + if (matcher_.get() == NULL) + { + throw OrthancException(ErrorCode_Plugin); + } + ParsedDicomFile f(dicom, size); std::auto_ptr<ParsedDicomFile> summary(matcher_->Extract(f)); reinterpret_cast<DicomFindAnswers*>(answers)->Add(*summary); @@ -399,25 +437,107 @@ }; - static char* CopyString(const std::string& str) + class OrthancPlugins::FindHandler : public IFindRequestHandler { - char *result = reinterpret_cast<char*>(malloc(str.size() + 1)); - if (result == NULL) + private: + OrthancPlugins& that_; + std::auto_ptr<DicomArray> currentQuery_; + + void Reset() { - throw OrthancException(ErrorCode_NotEnoughMemory); + currentQuery_.reset(NULL); + } + + public: + FindHandler(OrthancPlugins& that) : that_(that) + { + Reset(); } - if (str.size() == 0) + virtual void Handle(DicomFindAnswers& answers, + const DicomMap& input, + const std::list<DicomTag>& sequencesToReturn, + const std::string& remoteIp, + const std::string& remoteAet, + const std::string& calledAet) { - result[0] = '\0'; + DicomMap tmp; + tmp.Assign(input); + + for (std::list<DicomTag>::const_iterator it = sequencesToReturn.begin(); + it != sequencesToReturn.end(); ++it) + { + if (!input.HasTag(*it)) + { + tmp.SetValue(*it, ""); + } + } + + { + boost::mutex::scoped_lock lock(that_.pimpl_->findCallbackMutex_); + currentQuery_.reset(new DicomArray(tmp)); + + if (that_.pimpl_->findCallback_) + { + OrthancPluginErrorCode error = that_.pimpl_->findCallback_ + (reinterpret_cast<OrthancPluginFindAnswers*>(&answers), + reinterpret_cast<const OrthancPluginFindQuery*>(this), + remoteAet.c_str(), + calledAet.c_str()); + + if (error != OrthancPluginErrorCode_Success) + { + Reset(); + that_.GetErrorDictionary().LogError(error, true); + throw OrthancException(static_cast<ErrorCode>(error)); + } + } + + Reset(); + } } - else + + void Invoke(_OrthancPluginService service, + const _OrthancPluginFindOperation& operation) const { - memcpy(result, &str[0], str.size() + 1); + if (currentQuery_.get() == NULL) + { + throw OrthancException(ErrorCode_Plugin); + } + + switch (service) + { + case _OrthancPluginService_GetFindQuerySize: + *operation.resultUint32 = currentQuery_->GetSize(); + break; + + case _OrthancPluginService_GetFindQueryTag: + { + const DicomTag& tag = currentQuery_->GetElement(operation.index).GetTag(); + *operation.resultGroup = tag.GetGroup(); + *operation.resultElement = tag.GetElement(); + break; + } + + case _OrthancPluginService_GetFindQueryTagName: + { + const DicomTag& tag = currentQuery_->GetElement(operation.index).GetTag(); + *operation.resultString = CopyString(FromDcmtkBridge::GetName(tag)); + break; + } + + case _OrthancPluginService_GetFindQueryValue: + { + *operation.resultString = CopyString(currentQuery_->GetElement(operation.index).GetValue().GetContent()); + break; + } + + default: + throw OrthancException(ErrorCode_InternalError); + } } - - return result; - } + }; + OrthancPlugins::OrthancPlugins() @@ -741,6 +861,26 @@ } + void OrthancPlugins::RegisterFindCallback(const void* parameters) + { + const _OrthancPluginFindCallback& p = + *reinterpret_cast<const _OrthancPluginFindCallback*>(parameters); + + boost::mutex::scoped_lock lock(pimpl_->findCallbackMutex_); + + if (pimpl_->findCallback_ != NULL) + { + LOG(ERROR) << "Can only register one plugin to handle C-FIND requests"; + throw OrthancException(ErrorCode_Plugin); + } + else + { + LOG(INFO) << "Plugin has registered a callback to handle C-FIND requests"; + pimpl_->findCallback_ = p.callback; + } + } + + void OrthancPlugins::RegisterDecodeImageCallback(const void* parameters) { const _OrthancPluginDecodeImageCallback& p = @@ -1838,6 +1978,10 @@ RegisterWorklistCallback(parameters); return true; + case _OrthancPluginService_RegisterFindCallback: + RegisterFindCallback(parameters); + return true; + case _OrthancPluginService_RegisterDecodeImageCallback: RegisterDecodeImageCallback(parameters); return true; @@ -2314,6 +2458,33 @@ return true; } + case _OrthancPluginService_FindAddAnswer: + { + const _OrthancPluginFindOperation& p = + *reinterpret_cast<const _OrthancPluginFindOperation*>(parameters); + reinterpret_cast<DicomFindAnswers*>(p.answers)->Add(p.dicom, p.size); + return true; + } + + case _OrthancPluginService_FindMarkIncomplete: + { + const _OrthancPluginFindOperation& p = + *reinterpret_cast<const _OrthancPluginFindOperation*>(parameters); + reinterpret_cast<DicomFindAnswers*>(p.answers)->SetComplete(false); + return true; + } + + case _OrthancPluginService_GetFindQuerySize: + case _OrthancPluginService_GetFindQueryTag: + case _OrthancPluginService_GetFindQueryTagName: + case _OrthancPluginService_GetFindQueryValue: + { + const _OrthancPluginFindOperation& p = + *reinterpret_cast<const _OrthancPluginFindOperation*>(parameters); + reinterpret_cast<const FindHandler*>(p.query)->Invoke(service, p); + return true; + } + case _OrthancPluginService_CreateImage: case _OrthancPluginService_CreateImageAccessor: case _OrthancPluginService_DecodeDicomImage: @@ -2475,6 +2646,26 @@ } + IFindRequestHandler* OrthancPlugins::ConstructFindRequestHandler() + { + if (HasFindHandler()) + { + return new FindHandler(*this); + } + else + { + return NULL; + } + } + + + bool OrthancPlugins::HasFindHandler() + { + boost::mutex::scoped_lock lock(pimpl_->findCallbackMutex_); + return pimpl_->findCallback_ != NULL; + } + + bool OrthancPlugins::HasCustomImageDecoder() { boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_);