xref: /openbmc/bmcweb/redfish-core/lib/eventservice_sse.hpp (revision 4b712a29debc1a0860cc04850b262203cad402a5)
1 #pragma once
2 
3 #include "filter_expr_executor.hpp"
4 #include "privileges.hpp"
5 #include "registries/privilege_registry.hpp"
6 
7 #include <app.hpp>
8 #include <event_service_manager.hpp>
9 
10 #include <memory>
11 #include <string>
12 
13 namespace redfish
14 {
15 
16 inline void createSubscription(crow::sse_socket::Connection& conn,
17                                const crow::Request& req)
18 {
19     EventServiceManager& manager =
20         EventServiceManager::getInstance(&conn.getIoContext());
21     if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) ||
22         manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions)
23     {
24         BMCWEB_LOG_WARNING("Max SSE subscriptions reached");
25         conn.close("Max SSE subscriptions reached");
26         return;
27     }
28 
29     std::optional<filter_ast::LogicalAnd> filter;
30 
31     boost::urls::params_base::iterator filterIt =
32         req.url().params().find("$filter");
33 
34     if (filterIt != req.url().params().end())
35     {
36         std::string_view filterValue = (*filterIt).value;
37         filter = parseFilter(filterValue);
38         if (!filter)
39         {
40             conn.close(std::format("Bad $filter param: {}", filterValue));
41             return;
42         }
43     }
44 
45     std::string lastEventId(req.getHeaderValue("Last-Event-Id"));
46 
47     std::shared_ptr<Subscription> subValue =
48         std::make_shared<Subscription>(conn);
49 
50     // GET on this URI means, Its SSE subscriptionType.
51     subValue->userSub.subscriptionType = redfish::subscriptionTypeSSE;
52 
53     subValue->userSub.protocol = "Redfish";
54     subValue->userSub.retryPolicy = "TerminateAfterRetries";
55     subValue->userSub.eventFormatType = "Event";
56 
57     std::string id = manager.addSSESubscription(subValue, lastEventId);
58     if (id.empty())
59     {
60         conn.close("Internal Error");
61     }
62 }
63 
64 inline void deleteSubscription(crow::sse_socket::Connection& conn)
65 {
66     redfish::EventServiceManager::getInstance(&conn.getIoContext())
67         .deleteSseSubscription(conn);
68 }
69 
70 inline void requestRoutesEventServiceSse(App& app)
71 {
72     // Note, this endpoint is given the same privilege level as creating a
73     // subscription, because functionally, that's the operation being done
74     BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE")
75         .privileges(redfish::privileges::postEventDestinationCollection)
76         .serverSentEvent()
77         .onopen(createSubscription)
78         .onclose(deleteSubscription);
79 }
80 } // namespace redfish
81