blob: 86bf1d18e06383e549e080bb0d06a49ab7e020ac [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
AppaRao Puli5e44e3d2021-03-16 15:37:24 +00003#pragma once
4
Ed Tanousd7857202025-01-28 15:32:26 -08005#include "filter_expr_parser_ast.hpp"
6#include "filter_expr_printer.hpp"
7#include "http_request.hpp"
8#include "logging.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -07009#include "registries/privilege_registry.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "server_sent_event.hpp"
11#include "subscription.hpp"
Ed Tanous5b904292024-04-16 11:10:17 -070012
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000013#include <app.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080014#include <boost/url/params_base.hpp>
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000015#include <event_service_manager.hpp>
16
Ed Tanousd7857202025-01-28 15:32:26 -080017#include <format>
Ed Tanous5b904292024-04-16 11:10:17 -070018#include <memory>
Ed Tanousd7857202025-01-28 15:32:26 -080019#include <optional>
Ed Tanous5b904292024-04-16 11:10:17 -070020#include <string>
21
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000022namespace redfish
23{
24
Ed Tanousf80a87f2024-06-16 12:10:33 -070025inline void createSubscription(crow::sse_socket::Connection& conn,
26 const crow::Request& req)
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000027{
28 EventServiceManager& manager =
29 EventServiceManager::getInstance(&conn.getIoContext());
30 if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) ||
31 manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions)
32 {
Ed Tanous62598e32023-07-17 17:06:25 -070033 BMCWEB_LOG_WARNING("Max SSE subscriptions reached");
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000034 conn.close("Max SSE subscriptions reached");
35 return;
36 }
Ed Tanousf80a87f2024-06-16 12:10:33 -070037
38 std::optional<filter_ast::LogicalAnd> filter;
39
40 boost::urls::params_base::iterator filterIt =
41 req.url().params().find("$filter");
42
43 if (filterIt != req.url().params().end())
44 {
45 std::string_view filterValue = (*filterIt).value;
46 filter = parseFilter(filterValue);
47 if (!filter)
48 {
49 conn.close(std::format("Bad $filter param: {}", filterValue));
50 return;
51 }
52 }
53
54 std::string lastEventId(req.getHeaderValue("Last-Event-Id"));
55
Ed Tanous4b712a22023-08-02 12:56:52 -070056 std::shared_ptr<Subscription> subValue =
57 std::make_shared<Subscription>(conn);
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000058
Myung Bae5fe4ef32024-10-19 09:56:02 -040059 if (subValue->userSub == nullptr)
60 {
61 BMCWEB_LOG_ERROR("Subscription data is null");
62 conn.close("Internal Error");
63 return;
64 }
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000065
Myung Bae5fe4ef32024-10-19 09:56:02 -040066 // GET on this URI means, Its SSE subscriptionType.
67 subValue->userSub->subscriptionType = redfish::subscriptionTypeSSE;
68
69 subValue->userSub->protocol = "Redfish";
70 subValue->userSub->retryPolicy = "TerminateAfterRetries";
71 subValue->userSub->eventFormatType = "Event";
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000072
Ed Tanousf80a87f2024-06-16 12:10:33 -070073 std::string id = manager.addSSESubscription(subValue, lastEventId);
AppaRao Puli5e44e3d2021-03-16 15:37:24 +000074 if (id.empty())
75 {
76 conn.close("Internal Error");
77 }
78}
79
80inline void deleteSubscription(crow::sse_socket::Connection& conn)
81{
82 redfish::EventServiceManager::getInstance(&conn.getIoContext())
83 .deleteSseSubscription(conn);
84}
85
86inline void requestRoutesEventServiceSse(App& app)
87{
88 // Note, this endpoint is given the same privilege level as creating a
89 // subscription, because functionally, that's the operation being done
90 BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE")
91 .privileges(redfish::privileges::postEventDestinationCollection)
92 .serverSentEvent()
93 .onopen(createSubscription)
94 .onclose(deleteSubscription);
95}
96} // namespace redfish