2
2
#include < Poco/Net/HTTPClientSession.h>
3
3
#include < Poco/Net/HTTPRequest.h>
4
4
#include < Poco/Net/HTTPResponse.h>
5
+ #include < Poco/Net/WebSocket.h>
5
6
7
+ #include " olinkconnection.h"
6
8
#include " olink/clientregistry.h"
7
9
#include " olink/iobjectsink.h"
8
- #include " olinkconnection.h"
9
10
10
11
#include < iostream>
11
12
#include < memory>
@@ -15,7 +16,6 @@ using namespace ApiGear::PocoImpl;
15
16
namespace {
16
17
const std::string jsonContentType = " application/json" ;
17
18
const std::string defaultGatewayUrl = " ws://localhost:8000/ws" ;
18
- const std::string closeFramePayload = " bye" ;
19
19
const std::string pingFramePayload = " ping" ;
20
20
long retryInterval = 500 ; // Milliseconds
21
21
long smallDelay = 10 ; // Milliseconds
@@ -24,8 +24,8 @@ namespace{
24
24
25
25
OlinkConnection::OlinkConnection (ApiGear::ObjectLink::ClientRegistry& registry)
26
26
: m_node(ApiGear::ObjectLink::ClientNode::create(registry)),
27
- m_isConnecting( false ),
28
- m_disconnectRequested (false )
27
+ m_socket(* this ),
28
+ m_isConnecting (false )
29
29
{
30
30
auto writeFunction = [this ](const auto & msg) {
31
31
std::unique_lock<std::timed_mutex> lock (m_queueMutex);
@@ -36,58 +36,24 @@ OlinkConnection::OlinkConnection(ApiGear::ObjectLink::ClientRegistry& registry)
36
36
m_node->onWrite (writeFunction);
37
37
}
38
38
39
+ void OlinkConnection::onConnectionClosedFromNetwork ()
40
+ {
41
+ onDisconnected ();
42
+ }
43
+
39
44
OlinkConnection::~OlinkConnection ()
40
45
{
41
- m_disconnectRequested = true ;
42
46
// DisconnectAndUnlink modifies collection.
43
47
auto copyObjectLinkStatus = m_objectLinkStatus;
44
48
for (auto & object : copyObjectLinkStatus){
45
49
disconnectAndUnlink (object.first );
46
50
}
47
51
closeQueue ();
48
- if (m_receivingDone.valid ()){
49
- m_receivingDone.wait ();
50
- }
51
- onDisconnected ();
52
- }
53
-
54
- void OlinkConnection::receiveInLoop ()
55
- {
56
- onConnected ();
57
- auto serverClosedConnection = false ;
58
- do {
59
- try {
60
- // receiveFrame requires pocobuffer with initial size 0, as it always extends it with adding frame content.
61
- Poco::Buffer<char > pocobuffer (0 );
62
- int flags;
63
- auto canSocketRead = m_socket ? m_socket->poll (Poco::Timespan (10000 ), Poco::Net::WebSocket::SELECT_READ) : false ;
64
- if (canSocketRead && !m_disconnectRequested && m_socket) {
65
- std::unique_lock<std::timed_mutex> lock (m_socketMutex);
66
- auto frameSize = m_socket->receiveFrame (pocobuffer, flags);
67
- lock.unlock ();
68
- auto messagePayload = std::string (pocobuffer.begin (), frameSize);
69
- auto frameOpCode = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
70
- if (frameOpCode == Poco::Net::WebSocket::FRAME_OP_PING){
71
- writeMessage (messagePayload, Poco::Net::WebSocket::FRAME_OP_PONG);
72
- } else if (frameOpCode == Poco::Net::WebSocket::FRAME_OP_PONG) {
73
- // handle pong
74
- } else if (frameSize == 0 || frameOpCode == Poco::Net::WebSocket::FRAME_OP_CLOSE){
75
- std::cout << " close connection" << std::endl;
76
- serverClosedConnection = true ;
77
- } else {
78
- handleTextMessage (messagePayload);
79
- }
80
- }
81
- }
82
- catch (Poco::Exception& e) {
83
- serverClosedConnection = true ;
84
- std::cout << " connection closed with exception:" << e.what () << std::endl;
85
- }
86
- } while (!serverClosedConnection && !m_disconnectRequested);
87
- if (serverClosedConnection)
52
+ if (!m_socket.isClosed ())
88
53
{
89
- onDisconnected ();
54
+ m_socket. close ();
90
55
}
56
+ onDisconnected ();
91
57
}
92
58
93
59
void OlinkConnection::connectAndLinkObject (std::shared_ptr<ApiGear::ObjectLink::IObjectSink> object)
@@ -98,7 +64,7 @@ void OlinkConnection::connectAndLinkObject(std::shared_ptr<ApiGear::ObjectLink::
98
64
}
99
65
100
66
m_node->registry ().addSink (object);
101
- if (m_socket){
67
+ if (! m_socket. isClosed () ){
102
68
m_node->linkRemote (object->olinkObjectName ());
103
69
m_objectLinkStatus[object->olinkObjectName ()] = LinkStatus::Linked;
104
70
}
@@ -125,15 +91,15 @@ void OlinkConnection::connectToHost(Poco::URI url)
125
91
if (m_processMessagesTask){
126
92
m_processMessagesTask->cancel ();
127
93
}
128
- m_disconnectRequested = false ;
94
+
129
95
if (url.empty ()) {
130
96
m_serverUrl = Poco::URI (defaultGatewayUrl);
131
97
std::clog << " No host url provided" << std::endl;
132
98
} else {
133
99
m_serverUrl = url;
134
100
}
135
101
136
- if (! m_socket && !m_isConnecting) {
102
+ if (m_socket. isClosed () && !m_isConnecting) {
137
103
std::clog << " Connecting to host " << url.toString () << std::endl;
138
104
try {
139
105
m_isConnecting = true ;
@@ -142,15 +108,12 @@ void OlinkConnection::connectToHost(Poco::URI url)
142
108
request.setKeepAlive (true );
143
109
request.setContentType (jsonContentType);
144
110
Poco::Net::HTTPResponse response;
145
-
146
- m_socket = std::make_unique<Poco::Net::WebSocket>(session, request, response);
147
- if (m_socket){
148
- // Common default maximum frame size is 1Mb
149
- m_socket->setMaxPayloadSize (1048576 );
150
- }
151
- m_receivingDone = std::async (std::launch::async, [this ](){receiveInLoop (); });
111
+ auto socket = std::make_unique<Poco::Net::WebSocket>(session, request, response);
112
+ m_socket.changeSocket (std::move (socket));
113
+ onConnected ();
114
+
152
115
} catch (std::exception &e) {
153
- m_socket.reset ();
116
+ m_socket.close ();
154
117
std::cerr << " Exception " << e.what () << std::endl;
155
118
}
156
119
m_isConnecting = false ;
@@ -162,17 +125,13 @@ void OlinkConnection::connectToHost(Poco::URI url)
162
125
163
126
void OlinkConnection::disconnect () {
164
127
std::clog << " request to disconnect socket" << std::endl;
165
- m_disconnectRequested = true ;
166
-
167
128
for (auto & object : m_objectLinkStatus){
168
129
if (object.second != LinkStatus::NotLinked){
169
130
m_node->unlinkRemote (object.first );
170
131
}
171
132
}
172
133
closeQueue ();
173
- if (m_receivingDone.valid ()){
174
- m_receivingDone.wait ();
175
- }
134
+ m_socket.close ();
176
135
onDisconnected ();
177
136
}
178
137
@@ -182,7 +141,6 @@ void OlinkConnection::closeQueue()
182
141
m_processMessagesTask->cancel ();
183
142
}
184
143
flushMessages ();
185
- writeMessage (closeFramePayload, Poco::Net::WebSocket::FRAME_OP_CLOSE);
186
144
}
187
145
188
146
@@ -208,7 +166,6 @@ void OlinkConnection::onDisconnected()
208
166
{
209
167
object.second = LinkStatus::NotLinked;
210
168
}
211
- m_socket.reset ();
212
169
std::clog << " socket disconnected" << std::endl;
213
170
}
214
171
@@ -233,18 +190,19 @@ void OlinkConnection::scheduleProcessMessages(long delayMiliseconds)
233
190
234
191
void OlinkConnection::processMessages (Poco::Util::TimerTask& /* task*/ )
235
192
{
236
- if (! m_socket && !m_disconnectRequested ) {
193
+ if (m_socket. isClosed () ) {
237
194
connectToHost (m_serverUrl);
238
195
scheduleProcessMessages (tryReconnectDelay);
239
196
return ;
240
197
}
241
- writeMessage (pingFramePayload, Poco::Net::WebSocket::FRAME_OP_PING);
198
+
199
+ m_socket.writeMessage (pingFramePayload, Poco::Net::WebSocket::FRAME_OP_PING);
242
200
flushMessages ();
243
201
}
244
202
245
203
void OlinkConnection::flushMessages ()
246
204
{
247
- if (m_socket)
205
+ if (! m_socket. isClosed () )
248
206
{
249
207
std::deque<std::string> copyQueue;
250
208
std::unique_lock<std::timed_mutex> lock (m_queueMutex);
@@ -255,12 +213,12 @@ void OlinkConnection::flushMessages()
255
213
auto message = copyQueue.front ();
256
214
std::clog << " write message to socket " << message << std::endl;
257
215
// if we are using JSON we need to use txt message otherwise binary messages
258
- auto messageSent = writeMessage (message, Poco::Net::WebSocket::FRAME_TEXT);
216
+ auto messageSent = m_socket. writeMessage (message, Poco::Net::WebSocket::FRAME_TEXT);
259
217
if (messageSent){
260
218
copyQueue.pop_front ();
261
219
}
262
220
else {
263
- if (!m_disconnectRequested ){
221
+ if (!m_socket. isClosed () ){
264
222
lock.lock ();
265
223
// push again not sent elements to queue front
266
224
m_queue.insert (m_queue.begin (), copyQueue.begin (), copyQueue.end ());
@@ -272,20 +230,3 @@ void OlinkConnection::flushMessages()
272
230
}
273
231
}
274
232
}
275
-
276
- bool OlinkConnection::writeMessage (std::string message, int frameOpCode)
277
- {
278
- bool succeed = false ;
279
- try {
280
- if (m_socket) {
281
- std::unique_lock<std::timed_mutex> lock (m_socketMutex);
282
- m_socket->sendFrame (message.c_str (), static_cast <int >(message.size ()), frameOpCode);
283
- lock.unlock ();
284
- succeed = true ;
285
- }
286
- }
287
- catch (std::exception & e) {
288
- std::cerr << " Exception " << e.what () << std::endl;
289
- }
290
- return succeed;
291
- }
0 commit comments