# HG changeset patch # User Sebastien Jodogne # Date 1447844414 -3600 # Node ID 164d789113829b6f794948d6593b04391f0a767f # Parent 2dbf25006f888768e5026e4d717f4f4be65f5189 primitives to handle dicom worklists diff -r 2dbf25006f88 -r 164d78911382 CMakeLists.txt --- a/CMakeLists.txt Wed Nov 18 09:56:34 2015 +0100 +++ b/CMakeLists.txt Wed Nov 18 12:00:14 2015 +0100 @@ -155,6 +155,7 @@ OrthancServer/DicomProtocol/DicomFindAnswers.cpp OrthancServer/DicomProtocol/DicomServer.cpp OrthancServer/DicomProtocol/DicomUserConnection.cpp + OrthancServer/DicomProtocol/DicomWorklistAnswers.cpp OrthancServer/DicomProtocol/RemoteModalityParameters.cpp OrthancServer/DicomProtocol/ReusableDicomUserConnection.cpp OrthancServer/ExportedResource.cpp diff -r 2dbf25006f88 -r 164d78911382 Core/Enumerations.cpp --- a/Core/Enumerations.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/Core/Enumerations.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -325,6 +325,9 @@ case ErrorCode_CannotOrderSlices: return "Unable to order the slices of the series"; + case ErrorCode_NoWorklistHandler: + return "No request handler factory for DICOM C-Find Modality SCP"; + default: if (error >= ErrorCode_START_PLUGINS) { diff -r 2dbf25006f88 -r 164d78911382 Core/Enumerations.h --- a/Core/Enumerations.h Wed Nov 18 09:56:34 2015 +0100 +++ b/Core/Enumerations.h Wed Nov 18 12:00:14 2015 +0100 @@ -138,6 +138,7 @@ ErrorCode_DatabaseNotInitialized = 2038 /*!< Plugin trying to call the database during its initialization */, ErrorCode_SslDisabled = 2039 /*!< Orthanc has been built without SSL support */, ErrorCode_CannotOrderSlices = 2040 /*!< Unable to order the slices of the series */, + ErrorCode_NoWorklistHandler = 2041 /*!< No request handler factory for DICOM C-Find Modality SCP */, ErrorCode_START_PLUGINS = 1000000 }; diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/DicomFindAnswers.h --- a/OrthancServer/DicomProtocol/DicomFindAnswers.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/DicomFindAnswers.h Wed Nov 18 12:00:14 2015 +0100 @@ -39,7 +39,7 @@ namespace Orthanc { - class DicomFindAnswers + class DicomFindAnswers : public boost::noncopyable { private: std::vector items_; diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/DicomServer.cpp --- a/OrthancServer/DicomProtocol/DicomServer.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/DicomServer.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -94,6 +94,7 @@ findRequestHandlerFactory_ = NULL; moveRequestHandlerFactory_ = NULL; storeRequestHandlerFactory_ = NULL; + worklistRequestHandlerFactory_ = NULL; applicationEntityFilter_ = NULL; checkCalledAet_ = true; clientTimeout_ = 30; @@ -245,6 +246,29 @@ } } + void DicomServer::SetWorklistRequestHandlerFactory(IWorklistRequestHandlerFactory& factory) + { + Stop(); + worklistRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasWorklistRequestHandlerFactory() const + { + return (worklistRequestHandlerFactory_ != NULL); + } + + IWorklistRequestHandlerFactory& DicomServer::GetWorklistRequestHandlerFactory() const + { + if (HasWorklistRequestHandlerFactory()) + { + return *worklistRequestHandlerFactory_; + } + else + { + throw OrthancException(ErrorCode_NoWorklistHandler); + } + } + void DicomServer::SetApplicationEntityFilter(IApplicationEntityFilter& factory) { Stop(); diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/DicomServer.h --- a/OrthancServer/DicomProtocol/DicomServer.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/DicomServer.h Wed Nov 18 12:00:14 2015 +0100 @@ -35,6 +35,7 @@ #include "IFindRequestHandlerFactory.h" #include "IMoveRequestHandlerFactory.h" #include "IStoreRequestHandlerFactory.h" +#include "IWorklistRequestHandlerFactory.h" #include "IApplicationEntityFilter.h" #include @@ -58,6 +59,7 @@ IFindRequestHandlerFactory* findRequestHandlerFactory_; IMoveRequestHandlerFactory* moveRequestHandlerFactory_; IStoreRequestHandlerFactory* storeRequestHandlerFactory_; + IWorklistRequestHandlerFactory* worklistRequestHandlerFactory_; IApplicationEntityFilter* applicationEntityFilter_; static void ServerThread(DicomServer* server); @@ -91,6 +93,10 @@ bool HasStoreRequestHandlerFactory() const; IStoreRequestHandlerFactory& GetStoreRequestHandlerFactory() const; + void SetWorklistRequestHandlerFactory(IWorklistRequestHandlerFactory& handler); + bool HasWorklistRequestHandlerFactory() const; + IWorklistRequestHandlerFactory& GetWorklistRequestHandlerFactory() const; + void SetApplicationEntityFilter(IApplicationEntityFilter& handler); bool HasApplicationEntityFilter() const; IApplicationEntityFilter& GetApplicationEntityFilter() const; diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/DicomWorklistAnswers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomWorklistAnswers.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -0,0 +1,71 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#include "../PrecompiledHeadersServer.h" +#include "DicomWorklistAnswers.h" + +#include "../../Core/OrthancException.h" + +namespace Orthanc +{ + void DicomWorklistAnswers::Clear() + { + for (size_t i = 0; i < items_.size(); i++) + { + delete items_[i]; + } + + items_.clear(); + } + + void DicomWorklistAnswers::Add(ParsedDicomFile& dicom) + { + items_.push_back(dicom.Clone()); + } + + void DicomWorklistAnswers::Add(const std::string& dicom) + { + items_.push_back(new ParsedDicomFile(dicom)); + } + + const ParsedDicomFile& DicomWorklistAnswers::GetAnswer(size_t index) const + { + if (index < items_.size()) + { + return *items_[index]; + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } +} diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/DicomWorklistAnswers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/DicomWorklistAnswers.h Wed Nov 18 12:00:14 2015 +0100 @@ -0,0 +1,63 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../ParsedDicomFile.h" + +namespace Orthanc +{ + class DicomWorklistAnswers : public boost::noncopyable + { + private: + std::vector items_; + + public: + ~DicomWorklistAnswers() + { + Clear(); + } + + void Clear(); + + void Add(ParsedDicomFile& dicom); + + void Add(const std::string& dicom); + + size_t GetSize() const + { + return items_.size(); + } + + const ParsedDicomFile& GetAnswer(size_t index) const; + }; +} diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IApplicationEntityFilter.h --- a/OrthancServer/DicomProtocol/IApplicationEntityFilter.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IApplicationEntityFilter.h Wed Nov 18 12:00:14 2015 +0100 @@ -38,7 +38,7 @@ namespace Orthanc { - class IApplicationEntityFilter + class IApplicationEntityFilter : public boost::noncopyable { public: virtual ~IApplicationEntityFilter() diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IFindRequestHandler.h --- a/OrthancServer/DicomProtocol/IFindRequestHandler.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IFindRequestHandler.h Wed Nov 18 12:00:14 2015 +0100 @@ -34,13 +34,9 @@ #include "DicomFindAnswers.h" -#include -#include - - namespace Orthanc { - class IFindRequestHandler + class IFindRequestHandler : public boost::noncopyable { public: virtual ~IFindRequestHandler() diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IFindRequestHandlerFactory.h --- a/OrthancServer/DicomProtocol/IFindRequestHandlerFactory.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IFindRequestHandlerFactory.h Wed Nov 18 12:00:14 2015 +0100 @@ -36,7 +36,7 @@ namespace Orthanc { - class IFindRequestHandlerFactory + class IFindRequestHandlerFactory : public boost::noncopyable { public: virtual ~IFindRequestHandlerFactory() diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IMoveRequestHandler.h --- a/OrthancServer/DicomProtocol/IMoveRequestHandler.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IMoveRequestHandler.h Wed Nov 18 12:00:14 2015 +0100 @@ -40,7 +40,7 @@ namespace Orthanc { - class IMoveRequestIterator + class IMoveRequestIterator : public boost::noncopyable { public: enum Status diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IMoveRequestHandlerFactory.h --- a/OrthancServer/DicomProtocol/IMoveRequestHandlerFactory.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IMoveRequestHandlerFactory.h Wed Nov 18 12:00:14 2015 +0100 @@ -36,7 +36,7 @@ namespace Orthanc { - class IMoveRequestHandlerFactory + class IMoveRequestHandlerFactory : public boost::noncopyable { public: virtual ~IMoveRequestHandlerFactory() diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IStoreRequestHandler.h --- a/OrthancServer/DicomProtocol/IStoreRequestHandler.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IStoreRequestHandler.h Wed Nov 18 12:00:14 2015 +0100 @@ -40,7 +40,7 @@ namespace Orthanc { - class IStoreRequestHandler + class IStoreRequestHandler : public boost::noncopyable { public: virtual ~IStoreRequestHandler() diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IStoreRequestHandlerFactory.h --- a/OrthancServer/DicomProtocol/IStoreRequestHandlerFactory.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/DicomProtocol/IStoreRequestHandlerFactory.h Wed Nov 18 12:00:14 2015 +0100 @@ -36,7 +36,7 @@ namespace Orthanc { - class IStoreRequestHandlerFactory + class IStoreRequestHandlerFactory : public boost::noncopyable { public: virtual ~IStoreRequestHandlerFactory() diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IWorklistRequestHandler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IWorklistRequestHandler.h Wed Nov 18 12:00:14 2015 +0100 @@ -0,0 +1,57 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "DicomWorklistAnswers.h" + +namespace Orthanc +{ + class IWorklistRequestHandler : public boost::noncopyable + { + public: + virtual ~IWorklistRequestHandler() + { + } + + /** + * Can throw exceptions. Returns "false" iff too many results have + * to be returned. In such a case, a "Matching terminated due to + * Cancel request" DIMSE code would be returned. + * https://www.dabsoft.ch/dicom/4/V.4.1/ + **/ + virtual bool Handle(DicomWorklistAnswers& answers, + const ParsedDicomFile& query, + const std::string& remoteIp, + const std::string& remoteAet) = 0; + }; +} diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/DicomProtocol/IWorklistRequestHandlerFactory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancServer/DicomProtocol/IWorklistRequestHandlerFactory.h Wed Nov 18 12:00:14 2015 +0100 @@ -0,0 +1,48 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * In addition, as a special exception, the copyright holders of this + * program give permission to link the code of its release with the + * OpenSSL project's "OpenSSL" library (or with modified versions of it + * that use the same license as the "OpenSSL" library), and distribute + * the linked executables. You must obey the GNU General Public License + * in all respects for all of the code used other than "OpenSSL". If you + * modify file(s) with this exception, you may extend this exception to + * your version of the file(s), but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files + * in the program, then also delete it here. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "IWorklistRequestHandler.h" + +namespace Orthanc +{ + class IWorklistRequestHandlerFactory : public boost::noncopyable + { + public: + virtual ~IWorklistRequestHandlerFactory() + { + } + + virtual IWorklistRequestHandler* ConstructWorklistRequestHandler() = 0; + }; +} diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/Internals/CommandDispatcher.cpp --- a/OrthancServer/Internals/CommandDispatcher.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/Internals/CommandDispatcher.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -430,6 +430,11 @@ knownAbstractSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); } + if (server.HasWorklistRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_FINDModalityWorklistInformationModel); + } + // For C-MOVE if (server.HasMoveRequestHandlerFactory()) { @@ -812,11 +817,23 @@ break; case DicomRequestType_Find: - if (server_.HasFindRequestHandlerFactory()) // Should always be true + if (server_.HasFindRequestHandlerFactory() || // Should always be true + server_.HasWorklistRequestHandlerFactory()) { - std::auto_ptr handler - (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler()); - cond = Internals::findScp(assoc_, &msg, presID, *handler, remoteIp_, remoteAet_); + std::auto_ptr findHandler; + if (server_.HasFindRequestHandlerFactory()) + { + findHandler.reset(server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler()); + } + + std::auto_ptr worklistHandler; + if (server_.HasWorklistRequestHandlerFactory()) + { + worklistHandler.reset(server_.GetWorklistRequestHandlerFactory().ConstructWorklistRequestHandler()); + } + + cond = Internals::findScp(assoc_, &msg, presID, findHandler.get(), + worklistHandler.get(), remoteIp_, remoteAet_); } break; diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/Internals/FindScp.cpp --- a/OrthancServer/Internals/FindScp.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/Internals/FindScp.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -95,8 +95,8 @@ { struct FindScpData { - IFindRequestHandler* handler_; - DicomMap input_; + IFindRequestHandler* findHandler_; + IWorklistRequestHandler* worklistHandler_; DicomFindAnswers answers_; DcmDataset* lastRequest_; const std::string* remoteIp_; @@ -120,20 +120,54 @@ bzero(response, sizeof(T_DIMSE_C_FindRSP)); *statusDetail = NULL; + std::string sopClassUid(request->AffectedSOPClassUID); + FindScpData& data = *reinterpret_cast(callbackData); if (data.lastRequest_ == NULL) { - FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); + bool ok = false; try { - data.noCroppingOfResults_ = data.handler_->Handle(data.answers_, data.input_, - *data.remoteIp_, *data.remoteAet_); + if (sopClassUid == UID_FINDModalityWorklistInformationModel) + { + if (data.worklistHandler_ != NULL) + { + // TODO + std::auto_ptr query(ParsedDicomFile::CreateFromDcmtkDataset(requestIdentifiers)); + DicomWorklistAnswers a; + data.worklistHandler_->Handle(a, *query, *data.remoteIp_, *data.remoteAet_); + ok = true; + } + else + { + LOG(ERROR) << "No worklist handler is installed, cannot handle this C-FIND request"; + } + } + else + { + if (data.findHandler_ != NULL) + { + DicomMap input; + FromDcmtkBridge::Convert(input, *requestIdentifiers); + data.noCroppingOfResults_ = data.findHandler_->Handle(data.answers_, input, + *data.remoteIp_, *data.remoteAet_); + ok = true; + } + else + { + LOG(ERROR) << "No C-Find handler is installed, cannot handle this request"; + } + } } catch (OrthancException& e) { // Internal error! LOG(ERROR) << "C-FIND request handler has failed: " << e.What(); + } + + if (!ok) + { response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; *responseIdentifiers = NULL; return; @@ -175,13 +209,15 @@ OFCondition Internals::findScp(T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID, - IFindRequestHandler& handler, + IFindRequestHandler* findHandler, + IWorklistRequestHandler* worklistHandler, const std::string& remoteIp, const std::string& remoteAet) { FindScpData data; data.lastRequest_ = NULL; - data.handler_ = &handler; + data.findHandler_ = findHandler; + data.worklistHandler_ = worklistHandler; data.remoteIp_ = &remoteIp; data.remoteAet_ = &remoteAet; data.noCroppingOfResults_ = true; diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/Internals/FindScp.h --- a/OrthancServer/Internals/FindScp.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/Internals/FindScp.h Wed Nov 18 12:00:14 2015 +0100 @@ -33,6 +33,7 @@ #pragma once #include "../DicomProtocol/IFindRequestHandler.h" +#include "../DicomProtocol/IWorklistRequestHandler.h" #include @@ -43,7 +44,8 @@ OFCondition findScp(T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID, - IFindRequestHandler& handler, + IFindRequestHandler* findHandler, // can be NULL + IWorklistRequestHandler* worklistHandler, // can be NULL const std::string& remoteIp, const std::string& remoteAet); } diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/Internals/MoveScp.cpp --- a/OrthancServer/Internals/MoveScp.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/Internals/MoveScp.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -98,7 +98,6 @@ { std::string target_; IMoveRequestHandler* handler_; - DicomMap input_; DcmDataset* lastRequest_; unsigned int subOperationCount_; unsigned int failureCount_; @@ -128,11 +127,12 @@ MoveScpData& data = *reinterpret_cast(callbackData); if (data.lastRequest_ == NULL) { - FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); + DicomMap input; + FromDcmtkBridge::Convert(input, *requestIdentifiers); try { - data.iterator_.reset(data.handler_->Handle(data.target_, data.input_, + data.iterator_.reset(data.handler_->Handle(data.target_, input, *data.remoteIp_, *data.remoteAet_)); if (data.iterator_.get() == NULL) diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/ParsedDicomFile.cpp --- a/OrthancServer/ParsedDicomFile.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/ParsedDicomFile.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -823,6 +823,12 @@ } + ParsedDicomFile::ParsedDicomFile(void* fileFormat) : pimpl_(new PImpl) + { + pimpl_->file_.reset(static_cast(fileFormat)); + } + + ParsedDicomFile::ParsedDicomFile(const char* content, size_t size) : pimpl_(new PImpl) { Setup(content, size); @@ -1222,4 +1228,15 @@ { FromDcmtkBridge::Convert(tags, *pimpl_->file_->getDataset()); } + + + ParsedDicomFile* ParsedDicomFile::CreateFromDcmtkDataset(void* dataset) + { + assert(dataset != NULL); + + DcmDataset *d = static_cast(dataset); + std::auto_ptr fileFormat(new DcmFileFormat(d)); + + return new ParsedDicomFile(fileFormat.release()); + } } diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/ParsedDicomFile.h --- a/OrthancServer/ParsedDicomFile.h Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/ParsedDicomFile.h Wed Nov 18 12:00:14 2015 +0100 @@ -58,6 +58,8 @@ const std::string& value, bool decodeBinaryTags); + ParsedDicomFile(void* fileFormat); // Create by embedding a DcmFileFormat (takes ownership) + public: ParsedDicomFile(); // Create a minimal DICOM instance @@ -150,6 +152,8 @@ bool ExtractPdf(std::string& pdf); void Convert(DicomMap& tags); + + static ParsedDicomFile* CreateFromDcmtkDataset(void* dataset); }; } diff -r 2dbf25006f88 -r 164d78911382 OrthancServer/main.cpp --- a/OrthancServer/main.cpp Wed Nov 18 09:56:34 2015 +0100 +++ b/OrthancServer/main.cpp Wed Nov 18 12:00:14 2015 +0100 @@ -89,10 +89,32 @@ }; +class OrthancWorklistRequestHandler : public IWorklistRequestHandler +{ +private: + ServerContext& server_; + +public: + OrthancWorklistRequestHandler(ServerContext& context) : + server_(context) + { + } + + virtual bool Handle(DicomWorklistAnswers& answers, + const ParsedDicomFile& query, + const std::string& remoteIp, + const std::string& remoteAet) + { + printf("Worklist\n"); + return true; + } +}; + class MyDicomServerFactory : public IStoreRequestHandlerFactory, - public IFindRequestHandlerFactory, + public IFindRequestHandlerFactory, + public IWorklistRequestHandlerFactory, public IMoveRequestHandlerFactory { private: @@ -143,6 +165,11 @@ return new OrthancMoveRequestHandler(context_); } + virtual IWorklistRequestHandler* ConstructWorklistRequestHandler() + { + return new OrthancWorklistRequestHandler(context_); + } + void Done() { } @@ -550,6 +577,7 @@ PrintErrorCode(ErrorCode_DatabaseNotInitialized, "Plugin trying to call the database during its initialization"); PrintErrorCode(ErrorCode_SslDisabled, "Orthanc has been built without SSL support"); PrintErrorCode(ErrorCode_CannotOrderSlices, "Unable to order the slices of the series"); + PrintErrorCode(ErrorCode_NoWorklistHandler, "No request handler factory for DICOM C-Find Modality SCP"); } std::cout << std::endl; @@ -704,6 +732,10 @@ dicomServer.SetStoreRequestHandlerFactory(serverFactory); dicomServer.SetMoveRequestHandlerFactory(serverFactory); dicomServer.SetFindRequestHandlerFactory(serverFactory); + + // TODO - Disable the following line if no worklist plugin is available + dicomServer.SetWorklistRequestHandlerFactory(serverFactory); + dicomServer.SetPortNumber(Configuration::GetGlobalIntegerParameter("DicomPort", 4242)); dicomServer.SetApplicationEntityTitle(Configuration::GetGlobalStringParameter("DicomAet", "ORTHANC")); dicomServer.SetApplicationEntityFilter(dicomFilter); diff -r 2dbf25006f88 -r 164d78911382 Plugins/Include/orthanc/OrthancCPlugin.h --- a/Plugins/Include/orthanc/OrthancCPlugin.h Wed Nov 18 09:56:34 2015 +0100 +++ b/Plugins/Include/orthanc/OrthancCPlugin.h Wed Nov 18 12:00:14 2015 +0100 @@ -271,6 +271,7 @@ OrthancPluginErrorCode_DatabaseNotInitialized = 2038 /*!< Plugin trying to call the database during its initialization */, OrthancPluginErrorCode_SslDisabled = 2039 /*!< Orthanc has been built without SSL support */, OrthancPluginErrorCode_CannotOrderSlices = 2040 /*!< Unable to order the slices of the series */, + OrthancPluginErrorCode_NoWorklistHandler = 2041 /*!< No request handler factory for DICOM C-Find Modality SCP */, _OrthancPluginErrorCode_INTERNAL = 0x7fffffff } OrthancPluginErrorCode; diff -r 2dbf25006f88 -r 164d78911382 Resources/ErrorCodes.json --- a/Resources/ErrorCodes.json Wed Nov 18 09:56:34 2015 +0100 +++ b/Resources/ErrorCodes.json Wed Nov 18 12:00:14 2015 +0100 @@ -513,5 +513,10 @@ "Code": 2040, "Name": "CannotOrderSlices", "Description": "Unable to order the slices of the series" + }, + { + "Code": 2041, + "Name": "NoWorklistHandler", + "Description": "No request handler factory for DICOM C-Find Modality SCP" } ]