140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 35e44e3d8SAppaRao Puli #pragma once 45e44e3d8SAppaRao Puli 5d7857201SEd Tanous #include "filter_expr_parser_ast.hpp" 6d7857201SEd Tanous #include "filter_expr_printer.hpp" 7d7857201SEd Tanous #include "http_request.hpp" 8d7857201SEd Tanous #include "logging.hpp" 95b90429aSEd Tanous #include "registries/privilege_registry.hpp" 10d7857201SEd Tanous #include "server_sent_event.hpp" 11d7857201SEd Tanous #include "subscription.hpp" 125b90429aSEd Tanous 135e44e3d8SAppaRao Puli #include <app.hpp> 14d7857201SEd Tanous #include <boost/url/params_base.hpp> 155e44e3d8SAppaRao Puli #include <event_service_manager.hpp> 165e44e3d8SAppaRao Puli 17d7857201SEd Tanous #include <format> 185b90429aSEd Tanous #include <memory> 19d7857201SEd Tanous #include <optional> 205b90429aSEd Tanous #include <string> 215b90429aSEd Tanous 225e44e3d8SAppaRao Puli namespace redfish 235e44e3d8SAppaRao Puli { 245e44e3d8SAppaRao Puli 25f80a87f2SEd Tanous inline void createSubscription(crow::sse_socket::Connection& conn, 26f80a87f2SEd Tanous const crow::Request& req) 275e44e3d8SAppaRao Puli { 289838eb20SEd Tanous EventServiceManager& manager = EventServiceManager::getInstance(); 295e44e3d8SAppaRao Puli if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) || 305e44e3d8SAppaRao Puli manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions) 315e44e3d8SAppaRao Puli { 3262598e31SEd Tanous BMCWEB_LOG_WARNING("Max SSE subscriptions reached"); 335e44e3d8SAppaRao Puli conn.close("Max SSE subscriptions reached"); 345e44e3d8SAppaRao Puli return; 355e44e3d8SAppaRao Puli } 36f80a87f2SEd Tanous 37f80a87f2SEd Tanous std::optional<filter_ast::LogicalAnd> filter; 38f80a87f2SEd Tanous 39f80a87f2SEd Tanous boost::urls::params_base::iterator filterIt = 40f80a87f2SEd Tanous req.url().params().find("$filter"); 41f80a87f2SEd Tanous 42f80a87f2SEd Tanous if (filterIt != req.url().params().end()) 43f80a87f2SEd Tanous { 44*3d158643SEd Tanous const boost::urls::param& filterParam = *filterIt; 45*3d158643SEd Tanous filter = parseFilter(filterParam.value); 46f80a87f2SEd Tanous if (!filter) 47f80a87f2SEd Tanous { 48*3d158643SEd Tanous conn.close(std::format("Bad $filter param: {}", filterParam.value)); 49f80a87f2SEd Tanous return; 50f80a87f2SEd Tanous } 51f80a87f2SEd Tanous } 52f80a87f2SEd Tanous 53f80a87f2SEd Tanous std::string lastEventId(req.getHeaderValue("Last-Event-Id")); 54f80a87f2SEd Tanous 554b712a29SEd Tanous std::shared_ptr<Subscription> subValue = 564b712a29SEd Tanous std::make_shared<Subscription>(conn); 575e44e3d8SAppaRao Puli 585fe4ef35SMyung Bae if (subValue->userSub == nullptr) 595fe4ef35SMyung Bae { 605fe4ef35SMyung Bae BMCWEB_LOG_ERROR("Subscription data is null"); 615fe4ef35SMyung Bae conn.close("Internal Error"); 625fe4ef35SMyung Bae return; 635fe4ef35SMyung Bae } 645e44e3d8SAppaRao Puli 655fe4ef35SMyung Bae // GET on this URI means, Its SSE subscriptionType. 665fe4ef35SMyung Bae subValue->userSub->subscriptionType = redfish::subscriptionTypeSSE; 675fe4ef35SMyung Bae 685fe4ef35SMyung Bae subValue->userSub->protocol = "Redfish"; 695fe4ef35SMyung Bae subValue->userSub->retryPolicy = "TerminateAfterRetries"; 705fe4ef35SMyung Bae subValue->userSub->eventFormatType = "Event"; 715e44e3d8SAppaRao Puli 72f80a87f2SEd Tanous std::string id = manager.addSSESubscription(subValue, lastEventId); 735e44e3d8SAppaRao Puli if (id.empty()) 745e44e3d8SAppaRao Puli { 755e44e3d8SAppaRao Puli conn.close("Internal Error"); 765e44e3d8SAppaRao Puli } 775e44e3d8SAppaRao Puli } 785e44e3d8SAppaRao Puli 795e44e3d8SAppaRao Puli inline void deleteSubscription(crow::sse_socket::Connection& conn) 805e44e3d8SAppaRao Puli { 819838eb20SEd Tanous EventServiceManager::getInstance().deleteSseSubscription(conn); 825e44e3d8SAppaRao Puli } 835e44e3d8SAppaRao Puli 845e44e3d8SAppaRao Puli inline void requestRoutesEventServiceSse(App& app) 855e44e3d8SAppaRao Puli { 865e44e3d8SAppaRao Puli // Note, this endpoint is given the same privilege level as creating a 875e44e3d8SAppaRao Puli // subscription, because functionally, that's the operation being done 885e44e3d8SAppaRao Puli BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE") 895e44e3d8SAppaRao Puli .privileges(redfish::privileges::postEventDestinationCollection) 905e44e3d8SAppaRao Puli .serverSentEvent() 915e44e3d8SAppaRao Puli .onopen(createSubscription) 925e44e3d8SAppaRao Puli .onclose(deleteSubscription); 935e44e3d8SAppaRao Puli } 945e44e3d8SAppaRao Puli } // namespace redfish 95