Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
reportqueue.cc
1 #include "reportqueue.h"
2 
3 #include <chrono>
4 
5 ReportQueue::ReportQueue(const Config& config_in, std::shared_ptr<HttpInterface> http_client,
6  std::shared_ptr<INvStorage> storage_in)
7  : config(config_in), http(std::move(http_client)), storage(std::move(storage_in)) {
8  thread_ = std::thread(std::bind(&ReportQueue::run, this));
9 }
10 
11 ReportQueue::~ReportQueue() {
12  {
13  std::lock_guard<std::mutex> lock(m_);
14  shutdown_ = true;
15  }
16  cv_.notify_all();
17  thread_.join();
18 
19  LOG_TRACE << "Flushing report queue";
20  flushQueue();
21 }
22 
23 void ReportQueue::run() {
24  // Check if queue is nonempty. If so, move any reports to the Json array and
25  // try to send it to the server. Clear the Json array only if the send
26  // succeeds.
27  std::unique_lock<std::mutex> lock(m_);
28  while (!shutdown_) {
29  flushQueue();
30  cv_.wait_for(lock, std::chrono::seconds(10));
31  }
32 }
33 
34 void ReportQueue::enqueue(std::unique_ptr<ReportEvent> event) {
35  {
36  std::lock_guard<std::mutex> lock(m_);
37  storage->saveReportEvent(event->toJson());
38  }
39  cv_.notify_all();
40 }
41 
42 void ReportQueue::flushQueue() {
43  int64_t max_id = 0;
44  Json::Value report_array{Json::arrayValue};
45  storage->loadReportEvents(&report_array, &max_id);
46 
47  if (config.tls.server.empty()) {
48  // Prevent a lot of unnecessary garbage output in uptane vector tests.
49  LOG_TRACE << "No server specified. Clearing report queue.";
50  report_array.clear();
51  }
52 
53  if (!report_array.empty()) {
54  HttpResponse response = http->post(config.tls.server + "/events", report_array);
55 
56  // 404 implies the server does not support this feature. Nothing we can
57  // do, just move along.
58  if (response.http_status_code == 404) {
59  LOG_TRACE << "Server does not support event reports. Clearing report queue.";
60  }
61 
62  if (response.isOk() || response.http_status_code == 404) {
63  report_array.clear();
64  storage->deleteReportEvents(max_id);
65  }
66  }
67 }
68 
69 void ReportEvent::setEcu(const Uptane::EcuSerial& ecu) { custom["ecu"] = ecu.ToString(); }
70 void ReportEvent::setCorrelationId(const std::string& correlation_id) {
71  if (!correlation_id.empty()) {
72  custom["correlationId"] = correlation_id;
73  }
74 }
75 
76 Json::Value ReportEvent::toJson() const {
77  Json::Value out;
78 
79  out["id"] = id;
80  out["deviceTime"] = timestamp.ToString();
81  out["eventType"]["id"] = type;
82  out["eventType"]["version"] = version;
83  out["event"] = custom;
84 
85  return out;
86 }
87 
88 CampaignAcceptedReport::CampaignAcceptedReport(const std::string& campaign_id) : ReportEvent("campaign_accepted", 0) {
89  custom["campaignId"] = campaign_id;
90 }
91 
92 CampaignDeclinedReport::CampaignDeclinedReport(const std::string& campaign_id) : ReportEvent("campaign_declined", 0) {
93  custom["campaignId"] = campaign_id;
94 }
95 
96 CampaignPostponedReport::CampaignPostponedReport(const std::string& campaign_id)
97  : ReportEvent("campaign_postponed", 0) {
98  custom["campaignId"] = campaign_id;
99 }
100 
101 DevicePausedReport::DevicePausedReport(const std::string& correlation_id) : ReportEvent("DevicePaused", 0) {
102  setCorrelationId(correlation_id);
103 }
104 
105 DeviceResumedReport::DeviceResumedReport(const std::string& correlation_id) : ReportEvent("DeviceResumed", 0) {
106  setCorrelationId(correlation_id);
107 }
108 
109 EcuDownloadStartedReport::EcuDownloadStartedReport(const Uptane::EcuSerial& ecu, const std::string& correlation_id)
110  : ReportEvent("EcuDownloadStarted", 0) {
111  setEcu(ecu);
112  setCorrelationId(correlation_id);
113 }
114 
115 EcuDownloadCompletedReport::EcuDownloadCompletedReport(const Uptane::EcuSerial& ecu, const std::string& correlation_id,
116  bool success)
117  : ReportEvent("EcuDownloadCompleted", 0) {
118  setEcu(ecu);
119  setCorrelationId(correlation_id);
120  custom["success"] = success;
121 }
122 
123 EcuInstallationStartedReport::EcuInstallationStartedReport(const Uptane::EcuSerial& ecu,
124  const std::string& correlation_id)
125  : ReportEvent("EcuInstallationStarted", 0) {
126  setEcu(ecu);
127  setCorrelationId(correlation_id);
128 }
129 
130 EcuInstallationAppliedReport::EcuInstallationAppliedReport(const Uptane::EcuSerial& ecu,
131  const std::string& correlation_id)
132  : ReportEvent("EcuInstallationApplied", 0) {
133  setEcu(ecu);
134  setCorrelationId(correlation_id);
135 }
136 
137 EcuInstallationCompletedReport::EcuInstallationCompletedReport(const Uptane::EcuSerial& ecu,
138  const std::string& correlation_id, bool success)
139  : ReportEvent("EcuInstallationCompleted", 0) {
140  setEcu(ecu);
141  setCorrelationId(correlation_id);
142  custom["success"] = success;
143 }
ReportEvent
Definition: reportqueue.h:18
HttpResponse
Definition: httpinterface.h:17
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
Uptane::EcuSerial
Definition: types.h:346
event
Aktualizr status events.
Definition: events.h:15