xref: /openbmc/bmcweb/features/redfish/lib/eventservice_sse.hpp (revision 3577e44683a5ade8ad02a6418984b56f4ca2bcac)
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