1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #pragma once 4 5 #include "filter_expr_executor.hpp" 6 #include "privileges.hpp" 7 #include "registries/privilege_registry.hpp" 8 9 #include <app.hpp> 10 #include <event_service_manager.hpp> 11 12 #include <memory> 13 #include <string> 14 15 namespace redfish 16 { 17 18 inline void createSubscription(crow::sse_socket::Connection& conn, 19 const crow::Request& req) 20 { 21 EventServiceManager& manager = 22 EventServiceManager::getInstance(&conn.getIoContext()); 23 if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) || 24 manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions) 25 { 26 BMCWEB_LOG_WARNING("Max SSE subscriptions reached"); 27 conn.close("Max SSE subscriptions reached"); 28 return; 29 } 30 31 std::optional<filter_ast::LogicalAnd> filter; 32 33 boost::urls::params_base::iterator filterIt = 34 req.url().params().find("$filter"); 35 36 if (filterIt != req.url().params().end()) 37 { 38 std::string_view filterValue = (*filterIt).value; 39 filter = parseFilter(filterValue); 40 if (!filter) 41 { 42 conn.close(std::format("Bad $filter param: {}", filterValue)); 43 return; 44 } 45 } 46 47 std::string lastEventId(req.getHeaderValue("Last-Event-Id")); 48 49 std::shared_ptr<Subscription> subValue = 50 std::make_shared<Subscription>(conn); 51 52 if (subValue->userSub == nullptr) 53 { 54 BMCWEB_LOG_ERROR("Subscription data is null"); 55 conn.close("Internal Error"); 56 return; 57 } 58 59 // GET on this URI means, Its SSE subscriptionType. 60 subValue->userSub->subscriptionType = redfish::subscriptionTypeSSE; 61 62 subValue->userSub->protocol = "Redfish"; 63 subValue->userSub->retryPolicy = "TerminateAfterRetries"; 64 subValue->userSub->eventFormatType = "Event"; 65 66 std::string id = manager.addSSESubscription(subValue, lastEventId); 67 if (id.empty()) 68 { 69 conn.close("Internal Error"); 70 } 71 } 72 73 inline void deleteSubscription(crow::sse_socket::Connection& conn) 74 { 75 redfish::EventServiceManager::getInstance(&conn.getIoContext()) 76 .deleteSseSubscription(conn); 77 } 78 79 inline void requestRoutesEventServiceSse(App& app) 80 { 81 // Note, this endpoint is given the same privilege level as creating a 82 // subscription, because functionally, that's the operation being done 83 BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE") 84 .privileges(redfish::privileges::postEventDestinationCollection) 85 .serverSentEvent() 86 .onopen(createSubscription) 87 .onclose(deleteSubscription); 88 } 89 } // namespace redfish 90