Mercurial > hg > orthanc
annotate OrthancServer/DicomProtocol/DicomServer.cpp @ 111:0fc3b69c0357
preparing for release
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 04 Oct 2012 12:45:24 +0200 |
parents | 7593b57dc1bf |
children | 2d96cb181f45 |
rev | line source |
---|---|
0 | 1 /** |
62 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
0 | 3 * Copyright (C) 2012 Medical Physics Department, CHU of Liege, |
4 * Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 **/ | |
19 | |
20 | |
21 #include "DicomServer.h" | |
22 | |
62 | 23 #include "../../Core/OrthancException.h" |
0 | 24 #include "../../Core/Toolbox.h" |
25 #include "../Internals/CommandDispatcher.h" | |
26 | |
27 #include <boost/thread.hpp> | |
28 #include <dcmtk/dcmdata/dcdict.h> | |
102
7593b57dc1bf
switch to google log
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
101
diff
changeset
|
29 #include <glog/logging.h> |
0 | 30 |
31 | |
62 | 32 namespace Orthanc |
0 | 33 { |
34 struct DicomServer::PImpl | |
35 { | |
36 boost::thread thread_; | |
37 | |
38 //std::set< | |
39 }; | |
40 | |
41 | |
42 void DicomServer::ServerThread(DicomServer* server) | |
43 { | |
44 /* Disable "gethostbyaddr" (which results in memory leaks) and use raw IP addresses */ | |
45 dcmDisableGethostbyaddr.set(OFTrue); | |
46 | |
47 /* make sure data dictionary is loaded */ | |
48 if (!dcmDataDict.isDictionaryLoaded()) | |
49 { | |
102
7593b57dc1bf
switch to google log
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
101
diff
changeset
|
50 LOG(WARNING) << "no data dictionary loaded, check environment variable: " << DCM_DICT_ENVIRONMENT_VARIABLE; |
0 | 51 } |
52 | |
53 /* initialize network, i.e. create an instance of T_ASC_Network*. */ | |
54 T_ASC_Network *net; | |
55 OFCondition cond = ASC_initializeNetwork | |
56 (NET_ACCEPTOR, OFstatic_cast(int, server->port_), /*opt_acse_timeout*/ 30, &net); | |
57 if (cond.bad()) | |
58 { | |
102
7593b57dc1bf
switch to google log
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
101
diff
changeset
|
59 LOG(ERROR) << "cannot create network: " << cond.text(); |
62 | 60 throw OrthancException("Cannot create network"); |
0 | 61 } |
62 | |
102
7593b57dc1bf
switch to google log
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
101
diff
changeset
|
63 LOG(WARNING) << "DICOM server started"; |
0 | 64 |
65 server->started_ = true; | |
66 | |
67 while (server->continue_) | |
68 { | |
69 /* receive an association and acknowledge or reject it. If the association was */ | |
70 /* acknowledged, offer corresponding services and invoke one or more if required. */ | |
71 std::auto_ptr<Internals::CommandDispatcher> dispatcher(Internals::AcceptAssociation(*server, net)); | |
72 | |
73 if (dispatcher.get() != NULL) | |
74 { | |
75 if (server->isThreaded_) | |
76 { | |
77 server->bagOfDispatchers_.Add(dispatcher.release()); | |
78 } | |
79 else | |
80 { | |
81 IRunnableBySteps::RunUntilDone(*dispatcher); | |
82 } | |
83 } | |
84 } | |
85 | |
102
7593b57dc1bf
switch to google log
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
101
diff
changeset
|
86 LOG(WARNING) << "DICOM server stopping"; |
0 | 87 |
88 /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ | |
89 /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ | |
90 cond = ASC_dropNetwork(&net); | |
91 if (cond.bad()) | |
92 { | |
102
7593b57dc1bf
switch to google log
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
101
diff
changeset
|
93 LOG(ERROR) << "Error while dropping the network: " << cond.text(); |
0 | 94 } |
95 } | |
96 | |
97 | |
98 DicomServer::DicomServer() : pimpl_(new PImpl) | |
99 { | |
100 aet_ = "ANY-SCP"; | |
101 port_ = 104; | |
102 findRequestHandlerFactory_ = NULL; | |
103 moveRequestHandlerFactory_ = NULL; | |
104 storeRequestHandlerFactory_ = NULL; | |
105 applicationEntityFilter_ = NULL; | |
106 checkCalledAet_ = true; | |
107 clientTimeout_ = 30; | |
108 isThreaded_ = true; | |
109 } | |
110 | |
111 DicomServer::~DicomServer() | |
112 { | |
113 Stop(); | |
114 } | |
115 | |
2 | 116 void DicomServer::SetPortNumber(uint16_t port) |
0 | 117 { |
118 Stop(); | |
119 port_ = port; | |
120 } | |
121 | |
2 | 122 uint16_t DicomServer::GetPortNumber() const |
0 | 123 { |
124 return port_; | |
125 } | |
126 | |
127 void DicomServer::SetThreaded(bool isThreaded) | |
128 { | |
129 Stop(); | |
130 isThreaded_ = isThreaded; | |
131 } | |
132 | |
133 bool DicomServer::IsThreaded() const | |
134 { | |
135 return isThreaded_; | |
136 } | |
137 | |
138 void DicomServer::SetClientTimeout(uint32_t timeout) | |
139 { | |
140 Stop(); | |
141 clientTimeout_ = timeout; | |
142 } | |
143 | |
144 uint32_t DicomServer::GetClientTimeout() const | |
145 { | |
146 return clientTimeout_; | |
147 } | |
148 | |
149 | |
150 void DicomServer::SetCalledApplicationEntityTitleCheck(bool check) | |
151 { | |
152 Stop(); | |
153 checkCalledAet_ = check; | |
154 } | |
155 | |
156 bool DicomServer::HasCalledApplicationEntityTitleCheck() const | |
157 { | |
158 return checkCalledAet_; | |
159 } | |
160 | |
161 void DicomServer::SetApplicationEntityTitle(const std::string& aet) | |
162 { | |
163 if (aet.size() == 0) | |
164 { | |
62 | 165 throw OrthancException("Too short AET"); |
0 | 166 } |
167 | |
168 for (size_t i = 0; i < aet.size(); i++) | |
169 { | |
170 if (!isalnum(aet[i]) && aet[i] != '-') | |
171 { | |
62 | 172 throw OrthancException("Only alphanumeric characters are allowed in AET"); |
0 | 173 } |
174 } | |
175 | |
176 Stop(); | |
177 aet_ = aet; | |
178 } | |
179 | |
180 const std::string& DicomServer::GetApplicationEntityTitle() const | |
181 { | |
182 return aet_; | |
183 } | |
184 | |
185 void DicomServer::SetFindRequestHandlerFactory(IFindRequestHandlerFactory& factory) | |
186 { | |
187 Stop(); | |
188 findRequestHandlerFactory_ = &factory; | |
189 } | |
190 | |
191 bool DicomServer::HasFindRequestHandlerFactory() const | |
192 { | |
193 return (findRequestHandlerFactory_ != NULL); | |
194 } | |
195 | |
196 IFindRequestHandlerFactory& DicomServer::GetFindRequestHandlerFactory() const | |
197 { | |
198 if (HasFindRequestHandlerFactory()) | |
199 { | |
200 return *findRequestHandlerFactory_; | |
201 } | |
202 else | |
203 { | |
62 | 204 throw OrthancException("No C-FIND request handler factory"); |
0 | 205 } |
206 } | |
207 | |
208 void DicomServer::SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& factory) | |
209 { | |
210 Stop(); | |
211 moveRequestHandlerFactory_ = &factory; | |
212 } | |
213 | |
214 bool DicomServer::HasMoveRequestHandlerFactory() const | |
215 { | |
216 return (moveRequestHandlerFactory_ != NULL); | |
217 } | |
218 | |
219 IMoveRequestHandlerFactory& DicomServer::GetMoveRequestHandlerFactory() const | |
220 { | |
221 if (HasMoveRequestHandlerFactory()) | |
222 { | |
223 return *moveRequestHandlerFactory_; | |
224 } | |
225 else | |
226 { | |
62 | 227 throw OrthancException("No C-MOVE request handler factory"); |
0 | 228 } |
229 } | |
230 | |
231 void DicomServer::SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& factory) | |
232 { | |
233 Stop(); | |
234 storeRequestHandlerFactory_ = &factory; | |
235 } | |
236 | |
237 bool DicomServer::HasStoreRequestHandlerFactory() const | |
238 { | |
239 return (storeRequestHandlerFactory_ != NULL); | |
240 } | |
241 | |
242 IStoreRequestHandlerFactory& DicomServer::GetStoreRequestHandlerFactory() const | |
243 { | |
244 if (HasStoreRequestHandlerFactory()) | |
245 { | |
246 return *storeRequestHandlerFactory_; | |
247 } | |
248 else | |
249 { | |
62 | 250 throw OrthancException("No C-STORE request handler factory"); |
0 | 251 } |
252 } | |
253 | |
254 void DicomServer::SetApplicationEntityFilter(IApplicationEntityFilter& factory) | |
255 { | |
256 Stop(); | |
257 applicationEntityFilter_ = &factory; | |
258 } | |
259 | |
260 bool DicomServer::HasApplicationEntityFilter() const | |
261 { | |
262 return (applicationEntityFilter_ != NULL); | |
263 } | |
264 | |
265 IApplicationEntityFilter& DicomServer::GetApplicationEntityFilter() const | |
266 { | |
267 if (HasApplicationEntityFilter()) | |
268 { | |
269 return *applicationEntityFilter_; | |
270 } | |
271 else | |
272 { | |
62 | 273 throw OrthancException("No application entity filter"); |
0 | 274 } |
275 } | |
276 | |
277 void DicomServer::Start() | |
278 { | |
279 Stop(); | |
280 continue_ = true; | |
281 started_ = false; | |
282 pimpl_->thread_ = boost::thread(ServerThread, this); | |
283 | |
284 while (!started_) | |
285 { | |
286 Toolbox::USleep(50000); // Wait 50ms | |
287 } | |
288 } | |
289 | |
290 void DicomServer::Stop() | |
291 { | |
292 continue_ = false; | |
293 pimpl_->thread_.join(); | |
294 | |
295 bagOfDispatchers_.StopAll(); | |
296 } | |
297 } |