1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #include "gdcmAAssociateACPDU.h"
15 #include "gdcmSwapper.h"
16 #include "gdcmAAssociateRQPDU.h"
17 
18 namespace gdcm
19 {
20 namespace network
21 {
22 const uint8_t AAssociateACPDU::ItemType = 0x02; // PDUType ?
23 const uint8_t AAssociateACPDU::Reserved2 = 0x00;
24 const uint16_t AAssociateACPDU::ProtocolVersion = 0x01; // big endian
25 const uint16_t AAssociateACPDU::Reserved9_10 = 0x0000;
26 //const uint8_t AAssociateACPDU::Reserved11_26[16] = {  };
27 //const uint8_t AAssociateACPDU::Reserved27_42[16] = {  };
28 //const uint8_t AAssociateACPDU::Reserved43_74[32] = {  };
29 
AAssociateACPDU()30 AAssociateACPDU::AAssociateACPDU()
31 {
32   PDULength = 0; // len of
33   memset(Reserved11_26, ' ', sizeof(Reserved11_26));
34   memset(Reserved27_42, ' ', sizeof(Reserved27_42));
35   memset(Reserved43_74, ' ', sizeof(Reserved43_74));
36 
37   PDULength = (uint32_t)(Size() - 6);
38 }
39 
SetCalledAETitle(const char calledaetitle[16])40 void AAssociateACPDU::SetCalledAETitle(const char calledaetitle[16])
41 {
42   //size_t len = strlen( calledaetitle );
43   //assert( len <= 16 ); // since forwarded from AA-RQ no reason to be invalid
44   memcpy(Reserved11_26, calledaetitle, 16 );
45 }
46 
SetCallingAETitle(const char callingaetitle[16])47 void AAssociateACPDU::SetCallingAETitle(const char callingaetitle[16])
48 {
49   //size_t len = strlen( callingaetitle );
50   //assert( len <= 16 ); // since forwarded from AA-RQ no reason to be invalid
51   memcpy(Reserved27_42, callingaetitle, 16 );
52 }
53 
Read(std::istream & is)54 std::istream &AAssociateACPDU::Read(std::istream &is)
55 {
56   //uint8_t itemtype = 0;
57   //is.read( (char*)&itemtype, sizeof(ItemType) );
58   //assert( itemtype == ItemType );
59   assert( is.good() );
60   uint8_t reserved2;
61   is.read( (char*)&reserved2, sizeof(Reserved2) );
62   uint32_t pdulength = 0;
63   is.read( (char*)&pdulength, sizeof(PDULength) );
64   SwapperDoOp::SwapArray(&pdulength,1);
65   PDULength = pdulength;
66   uint16_t protocolversion;
67   is.read( (char*)&protocolversion, sizeof(ProtocolVersion) );
68   SwapperDoOp::SwapArray(&protocolversion,1);
69   if( protocolversion != ProtocolVersion )
70     {
71     gdcmErrorMacro( "Improper Protocol Version: " << protocolversion );
72     }
73   uint16_t reserved9_10;
74   is.read( (char*)&reserved9_10, sizeof(Reserved9_10) );
75   SwapperDoOp::SwapArray(&reserved9_10,1);
76   char reserved11_26[16];
77   memset( reserved11_26, 0, sizeof(reserved11_26));
78   is.read( (char*)&reserved11_26, sizeof(Reserved11_26) ); // called
79   memcpy( Reserved11_26, reserved11_26, sizeof(Reserved11_26) );
80   char reserved27_42[16];
81   memset( reserved27_42, 0, sizeof(reserved27_42));
82   is.read( (char*)&reserved27_42, sizeof(Reserved27_42) ); // calling
83   memcpy( Reserved27_42, reserved27_42, sizeof(Reserved27_42) );
84   uint8_t reserved43_74[32];
85   memset( reserved43_74, 0, sizeof(reserved43_74));
86   is.read( (char*)&reserved43_74, sizeof(Reserved43_74) ); // 0 (32 times)
87   memcpy( Reserved43_74, reserved43_74, sizeof(Reserved43_74) );
88 
89   uint8_t itemtype2 = 0x0;
90   size_t curlen = 0;
91   while( curlen + 68 < PDULength )
92     {
93     is.read( (char*)&itemtype2, sizeof(ItemType) );
94     switch ( itemtype2 )
95       {
96     case 0x10: // ApplicationContext ItemType
97       AppContext.Read( is );
98       curlen += AppContext.Size();
99       break;
100     case 0x21: // PresentationContextAC ItemType
101         {
102         PresentationContextAC pcac;
103         pcac.Read( is );
104         PresContextAC.push_back( pcac );
105         curlen += pcac.Size();
106         }
107       break;
108     case 0x50: // UserInformation ItemType
109       UserInfo.Read( is );
110       curlen += UserInfo.Size();
111       break;
112     default:
113       gdcmErrorMacro( "Unknown ItemType: " << std::hex << (int) itemtype2 );
114       curlen = PDULength; // make sure to exit
115       break;
116       }
117     // WARNING: I cannot simply call Size() since UserInfo is initialized with GDCM
118     // own parameter, this will bias the computation. Instead compute relative
119     // length of remaining bytes to read.
120     //curlen = Size();
121     }
122   assert( curlen + 68 == PDULength );
123   assert( PDULength + 4 + 1 + 1 == Size() );
124 
125   return is;
126 }
127 
Write(std::ostream & os) const128 const std::ostream &AAssociateACPDU::Write(std::ostream &os) const
129 {
130   os.write( (const char*)&ItemType, sizeof(ItemType) );
131   os.write( (const char*)&Reserved2, sizeof(Reserved2) );
132   //os.write( (const char*)&PDULength, sizeof(PDULength) );
133   uint32_t copy = PDULength;
134   SwapperDoOp::SwapArray(&copy,1);
135   os.write( (const char*)&copy, sizeof(PDULength) );
136   uint16_t protocolversion = ProtocolVersion;
137   SwapperDoOp::SwapArray(&protocolversion,1);
138   os.write( (const char*)&protocolversion, sizeof(ProtocolVersion) );
139   os.write( (const char*)&Reserved9_10, sizeof(Reserved9_10) );
140   os.write( (const char*)&Reserved11_26, sizeof(Reserved11_26) );
141   //const char calling[] = "ANY-SCP         ";
142   //os.write( calling, 16 );
143 
144   os.write( (const char*)&Reserved27_42, sizeof(Reserved27_42) );
145   //const char called[] = "STORESCU        ";
146   //const char called[] = "ECHOSCU        ";
147   //os.write( called, 16 );
148   os.write( (const char*)&Reserved43_74, sizeof(Reserved43_74) );
149   AppContext.Write( os );
150   gdcmAssertAlwaysMacro( PresContextAC.size() );
151   std::vector<PresentationContextAC>::const_iterator it = PresContextAC.begin();
152   for( ; it != PresContextAC.end(); ++it )
153     {
154     it->Write( os );
155     }
156   UserInfo.Write( os );
157 
158   assert( PDULength + 4 + 1 + 1 == Size() );
159 
160   return os;
161 }
162 
Size() const163 size_t AAssociateACPDU::Size() const
164 {
165   size_t ret = 0;
166   ret += sizeof(ItemType);
167   ret += sizeof(Reserved2);
168   ret += sizeof(PDULength);
169   ret += sizeof(ProtocolVersion);
170   ret += sizeof(Reserved9_10);
171   ret += sizeof(Reserved11_26);
172   ret += sizeof(Reserved27_42);
173   ret += sizeof(Reserved43_74);
174   ret += AppContext.Size();
175   std::vector<PresentationContextAC>::const_iterator it = PresContextAC.begin();
176   for( ; it != PresContextAC.end(); ++it )
177     {
178     ret += it->Size();
179     }
180   ret += UserInfo.Size();
181   return ret;
182 }
183 
AddPresentationContextAC(PresentationContextAC const & pcac)184 void AAssociateACPDU::AddPresentationContextAC( PresentationContextAC const &pcac )
185 {
186   PresContextAC.push_back( pcac );
187   PDULength = (uint32_t)(Size() - 6);
188   assert( PDULength + 4 + 1 + 1 == Size() );
189 }
190 
Print(std::ostream & os) const191 void AAssociateACPDU::Print(std::ostream &os) const
192 {
193   os << "ProtocolVersion: " << std::hex << ProtocolVersion << std::dec << std::endl;
194   os << "Reserved9_10: " << std::hex << Reserved9_10 << std::dec << std::endl;
195   os << "Reserved11_26: [" << std::string(Reserved11_26,sizeof(Reserved11_26)) << "]" << std::endl;
196   os << "Reserved27_42: [" << std::string(Reserved27_42,sizeof(Reserved27_42)) << "]" << std::endl;
197   /*os << "Reserved43_74: [" << std::string(Reserved43_74,sizeof(Reserved43_74)) << "]" << std::endl;*/
198   os << "Application Context Name: ";
199   AppContext.Print( os );
200   os << "List of PresentationContextAC: " << std::endl;
201   std::vector<PresentationContextAC>::const_iterator it = PresContextAC.begin();
202   for( ; it != PresContextAC.end(); ++it )
203     {
204     it->Print(os);
205     }
206   os << "User Information: ";
207   UserInfo.Print( os );
208 }
209 
InitFromRQ(AAssociateRQPDU const & rqpdu)210 void AAssociateACPDU::InitFromRQ( AAssociateRQPDU const & rqpdu )
211 {
212   // Table 9-17 ASSOCIATE-AC PDU fields
213   // This reserved field shall be sent with a value identical to the value
214   // received in the same field of the A-ASSOCIATE-RQ PDU
215   const std::string called = rqpdu.GetCalledAETitle();
216   SetCalledAETitle( rqpdu.GetCalledAETitle().c_str() );
217   const std::string calling = rqpdu.GetCallingAETitle();
218   SetCallingAETitle( rqpdu.GetCallingAETitle().c_str() );
219   const std::string reserved = rqpdu.GetReserved43_74();
220   memcpy( Reserved43_74, reserved.c_str(), sizeof(Reserved43_74) );
221 
222   assert( ProtocolVersion == 0x01 );
223   assert( Reserved9_10 == 0x0 );
224   assert( memcmp( Reserved11_26, called.c_str(), sizeof( Reserved11_26) ) == 0 );
225   assert( memcmp( Reserved27_42, calling.c_str(), sizeof(Reserved27_42) ) == 0 );
226   assert( memcmp( Reserved43_74, reserved.c_str(), sizeof(Reserved43_74) ) == 0 );
227 }
228 
229 
InitSimple(AAssociateRQPDU const & rqpdu)230 void AAssociateACPDU::InitSimple( AAssociateRQPDU const & rqpdu )
231 {
232   TransferSyntaxSub ts1;
233   ts1.SetNameFromUID( UIDs::ImplicitVRLittleEndianDefaultTransferSyntaxforDICOM );
234 
235   assert( rqpdu.GetNumberOfPresentationContext() );
236   for( unsigned int index = 0; index < rqpdu.GetNumberOfPresentationContext(); index++ )
237     {
238     // FIXME / HARDCODED We only ever accept Little Endian
239     // FIXME we should check :
240     // rqpdu.GetAbstractSyntax() contains LittleEndian
241     PresentationContextAC pcac1;
242     PresentationContextRQ const &pc = rqpdu.GetPresentationContext(index);
243     uint8_t id = pc.GetPresentationContextID();
244 
245     pcac1.SetPresentationContextID( id ); // DCMTK MR
246     pcac1.SetTransferSyntax( ts1 );
247     AddPresentationContextAC( pcac1 );
248     }
249 
250 }
251 
252 } // end namespace network
253 } // end namespace gdcm
254