15e44e3d8SAppaRao Puli #pragma once 25e44e3d8SAppaRao Puli 3*f80a87f2SEd Tanous #include "filter_expr_executor.hpp" 45b90429aSEd Tanous #include "privileges.hpp" 55b90429aSEd Tanous #include "registries/privilege_registry.hpp" 65b90429aSEd Tanous 75e44e3d8SAppaRao Puli #include <app.hpp> 85e44e3d8SAppaRao Puli #include <event_service_manager.hpp> 95e44e3d8SAppaRao Puli 105b90429aSEd Tanous #include <memory> 115b90429aSEd Tanous #include <string> 125b90429aSEd Tanous 135e44e3d8SAppaRao Puli namespace redfish 145e44e3d8SAppaRao Puli { 155e44e3d8SAppaRao Puli 16*f80a87f2SEd Tanous inline void createSubscription(crow::sse_socket::Connection& conn, 17*f80a87f2SEd Tanous const crow::Request& req) 185e44e3d8SAppaRao Puli { 195e44e3d8SAppaRao Puli EventServiceManager& manager = 205e44e3d8SAppaRao Puli EventServiceManager::getInstance(&conn.getIoContext()); 215e44e3d8SAppaRao Puli if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) || 225e44e3d8SAppaRao Puli manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions) 235e44e3d8SAppaRao Puli { 2462598e31SEd Tanous BMCWEB_LOG_WARNING("Max SSE subscriptions reached"); 255e44e3d8SAppaRao Puli conn.close("Max SSE subscriptions reached"); 265e44e3d8SAppaRao Puli return; 275e44e3d8SAppaRao Puli } 28*f80a87f2SEd Tanous 29*f80a87f2SEd Tanous std::optional<filter_ast::LogicalAnd> filter; 30*f80a87f2SEd Tanous 31*f80a87f2SEd Tanous boost::urls::params_base::iterator filterIt = 32*f80a87f2SEd Tanous req.url().params().find("$filter"); 33*f80a87f2SEd Tanous 34*f80a87f2SEd Tanous if (filterIt != req.url().params().end()) 35*f80a87f2SEd Tanous { 36*f80a87f2SEd Tanous std::string_view filterValue = (*filterIt).value; 37*f80a87f2SEd Tanous filter = parseFilter(filterValue); 38*f80a87f2SEd Tanous if (!filter) 39*f80a87f2SEd Tanous { 40*f80a87f2SEd Tanous conn.close(std::format("Bad $filter param: {}", filterValue)); 41*f80a87f2SEd Tanous return; 42*f80a87f2SEd Tanous } 43*f80a87f2SEd Tanous } 44*f80a87f2SEd Tanous 45*f80a87f2SEd Tanous std::string lastEventId(req.getHeaderValue("Last-Event-Id")); 46*f80a87f2SEd Tanous 475e44e3d8SAppaRao Puli std::shared_ptr<redfish::Subscription> subValue = 485e44e3d8SAppaRao Puli std::make_shared<redfish::Subscription>(conn); 495e44e3d8SAppaRao Puli 505e44e3d8SAppaRao Puli // GET on this URI means, Its SSE subscriptionType. 515e44e3d8SAppaRao Puli subValue->subscriptionType = redfish::subscriptionTypeSSE; 525e44e3d8SAppaRao Puli 535e44e3d8SAppaRao Puli subValue->protocol = "Redfish"; 545e44e3d8SAppaRao Puli subValue->retryPolicy = "TerminateAfterRetries"; 555e44e3d8SAppaRao Puli subValue->eventFormatType = "Event"; 56*f80a87f2SEd Tanous subValue->filter = filter; 575e44e3d8SAppaRao Puli 58*f80a87f2SEd Tanous std::string id = manager.addSSESubscription(subValue, lastEventId); 595e44e3d8SAppaRao Puli if (id.empty()) 605e44e3d8SAppaRao Puli { 615e44e3d8SAppaRao Puli conn.close("Internal Error"); 625e44e3d8SAppaRao Puli } 635e44e3d8SAppaRao Puli } 645e44e3d8SAppaRao Puli 655e44e3d8SAppaRao Puli inline void deleteSubscription(crow::sse_socket::Connection& conn) 665e44e3d8SAppaRao Puli { 675e44e3d8SAppaRao Puli redfish::EventServiceManager::getInstance(&conn.getIoContext()) 685e44e3d8SAppaRao Puli .deleteSseSubscription(conn); 695e44e3d8SAppaRao Puli } 705e44e3d8SAppaRao Puli 715e44e3d8SAppaRao Puli inline void requestRoutesEventServiceSse(App& app) 725e44e3d8SAppaRao Puli { 735e44e3d8SAppaRao Puli // Note, this endpoint is given the same privilege level as creating a 745e44e3d8SAppaRao Puli // subscription, because functionally, that's the operation being done 755e44e3d8SAppaRao Puli BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE") 765e44e3d8SAppaRao Puli .privileges(redfish::privileges::postEventDestinationCollection) 775e44e3d8SAppaRao Puli .serverSentEvent() 785e44e3d8SAppaRao Puli .onopen(createSubscription) 795e44e3d8SAppaRao Puli .onclose(deleteSubscription); 805e44e3d8SAppaRao Puli } 815e44e3d8SAppaRao Puli } // namespace redfish 82