xref: /openbmc/bmcweb/features/redfish/src/subscription.cpp (revision 81ee0e74bd3a575593ee2a21de560936843f526a)
102c1e29fSAlexander Hansen /*
202c1e29fSAlexander Hansen Copyright (c) 2020 Intel Corporation
302c1e29fSAlexander Hansen 
402c1e29fSAlexander Hansen Licensed under the Apache License, Version 2.0 (the "License");
502c1e29fSAlexander Hansen you may not use this file except in compliance with the License.
602c1e29fSAlexander Hansen You may obtain a copy of the License at
702c1e29fSAlexander Hansen 
802c1e29fSAlexander Hansen       http://www.apache.org/licenses/LICENSE-2.0
902c1e29fSAlexander Hansen 
1002c1e29fSAlexander Hansen Unless required by applicable law or agreed to in writing, software
1102c1e29fSAlexander Hansen distributed under the License is distributed on an "AS IS" BASIS,
1202c1e29fSAlexander Hansen WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1302c1e29fSAlexander Hansen See the License for the specific language governing permissions and
1402c1e29fSAlexander Hansen limitations under the License.
1502c1e29fSAlexander Hansen */
1602c1e29fSAlexander Hansen #include "subscription.hpp"
1702c1e29fSAlexander Hansen 
18fb546105SMyung Bae #include "dbus_singleton.hpp"
19b80ba2e4SAlexander Hansen #include "event_log.hpp"
2002c1e29fSAlexander Hansen #include "event_logs_object_type.hpp"
2102c1e29fSAlexander Hansen #include "event_matches_filter.hpp"
2202c1e29fSAlexander Hansen #include "event_service_store.hpp"
2302c1e29fSAlexander Hansen #include "filter_expr_executor.hpp"
24fb546105SMyung Bae #include "heartbeat_messages.hpp"
2502c1e29fSAlexander Hansen #include "http_client.hpp"
2602c1e29fSAlexander Hansen #include "http_response.hpp"
2702c1e29fSAlexander Hansen #include "logging.hpp"
2802c1e29fSAlexander Hansen #include "metric_report.hpp"
2902c1e29fSAlexander Hansen #include "server_sent_event.hpp"
3002c1e29fSAlexander Hansen #include "ssl_key_handler.hpp"
3102c1e29fSAlexander Hansen #include "utils/time_utils.hpp"
3202c1e29fSAlexander Hansen 
33fb546105SMyung Bae #include <boost/asio/error.hpp>
3402c1e29fSAlexander Hansen #include <boost/asio/io_context.hpp>
35fb546105SMyung Bae #include <boost/asio/steady_timer.hpp>
3602c1e29fSAlexander Hansen #include <boost/beast/http/verb.hpp>
3702c1e29fSAlexander Hansen #include <boost/system/errc.hpp>
3802c1e29fSAlexander Hansen #include <boost/url/format.hpp>
3902c1e29fSAlexander Hansen #include <boost/url/url_view_base.hpp>
4002c1e29fSAlexander Hansen #include <nlohmann/json.hpp>
4102c1e29fSAlexander Hansen 
4202c1e29fSAlexander Hansen #include <algorithm>
43fb546105SMyung Bae #include <chrono>
4402c1e29fSAlexander Hansen #include <cstdint>
4502c1e29fSAlexander Hansen #include <cstdlib>
4602c1e29fSAlexander Hansen #include <ctime>
4702c1e29fSAlexander Hansen #include <format>
4802c1e29fSAlexander Hansen #include <functional>
4902c1e29fSAlexander Hansen #include <memory>
5002c1e29fSAlexander Hansen #include <span>
5102c1e29fSAlexander Hansen #include <string>
5202c1e29fSAlexander Hansen #include <string_view>
5302c1e29fSAlexander Hansen #include <utility>
5402c1e29fSAlexander Hansen #include <vector>
5502c1e29fSAlexander Hansen 
5602c1e29fSAlexander Hansen namespace redfish
5702c1e29fSAlexander Hansen {
5802c1e29fSAlexander Hansen 
5902c1e29fSAlexander Hansen Subscription::Subscription(
6002c1e29fSAlexander Hansen     std::shared_ptr<persistent_data::UserSubscription> userSubIn,
6102c1e29fSAlexander Hansen     const boost::urls::url_view_base& url, boost::asio::io_context& ioc) :
6202c1e29fSAlexander Hansen     userSub{std::move(userSubIn)},
63fb546105SMyung Bae     policy(std::make_shared<crow::ConnectionPolicy>()), hbTimer(ioc)
6402c1e29fSAlexander Hansen {
6502c1e29fSAlexander Hansen     userSub->destinationUrl = url;
6602c1e29fSAlexander Hansen     client.emplace(ioc, policy);
6702c1e29fSAlexander Hansen     // Subscription constructor
6802c1e29fSAlexander Hansen     policy->invalidResp = retryRespHandler;
6902c1e29fSAlexander Hansen }
7002c1e29fSAlexander Hansen 
7102c1e29fSAlexander Hansen Subscription::Subscription(crow::sse_socket::Connection& connIn) :
7202c1e29fSAlexander Hansen     userSub{std::make_shared<persistent_data::UserSubscription>()},
73fb546105SMyung Bae     sseConn(&connIn), hbTimer(crow::connections::systemBus->get_io_context())
7402c1e29fSAlexander Hansen {}
7502c1e29fSAlexander Hansen 
7602c1e29fSAlexander Hansen // callback for subscription sendData
7702c1e29fSAlexander Hansen void Subscription::resHandler(const std::shared_ptr<Subscription>& /*unused*/,
7802c1e29fSAlexander Hansen                               const crow::Response& res)
7902c1e29fSAlexander Hansen {
8002c1e29fSAlexander Hansen     BMCWEB_LOG_DEBUG("Response handled with return code: {}", res.resultInt());
8102c1e29fSAlexander Hansen 
8202c1e29fSAlexander Hansen     if (!client)
8302c1e29fSAlexander Hansen     {
8402c1e29fSAlexander Hansen         BMCWEB_LOG_ERROR(
8502c1e29fSAlexander Hansen             "Http client wasn't filled but http client callback was called.");
8602c1e29fSAlexander Hansen         return;
8702c1e29fSAlexander Hansen     }
8802c1e29fSAlexander Hansen 
8902c1e29fSAlexander Hansen     if (userSub->retryPolicy != "TerminateAfterRetries")
9002c1e29fSAlexander Hansen     {
9102c1e29fSAlexander Hansen         return;
9202c1e29fSAlexander Hansen     }
9302c1e29fSAlexander Hansen     if (client->isTerminated())
9402c1e29fSAlexander Hansen     {
95fb546105SMyung Bae         hbTimer.cancel();
9602c1e29fSAlexander Hansen         if (deleter)
9702c1e29fSAlexander Hansen         {
9802c1e29fSAlexander Hansen             BMCWEB_LOG_INFO("Subscription {} is deleted after MaxRetryAttempts",
9902c1e29fSAlexander Hansen                             userSub->id);
10002c1e29fSAlexander Hansen             deleter();
10102c1e29fSAlexander Hansen         }
10202c1e29fSAlexander Hansen     }
10302c1e29fSAlexander Hansen }
10402c1e29fSAlexander Hansen 
105fb546105SMyung Bae void Subscription::sendHeartbeatEvent()
106fb546105SMyung Bae {
107fb546105SMyung Bae     // send the heartbeat message
108fb546105SMyung Bae     nlohmann::json eventMessage = messages::redfishServiceFunctional();
109fb546105SMyung Bae 
110fb546105SMyung Bae     std::string heartEventId = std::to_string(eventSeqNum);
111fb546105SMyung Bae     eventMessage["EventId"] = heartEventId;
112fb546105SMyung Bae     eventMessage["EventTimestamp"] = time_utils::getDateTimeOffsetNow().first;
113fb546105SMyung Bae     eventMessage["OriginOfCondition"] =
114fb546105SMyung Bae         std::format("/redfish/v1/EventService/Subscriptions/{}", userSub->id);
115fb546105SMyung Bae     eventMessage["MemberId"] = "0";
116fb546105SMyung Bae 
117fb546105SMyung Bae     nlohmann::json::array_t eventRecord;
118fb546105SMyung Bae     eventRecord.emplace_back(std::move(eventMessage));
119fb546105SMyung Bae 
120fb546105SMyung Bae     nlohmann::json msgJson;
121fb546105SMyung Bae     msgJson["@odata.type"] = "#Event.v1_4_0.Event";
122fb546105SMyung Bae     msgJson["Name"] = "Heartbeat";
123fb546105SMyung Bae     msgJson["Id"] = heartEventId;
124fb546105SMyung Bae     msgJson["Events"] = std::move(eventRecord);
125fb546105SMyung Bae 
126fb546105SMyung Bae     std::string strMsg =
127fb546105SMyung Bae         msgJson.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
128fb546105SMyung Bae     sendEventToSubscriber(std::move(strMsg));
129fb546105SMyung Bae     eventSeqNum++;
130fb546105SMyung Bae }
131fb546105SMyung Bae 
132fb546105SMyung Bae void Subscription::scheduleNextHeartbeatEvent()
133fb546105SMyung Bae {
134fb546105SMyung Bae     hbTimer.expires_after(std::chrono::minutes(userSub->hbIntervalMinutes));
135fb546105SMyung Bae     hbTimer.async_wait(
136fb546105SMyung Bae         std::bind_front(&Subscription::onHbTimeout, this, weak_from_this()));
137fb546105SMyung Bae }
138fb546105SMyung Bae 
139fb546105SMyung Bae void Subscription::heartbeatParametersChanged()
140fb546105SMyung Bae {
141fb546105SMyung Bae     hbTimer.cancel();
142fb546105SMyung Bae 
143fb546105SMyung Bae     if (userSub->sendHeartbeat)
144fb546105SMyung Bae     {
145fb546105SMyung Bae         scheduleNextHeartbeatEvent();
146fb546105SMyung Bae     }
147fb546105SMyung Bae }
148fb546105SMyung Bae 
149fb546105SMyung Bae void Subscription::onHbTimeout(const std::weak_ptr<Subscription>& weakSelf,
150fb546105SMyung Bae                                const boost::system::error_code& ec)
151fb546105SMyung Bae {
152fb546105SMyung Bae     if (ec == boost::asio::error::operation_aborted)
153fb546105SMyung Bae     {
154fb546105SMyung Bae         BMCWEB_LOG_DEBUG("heartbeat timer async_wait is aborted");
155fb546105SMyung Bae         return;
156fb546105SMyung Bae     }
157fb546105SMyung Bae     if (ec == boost::system::errc::operation_canceled)
158fb546105SMyung Bae     {
159fb546105SMyung Bae         BMCWEB_LOG_DEBUG("heartbeat timer async_wait canceled");
160fb546105SMyung Bae         return;
161fb546105SMyung Bae     }
162fb546105SMyung Bae     if (ec)
163fb546105SMyung Bae     {
164fb546105SMyung Bae         BMCWEB_LOG_CRITICAL("heartbeat timer async_wait failed: {}", ec);
165fb546105SMyung Bae         return;
166fb546105SMyung Bae     }
167fb546105SMyung Bae 
168fb546105SMyung Bae     std::shared_ptr<Subscription> self = weakSelf.lock();
169fb546105SMyung Bae     if (!self)
170fb546105SMyung Bae     {
171fb546105SMyung Bae         BMCWEB_LOG_CRITICAL("onHbTimeout failed on Subscription");
172fb546105SMyung Bae         return;
173fb546105SMyung Bae     }
174fb546105SMyung Bae 
175fb546105SMyung Bae     // Timer expired.
176fb546105SMyung Bae     sendHeartbeatEvent();
177fb546105SMyung Bae 
178fb546105SMyung Bae     // reschedule heartbeat timer
179fb546105SMyung Bae     scheduleNextHeartbeatEvent();
180fb546105SMyung Bae }
181fb546105SMyung Bae 
18202c1e29fSAlexander Hansen bool Subscription::sendEventToSubscriber(std::string&& msg)
18302c1e29fSAlexander Hansen {
18402c1e29fSAlexander Hansen     persistent_data::EventServiceConfig eventServiceConfig =
18502c1e29fSAlexander Hansen         persistent_data::EventServiceStore::getInstance()
18602c1e29fSAlexander Hansen             .getEventServiceConfig();
18702c1e29fSAlexander Hansen     if (!eventServiceConfig.enabled)
18802c1e29fSAlexander Hansen     {
18902c1e29fSAlexander Hansen         return false;
19002c1e29fSAlexander Hansen     }
19102c1e29fSAlexander Hansen 
19202c1e29fSAlexander Hansen     if (client)
19302c1e29fSAlexander Hansen     {
19402c1e29fSAlexander Hansen         client->sendDataWithCallback(
19502c1e29fSAlexander Hansen             std::move(msg), userSub->destinationUrl,
19602c1e29fSAlexander Hansen             static_cast<ensuressl::VerifyCertificate>(
19702c1e29fSAlexander Hansen                 userSub->verifyCertificate),
19802c1e29fSAlexander Hansen             userSub->httpHeaders, boost::beast::http::verb::post,
19902c1e29fSAlexander Hansen             std::bind_front(&Subscription::resHandler, this,
20002c1e29fSAlexander Hansen                             shared_from_this()));
20102c1e29fSAlexander Hansen         return true;
20202c1e29fSAlexander Hansen     }
20302c1e29fSAlexander Hansen 
20402c1e29fSAlexander Hansen     if (sseConn != nullptr)
20502c1e29fSAlexander Hansen     {
20602c1e29fSAlexander Hansen         eventSeqNum++;
20702c1e29fSAlexander Hansen         sseConn->sendSseEvent(std::to_string(eventSeqNum), msg);
20802c1e29fSAlexander Hansen     }
20902c1e29fSAlexander Hansen     return true;
21002c1e29fSAlexander Hansen }
21102c1e29fSAlexander Hansen 
212*81ee0e74SChandramohan Harkude bool Subscription::sendTestEventLog(TestEvent& testEvent)
21302c1e29fSAlexander Hansen {
21402c1e29fSAlexander Hansen     nlohmann::json::array_t logEntryArray;
21502c1e29fSAlexander Hansen     nlohmann::json& logEntryJson = logEntryArray.emplace_back();
21602c1e29fSAlexander Hansen 
217*81ee0e74SChandramohan Harkude     if (testEvent.eventGroupId)
218*81ee0e74SChandramohan Harkude     {
219*81ee0e74SChandramohan Harkude         logEntryJson["EventGroupId"] = *testEvent.eventGroupId;
220*81ee0e74SChandramohan Harkude     }
221*81ee0e74SChandramohan Harkude 
222*81ee0e74SChandramohan Harkude     if (testEvent.eventId)
223*81ee0e74SChandramohan Harkude     {
224*81ee0e74SChandramohan Harkude         logEntryJson["EventId"] = *testEvent.eventId;
225*81ee0e74SChandramohan Harkude     }
226*81ee0e74SChandramohan Harkude 
227*81ee0e74SChandramohan Harkude     if (testEvent.eventTimestamp)
228*81ee0e74SChandramohan Harkude     {
229*81ee0e74SChandramohan Harkude         logEntryJson["EventTimestamp"] = *testEvent.eventTimestamp;
230*81ee0e74SChandramohan Harkude     }
231*81ee0e74SChandramohan Harkude 
232*81ee0e74SChandramohan Harkude     if (testEvent.originOfCondition)
233*81ee0e74SChandramohan Harkude     {
234*81ee0e74SChandramohan Harkude         logEntryJson["OriginOfCondition"]["@odata.id"] =
235*81ee0e74SChandramohan Harkude             *testEvent.originOfCondition;
236*81ee0e74SChandramohan Harkude     }
237*81ee0e74SChandramohan Harkude     if (testEvent.severity)
238*81ee0e74SChandramohan Harkude     {
239*81ee0e74SChandramohan Harkude         logEntryJson["Severity"] = *testEvent.severity;
240*81ee0e74SChandramohan Harkude     }
241*81ee0e74SChandramohan Harkude 
242*81ee0e74SChandramohan Harkude     if (testEvent.message)
243*81ee0e74SChandramohan Harkude     {
244*81ee0e74SChandramohan Harkude         logEntryJson["Message"] = *testEvent.message;
245*81ee0e74SChandramohan Harkude     }
246*81ee0e74SChandramohan Harkude 
247*81ee0e74SChandramohan Harkude     if (testEvent.resolution)
248*81ee0e74SChandramohan Harkude     {
249*81ee0e74SChandramohan Harkude         logEntryJson["Resolution"] = *testEvent.resolution;
250*81ee0e74SChandramohan Harkude     }
251*81ee0e74SChandramohan Harkude 
252*81ee0e74SChandramohan Harkude     if (testEvent.messageId)
253*81ee0e74SChandramohan Harkude     {
254*81ee0e74SChandramohan Harkude         logEntryJson["MessageId"] = *testEvent.messageId;
255*81ee0e74SChandramohan Harkude     }
256*81ee0e74SChandramohan Harkude 
257*81ee0e74SChandramohan Harkude     if (testEvent.messageArgs)
258*81ee0e74SChandramohan Harkude     {
259*81ee0e74SChandramohan Harkude         logEntryJson["MessageArgs"] = *testEvent.messageArgs;
260*81ee0e74SChandramohan Harkude     }
26102c1e29fSAlexander Hansen     // MemberId is 0 : since we are sending one event record.
26202c1e29fSAlexander Hansen     logEntryJson["MemberId"] = "0";
26302c1e29fSAlexander Hansen 
26402c1e29fSAlexander Hansen     nlohmann::json msg;
26502c1e29fSAlexander Hansen     msg["@odata.type"] = "#Event.v1_4_0.Event";
26602c1e29fSAlexander Hansen     msg["Id"] = std::to_string(eventSeqNum);
26702c1e29fSAlexander Hansen     msg["Name"] = "Event Log";
26802c1e29fSAlexander Hansen     msg["Events"] = logEntryArray;
26902c1e29fSAlexander Hansen 
27002c1e29fSAlexander Hansen     std::string strMsg =
27102c1e29fSAlexander Hansen         msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
27202c1e29fSAlexander Hansen     return sendEventToSubscriber(std::move(strMsg));
27302c1e29fSAlexander Hansen }
27402c1e29fSAlexander Hansen 
27502c1e29fSAlexander Hansen void Subscription::filterAndSendEventLogs(
27602c1e29fSAlexander Hansen     const std::vector<EventLogObjectsType>& eventRecords)
27702c1e29fSAlexander Hansen {
27802c1e29fSAlexander Hansen     nlohmann::json::array_t logEntryArray;
27902c1e29fSAlexander Hansen     for (const EventLogObjectsType& logEntry : eventRecords)
28002c1e29fSAlexander Hansen     {
28102c1e29fSAlexander Hansen         std::vector<std::string_view> messageArgsView(
28202c1e29fSAlexander Hansen             logEntry.messageArgs.begin(), logEntry.messageArgs.end());
28302c1e29fSAlexander Hansen 
28402c1e29fSAlexander Hansen         nlohmann::json::object_t bmcLogEntry;
28502c1e29fSAlexander Hansen         if (event_log::formatEventLogEntry(
28602c1e29fSAlexander Hansen                 logEntry.id, logEntry.messageId, messageArgsView,
28702c1e29fSAlexander Hansen                 logEntry.timestamp, userSub->customText, bmcLogEntry) != 0)
28802c1e29fSAlexander Hansen         {
28902c1e29fSAlexander Hansen             BMCWEB_LOG_DEBUG("Read eventLog entry failed");
29002c1e29fSAlexander Hansen             continue;
29102c1e29fSAlexander Hansen         }
29202c1e29fSAlexander Hansen 
29302c1e29fSAlexander Hansen         if (!eventMatchesFilter(*userSub, bmcLogEntry, ""))
29402c1e29fSAlexander Hansen         {
29502c1e29fSAlexander Hansen             BMCWEB_LOG_DEBUG("Event {} did not match the filter",
29602c1e29fSAlexander Hansen                              nlohmann::json(bmcLogEntry).dump());
29702c1e29fSAlexander Hansen             continue;
29802c1e29fSAlexander Hansen         }
29902c1e29fSAlexander Hansen 
30002c1e29fSAlexander Hansen         if (filter)
30102c1e29fSAlexander Hansen         {
30202c1e29fSAlexander Hansen             if (!memberMatches(bmcLogEntry, *filter))
30302c1e29fSAlexander Hansen             {
30402c1e29fSAlexander Hansen                 BMCWEB_LOG_DEBUG("Filter didn't match");
30502c1e29fSAlexander Hansen                 continue;
30602c1e29fSAlexander Hansen             }
30702c1e29fSAlexander Hansen         }
30802c1e29fSAlexander Hansen 
30902c1e29fSAlexander Hansen         logEntryArray.emplace_back(std::move(bmcLogEntry));
31002c1e29fSAlexander Hansen     }
31102c1e29fSAlexander Hansen 
31202c1e29fSAlexander Hansen     if (logEntryArray.empty())
31302c1e29fSAlexander Hansen     {
31402c1e29fSAlexander Hansen         BMCWEB_LOG_DEBUG("No log entries available to be transferred.");
31502c1e29fSAlexander Hansen         return;
31602c1e29fSAlexander Hansen     }
31702c1e29fSAlexander Hansen 
31802c1e29fSAlexander Hansen     nlohmann::json msg;
31902c1e29fSAlexander Hansen     msg["@odata.type"] = "#Event.v1_4_0.Event";
32002c1e29fSAlexander Hansen     msg["Id"] = std::to_string(eventSeqNum);
32102c1e29fSAlexander Hansen     msg["Name"] = "Event Log";
32202c1e29fSAlexander Hansen     msg["Events"] = std::move(logEntryArray);
32302c1e29fSAlexander Hansen     std::string strMsg =
32402c1e29fSAlexander Hansen         msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
32502c1e29fSAlexander Hansen     sendEventToSubscriber(std::move(strMsg));
32602c1e29fSAlexander Hansen     eventSeqNum++;
32702c1e29fSAlexander Hansen }
32802c1e29fSAlexander Hansen 
32902c1e29fSAlexander Hansen void Subscription::filterAndSendReports(const std::string& reportId,
33002c1e29fSAlexander Hansen                                         const telemetry::TimestampReadings& var)
33102c1e29fSAlexander Hansen {
33202c1e29fSAlexander Hansen     boost::urls::url mrdUri = boost::urls::format(
33302c1e29fSAlexander Hansen         "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", reportId);
33402c1e29fSAlexander Hansen 
33502c1e29fSAlexander Hansen     // Empty list means no filter. Send everything.
33602c1e29fSAlexander Hansen     if (!userSub->metricReportDefinitions.empty())
33702c1e29fSAlexander Hansen     {
33802c1e29fSAlexander Hansen         if (std::ranges::find(userSub->metricReportDefinitions,
33902c1e29fSAlexander Hansen                               mrdUri.buffer()) ==
34002c1e29fSAlexander Hansen             userSub->metricReportDefinitions.end())
34102c1e29fSAlexander Hansen         {
34202c1e29fSAlexander Hansen             return;
34302c1e29fSAlexander Hansen         }
34402c1e29fSAlexander Hansen     }
34502c1e29fSAlexander Hansen 
34602c1e29fSAlexander Hansen     nlohmann::json msg;
34702c1e29fSAlexander Hansen     if (!telemetry::fillReport(msg, reportId, var))
34802c1e29fSAlexander Hansen     {
34902c1e29fSAlexander Hansen         BMCWEB_LOG_ERROR("Failed to fill the MetricReport for DBus "
35002c1e29fSAlexander Hansen                          "Report with id {}",
35102c1e29fSAlexander Hansen                          reportId);
35202c1e29fSAlexander Hansen         return;
35302c1e29fSAlexander Hansen     }
35402c1e29fSAlexander Hansen 
35502c1e29fSAlexander Hansen     // Context is set by user during Event subscription and it must be
35602c1e29fSAlexander Hansen     // set for MetricReport response.
35702c1e29fSAlexander Hansen     if (!userSub->customText.empty())
35802c1e29fSAlexander Hansen     {
35902c1e29fSAlexander Hansen         msg["Context"] = userSub->customText;
36002c1e29fSAlexander Hansen     }
36102c1e29fSAlexander Hansen 
36202c1e29fSAlexander Hansen     std::string strMsg =
36302c1e29fSAlexander Hansen         msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace);
36402c1e29fSAlexander Hansen     sendEventToSubscriber(std::move(strMsg));
36502c1e29fSAlexander Hansen }
36602c1e29fSAlexander Hansen 
36702c1e29fSAlexander Hansen void Subscription::updateRetryConfig(uint32_t retryAttempts,
36802c1e29fSAlexander Hansen                                      uint32_t retryTimeoutInterval)
36902c1e29fSAlexander Hansen {
37002c1e29fSAlexander Hansen     if (policy == nullptr)
37102c1e29fSAlexander Hansen     {
37202c1e29fSAlexander Hansen         BMCWEB_LOG_DEBUG("Retry policy was nullptr, ignoring set");
37302c1e29fSAlexander Hansen         return;
37402c1e29fSAlexander Hansen     }
37502c1e29fSAlexander Hansen     policy->maxRetryAttempts = retryAttempts;
37602c1e29fSAlexander Hansen     policy->retryIntervalSecs = std::chrono::seconds(retryTimeoutInterval);
37702c1e29fSAlexander Hansen }
37802c1e29fSAlexander Hansen 
37902c1e29fSAlexander Hansen uint64_t Subscription::getEventSeqNum() const
38002c1e29fSAlexander Hansen {
38102c1e29fSAlexander Hansen     return eventSeqNum;
38202c1e29fSAlexander Hansen }
38302c1e29fSAlexander Hansen 
38402c1e29fSAlexander Hansen bool Subscription::matchSseId(const crow::sse_socket::Connection& thisConn)
38502c1e29fSAlexander Hansen {
38602c1e29fSAlexander Hansen     return &thisConn == sseConn;
38702c1e29fSAlexander Hansen }
38802c1e29fSAlexander Hansen 
38902c1e29fSAlexander Hansen // Check used to indicate what response codes are valid as part of our retry
39002c1e29fSAlexander Hansen // policy.  2XX is considered acceptable
39102c1e29fSAlexander Hansen boost::system::error_code Subscription::retryRespHandler(unsigned int respCode)
39202c1e29fSAlexander Hansen {
39302c1e29fSAlexander Hansen     BMCWEB_LOG_DEBUG("Checking response code validity for SubscriptionEvent");
39402c1e29fSAlexander Hansen     if ((respCode < 200) || (respCode >= 300))
39502c1e29fSAlexander Hansen     {
39602c1e29fSAlexander Hansen         return boost::system::errc::make_error_code(
39702c1e29fSAlexander Hansen             boost::system::errc::result_out_of_range);
39802c1e29fSAlexander Hansen     }
39902c1e29fSAlexander Hansen 
40002c1e29fSAlexander Hansen     // Return 0 if the response code is valid
40102c1e29fSAlexander Hansen     return boost::system::errc::make_error_code(boost::system::errc::success);
40202c1e29fSAlexander Hansen }
40302c1e29fSAlexander Hansen 
40402c1e29fSAlexander Hansen } // namespace redfish
405