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