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