GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/Server.cpp
Date: 2025-08-17 04:10:43
Exec Total Coverage
Lines: 249 282 88.3%
Branches: 283 600 47.2%

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