1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef GDCMULCONNECTIONMANAGER_H
19 #define GDCMULCONNECTIONMANAGER_H
20 
21 #include "gdcmULTransitionTable.h"
22 #include "gdcmULConnection.h"
23 #include "gdcmULConnectionInfo.h"
24 #include "gdcmPresentationDataValue.h"
25 #include "gdcmULConnectionCallback.h"
26 #include "gdcmSubject.h"
27 #include "gdcmPresentationContext.h"
28 
29 namespace gdcm {
30   class File;
31   class BaseRootQuery;
32   class BaseQuery;
33 
34   namespace network {
35 
36 /**
37  * \brief ULConnectionManager
38  * \details The ULConnectionManager performs actions on the ULConnection given inputs
39  * from the user and from the state of what's going on around the connection
40  * (ie, timeouts of the ARTIM timer, responses from the peer across the
41  * connection, etc).
42  *
43  * Its inputs are ULEvents, and it performs ULActions.
44  */
45   class GDCM_EXPORT ULConnectionManager : public Subject
46   {
47     protected:
48       ULConnection* mConnection;
49       ULConnection* mSecondaryConnection;
50       ULTransitionTable mTransitions;
51 
52       //no copying
53       ULConnectionManager(const ULConnectionManager& inCM);
54 
55       //event handler loop.
56       //will just keep running until the current event is nonexistent.
57       //at which point, it will return the current state of the connection
58       //this starts by initiating an action, but can be put into a passive mode
59       //for a cmove/cstore combination by setting startWaiting to true
60       EStateID RunEventLoop(ULEvent& inEvent, ULConnection* inWhichConnection,
61         ULConnectionCallback* inCallback, const bool& startWaiting);
62 
63       //like the above, but will manage the event loop for a move event (which
64       //is basically two simultaneous connections interwoven, one inbound and
65       //the other outbound.  Note, for instance, that cmoversp's can be sent back
66       //during the other connection's operation.
67       EStateID RunMoveEventLoop(ULEvent& inEvent, ULConnectionCallback* inCallback);
68 
69     public:
70       ULConnectionManager();
71       ~ULConnectionManager() override;
72 
73       // NOTE: (MM) The following two functions are difficults to use, therefore marking
74       // them as internal for now.
75 
76       // \internal
77       /// returns true if a connection of the given AETitle (ie, 'this' program)
78       /// is able to connect to the given AETitle and Port in a certain amount of
79       /// time providing the connection type will establish the proper exchange
80       /// syntax with a server; if a different functionality is required, a
81       /// different connection should be established.
82       /// returns false if the connection type is 'move'-- have to give a return
83       /// port for move to work as specified.
84       bool EstablishConnection(const std::string& inAETitle,
85         const std::string& inConnectAETitle,
86         const std::string& inComputerName, long inIPAddress,
87         uint16_t inConnectPort, double inTimeout,
88         std::vector<PresentationContext> const & pcVector );
89 
90       /// returns true for above reasons, but contains the special 'move' port
91       /// \internal
92       bool EstablishConnectionMove(const std::string& inAETitle,
93         const std::string& inConnectAETitle,
94         const std::string& inComputerName, long inIPAddress,
95         uint16_t inConnectPort, double inTimeout,
96         uint16_t inReturnPort,
97         std::vector<PresentationContext> const & pcVector);
98       // \endinternal
99 
100 
101       //bool ReestablishConnection(const EConnectionType& inConnectionType,
102       //  const DataSet& inDS);
103 
104       //allows for a connection to be broken, but waits for an acknowledgement
105       //of the breaking for a certain amount of time.  Returns true of the
106       //other side acknowledges the break
107       bool BreakConnection(const double& inTimeout);
108 
109       //severs the connection, if it's open, without waiting for any kind of response.
110       //typically done if the program is going down.
111       void BreakConnectionNow();
112 
113       //This function will send a given piece of data
114       //across the network connection.  It will return true if the
115       //sending worked, false otherwise.
116       //note that sending is asynchronous; as such, there's
117       //also a 'receive' option, but that requires a callback function.
118       //bool SendData();
119 
120       //send the Data PDU associated with Echo (ie, a default DataPDU)
121       //this lets the user confirm that the connection is alive.
122       //the user should look to cout to see the response of the echo command
123       //returns the PresentationDataValue that was returned by the remote
124       //host.  Note that the PDV can be uninitialized, which would indicate failure.
125       //Echo does not use a callback for results.
126       std::vector<PresentationDataValue> SendEcho();
127 
128       // \internal
129       // API will change...
130       std::vector<DataSet> SendStore(const File &file, std::istream * pStream = nullptr, std::streampos dataSetOffset = 0  );
131       std::vector<DataSet> SendFind(const BaseRootQuery* inRootQuery);
132       std::vector<DataSet> SendMove(const BaseRootQuery* inRootQuery);
133 
134 	  std::vector<DataSet> SendNEventReport	(const BaseQuery* inQuery);
135       std::vector<DataSet> SendNGet			(const BaseQuery* inQuery);
136       std::vector<DataSet> SendNSet			(const BaseQuery* inQuery);
137       std::vector<DataSet> SendNAction		(const BaseQuery* inQuery);
138       std::vector<DataSet> SendNCreate		(const BaseQuery* inQuery);
139       std::vector<DataSet> SendNDelete		(const BaseQuery* inQuery);
140       // \endinternal
141 
142       ///callback based API
143       void SendStore(const File & file, ULConnectionCallback* inCallback, std::istream * pStream = nullptr , std::streampos dataSetOffset = 0 );
144       void SendFind(const BaseRootQuery* inRootQuery, ULConnectionCallback* inCallback);
145       /// return false upon error
146       bool SendMove(const BaseRootQuery* inRootQuery, ULConnectionCallback* inCallback);
147 
148       void SendNEventReport	(const BaseQuery* inQuery, ULConnectionCallback* inCallback);
149       void SendNGet			(const BaseQuery* inQuery, ULConnectionCallback* inCallback);
150       void SendNSet			(const BaseQuery* inQuery, ULConnectionCallback* inCallback);
151       void SendNAction		(const BaseQuery* inQuery, ULConnectionCallback* inCallback);
152       void SendNCreate		(const BaseQuery* inQuery, ULConnectionCallback* inCallback);
153       void SendNDelete		(const BaseQuery* inQuery, ULConnectionCallback* inCallback);
154 
155     };
156   }
157 }
158 
159 #endif // GDCMULCONNECTIONMANAGER_H
160