GCC Code Coverage Report


Directory: ./
File: pdserv/src/msrproto/Server.cpp
Date: 2023-11-12 04:06:57
Exec Total Coverage
Lines: 245 278 88.1%
Branches: 277 588 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 130 Server::Server(const PdServ::Main *main, const PdServ::Config &config):
63 main(main),
64 log(log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("msr"))),
65
3/6
✓ Branch 10 taken 130 times.
✗ Branch 11 not taken.
✓ Branch 17 taken 130 times.
✗ Branch 18 not taken.
✓ Branch 36 taken 130 times.
✗ Branch 37 not taken.
135 state_(Init)
66 {
67 130 server = 0;
68 130 maxInputBufferSize = 0U;
69
70
2/4
✓ Branch 3 taken 130 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 130 times.
✗ Branch 10 not taken.
130 bindaddr = config["bindaddr"].toString();
71
2/4
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
130 m_broadcast = config["broadcast"].toUInt(1);
72
73
2/2
✓ Branch 2 taken 129 times.
✓ Branch 3 taken 1 times.
130 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 129 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 129 times.
✗ Branch 10 not taken.
258 const std::string host = config["bindhost"].toString();
78
2/4
✓ Branch 3 taken 129 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 129 times.
✗ Branch 10 not taken.
258 const std::string port = config["port"].toString();
79
80
3/6
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 129 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 129 times.
129 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 130 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 130 times.
✗ Branch 10 not taken.
130 tlsbindaddr = config["tlsbindaddr"].toString();
91 #endif
92
93
2/4
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
130 itemize = config["splitvectors"].toUInt();
94
95 130 insertRoot = &variableDirectory;
96
3/6
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 130 times.
130 if (config["pathprefix"])
97 insertRoot = variableDirectory.create(
98 config["pathprefix"].toString(main->name));
99
100
2/4
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
130 maxConnections = config["maxconnections"].toUInt(~0U);
101
102
1/2
✓ Branch 4 taken 130 times.
✗ Branch 5 not taken.
390 for (std::list<const PdServ::Task*> taskList(main->getTasks());
103
2/2
✓ Branch 1 taken 260 times.
✓ Branch 2 taken 130 times.
650 taskList.size(); taskList.pop_front())
104
1/2
✓ Branch 9 taken 260 times.
✗ Branch 10 not taken.
260 createChannels(insertRoot, taskList.front());
105
106
1/2
✓ Branch 7 taken 130 times.
✗ Branch 8 not taken.
130 createParameters(insertRoot);
107
108
2/4
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
130 unsigned int bufLimit = config["parserbufferlimit"].toUInt();
109
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
130 if (bufLimit > 1024 and maxInputBufferSize > bufLimit)
110 maxInputBufferSize = bufLimit;
111
8/16
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 130 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 130 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 130 times.
✗ Branch 16 not taken.
✓ Branch 24 taken 130 times.
✗ Branch 25 not taken.
✓ Branch 28 taken 130 times.
✗ Branch 29 not taken.
✓ Branch 32 taken 130 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 130 times.
✗ Branch 37 not taken.
130 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 130 times.
✗ Branch 4 not taken.
260 std::unique_lock<std::mutex> lck(mutex);
119
1/2
✓ Branch 4 taken 130 times.
✗ Branch 5 not taken.
130 start();
120 390 startup_cv.wait(lck, [this]{ return state_ != Init; });
121 }
122
2/2
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 125 times.
130 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 125 }
130
131 /////////////////////////////////////////////////////////////////////////////
132 375 Server::~Server()
133 {
134 125 terminate();
135 125 join();
136
137 // Parameters and Channels are deleted when variable tree
138 // is deleted
139 250 }
140
141 /////////////////////////////////////////////////////////////////////////////
142 24 std::string Server::getAddr(char sep) const
143 {
144 24 return server->getAddr(sep);
145 }
146
147 /////////////////////////////////////////////////////////////////////////////
148 260 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 260 times.
✗ Branch 5 not taken.
520 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 260 times.
✗ Branch 6 not taken.
260 channels.reserve(channels.size() + signals.size() + 4);
160
161
2/2
✓ Branch 1 taken 520 times.
✓ Branch 2 taken 260 times.
1300 for (; signals.size(); signals.pop_front()) {
162 520 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 520 times.
✗ Branch 7 not taken.
1560 PdServ::DataType::Iterator<CreateChannel>(
167 520 signal->dtype, signal->dim,
168
1/2
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
1040 CreateChannel(this, baseDir, signal));
169 }
170
171
2/4
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 260 times.
✗ Branch 12 not taken.
260 DirectoryNode* taskInfo = variableDirectory.create("Taskinfo");
172
173
1/2
✓ Branch 2 taken 260 times.
✗ Branch 3 not taken.
520 std::ostringstream os;
174
1/2
✓ Branch 5 taken 260 times.
✗ Branch 6 not taken.
260 os << task->index;
175
2/4
✓ Branch 5 taken 260 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 260 times.
✗ Branch 10 not taken.
260 DirectoryNode* t = taskInfo->create(os.str());
176
177
3/6
✓ Branch 3 taken 260 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 260 times.
✗ Branch 10 not taken.
260 c = new TimeSignal(task, channels.size());
178
1/2
✓ Branch 4 taken 260 times.
✗ Branch 5 not taken.
260 channels.push_back(c);
179
2/4
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 260 times.
✗ Branch 12 not taken.
260 t->insert(c, "TaskTime");
180
181
3/6
✓ Branch 3 taken 260 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 260 times.
✗ Branch 10 not taken.
260 c = new StatSignal(task, StatSignal::ExecTime, channels.size());
182
1/2
✓ Branch 4 taken 260 times.
✗ Branch 5 not taken.
260 channels.push_back(c);
183
2/4
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 260 times.
✗ Branch 12 not taken.
260 t->insert(c, "ExecTime");
184
185
3/6
✓ Branch 3 taken 260 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 260 times.
✗ Branch 10 not taken.
260 c = new StatSignal(task, StatSignal::Period, channels.size());
186
1/2
✓ Branch 4 taken 260 times.
✗ Branch 5 not taken.
260 channels.push_back(c);
187
2/4
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 260 times.
✗ Branch 12 not taken.
260 t->insert(c, "Period");
188
189
3/6
✓ Branch 3 taken 260 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 260 times.
✗ Branch 10 not taken.
260 c = new StatSignal(task, StatSignal::Overrun, channels.size());
190
1/2
✓ Branch 4 taken 260 times.
✗ Branch 5 not taken.
260 channels.push_back(c);
191
2/4
✓ Branch 7 taken 260 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 260 times.
✗ Branch 12 not taken.
260 t->insert(c, "Overrun");
192 260 }
193
194 /////////////////////////////////////////////////////////////////////////////
195 130 void Server::createParameters(DirectoryNode* baseDir)
196 {
197 LOG4CPLUS_TRACE_STR(log,
198 LOG4CPLUS_TEXT("Create parameters"));
199
200
1/2
✓ Branch 13 taken 130 times.
✗ Branch 14 not taken.
260 std::list<const PdServ::Parameter*> mainParam(main->getParameters());
201
202
1/2
✓ Branch 5 taken 130 times.
✗ Branch 6 not taken.
130 parameters.reserve(parameters.size() + mainParam.size());
203
204
2/2
✓ Branch 1 taken 780 times.
✓ Branch 2 taken 130 times.
1690 for (; mainParam.size(); mainParam.pop_front()) {
205 780 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 1560 maxInputBufferSize =
229 780 std::max(maxInputBufferSize,
230 1560 param->memSize * 4U + param->path.size() + 512);
231
232
1/2
✓ Branch 6 taken 780 times.
✗ Branch 7 not taken.
2340 PdServ::DataType::Iterator<CreateParameter>(
233 780 param->dtype, param->dim,
234
1/2
✓ Branch 1 taken 780 times.
✗ Branch 2 not taken.
1560 CreateParameter(this, baseDir, param));
235 }
236 130 }
237
238 /////////////////////////////////////////////////////////////////////////////
239 240 size_t Server::getMaxInputBufferSize() const
240 {
241 240 return maxInputBufferSize;
242 }
243
244 /////////////////////////////////////////////////////////////////////////////
245 130 void Server::initial()
246 {
247
3/4
✓ Branch 3 taken 130 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 56 times.
✓ Branch 10 taken 74 times.
186 std::unique_lock<std::mutex> lck(mutex);
248 struct NotifyAtLeave {
249 std::condition_variable& cv_;
250 130 NotifyAtLeave(std::condition_variable& cv) : cv_(cv) {}
251 130 ~NotifyAtLeave() { cv_.notify_all();}
252
2/2
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 74 times.
186 } 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 130 state_ = Stopped;
257
258
4/8
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 130 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 130 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 130 times.
✗ Branch 19 not taken.
130 LOG4CPLUS_INFO_STR(log, LOG4CPLUS_TEXT("Initializing MSR server"));
259
260 // Split bindaddr into interface and port
261
4/4
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 74 times.
✓ Branch 8 taken 56 times.
✓ Branch 9 taken 74 times.
186 std::string port, interface;
262 130 size_t colon = bindaddr.rfind(':');
263
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 if (colon == std::string::npos) {
264 // No colon specified, assume bindaddr specifies port only
265
1/2
✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
130 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 130 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
130 server.reset(new net::TCPServer(5));
274
275
2/2
✓ Branch 1 taken 129 times.
✓ Branch 2 taken 1 times.
130 if (port.empty()) {
276
1/2
✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
129 port = "2345";
277 }
278
4/6
✓ Branch 5 taken 130 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 130 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 127 times.
130 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 127 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 69 times.
✓ Branch 19 taken 58 times.
127 if (!main->tlsReady()) {
289 69 state_ = Running;
290 69 return;
291 }
292
2/4
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 58 times.
✗ Branch 7 not taken.
58 secure_server.reset(new net::TCPServer(5));
293 58 colon = tlsbindaddr.rfind(':');
294
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 if (colon == std::string::npos) {
295 // No colon specified, assume bindaddr specifies port only
296
1/2
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
58 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 58 times.
58 if (port.empty()) {
304 port = "4523";
305 }
306
4/6
✓ Branch 5 taken 58 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 58 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 56 times.
58 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 \"") << LOG4CPLUS_STRING_TO_TSTRING(
310 bindaddr) << LOG4CPLUS_TEXT("\" already in use"));
311 2 return;
312 }
313
314 #endif
315
2/2
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 74 times.
56 state_ = Running;
316 }
317
318 /////////////////////////////////////////////////////////////////////////////
319 // Returns:
320 // 1: successful
321 // 0: could not connect because port is in use
322 // -1: some error occurred
323 188 int Server::listenTo(
324 const std::string &interface,
325 const std::string &port,
326 net::TCPServer &server)
327 {
328 try {
329
3/4
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 183 times.
188 if (!server.listenTo(interface, port))
330 5 return 0;
331
332
8/18
✓ Branch 6 taken 183 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 183 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 183 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 183 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 183 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 183 times.
✗ Branch 24 not taken.
✓ Branch 29 taken 183 times.
✗ Branch 30 not taken.
✓ Branch 33 taken 183 times.
✗ Branch 34 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
183 LOG4CPLUS_INFO(log,
333 LOG4CPLUS_TEXT("Server started on ")
334 << LOG4CPLUS_STRING_TO_TSTRING(server.getAddr()));
335
336 183 return 1;
337 }
338 catch (const std::string& s) {
339 LOG4CPLUS_ERROR(log,
340 LOG4CPLUS_TEXT("Socket failure: ")
341 << LOG4CPLUS_STRING_TO_TSTRING(s));
342 return -1;
343 }
344 }
345
346 /////////////////////////////////////////////////////////////////////////////
347 130 void Server::final()
348 {
349 130 server.reset();
350 #ifdef GNUTLS_FOUND
351 130 secure_server.reset();
352 #endif
353
354 130 state_ = Stopped;
355
356 while (true) {
357 {
358
3/4
✓ Branch 3 taken 158 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 28 times.
✓ Branch 7 taken 130 times.
186 std::unique_lock<std::mutex> lock(mutex);
359
5/6
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 28 times.
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 130 times.
✓ Branch 9 taken 28 times.
158 if (sessions.empty() and pending_sessions.empty())
360
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 130 times.
130 break;
361 }
362 28 Thread::sleep(100);
363 28 }
364
365
3/6
✓ Branch 6 taken 130 times.
✗ Branch 7 not taken.
✓ Branch 12 taken 130 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 130 times.
✗ Branch 17 not taken.
130 LOG4CPLUS_INFO_STR(log, LOG4CPLUS_TEXT("Exiting MSR server"));
366 130 }
367
368 /////////////////////////////////////////////////////////////////////////////
369 130 void Server::run()
370 {
371
2/2
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 125 times.
130 if (!active())
372 5 return;
373 #ifdef GNUTLS_FOUND
374 125 const auto servers = secure_server
375 112 ? std::vector<net::TCPSocket *> {server.get(), secure_server.get()}
376
17/32
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 69 times.
✓ Branch 8 taken 56 times.
✗ Branch 9 not taken.
✓ Branch 16 taken 69 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 69 times.
✓ Branch 19 taken 56 times.
✓ Branch 21 taken 69 times.
✓ Branch 22 taken 56 times.
✓ Branch 24 taken 69 times.
✓ Branch 25 taken 56 times.
✓ Branch 27 taken 56 times.
✓ Branch 28 taken 69 times.
✓ Branch 30 taken 56 times.
✓ Branch 31 taken 69 times.
✓ Branch 33 taken 56 times.
✓ Branch 34 taken 69 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.
362 : std::vector<net::TCPSocket *> {server.get()};
377 249 while (const auto pending_server = static_cast<net::TCPServer *>(
378
3/4
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 125 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 124 times.
249 net::TCPSocket::select(servers))) {
379 #else
380 const auto pending_server = server.get();
381 while (server->isPendingConnection()) {
382 #endif
383
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 124 times.
124 if (!active())
384 return;
385
386
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 124 times.
124 if (sessions.size() == maxConnections) {
387 std::string name = server->reject();
388 LOG4CPLUS_WARN(log,
389 LOG4CPLUS_TEXT("Maximum connection count reached. "
390 "Rejecting client connection attempt from ")
391 << LOG4CPLUS_STRING_TO_TSTRING(name));
392 continue;
393 }
394
395 124 Session* session = 0;
396 try {
397
2/8
✓ Branch 3 taken 124 times.
✗ Branch 4 not taken.
✓ Branch 9 taken 124 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
248 std::unique_lock<std::mutex> lock(mutex);
398
399
5/8
✓ Branch 6 taken 124 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 118 times.
✓ Branch 9 taken 6 times.
✓ Branch 14 taken 118 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 118 times.
✗ Branch 19 not taken.
124 LOG4CPLUS_DEBUG_STR(log,
400 LOG4CPLUS_TEXT("New client connection"));
401
2/2
✓ Branch 2 taken 70 times.
✓ Branch 3 taken 54 times.
124 if (pending_server == server.get())
402
2/4
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 70 times.
✗ Branch 6 not taken.
70 session = new Session(this, pending_server);
403 #ifdef GNUTLS_FOUND
404
1/2
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
54 else if (pending_server == secure_server.get())
405
2/4
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
54 session = new PdServ::TlsSession<Session>(this, pending_server);
406 #endif
407
408
1/2
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
124 session->setSockOpt(SOL_SOCKET, SO_KEEPALIVE, 1);
409
1/2
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
124 session->setSockOpt(SOL_TCP, TCP_KEEPIDLE, 300);
410
1/2
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
124 pending_sessions.insert(session);
411
1/2
✓ Branch 4 taken 124 times.
✗ Branch 5 not taken.
124 session->detach();
412 }
413 catch (const std::string& s) {
414 LOG4CPLUS_FATAL(log,
415 LOG4CPLUS_TEXT("Socket failure: ")
416 << LOG4CPLUS_STRING_TO_TSTRING(s));
417 if (session)
418 session->close();
419 }
420 124 }
421 }
422
423 /////////////////////////////////////////////////////////////////////////////
424 20 void Server::broadcast(Session *s, const struct timespec& ts,
425 const std::string& action, const std::string &message)
426 {
427
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
20 if (!m_broadcast)
428 return;
429
430
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);
431 42 for (std::set<Session*>::iterator it = sessions.begin();
432
2/2
✓ Branch 6 taken 22 times.
✓ Branch 7 taken 20 times.
42 it != sessions.end(); ++it)
433
1/2
✓ Branch 6 taken 22 times.
✗ Branch 7 not taken.
22 (*it)->broadcast(s, ts, action, message);
434 }
435
436 /////////////////////////////////////////////////////////////////////////////
437 124 void Server::sessionClosed(Session *s)
438 {
439
1/2
✓ Branch 3 taken 124 times.
✗ Branch 4 not taken.
248 std::unique_lock<std::mutex> lock(mutex);
440
1/2
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
124 sessions.erase(s);
441
1/2
✓ Branch 2 taken 124 times.
✗ Branch 3 not taken.
124 pending_sessions.erase(s);
442 124 }
443
444 /////////////////////////////////////////////////////////////////////////////
445 120 void Server::sessionReady(Session *s)
446 {
447
1/2
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
240 std::unique_lock<std::mutex> lock(mutex);
448
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 sessions.insert(s);
449
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 pending_sessions.erase(s);
450 120 }
451
452 /////////////////////////////////////////////////////////////////////////////
453 5 void Server::getSessionStatistics(
454 std::list<PdServ::SessionStatistics>& stats) const
455 {
456
1/2
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
10 std::unique_lock<std::mutex> lock(mutex);
457 10 for (std::set<Session*>::iterator it = sessions.begin();
458
2/2
✓ Branch 6 taken 5 times.
✓ Branch 7 taken 5 times.
10 it != sessions.end(); ++it) {
459 10 PdServ::SessionStatistics s;
460
1/2
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
5 (*it)->getSessionStatistics(s);
461
1/2
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
5 stats.push_back(s);
462 }
463 5 }
464
465 /////////////////////////////////////////////////////////////////////////////
466 void Server::setAic(const Parameter *p)
467 {
468 std::unique_lock<std::mutex> lock(mutex);
469 for (std::set<Session*>::iterator it = sessions.begin();
470 it != sessions.end(); ++it)
471 (*it)->setAIC(p);
472 }
473
474 /////////////////////////////////////////////////////////////////////////////
475 43 void Server::parameterChanged(const PdServ::Parameter *mainParam,
476 size_t offset, size_t count,
477 const char* data, const struct timespec* time)
478 {
479
1/2
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
43 const Parameter *p = find(mainParam);
480
481
1/2
✓ Branch 3 taken 43 times.
✗ Branch 4 not taken.
86 std::unique_lock<std::mutex> lock(mutex);
482 89 for (std::set<Session*>::iterator it = sessions.begin();
483
2/2
✓ Branch 6 taken 46 times.
✓ Branch 7 taken 43 times.
89 it != sessions.end(); ++it)
484
1/2
✓ Branch 6 taken 46 times.
✗ Branch 7 not taken.
46 p->inform(*it, offset, offset + count, data, time);
485 43 }
486
487 /////////////////////////////////////////////////////////////////////////////
488 7 const Channel* Server::getChannel(size_t n) const
489 {
490
1/2
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
7 return n < channels.size() ? channels[n] : 0;
491 }
492
493 /////////////////////////////////////////////////////////////////////////////
494 17 const Server::Channels& Server::getChannels() const
495 {
496 17 return channels;
497 }
498
499 /////////////////////////////////////////////////////////////////////////////
500 10 void Server::listDir(PdServ::Session *session,
501 XmlElement& xml, const std::string& path, bool hex, bool derived) const
502 {
503 10 variableDirectory.list(session, xml, path, 0, hex, derived);
504 10 }
505
506 /////////////////////////////////////////////////////////////////////////////
507 84 const Parameter* Server::getParameter(size_t n) const
508 {
509
1/2
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
84 return n < parameters.size() ? parameters[n] : 0;
510 }
511
512 /////////////////////////////////////////////////////////////////////////////
513 5 const Server::Parameters& Server::getParameters() const
514 {
515 5 return parameters;
516 }
517
518 /////////////////////////////////////////////////////////////////////////////
519 43 const Parameter *Server::find( const PdServ::Parameter *p) const
520 {
521 43 return parameterMap.find(p)->second;
522 }
523
524 /////////////////////////////////////////////////////////////////////////////
525 /////////////////////////////////////////////////////////////////////////////
526 1300 Server::CreateVariable::CreateVariable(
527 1300 Server* server, DirectoryNode* baseDir, const PdServ::Variable* var):
528 1300 parent(0), server(server), baseDir(baseDir), var(var)
529 {
530 1300 }
531
532 /////////////////////////////////////////////////////////////////////////////
533 3380 Server::CreateVariable::CreateVariable(const CreateVariable& other):
534 6760 parent(&other), server(other.server),
535 10140 baseDir(other.baseDir), var(other.var)
536 {
537 3380 }
538
539 /////////////////////////////////////////////////////////////////////////////
540 8840 std::string Server::CreateVariable::path() const
541 {
542
4/6
✓ Branch 3 taken 5720 times.
✓ Branch 4 taken 3120 times.
✓ Branch 9 taken 5720 times.
✗ Branch 10 not taken.
✓ Branch 19 taken 3120 times.
✗ Branch 20 not taken.
17680 return (parent ? parent->path() : var->path)
543
3/6
✓ Branch 8 taken 8840 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 8840 times.
✗ Branch 15 not taken.
✓ Branch 19 taken 8840 times.
✗ Branch 20 not taken.
26520 + std::string(!name.empty(), '/') + name;
544 }
545
546 /////////////////////////////////////////////////////////////////////////////
547 2080 void Server::CreateVariable::newDimension(
548 const PdServ::DataType& /*dtype*/,
549 const PdServ::DataType::DimType& /*dim*/,
550 size_t /*dimIdx*/, size_t elemIdx,
551 CreateVariable& /*c*/, size_t /*offset*/)
552 {
553
1/2
✓ Branch 2 taken 2080 times.
✗ Branch 3 not taken.
4160 std::ostringstream os;
554
1/2
✓ Branch 2 taken 2080 times.
✗ Branch 3 not taken.
2080 os << elemIdx;
555
1/2
✓ Branch 2 taken 2080 times.
✗ Branch 3 not taken.
2080 name = os.str();
556 2080 }
557
558 /////////////////////////////////////////////////////////////////////////////
559 void Server::CreateVariable::newField(const PdServ::DataType::Field* field,
560 CreateVariable& /*c*/, size_t /*offset*/)
561 {
562 name = field->name;
563 }
564
565 /////////////////////////////////////////////////////////////////////////////
566 3380 bool Server::CreateVariable::newVariable(
567 const PdServ::DataType& dtype,
568 const PdServ::DataType::DimType& dim,
569 size_t dimIdx, size_t elemIdx, size_t offset) const
570 {
571 3380 bool rv = false;
572
573
1/2
✓ Branch 4 taken 3380 times.
✗ Branch 5 not taken.
3380 if (dtype.isPrimary()) {
574
5/8
✓ Branch 0 taken 1300 times.
✓ Branch 1 taken 2080 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1300 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2080 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2080 times.
3380 if ((dimIdx == 0 and elemIdx == 0) or !server->itemize) {
575 // Root element of a primary variable
576 1300 rv = createVariable(dtype, dim, offset);
577 }
578
2/2
✓ Branch 2 taken 1820 times.
✓ Branch 3 taken 260 times.
2080 else if (dimIdx == dim.size()) {
579 // Leaf node with only one element
580 static const size_t d = 1;
581
1/2
✓ Branch 6 taken 1820 times.
✗ Branch 7 not taken.
5460 rv = createVariable(dtype,
582 5460 PdServ::DataType::DimType(1, &d), offset);
583 }
584 }
585
586 3380 return rv;
587 }
588
589 /////////////////////////////////////////////////////////////////////////////
590 /////////////////////////////////////////////////////////////////////////////
591 520 Server::CreateChannel::CreateChannel(
592 520 Server* server, DirectoryNode* baseDir, const PdServ::Signal* s):
593 520 CreateVariable(server, baseDir, s)
594 {
595 520 }
596
597 /////////////////////////////////////////////////////////////////////////////
598 1040 bool Server::CreateChannel::createVariable(const PdServ::DataType& dtype,
599 const PdServ::DataType::DimType& dim, size_t offset) const
600 {
601
1/2
✓ Branch 6 taken 1040 times.
✗ Branch 7 not taken.
1040 Channel *c = new Channel(static_cast<const PdServ::Signal*>(var),
602
1/2
✓ Branch 8 taken 1040 times.
✗ Branch 9 not taken.
1040 server->channels.size(), dtype, dim, offset);
603 bool rv;
604
605
2/4
✗ Branch 12 not taken.
✓ Branch 13 taken 1040 times.
✓ Branch 14 taken 1040 times.
✗ Branch 15 not taken.
1040 if (server->itemize) {
606 1040 char hidden = 0;
607 1040 char persist = 0;
608
2/4
✓ Branch 17 taken 1040 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 1040 times.
✗ Branch 22 not taken.
1040 baseDir->traditionalPathInsert(c, path(), hidden, persist);
609
3/6
✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1040 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1040 times.
1040 c->hidden = hidden == 'c' or hidden == 'k' or hidden == 1;
610
611
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1040 times.
1040 rv = c->hidden;
612 }
613 else {
614 baseDir->pathInsert(c, path());
615 rv = true;
616 }
617
618
1/2
✓ Branch 7 taken 1040 times.
✗ Branch 8 not taken.
1040 server->channels.push_back(c);
619 1040 return rv;
620 }
621
622 /////////////////////////////////////////////////////////////////////////////
623 /////////////////////////////////////////////////////////////////////////////
624 780 Server::CreateParameter::CreateParameter(
625 780 Server* server, DirectoryNode* baseDir, const PdServ::Parameter* p):
626 780 CreateVariable(server, baseDir, p), parentParameter(0)
627 {
628 780 }
629
630 /////////////////////////////////////////////////////////////////////////////
631 2080 bool Server::CreateParameter::createVariable(const PdServ::DataType& dtype,
632 const PdServ::DataType::DimType& dim, size_t offset) const
633 {
634
1/2
✓ Branch 6 taken 2080 times.
✗ Branch 7 not taken.
2080 Parameter *p = new Parameter(static_cast<const PdServ::Parameter*>(var),
635
1/2
✓ Branch 11 taken 2080 times.
✗ Branch 12 not taken.
2080 server->parameters.size(), dtype, dim, offset, parentParameter);
636 bool rv;
637
638
1/2
✓ Branch 7 taken 2080 times.
✗ Branch 8 not taken.
2080 server->parameters.push_back(p);
639
640
2/4
✗ Branch 12 not taken.
✓ Branch 13 taken 2080 times.
✓ Branch 14 taken 2080 times.
✗ Branch 15 not taken.
2080 if (server->itemize) {
641 2080 char hidden = 0;
642 2080 char persist = 0;
643
2/4
✓ Branch 17 taken 2080 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 2080 times.
✗ Branch 22 not taken.
2080 baseDir->traditionalPathInsert(p, path(), hidden, persist);
644
2/4
✓ Branch 0 taken 2080 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2080 times.
2080 p->hidden = hidden == 'p' or hidden == 1;
645 2080 p->persistent = persist;
646
647
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 2080 times.
2080 rv = p->hidden;
648 }
649 else {
650 baseDir->pathInsert(p, path());
651 rv = true;
652 }
653
654
2/2
✓ Branch 3 taken 780 times.
✓ Branch 4 taken 1300 times.
2080 if (!parentParameter)
655
2/4
✓ Branch 7 taken 780 times.
✗ Branch 8 not taken.
✓ Branch 23 taken 780 times.
✗ Branch 24 not taken.
780 server->parameterMap[static_cast<const PdServ::Parameter*>(var)] = p;
656 2080 parentParameter = p;
657
658 2080 return rv;
659 }
660