xref: /openbmc/bmcweb/features/redfish/lib/eventservice_sse.hpp (revision 40e9b92ec19acffb46f83a6e55b18974da5d708e)
1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
35e44e3d8SAppaRao Puli #pragma once
45e44e3d8SAppaRao Puli 
5f80a87f2SEd Tanous #include "filter_expr_executor.hpp"
65b90429aSEd Tanous #include "privileges.hpp"
75b90429aSEd Tanous #include "registries/privilege_registry.hpp"
85b90429aSEd Tanous 
95e44e3d8SAppaRao Puli #include <app.hpp>
105e44e3d8SAppaRao Puli #include <event_service_manager.hpp>
115e44e3d8SAppaRao Puli 
125b90429aSEd Tanous #include <memory>
135b90429aSEd Tanous #include <string>
145b90429aSEd Tanous 
155e44e3d8SAppaRao Puli namespace redfish
165e44e3d8SAppaRao Puli {
175e44e3d8SAppaRao Puli 
18f80a87f2SEd Tanous inline void createSubscription(crow::sse_socket::Connection& conn,
19f80a87f2SEd Tanous                                const crow::Request& req)
205e44e3d8SAppaRao Puli {
215e44e3d8SAppaRao Puli     EventServiceManager& manager =
225e44e3d8SAppaRao Puli         EventServiceManager::getInstance(&conn.getIoContext());
235e44e3d8SAppaRao Puli     if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) ||
245e44e3d8SAppaRao Puli         manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions)
255e44e3d8SAppaRao Puli     {
2662598e31SEd Tanous         BMCWEB_LOG_WARNING("Max SSE subscriptions reached");
275e44e3d8SAppaRao Puli         conn.close("Max SSE subscriptions reached");
285e44e3d8SAppaRao Puli         return;
295e44e3d8SAppaRao Puli     }
30f80a87f2SEd Tanous 
31f80a87f2SEd Tanous     std::optional<filter_ast::LogicalAnd> filter;
32f80a87f2SEd Tanous 
33f80a87f2SEd Tanous     boost::urls::params_base::iterator filterIt =
34f80a87f2SEd Tanous         req.url().params().find("$filter");
35f80a87f2SEd Tanous 
36f80a87f2SEd Tanous     if (filterIt != req.url().params().end())
37f80a87f2SEd Tanous     {
38f80a87f2SEd Tanous         std::string_view filterValue = (*filterIt).value;
39f80a87f2SEd Tanous         filter = parseFilter(filterValue);
40f80a87f2SEd Tanous         if (!filter)
41f80a87f2SEd Tanous         {
42f80a87f2SEd Tanous             conn.close(std::format("Bad $filter param: {}", filterValue));
43f80a87f2SEd Tanous             return;
44f80a87f2SEd Tanous         }
45f80a87f2SEd Tanous     }
46f80a87f2SEd Tanous 
47f80a87f2SEd Tanous     std::string lastEventId(req.getHeaderValue("Last-Event-Id"));
48f80a87f2SEd Tanous 
494b712a29SEd Tanous     std::shared_ptr<Subscription> subValue =
504b712a29SEd Tanous         std::make_shared<Subscription>(conn);
515e44e3d8SAppaRao Puli 
525fe4ef35SMyung Bae     if (subValue->userSub == nullptr)
535fe4ef35SMyung Bae     {
545fe4ef35SMyung Bae         BMCWEB_LOG_ERROR("Subscription data is null");
555fe4ef35SMyung Bae         conn.close("Internal Error");
565fe4ef35SMyung Bae         return;
575fe4ef35SMyung Bae     }
585e44e3d8SAppaRao Puli 
595fe4ef35SMyung Bae     // GET on this URI means, Its SSE subscriptionType.
605fe4ef35SMyung Bae     subValue->userSub->subscriptionType = redfish::subscriptionTypeSSE;
615fe4ef35SMyung Bae 
625fe4ef35SMyung Bae     subValue->userSub->protocol = "Redfish";
635fe4ef35SMyung Bae     subValue->userSub->retryPolicy = "TerminateAfterRetries";
645fe4ef35SMyung Bae     subValue->userSub->eventFormatType = "Event";
655e44e3d8SAppaRao Puli 
66f80a87f2SEd Tanous     std::string id = manager.addSSESubscription(subValue, lastEventId);
675e44e3d8SAppaRao Puli     if (id.empty())
685e44e3d8SAppaRao Puli     {
695e44e3d8SAppaRao Puli         conn.close("Internal Error");
705e44e3d8SAppaRao Puli     }
715e44e3d8SAppaRao Puli }
725e44e3d8SAppaRao Puli 
735e44e3d8SAppaRao Puli inline void deleteSubscription(crow::sse_socket::Connection& conn)
745e44e3d8SAppaRao Puli {
755e44e3d8SAppaRao Puli     redfish::EventServiceManager::getInstance(&conn.getIoContext())
765e44e3d8SAppaRao Puli         .deleteSseSubscription(conn);
775e44e3d8SAppaRao Puli }
785e44e3d8SAppaRao Puli 
795e44e3d8SAppaRao Puli inline void requestRoutesEventServiceSse(App& app)
805e44e3d8SAppaRao Puli {
815e44e3d8SAppaRao Puli     // Note, this endpoint is given the same privilege level as creating a
825e44e3d8SAppaRao Puli     // subscription, because functionally, that's the operation being done
835e44e3d8SAppaRao Puli     BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE")
845e44e3d8SAppaRao Puli         .privileges(redfish::privileges::postEventDestinationCollection)
855e44e3d8SAppaRao Puli         .serverSentEvent()
865e44e3d8SAppaRao Puli         .onopen(createSubscription)
875e44e3d8SAppaRao Puli         .onclose(deleteSubscription);
885e44e3d8SAppaRao Puli }
895e44e3d8SAppaRao Puli } // namespace redfish
90