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