1 | // |
2 | // DialogServer.cpp |
3 | // |
4 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
5 | // and Contributors. |
6 | // |
7 | // SPDX-License-Identifier: BSL-1.0 |
8 | // |
9 | |
10 | |
11 | #include "DialogServer.h" |
12 | #include "Poco/Net/DialogSocket.h" |
13 | #include "Poco/Net/SocketAddress.h" |
14 | #include "Poco/Timespan.h" |
15 | #include <iostream> |
16 | #include "Poco/Net/SecureStreamSocket.h" |
17 | #include "Poco/Net/SSLManager.h" |
18 | #include "Poco/Net/Context.h" |
19 | #include "Poco/Net/SecureStreamSocketImpl.h" |
20 | |
21 | using Poco::Net::Socket; |
22 | using Poco::Net::DialogSocket; |
23 | using Poco::Net::SocketAddress; |
24 | using Poco::FastMutex; |
25 | using Poco::Thread; |
26 | using Poco::Net::SecureStreamSocket; |
27 | using Poco::Net::SSLManager; |
28 | using Poco::Exception; |
29 | using Poco::Net::Context; |
30 | using Poco::Net::Session; |
31 | using Poco::Net::SecureStreamSocketImpl; |
32 | |
33 | DialogServer::DialogServer(bool acceptCommands, bool ssl): |
34 | _socket(SocketAddress()), |
35 | _thread("DialogServer" ), |
36 | _stop(false), |
37 | _acceptCommands(acceptCommands), |
38 | _log(false), |
39 | _ssl(ssl) |
40 | { |
41 | _thread.start(*this); |
42 | _ready.wait(); |
43 | } |
44 | |
45 | |
46 | DialogServer::~DialogServer() |
47 | { |
48 | _stop = true; |
49 | _thread.join(); |
50 | } |
51 | |
52 | |
53 | Poco::UInt16 DialogServer::port() const |
54 | { |
55 | return _socket.address().port(); |
56 | } |
57 | |
58 | |
59 | void handleDataSSLrequest(DialogSocket& ds, bool ssl, Session::Ptr& sslSession) |
60 | { |
61 | if (ssl) |
62 | { |
63 | try |
64 | { |
65 | Context::Ptr cDefaultServerContext = SSLManager::instance().defaultServerContext(); |
66 | SecureStreamSocket sss(SecureStreamSocket::attach(ds, cDefaultServerContext, sslSession)); |
67 | sss.setLazyHandshake(true); |
68 | if (sss.completeHandshake() == 1) |
69 | { |
70 | ds = sss; |
71 | } |
72 | } |
73 | catch (Exception&) { |
74 | } |
75 | } |
76 | } |
77 | |
78 | void handleSSLrequest(DialogSocket& ds, bool ssl, Session::Ptr& sslSession) |
79 | { |
80 | if (ssl) |
81 | { |
82 | try |
83 | { |
84 | Context::Ptr cDefaultServerContext = SSLManager::instance().defaultServerContext(); |
85 | ds.sendMessage("200 OK" ); |
86 | SecureStreamSocket sss(SecureStreamSocket::attach(ds, cDefaultServerContext)); |
87 | sss.setLazyHandshake(true); |
88 | if (sss.completeHandshake() == 1) |
89 | { |
90 | ds = sss; |
91 | |
92 | SecureStreamSocketImpl* pSecure = dynamic_cast<SecureStreamSocketImpl*>(sss.impl()); |
93 | if (pSecure != nullptr) |
94 | sslSession = pSecure->currentSession(); |
95 | } |
96 | else |
97 | { |
98 | ds.sendMessage("501 Explicit TLS authentication not available" ); |
99 | } |
100 | } |
101 | catch (Exception&) { |
102 | ds.sendMessage("501 Explicit TLS authentication not available" ); |
103 | } |
104 | } |
105 | else |
106 | { |
107 | ds.sendMessage("501 Explicit TLS authentication not available" ); |
108 | } |
109 | } |
110 | |
111 | void DialogServer::run() |
112 | { |
113 | _ready.set(); |
114 | Poco::Timespan span(250000); |
115 | while (!_stop) |
116 | { |
117 | if (_socket.poll(span, Socket::SELECT_READ)) |
118 | { |
119 | DialogSocket ds = _socket.acceptConnection(); |
120 | if (!_SSLsession.isNull()) { |
121 | handleDataSSLrequest(ds, _ssl, _SSLsession); |
122 | } |
123 | { |
124 | FastMutex::ScopedLock lock(_mutex); |
125 | if (!_nextResponses.empty()) |
126 | { |
127 | ds.sendMessage(_nextResponses.front()); |
128 | _nextResponses.erase(_nextResponses.begin()); |
129 | } |
130 | } |
131 | if (_acceptCommands) |
132 | { |
133 | try |
134 | { |
135 | |
136 | std::string command; |
137 | while (ds.receiveMessage(command)) |
138 | { |
139 | if ((command == "AUTH TLS" ) || (command == "AUTH SSL" )) |
140 | { |
141 | handleSSLrequest(ds, _ssl, _SSLsession); |
142 | continue; |
143 | } |
144 | else if ((command == "PBSZ 0" ) || (command == "PROT P" )) |
145 | { |
146 | ds.sendMessage("200 OK" ); |
147 | continue; |
148 | } |
149 | |
150 | if (_log) std::cout << ">> " << command << std::endl; |
151 | { |
152 | FastMutex::ScopedLock lock(_mutex); |
153 | _lastCommands.push_back(command); |
154 | if (!_nextResponses.empty()) |
155 | { |
156 | if (_log) std::cout << "<< " << _nextResponses.front() << std::endl; |
157 | ds.sendMessage(_nextResponses.front()); |
158 | _nextResponses.erase(_nextResponses.begin()); |
159 | } |
160 | } |
161 | } |
162 | } |
163 | catch (Poco::Exception& exc) |
164 | { |
165 | std::cerr << "DialogServer: " << exc.displayText() << std::endl; |
166 | } |
167 | } |
168 | } |
169 | } |
170 | } |
171 | |
172 | |
173 | const std::string& DialogServer::lastCommand() const |
174 | { |
175 | FastMutex::ScopedLock lock(_mutex); |
176 | |
177 | static const std::string EMPTY; |
178 | if (_lastCommands.empty()) |
179 | return EMPTY; |
180 | else |
181 | return _lastCommands.back(); |
182 | } |
183 | |
184 | |
185 | const std::vector<std::string>& DialogServer::lastCommands() const |
186 | { |
187 | return _lastCommands; |
188 | } |
189 | |
190 | |
191 | std::string DialogServer::popCommand() |
192 | { |
193 | FastMutex::ScopedLock lock(_mutex); |
194 | |
195 | std::string command; |
196 | if (!_lastCommands.empty()) |
197 | { |
198 | command = _lastCommands.front(); |
199 | _lastCommands.erase(_lastCommands.begin()); |
200 | } |
201 | return command; |
202 | } |
203 | |
204 | |
205 | std::string DialogServer::popCommandWait() |
206 | { |
207 | std::string result(popCommand()); |
208 | while (result.empty()) |
209 | { |
210 | Thread::sleep(100); |
211 | result = popCommand(); |
212 | } |
213 | return result; |
214 | } |
215 | |
216 | |
217 | void DialogServer::addResponse(const std::string& response) |
218 | { |
219 | FastMutex::ScopedLock lock(_mutex); |
220 | |
221 | _nextResponses.push_back(response); |
222 | } |
223 | |
224 | |
225 | void DialogServer::clearCommands() |
226 | { |
227 | FastMutex::ScopedLock lock(_mutex); |
228 | |
229 | _lastCommands.clear(); |
230 | } |
231 | |
232 | |
233 | void DialogServer::clearResponses() |
234 | { |
235 | FastMutex::ScopedLock lock(_mutex); |
236 | |
237 | _nextResponses.clear(); |
238 | } |
239 | |
240 | |
241 | void DialogServer::log(bool flag) |
242 | { |
243 | _log = flag; |
244 | } |
245 | |
246 | void DialogServer::setSslSession(Session::Ptr cSession) |
247 | { |
248 | _SSLsession = cSession; |
249 | } |
250 | |
251 | Session::Ptr DialogServer::getSslSession() |
252 | { |
253 | return _SSLsession; |
254 | } |
255 | |