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