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> 14*3577e446SEd Tanous #include <boost/url/param.hpp> 15d7857201SEd Tanous #include <boost/url/params_base.hpp> 165e44e3d8SAppaRao Puli #include <event_service_manager.hpp> 175e44e3d8SAppaRao Puli 18d7857201SEd Tanous #include <format> 195b90429aSEd Tanous #include <memory> 20d7857201SEd Tanous #include <optional> 215b90429aSEd Tanous #include <string> 225b90429aSEd Tanous 235e44e3d8SAppaRao Puli namespace redfish 245e44e3d8SAppaRao Puli { 255e44e3d8SAppaRao Puli 26f80a87f2SEd Tanous inline void createSubscription(crow::sse_socket::Connection& conn, 27f80a87f2SEd Tanous const crow::Request& req) 285e44e3d8SAppaRao Puli { 299838eb20SEd Tanous EventServiceManager& manager = EventServiceManager::getInstance(); 305e44e3d8SAppaRao Puli if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) || 315e44e3d8SAppaRao Puli manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions) 325e44e3d8SAppaRao Puli { 3362598e31SEd Tanous BMCWEB_LOG_WARNING("Max SSE subscriptions reached"); 345e44e3d8SAppaRao Puli conn.close("Max SSE subscriptions reached"); 355e44e3d8SAppaRao Puli return; 365e44e3d8SAppaRao Puli } 37f80a87f2SEd Tanous 38f80a87f2SEd Tanous std::optional<filter_ast::LogicalAnd> filter; 39f80a87f2SEd Tanous 40f80a87f2SEd Tanous boost::urls::params_base::iterator filterIt = 41f80a87f2SEd Tanous req.url().params().find("$filter"); 42f80a87f2SEd Tanous 43f80a87f2SEd Tanous if (filterIt != req.url().params().end()) 44f80a87f2SEd Tanous { 453d158643SEd Tanous const boost::urls::param& filterParam = *filterIt; 463d158643SEd Tanous filter = parseFilter(filterParam.value); 47f80a87f2SEd Tanous if (!filter) 48f80a87f2SEd Tanous { 493d158643SEd Tanous conn.close(std::format("Bad $filter param: {}", filterParam.value)); 50f80a87f2SEd Tanous return; 51f80a87f2SEd Tanous } 52f80a87f2SEd Tanous } 53f80a87f2SEd Tanous 54f80a87f2SEd Tanous std::string lastEventId(req.getHeaderValue("Last-Event-Id")); 55f80a87f2SEd Tanous 564b712a29SEd Tanous std::shared_ptr<Subscription> subValue = 574b712a29SEd Tanous std::make_shared<Subscription>(conn); 585e44e3d8SAppaRao Puli 595fe4ef35SMyung Bae if (subValue->userSub == nullptr) 605fe4ef35SMyung Bae { 615fe4ef35SMyung Bae BMCWEB_LOG_ERROR("Subscription data is null"); 625fe4ef35SMyung Bae conn.close("Internal Error"); 635fe4ef35SMyung Bae return; 645fe4ef35SMyung Bae } 655e44e3d8SAppaRao Puli 665fe4ef35SMyung Bae // GET on this URI means, Its SSE subscriptionType. 675fe4ef35SMyung Bae subValue->userSub->subscriptionType = redfish::subscriptionTypeSSE; 685fe4ef35SMyung Bae 695fe4ef35SMyung Bae subValue->userSub->protocol = "Redfish"; 705fe4ef35SMyung Bae subValue->userSub->retryPolicy = "TerminateAfterRetries"; 715fe4ef35SMyung Bae subValue->userSub->eventFormatType = "Event"; 725e44e3d8SAppaRao Puli 73f80a87f2SEd Tanous std::string id = manager.addSSESubscription(subValue, lastEventId); 745e44e3d8SAppaRao Puli if (id.empty()) 755e44e3d8SAppaRao Puli { 765e44e3d8SAppaRao Puli conn.close("Internal Error"); 775e44e3d8SAppaRao Puli } 785e44e3d8SAppaRao Puli } 795e44e3d8SAppaRao Puli 805e44e3d8SAppaRao Puli inline void deleteSubscription(crow::sse_socket::Connection& conn) 815e44e3d8SAppaRao Puli { 829838eb20SEd Tanous EventServiceManager::getInstance().deleteSseSubscription(conn); 835e44e3d8SAppaRao Puli } 845e44e3d8SAppaRao Puli 855e44e3d8SAppaRao Puli inline void requestRoutesEventServiceSse(App& app) 865e44e3d8SAppaRao Puli { 875e44e3d8SAppaRao Puli // Note, this endpoint is given the same privilege level as creating a 885e44e3d8SAppaRao Puli // subscription, because functionally, that's the operation being done 895e44e3d8SAppaRao Puli BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE") 905e44e3d8SAppaRao Puli .privileges(redfish::privileges::postEventDestinationCollection) 915e44e3d8SAppaRao Puli .serverSentEvent() 925e44e3d8SAppaRao Puli .onopen(createSubscription) 935e44e3d8SAppaRao Puli .onclose(deleteSubscription); 945e44e3d8SAppaRao Puli } 955e44e3d8SAppaRao Puli } // namespace redfish 96