Directory: | ./ |
---|---|
File: | pdcom5/src/msrproto/ProtocolHandler.cpp |
Date: | 2024-12-15 04:08:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 904 | 1106 | 81.7% |
Branches: | 988 | 1982 | 49.8% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /***************************************************************************** | ||
2 | * | ||
3 | * Copyright (C) 2015-2016 Richard Hacker (lerichi at gmx dot net) | ||
4 | * | ||
5 | * This file is part of the PdCom library. | ||
6 | * | ||
7 | * The PdCom 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 by | ||
9 | * the Free Software Foundation, either version 3 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | * The PdCom 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 PdCom library. If not, see <http://www.gnu.org/licenses/>. | ||
19 | * | ||
20 | *****************************************************************************/ | ||
21 | |||
22 | #include "ProtocolHandler.h" | ||
23 | |||
24 | #include "../Debug.h" | ||
25 | #include "../SpyLayer.h" | ||
26 | #include "Channel.h" | ||
27 | #include "DirNode.h" | ||
28 | #include "Parameter.h" | ||
29 | #include "Subscription.h" | ||
30 | #include "expat_wrapper_impl.h" | ||
31 | |||
32 | #include <algorithm> | ||
33 | #include <cstring> | ||
34 | #include <errno.h> | ||
35 | #include <mutex> | ||
36 | #include <ostream> | ||
37 | #include <pdcom5/Exception.h> | ||
38 | #include <pdcom5/Subscriber.h> | ||
39 | #include <sstream> | ||
40 | #include <stdexcept> | ||
41 | #include <typeinfo> | ||
42 | |||
43 | #if defined _WIN32 || defined __ANDROID__ | ||
44 | namespace { | ||
45 | struct PthreadCancelDisabler | ||
46 | {}; | ||
47 | } // namespace | ||
48 | |||
49 | #else | ||
50 | |||
51 | #include <pthread.h> | ||
52 | namespace { | ||
53 | class PthreadCancelDisabler | ||
54 | { | ||
55 | int cancel_state_ = 0; | ||
56 | |||
57 | public: | ||
58 | PthreadCancelDisabler() | ||
59 | { | ||
60 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state_); | ||
61 | } | ||
62 | ~PthreadCancelDisabler() { pthread_setcancelstate(cancel_state_, nullptr); } | ||
63 | }; | ||
64 | } // namespace | ||
65 | |||
66 | #endif | ||
67 | |||
68 | #ifdef PDC_DEBUG | ||
69 | #include <stdlib.h> // getenv(), atoi() | ||
70 | #endif | ||
71 | |||
72 | using PdCom::impl::MsrProto::Channel; | ||
73 | using PdCom::impl::MsrProto::ChannelSubscriptionsWithGroup; | ||
74 | using PdCom::impl::MsrProto::ChannelSubscriptionsWithoutGroup; | ||
75 | using PdCom::impl::MsrProto::EventSubscription; | ||
76 | using PdCom::impl::MsrProto::ExpatWrapper; | ||
77 | using PdCom::impl::MsrProto::Parameter; | ||
78 | using PdCom::impl::MsrProto::PeriodicSubscription; | ||
79 | using PdCom::impl::MsrProto::PollSubscription; | ||
80 | using PdCom::impl::MsrProto::ProtocolHandler; | ||
81 | using PdCom::impl::MsrProto::Variable; | ||
82 | using PdCom::impl::MsrProto::XmlStream; | ||
83 | |||
84 | |||
85 | namespace { | ||
86 | struct Attribute | ||
87 | { /*{{{*/ | ||
88 | 3828 | Attribute(const char **atts) : atts(atts) {} | |
89 | |||
90 | 7708 | const char *find(const char *const arg, const char *const else_return = "") | |
91 | { | ||
92 |
3/4✓ Branch 0 taken 27555 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 25639 times.
✓ Branch 5 taken 1916 times.
|
27555 | for (size_t i = 0; arg and atts[i]; i += 2) { |
93 |
4/6✗ Branch 2 not taken.
✓ Branch 3 taken 25639 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 25639 times.
✓ Branch 6 taken 5792 times.
✓ Branch 7 taken 19847 times.
|
25639 | if (!strcmp(atts[i], arg)) |
94 | 5792 | return atts[i + 1]; | |
95 | } | ||
96 | |||
97 | 1916 | return else_return; | |
98 | } | ||
99 | |||
100 | 333 | bool getString(const char *arg, const char *&val) | |
101 | { | ||
102 | 333 | const char *attr = find(arg, nullptr); | |
103 | |||
104 |
2/2✓ Branch 0 taken 154 times.
✓ Branch 1 taken 179 times.
|
333 | if (!attr) |
105 | 154 | return false; | |
106 | |||
107 | 179 | val = attr; | |
108 | 179 | return true; | |
109 | }; | ||
110 | |||
111 | 2598 | bool getUInt(const char *arg, unsigned int &val) | |
112 | { | ||
113 | 2598 | const char *attr = find(arg); | |
114 | |||
115 | // Only test for numbers, even leading '+' is ignored | ||
116 |
3/4✓ Branch 1 taken 2060 times.
✓ Branch 2 taken 538 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2060 times.
|
2598 | if (*attr < '0' or *attr > '9') |
117 | 538 | return false; | |
118 | |||
119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2060 times.
|
2060 | val = atol(attr); |
120 | 2060 | return true; | |
121 | } | ||
122 | |||
123 | 140 | bool getInt(const char *arg, int &val) | |
124 | { | ||
125 | 140 | const char *attr = find(arg); | |
126 | |||
127 | // Only test for numbers, even leading '+' is ignored | ||
128 |
4/6✓ Branch 1 taken 59 times.
✓ Branch 2 taken 81 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 59 times.
✓ Branch 7 taken 81 times.
✗ Branch 8 not taken.
|
140 | if ((*attr < '0' or *attr > '9') and *attr != '-') |
129 | 81 | return false; | |
130 | |||
131 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | val = atoi(attr); |
132 | 59 | return true; | |
133 | } | ||
134 | |||
135 | 377 | bool isTrue(const char *arg) | |
136 | { | ||
137 | 377 | unsigned int val; | |
138 |
1/4✗ Branch 2 not taken.
✓ Branch 3 taken 377 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
377 | return getUInt(arg, val) and val; |
139 | } | ||
140 | |||
141 | 208 | bool getDouble(const char *arg, double &val) | |
142 | { | ||
143 | 208 | const char *attr = find(arg); | |
144 | |||
145 |
1/2✓ Branch 1 taken 208 times.
✗ Branch 2 not taken.
|
208 | if (*attr) |
146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 208 times.
|
208 | val = atof(attr); |
147 | |||
148 | 208 | return *attr; | |
149 | } | ||
150 | |||
151 | 541 | std::chrono::nanoseconds getTime_ns(const char *arg) | |
152 | { | ||
153 | 541 | const char *attr = find(arg); | |
154 | |||
155 | 541 | int64_t time_ns = 0; | |
156 | 541 | size_t i = 0; | |
157 | 6426 | do { | |
158 |
6/6✓ Branch 1 taken 5344 times.
✓ Branch 2 taken 1623 times.
✓ Branch 3 taken 2098 times.
✓ Branch 4 taken 3246 times.
✓ Branch 6 taken 541 times.
✓ Branch 7 taken 1557 times.
|
6967 | if (!*attr or (!i and *attr == '.')) { |
159 |
2/2✓ Branch 0 taken 541 times.
✓ Branch 1 taken 1623 times.
|
4328 | if (!i) |
160 | 541 | i = 10; | |
161 | } | ||
162 |
2/4✓ Branch 1 taken 4803 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4803 times.
|
4803 | else if (*attr < '0' or *attr > '9') |
163 | ✗ | return std::chrono::nanoseconds {0}; | |
164 | |||
165 |
2/2✓ Branch 1 taken 6426 times.
✓ Branch 2 taken 541 times.
|
6967 | if (*attr != '.') { |
166 |
3/4✓ Branch 1 taken 1623 times.
✓ Branch 2 taken 4803 times.
✓ Branch 3 taken 1623 times.
✗ Branch 4 not taken.
|
6426 | if (*attr or i != 10) |
167 | 6426 | time_ns *= 10; | |
168 | |||
169 |
2/2✓ Branch 1 taken 4803 times.
✓ Branch 2 taken 1623 times.
|
6426 | if (*attr) |
170 | 4803 | time_ns += *attr - '0'; | |
171 | } | ||
172 | |||
173 |
2/2✓ Branch 1 taken 5344 times.
✓ Branch 2 taken 1623 times.
|
6967 | if (*attr) |
174 | 5344 | ++attr; | |
175 | |||
176 |
8/8✓ Branch 1 taken 6426 times.
✓ Branch 2 taken 541 times.
✓ Branch 3 taken 5410 times.
✓ Branch 4 taken 1016 times.
✓ Branch 5 taken 4869 times.
✓ Branch 6 taken 541 times.
✓ Branch 7 taken 6426 times.
✓ Branch 8 taken 541 times.
|
6967 | } while (*attr == '.' or !i or --i); |
177 | |||
178 | 541 | return std::chrono::nanoseconds {time_ns}; | |
179 | } | ||
180 | |||
181 | 50 | bool getMessage(const char *tag_name, PdCom::Message &msg, bool hasSeqNo) | |
182 | { | ||
183 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
|
50 | const bool is_reset = !strcmp(tag_name, "reset"); |
184 | 50 | const char *c = nullptr; | |
185 | 50 | unsigned int u = 0; | |
186 |
4/6✓ Branch 2 taken 2 times.
✓ Branch 3 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 50 times.
|
50 | if (!getString("name", c) && !getString("path", c)) { |
187 | log_debug("Missing name in message"); | ||
188 | ✗ | return false; | |
189 | } | ||
190 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 | msg.path = c; |
191 |
4/6✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 48 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 50 times.
|
50 | if (hasSeqNo && !getUInt("seq", u)) { |
192 | log_debug("Invalid or missing sequence number in message"); | ||
193 | ✗ | return false; | |
194 | } | ||
195 | 50 | msg.seqNo = u; | |
196 | // index is optional, set it to -1 if absent. | ||
197 | 50 | msg.index = -1; | |
198 | 50 | getInt("index", msg.index); | |
199 |
1/2✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
|
50 | msg.time = getTime_ns("time"); |
200 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 31 times.
|
50 | if (is_reset) { |
201 | 19 | msg.level = PdCom::LogLevel::Reset; | |
202 | 19 | return true; | |
203 | } | ||
204 | // text is also optional | ||
205 |
2/2✓ Branch 2 taken 30 times.
✓ Branch 3 taken 1 times.
|
31 | if (getString("text", c)) { |
206 |
1/2✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
|
30 | msg.text = c; |
207 | } | ||
208 | else { | ||
209 | 1 | msg.text = std::string(); | |
210 | } | ||
211 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 29 times.
|
31 | if (getUInt("state", u)) { |
212 | // | ||
213 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (!u) { |
214 | 1 | msg.level = PdCom::LogLevel::Reset; | |
215 | } | ||
216 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | else if (!strcmp(tag_name, "crit_error")) |
217 | ✗ | msg.level = PdCom::LogLevel::Critical; | |
218 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | else if (!strcmp(tag_name, "error")) |
219 | 1 | msg.level = PdCom::LogLevel::Error; | |
220 | ✗ | else if (!strcmp(tag_name, "warn")) | |
221 | ✗ | msg.level = PdCom::LogLevel::Warn; | |
222 | ✗ | else if (!strcmp(tag_name, "info")) | |
223 | ✗ | msg.level = PdCom::LogLevel::Info; | |
224 | else { | ||
225 | log_debug("Invalid event attribute name %s", tag_name); | ||
226 | ✗ | return false; | |
227 | } | ||
228 | } | ||
229 |
3/6✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 29 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 29 times.
|
29 | else if (!getUInt("prio", u) || u > 7) { |
230 | log_debug("Invalid priority in message"); | ||
231 | ✗ | return false; | |
232 | } | ||
233 | else | ||
234 | 29 | msg.level = static_cast<PdCom::LogLevel>(u); | |
235 | 31 | return true; | |
236 | } | ||
237 | |||
238 | 5 | bool getClientStatistics(PdCom::ClientStatistics &stats) | |
239 | { | ||
240 | 5 | const char *c = nullptr; | |
241 | 5 | unsigned count = 0; | |
242 | 5 | double d = 0.0; | |
243 | 5 | stats = {}; | |
244 | |||
245 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (getString("name", c)) { |
246 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | stats.name_ = c; |
247 | } | ||
248 | |||
249 | // yes, this is a typo. It is what it is. | ||
250 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (getString("apname", c)) { |
251 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | stats.application_name_ = c; |
252 | } | ||
253 | |||
254 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (getUInt("countin", count)) |
255 | 5 | stats.received_bytes_ = count; | |
256 | |||
257 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (getUInt("countout", count)) |
258 | 5 | stats.sent_bytes_ = count; | |
259 | |||
260 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | if (getDouble("connectedtime", d)) |
261 | 10 | stats.connected_time_ = | |
262 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | std::chrono::duration_cast<std::chrono::nanoseconds>( |
263 | 10 | std::chrono::duration<double>(d)); | |
264 | |||
265 | 5 | return true; | |
266 | } | ||
267 | |||
268 | const char **atts; | ||
269 | }; /*}}}*/ | ||
270 | } // namespace | ||
271 | |||
272 | |||
273 | 157 | XmlStream::XmlStream(PdCom::impl::Process *process, std::streambuf *sb) : | |
274 | 157 | os(sb), process(process) | |
275 | { | ||
276 |
1/2✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
|
157 | os.exceptions(std::ios_base::badbit); |
277 | 157 | } | |
278 | 662 | void XmlStream::lock() | |
279 | { | ||
280 | 662 | process->transmitSemaphore(true); | |
281 | 662 | } | |
282 | 662 | void XmlStream::unlock() | |
283 | { | ||
284 | 662 | process->transmitSemaphore(false); | |
285 | 662 | } | |
286 | |||
287 | |||
288 | namespace { | ||
289 | struct XmlCommand | ||
290 | { /*{{{*/ | ||
291 | struct Attribute | ||
292 | { | ||
293 | // Create an attribute for a command. | ||
294 | Attribute(XmlCommand &command, const char *name) : cout(command.cout) | ||
295 | { | ||
296 | // send the preamble | ||
297 | cout << ' ' << name << "=\""; | ||
298 | } | ||
299 | ~Attribute() noexcept(false) { cout << '"'; } | ||
300 | |||
301 | XmlStream &cout; | ||
302 | }; | ||
303 | |||
304 | 662 | XmlCommand(XmlStream &cout, const char *command) : | |
305 | 662 | cout(cout), guard(cout), p_flush(true) | |
306 | { | ||
307 |
2/4✓ Branch 3 taken 662 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 662 times.
✗ Branch 8 not taken.
|
662 | cout << '<' << command; |
308 | 662 | } | |
309 | |||
310 | 662 | ~XmlCommand() noexcept(false) | |
311 | 662 | { | |
312 |
1/2✓ Branch 3 taken 662 times.
✗ Branch 4 not taken.
|
662 | cout << ">\r\n"; |
313 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 662 times.
✓ Branch 3 taken 554 times.
✓ Branch 4 taken 108 times.
|
662 | if (p_flush) |
314 |
1/2✓ Branch 3 taken 554 times.
✗ Branch 4 not taken.
|
554 | cout.flush(); |
315 | 662 | } | |
316 | |||
317 | 485 | XmlCommand &addEscapedAttribute(const char *name, const std::string &str) | |
318 | { | ||
319 |
4/8✓ Branch 4 taken 485 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 485 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 485 times.
✗ Branch 14 not taken.
✓ Branch 18 taken 485 times.
✗ Branch 19 not taken.
|
485 | cout << ' ' << name << '=' << '"'; |
320 | |||
321 |
2/2✓ Branch 8 taken 5154 times.
✓ Branch 9 taken 476 times.
|
5630 | for (const char c : str) { |
322 |
5/5✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 5091 times.
|
5154 | switch (c) { |
323 | 18 | case '"': | |
324 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | cout << """; |
325 | 18 | break; | |
326 | 18 | case '<': | |
327 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | cout << "<"; |
328 | 18 | break; | |
329 | 18 | case '&': | |
330 |
1/2✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
|
18 | cout << "&"; |
331 | 18 | break; | |
332 | 9 | case '\0': | |
333 |
1/2✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | throw PdCom::InvalidArgument("Value must not contain NULL"); |
334 | 5091 | default: | |
335 |
1/2✓ Branch 3 taken 5091 times.
✗ Branch 4 not taken.
|
5091 | cout << c; |
336 | } | ||
337 | } | ||
338 | |||
339 |
1/2✓ Branch 4 taken 476 times.
✗ Branch 5 not taken.
|
476 | cout << '"'; |
340 | |||
341 | 476 | return *this; | |
342 | } | ||
343 | |||
344 | template <typename T> | ||
345 | 791 | XmlCommand &addAttribute(const char *name, T const &val, bool active = true) | |
346 | { | ||
347 |
8/16✓ Branch 0 taken 48 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 52 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 66 times.
✓ Branch 5 taken 31 times.
✓ Branch 6 taken 243 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 142 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 59 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 150 times.
✗ Branch 15 not taken.
|
791 | if (active) |
348 |
35/80✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 48 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 48 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 48 times.
✗ Branch 17 not taken.
✓ Branch 21 taken 48 times.
✗ Branch 22 not taken.
✓ Branch 31 taken 52 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 52 times.
✗ Branch 36 not taken.
✓ Branch 39 taken 52 times.
✗ Branch 40 not taken.
✓ Branch 43 taken 52 times.
✗ Branch 44 not taken.
✓ Branch 48 taken 52 times.
✗ Branch 49 not taken.
✓ Branch 58 taken 66 times.
✗ Branch 59 not taken.
✓ Branch 62 taken 66 times.
✗ Branch 63 not taken.
✓ Branch 66 taken 66 times.
✗ Branch 67 not taken.
✓ Branch 70 taken 66 times.
✗ Branch 71 not taken.
✓ Branch 75 taken 66 times.
✗ Branch 76 not taken.
✓ Branch 85 taken 243 times.
✗ Branch 86 not taken.
✓ Branch 89 taken 243 times.
✗ Branch 90 not taken.
✓ Branch 93 taken 243 times.
✗ Branch 94 not taken.
✓ Branch 97 taken 243 times.
✗ Branch 98 not taken.
✓ Branch 102 taken 243 times.
✗ Branch 103 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✓ Branch 139 taken 142 times.
✗ Branch 140 not taken.
✓ Branch 143 taken 142 times.
✗ Branch 144 not taken.
✓ Branch 147 taken 142 times.
✗ Branch 148 not taken.
✓ Branch 151 taken 142 times.
✗ Branch 152 not taken.
✓ Branch 156 taken 142 times.
✗ Branch 157 not taken.
✓ Branch 166 taken 59 times.
✗ Branch 167 not taken.
✓ Branch 170 taken 59 times.
✗ Branch 171 not taken.
✓ Branch 174 taken 59 times.
✗ Branch 175 not taken.
✓ Branch 178 taken 59 times.
✗ Branch 179 not taken.
✓ Branch 183 taken 59 times.
✗ Branch 184 not taken.
✓ Branch 193 taken 150 times.
✗ Branch 194 not taken.
✓ Branch 197 taken 150 times.
✗ Branch 198 not taken.
✓ Branch 201 taken 150 times.
✗ Branch 202 not taken.
✓ Branch 205 taken 150 times.
✗ Branch 206 not taken.
✓ Branch 210 taken 150 times.
✗ Branch 211 not taken.
|
760 | cout << ' ' << name << "=\"" << val << '"'; |
349 | 791 | return *this; | |
350 | } | ||
351 | |||
352 | template <typename T> | ||
353 | 43 | XmlCommand &addAttributeStream(const char *name, T &&callback) | |
354 | { | ||
355 |
3/6✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 43 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 43 times.
✗ Branch 13 not taken.
|
43 | cout << ' ' << name << "=\""; |
356 | 43 | callback(cout); | |
357 |
1/2✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
|
43 | cout << '"'; |
358 | 43 | return *this; | |
359 | } | ||
360 | |||
361 | 108 | XmlCommand &noFlush() | |
362 | { | ||
363 | 108 | p_flush = false; | |
364 | 108 | return *this; | |
365 | } | ||
366 | |||
367 | 445 | XmlCommand &setId(const char *id) | |
368 | { | ||
369 |
2/4✓ Branch 0 taken 445 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 445 times.
✗ Branch 4 not taken.
|
445 | if (id and *id) |
370 |
1/2✓ Branch 8 taken 445 times.
✗ Branch 9 not taken.
|
445 | cout << " id=\"" << id << '"'; |
371 | |||
372 | 445 | return *this; | |
373 | } | ||
374 | |||
375 | XmlStream &cout; | ||
376 | std::lock_guard<XmlStream> guard; | ||
377 | bool p_flush; | ||
378 | }; /*}}}*/ | ||
379 | } // namespace | ||
380 | |||
381 | /////////////////////////////////////////////////////////////////////////// | ||
382 | 157 | ProtocolHandler::ProtocolHandler(PdCom::impl::Process *process, IOLayer *io) : | |
383 | PdCom::impl::ProtocolHandler(process), | ||
384 | StreambufLayer(io), | ||
385 | ExpatWrapper<ProtocolHandler, true>(), | ||
386 | cout(process, this), | ||
387 | root(std::make_shared<DirNode>()), | ||
388 |
11/22✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 157 times.
✗ Branch 9 not taken.
✓ Branch 28 taken 157 times.
✗ Branch 29 not taken.
✓ Branch 32 taken 157 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 157 times.
✗ Branch 37 not taken.
✓ Branch 43 taken 157 times.
✗ Branch 44 not taken.
✓ Branch 56 taken 157 times.
✗ Branch 57 not taken.
✓ Branch 60 taken 157 times.
✗ Branch 61 not taken.
✓ Branch 79 taken 157 times.
✗ Branch 80 not taken.
✓ Branch 87 taken 157 times.
✗ Branch 88 not taken.
✓ Branch 94 taken 157 times.
✗ Branch 95 not taken.
|
157 | channel_subscriptions_(new ChannelSubscriptionsWithGroup()) |
389 | { /*{{{*/ | ||
390 | |||
391 | #if PDC_DEBUG | ||
392 | { | ||
393 | char *spy = getenv("SPY"); | ||
394 | if (spy and atoi(spy)) | ||
395 | insert(new SpyLayer(io)); | ||
396 | } | ||
397 | #endif | ||
398 | |||
399 | 157 | const char buf[] = "<xml>"; | |
400 |
1/2✓ Branch 3 taken 157 times.
✗ Branch 4 not taken.
|
157 | ExpatBuffer<sizeof(buf)> inputBuf(*this); |
401 | 157 | std::memcpy(inputBuf.fill(), buf, sizeof(buf)); | |
402 |
2/4✓ Branch 6 taken 157 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 157 times.
|
157 | if (!parse(std::move(inputBuf), sizeof(buf) - 1, false)) |
403 | ✗ | throw Exception("setting up xml parser failed"); | |
404 | 157 | } /*}}}*/ | |
405 | |||
406 | /////////////////////////////////////////////////////////////////////////// | ||
407 | 312 | ProtocolHandler::~ProtocolHandler() | |
408 | { /*{{{*/ | ||
409 | log_debug("killed %p", static_cast<void *>(this)); | ||
410 | 312 | } /*}}}*/ | |
411 | |||
412 | /////////////////////////////////////////////////////////////////////////// | ||
413 | ✗ | void ProtocolHandler::xmlError(const char *err_msg) | |
414 | { /*{{{*/ | ||
415 | ✗ | if (state != StartUp and state != WaitForConnected) | |
416 | ✗ | throw ProtocolError(std::string("Fatal XML parsing error: ") + err_msg); | |
417 | ✗ | } /*}}}*/ | |
418 | |||
419 | #if PDC_DEBUG | ||
420 | const char *statename[] = { | ||
421 | "StartUp", | ||
422 | "Idle", | ||
423 | "GetListing", | ||
424 | "WaitForConnected", | ||
425 | }; | ||
426 | #endif | ||
427 | |||
428 | namespace { | ||
429 | constexpr const char *message_tags[] = { | ||
430 | "crit_error", "error", "warn", "info", "reset", | ||
431 | }; | ||
432 | |||
433 | 32 | bool is_message_tag(const char *name) | |
434 | { | ||
435 |
1/2✓ Branch 0 taken 82 times.
✗ Branch 1 not taken.
|
82 | for (const auto t : message_tags) { |
436 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 82 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 50 times.
|
82 | if (!strcmp(name, t)) |
437 | 32 | return true; | |
438 | } | ||
439 | ✗ | return false; | |
440 | } | ||
441 | } // namespace | ||
442 | |||
443 | /////////////////////////////////////////////////////////////////////////// | ||
444 | 2811 | void ProtocolHandler::startElement(const char *name, const char **atts) | |
445 | { /*{{{*/ | ||
446 | 2811 | const char *id = nullptr; | |
447 | |||
448 |
11/13✗ Branch 3 not taken.
✓ Branch 4 taken 2811 times.
✓ Branch 5 taken 157 times.
✓ Branch 6 taken 155 times.
✓ Branch 7 taken 85 times.
✓ Branch 8 taken 1206 times.
✓ Branch 9 taken 293 times.
✓ Branch 10 taken 846 times.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 42 times.
✓ Branch 13 taken 18 times.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
|
2811 | switch (state) { |
449 | 157 | case StartUp: | |
450 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
✓ Branch 2 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 157 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 157 times.
✗ Branch 9 not taken.
|
157 | if (!strcmp(name, "xml") and level() == 1) |
451 | 157 | state = WaitForConnected; | |
452 | 157 | break; | |
453 | |||
454 | 155 | case WaitForConnected: | |
455 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 155 times.
✓ Branch 2 taken 155 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 155 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 155 times.
✗ Branch 9 not taken.
|
155 | if (!strcmp(name, "connected") and level() == 2) { |
456 | 155 | Attribute a(atts); | |
457 | 155 | feature = a.find("features"); | |
458 |
1/2✓ Branch 3 taken 155 times.
✗ Branch 4 not taken.
|
155 | m_name = a.find("app"); |
459 |
1/2✓ Branch 3 taken 155 times.
✗ Branch 4 not taken.
|
155 | m_version = a.find("appversion"); |
460 | |||
461 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 155 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 145 times.
|
155 | if (!feature.group) |
462 | 20 | channel_subscriptions_.reset( | |
463 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
10 | new ChannelSubscriptionsWithoutGroup()); |
464 | |||
465 | // if login is mandatory, <saslauth> is sent automatically by | ||
466 | // server | ||
467 |
8/10✗ Branch 3 not taken.
✓ Branch 4 taken 155 times.
✓ Branch 5 taken 145 times.
✓ Branch 6 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 145 times.
✓ Branch 10 taken 28 times.
✓ Branch 11 taken 117 times.
✓ Branch 12 taken 28 times.
✓ Branch 13 taken 127 times.
|
155 | if (feature.login and !strcmp(a.find("login"), "mandatory")) { |
468 |
2/2✓ Branch 12 taken 27 times.
✓ Branch 13 taken 1 times.
|
28 | if (process->auth_manager_) { |
469 | 27 | state = WaitForLogin; | |
470 | 27 | break; | |
471 | } | ||
472 | else | ||
473 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | throw LoginRequired(); |
474 | } | ||
475 |
2/4✓ Branch 2 taken 127 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 127 times.
✗ Branch 6 not taken.
|
254 | XmlCommand(cout, "remote_host") |
476 |
1/2✓ Branch 3 taken 127 times.
✗ Branch 4 not taken.
|
254 | .addAttribute("access", "allow") |
477 | .addEscapedAttribute( | ||
478 |
2/4✓ Branch 6 taken 127 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 127 times.
✗ Branch 11 not taken.
|
254 | "applicationname", process->applicationName()) |
479 |
2/4✓ Branch 6 taken 127 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 127 times.
✗ Branch 11 not taken.
|
254 | .addEscapedAttribute("hostname", process->hostname()) |
480 |
1/2✓ Branch 2 taken 127 times.
✗ Branch 3 not taken.
|
127 | .setId("init"); |
481 | |||
482 |
2/2✓ Branch 4 taken 127 times.
✓ Branch 5 taken 27 times.
|
127 | state = Idle; |
483 | } | ||
484 | 127 | break; | |
485 | |||
486 | 85 | case WaitForLogin: | |
487 |
4/6✗ Branch 2 not taken.
✓ Branch 3 taken 85 times.
✓ Branch 4 taken 85 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 23 times.
✓ Branch 7 taken 62 times.
|
255 | if (level() == 2 and !strcmp(name, "saslauth") |
488 |
3/4✓ Branch 0 taken 85 times.
✗ Branch 1 not taken.
✓ Branch 6 taken 23 times.
✓ Branch 7 taken 62 times.
|
170 | and processLogin(atts)) { |
489 |
1/2✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
|
46 | XmlCommand(cout, "remote_host") |
490 |
1/2✓ Branch 3 taken 23 times.
✗ Branch 4 not taken.
|
46 | .addAttribute("access", "allow") |
491 | .addEscapedAttribute( | ||
492 |
2/4✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 23 times.
✗ Branch 11 not taken.
|
46 | "applicationname", process->applicationName()) |
493 |
2/4✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 23 times.
✗ Branch 11 not taken.
|
46 | .addEscapedAttribute("hostname", process->hostname()) |
494 |
1/2✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
|
23 | .setId("init"); |
495 | |||
496 | 23 | state = Idle; | |
497 | } | ||
498 | 85 | break; | |
499 | |||
500 | 1206 | case Idle: | |
501 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1206 times.
|
1206 | if (level() != 2) { |
502 | log_debug("Unknown XML tag in Idle: %s", name); | ||
503 | ✗ | break; | |
504 | } | ||
505 | |||
506 | // find() returns "" if id is not found | ||
507 | 1206 | id = Attribute(atts).find("id"); | |
508 | |||
509 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1206 times.
✓ Branch 2 taken 385 times.
✓ Branch 3 taken 821 times.
|
1206 | if (!strcmp(name, "data")) { |
510 | 385 | Attribute a(atts); | |
511 | |||
512 | 385 | unsigned int dataGroupId = 0; | |
513 | 385 | a.getUInt("group", dataGroupId); | |
514 | |||
515 |
1/2✓ Branch 2 taken 385 times.
✗ Branch 3 not taken.
|
385 | dataTime = a.getTime_ns("time"); |
516 | |||
517 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 385 times.
✓ Branch 5 taken 42 times.
✓ Branch 6 taken 343 times.
|
385 | if (!feature.group) { |
518 | 42 | state = ReadDataOrEvent; | |
519 | } | ||
520 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 341 times.
|
343 | else if (!dataGroupId) { |
521 | // Attribute "group" not found. Event transmission | ||
522 | 2 | state = ReadEvent; | |
523 | } | ||
524 | else { | ||
525 | 341 | periodic_receive_handle_ = | |
526 |
1/2✓ Branch 4 taken 341 times.
✗ Branch 5 not taken.
|
1364 | channel_subscriptions_->startNewDataRecieving( |
527 |
1/2✓ Branch 1 taken 341 times.
✗ Branch 2 not taken.
|
682 | dataGroupId, variable_cache_.lock(), |
528 | 1023 | dataTime); | |
529 | 341 | state = ReadData; | |
530 | } | ||
531 | } | ||
532 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 821 times.
✓ Branch 2 taken 133 times.
✓ Branch 3 taken 688 times.
|
821 | else if (!strcmp(name, "pu")) { |
533 | 133 | unsigned int index; | |
534 | |||
535 |
5/10✗ Branch 3 not taken.
✓ Branch 4 taken 133 times.
✓ Branch 5 taken 133 times.
✗ Branch 6 not taken.
✓ Branch 11 taken 133 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 133 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 133 times.
✗ Branch 17 not taken.
|
133 | if (!feature.xsap and Attribute(atts).getUInt("index", index)) { |
536 |
3/4✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✓ Branch 6 taken 100 times.
|
399 | if (parameter_event_.find(index) |
537 | 399 | != parameter_event_.end()) { | |
538 |
1/2✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
|
33 | pollParameter(index, "pollParameterEvent"); |
539 | } | ||
540 | } | ||
541 | } | ||
542 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 688 times.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 611 times.
|
688 | else if (!strcmp(name, "parameter")) { |
543 | 77 | Parameter *p = getParameter(atts); | |
544 |
1/2✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
|
77 | if (p) { |
545 | 77 | Attribute a(atts); | |
546 |
1/2✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
|
77 | const auto time_ns = a.getTime_ns("mtime"); |
547 | 77 | unsigned int pm; | |
548 | 203 | const auto getValue = [&a, p, this]() { | |
549 | 42 | auto cache = variable_cache_.lock(); | |
550 | 42 | const char *const hexvalue = a.find("hexvalue"); | |
551 |
2/4✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
|
42 | if (hexvalue && *hexvalue) |
552 |
2/4✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 42 times.
✗ Branch 7 not taken.
|
84 | cache[0].readFromHexDec(hexvalue, *p); |
553 | else | ||
554 | ✗ | cache[0].readFromString(a.find("value"), *p); | |
555 | 42 | return cache; | |
556 | 77 | }; | |
557 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 71 times.
|
154 | if (!strcmp(id, "pollParameter") |
558 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 71 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
77 | and !subscription_pending_parameter_polls_.empty()) { |
559 | 6 | auto sub_collection = std::move( | |
560 | 12 | subscription_pending_parameter_polls_.front()); | |
561 | 6 | subscription_pending_parameter_polls_.pop_front(); | |
562 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | sub_collection.subscriptions_.readData( |
563 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
12 | getValue()[0].data(), time_ns); |
564 | } | ||
565 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 68 times.
|
71 | else if (!strcmp(id, "VariablePollParameter")) { |
566 |
1/2✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
|
6 | variable_pending_polls_.processResult( |
567 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
6 | *p, getValue()[0].data(), time_ns); |
568 | } | ||
569 |
1/2✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
|
68 | else if ( |
570 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 68 times.
|
68 | !feature.xsap |
571 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 35 times.
|
68 | and !strcmp(id, "pollParameterEvent")) { |
572 |
2/4✓ Branch 3 taken 33 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 33 times.
✗ Branch 8 not taken.
|
99 | parameter_event_[p->index_].readData( |
573 |
2/4✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
|
66 | getValue()[0].data(), time_ns); |
574 | } | ||
575 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 30 times.
|
35 | else if (!strcmp(id, "pendingParameter")) |
576 |
1/2✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | pendingAck(p); |
577 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
|
30 | else if (a.getUInt("pm", pm) && pm == 1) { |
578 | ✗ | parameter_event_[p->index_].readData( | |
579 | ✗ | getValue()[0].data(), time_ns); | |
580 | } | ||
581 | } | ||
582 | } | ||
583 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 611 times.
✓ Branch 2 taken 61 times.
✓ Branch 3 taken 550 times.
|
611 | else if (!strcmp(name, "channel")) { |
584 | 61 | Channel *c = getChannel(atts); | |
585 |
1/2✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
|
61 | if (c) { |
586 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 54 times.
|
122 | if (!strcmp(id, "pollChannel") |
587 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 54 times.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
61 | and !subscription_pending_channel_polls_.empty()) { |
588 | // can be nullptr if subscription was deleted in the | ||
589 | // meantime | ||
590 | 7 | auto channel_poll = std::move( | |
591 | 14 | subscription_pending_channel_polls_.front()); | |
592 | 7 | subscription_pending_channel_polls_.pop_front(); | |
593 | 7 | Attribute a(atts); | |
594 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
14 | auto cache = variable_cache_.lock(); |
595 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | if (const auto s = a.find("hexvalue", nullptr)) |
596 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
|
7 | cache[0].readFromHexDec(s, *c); |
597 | else | ||
598 | ✗ | cache[0].readFromString(a.find("value"), *c); | |
599 |
2/4✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
14 | channel_poll.subscriptions_.readData( |
600 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | cache[0].data(), a.getTime_ns("time")); |
601 | } | ||
602 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
|
54 | else if (!strcmp(id, "VariablePollChannel")) { |
603 | ✗ | Attribute a(atts); | |
604 | ✗ | auto cache = variable_cache_.lock(); | |
605 | ✗ | if (const auto s = a.find("hexvalue", nullptr)) | |
606 | ✗ | cache[0].readFromHexDec(s, *c); | |
607 | else | ||
608 | ✗ | cache[0].readFromString(a.find("value"), *c); | |
609 | ✗ | variable_pending_polls_.processResult( | |
610 | ✗ | *c, cache[0].data(), a.getTime_ns("time")); | |
611 | } | ||
612 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 33 times.
|
54 | else if (!strcmp(id, "pendingChannel")) |
613 | 21 | pendingAck(c); | |
614 | } | ||
615 | } | ||
616 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 550 times.
✓ Branch 2 taken 435 times.
✓ Branch 3 taken 115 times.
|
550 | else if (!strcmp(name, "ack")) { |
617 | // Check which ack was called | ||
618 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 387 times.
|
435 | if (!strcmp(id, ChannelSubscriptions::xsadId)) |
619 | 48 | channel_subscriptions_->xsadAck(process); | |
620 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 387 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 387 times.
|
387 | else if (!strcmp(id, "xsapQ")) |
621 | ✗ | xsapAck(); | |
622 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 387 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 387 times.
|
387 | else if (!strcmp(id, ChannelSubscriptions::xsodId)) |
623 | ✗ | channel_subscriptions_->xsodAck(); | |
624 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 387 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 361 times.
|
387 | else if (!strcmp(id, "pendingChannel")) |
625 | 26 | pendingAck(nullptr); | |
626 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 361 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 289 times.
|
361 | else if (!strcmp(id, "findQ")) |
627 | 72 | processFindRequest(); | |
628 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 289 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 281 times.
|
289 | else if (!strcmp(id, "listQ")) { |
629 | 8 | fullListing = Cached; | |
630 | |||
631 | // Process all pending list and find requests | ||
632 |
1/2✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
|
8 | while (processListRequest()) |
633 | ; | ||
634 |
1/2✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
|
8 | while (processFindRequest()) |
635 | ; | ||
636 | } | ||
637 |
6/8✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 266 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 266 times.
|
281 | else if (!strcmp(id, "history") and !seqNoQ.empty()) { |
638 |
2/2✓ Branch 6 taken 9 times.
✓ Branch 7 taken 6 times.
|
15 | if (messageSeqNo != seqNoQ.front()) { |
639 | 18 | PdCom::Message m = {}; | |
640 |
1/2✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
9 | m.seqNo = seqNoQ.front(); |
641 |
2/4✓ Branch 17 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 9 times.
✗ Branch 21 not taken.
|
9 | process->getMessageReply(m); |
642 | } | ||
643 | 15 | seqNoQ.pop(); | |
644 | } | ||
645 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 266 times.
✓ Branch 2 taken 149 times.
✓ Branch 3 taken 117 times.
|
266 | else if (!strcmp(id, "init")) |
646 | 149 | process->connected(); | |
647 | } | ||
648 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 10 times.
|
115 | else if ( |
649 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 105 times.
✓ Branch 4 taken 97 times.
✓ Branch 5 taken 8 times.
|
220 | !strcmp(name, "listing") or !strcmp(name, "channels") |
650 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 97 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 89 times.
|
97 | or !strcmp(name, "parameters")) { |
651 | 26 | state = GetListing; | |
652 | } | ||
653 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 83 times.
|
89 | else if (!strcmp(name, "saslauth")) |
654 | 6 | processLogin(atts); | |
655 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 80 times.
|
83 | else if (!strcmp(name, "ping")) |
656 | 3 | process->pingReply(); | |
657 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 58 times.
|
80 | else if (!strcmp(name, "broadcast")) |
658 | 22 | processBroadcast(atts); | |
659 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 37 times.
|
58 | else if (!strcmp(name, "message_history")) |
660 | 21 | state = GetActiveMessages; | |
661 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 32 times.
|
37 | else if (!strcmp(name, "clients")) { |
662 | 5 | state = ReadClientStatistics; | |
663 | 5 | client_statistics.clear(); | |
664 | } | ||
665 |
3/6✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 15 taken 32 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 32 times.
✗ Branch 18 not taken.
|
32 | else if (is_message_tag(name) and process->message_manager_) { |
666 | 64 | PdCom::Message msg = {}; | |
667 | 32 | Attribute a(atts); | |
668 |
3/6✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
|
32 | if (a.getMessage(name, msg, feature.history)) { |
669 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 26 times.
|
32 | if (!strcmp(id, "history")) { |
670 | 6 | messageSeqNo = msg.seqNo; | |
671 |
1/2✓ Branch 20 taken 6 times.
✗ Branch 21 not taken.
|
6 | process->getMessageReply(std::move(msg)); |
672 | } | ||
673 | else { | ||
674 |
1/2✓ Branch 20 taken 26 times.
✗ Branch 21 not taken.
|
26 | process->processMessage(std::move(msg)); |
675 | } | ||
676 | } | ||
677 | else { | ||
678 | log_debug("Failed to parse message"); | ||
679 | } | ||
680 | } | ||
681 | 1206 | break; | |
682 | |||
683 | 293 | case GetListing: | |
684 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 293 times.
|
293 | if (level() != 3) { |
685 | log_debug("Unknown XML tag in GetListing: %s", name); | ||
686 | ✗ | break; | |
687 | } | ||
688 | |||
689 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 293 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 288 times.
|
293 | if (!strcmp(name, "dir")) { |
690 | 5 | const char *path; | |
691 |
2/6✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
10 | if (Attribute(atts).getString("path", path) |
692 |
10/32✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 17 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 5 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 5 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 5 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 5 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
|
10 | and !root->find(path)) { |
693 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
5 | DirNode *node = new DirNode; |
694 |
2/4✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 14 not taken.
|
5 | root->insert(std::unique_ptr<DirNode>(node), path); |
695 | log_debug("Create dir %s", node->path().c_str()); | ||
696 | } | ||
697 | } | ||
698 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 149 times.
✓ Branch 3 taken 139 times.
|
288 | else if (!strcmp(name, "channel")) |
699 | 149 | getChannel(atts); | |
700 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 139 times.
✓ Branch 2 taken 139 times.
✗ Branch 3 not taken.
|
139 | else if (!strcmp(name, "parameter")) |
701 | 139 | getParameter(atts); | |
702 | 293 | break; | |
703 | |||
704 | 846 | case ReadData: | |
705 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 846 times.
|
846 | if (level() != 3) { |
706 | log_debug("Unknown XML tag in ReadData: %s", name); | ||
707 | ✗ | break; | |
708 | } | ||
709 | |||
710 | 846 | readPeriodicData(name, atts); | |
711 | |||
712 | 846 | break; | |
713 | |||
714 | 4 | case ReadEvent: | |
715 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (level() != 3) { |
716 | log_debug("Unknown XML tag in ReadEvent: %s", name); | ||
717 | ✗ | break; | |
718 | } | ||
719 | |||
720 | 4 | readEventData(name, atts); | |
721 | |||
722 | 4 | break; | |
723 | |||
724 | 42 | case ReadDataOrEvent: | |
725 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
|
42 | if (level() != 3) { |
726 | log_debug("Unknown XML tag in ReadDataOrEvent: %s", name); | ||
727 | ✗ | break; | |
728 | } | ||
729 | |||
730 |
1/2✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
42 | if (name[0] == 'F') { |
731 | 42 | state = ReadData; | |
732 | 42 | periodic_receive_handle_ = | |
733 |
1/2✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
|
168 | channel_subscriptions_->startNewDataRecieving( |
734 | 210 | 0, variable_cache_.lock(), dataTime); | |
735 | 42 | readPeriodicData(name, atts); | |
736 | } | ||
737 | ✗ | else if (name[0] == 'E') { | |
738 | ✗ | state = ReadEvent; | |
739 | ✗ | readEventData(name, atts); | |
740 | } | ||
741 | |||
742 | 42 | break; | |
743 | 18 | case GetActiveMessages: | |
744 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
|
18 | if (level() != 3) { |
745 | log_debug("Unknown XML tag in GetActiveMessages: %s", name); | ||
746 | ✗ | break; | |
747 | } | ||
748 | |||
749 | { | ||
750 | 36 | Message msg; | |
751 |
2/4✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
|
18 | if (Attribute(atts).getMessage(name, msg, true)) { |
752 |
1/2✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
18 | messageList.push_back(std::move(msg)); |
753 | 18 | } | |
754 | } | ||
755 | 18 | break; | |
756 | |||
757 | 5 | case ReadClientStatistics: | |
758 |
4/8✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
|
5 | if (level() != 3 or strcmp(name, "client")) { |
759 | log_debug("Unknown XML tag in ReadClientStatistics: %s", name); | ||
760 | ✗ | break; | |
761 | } | ||
762 | |||
763 | { | ||
764 | 10 | PdCom::ClientStatistics stats; | |
765 |
2/4✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
|
5 | if (Attribute(atts).getClientStatistics(stats)) { |
766 |
1/2✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
5 | client_statistics.push_back(std::move(stats)); |
767 | } | ||
768 | else { | ||
769 | log_debug("Drop incomplete <client> tag"); | ||
770 | 5 | } | |
771 | } | ||
772 | 5 | break; | |
773 | |||
774 | ✗ | default: | |
775 | ✗ | break; | |
776 | }; | ||
777 | 2810 | } /*}}}*/ | |
778 | |||
779 | /////////////////////////////////////////////////////////////////////////// | ||
780 | 2653 | void ProtocolHandler::endElement(const char *name) | |
781 | { /*{{{*/ | ||
782 |
7/8✗ Branch 3 not taken.
✓ Branch 4 taken 2653 times.
✓ Branch 5 taken 319 times.
✓ Branch 6 taken 1271 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 39 times.
✓ Branch 9 taken 10 times.
✓ Branch 10 taken 1008 times.
|
2653 | switch (state) { |
783 | 319 | case GetListing: | |
784 |
2/2✓ Branch 2 taken 26 times.
✓ Branch 3 taken 293 times.
|
319 | if (level() == 2) { |
785 | 26 | state = Idle; | |
786 | |||
787 | // name is either | ||
788 | // - channels | ||
789 | // - parameters | ||
790 | // - listing | ||
791 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 16 times.
|
26 | if (!strcmp(name, "listing")) |
792 | 10 | processListRequest(); | |
793 | } | ||
794 | |||
795 | 319 | break; | |
796 | |||
797 | 1271 | case ReadData: | |
798 |
6/8✓ Branch 2 taken 383 times.
✓ Branch 3 taken 888 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 383 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 383 times.
✓ Branch 8 taken 888 times.
✓ Branch 9 taken 383 times.
|
1271 | if (level() != 2 or strcmp(name, "data")) |
799 | 888 | break; | |
800 |
1/2✓ Branch 2 taken 383 times.
✗ Branch 3 not taken.
|
383 | if (periodic_receive_handle_) { |
801 | 383 | periodic_receive_handle_.endNewDataRecieving(); | |
802 | 383 | periodic_receive_handle_ = {}; | |
803 | } | ||
804 | 383 | state = Idle; | |
805 | 383 | break; | |
806 | |||
807 | 6 | case ReadEvent: | |
808 | case ReadDataOrEvent: | ||
809 |
6/8✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 4 times.
|
6 | if (level() == 2 and !strcmp(name, "data")) { |
810 | 2 | state = Idle; | |
811 | } | ||
812 | 6 | break; | |
813 | |||
814 | 39 | case GetActiveMessages: | |
815 |
6/8✓ Branch 2 taken 21 times.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 21 times.
✓ Branch 9 taken 18 times.
|
39 | if (level() == 2 and !strcmp(name, "message_history")) { |
816 | 21 | state = Idle; | |
817 |
1/2✓ Branch 21 taken 21 times.
✗ Branch 22 not taken.
|
21 | process->activeMessagesReply(std::move(messageList)); |
818 | 21 | messageList.clear(); | |
819 | } | ||
820 | 39 | break; | |
821 | |||
822 | 10 | case ReadClientStatistics: | |
823 |
6/8✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 5 times.
|
10 | if (level() == 2 and !strcmp(name, "clients")) { |
824 | 5 | state = Idle; | |
825 |
1/2✓ Branch 21 taken 5 times.
✗ Branch 22 not taken.
|
5 | process->clientStatisticsReply(std::move(client_statistics)); |
826 | 5 | client_statistics.clear(); | |
827 | } | ||
828 | 10 | break; | |
829 | |||
830 | 1008 | default: | |
831 | 1008 | break; | |
832 | } | ||
833 | 2653 | } /*}}}*/ | |
834 | |||
835 | /////////////////////////////////////////////////////////////////////////// | ||
836 | // Arguments: | ||
837 | // var: if var == 0, this is a test to check whether path was found | ||
838 | // if var != 0, found the variable --> subscribe it | ||
839 | 52 | void ProtocolHandler::pendingAck(Variable *var) | |
840 | { /*{{{*/ | ||
841 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 52 times.
|
52 | if (pending_queue_.empty()) |
842 | ✗ | throw ProtocolError("Empty pending request queue"); | |
843 | |||
844 |
2/2✓ Branch 8 taken 52 times.
✓ Branch 9 taken 52 times.
|
104 | for (const auto &weak_sub : pending_queue_.front().subscriptions_) { |
845 |
2/2✓ Branch 4 taken 26 times.
✓ Branch 5 taken 26 times.
|
78 | auto ps = weak_sub.lock(); |
846 |
2/2✓ Branch 1 taken 26 times.
✓ Branch 2 taken 26 times.
|
52 | if (!ps) |
847 | 26 | continue; | |
848 | |||
849 |
2/2✓ Branch 3 taken 26 times.
✓ Branch 4 taken 26 times.
|
52 | std::shared_ptr<PdCom::impl::Subscription> new_sub; |
850 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | if (var) { |
851 |
1/2✓ Branch 11 taken 26 times.
✗ Branch 12 not taken.
|
182 | new_sub = subscribe( |
852 | 26 | ps->This_, | |
853 | 78 | std::static_pointer_cast<const MsrProto::Variable>( | |
854 |
1/2✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
|
52 | var->shared_from_this()), |
855 | 130 | ps->subscriber_, ps->getSelector(), false); | |
856 | } | ||
857 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
|
26 | if (!new_sub) { |
858 | ✗ | new_sub = std::make_shared<InvalidSubscription>( | |
859 | ✗ | ps->This_, ps->subscriber_, process->shared_from_this()); | |
860 | ✗ | process->pending_callbacks_.push_back( | |
861 | {new_sub, PdCom::Subscription::State::Invalid}); | ||
862 | } | ||
863 |
1/2✓ Branch 19 taken 26 times.
✗ Branch 20 not taken.
|
26 | process->replace(ps, new_sub); |
864 |
1/2✓ Branch 9 taken 26 times.
✗ Branch 10 not taken.
|
26 | ps->replaceImpl(std::move(new_sub)); |
865 | } | ||
866 | |||
867 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 26 times.
|
52 | if (!var) { |
868 | // End of processing; clean up structures | ||
869 | 26 | pending_queue_.pop_front(); | |
870 | } | ||
871 | 52 | } /*}}}*/ | |
872 | |||
873 | /////////////////////////////////////////////////////////////////////////// | ||
874 | ✗ | void ProtocolHandler::xsapAck() | |
875 | { /*{{{*/ | ||
876 | ✗ | if (xsapQ.empty()) | |
877 | ✗ | throw ProtocolError("no pending xsad commands available"); | |
878 | |||
879 | ✗ | auto map_it = parameter_event_.find(xsapQ.front()); | |
880 | ✗ | if (map_it != parameter_event_.end()) { | |
881 | ✗ | map_it->second.broadcastState( | |
882 | PdCom::Subscription::State::Active, | ||
883 | ✗ | process->pending_callbacks_); | |
884 | } | ||
885 | |||
886 | ✗ | xsapQ.pop(); | |
887 | ✗ | } /*}}}*/ | |
888 | |||
889 | /////////////////////////////////////////////////////////////////////////// | ||
890 | 216 | Parameter *ProtocolHandler::getParameter(const char **_atts) | |
891 | { /*{{{*/ | ||
892 | 216 | Attribute atts(_atts); | |
893 | 216 | unsigned index; | |
894 | |||
895 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 216 times.
|
216 | if (!atts.getUInt("index", index)) |
896 | ✗ | return 0; | |
897 | |||
898 |
1/2✓ Branch 2 taken 216 times.
✗ Branch 3 not taken.
|
216 | Parameter *¶m = parameter[index]; |
899 |
2/2✓ Branch 1 taken 174 times.
✓ Branch 2 taken 42 times.
|
216 | if (!param) { |
900 | // index="0" name="/Constant/Value" datasize="8" typ="TDBL_LIST" | ||
901 | // anz="10" cnum="10" rnum="1" orientation="VECTOR" flags="7" | ||
902 | 174 | const char *name = atts.find("name"); | |
903 | |||
904 | // Check index and name | ||
905 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
|
174 | if (!*name) { |
906 | log_debug("Missing index or name for variable. Ignoring"); | ||
907 | ✗ | return 0; | |
908 | } | ||
909 | |||
910 | // Check whether variable exists | ||
911 |
3/6✓ Branch 8 taken 174 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 174 times.
✗ Branch 13 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 174 times.
|
174 | if (std::dynamic_pointer_cast<Variable>(root->find(name))) { |
912 | log_debug("%s exists. Ignoring", name); | ||
913 | ✗ | return 0; | |
914 | } | ||
915 | |||
916 |
1/2✓ Branch 6 taken 174 times.
✗ Branch 7 not taken.
|
348 | SizeInfo size_info; |
917 |
1/2✓ Branch 2 taken 174 times.
✗ Branch 3 not taken.
|
174 | const auto type_info = getDataType(_atts, size_info); |
918 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
|
174 | if (!type_info) { |
919 | log_debug("Datatype for %s unspecified. Ignoring", name); | ||
920 | ✗ | return 0; | |
921 | } | ||
922 | |||
923 | 174 | unsigned int flags; | |
924 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 174 times.
|
174 | if (!atts.getUInt("flags", flags)) { |
925 | log_debug("Flags for %s unspecified. Ignoring", name); | ||
926 | ✗ | return 0; | |
927 | } | ||
928 | |||
929 | 174 | auto shared_param = std::make_shared<Parameter>( | |
930 |
1/2✓ Branch 4 taken 174 times.
✗ Branch 5 not taken.
|
522 | std::move(size_info), type_info, process->shared_from_this(), |
931 |
2/4✓ Branch 9 taken 174 times.
✗ Branch 10 not taken.
✓ Branch 16 taken 174 times.
✗ Branch 17 not taken.
|
870 | index, flags, atts.find("alias"), atts.isTrue("dir")); |
932 | 174 | param = shared_param.get(); | |
933 |
1/2✓ Branch 10 taken 174 times.
✗ Branch 11 not taken.
|
174 | root->insert(std::move(shared_param), name); |
934 | } | ||
935 | |||
936 | 216 | return param; | |
937 | } /*}}}*/ | ||
938 | |||
939 | /////////////////////////////////////////////////////////////////////////// | ||
940 | 210 | Channel *ProtocolHandler::getChannel(const char **_atts) | |
941 | { /*{{{*/ | ||
942 | 210 | Attribute atts(_atts); | |
943 | 210 | unsigned index; | |
944 | |||
945 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 210 times.
|
210 | if (!atts.getUInt("index", index)) |
946 | ✗ | return 0; | |
947 | |||
948 |
1/2✓ Branch 2 taken 210 times.
✗ Branch 3 not taken.
|
210 | Channel *&chan = channel[index]; |
949 |
2/2✓ Branch 1 taken 203 times.
✓ Branch 2 taken 7 times.
|
210 | if (!chan) { |
950 | // index="0" name="/Constant/Value" datasize="8" typ="TDBL_LIST" | ||
951 | // anz="10" cnum="10" rnum="1" orientation="VECTOR" flags="7" | ||
952 | 203 | const char *name = atts.find("name"); | |
953 | |||
954 | // Check index and name | ||
955 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 203 times.
|
203 | if (!*name) { |
956 | log_debug("Missing index or name for variable. Ignoring"); | ||
957 | ✗ | return 0; | |
958 | } | ||
959 | |||
960 | // Check whether variable exists | ||
961 |
3/6✓ Branch 8 taken 203 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 203 times.
✗ Branch 13 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 203 times.
|
203 | if (std::dynamic_pointer_cast<Variable>(root->find(name))) { |
962 | log_debug("%s exists. Ignoring", name); | ||
963 | ✗ | return 0; | |
964 | } | ||
965 | |||
966 |
1/2✓ Branch 8 taken 203 times.
✗ Branch 9 not taken.
|
406 | SizeInfo size_info; |
967 |
1/2✓ Branch 2 taken 203 times.
✗ Branch 3 not taken.
|
203 | const auto type_info = getDataType(_atts, size_info); |
968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 203 times.
|
203 | if (!type_info) { |
969 | log_debug("Datatype for %s unspecified. Ignoring", name); | ||
970 | ✗ | return 0; | |
971 | } | ||
972 | |||
973 | 203 | unsigned int bufsize; | |
974 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 203 times.
|
203 | if (!atts.getUInt("bufsize", bufsize)) { |
975 | log_debug("bufsize for %s unspecified. Ignoring", name); | ||
976 | ✗ | return 0; | |
977 | } | ||
978 | |||
979 | 203 | double freq; | |
980 |
3/6✓ Branch 1 taken 203 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 203 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 203 times.
|
203 | if (!atts.getDouble("HZ", freq) or !freq) { |
981 | log_debug("HZ for %s unspecified or zero. Ignoring", name); | ||
982 | ✗ | return 0; | |
983 | } | ||
984 | |||
985 | 203 | unsigned int taskId = 0; | |
986 | 203 | atts.getUInt("task", taskId); | |
987 | |||
988 | 203 | auto shared_chan = std::make_shared<Channel>( | |
989 |
1/2✓ Branch 4 taken 203 times.
✗ Branch 5 not taken.
|
609 | std::move(size_info), type_info, process->shared_from_this(), |
990 | 609 | index, taskId, 1.0 / freq, atts.find("alias"), bufsize, | |
991 |
2/4✓ Branch 10 taken 203 times.
✗ Branch 11 not taken.
✓ Branch 16 taken 203 times.
✗ Branch 17 not taken.
|
1421 | atts.isTrue("dir")); |
992 | 203 | chan = shared_chan.get(); | |
993 |
1/2✓ Branch 10 taken 203 times.
✗ Branch 11 not taken.
|
203 | root->insert(std::move(shared_chan), name); |
994 | } | ||
995 | |||
996 | 210 | return chan; | |
997 | } /*}}}*/ | ||
998 | |||
999 | namespace { | ||
1000 | struct TypeMap | ||
1001 | { | ||
1002 | const char *msr_name; | ||
1003 | const PdCom::TypeInfo *type_info; | ||
1004 | size_t len; | ||
1005 | template <size_t N> | ||
1006 | constexpr TypeMap(const char (&name)[N], PdCom::TypeInfo const &ti) : | ||
1007 | msr_name(&name[0]), type_info(&ti), len(N - 1) | ||
1008 | {} | ||
1009 | }; | ||
1010 | } // namespace | ||
1011 | |||
1012 | /////////////////////////////////////////////////////////////////////////// | ||
1013 | const PdCom::TypeInfo * | ||
1014 | 377 | ProtocolHandler::getDataType(const char **atts, PdCom::SizeInfo &size_info) | |
1015 | { /*{{{*/ | ||
1016 | 377 | unsigned int rnum = 0; | |
1017 | 377 | unsigned int cnum = 0; | |
1018 | 377 | unsigned int count = 0; | |
1019 | 377 | const char *orientation = 0; | |
1020 | using PdCom::SizeInfo; | ||
1021 | using PdCom::TypeInfo; | ||
1022 | 377 | const TypeInfo *ans = nullptr; | |
1023 | |||
1024 | static constexpr TypeMap type_map[] = { | ||
1025 | {"TDBL", details::TypeInfoTraits<double>::type_info}, | ||
1026 | {"TINT", details::TypeInfoTraits<int32_t>::type_info}, | ||
1027 | {"TUINT", details::TypeInfoTraits<uint32_t>::type_info}, | ||
1028 | {"TCHAR", details::TypeInfoTraits<int8_t>::type_info}, | ||
1029 | {"TUCHAR", details::TypeInfoTraits<uint8_t>::type_info}, | ||
1030 | {"TSHORT", details::TypeInfoTraits<int16_t>::type_info}, | ||
1031 | {"TUSHORT", details::TypeInfoTraits<uint16_t>::type_info}, | ||
1032 | {"TLINT", details::TypeInfoTraits<int64_t>::type_info}, | ||
1033 | {"TULINT", details::TypeInfoTraits<uint64_t>::type_info}, | ||
1034 | {"TFLT", details::TypeInfoTraits<float>::type_info}, | ||
1035 | }; | ||
1036 | |||
1037 | 377 | const char *const typeStr = Attribute(atts).find("typ"); | |
1038 | |||
1039 | // Try and find the name in msr_dtypemap | ||
1040 |
2/2✓ Branch 0 taken 3770 times.
✓ Branch 1 taken 377 times.
|
4147 | for (const auto &t : type_map) { |
1041 |
4/6✗ Branch 2 not taken.
✓ Branch 3 taken 3770 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3770 times.
✓ Branch 6 taken 377 times.
✓ Branch 7 taken 3393 times.
|
3770 | if (!strncmp(typeStr, t.msr_name, t.len)) |
1042 | 377 | ans = t.type_info; | |
1043 | } | ||
1044 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 377 times.
|
377 | if (!ans) |
1045 | ✗ | return nullptr; | |
1046 | |||
1047 | // cache variable data | ||
1048 |
2/2✓ Branch 1 taken 2940 times.
✓ Branch 2 taken 377 times.
|
3317 | for (int i = 0; atts[i]; i += 2) { |
1049 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 2940 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 2891 times.
|
2940 | if (!strcmp(atts[i], "rnum")) { |
1050 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
|
49 | rnum = atoi(atts[i + 1]); |
1051 | } | ||
1052 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 2891 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 2842 times.
|
2891 | else if (!strcmp(atts[i], "cnum")) { |
1053 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
|
49 | cnum = atoi(atts[i + 1]); |
1054 | } | ||
1055 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 2842 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 2793 times.
|
2842 | else if (!strcmp(atts[i], "anz")) { |
1056 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
|
49 | count = atoi(atts[i + 1]); |
1057 | } | ||
1058 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 2793 times.
✓ Branch 3 taken 49 times.
✓ Branch 4 taken 2744 times.
|
2793 | else if (!strcmp(atts[i], "orientation")) { |
1059 | 49 | orientation = atts[i + 1]; | |
1060 | } | ||
1061 | } | ||
1062 | |||
1063 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 328 times.
|
377 | if (orientation) { |
1064 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 17 times.
|
49 | if (!strcmp(orientation, "VECTOR")) { |
1065 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
32 | if (!count) |
1066 | ✗ | return nullptr; | |
1067 | |||
1068 | 32 | size_info = SizeInfo::RowVector(count); | |
1069 | } | ||
1070 |
3/6✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
|
17 | else if (orientation and !strncmp(orientation, "MATRIX", 6)) { |
1071 |
2/4✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
|
17 | if (!(rnum and cnum)) |
1072 | ✗ | return nullptr; | |
1073 | |||
1074 | 17 | size_info = SizeInfo::Matrix(rnum, cnum); | |
1075 | } | ||
1076 | else | ||
1077 | ✗ | return nullptr; | |
1078 | } | ||
1079 | else { | ||
1080 |
3/6✓ Branch 0 taken 328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 328 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 328 times.
|
328 | if (rnum > 1 or cnum > 1 or count > 1) |
1081 | ✗ | return nullptr; | |
1082 | |||
1083 | 328 | size_info = SizeInfo::Scalar(); | |
1084 | } | ||
1085 | |||
1086 | 377 | return ans; | |
1087 | } /*}}}*/ | ||
1088 | |||
1089 | /////////////////////////////////////////////////////////////////////////// | ||
1090 | 64 | bool ProtocolHandler::login(const char *mech, const char *clientData) | |
1091 | { /*{{{*/ | ||
1092 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 63 times.
|
64 | if (!feature.login) |
1093 | 1 | return false; | |
1094 | |||
1095 |
2/4✓ Branch 3 taken 63 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 63 times.
✗ Branch 7 not taken.
|
126 | XmlCommand sasl(cout, "auth"); |
1096 |
3/4✓ Branch 0 taken 31 times.
✓ Branch 1 taken 32 times.
✓ Branch 3 taken 31 times.
✗ Branch 4 not taken.
|
63 | if (mech and *mech) |
1097 |
1/2✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
|
31 | sasl.addAttribute("mech", mech); |
1098 | |||
1099 |
4/4✓ Branch 0 taken 59 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 31 times.
|
63 | if (clientData and *clientData) |
1100 |
1/2✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
|
28 | sasl.addAttribute("clientdata", clientData); |
1101 | |||
1102 | 63 | return true; | |
1103 | } /*}}}*/ | ||
1104 | |||
1105 | /////////////////////////////////////////////////////////////////////////// | ||
1106 | 1 | void ProtocolHandler::logout() | |
1107 | { /*{{{*/ | ||
1108 |
2/4✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
1 | XmlCommand(cout, "auth").addAttribute("logout", 1); |
1109 | 1 | } /*}}}*/ | |
1110 | |||
1111 | /////////////////////////////////////////////////////////////////////////// | ||
1112 | 91 | bool ProtocolHandler::processLogin(const char **_atts) | |
1113 | { /*{{{*/ | ||
1114 | // pdserv sends an empty saslauth tag after logout() | ||
1115 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 90 times.
|
91 | if (!*_atts) |
1116 | 1 | return false; | |
1117 | 90 | Attribute atts(_atts); | |
1118 | 90 | int finished = 0; | |
1119 |
6/6✓ Branch 1 taken 28 times.
✓ Branch 2 taken 62 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 86 times.
|
90 | if (atts.getInt("success", finished) and !finished) |
1120 | 4 | finished = -1; | |
1121 | |||
1122 | 90 | const char *mechlist = 0; | |
1123 | 90 | atts.getString("mechlist", mechlist); | |
1124 | |||
1125 | 90 | const char *serverdata = 0; | |
1126 | 90 | atts.getString("serverdata", serverdata); | |
1127 | |||
1128 |
1/2✓ Branch 16 taken 90 times.
✗ Branch 17 not taken.
|
90 | process->loginReply(mechlist, serverdata, finished); |
1129 | 90 | return finished > 0; | |
1130 | } /*}}}*/ | ||
1131 | |||
1132 | |||
1133 | /////////////////////////////////////////////////////////////////////////// | ||
1134 | 28 | void ProtocolHandler::setPolite(bool state) | |
1135 | { /*{{{*/ | ||
1136 |
3/10✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
28 | if (state != polite and feature.polite) { |
1137 | ✗ | polite = state; | |
1138 | |||
1139 | ✗ | XmlCommand(cout, "remote_host").addAttribute("polite", state); | |
1140 | } | ||
1141 | 28 | } /*}}}*/ | |
1142 | |||
1143 | /////////////////////////////////////////////////////////////////////////// | ||
1144 | 1143 | bool ProtocolHandler::asyncData() | |
1145 | { /*{{{*/ | ||
1146 |
1/2✓ Branch 3 taken 1143 times.
✗ Branch 4 not taken.
|
1143 | ExpatBuffer<ReadBufferSize> inputBuffer(*this); |
1147 | |||
1148 | const auto n = | ||
1149 |
1/2✓ Branch 6 taken 1143 times.
✗ Branch 7 not taken.
|
1143 | StreambufLayer::read(inputBuffer.fill<char>(), inputBuffer.size()); |
1150 |
4/6✗ Branch 3 not taken.
✓ Branch 4 taken 1143 times.
✓ Branch 5 taken 1143 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1126 times.
✓ Branch 8 taken 17 times.
|
1143 | if (!protocolError and n > 0) |
1151 |
2/2✓ Branch 6 taken 1125 times.
✓ Branch 7 taken 1 times.
|
1127 | parse(std::move(inputBuffer), n); |
1152 | 1142 | return n != 0; | |
1153 | } /*}}}*/ | ||
1154 | |||
1155 | /////////////////////////////////////////////////////////////////////////// | ||
1156 | |||
1157 | 2452 | void ProtocolHandler::cancelSubscriptions() | |
1158 | { | ||
1159 |
2/2✓ Branch 6 taken 52 times.
✓ Branch 7 taken 2452 times.
|
2504 | for (auto &kv : cancelations_) { |
1160 | 52 | const auto tm = kv.first; | |
1161 |
1/2✗ Branch 5 not taken.
✓ Branch 6 taken 52 times.
|
52 | if (tm == PdCom::event_mode) { |
1162 | ✗ | for (const auto &var : kv.second) { | |
1163 | ✗ | if (var->is_parameter_) { | |
1164 | const bool unsubscribe = | ||
1165 | ✗ | parameter_event_.at(var->index_).remove_expired(); | |
1166 | ✗ | if (unsubscribe and feature.xsap) { | |
1167 | ✗ | XmlCommand(cout, "xsop") | |
1168 | ✗ | .addAttribute("parameters", var->index_); | |
1169 | } | ||
1170 | } | ||
1171 | else { | ||
1172 | ✗ | channel_subscriptions_->unsubscribeEvent(*var, cout); | |
1173 | } | ||
1174 | } | ||
1175 | ✗ | kv.second.clear(); | |
1176 | } | ||
1177 | |||
1178 |
1/2✓ Branch 1 taken 52 times.
✗ Branch 2 not taken.
|
52 | else if (tm.getInterval() > 0) { |
1179 |
2/2✓ Branch 6 taken 3 times.
✓ Branch 7 taken 52 times.
|
55 | for (const auto &var : kv.second) { |
1180 |
1/2✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
|
3 | channel_subscriptions_->unsubscribePeriodic(tm, *var, cout); |
1181 | } | ||
1182 | 52 | kv.second.clear(); | |
1183 | } | ||
1184 | } | ||
1185 | 2452 | } | |
1186 | /////////////////////////////////////////////////////////////////////////// | ||
1187 | 84 | bool ProtocolHandler::find(const std::string &path) | |
1188 | { /*{{{*/ | ||
1189 |
1/2✓ Branch 5 taken 84 times.
✗ Branch 6 not taken.
|
168 | auto var = std::dynamic_pointer_cast<Variable>(root->find(path)); |
1190 |
5/6✓ Branch 1 taken 73 times.
✓ Branch 2 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 73 times.
✓ Branch 7 taken 11 times.
✓ Branch 8 taken 73 times.
|
84 | if (var or path.empty()) { |
1191 |
1/2✓ Branch 21 taken 11 times.
✗ Branch 22 not taken.
|
11 | process->findReply(PdCom::impl::Variable::toUApi(var)); |
1192 | 11 | return true; | |
1193 | } | ||
1194 | |||
1195 | // we already have all variables cached, so we know the requested one does | ||
1196 | // not exist. | ||
1197 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 73 times.
|
73 | if (fullListing == Cached) { |
1198 | ✗ | process->findReply({}); | |
1199 | ✗ | return true; | |
1200 | } | ||
1201 | |||
1202 |
1/2✓ Branch 3 taken 73 times.
✗ Branch 4 not taken.
|
73 | findQ.push(path); |
1203 | |||
1204 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 73 times.
✗ Branch 6 not taken.
|
73 | if (fullListing == Uncached) { |
1205 | // Do not flush next command | ||
1206 |
3/6✓ Branch 3 taken 73 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 73 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 73 times.
✗ Branch 13 not taken.
|
73 | XmlCommand(cout, "rp").addEscapedAttribute("name", path).noFlush(); |
1207 | |||
1208 |
4/8✓ Branch 3 taken 73 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 73 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 73 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 73 times.
✗ Branch 15 not taken.
|
73 | XmlCommand(cout, "rk").addEscapedAttribute("name", path).setId("findQ"); |
1209 | } | ||
1210 | |||
1211 | 73 | return false; | |
1212 | } /*}}}*/ | ||
1213 | |||
1214 | /////////////////////////////////////////////////////////////////////////// | ||
1215 | 80 | bool ProtocolHandler::processFindRequest() | |
1216 | { /*{{{*/ | ||
1217 |
2/2✓ Branch 2 taken 8 times.
✓ Branch 3 taken 72 times.
|
80 | if (findQ.empty()) // required by listReply! |
1218 | 8 | return false; | |
1219 | |||
1220 |
2/4✓ Branch 5 taken 72 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 72 times.
✗ Branch 10 not taken.
|
144 | std::shared_ptr<DirNode> node = root->find(findQ.front()); |
1221 |
1/2✓ Branch 23 taken 72 times.
✗ Branch 24 not taken.
|
144 | process->findReply(PdCom::impl::Variable::toUApi( |
1222 | 144 | std::dynamic_pointer_cast<PdCom::impl::Variable>(node))); | |
1223 |
1/2✓ Branch 2 taken 72 times.
✗ Branch 3 not taken.
|
72 | findQ.pop(); |
1224 | |||
1225 | 72 | return !findQ.empty(); | |
1226 | } /*}}}*/ | ||
1227 | |||
1228 | /////////////////////////////////////////////////////////////////////////// | ||
1229 | 19 | bool ProtocolHandler::list(const std::string &dir) | |
1230 | { /*{{{*/ | ||
1231 | 19 | listQ.push(dir); | |
1232 | |||
1233 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
|
19 | if (fullListing != Uncached) { |
1234 | ✗ | if (fullListing == Cached) | |
1235 | ✗ | processListRequest(); | |
1236 | } | ||
1237 |
7/8✓ Branch 2 taken 12 times.
✓ Branch 3 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 10 times.
✓ Branch 11 taken 9 times.
✓ Branch 12 taken 10 times.
|
19 | else if (dir.empty() or !feature.list) { |
1238 | // List everything. First send a <rp> and the state machine | ||
1239 | // will send a <rp> thereafter | ||
1240 |
1/2✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
|
9 | XmlCommand(cout, "rk").noFlush(); |
1241 |
2/4✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
|
9 | XmlCommand(cout, "rp").setId("listQ"); |
1242 | |||
1243 | 9 | fullListing = InProgress; | |
1244 | } | ||
1245 | else | ||
1246 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
20 | XmlCommand(cout, "list") |
1247 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
20 | .addEscapedAttribute("path", dir) |
1248 |
1/2✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | .addAttribute("noderived", 1); |
1249 | |||
1250 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
|
19 | return fullListing == Cached; |
1251 | } /*}}}*/ | ||
1252 | |||
1253 | 6 | void PdCom::impl::MsrProto::ProtocolHandler::getClientStatistics() | |
1254 | { | ||
1255 |
1/2✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | XmlCommand(cout, "read_statistics"); |
1256 | 6 | } | |
1257 | |||
1258 | /////////////////////////////////////////////////////////////////////////// | ||
1259 | 18 | bool ProtocolHandler::processListRequest() | |
1260 | { /*{{{*/ | ||
1261 |
2/4✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
|
36 | std::string path = listQ.front(); |
1262 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | listQ.pop(); |
1263 | |||
1264 | 36 | std::vector<std::string> dirList; | |
1265 | |||
1266 | 36 | DirNode::List list; | |
1267 | 18 | const bool listall = path.empty(); | |
1268 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
|
18 | if (listall) |
1269 |
1/2✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
6 | root->getAllChildren(list); |
1270 | else { | ||
1271 | // Directory list | ||
1272 |
1/2✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
24 | std::shared_ptr<DirNode> node = root->find(path); |
1273 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | if (node) |
1274 |
1/2✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
|
12 | node->getChildren(list); |
1275 | } | ||
1276 | |||
1277 | 36 | std::vector<PdCom::Variable> varList; | |
1278 |
1/2✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
|
18 | varList.reserve(list.size()); |
1279 | |||
1280 |
2/2✓ Branch 5 taken 276 times.
✓ Branch 6 taken 18 times.
|
294 | for (const auto &node : list) { |
1281 |
7/8✓ Branch 0 taken 18 times.
✓ Branch 1 taken 258 times.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✓ Branch 11 taken 12 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 270 times.
|
276 | if (!listall and node->hasChildren()) |
1282 |
2/4✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
|
6 | dirList.push_back(node->path()); |
1283 | |||
1284 | 552 | auto v = std::dynamic_pointer_cast<PdCom::impl::Variable>(node); | |
1285 |
2/2✓ Branch 1 taken 218 times.
✓ Branch 2 taken 58 times.
|
276 | if (v) |
1286 |
1/2✓ Branch 6 taken 218 times.
✗ Branch 7 not taken.
|
218 | varList.emplace_back(impl::Variable::toUApi(v)); |
1287 | } | ||
1288 | |||
1289 |
3/6✓ Branch 17 taken 18 times.
✗ Branch 18 not taken.
✓ Branch 21 taken 18 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 18 times.
✗ Branch 25 not taken.
|
18 | process->listReply(varList, dirList); |
1290 | |||
1291 | 36 | return !listQ.empty(); | |
1292 | } /*}}}*/ | ||
1293 | |||
1294 | /////////////////////////////////////////////////////////////////////////// | ||
1295 | 7 | void ProtocolHandler::pollChannel(PollSubscription &sub) | |
1296 | { /*{{{*/ | ||
1297 | 14 | const auto var_ptr = sub.variable_.lock(); | |
1298 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if (!var_ptr) |
1299 | ✗ | throw EmptyVariable(); | |
1300 | 7 | const auto index = static_cast<const Variable &>(*var_ptr).index_; | |
1301 |
2/4✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
|
21 | if (subscription_pending_channel_polls_.append( |
1302 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
14 | index, sub.shared_from_this())) |
1303 |
1/2✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
7 | pollChannel(index, "pollChannel"); |
1304 | 7 | } | |
1305 | |||
1306 | 7 | void ProtocolHandler::pollChannel(size_t index, const char *id) | |
1307 | { | ||
1308 |
1/2✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
14 | XmlCommand(cout, "rk") |
1309 |
1/2✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
|
14 | .addAttribute("index", index) |
1310 |
1/2✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
14 | .addAttribute("hex", 1) |
1311 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | .setId(id); |
1312 | 7 | } /*}}}*/ | |
1313 | |||
1314 | 6 | void ProtocolHandler::pollParameter(PollSubscription &sub) | |
1315 | { | ||
1316 | 12 | const auto var_ptr = sub.variable_.lock(); | |
1317 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (!var_ptr) |
1318 | ✗ | throw EmptyVariable(); | |
1319 | 6 | const auto index = static_cast<const Variable &>(*var_ptr).index_; | |
1320 |
2/4✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
18 | if (subscription_pending_parameter_polls_.append( |
1321 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | index, sub.shared_from_this())) |
1322 |
1/2✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | pollParameter(index, "pollParameter"); |
1323 | 6 | } | |
1324 | |||
1325 | /////////////////////////////////////////////////////////////////////////// | ||
1326 | 47 | void ProtocolHandler::pollParameter(size_t index, const char *id) | |
1327 | { /*{{{*/ | ||
1328 |
1/2✓ Branch 3 taken 47 times.
✗ Branch 4 not taken.
|
94 | XmlCommand(cout, "rp") |
1329 |
1/2✓ Branch 3 taken 47 times.
✗ Branch 4 not taken.
|
94 | .addAttribute("index", index) |
1330 |
1/2✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
|
94 | .addAttribute("short", 1) |
1331 |
1/2✓ Branch 4 taken 47 times.
✗ Branch 5 not taken.
|
94 | .addAttribute("hex", 1) |
1332 |
1/2✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
|
47 | .setId(id); |
1333 | 47 | } /*}}}*/ | |
1334 | |||
1335 | 8 | void ProtocolHandler::pollVariable( | |
1336 | const PdCom::impl::Variable &_var, | ||
1337 | VariablePollPromise &&promise) | ||
1338 | { | ||
1339 | 8 | const auto &var = static_cast<const MsrProto::Variable &>(_var); | |
1340 |
2/4✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
|
8 | if (variable_pending_polls_.append(var, std::move(promise))) { |
1341 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
|
8 | if (var.is_parameter_) |
1342 | 8 | pollParameter(var.index_, "VariablePollParameter"); | |
1343 | else | ||
1344 | ✗ | pollChannel(var.index_, "VariablePollChannel"); | |
1345 | } | ||
1346 | 8 | } | |
1347 | |||
1348 | /////////////////////////////////////////////////////////////////////////// | ||
1349 | 84 | std::shared_ptr<PdCom::impl::Subscription> ProtocolHandler::subscribe( | |
1350 | PdCom::Subscription *subscription, | ||
1351 | std::shared_ptr<const PdCom::impl::Variable> _var, | ||
1352 | PdCom::Subscriber &subscriber, | ||
1353 | const PdCom::Selector &selector, | ||
1354 | bool notify_pending) | ||
1355 | { | ||
1356 | 168 | auto var = std::dynamic_pointer_cast<const Variable>(_var); | |
1357 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
|
84 | if (!var) |
1358 | ✗ | return nullptr; | |
1359 |
2/2✓ Branch 10 taken 4 times.
✓ Branch 11 taken 80 times.
|
84 | if (subscriber.getTransmission() == PdCom::poll_mode) { |
1360 | 4 | auto ans = std::make_shared<PollSubscription>( | |
1361 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | var, subscription, subscriber, process->shared_from_this(), |
1362 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
12 | selector); |
1363 |
1/2✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
|
4 | process->pending_callbacks_.push_back( |
1364 | {ans, PdCom::Subscription::State::Active}); | ||
1365 | 4 | return ans; | |
1366 | } | ||
1367 |
2/2✓ Branch 10 taken 34 times.
✓ Branch 11 taken 46 times.
|
80 | else if (subscriber.getTransmission() == PdCom::event_mode) { |
1368 |
3/4✗ Branch 4 not taken.
✓ Branch 5 taken 34 times.
✓ Branch 6 taken 31 times.
✓ Branch 7 taken 3 times.
|
34 | if (var->is_parameter_) { |
1369 | 31 | auto ans = std::make_shared<EventSubscription>( | |
1370 |
1/2✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
|
62 | var, subscription, subscriber, process->shared_from_this(), |
1371 |
1/2✓ Branch 3 taken 31 times.
✗ Branch 4 not taken.
|
93 | selector); |
1372 |
3/4✓ Branch 4 taken 31 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 19 times.
✓ Branch 9 taken 12 times.
|
31 | if (parameter_event_[var->index_].empty()) { |
1373 | // not yet subscribed | ||
1374 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 19 times.
|
19 | if (feature.xsap) { |
1375 | ✗ | XmlCommand(cout, "xsap") | |
1376 | ✗ | .addAttribute("parameters", var->index_) | |
1377 | ✗ | .addAttribute("hex", 1) | |
1378 | ✗ | .setId("xsapQ"); | |
1379 | ✗ | xsapQ.push(var->index_); | |
1380 | ✗ | if (notify_pending) | |
1381 | ✗ | process->pending_callbacks_.push_back( | |
1382 | {ans, PdCom::Subscription::State::Pending}); | ||
1383 | } | ||
1384 | else { | ||
1385 |
1/2✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
|
19 | parameter_event_[var->index_].currentState = |
1386 | PdCom::Subscription::State::Active; | ||
1387 |
1/2✓ Branch 11 taken 19 times.
✗ Branch 12 not taken.
|
19 | process->pending_callbacks_.push_back( |
1388 | {ans, PdCom::Subscription::State::Active}); | ||
1389 | } | ||
1390 | } | ||
1391 | else { | ||
1392 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (notify_pending |
1393 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
12 | or parameter_event_[var->index_].currentState |
1394 | != PdCom::Subscription::State::Pending) | ||
1395 |
1/2✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
|
24 | process->pending_callbacks_.push_back( |
1396 |
1/2✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
12 | {ans, parameter_event_[var->index_].currentState}); |
1397 | } | ||
1398 |
2/4✓ Branch 5 taken 31 times.
✗ Branch 6 not taken.
✓ Branch 11 taken 31 times.
✗ Branch 12 not taken.
|
31 | parameter_event_[var->index_].insert(ans); |
1399 | 31 | return ans; | |
1400 | } | ||
1401 | else { | ||
1402 | 3 | return channel_subscriptions_->subscribeEvent( | |
1403 | subscription, var, subscriber, selector, notify_pending, | ||
1404 |
1/2✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
|
3 | cout); |
1405 | } | ||
1406 | } | ||
1407 | else { | ||
1408 |
2/4✗ Branch 4 not taken.
✓ Branch 5 taken 46 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 46 times.
|
46 | if (var->is_parameter_) |
1409 | ✗ | return {}; | |
1410 | 46 | return channel_subscriptions_->subscribePeriodic( | |
1411 |
1/2✓ Branch 7 taken 46 times.
✗ Branch 8 not taken.
|
46 | subscription, var, subscriber, selector, notify_pending, cout); |
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | |||
1416 | /////////////////////////////////////////////////////////////////////////// | ||
1417 | 28 | std::shared_ptr<PdCom::impl::Subscription> ProtocolHandler::subscribe( | |
1418 | PdCom::Subscription *subscription, | ||
1419 | const std::string &path, | ||
1420 | PdCom::Subscriber &subscriber, | ||
1421 | const PdCom::Selector &selector) | ||
1422 | { /*{{{*/ | ||
1423 |
1/2✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
|
28 | setPolite(false); |
1424 | |||
1425 |
5/6✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 26 times.
✓ Branch 15 taken 26 times.
✓ Branch 16 taken 2 times.
|
54 | if (auto var = std::dynamic_pointer_cast<Variable>(root->find(path))) { |
1426 |
3/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 26 times.
✓ Branch 10 taken 2 times.
|
2 | return subscribe(subscription, var, subscriber, selector, false); |
1427 | } | ||
1428 | |||
1429 | // Variable is unknown. Find it first. This requires interaction | ||
1430 | // with the server, which automatically postpones calls to | ||
1431 | // request->subscriber to a later point in time | ||
1432 | 26 | const auto it = std::find_if( | |
1433 | 78 | pending_queue_.begin(), pending_queue_.end(), | |
1434 |
1/2✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
|
104 | [&path](const PendingRequest &pr) { return pr.path_ == path; }); |
1435 | |||
1436 | 26 | auto ans = std::make_shared<PendingSubscription>( | |
1437 |
1/2✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
|
52 | subscription, subscriber, process->shared_from_this(), |
1438 |
1/2✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
|
78 | selector.impl_); |
1439 | |||
1440 |
1/2✓ Branch 6 taken 26 times.
✗ Branch 7 not taken.
|
26 | if (it == pending_queue_.end()) { |
1441 | // Discovery not yet active | ||
1442 |
2/4✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
|
52 | XmlCommand(cout, "rp") |
1443 |
1/2✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
|
52 | .addAttribute("name", path) |
1444 |
1/2✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
|
52 | .addAttribute("hex", 1) |
1445 |
1/2✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
26 | .setId("pendingParameter") |
1446 | 26 | .noFlush(); | |
1447 |
2/4✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 26 times.
✗ Branch 6 not taken.
|
52 | XmlCommand(cout, "rk") |
1448 |
1/2✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
|
52 | .addAttribute("name", path) |
1449 |
1/2✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
|
26 | .setId("pendingChannel"); |
1450 |
5/10✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
✓ Branch 12 taken 26 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 26 times.
✗ Branch 17 not taken.
✓ Branch 23 taken 26 times.
✓ Branch 24 taken 26 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
|
26 | pending_queue_.push_back({path, {{ans}}}); |
1451 | } | ||
1452 | else { | ||
1453 | ✗ | it->subscriptions_.insert(ans); | |
1454 | } | ||
1455 |
1/2✓ Branch 11 taken 26 times.
✗ Branch 12 not taken.
|
26 | process->pending_callbacks_.push_back( |
1456 | {ans, PdCom::Subscription::State::Pending}); | ||
1457 | 26 | return ans; | |
1458 | } /*}}}*/ | ||
1459 | |||
1460 | 33 | void ProtocolHandler::unsubscribe(EventSubscription &s) noexcept | |
1461 | { | ||
1462 |
1/2✓ Branch 3 taken 33 times.
✗ Branch 4 not taken.
|
66 | const auto var_ptr = s.variable_.lock(); |
1463 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
|
33 | if (!var_ptr) |
1464 | ✗ | return; | |
1465 | try { | ||
1466 |
3/8✓ Branch 6 taken 33 times.
✗ Branch 7 not taken.
✓ Branch 11 taken 33 times.
✗ Branch 12 not taken.
✓ Branch 17 taken 33 times.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
|
99 | cancelations_[PdCom::event_mode].insert( |
1467 | 66 | std::static_pointer_cast<const Variable>(var_ptr)); | |
1468 | } | ||
1469 | ✗ | catch (std::bad_alloc const &) { | |
1470 | // never going to happen | ||
1471 | } | ||
1472 | } | ||
1473 | |||
1474 | 46 | void ProtocolHandler::unsubscribe(PeriodicSubscription &s) noexcept | |
1475 | { | ||
1476 |
1/2✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
|
92 | const auto var_ptr = s.variable_.lock(); |
1477 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
|
46 | if (!var_ptr) |
1478 | ✗ | return; | |
1479 | try { | ||
1480 |
2/4✓ Branch 11 taken 46 times.
✗ Branch 12 not taken.
✓ Branch 16 taken 46 times.
✗ Branch 17 not taken.
|
92 | cancelations_[s.subscriber_.getTransmission()].insert( |
1481 |
1/4✓ Branch 4 taken 46 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
92 | std::static_pointer_cast<const Variable>(var_ptr)); |
1482 | } | ||
1483 | ✗ | catch (std::bad_alloc const &) { | |
1484 | // never going to happen | ||
1485 | } | ||
1486 | ✗ | catch (...) { | |
1487 | } | ||
1488 | } | ||
1489 | |||
1490 | /////////////////////////////////////////////////////////////////////////// | ||
1491 | 4 | void ProtocolHandler::ping() | |
1492 | { /*{{{*/ | ||
1493 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | XmlCommand(cout, "ping"); |
1494 | 4 | } /*}}}*/ | |
1495 | |||
1496 | /////////////////////////////////////////////////////////////////////////// | ||
1497 | 14 | std::string ProtocolHandler::name() const | |
1498 | { /*{{{*/ | ||
1499 | 14 | return m_name; | |
1500 | } /*}}}*/ | ||
1501 | |||
1502 | /////////////////////////////////////////////////////////////////////////// | ||
1503 | 11 | std::string ProtocolHandler::version() const | |
1504 | { /*{{{*/ | ||
1505 | 11 | return m_version; | |
1506 | } /*}}}*/ | ||
1507 | |||
1508 | /////////////////////////////////////////////////////////////////////////// | ||
1509 | 43 | PdCom::Variable::SetValueFuture ProtocolHandler::writeParameter( | |
1510 | const Parameter &p, | ||
1511 | const void *src, | ||
1512 | PdCom::TypeInfo::DataType src_type, | ||
1513 | size_t idx, | ||
1514 | size_t n) | ||
1515 | { /*{{{*/ | ||
1516 |
1/2✓ Branch 3 taken 43 times.
✗ Branch 4 not taken.
|
86 | XmlCommand(cout, "wp") |
1517 |
1/2✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
|
86 | .addAttribute("index", p.index_) |
1518 |
1/2✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
|
43 | .addAttribute("startindex", idx, idx) |
1519 | .addAttributeStream( | ||
1520 | "hexvalue", | ||
1521 | 43 | [&, this](XmlStream &os) { | |
1522 |
1/2✗ Branch 5 not taken.
✓ Branch 6 taken 43 times.
|
43 | encoder_.toHex(*p.type_info, src, src_type, n, os); |
1523 |
1/2✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
|
129 | }) |
1524 |
1/2✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
|
43 | .setId("wp"); |
1525 | // TODO(igh-vh) implement parameter setValue notification in msr and | ||
1526 | // pdserv | ||
1527 | 43 | return {}; | |
1528 | } /*}}}*/ | ||
1529 | |||
1530 | /////////////////////////////////////////////////////////////////////////// | ||
1531 | /////////////////////////////////////////////////////////////////////////// | ||
1532 | 29625 | bool fcmp(const char *p, const char *target, size_t len) | |
1533 | { | ||
1534 |
7/10✗ Branch 0 not taken.
✓ Branch 1 taken 29625 times.
✓ Branch 2 taken 17345 times.
✓ Branch 3 taken 12280 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 17345 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17345 times.
✓ Branch 8 taken 1820 times.
✓ Branch 9 taken 15525 times.
|
29625 | return len >= ::strlen(target) && !strncmp(p, target, len); |
1535 | } | ||
1536 | |||
1537 | 155 | void ProtocolHandler::Feature::operator=(const char *str) | |
1538 | { /*{{{*/ | ||
1539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 155 times.
|
155 | if (!str) |
1540 | ✗ | return; | |
1541 | 155 | *this = Feature {}; | |
1542 | |||
1543 | 155 | const char *p = str; | |
1544 | size_t len; | ||
1545 | |||
1546 | 1820 | do { | |
1547 | 1975 | p = str; | |
1548 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1975 times.
|
1975 | str = strchr(str, ','); |
1549 | |||
1550 |
3/4✓ Branch 0 taken 1820 times.
✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 155 times.
|
1975 | len = str ? str++ - p : strlen(p); |
1551 | |||
1552 |
1/2✓ Branch 0 taken 1975 times.
✗ Branch 1 not taken.
|
1975 | if (len) { |
1553 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "pushparameters", len)) |
1554 | 155 | pushparameters = true; | |
1555 | |||
1556 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "binparameters", len)) |
1557 | 155 | binparameters = true; | |
1558 | |||
1559 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "eventchannels", len)) |
1560 | 155 | eventchannels = true; | |
1561 | |||
1562 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "statistics", len)) |
1563 | 155 | statistics = true; | |
1564 | |||
1565 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "pmtime", len)) |
1566 | 155 | pmtime = true; | |
1567 | |||
1568 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "aic", len)) |
1569 | 155 | aic = true; | |
1570 | |||
1571 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "messages", len)) |
1572 | 155 | messages = true; | |
1573 | |||
1574 |
2/2✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1830 times.
|
1975 | if (fcmp(p, "group", len)) |
1575 | 145 | group = true; | |
1576 | |||
1577 |
2/2✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1830 times.
|
1975 | if (fcmp(p, "history", len)) |
1578 | 145 | history = true; | |
1579 | |||
1580 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1975 times.
|
1975 | if (fcmp(p, "quiet", len)) |
1581 | ✗ | quiet = true; | |
1582 | |||
1583 |
2/2✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1830 times.
|
1975 | if (fcmp(p, "list", len)) { |
1584 | 145 | list = true; | |
1585 | 145 | group = true; | |
1586 | } | ||
1587 | |||
1588 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1975 times.
|
1975 | if (fcmp(p, "exclusive", len)) |
1589 | ✗ | exclusive = true; | |
1590 | |||
1591 |
2/2✓ Branch 1 taken 155 times.
✓ Branch 2 taken 1820 times.
|
1975 | if (fcmp(p, "polite", len)) |
1592 | 155 | polite = true; | |
1593 | |||
1594 | /* feature disabled, because xsap does not work on all | ||
1595 | parameters in pdserv (those who are generated with | ||
1596 | msr:splitvectors), Hm | ||
1597 | |||
1598 | if (fcmp(p, "xsap", len)) | ||
1599 | xsap = true; | ||
1600 | */ | ||
1601 | |||
1602 |
2/2✓ Branch 1 taken 145 times.
✓ Branch 2 taken 1830 times.
|
1975 | if (fcmp(p, "login", 5)) |
1603 | 145 | login = true; | |
1604 | |||
1605 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1975 times.
|
1975 | if (fcmp(p, "eventid=", 8)) |
1606 | ✗ | eventid = strtoul(p + 8, 0, 0); | |
1607 | } | ||
1608 | |||
1609 |
2/2✓ Branch 0 taken 1820 times.
✓ Branch 1 taken 155 times.
|
1975 | } while (str); |
1610 | } /*}}}*/ | ||
1611 | |||
1612 | |||
1613 | 16 | void ProtocolHandler::getMessage(uint32_t seqNo) | |
1614 | { | ||
1615 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 15 times.
|
16 | if (!feature.history) { |
1616 |
1/2✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
|
1 | process->getMessageReply({}); |
1617 | } | ||
1618 | else { | ||
1619 |
1/2✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
|
30 | XmlCommand(cout, "message_history") |
1620 |
1/2✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
|
30 | .addAttribute("seq", seqNo) |
1621 |
1/2✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
|
15 | .setId("history"); |
1622 | 15 | seqNoQ.push(seqNo); | |
1623 | } | ||
1624 | 16 | } | |
1625 | |||
1626 | 22 | void ProtocolHandler::getActiveMessages() | |
1627 | { | ||
1628 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 21 times.
|
22 | if (!feature.history) { |
1629 |
1/2✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
|
1 | process->activeMessagesReply({}); |
1630 | } | ||
1631 | else | ||
1632 |
1/2✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
|
21 | XmlCommand(cout, "message_history"); |
1633 | 22 | } | |
1634 | |||
1635 | 29 | void ProtocolHandler::broadcast( | |
1636 | const std::string &message, | ||
1637 | const std::string &attr) | ||
1638 | { | ||
1639 |
2/4✓ Branch 3 taken 29 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
|
58 | XmlCommand msg(cout, "broadcast"); |
1640 |
2/2✓ Branch 3 taken 20 times.
✓ Branch 4 taken 9 times.
|
29 | msg.addEscapedAttribute(attr.c_str(), message); |
1641 | 20 | } | |
1642 | |||
1643 | |||
1644 | 22 | void ProtocolHandler::processBroadcast(const char **atts) | |
1645 | { | ||
1646 | 22 | Attribute a(atts); | |
1647 | 22 | const char *try_keys[] = {"action", "text"}; | |
1648 | 22 | const char *value = nullptr, *user = nullptr; | |
1649 |
1/2✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
|
22 | if (!a.getString("user", user)) |
1650 | 22 | user = "anonymous"; | |
1651 |
2/4✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 22 times.
|
33 | for (const char *key : try_keys) { |
1652 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 11 times.
|
33 | if (a.getString(key, value)) { |
1653 |
5/10✓ Branch 19 taken 22 times.
✗ Branch 20 not taken.
✓ Branch 23 taken 22 times.
✗ Branch 24 not taken.
✓ Branch 29 taken 22 times.
✗ Branch 30 not taken.
✓ Branch 36 taken 22 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 22 times.
✗ Branch 41 not taken.
|
22 | process->broadcastReply(value, key, a.getTime_ns("time"), user); |
1654 | 22 | return; | |
1655 | } | ||
1656 | } | ||
1657 | } | ||
1658 | |||
1659 | 4 | void PdCom::impl::MsrProto::ProtocolHandler::readEventData( | |
1660 | const char *name, | ||
1661 | const char **atts) | ||
1662 | { | ||
1663 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | if (name[0] == 'E') { |
1664 | 2 | Attribute a(atts); | |
1665 | 2 | unsigned int index; | |
1666 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (a.getUInt("c", index)) { |
1667 | 2 | const auto map_it = | |
1668 |
1/2✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
4 | channel_subscriptions_->getEventMap().find(index); |
1669 |
3/10✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
4 | if (map_it != channel_subscriptions_->getEventMap().end() |
1670 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
4 | and channel[index]) { |
1671 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
4 | auto cache = variable_cache_.lock(); |
1672 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (const char *d = a.find("d")) { |
1673 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
4 | cache[0].readFromBase64( |
1674 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | a.find("d"), strlen(d), *channel[index]); |
1675 |
2/4✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
|
2 | map_it->second.readData(cache[0].data(), dataTime); |
1676 | } | ||
1677 | } | ||
1678 | } | ||
1679 | } | ||
1680 | 4 | } | |
1681 | |||
1682 | 888 | void PdCom::impl::MsrProto::ProtocolHandler::readPeriodicData( | |
1683 | const char *name, | ||
1684 | const char **atts) | ||
1685 | { | ||
1686 |
5/6✓ Branch 1 taken 547 times.
✓ Branch 2 taken 341 times.
✓ Branch 5 taken 547 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 547 times.
✓ Branch 8 taken 341 times.
|
888 | if (name[0] == 'F' and periodic_receive_handle_) { |
1687 | 547 | Attribute a(atts); | |
1688 | 547 | unsigned int index = 0; | |
1689 |
4/8✓ Branch 1 taken 547 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 547 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 547 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 547 times.
✗ Branch 11 not taken.
|
547 | if (a.getUInt("c", index) and channel[index]) { |
1690 |
2/4✓ Branch 4 taken 547 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 547 times.
✗ Branch 10 not taken.
|
547 | periodic_receive_handle_.readData(*channel[index], a.find("d")); |
1691 | } | ||
1692 | } | ||
1693 |
4/8✗ Branch 0 not taken.
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 341 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 341 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 341 times.
✗ Branch 9 not taken.
|
341 | else if (!strcmp(name, "time") and periodic_receive_handle_) { |
1694 |
1/2✓ Branch 6 taken 341 times.
✗ Branch 7 not taken.
|
341 | periodic_receive_handle_.readTimestamps(Attribute(atts).find("d")); |
1695 | } | ||
1696 | 888 | } | |
1697 | |||
1698 | template class PdCom::impl::MsrProto::ExpatWrapper<ProtocolHandler, true>; | ||
1699 | |||
1700 | 13 | bool ProtocolHandler::SubscriptionPendingPollList::append( | |
1701 | unsigned int const id, | ||
1702 | const std::shared_ptr<PollSubscription> &sub) | ||
1703 | { | ||
1704 |
4/8✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 13 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 13 times.
✗ Branch 20 not taken.
|
13 | for (auto &pp : *this) { |
1705 | ✗ | if (pp.id_ == id) { | |
1706 | ✗ | pp.subscriptions_.insert(sub); | |
1707 | ✗ | pp.subscriptions_.remove_expired(); | |
1708 | ✗ | return false; | |
1709 | } | ||
1710 | } | ||
1711 |
4/8✓ Branch 8 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✓ Branch 19 taken 13 times.
✓ Branch 20 taken 13 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
|
13 | push_back({id, {{sub}}}); |
1712 | 13 | return true; | |
1713 | } | ||
1714 | |||
1715 | 8 | bool ProtocolHandler::VariablePendingPollList::append( | |
1716 | const Variable &var, | ||
1717 | VariablePollPromise promise) | ||
1718 | { | ||
1719 |
4/8✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 8 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 20 not taken.
|
8 | for (auto &pp : polls_) { |
1720 | ✗ | if (pp.id_ == var.index_ and pp.is_parameter_ == var.is_parameter_) { | |
1721 | ✗ | pp.promises_.push_back(std::move(promise)); | |
1722 | ✗ | return false; | |
1723 | } | ||
1724 | } | ||
1725 | 8 | polls_.emplace_back(std::move(promise), var.index_, var.is_parameter_); | |
1726 | 8 | return true; | |
1727 | } | ||
1728 | |||
1729 | |||
1730 | 3 | void ProtocolHandler::VariablePendingPollList::processResult( | |
1731 | Variable const &var, | ||
1732 | const char *data, | ||
1733 | std::chrono::nanoseconds ts) | ||
1734 | { | ||
1735 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (polls_.empty()) |
1736 | ✗ | return; | |
1737 |
1/2✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
|
6 | auto head = std::move(polls_.front()); |
1738 | 3 | polls_.pop_front(); | |
1739 |
3/6✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
|
3 | if (var.is_parameter_ != head.is_parameter_) |
1740 | ✗ | throw ProtocolError("Channel/Parameter poll reply mismatch"); | |
1741 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
3 | if (head.id_ != var.index_) |
1742 | ✗ | throw ProtocolError("Got wrong parameter index reply"); | |
1743 |
2/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
6 | auto ans = PdCom::VariablePollResult {var.toUApi()}; |
1744 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | std::copy( |
1745 |
1/2✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
3 | data, data + var.totalSizeInBytes(), |
1746 | 3 | reinterpret_cast<char *>(ans.getData())); | |
1747 |
2/2✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
|
6 | for (auto &promise : head.promises_) |
1748 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | promise.resolve(ans, ts); |
1749 | } | ||
1750 | |||
1751 | 312 | ProtocolHandler::VariablePendingPollList::~VariablePendingPollList() | |
1752 | { | ||
1753 | 312 | const PdCom::ProcessGoneAway ex {}; | |
1754 |
2/2✓ Branch 6 taken 5 times.
✓ Branch 7 taken 156 times.
|
161 | for (auto &poll_list : polls_) |
1755 |
2/2✓ Branch 6 taken 5 times.
✓ Branch 7 taken 5 times.
|
10 | for (auto &pending_poll : poll_list.promises_) |
1756 | try { | ||
1757 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | pending_poll.reject(ex); |
1758 | } | ||
1759 | ✗ | catch (...) { | |
1760 | } | ||
1761 | 156 | } | |
1762 | |||
1763 | ✗ | PdCom::Variable::SetValueFuture ProtocolHandler::PendingSetValues::push() | |
1764 | { | ||
1765 | ✗ | auto ans = createFuture<PdCom::Exception const &>(); | |
1766 | ✗ | queue_.push(std::move(ans.second)); | |
1767 | ✗ | return std::move(ans.first); | |
1768 | } | ||
1769 | |||
1770 | ✗ | void ProtocolHandler::PendingSetValues::pop() | |
1771 | { | ||
1772 | ✗ | if (queue_.empty()) | |
1773 | ✗ | return; | |
1774 | |||
1775 | ✗ | auto promise = std::move(queue_.front()); | |
1776 | ✗ | queue_.pop(); | |
1777 | ✗ | promise.resolve(); | |
1778 | } | ||
1779 | |||
1780 | |||
1781 | 312 | ProtocolHandler::PendingSetValues::~PendingSetValues() | |
1782 | { | ||
1783 | 312 | auto q = std::move(queue_); | |
1784 | 312 | const PdCom::ProcessGoneAway ex {}; | |
1785 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 156 times.
|
156 | while (!q.empty()) { |
1786 | try { | ||
1787 | ✗ | q.front().reject(ex); | |
1788 | } | ||
1789 | ✗ | catch (...) { | |
1790 | } | ||
1791 | ✗ | q.pop(); | |
1792 | } | ||
1793 | 156 | } | |
1794 | |||
1795 | std::vector<PdCom::Process::SubscriptionInfo> | ||
1796 | ✗ | ProtocolHandler::getActiveSubscriptions() const | |
1797 | { | ||
1798 | ✗ | std::vector<PdCom::Process::SubscriptionInfo> ans; | |
1799 | // parameter event | ||
1800 | ✗ | for (const auto &map : parameter_event_) { | |
1801 | ✗ | PdCom::Variable v = impl::Variable::toUApi( | |
1802 | ✗ | std::static_pointer_cast<const MsrProto::Variable>( | |
1803 | ✗ | parameter.at(map.first)->shared_from_this())); | |
1804 | ✗ | for (const auto &weak_sub : map.second) { | |
1805 | ✗ | if (const auto sub = weak_sub.lock()) { | |
1806 | ✗ | ans.emplace_back(sub->This_, &sub->subscriber_, v); | |
1807 | } | ||
1808 | } | ||
1809 | } | ||
1810 | // channels | ||
1811 | ✗ | channel_subscriptions_->dump(ans, channel); | |
1812 | ✗ | return ans; | |
1813 | } | ||
1814 | |||
1815 | std::shared_ptr<PdCom::impl::Subscription> | ||
1816 | 2 | ChannelSubscriptionsWithGroup::subscribeEvent( | |
1817 | PdCom::Subscription *subscription, | ||
1818 | std::shared_ptr<const Variable> var, | ||
1819 | PdCom::Subscriber &subscriber, | ||
1820 | const PdCom::Selector &selector, | ||
1821 | bool notify_pending, | ||
1822 | XmlStream &cout) | ||
1823 | { | ||
1824 | 4 | auto process = var->process.lock(); | |
1825 | 2 | auto ans = std::make_shared<EventSubscription>( | |
1826 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | var, subscription, subscriber, process, selector); |
1827 | |||
1828 |
2/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | if (event_[var->index_].empty()) { |
1829 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | XmlCommand(cout, "xsad") |
1830 |
1/2✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | .addAttribute("channels", var->index_) |
1831 |
1/2✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | .addAttribute("group", 0) |
1832 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | .addAttribute("coding", "Base64") |
1833 |
1/2✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | .addAttribute("event", 1) |
1834 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | .setId(xsadId); |
1835 |
1/2✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
|
2 | xsadQ.push({0, var->index_}); |
1836 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (notify_pending) |
1837 |
1/2✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
|
2 | process->pending_callbacks_.push_back( |
1838 | {ans, PdCom::Subscription::State::Pending}); | ||
1839 | } | ||
1840 | else { | ||
1841 | ✗ | if (notify_pending | |
1842 | ✗ | or event_[var->index_].currentState | |
1843 | != PdCom::Subscription::State::Pending) | ||
1844 | ✗ | process->pending_callbacks_.push_back( | |
1845 | ✗ | {ans, event_[var->index_].currentState}); | |
1846 | } | ||
1847 |
2/4✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
|
2 | event_[var->index_].insert(ans); |
1848 | 4 | return ans; | |
1849 | } | ||
1850 | |||
1851 | std::shared_ptr<PdCom::impl::Subscription> | ||
1852 | 42 | PdCom::impl::MsrProto::ChannelSubscriptionsWithGroup::subscribePeriodic( | |
1853 | PdCom::Subscription *subscription, | ||
1854 | std::shared_ptr<const Variable> var, | ||
1855 | PdCom::Subscriber &subscriber, | ||
1856 | const PdCom::Selector &selector, | ||
1857 | bool notify_pending, | ||
1858 | XmlStream &cout) | ||
1859 | { | ||
1860 | 84 | auto process = var->process.lock(); | |
1861 | 42 | auto ans = std::make_shared<PeriodicSubscription>( | |
1862 |
1/2✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
84 | var, subscription, subscriber, process, selector); |
1863 | 42 | const auto si = periodic_subscriptions_with_group_.add( | |
1864 |
1/2✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
|
42 | process->pending_callbacks_, notify_pending, ans); |
1865 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
|
42 | if (si.needs_server_action) { |
1866 |
2/4✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
|
84 | XmlCommand(cout, "xsad") |
1867 |
1/2✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
|
84 | .addAttribute("channels", var->index_) |
1868 |
1/2✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
|
42 | .addAttribute("group", si.group_id) |
1869 |
1/2✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
|
42 | .addAttribute("coding", "Base64") |
1870 |
1/2✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
|
42 | .addAttribute("reduction", si.decimation_) |
1871 |
1/2✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
|
42 | .addAttribute("blocksize", si.blocksize_) |
1872 |
1/2✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
|
42 | .setId(xsadId); |
1873 |
1/2✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
|
42 | xsadQ.push({si.group_id, var->index_}); |
1874 | } | ||
1875 | 84 | return ans; | |
1876 | } | ||
1877 | |||
1878 | ✗ | void ChannelSubscriptionsWithGroup::unsubscribeEvent( | |
1879 | const Variable &var, | ||
1880 | XmlStream &cout) | ||
1881 | { | ||
1882 | ✗ | const bool unsubscribe = event_.at(var.index_).remove_expired(); | |
1883 | ✗ | if (unsubscribe) { | |
1884 | ✗ | XmlCommand(cout, "xsod") | |
1885 | ✗ | .addAttribute("channels", var.index_) | |
1886 | ✗ | .addAttribute("group", 0); | |
1887 | } | ||
1888 | } | ||
1889 | |||
1890 | 1 | void ChannelSubscriptionsWithGroup::unsubscribePeriodic( | |
1891 | PdCom::Transmission tm, | ||
1892 | const Variable &var, | ||
1893 | XmlStream &cout) | ||
1894 | { | ||
1895 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
1 | const auto si = periodic_subscriptions_with_group_.remove(var, tm); |
1896 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | if (si.needs_server_action) { |
1897 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | xsodQ.push(si.group_id); |
1898 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | XmlCommand(cout, "xsod") |
1899 |
1/2✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | .addAttribute("channels", var.index_) |
1900 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | .addAttribute("group", si.group_id) |
1901 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | .setId(xsodId); |
1902 | } | ||
1903 | 1 | } | |
1904 | |||
1905 | 44 | void PdCom::impl::MsrProto::ChannelSubscriptionsWithGroup::xsadAck( | |
1906 | Process *process) | ||
1907 | { | ||
1908 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
|
44 | if (xsadQ.empty()) |
1909 | ✗ | throw ProtocolError("no pending xsad commands available"); | |
1910 |
1/2✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
|
44 | const auto ids = xsadQ.front(); |
1911 |
1/2✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
44 | xsadQ.pop(); |
1912 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42 times.
|
44 | if (ids.group_id == 0) { |
1913 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | const auto map_it = event_.find(ids.channel_id); |
1914 |
1/2✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
2 | if (map_it == event_.end()) |
1915 | ✗ | return; | |
1916 |
2/4✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | map_it->second.broadcastState( |
1917 | PdCom::Subscription::State::Active, | ||
1918 | process->pending_callbacks_); | ||
1919 | } | ||
1920 | else { | ||
1921 |
2/4✓ Branch 3 taken 42 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
|
84 | periodic_subscriptions_with_group_.subscribeWasConfirmed( |
1922 | 42 | process->pending_callbacks_, ids.group_id, ids.channel_id); | |
1923 | } | ||
1924 | } | ||
1925 | |||
1926 | ✗ | void PdCom::impl::MsrProto::ChannelSubscriptionsWithGroup::xsodAck() | |
1927 | { | ||
1928 | ✗ | if (xsodQ.empty()) | |
1929 | ✗ | throw ProtocolError("no pending xsod commands available"); | |
1930 | |||
1931 | ✗ | const auto id = xsodQ.front(); | |
1932 | ✗ | xsodQ.pop(); | |
1933 | |||
1934 | ✗ | periodic_subscriptions_with_group_.unsubscribeDone(id); | |
1935 | } | ||
1936 | |||
1937 | ✗ | void PdCom::impl::MsrProto::ChannelSubscriptionsWithGroup::dump( | |
1938 | std::vector<PdCom::Process::SubscriptionInfo> &ans, | ||
1939 | const std::unordered_map<unsigned, Channel *> &channels) const | ||
1940 | { | ||
1941 | ✗ | ChannelSubscriptions::dump(ans, channels); | |
1942 | // channel periodic | ||
1943 | ✗ | periodic_subscriptions_with_group_.dump(ans, channels); | |
1944 | } | ||
1945 | |||
1946 | std::shared_ptr<PdCom::impl::Subscription> | ||
1947 | 1 | PdCom::impl::MsrProto::ChannelSubscriptionsWithoutGroup::subscribeEvent( | |
1948 | PdCom::Subscription *subscription, | ||
1949 | std::shared_ptr<const Variable> var, | ||
1950 | PdCom::Subscriber &subscriber, | ||
1951 | const PdCom::Selector &selector, | ||
1952 | bool notify_pending, | ||
1953 | XmlStream &cout) | ||
1954 | { | ||
1955 | // can't have periodic and event at the same time | ||
1956 |
2/4✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | if (periodic_subscriptions_without_group_.hasChannel(var->index_)) |
1957 | 1 | return {}; | |
1958 | |||
1959 | |||
1960 | ✗ | auto process = var->process.lock(); | |
1961 | ✗ | auto ans = std::make_shared<EventSubscription>( | |
1962 | ✗ | var, subscription, subscriber, process, selector); | |
1963 | |||
1964 | ✗ | if (event_[var->index_].empty()) { | |
1965 | ✗ | event_[var->index_].currentState = PdCom::Subscription::State::Pending; | |
1966 | ✗ | XmlCommand(cout, "xsad") | |
1967 | ✗ | .addAttribute("channels", var->index_) | |
1968 | ✗ | .addAttribute("coding", "Base64") | |
1969 | ✗ | .addAttribute("event", 1) | |
1970 | ✗ | .setId(xsadId); | |
1971 | ✗ | xsadQ.push({true, var->index_}); | |
1972 | ✗ | if (notify_pending) | |
1973 | ✗ | process->pending_callbacks_.push_back( | |
1974 | {ans, PdCom::Subscription::State::Pending}); | ||
1975 | } | ||
1976 | else { | ||
1977 | ✗ | if (notify_pending | |
1978 | ✗ | or event_[var->index_].currentState | |
1979 | != PdCom::Subscription::State::Pending) | ||
1980 | ✗ | process->pending_callbacks_.push_back( | |
1981 | ✗ | {ans, event_[var->index_].currentState}); | |
1982 | } | ||
1983 | ✗ | event_[var->index_].insert(ans); | |
1984 | ✗ | return ans; | |
1985 | } | ||
1986 | |||
1987 | std::shared_ptr<PdCom::impl::Subscription> | ||
1988 | 4 | ChannelSubscriptionsWithoutGroup::subscribePeriodic( | |
1989 | PdCom::Subscription *subscription, | ||
1990 | std::shared_ptr<const Variable> var, | ||
1991 | PdCom::Subscriber &subscriber, | ||
1992 | const PdCom::Selector &selector, | ||
1993 | bool notify_pending, | ||
1994 | XmlStream &cout) | ||
1995 | { | ||
1996 | { | ||
1997 |
2/4✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
8 | const auto it = event_.find(var->index_); |
1998 |
4/10✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
|
4 | if (it != event_.end() && !it->second.empty()) |
1999 | // periodic and event not allowed at the same time. | ||
2000 | ✗ | return {}; | |
2001 | } | ||
2002 | 8 | auto process = var->process.lock(); | |
2003 | 4 | auto ans = std::make_shared<PeriodicSubscription>( | |
2004 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | var, subscription, subscriber, process, selector); |
2005 | 4 | const auto si = periodic_subscriptions_without_group_.add( | |
2006 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | process->pending_callbacks_, notify_pending, ans); |
2007 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | if (si.needs_server_action) { |
2008 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | XmlCommand(cout, "xsad") |
2009 |
1/2✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
|
8 | .addAttribute("channels", var->index_) |
2010 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | .addAttribute("coding", "Base64") |
2011 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | .addAttribute("reduction", si.decimation_) |
2012 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | .addAttribute("blocksize", si.blocksize_) |
2013 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | .setId(xsadId); |
2014 |
1/2✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
|
4 | xsadQ.push({false, var->index_}); |
2015 | } | ||
2016 | 4 | return ans; | |
2017 | } | ||
2018 | |||
2019 | ✗ | void PdCom::impl::MsrProto::ChannelSubscriptionsWithoutGroup::unsubscribeEvent( | |
2020 | const Variable &var, | ||
2021 | XmlStream &cout) | ||
2022 | { | ||
2023 | ✗ | const bool unsubscribe = event_.at(var.index_).remove_expired(); | |
2024 | ✗ | if (unsubscribe) { | |
2025 | ✗ | XmlCommand(cout, "xsod").addAttribute("channels", var.index_); | |
2026 | } | ||
2027 | } | ||
2028 | |||
2029 | 2 | void PdCom::impl::MsrProto::ChannelSubscriptionsWithoutGroup:: | |
2030 | unsubscribePeriodic( | ||
2031 | PdCom::Transmission /* tm */, | ||
2032 | const Variable &var, | ||
2033 | XmlStream &cout) | ||
2034 | { | ||
2035 | 2 | const auto si = periodic_subscriptions_without_group_.remove(var); | |
2036 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
2 | if (si.needs_server_action) { |
2037 |
2/4✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | XmlCommand(cout, "xsod").addAttribute("channels", var.index_); |
2038 | } | ||
2039 | 2 | } | |
2040 | |||
2041 | 4 | void PdCom::impl::MsrProto::ChannelSubscriptionsWithoutGroup::xsadAck( | |
2042 | Process *process) | ||
2043 | { | ||
2044 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (xsadQ.empty()) |
2045 | ✗ | throw ProtocolError("no pending xsad commands available"); | |
2046 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | const auto ids = xsadQ.front(); |
2047 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | xsadQ.pop(); |
2048 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | if (ids.first) { |
2049 | ✗ | const auto map_it = event_.find(ids.second); | |
2050 | ✗ | if (map_it == event_.end()) | |
2051 | ✗ | return; | |
2052 | ✗ | map_it->second.broadcastState( | |
2053 | PdCom::Subscription::State::Active, | ||
2054 | process->pending_callbacks_); | ||
2055 | } | ||
2056 | else { | ||
2057 |
2/4✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
8 | periodic_subscriptions_without_group_.subscribeWasConfirmed( |
2058 | 4 | process->pending_callbacks_, ids.second); | |
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | ✗ | void PdCom::impl::MsrProto::ChannelSubscriptionsWithoutGroup::dump( | |
2063 | std::vector<PdCom::Process::SubscriptionInfo> &ans, | ||
2064 | const std::unordered_map<unsigned, Channel *> &channels) const | ||
2065 | { | ||
2066 | ✗ | ChannelSubscriptions::dump(ans, channels); | |
2067 | ✗ | periodic_subscriptions_without_group_.dump(ans, channels); | |
2068 | } | ||
2069 | |||
2070 | ✗ | void PdCom::impl::MsrProto::ChannelSubscriptions::dump( | |
2071 | std::vector<PdCom::Process::SubscriptionInfo> &ans, | ||
2072 | const std::unordered_map<unsigned, Channel *> &channels) const | ||
2073 | { | ||
2074 | // channel event | ||
2075 | ✗ | for (const auto &map : event_) { | |
2076 | ✗ | PdCom::Variable v = impl::Variable::toUApi( | |
2077 | ✗ | std::static_pointer_cast<const MsrProto::Variable>( | |
2078 | ✗ | channels.at(map.first)->shared_from_this())); | |
2079 | ✗ | for (const auto &weak_sub : map.second) { | |
2080 | ✗ | if (const auto sub = weak_sub.lock()) { | |
2081 | ✗ | ans.emplace_back(sub->This_, &sub->subscriber_, v); | |
2082 | } | ||
2083 | } | ||
2084 | } | ||
2085 | } | ||
2086 |