GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/Server.cpp
Date: 2024-12-15 04:08:34
Exec Total Coverage
Lines: 246 279 88.2%
Branches: 281 596 47.1%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright 2010 Richard Hacker (lerichi at gmx dot net)
6 *
7 * This file is part of the pdserv library.
8 *
9 * The pdserv library is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * The pdserv library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the pdserv library. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *****************************************************************************/
23
24 #include "config.h"
25
26 #include "Server.h"
27 #include "Channel.h"
28 #include "TimeSignal.h"
29 #include "StatSignal.h"
30 #include "Parameter.h"
31 #include "Session.h"
32 #include "../Exceptions.h"
33 #include "../Main.h"
34 #include "../Task.h"
35 #include "../Signal.h"
36 #include "../Parameter.h"
37 #include "../TCP.h"
38
39 #ifdef GNUTLS_FOUND
40 #include "../TlsSession.h"
41 #include "../TlsSessionImpl.h"
42 #endif
43
44 #include <string>
45 #include <cerrno>
46 #include <algorithm>
47 #include <log4cplus/loggingmacros.h>
48
49 using namespace MsrProto;
50
51 template <class T>
52 std::string toString(T val)
53 {
54 std::ostringstream os;
55 os << val + 0; // val + 0 is a neat way of preventing ostream
56 // from printing characters when processing
57 // char values
58 return os.str();
59 }
60
61 /////////////////////////////////////////////////////////////////////////////
62 154 Server::Server(const PdServ::Main *main, const PdServ::Config &config):
63 main(main),
64 log(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("msr"))),
65 broadcastLog(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("broadcast"))),
66
5/10
✓ Branch 10 taken 154 times.
✗ Branch 11 not taken.
✓ Branch 17 taken 154 times.
✗ Branch 18 not taken.
✓ Branch 27 taken 154 times.
✗ Branch 28 not taken.
✓ Branch 32 taken 154 times.
✗ Branch 33 not taken.
✓ Branch 51 taken 154 times.
✗ Branch 52 not taken.
159 state_(Init)
67 {
68 154 server = 0;
69 154 maxInputBufferSize = 0U;
70
71
2/4
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 154 times.
✗ Branch 10 not taken.
154 bindaddr = config["bindaddr"].toString();
72
2/4
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
154 m_broadcast = config["broadcast"].toUInt(1);
73
74
2/2
✓ Branch 2 taken 153 times.
✓ Branch 3 taken 1 times.
154 if (bindaddr.empty()) {
75 // It is difficult to multi-host in future using separate host and
76 // port configurations. It is better to use one configuration
77 // parameter, 'bindaddr' instead.
78
2/4
✓ Branch 3 taken 153 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 153 times.
✗ Branch 10 not taken.
306 const std::string host = config["bindhost"].toString();
79
2/4
✓ Branch 3 taken 153 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 153 times.
✗ Branch 10 not taken.
306 const std::string port = config["port"].toString();
80
81
3/6
✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 153 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 153 times.
153 if (!port.empty() or !host.empty()) {
82 LOG4CPLUS_WARN_STR(log,
83 LOG4CPLUS_TEXT(
84 "'bindhost' and 'port' are deprecated. "
85 "Use 'bindaddr' instead."));
86 bindaddr = host + ':' + port;
87 }
88 }
89
90 #ifdef GNUTLS_FOUND
91
2/4
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 154 times.
✗ Branch 10 not taken.
154 tlsbindaddr = config["tlsbindaddr"].toString();
92 #endif
93
94
2/4
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
154 itemize = config["splitvectors"].toUInt();
95
96 154 insertRoot = &variableDirectory;
97
3/6
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 154 times.
154 if (config["pathprefix"])
98 insertRoot = variableDirectory.create(
99 config["pathprefix"].toString(main->name));
100
101
2/4
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
154 maxConnections = config["maxconnections"].toUInt(~0U);
102
103
1/2
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
462 for (std::list<const PdServ::Task*> taskList(main->getTasks());
104
2/2
✓ Branch 1 taken 308 times.
✓ Branch 2 taken 154 times.
770 taskList.size(); taskList.pop_front())
105
1/2
✓ Branch 9 taken 308 times.
✗ Branch 10 not taken.
308 createChannels(insertRoot, taskList.front());
106
107
1/2
✓ Branch 7 taken 154 times.
✗ Branch 8 not taken.
154 createParameters(insertRoot);
108
109
2/4
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
154 unsigned int bufLimit = config["parserbufferlimit"].toUInt();
110
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
154 if (bufLimit > 1024 and maxInputBufferSize > bufLimit)
111 maxInputBufferSize = bufLimit;
112
8/16
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 154 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 154 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 154 times.
✗ Branch 16 not taken.
✓ Branch 24 taken 154 times.
✗ Branch 25 not taken.
✓ Branch 28 taken 154 times.
✗ Branch 29 not taken.
✓ Branch 32 taken 154 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 154 times.
✗ Branch 37 not taken.
154 LOG4CPLUS_INFO(log,
113 LOG4CPLUS_TEXT("Limiting XML input buffer to ")
114 << maxInputBufferSize
115 << LOG4CPLUS_TEXT(" bytes"));
116
117 // wait for background thread to boot
118 {
119
1/2
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
308 std::unique_lock<std::mutex> lck(mutex);
120
1/2
✓ Branch 4 taken 154 times.
✗ Branch 5 not taken.
154 start();
121 462 startup_cv.wait(lck, [this]{ return state_ != Init; });
122 }
123
2/2
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 149 times.
154 if (state_ != Running)
124 {
125 // dtor is not called, so cleanup.
126 5 terminate();
127 5 join();
128
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 throw PdServ::Errno(EADDRINUSE);
129 }
130 149 }
131
132 /////////////////////////////////////////////////////////////////////////////
133 447 Server::~Server()
134 {
135 149 terminate();
136 149 join();
137
138 // Parameters and Channels are deleted when variable tree
139 // is deleted
140 298 }
141
142 /////////////////////////////////////////////////////////////////////////////
143 30 std::string Server::getAddr(char sep) const
144 {
145 30 return server->getAddr(sep);
146 }
147
148 /////////////////////////////////////////////////////////////////////////////
149 308 void Server::createChannels(DirectoryNode* baseDir, const PdServ::Task* task)
150 {
151 Channel* c;
152
153 LOG4CPLUS_TRACE(log,
154 LOG4CPLUS_TEXT("Create channels for task ") << task->index
155 << LOG4CPLUS_TEXT(", Ts=") << task->sampleTime);
156
157
1/2
✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
616 std::list<const PdServ::Signal*> signals(task->getSignals());
158
159 // Reserve at least signal count and additionally 4 Taskinfo signals
160
1/2
✓ Branch 5 taken 308 times.
✗ Branch 6 not taken.
308 channels.reserve(channels.size() + signals.size() + 4);
161
162
2/2
✓ Branch 1 taken 924 times.
✓ Branch 2 taken 308 times.
2156 for (; signals.size(); signals.pop_front()) {
163 924 const PdServ::Signal *signal = signals.front();
164
165 // LOG4CPLUS_TRACE(log, LOG4CPLUS_TEXT(signal->path)
166 // << signal->dtype.name);
167
1/2
✓ Branch 6 taken 924 times.
✗ Branch 7 not taken.
2772 PdServ::DataType::Iterator<CreateChannel>(
168 924 signal->dtype, signal->dim,
169 1848 CreateChannel(this, baseDir, signal));
170 }
171
172
2/4
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 308 times.
✗ Branch 12 not taken.
308 DirectoryNode* taskInfo = variableDirectory.create("Taskinfo");
173
174
1/2
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
616 std::ostringstream os;
175
1/2
✓ Branch 5 taken 308 times.
✗ Branch 6 not taken.
308 os << task->index;
176
2/4
✓ Branch 5 taken 308 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 308 times.
✗ Branch 10 not taken.
308 DirectoryNode* t = taskInfo->create(os.str());
177
178
3/6
✓ Branch 3 taken 308 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 308 times.
✗ Branch 10 not taken.
308 c = new TimeSignal(task, channels.size());
179
1/2
✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
308 channels.push_back(c);
180
2/4
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 308 times.
✗ Branch 12 not taken.
308 t->insert(c, "TaskTime");
181
182
3/6
✓ Branch 3 taken 308 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 308 times.
✗ Branch 10 not taken.
308 c = new StatSignal(task, StatSignal::ExecTime, channels.size());
183
1/2
✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
308 channels.push_back(c);
184
2/4
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 308 times.
✗ Branch 12 not taken.
308 t->insert(c, "ExecTime");
185
186
3/6
✓ Branch 3 taken 308 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 308 times.
✗ Branch 10 not taken.
308 c = new StatSignal(task, StatSignal::Period, channels.size());
187
1/2
✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
308 channels.push_back(c);
188
2/4
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 308 times.
✗ Branch 12 not taken.
308 t->insert(c, "Period");
189
190
3/6
✓ Branch 3 taken 308 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 308 times.
✗ Branch 10 not taken.
308 c = new StatSignal(task, StatSignal::Overrun, channels.size());
191
1/2
✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
308 channels.push_back(c);
192
2/4
✓ Branch 7 taken 308 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 308 times.
✗ Branch 12 not taken.
308 t->insert(c, "Overrun");
193 308 }
194
195 /////////////////////////////////////////////////////////////////////////////
196 154 void Server::createParameters(DirectoryNode* baseDir)
197 {
198 LOG4CPLUS_TRACE_STR(log,
199 LOG4CPLUS_TEXT("Create parameters"));
200
201
1/2
✓ Branch 13 taken 154 times.
✗ Branch 14 not taken.
308 std::list<const PdServ::Parameter*> mainParam(main->getParameters());
202
203
1/2
✓ Branch 5 taken 154 times.
✗ Branch 6 not taken.
154 parameters.reserve(parameters.size() + mainParam.size());
204
205
2/2
✓ Branch 1 taken 924 times.
✓ Branch 2 taken 154 times.
2002 for (; mainParam.size(); mainParam.pop_front()) {
206 924 const PdServ::Parameter *param = mainParam.front();
207
208 // Calculate maximum dataspace requirement to change a parameter
209 // in bytes.
210 //
211 // The following table shows the requirement for selected data types:
212 // Type | bytes | infr. | mant | exp | total
213 // -------+-------+-------+--------+------+-------
214 // double | 8 | 3 | 16 | 4 | 23
215 // int64 | 8 | 1 | 19 | | 20
216 // single | 4 | 3 | 7 | 4 | 14
217 // int32 | 4 | 1 | 10 | | 11
218 // int16 | 2 | 1 | 5 | | 6
219 // int8 | 1 | 1 | 3 | | 4
220 //
221 // where:
222 // bytes: sizeof(type)
223 // infr: characters for infrastrucure (sign, exp, decimal point,
224 // field separator)
225 // mant: characters for mantissa representation
226 // exp: characters for exponent representation
227 //
228 // Thus it is safe to caculate with 4 characters per raw byte
229 1848 maxInputBufferSize =
230 924 std::max(maxInputBufferSize,
231 1848 param->memSize * 4U + param->path.size() + 512);
232
233
1/2
✓ Branch 6 taken 924 times.
✗ Branch 7 not taken.
2772 PdServ::DataType::Iterator<CreateParameter>(
234 924 param->dtype, param->dim,
235 1848 CreateParameter(this, baseDir, param));
236 }
237 154 }
238
239 /////////////////////////////////////////////////////////////////////////////
240 288 size_t Server::getMaxInputBufferSize() const
241 {
242 288 return maxInputBufferSize;
243 }
244
245 /////////////////////////////////////////////////////////////////////////////
246 154 void Server::initial()
247 {
248
3/4
✓ Branch 3 taken 154 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 68 times.
✓ Branch 10 taken 86 times.
222 std::unique_lock<std::mutex> lck(mutex);
249 struct NotifyAtLeave {
250 std::condition_variable& cv_;
251 154 NotifyAtLeave(std::condition_variable& cv) : cv_(cv) {}
252 154 ~NotifyAtLeave() { cv_.notify_all();}
253
2/2
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 86 times.
222 } const wakeup_parent_thread(startup_cv);
254
255 // set state to error first, the parent thread won't notice
256 // since we're holding the mutex which keeps it from waking up
257 154 state_ = Stopped;
258
259
4/8
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 154 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 154 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 154 times.
✗ Branch 19 not taken.
154 LOG4CPLUS_INFO_STR(log, LOG4CPLUS_TEXT("Initializing MSR server"));
260
261 // Split bindaddr into interface and port
262
4/4
✓ Branch 5 taken 68 times.
✓ Branch 6 taken 86 times.
✓ Branch 8 taken 68 times.
✓ Branch 9 taken 86 times.
222 std::string port, interface;
263 154 size_t colon = bindaddr.rfind(':');
264
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 if (colon == std::string::npos) {
265 // No colon specified, assume bindaddr specifies port only
266
1/2
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
154 port = bindaddr;
267 }
268 else {
269 // split interface:port
270 interface = bindaddr.substr(0, colon);
271 port = bindaddr.substr(colon+1);
272 }
273
274
2/4
✓ Branch 2 taken 154 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
154 server.reset(new net::TCPServer(5));
275
276
2/2
✓ Branch 1 taken 153 times.
✓ Branch 2 taken 1 times.
154 if (port.empty()) {
277
1/2
✓ Branch 1 taken 153 times.
✗ Branch 2 not taken.
153 port = "2345";
278 }
279
4/6
✓ Branch 5 taken 154 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 154 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 151 times.
154 if (listenTo(interface, port, *server) != 1) {
280
8/16
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 3 times.
✗ Branch 31 not taken.
3 LOG4CPLUS_ERROR(
281 log,
282 LOG4CPLUS_TEXT("Port in \"") << LOG4CPLUS_STRING_TO_TSTRING(
283 bindaddr) << LOG4CPLUS_TEXT("\" already in use"));
284 3 return;
285 }
286
287 #ifdef GNUTLS_FOUND
288 // skip tls setup if not configured
289
3/4
✓ Branch 16 taken 151 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 81 times.
✓ Branch 19 taken 70 times.
151 if (!main->tlsReady()) {
290 81 state_ = Running;
291 81 return;
292 }
293
2/4
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 70 times.
✗ Branch 7 not taken.
70 secure_server.reset(new net::TCPServer(5));
294 70 colon = tlsbindaddr.rfind(':');
295
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 if (colon == std::string::npos) {
296 // No colon specified, assume bindaddr specifies port only
297
1/2
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
70 port = tlsbindaddr;
298 }
299 else {
300 // split interface:port
301 interface = tlsbindaddr.substr(0, colon);
302 port = tlsbindaddr.substr(colon + 1);
303 }
304
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 70 times.
70 if (port.empty()) {
305 port = "4523";
306 }
307
4/6
✓ Branch 5 taken 70 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 70 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 68 times.
70 if (listenTo(interface, port, *secure_server) != 1) {
308
8/16
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
2 LOG4CPLUS_ERROR(
309 log,
310 LOG4CPLUS_TEXT("TLS Port in \"") << LOG4CPLUS_STRING_TO_TSTRING(
311 bindaddr) << LOG4CPLUS_TEXT("\" already in use"));
312 2 return;
313 }
314
315 #endif
316
2/2
✓ Branch 3 taken 68 times.
✓ Branch 4 taken 86 times.
68 state_ = Running;
317 }
318
319 /////////////////////////////////////////////////////////////////////////////
320 // Returns:
321 // 1: successful
322 // 0: could not connect because port is in use
323 // -1: some error occurred
324 224 int Server::listenTo(
325 const std::string &interface,
326 const std::string &port,
327 net::TCPServer &server)
328 {
329 try {
330
3/4
✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 219 times.
224 if (!server.listenTo(interface, port))
331 5 return 0;
332
333
8/18
✓ Branch 6 taken 219 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 219 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 219 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 219 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 219 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 219 times.
✗ Branch 24 not taken.
✓ Branch 29 taken 219 times.
✗ Branch 30 not taken.
✓ Branch 33 taken 219 times.
✗ Branch 34 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
219 LOG4CPLUS_INFO(log,
334 LOG4CPLUS_TEXT("Server started on ")
335 << LOG4CPLUS_STRING_TO_TSTRING(server.getAddr()));
336
337 219 return 1;
338 }
339 catch (const std::string& s) {
340 LOG4CPLUS_ERROR(log,
341 LOG4CPLUS_TEXT("Socket failure: ")
342 << LOG4CPLUS_STRING_TO_TSTRING(s));
343 return -1;
344 }
345 }
346
347 /////////////////////////////////////////////////////////////////////////////
348 154 void Server::final()
349 {
350 154 server.reset();
351 #ifdef GNUTLS_FOUND
352 154 secure_server.reset();
353 #endif
354
355 154 state_ = Stopped;
356
357 while (true) {
358 {
359
3/4
✓ Branch 3 taken 193 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 39 times.
✓ Branch 7 taken 154 times.
232 std::unique_lock<std::mutex> lock(mutex);
360
5/6
✓ Branch 2 taken 154 times.
✓ Branch 3 taken 39 times.
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 154 times.
✓ Branch 9 taken 39 times.
193 if (sessions.empty() and pending_sessions.empty())
361
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 154 times.
154 break;
362 }
363 39 Thread::sleep(100);
364 39 }
365
366
3/6
✓ Branch 6 taken 154 times.
✗ Branch 7 not taken.
✓ Branch 12 taken 154 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 154 times.
✗ Branch 17 not taken.
154 LOG4CPLUS_INFO_STR(log, LOG4CPLUS_TEXT("Exiting MSR server"));
367 154 }
368
369 /////////////////////////////////////////////////////////////////////////////
370 154 void Server::run()
371 {
372
2/2
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 149 times.
154 if (!active())
373 5 return;
374 #ifdef GNUTLS_FOUND
375 149 const auto servers = secure_server
376 136 ? std::vector<net::TCPSocket *> {server.get(), secure_server.get()}
377
17/32
✓ Branch 2 taken 68 times.
✓ Branch 3 taken 81 times.
✓ Branch 8 taken 68 times.
✗ Branch 9 not taken.
✓ Branch 16 taken 81 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 81 times.
✓ Branch 19 taken 68 times.
✓ Branch 21 taken 81 times.
✓ Branch 22 taken 68 times.
✓ Branch 24 taken 81 times.
✓ Branch 25 taken 68 times.
✓ Branch 27 taken 68 times.
✓ Branch 28 taken 81 times.
✓ Branch 30 taken 68 times.
✓ Branch 31 taken 81 times.
✓ Branch 33 taken 68 times.
✓ Branch 34 taken 81 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 5 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
434 : std::vector<net::TCPSocket *> {server.get()};
378 297 while (const auto pending_server = static_cast<net::TCPServer *>(
379
3/4
✓ Branch 1 taken 148 times.
✓ Branch 2 taken 149 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 148 times.
297 net::TCPSocket::select(servers))) {
380 #else
381 const auto pending_server = server.get();
382 while (server->isPendingConnection()) {
383 #endif
384
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 148 times.
148 if (!active())
385 return;
386
387
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 148 times.
148 if (sessions.size() == maxConnections) {
388 std::string name = server->reject();
389 LOG4CPLUS_WARN(log,
390 LOG4CPLUS_TEXT("Maximum connection count reached. "
391 "Rejecting client connection attempt from ")
392 << LOG4CPLUS_STRING_TO_TSTRING(name));
393 continue;
394 }
395
396 148 Session* session = 0;
397 try {
398
2/8
✓ Branch 3 taken 148 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 148 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
296 std::unique_lock<std::mutex> lock(mutex);
399
400
5/8
✓ Branch 6 taken 148 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 142 times.
✓ Branch 9 taken 6 times.
✓ Branch 14 taken 142 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 142 times.
✗ Branch 19 not taken.
148 LOG4CPLUS_DEBUG_STR(log,
401 LOG4CPLUS_TEXT("New client connection"));
402
2/2
✓ Branch 2 taken 82 times.
✓ Branch 3 taken 66 times.
148 if (pending_server == server.get())
403
2/4
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 82 times.
✗ Branch 6 not taken.
82 session = new Session(this, pending_server);
404 #ifdef GNUTLS_FOUND
405
1/2
✓ Branch 2 taken 66 times.
✗ Branch 3 not taken.
66 else if (pending_server == secure_server.get())
406
2/4
✓ Branch 3 taken 66 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 66 times.
✗ Branch 8 not taken.
66 session = new PdServ::TlsSession<Session>(this, pending_server);
407 #endif
408
409
1/2
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
148 session->setSockOpt(SOL_SOCKET, SO_KEEPALIVE, 1);
410
1/2
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
148 session->setSockOpt(SOL_TCP, TCP_KEEPIDLE, 300);
411
1/2
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
148 pending_sessions.insert(session);
412
1/2
✓ Branch 4 taken 148 times.
✗ Branch 5 not taken.
148 session->detach();
413 }
414 catch (const std::string& s) {
415 LOG4CPLUS_FATAL(log,
416 LOG4CPLUS_TEXT("Socket failure: ")
417 << LOG4CPLUS_STRING_TO_TSTRING(s));
418 if (session)
419 session->close();
420 }
421 148 }
422 }
423
424 /////////////////////////////////////////////////////////////////////////////
425 20 void Server::broadcast(Session *s, const struct timespec& ts,
426 const std::string& action, const std::string &message)
427 {
428
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
20 if (!m_broadcast)
429 return;
430
431
4/8
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 20 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 20 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 20 times.
✗ Branch 16 not taken.
20 LOG4CPLUS_INFO_STR(broadcastLog, message);
432
433
2/4
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
40 std::unique_lock<std::mutex> lock(mutex);
434 42 for (std::set<Session*>::iterator it = sessions.begin();
435
2/2
✓ Branch 6 taken 22 times.
✓ Branch 7 taken 20 times.
42 it != sessions.end(); ++it)
436
1/2
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
22 (*it)->broadcast(s, ts, action, message);
437 }
438
439 /////////////////////////////////////////////////////////////////////////////
440 148 void Server::sessionClosed(Session *s)
441 {
442
1/2
✓ Branch 3 taken 148 times.
✗ Branch 4 not taken.
296 std::unique_lock<std::mutex> lock(mutex);
443
1/2
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
148 sessions.erase(s);
444
1/2
✓ Branch 2 taken 148 times.
✗ Branch 3 not taken.
148 pending_sessions.erase(s);
445 148 }
446
447 /////////////////////////////////////////////////////////////////////////////
448 144 void Server::sessionReady(Session *s)
449 {
450
1/2
✓ Branch 3 taken 144 times.
✗ Branch 4 not taken.
288 std::unique_lock<std::mutex> lock(mutex);
451
1/2
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
144 sessions.insert(s);
452
1/2
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
144 pending_sessions.erase(s);
453 144 }
454
455 /////////////////////////////////////////////////////////////////////////////
456 5 void Server::getSessionStatistics(
457 std::list<PdServ::SessionStatistics>& stats) const
458 {
459
1/2
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
10 std::unique_lock<std::mutex> lock(mutex);
460 10 for (std::set<Session*>::iterator it = sessions.begin();
461
2/2
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 5 times.
10 it != sessions.end(); ++it) {
462 10 PdServ::SessionStatistics s;
463
1/2
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
5 (*it)->getSessionStatistics(s);
464
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 stats.push_back(s);
465 }
466 5 }
467
468 /////////////////////////////////////////////////////////////////////////////
469 void Server::setAic(const Parameter *p)
470 {
471 std::unique_lock<std::mutex> lock(mutex);
472 for (std::set<Session*>::iterator it = sessions.begin();
473 it != sessions.end(); ++it)
474 (*it)->setAIC(p);
475 }
476
477 /////////////////////////////////////////////////////////////////////////////
478 43 void Server::parameterChanged(const PdServ::Parameter *mainParam,
479 size_t offset, size_t count,
480 const char* data, const struct timespec* time)
481 {
482
1/2
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
43 const Parameter *p = find(mainParam);
483
484
1/2
✓ Branch 3 taken 43 times.
✗ Branch 4 not taken.
86 std::unique_lock<std::mutex> lock(mutex);
485 89 for (std::set<Session*>::iterator it = sessions.begin();
486
2/2
✓ Branch 6 taken 46 times.
✓ Branch 7 taken 43 times.
89 it != sessions.end(); ++it)
487
1/2
✓ Branch 6 taken 46 times.
✗ Branch 7 not taken.
46 p->inform(*it, offset, offset + count, data, time);
488 43 }
489
490 /////////////////////////////////////////////////////////////////////////////
491 7 const Channel* Server::getChannel(size_t n) const
492 {
493
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 return n < channels.size() ? channels[n] : 0;
494 }
495
496 /////////////////////////////////////////////////////////////////////////////
497 49 const Server::Channels& Server::getChannels() const
498 {
499 49 return channels;
500 }
501
502 /////////////////////////////////////////////////////////////////////////////
503 10 void Server::listDir(PdServ::Session *session,
504 XmlElement& xml, const std::string& path, bool hex, bool derived) const
505 {
506 10 variableDirectory.list(session, xml, path, 0, hex, derived);
507 10 }
508
509 /////////////////////////////////////////////////////////////////////////////
510 84 const Parameter* Server::getParameter(size_t n) const
511 {
512
1/2
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
84 return n < parameters.size() ? parameters[n] : 0;
513 }
514
515 /////////////////////////////////////////////////////////////////////////////
516 5 const Server::Parameters& Server::getParameters() const
517 {
518 5 return parameters;
519 }
520
521 /////////////////////////////////////////////////////////////////////////////
522 43 const Parameter *Server::find( const PdServ::Parameter *p) const
523 {
524 43 return parameterMap.find(p)->second;
525 }
526
527 /////////////////////////////////////////////////////////////////////////////
528 /////////////////////////////////////////////////////////////////////////////
529 1848 Server::CreateVariable::CreateVariable(
530 1848 Server* server, DirectoryNode* baseDir, const PdServ::Variable* var):
531 1848 parent(0), server(server), baseDir(baseDir), var(var)
532 {
533 1848 }
534
535 /////////////////////////////////////////////////////////////////////////////
536 4312 Server::CreateVariable::CreateVariable(const CreateVariable& other):
537 8624 parent(&other), server(other.server),
538 12936 baseDir(other.baseDir), var(other.var)
539 {
540 4312 }
541
542 /////////////////////////////////////////////////////////////////////////////
543 11088 std::string Server::CreateVariable::path() const
544 {
545
4/6
✓ Branch 3 taken 7084 times.
✓ Branch 4 taken 4004 times.
✓ Branch 9 taken 7084 times.
✗ Branch 10 not taken.
✓ Branch 19 taken 4004 times.
✗ Branch 20 not taken.
22176 return (parent ? parent->path() : var->path)
546
3/6
✓ Branch 8 taken 11088 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 11088 times.
✗ Branch 15 not taken.
✓ Branch 19 taken 11088 times.
✗ Branch 20 not taken.
33264 + std::string(!name.empty(), '/') + name;
547 }
548
549 /////////////////////////////////////////////////////////////////////////////
550 2464 void Server::CreateVariable::newDimension(
551 const PdServ::DataType& /*dtype*/,
552 const PdServ::DataType::DimType& /*dim*/,
553 size_t /*dimIdx*/, size_t elemIdx,
554 CreateVariable& /*c*/, size_t /*offset*/)
555 {
556
1/2
✓ Branch 2 taken 2464 times.
✗ Branch 3 not taken.
4928 std::ostringstream os;
557
1/2
✓ Branch 2 taken 2464 times.
✗ Branch 3 not taken.
2464 os << elemIdx;
558
1/2
✓ Branch 2 taken 2464 times.
✗ Branch 3 not taken.
2464 name = os.str();
559 2464 }
560
561 /////////////////////////////////////////////////////////////////////////////
562 void Server::CreateVariable::newField(const PdServ::DataType::Field* field,
563 CreateVariable& /*c*/, size_t /*offset*/)
564 {
565 name = field->name;
566 }
567
568 /////////////////////////////////////////////////////////////////////////////
569 4312 bool Server::CreateVariable::newVariable(
570 const PdServ::DataType& dtype,
571 const PdServ::DataType::DimType& dim,
572 size_t dimIdx, size_t elemIdx, size_t offset) const
573 {
574 4312 bool rv = false;
575
576
1/2
✓ Branch 4 taken 4312 times.
✗ Branch 5 not taken.
4312 if (dtype.isPrimary()) {
577
5/8
✓ Branch 0 taken 1848 times.
✓ Branch 1 taken 2464 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1848 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2464 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2464 times.
4312 if ((dimIdx == 0 and elemIdx == 0) or !server->itemize) {
578 // Root element of a primary variable
579 1848 rv = createVariable(dtype, dim, offset);
580 }
581
2/2
✓ Branch 2 taken 2156 times.
✓ Branch 3 taken 308 times.
2464 else if (dimIdx == dim.size()) {
582 // Leaf node with only one element
583 static const size_t d = 1;
584
1/2
✓ Branch 6 taken 2156 times.
✗ Branch 7 not taken.
6468 rv = createVariable(dtype,
585 6468 PdServ::DataType::DimType(1, &d), offset);
586 }
587 }
588
589 4312 return rv;
590 }
591
592 /////////////////////////////////////////////////////////////////////////////
593 /////////////////////////////////////////////////////////////////////////////
594 924 Server::CreateChannel::CreateChannel(
595 924 Server* server, DirectoryNode* baseDir, const PdServ::Signal* s):
596 924 CreateVariable(server, baseDir, s)
597 {
598 924 }
599
600 /////////////////////////////////////////////////////////////////////////////
601 1540 bool Server::CreateChannel::createVariable(const PdServ::DataType& dtype,
602 const PdServ::DataType::DimType& dim, size_t offset) const
603 {
604
1/2
✓ Branch 6 taken 1540 times.
✗ Branch 7 not taken.
1540 Channel *c = new Channel(static_cast<const PdServ::Signal*>(var),
605
1/2
✓ Branch 8 taken 1540 times.
✗ Branch 9 not taken.
1540 server->channels.size(), dtype, dim, offset);
606 bool rv;
607
608
2/4
✗ Branch 12 not taken.
✓ Branch 13 taken 1540 times.
✓ Branch 14 taken 1540 times.
✗ Branch 15 not taken.
1540 if (server->itemize) {
609 1540 char hidden = 0;
610 1540 char persist = 0;
611
2/4
✓ Branch 17 taken 1540 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 1540 times.
✗ Branch 22 not taken.
1540 baseDir->traditionalPathInsert(c, path(), hidden, persist);
612
3/6
✓ Branch 0 taken 1540 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1540 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1540 times.
1540 c->hidden = hidden == 'c' or hidden == 'k' or hidden == 1;
613
614
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1540 times.
1540 rv = c->hidden;
615 }
616 else {
617 baseDir->pathInsert(c, path());
618 rv = true;
619 }
620
621
1/2
✓ Branch 7 taken 1540 times.
✗ Branch 8 not taken.
1540 server->channels.push_back(c);
622 1540 return rv;
623 }
624
625 /////////////////////////////////////////////////////////////////////////////
626 /////////////////////////////////////////////////////////////////////////////
627 924 Server::CreateParameter::CreateParameter(
628 924 Server* server, DirectoryNode* baseDir, const PdServ::Parameter* p):
629 924 CreateVariable(server, baseDir, p), parentParameter(0)
630 {
631 924 }
632
633 /////////////////////////////////////////////////////////////////////////////
634 2464 bool Server::CreateParameter::createVariable(const PdServ::DataType& dtype,
635 const PdServ::DataType::DimType& dim, size_t offset) const
636 {
637
1/2
✓ Branch 6 taken 2464 times.
✗ Branch 7 not taken.
2464 Parameter *p = new Parameter(static_cast<const PdServ::Parameter*>(var),
638
1/2
✓ Branch 11 taken 2464 times.
✗ Branch 12 not taken.
2464 server->parameters.size(), dtype, dim, offset, parentParameter);
639 bool rv;
640
641
1/2
✓ Branch 7 taken 2464 times.
✗ Branch 8 not taken.
2464 server->parameters.push_back(p);
642
643
2/4
✗ Branch 12 not taken.
✓ Branch 13 taken 2464 times.
✓ Branch 14 taken 2464 times.
✗ Branch 15 not taken.
2464 if (server->itemize) {
644 2464 char hidden = 0;
645 2464 char persist = 0;
646
2/4
✓ Branch 17 taken 2464 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 2464 times.
✗ Branch 22 not taken.
2464 baseDir->traditionalPathInsert(p, path(), hidden, persist);
647
2/4
✓ Branch 0 taken 2464 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2464 times.
2464 p->hidden = hidden == 'p' or hidden == 1;
648 2464 p->persistent = persist;
649
650
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 2464 times.
2464 rv = p->hidden;
651 }
652 else {
653 baseDir->pathInsert(p, path());
654 rv = true;
655 }
656
657
2/2
✓ Branch 3 taken 924 times.
✓ Branch 4 taken 1540 times.
2464 if (!parentParameter)
658
2/4
✓ Branch 7 taken 924 times.
✗ Branch 8 not taken.
✓ Branch 23 taken 924 times.
✗ Branch 24 not taken.
924 server->parameterMap[static_cast<const PdServ::Parameter*>(var)] = p;
659 2464 parentParameter = p;
660
661 2464 return rv;
662 }
663