fw4spl
SeriesRetriever.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwPacsIO/SeriesRetriever.hpp"
8 
9 #include "fwPacsIO/exceptions/RequestFailure.hpp"
10 
11 #include <fwDcmtkTools/Dictionary.hpp>
12 
13 #include <fwRuntime/operations.hpp>
14 
15 #include <fwThread/Worker.hpp>
16 
17 #include <fwTools/System.hpp>
18 
19 #include <boost/filesystem/operations.hpp>
20 
21 #include <dcmtk/config/osconfig.h>
22 #include <dcmtk/dcmnet/diutil.h>
23 
24 namespace fwPacsIO
25 {
26 
27 const ::fwCom::Slots::SlotKeyType SeriesRetriever::s_PROGRESS_CALLBACK_SLOT = "CMoveProgressCallback";
28 
29 // ----------------------------------------------------------------------------
30 
32  m_path(""),
33  m_progressCallback(ProgressCallbackSlotType::sptr())
34 {
35 }
36 
37 // ----------------------------------------------------------------------------
38 
40 {
41 }
42 
43 // ----------------------------------------------------------------------------
44 
45 void SeriesRetriever::initialize(const std::string& applicationTitle,
46  unsigned short applicationport, int timeout,
47  ProgressCallbackSlotType::sptr progressCallback)
48 {
49  //Callback
50  m_progressCallback = progressCallback;
51 
52  //Creating folder
54  if (!::boost::filesystem::exists(m_path))
55  {
56  ::boost::filesystem::create_directories(m_path);
57  }
58 
59  // Load dictionary
61 
62  //Configure network connection
63  this->setAETitle(applicationTitle.c_str());
64  this->setPort(applicationport);
65 
66  // Load configuration
67  ::boost::filesystem::path cfgPath =
68  ::fwRuntime::getLibraryResourceFilePath("fwPacsIO-" FWPACSIO_VER "/storescp.cfg");
69  SLM_ASSERT("storescp.cfg not found !", ::boost::filesystem::exists(cfgPath));
70  this->loadAssociationCfgFile(cfgPath.string().c_str());
71  this->setAndCheckAssociationProfile("Default");
72 
73  // Set non blocking states & timeout so we don't end up in an infinite loop
74  this->setConnectionTimeout(timeout);
75  this->setConnectionBlockingMode(DUL_NOBLOCK);
76 }
77 
78 // ----------------------------------------------------------------------------
79 
81 {
82  // Reset instance count
83  m_instanceIndex = 0;
84 
85  // Start listening
86  return this->listen().good();
87 }
88 
89 // ----------------------------------------------------------------------------
90 
91 OFCondition SeriesRetriever::handleIncomingCommand(T_DIMSE_Message* incomingMsg,
92  const DcmPresentationContextInfo& presContextInfo)
93 {
94  OFCondition cond;
95 
96  // Process C-STORE request
97  if( incomingMsg->CommandField == DIMSE_C_STORE_RQ )
98  {
99  cond = handleSTORERequest( incomingMsg, presContextInfo.presentationContextID );
100  }
101  // Process other requests
102  else
103  {
104  cond = DcmSCP::handleIncomingCommand(incomingMsg, presContextInfo);
105  }
106 
107  return cond;
108 }
109 
110 // ----------------------------------------------------------------------------
111 
112 OFCondition SeriesRetriever::handleSTORERequest(T_DIMSE_Message* incomingMsg,
113  T_ASC_PresentationContextID presID)
114 {
115  OFCondition cond;
116 
117  // Dump incoming message
118  SLM_TRACE("Received C-STORE Request");
119  OFString tempStr;
120  OSLM_TRACE(DIMSE_dumpMessage(tempStr, incomingMsg->msg.CStoreRQ, DIMSE_INCOMING, NULL, presID));
121 
122  // Get Dataset
123  DcmDataset* dataset = new DcmDataset();
124  if (this->receiveDIMSEDataset(&presID, &dataset).good())
125  {
126  if (dataset != NULL)
127  {
128 
129  //Find the series UID
130  OFString seriesID;
131  if(dataset->findAndGetOFStringArray(DCM_SeriesInstanceUID, seriesID).good())
132  {
133  SLM_TRACE("Series Instance UID: " + std::string(seriesID.c_str()));
134  }
135 
136  //Find the instance UID
137  OFString iname;
138  if (dataset->findAndGetOFStringArray(DCM_SOPInstanceUID, iname).good())
139  {
140  SLM_TRACE("SOP Instance UID: " + std::string(iname.c_str()));
141  }
142 
143  //Create Folder
144  ::boost::filesystem::path seriesPath = ::boost::filesystem::path(m_path.string() + seriesID.c_str() + "/");
145  if (!::boost::filesystem::exists(seriesPath))
146  {
147  ::boost::filesystem::create_directories(seriesPath);
148  }
149 
150  //Save the file in the specified folder
151  std::string filePath = seriesPath.string() + iname.c_str();
152  dataset->saveFile(filePath.c_str());
153 
154  // Send a store response
155  T_DIMSE_C_StoreRSP rsp;
156  rsp.DimseStatus = STATUS_Success;
157  cond = this->sendSTOREResponse(presID, incomingMsg->msg.CStoreRQ, rsp.DimseStatus);
158 
159  // Dump outgoing message
160  SLM_TRACE("Sending C-STORE Response");
161  OSLM_TRACE(DIMSE_dumpMessage(tempStr, rsp, DIMSE_OUTGOING, NULL, presID));
162 
163  if (cond.bad())
164  {
165  const std::string msg = "Cannot send C-STORE Response to the server.";
166  throw ::fwPacsIO::exceptions::RequestFailure(msg);
167  }
168  else
169  {
170  SLM_TRACE("C-STORE Response successfully sent.");
171  }
172 
173  // Notify callback
175  {
176  m_progressCallback->asyncRun(seriesID.c_str(), ++m_instanceIndex, filePath);
177  }
178 
179  }
180  }
181 
182  return cond;
183 
184 }
185 
186 } //namespace fwPacsIO
187 
virtual OFCondition handleSTORERequest(T_DIMSE_Message *incomingMsg, T_ASC_PresentationContextID presID)
Handle C-STORE Request.
static FWDCMTKTOOLS_API void loadDictionary()
Load the DICOM dictionary.
Definition: Dictionary.cpp:25
FWPACSIO_API void initialize(const std::string &applicationTitle, unsigned short applicationport, int timeout=3, ProgressCallbackSlotType::sptr progressCallback=ProgressCallbackSlotType::sptr())
Initialize the connection.
FWPACSIO_API ~SeriesRetriever()
Destructor.
fwPacsIO contains classes used to communicate with a PACS.
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
virtual OFCondition handleIncomingCommand(T_DIMSE_Message *incomingMsg, const DcmPresentationContextInfo &presContextInfo) override
Handle Incoming Command (Override)
FWPACSIO_API bool start()
Start the server.
static FWTOOLS_APIconst::boost::filesystem::path getTemporaryFolder(const std::string &subFolderPrefix="") noexcept
Returns a unique per-process temporary folder. The top level temporary folder will be automatically d...
Definition: System.cpp:148
FWPACSIO_API SeriesRetriever()
Constructor.
#define SLM_TRACE(message)
Definition: spyLog.hpp:228
ProgressCallbackSlotType::sptr m_progressCallback
Progress callback slot.
unsigned int m_instanceIndex
Dowloaded instance index.
::boost::filesystem::path m_path
Path where the files must be saved.