Mercurial > hg > orthanc
annotate OrthancServer/DicomProtocol/DicomUserConnection.cpp @ 763:b5e6d2823115
dynamic negotiation of storage sop classes
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 29 Apr 2014 17:15:59 +0200 |
parents | b79eda29896d |
children | 0a2f8c707c78 |
rev | line source |
---|---|
0 | 1 /** |
62 | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
689 | 3 * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, |
0 | 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. | |
136 | 10 * |
11 * In addition, as a special exception, the copyright holders of this | |
12 * program give permission to link the code of its release with the | |
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 * that use the same license as the "OpenSSL" library), and distribute | |
15 * the linked executables. You must obey the GNU General Public License | |
16 * in all respects for all of the code used other than "OpenSSL". If you | |
17 * modify file(s) with this exception, you may extend this exception to | |
18 * your version of the file(s), but you are not obligated to do so. If | |
19 * you do not wish to do so, delete this exception statement from your | |
20 * version. If you delete this exception statement from all source files | |
21 * in the program, then also delete it here. | |
0 | 22 * |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 **/ | |
31 | |
32 | |
33 #include "DicomUserConnection.h" | |
34 | |
62 | 35 #include "../../Core/OrthancException.h" |
0 | 36 #include "../ToDcmtkBridge.h" |
37 #include "../FromDcmtkBridge.h" | |
38 | |
39 #include <dcmtk/dcmdata/dcistrmb.h> | |
40 #include <dcmtk/dcmdata/dcistrmf.h> | |
41 #include <dcmtk/dcmdata/dcfilefo.h> | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
42 #include <dcmtk/dcmdata/dcmetinf.h> |
0 | 43 #include <dcmtk/dcmnet/diutil.h> |
44 | |
45 #include <set> | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
46 #include <glog/logging.h> |
0 | 47 |
48 | |
49 | |
50 #ifdef _WIN32 | |
51 /** | |
52 * "The maximum length, in bytes, of the string returned in the buffer | |
53 * pointed to by the name parameter is dependent on the namespace provider, | |
54 * but this string must be 256 bytes or less. | |
55 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms738527(v=vs.85).aspx | |
56 **/ | |
57 #define HOST_NAME_MAX 256 | |
58 #endif | |
59 | |
60 | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
61 static const char* DEFAULT_PREFERRED_TRANSFER_SYNTAX = UID_LittleEndianImplicitTransferSyntax; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
62 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
63 /** |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
64 * "If we have more than 64 storage SOP classes, tools such as |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
65 * storescu will fail because they attempt to negotiate two |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
66 * presentation contexts for each SOP class, and there is a total |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
67 * limit of 128 contexts for one association." |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
68 **/ |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
69 static const unsigned int MAXIMUM_STORAGE_SOP_CLASSES = 64; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
70 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
71 |
62 | 72 namespace Orthanc |
0 | 73 { |
74 struct DicomUserConnection::PImpl | |
75 { | |
76 // Connection state | |
77 T_ASC_Network* net_; | |
78 T_ASC_Parameters* params_; | |
79 T_ASC_Association* assoc_; | |
80 | |
81 bool IsOpen() const | |
82 { | |
83 return assoc_ != NULL; | |
84 } | |
85 | |
86 void CheckIsOpen() const; | |
87 | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
88 void Store(DcmInputStream& is, DicomUserConnection& connection); |
0 | 89 }; |
90 | |
91 | |
92 static void Check(const OFCondition& cond) | |
93 { | |
94 if (cond.bad()) | |
95 { | |
62 | 96 throw OrthancException("DicomUserConnection: " + std::string(cond.text())); |
0 | 97 } |
98 } | |
99 | |
100 void DicomUserConnection::PImpl::CheckIsOpen() const | |
101 { | |
102 if (!IsOpen()) | |
103 { | |
62 | 104 throw OrthancException("DicomUserConnection: First open the connection"); |
0 | 105 } |
106 } | |
107 | |
108 | |
109 void DicomUserConnection::CheckIsOpen() const | |
110 { | |
111 pimpl_->CheckIsOpen(); | |
112 } | |
113 | |
114 | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
115 static void RegisterStorageSOPClass(T_ASC_Parameters* params, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
116 unsigned int& presentationContextId, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
117 const std::string& sopClass, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
118 const char* asPreferred[], |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
119 std::vector<const char*>& asFallback) |
0 | 120 { |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
121 Check(ASC_addPresentationContext(params, presentationContextId, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
122 sopClass.c_str(), asPreferred, 1)); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
123 presentationContextId += 2; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
124 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
125 if (asFallback.size() > 0) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
126 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
127 Check(ASC_addPresentationContext(params, presentationContextId, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
128 sopClass.c_str(), &asFallback[0], asFallback.size())); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
129 presentationContextId += 2; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
130 } |
0 | 131 } |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
132 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
133 |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
134 void DicomUserConnection::SetupPresentationContexts(const std::string& preferredTransferSyntax) |
0 | 135 { |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
136 // Flatten an array with the preferred transfer syntax |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
137 const char* asPreferred[1] = { preferredTransferSyntax.c_str() }; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
138 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
139 // Setup the fallback transfer syntaxes |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
140 std::set<std::string> fallbackSyntaxes; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
141 fallbackSyntaxes.insert(UID_LittleEndianExplicitTransferSyntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
142 fallbackSyntaxes.insert(UID_BigEndianExplicitTransferSyntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
143 fallbackSyntaxes.insert(UID_LittleEndianImplicitTransferSyntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
144 fallbackSyntaxes.erase(preferredTransferSyntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
145 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
146 // Flatten an array with the fallback transfer syntaxes |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
147 std::vector<const char*> asFallback; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
148 asFallback.reserve(fallbackSyntaxes.size()); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
149 for (std::set<std::string>::const_iterator |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
150 it = fallbackSyntaxes.begin(); it != fallbackSyntaxes.end(); ++it) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
151 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
152 asFallback.push_back(it->c_str()); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
153 } |
0 | 154 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
155 CheckStorageSOPClassesInvariant(); |
0 | 156 unsigned int presentationContextId = 1; |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
157 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
158 for (std::list<std::string>::const_iterator it = reservedStorageSOPClasses_.begin(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
159 it != reservedStorageSOPClasses_.end(); it++) |
0 | 160 { |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
161 RegisterStorageSOPClass(pimpl_->params_, presentationContextId, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
162 *it, asPreferred, asFallback); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
163 } |
0 | 164 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
165 for (std::set<std::string>::const_iterator it = storageSOPClasses_.begin(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
166 it != storageSOPClasses_.end(); it++) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
167 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
168 RegisterStorageSOPClass(pimpl_->params_, presentationContextId, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
169 *it, asPreferred, asFallback); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
170 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
171 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
172 for (std::set<std::string>::const_iterator it = defaultStorageSOPClasses_.begin(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
173 it != defaultStorageSOPClasses_.end(); it++) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
174 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
175 RegisterStorageSOPClass(pimpl_->params_, presentationContextId, |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
176 *it, asPreferred, asFallback); |
0 | 177 } |
178 } | |
179 | |
180 | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
181 static bool IsGenericTransferSyntax(const std::string& syntax) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
182 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
183 return (syntax == UID_LittleEndianExplicitTransferSyntax || |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
184 syntax == UID_BigEndianExplicitTransferSyntax || |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
185 syntax == UID_LittleEndianImplicitTransferSyntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
186 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
187 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
188 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
189 void DicomUserConnection::PImpl::Store(DcmInputStream& is, DicomUserConnection& connection) |
0 | 190 { |
191 CheckIsOpen(); | |
192 | |
193 DcmFileFormat dcmff; | |
194 Check(dcmff.read(is, EXS_Unknown, EGL_noChange, DCM_MaxReadLength)); | |
195 | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
196 // Determine the storage SOP class UID for this instance |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
197 static const DcmTagKey DCM_SOP_CLASS_UID(0x0008, 0x0016); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
198 OFString sopClassUid; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
199 if (dcmff.getDataset()->findAndGetOFString(DCM_SOP_CLASS_UID, sopClassUid).good()) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
200 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
201 connection.AddStorageSOPClass(sopClassUid.c_str()); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
202 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
203 |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
204 // Determine whether a new presentation context must be |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
205 // negotiated, depending on the transfer syntax of this instance |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
206 DcmXfer xfer(dcmff.getDataset()->getOriginalXfer()); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
207 const std::string syntax(xfer.getXferID()); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
208 bool isGeneric = IsGenericTransferSyntax(syntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
209 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
210 if (isGeneric ^ IsGenericTransferSyntax(connection.GetPreferredTransferSyntax())) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
211 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
212 // Making a generic-to-specific or specific-to-generic change of |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
213 // the transfer syntax. Renegotiate the connection. |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
214 LOG(INFO) << "Change in the transfer syntax: the C-Store associated must be renegotiated"; |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
215 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
216 if (isGeneric) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
217 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
218 connection.ResetPreferredTransferSyntax(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
219 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
220 else |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
221 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
222 connection.SetPreferredTransferSyntax(syntax); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
223 } |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
224 } |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
225 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
226 if (!connection.IsOpen()) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
227 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
228 LOG(INFO) << "Renegotiating a C-Store association due to a change in the parameters"; |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
229 connection.Open(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
230 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
231 |
0 | 232 // Figure out which SOP class and SOP instance is encapsulated in the file |
233 DIC_UI sopClass; | |
234 DIC_UI sopInstance; | |
235 if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance)) | |
236 { | |
62 | 237 throw OrthancException("DicomUserConnection: Unable to find the SOP class and instance"); |
0 | 238 } |
239 | |
240 // Figure out which of the accepted presentation contexts should be used | |
241 int presID = ASC_findAcceptedPresentationContextID(assoc_, sopClass); | |
242 if (presID == 0) | |
243 { | |
244 const char *modalityName = dcmSOPClassUIDToModality(sopClass); | |
245 if (!modalityName) modalityName = dcmFindNameOfUID(sopClass); | |
246 if (!modalityName) modalityName = "unknown SOP class"; | |
62 | 247 throw OrthancException("DicomUserConnection: No presentation context for modality " + |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
248 std::string(modalityName)); |
0 | 249 } |
250 | |
251 // Prepare the transmission of data | |
252 T_DIMSE_C_StoreRQ req; | |
253 memset(&req, 0, sizeof(req)); | |
254 req.MessageID = assoc_->nextMsgID++; | |
255 strcpy(req.AffectedSOPClassUID, sopClass); | |
256 strcpy(req.AffectedSOPInstanceUID, sopInstance); | |
257 req.DataSetType = DIMSE_DATASET_PRESENT; | |
258 req.Priority = DIMSE_PRIORITY_MEDIUM; | |
259 | |
260 // Finally conduct transmission of data | |
261 T_DIMSE_C_StoreRSP rsp; | |
262 DcmDataset* statusDetail = NULL; | |
263 Check(DIMSE_storeUser(assoc_, presID, &req, | |
264 NULL, dcmff.getDataset(), /*progressCallback*/ NULL, NULL, | |
265 /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, | |
266 &rsp, &statusDetail, NULL)); | |
267 | |
268 if (statusDetail != NULL) | |
269 { | |
270 delete statusDetail; | |
271 } | |
272 } | |
273 | |
274 | |
275 static void FindCallback( | |
276 /* in */ | |
277 void *callbackData, | |
278 T_DIMSE_C_FindRQ *request, /* original find request */ | |
279 int responseCount, | |
280 T_DIMSE_C_FindRSP *response, /* pending response received */ | |
281 DcmDataset *responseIdentifiers /* pending response identifiers */ | |
282 ) | |
283 { | |
657
5425bb6f1ea5
further cppcheck fixes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
656
diff
changeset
|
284 DicomFindAnswers& answers = *reinterpret_cast<DicomFindAnswers*>(callbackData); |
0 | 285 |
286 if (responseIdentifiers != NULL) | |
287 { | |
288 DicomMap m; | |
289 FromDcmtkBridge::Convert(m, *responseIdentifiers); | |
290 answers.Add(m); | |
291 } | |
292 } | |
293 | |
294 void DicomUserConnection::Find(DicomFindAnswers& result, | |
295 FindRootModel model, | |
296 const DicomMap& fields) | |
297 { | |
298 CheckIsOpen(); | |
299 | |
300 const char* sopClass; | |
301 std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); | |
302 switch (model) | |
303 { | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
304 case FindRootModel_Patient: |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
305 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
306 sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; |
0 | 307 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
308 // Accession number |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
309 if (!fields.HasTag(0x0008, 0x0050)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
310 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); |
0 | 311 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
312 // Patient ID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
313 if (!fields.HasTag(0x0010, 0x0020)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
314 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); |
0 | 315 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
316 break; |
0 | 317 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
318 case FindRootModel_Study: |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
319 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
320 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; |
0 | 321 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
322 // Accession number |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
323 if (!fields.HasTag(0x0008, 0x0050)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
324 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); |
0 | 325 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
326 // Study instance UID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
327 if (!fields.HasTag(0x0020, 0x000d)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
328 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); |
0 | 329 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
330 break; |
0 | 331 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
332 case FindRootModel_Series: |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
333 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
334 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; |
0 | 335 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
336 // Accession number |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
337 if (!fields.HasTag(0x0008, 0x0050)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
338 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); |
0 | 339 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
340 // Study instance UID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
341 if (!fields.HasTag(0x0020, 0x000d)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
342 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); |
0 | 343 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
344 // Series instance UID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
345 if (!fields.HasTag(0x0020, 0x000e)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
346 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); |
0 | 347 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
348 break; |
0 | 349 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
350 case FindRootModel_Instance: |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
351 if (manufacturer_ == ModalityManufacturer_ClearCanvas || |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
352 manufacturer_ == ModalityManufacturer_Dcm4Chee) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
353 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
354 // This is a particular case for ClearCanvas, thanks to Peter Somlo <peter.somlo@gmail.com>. |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
355 // https://groups.google.com/d/msg/orthanc-users/j-6C3MAVwiw/iolB9hclom8J |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
356 // http://www.clearcanvas.ca/Home/Community/OldForums/tabid/526/aff/11/aft/14670/afv/topic/Default.aspx |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
357 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "IMAGE"); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
358 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
359 else |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
360 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
361 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
362 } |
519
1b2cdc855bd3
Parameter for PACS manufacturer, support for ClearCanvas
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
399
diff
changeset
|
363 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
364 sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; |
0 | 365 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
366 // Accession number |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
367 if (!fields.HasTag(0x0008, 0x0050)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
368 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); |
0 | 369 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
370 // Study instance UID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
371 if (!fields.HasTag(0x0020, 0x000d)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
372 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); |
0 | 373 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
374 // Series instance UID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
375 if (!fields.HasTag(0x0020, 0x000e)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
376 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); |
0 | 377 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
378 // SOP Instance UID |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
379 if (!fields.HasTag(0x0008, 0x0018)) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
380 DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); |
0 | 381 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
382 break; |
0 | 383 |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
384 default: |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
385 throw OrthancException(ErrorCode_ParameterOutOfRange); |
0 | 386 } |
387 | |
388 // Figure out which of the accepted presentation contexts should be used | |
389 int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); | |
390 if (presID == 0) | |
391 { | |
62 | 392 throw OrthancException("DicomUserConnection: The C-FIND command is not supported by the distant AET"); |
0 | 393 } |
394 | |
395 T_DIMSE_C_FindRQ request; | |
396 memset(&request, 0, sizeof(request)); | |
397 request.MessageID = pimpl_->assoc_->nextMsgID++; | |
398 strcpy(request.AffectedSOPClassUID, sopClass); | |
399 request.DataSetType = DIMSE_DATASET_PRESENT; | |
400 request.Priority = DIMSE_PRIORITY_MEDIUM; | |
401 | |
402 T_DIMSE_C_FindRSP response; | |
403 DcmDataset* statusDetail = NULL; | |
404 OFCondition cond = DIMSE_findUser(pimpl_->assoc_, presID, &request, dataset.get(), | |
405 FindCallback, &result, | |
406 /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, | |
407 &response, &statusDetail); | |
408 | |
409 if (statusDetail) | |
410 { | |
411 delete statusDetail; | |
412 } | |
413 | |
414 Check(cond); | |
415 } | |
416 | |
417 | |
418 void DicomUserConnection::FindPatient(DicomFindAnswers& result, | |
419 const DicomMap& fields) | |
420 { | |
421 // Only keep the filters from "fields" that are related to the patient | |
422 DicomMap s; | |
423 fields.ExtractPatientInformation(s); | |
424 Find(result, FindRootModel_Patient, s); | |
425 } | |
426 | |
427 void DicomUserConnection::FindStudy(DicomFindAnswers& result, | |
428 const DicomMap& fields) | |
429 { | |
430 // Only keep the filters from "fields" that are related to the study | |
431 DicomMap s; | |
432 fields.ExtractStudyInformation(s); | |
433 | |
80 | 434 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID); |
435 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER); | |
725 | 436 s.CopyTagIfExists(fields, DICOM_TAG_MODALITIES_IN_STUDY); |
0 | 437 |
438 Find(result, FindRootModel_Study, s); | |
439 } | |
440 | |
441 void DicomUserConnection::FindSeries(DicomFindAnswers& result, | |
442 const DicomMap& fields) | |
443 { | |
444 // Only keep the filters from "fields" that are related to the series | |
445 DicomMap s; | |
446 fields.ExtractSeriesInformation(s); | |
447 | |
80 | 448 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID); |
449 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER); | |
450 s.CopyTagIfExists(fields, DICOM_TAG_STUDY_INSTANCE_UID); | |
0 | 451 |
452 Find(result, FindRootModel_Series, s); | |
453 } | |
454 | |
455 void DicomUserConnection::FindInstance(DicomFindAnswers& result, | |
456 const DicomMap& fields) | |
457 { | |
458 // Only keep the filters from "fields" that are related to the instance | |
459 DicomMap s; | |
460 fields.ExtractInstanceInformation(s); | |
461 | |
80 | 462 s.CopyTagIfExists(fields, DICOM_TAG_PATIENT_ID); |
463 s.CopyTagIfExists(fields, DICOM_TAG_ACCESSION_NUMBER); | |
464 s.CopyTagIfExists(fields, DICOM_TAG_STUDY_INSTANCE_UID); | |
465 s.CopyTagIfExists(fields, DICOM_TAG_SERIES_INSTANCE_UID); | |
0 | 466 |
467 Find(result, FindRootModel_Instance, s); | |
468 } | |
469 | |
470 | |
471 void DicomUserConnection::Move(const std::string& targetAet, | |
472 const DicomMap& fields) | |
473 { | |
474 CheckIsOpen(); | |
475 | |
476 const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel; | |
477 std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); | |
478 | |
479 // Figure out which of the accepted presentation contexts should be used | |
480 int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); | |
481 if (presID == 0) | |
482 { | |
62 | 483 throw OrthancException("DicomUserConnection: The C-MOVE command is not supported by the distant AET"); |
0 | 484 } |
485 | |
486 T_DIMSE_C_MoveRQ request; | |
487 memset(&request, 0, sizeof(request)); | |
488 request.MessageID = pimpl_->assoc_->nextMsgID++; | |
489 strcpy(request.AffectedSOPClassUID, sopClass); | |
490 request.DataSetType = DIMSE_DATASET_PRESENT; | |
491 request.Priority = DIMSE_PRIORITY_MEDIUM; | |
492 strncpy(request.MoveDestination, targetAet.c_str(), sizeof(DIC_AE) / sizeof(char)); | |
493 | |
494 T_DIMSE_C_MoveRSP response; | |
495 DcmDataset* statusDetail = NULL; | |
496 DcmDataset* responseIdentifiers = NULL; | |
497 OFCondition cond = DIMSE_moveUser(pimpl_->assoc_, presID, &request, dataset.get(), | |
498 NULL, NULL, | |
499 /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, | |
500 pimpl_->net_, NULL, NULL, | |
501 &response, &statusDetail, &responseIdentifiers); | |
502 | |
503 if (statusDetail) | |
504 { | |
505 delete statusDetail; | |
506 } | |
507 | |
508 if (responseIdentifiers) | |
509 { | |
510 delete responseIdentifiers; | |
511 } | |
512 | |
513 Check(cond); | |
514 } | |
515 | |
516 | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
517 void DicomUserConnection::ResetStorageSOPClasses() |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
518 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
519 CheckStorageSOPClassesInvariant(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
520 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
521 storageSOPClasses_.clear(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
522 defaultStorageSOPClasses_.clear(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
523 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
524 // Copy the short list of storage SOP classes from DCMTK, making |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
525 // room for the 4 SOP classes reserved for C-ECHO, C-FIND, C-MOVE. |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
526 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
527 std::set<std::string> uncommon; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
528 uncommon.insert(UID_BlendingSoftcopyPresentationStateStorage); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
529 uncommon.insert(UID_GrayscaleSoftcopyPresentationStateStorage); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
530 uncommon.insert(UID_ColorSoftcopyPresentationStateStorage); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
531 uncommon.insert(UID_PseudoColorSoftcopyPresentationStateStorage); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
532 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
533 // Add the storage syntaxes for C-STORE |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
534 for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs - 1; i++) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
535 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
536 if (uncommon.find(dcmShortSCUStorageSOPClassUIDs[i]) == uncommon.end()) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
537 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
538 defaultStorageSOPClasses_.insert(dcmShortSCUStorageSOPClassUIDs[i]); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
539 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
540 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
541 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
542 CheckStorageSOPClassesInvariant(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
543 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
544 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
545 |
656 | 546 DicomUserConnection::DicomUserConnection() : |
547 pimpl_(new PImpl), | |
666
b8383ac0b227
fix cppcheck warning
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
662
diff
changeset
|
548 preferredTransferSyntax_(DEFAULT_PREFERRED_TRANSFER_SYNTAX), |
656 | 549 localAet_("STORESCU"), |
550 distantAet_("ANY-SCP"), | |
551 distantHost_("127.0.0.1") | |
0 | 552 { |
553 distantPort_ = 104; | |
519
1b2cdc855bd3
Parameter for PACS manufacturer, support for ClearCanvas
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
399
diff
changeset
|
554 manufacturer_ = ModalityManufacturer_Generic; |
0 | 555 |
556 pimpl_->net_ = NULL; | |
557 pimpl_->params_ = NULL; | |
558 pimpl_->assoc_ = NULL; | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
559 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
560 // SOP classes for C-ECHO, C-FIND and C-MOVE |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
561 reservedStorageSOPClasses_.push_back(UID_VerificationSOPClass); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
562 reservedStorageSOPClasses_.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
563 reservedStorageSOPClasses_.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
564 reservedStorageSOPClasses_.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
565 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
566 ResetStorageSOPClasses(); |
0 | 567 } |
568 | |
569 DicomUserConnection::~DicomUserConnection() | |
570 { | |
571 Close(); | |
572 } | |
573 | |
574 void DicomUserConnection::SetLocalApplicationEntityTitle(const std::string& aet) | |
575 { | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
576 if (localAet_ != aet) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
577 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
578 Close(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
579 localAet_ = aet; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
580 } |
0 | 581 } |
582 | |
583 void DicomUserConnection::SetDistantApplicationEntityTitle(const std::string& aet) | |
584 { | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
585 if (distantAet_ != aet) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
586 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
587 Close(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
588 distantAet_ = aet; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
589 } |
0 | 590 } |
591 | |
519
1b2cdc855bd3
Parameter for PACS manufacturer, support for ClearCanvas
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
399
diff
changeset
|
592 void DicomUserConnection::SetDistantManufacturer(ModalityManufacturer manufacturer) |
1b2cdc855bd3
Parameter for PACS manufacturer, support for ClearCanvas
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
399
diff
changeset
|
593 { |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
594 if (manufacturer_ != manufacturer) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
595 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
596 Close(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
597 manufacturer_ = manufacturer; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
598 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
599 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
600 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
601 void DicomUserConnection::ResetPreferredTransferSyntax() |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
602 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
603 SetPreferredTransferSyntax(DEFAULT_PREFERRED_TRANSFER_SYNTAX); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
604 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
605 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
606 void DicomUserConnection::SetPreferredTransferSyntax(const std::string& preferredTransferSyntax) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
607 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
608 if (preferredTransferSyntax_ != preferredTransferSyntax) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
609 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
610 Close(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
611 preferredTransferSyntax_ = preferredTransferSyntax; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
612 } |
519
1b2cdc855bd3
Parameter for PACS manufacturer, support for ClearCanvas
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
399
diff
changeset
|
613 } |
1b2cdc855bd3
Parameter for PACS manufacturer, support for ClearCanvas
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
399
diff
changeset
|
614 |
0 | 615 |
616 void DicomUserConnection::SetDistantHost(const std::string& host) | |
617 { | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
618 if (distantHost_ != host) |
0 | 619 { |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
620 if (host.size() > HOST_NAME_MAX - 10) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
621 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
622 throw OrthancException("Distant host name is too long"); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
623 } |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
624 |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
625 Close(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
626 distantHost_ = host; |
0 | 627 } |
628 } | |
629 | |
630 void DicomUserConnection::SetDistantPort(uint16_t port) | |
631 { | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
632 if (distantPort_ != port) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
633 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
634 Close(); |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
635 distantPort_ = port; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
636 } |
0 | 637 } |
638 | |
639 void DicomUserConnection::Open() | |
640 { | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
641 if (IsOpen()) |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
642 { |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
643 // Don't reopen the connection |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
644 return; |
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
645 } |
0 | 646 |
647 Check(ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ 30, &pimpl_->net_)); | |
648 Check(ASC_createAssociationParameters(&pimpl_->params_, /*opt_maxReceivePDULength*/ ASC_DEFAULTMAXPDU)); | |
649 | |
650 // Set this application's title and the called application's title in the params | |
651 Check(ASC_setAPTitles(pimpl_->params_, localAet_.c_str(), distantAet_.c_str(), NULL)); | |
652 | |
653 // Set the network addresses of the local and distant entities | |
654 char localHost[HOST_NAME_MAX]; | |
655 gethostname(localHost, HOST_NAME_MAX - 1); | |
656 | |
657 char distantHostAndPort[HOST_NAME_MAX]; | |
2 | 658 |
659 #ifdef _MSC_VER | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
660 _snprintf |
2 | 661 #else |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
662 snprintf |
2 | 663 #endif |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
664 (distantHostAndPort, HOST_NAME_MAX - 1, "%s:%d", distantHost_.c_str(), distantPort_); |
0 | 665 |
666 Check(ASC_setPresentationAddresses(pimpl_->params_, localHost, distantHostAndPort)); | |
667 | |
668 // Set various options | |
669 Check(ASC_setTransportLayerType(pimpl_->params_, /*opt_secureConnection*/ false)); | |
670 | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
671 SetupPresentationContexts(preferredTransferSyntax_); |
0 | 672 |
673 // Do the association | |
674 Check(ASC_requestAssociation(pimpl_->net_, pimpl_->params_, &pimpl_->assoc_)); | |
675 | |
676 if (ASC_countAcceptedPresentationContexts(pimpl_->params_) == 0) | |
677 { | |
62 | 678 throw OrthancException("DicomUserConnection: No Acceptable Presentation Contexts"); |
0 | 679 } |
680 } | |
681 | |
682 void DicomUserConnection::Close() | |
683 { | |
684 if (pimpl_->assoc_ != NULL) | |
685 { | |
686 ASC_releaseAssociation(pimpl_->assoc_); | |
687 ASC_destroyAssociation(&pimpl_->assoc_); | |
688 pimpl_->assoc_ = NULL; | |
689 pimpl_->params_ = NULL; | |
690 } | |
691 else | |
692 { | |
693 if (pimpl_->params_ != NULL) | |
694 { | |
695 ASC_destroyAssociationParameters(&pimpl_->params_); | |
696 pimpl_->params_ = NULL; | |
697 } | |
698 } | |
699 | |
700 if (pimpl_->net_ != NULL) | |
701 { | |
702 ASC_dropNetwork(&pimpl_->net_); | |
703 pimpl_->net_ = NULL; | |
704 } | |
705 } | |
706 | |
707 bool DicomUserConnection::IsOpen() const | |
708 { | |
709 return pimpl_->IsOpen(); | |
710 } | |
711 | |
712 void DicomUserConnection::Store(const char* buffer, size_t size) | |
713 { | |
714 // Prepare an input stream for the memory buffer | |
715 DcmInputBufferStream is; | |
716 if (size > 0) | |
717 is.setBuffer(buffer, size); | |
718 is.setEos(); | |
719 | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
720 pimpl_->Store(is, *this); |
0 | 721 } |
722 | |
723 void DicomUserConnection::Store(const std::string& buffer) | |
724 { | |
725 if (buffer.size() > 0) | |
726 Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size()); | |
727 else | |
728 Store(NULL, 0); | |
729 } | |
730 | |
731 void DicomUserConnection::StoreFile(const std::string& path) | |
732 { | |
733 // Prepare an input stream for the file | |
734 DcmInputFileStream is(path.c_str()); | |
662
70161eb45b5c
orthanc can act as a C-Store SCU for JPEG transfer syntax
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
657
diff
changeset
|
735 pimpl_->Store(is, *this); |
0 | 736 } |
737 | |
738 bool DicomUserConnection::Echo() | |
739 { | |
740 CheckIsOpen(); | |
741 DIC_US status; | |
742 Check(DIMSE_echoUser(pimpl_->assoc_, pimpl_->assoc_->nextMsgID++, | |
743 /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, | |
744 &status, NULL)); | |
745 return status == STATUS_Success; | |
746 } | |
747 | |
748 | |
749 void DicomUserConnection::MoveSeries(const std::string& targetAet, | |
750 const DicomMap& findResult) | |
751 { | |
752 DicomMap simplified; | |
80 | 753 simplified.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, findResult.GetValue(DICOM_TAG_STUDY_INSTANCE_UID)); |
754 simplified.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, findResult.GetValue(DICOM_TAG_SERIES_INSTANCE_UID)); | |
0 | 755 Move(targetAet, simplified); |
756 } | |
757 | |
758 void DicomUserConnection::MoveSeries(const std::string& targetAet, | |
759 const std::string& studyUid, | |
760 const std::string& seriesUid) | |
761 { | |
762 DicomMap map; | |
80 | 763 map.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid); |
764 map.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid); | |
0 | 765 Move(targetAet, map); |
766 } | |
767 | |
768 void DicomUserConnection::MoveInstance(const std::string& targetAet, | |
769 const DicomMap& findResult) | |
770 { | |
771 DicomMap simplified; | |
80 | 772 simplified.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, findResult.GetValue(DICOM_TAG_STUDY_INSTANCE_UID)); |
773 simplified.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, findResult.GetValue(DICOM_TAG_SERIES_INSTANCE_UID)); | |
774 simplified.SetValue(DICOM_TAG_SOP_INSTANCE_UID, findResult.GetValue(DICOM_TAG_SOP_INSTANCE_UID)); | |
0 | 775 Move(targetAet, simplified); |
776 } | |
777 | |
778 void DicomUserConnection::MoveInstance(const std::string& targetAet, | |
779 const std::string& studyUid, | |
780 const std::string& seriesUid, | |
781 const std::string& instanceUid) | |
782 { | |
783 DicomMap map; | |
80 | 784 map.SetValue(DICOM_TAG_STUDY_INSTANCE_UID, studyUid); |
785 map.SetValue(DICOM_TAG_SERIES_INSTANCE_UID, seriesUid); | |
786 map.SetValue(DICOM_TAG_SOP_INSTANCE_UID, instanceUid); | |
0 | 787 Move(targetAet, map); |
788 } | |
789 | |
790 void DicomUserConnection::SetConnectionTimeout(uint32_t seconds) | |
791 { | |
792 dcmConnectionTimeout.set(seconds); | |
793 } | |
794 | |
763
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
795 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
796 void DicomUserConnection::CheckStorageSOPClassesInvariant() const |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
797 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
798 assert(storageSOPClasses_.size() + |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
799 defaultStorageSOPClasses_.size() + |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
800 reservedStorageSOPClasses_.size() <= MAXIMUM_STORAGE_SOP_CLASSES); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
801 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
802 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
803 void DicomUserConnection::AddStorageSOPClass(const char* sop) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
804 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
805 CheckStorageSOPClassesInvariant(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
806 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
807 if (storageSOPClasses_.find(sop) != storageSOPClasses_.end()) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
808 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
809 // This storage SOP class is already explicitly registered. Do |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
810 // nothing. |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
811 return; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
812 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
813 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
814 if (defaultStorageSOPClasses_.find(sop) != defaultStorageSOPClasses_.end()) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
815 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
816 // This storage SOP class is not explicitly registered, but is |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
817 // used by default. Just register it explicitly. |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
818 defaultStorageSOPClasses_.erase(sop); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
819 storageSOPClasses_.insert(sop); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
820 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
821 CheckStorageSOPClassesInvariant(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
822 return; |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
823 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
824 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
825 // This storage SOP class is neither explicitly, nor implicitly |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
826 // registered. Close the connection and register it explicitly. |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
827 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
828 Close(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
829 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
830 if (reservedStorageSOPClasses_.size() + |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
831 storageSOPClasses_.size() >= MAXIMUM_STORAGE_SOP_CLASSES) // (*) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
832 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
833 // The maximum number of SOP classes is reached |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
834 ResetStorageSOPClasses(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
835 defaultStorageSOPClasses_.erase(sop); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
836 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
837 else if (reservedStorageSOPClasses_.size() + storageSOPClasses_.size() + |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
838 defaultStorageSOPClasses_.size() >= MAXIMUM_STORAGE_SOP_CLASSES) |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
839 { |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
840 // Make room in the default storage syntaxes |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
841 assert(defaultStorageSOPClasses_.size() > 0); // Necessarily true because condition (*) is false |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
842 defaultStorageSOPClasses_.erase(*defaultStorageSOPClasses_.rbegin()); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
843 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
844 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
845 // Explicitly register the new storage syntax |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
846 storageSOPClasses_.insert(sop); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
847 |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
848 CheckStorageSOPClassesInvariant(); |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
849 } |
b5e6d2823115
dynamic negotiation of storage sop classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
732
diff
changeset
|
850 |
0 | 851 } |