| 254 | } |
| 255 | |
| 256 | void C2Agent::performHeartBeat() { |
| 257 | C2Payload payload(Operation::HEARTBEAT); |
| 258 | logger_->log_trace("Performing heartbeat"); |
| 259 | std::shared_ptr<state::response::NodeReporter> reporter = std::dynamic_pointer_cast<state::response::NodeReporter>(update_sink_); |
| 260 | std::vector<std::shared_ptr<state::response::ResponseNode>> metrics; |
| 261 | if (reporter) { |
| 262 | if (!manifest_sent_) { |
| 263 | // include agent manifest for the first heartbeat |
| 264 | metrics = reporter->getHeartbeatNodes(true); |
| 265 | manifest_sent_ = true; |
| 266 | } else { |
| 267 | metrics = reporter->getHeartbeatNodes(false); |
| 268 | } |
| 269 | |
| 270 | payload.reservePayloads(metrics.size()); |
| 271 | for (const auto& metric : metrics) { |
| 272 | C2Payload child_metric_payload(Operation::HEARTBEAT); |
| 273 | child_metric_payload.setLabel(metric->getName()); |
| 274 | child_metric_payload.setContainer(metric->isArray()); |
| 275 | serializeMetrics(child_metric_payload, metric->getName(), metric->serialize(), metric->isArray()); |
| 276 | payload.addPayload(std::move(child_metric_payload)); |
| 277 | } |
| 278 | } |
| 279 | C2Payload && response = protocol_.load()->consumePayload(payload); |
| 280 | |
| 281 | enqueue_c2_server_response(std::move(response)); |
| 282 | |
| 283 | std::lock_guard<std::mutex> lock(heartbeat_mutex); |
| 284 | |
| 285 | for (auto reporter : heartbeat_protocols_) { |
| 286 | reporter->heartbeat(payload); |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | void C2Agent::serializeMetrics(C2Payload &metric_payload, const std::string &name, const std::vector<state::response::SerializedResponseNode> &metrics, bool is_container, bool is_collapsible) { |
| 291 | const auto payloads = std::count_if(begin(metrics), end(metrics), [](const state::response::SerializedResponseNode& metric) { return !metric.children.empty(); }); |
nothing calls this directly
no test coverage detected