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 
createSubscription(crow::sse_socket::Connection & conn,const crow::Request & req)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<redfish::Subscription> subValue =
48         std::make_shared<redfish::Subscription>(conn);
49 
50     // GET on this URI means, Its SSE subscriptionType.
51     subValue->subscriptionType = redfish::subscriptionTypeSSE;
52 
53     subValue->protocol = "Redfish";
54     subValue->retryPolicy = "TerminateAfterRetries";
55     subValue->eventFormatType = "Event";
56     subValue->filter = filter;
57 
58     std::string id = manager.addSSESubscription(subValue, lastEventId);
59     if (id.empty())
60     {
61         conn.close("Internal Error");
62     }
63 }
64 
deleteSubscription(crow::sse_socket::Connection & conn)65 inline void deleteSubscription(crow::sse_socket::Connection& conn)
66 {
67     redfish::EventServiceManager::getInstance(&conn.getIoContext())
68         .deleteSseSubscription(conn);
69 }
70 
requestRoutesEventServiceSse(App & app)71 inline void requestRoutesEventServiceSse(App& app)
72 {
73     // Note, this endpoint is given the same privilege level as creating a
74     // subscription, because functionally, that's the operation being done
75     BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE")
76         .privileges(redfish::privileges::postEventDestinationCollection)
77         .serverSentEvent()
78         .onopen(createSubscription)
79         .onclose(deleteSubscription);
80 }
81 } // namespace redfish
82