| Ed Tanous | 40e9b92 | 2024-09-10 13:50:16 -0700 | [diff] [blame] | 1 | // SPDX-License-Identifier: Apache-2.0 | 
|  | 2 | // SPDX-FileCopyrightText: Copyright OpenBMC Authors | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 3 | #pragma once | 
|  | 4 |  | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 5 | #include "filter_expr_parser_ast.hpp" | 
|  | 6 | #include "filter_expr_printer.hpp" | 
|  | 7 | #include "http_request.hpp" | 
|  | 8 | #include "logging.hpp" | 
| Ed Tanous | 5b90429 | 2024-04-16 11:10:17 -0700 | [diff] [blame] | 9 | #include "registries/privilege_registry.hpp" | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 10 | #include "server_sent_event.hpp" | 
|  | 11 | #include "subscription.hpp" | 
| Ed Tanous | 5b90429 | 2024-04-16 11:10:17 -0700 | [diff] [blame] | 12 |  | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 13 | #include <app.hpp> | 
| Ed Tanous | 3577e44 | 2025-08-19 19:34:00 -0700 | [diff] [blame] | 14 | #include <boost/url/param.hpp> | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 15 | #include <boost/url/params_base.hpp> | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 16 | #include <event_service_manager.hpp> | 
|  | 17 |  | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 18 | #include <format> | 
| Ed Tanous | 5b90429 | 2024-04-16 11:10:17 -0700 | [diff] [blame] | 19 | #include <memory> | 
| Ed Tanous | d785720 | 2025-01-28 15:32:26 -0800 | [diff] [blame] | 20 | #include <optional> | 
| Ed Tanous | 5b90429 | 2024-04-16 11:10:17 -0700 | [diff] [blame] | 21 | #include <string> | 
|  | 22 |  | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 23 | namespace redfish | 
|  | 24 | { | 
|  | 25 |  | 
| Ed Tanous | f80a87f | 2024-06-16 12:10:33 -0700 | [diff] [blame] | 26 | inline void createSubscription(crow::sse_socket::Connection& conn, | 
|  | 27 | const crow::Request& req) | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 28 | { | 
| Ed Tanous | 9838eb2 | 2025-01-29 16:24:42 -0800 | [diff] [blame] | 29 | EventServiceManager& manager = EventServiceManager::getInstance(); | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 30 | if ((manager.getNumberOfSubscriptions() >= maxNoOfSubscriptions) || | 
|  | 31 | manager.getNumberOfSSESubscriptions() >= maxNoOfSSESubscriptions) | 
|  | 32 | { | 
| Ed Tanous | 62598e3 | 2023-07-17 17:06:25 -0700 | [diff] [blame] | 33 | BMCWEB_LOG_WARNING("Max SSE subscriptions reached"); | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 34 | conn.close("Max SSE subscriptions reached"); | 
|  | 35 | return; | 
|  | 36 | } | 
| Ed Tanous | f80a87f | 2024-06-16 12:10:33 -0700 | [diff] [blame] | 37 |  | 
|  | 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 | { | 
| Ed Tanous | 3d15864 | 2025-05-12 14:20:49 -0700 | [diff] [blame] | 45 | const boost::urls::param& filterParam = *filterIt; | 
|  | 46 | filter = parseFilter(filterParam.value); | 
| Ed Tanous | f80a87f | 2024-06-16 12:10:33 -0700 | [diff] [blame] | 47 | if (!filter) | 
|  | 48 | { | 
| Ed Tanous | 3d15864 | 2025-05-12 14:20:49 -0700 | [diff] [blame] | 49 | conn.close(std::format("Bad $filter param: {}", filterParam.value)); | 
| Ed Tanous | f80a87f | 2024-06-16 12:10:33 -0700 | [diff] [blame] | 50 | return; | 
|  | 51 | } | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | std::string lastEventId(req.getHeaderValue("Last-Event-Id")); | 
|  | 55 |  | 
| Ed Tanous | 4b712a2 | 2023-08-02 12:56:52 -0700 | [diff] [blame] | 56 | std::shared_ptr<Subscription> subValue = | 
|  | 57 | std::make_shared<Subscription>(conn); | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 58 |  | 
| Myung Bae | 5fe4ef3 | 2024-10-19 09:56:02 -0400 | [diff] [blame] | 59 | if (subValue->userSub == nullptr) | 
|  | 60 | { | 
|  | 61 | BMCWEB_LOG_ERROR("Subscription data is null"); | 
|  | 62 | conn.close("Internal Error"); | 
|  | 63 | return; | 
|  | 64 | } | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 65 |  | 
| Myung Bae | 5fe4ef3 | 2024-10-19 09:56:02 -0400 | [diff] [blame] | 66 | // 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 Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 72 |  | 
| Ed Tanous | f80a87f | 2024-06-16 12:10:33 -0700 | [diff] [blame] | 73 | std::string id = manager.addSSESubscription(subValue, lastEventId); | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 74 | if (id.empty()) | 
|  | 75 | { | 
|  | 76 | conn.close("Internal Error"); | 
|  | 77 | } | 
|  | 78 | } | 
|  | 79 |  | 
|  | 80 | inline void deleteSubscription(crow::sse_socket::Connection& conn) | 
|  | 81 | { | 
| Ed Tanous | 9838eb2 | 2025-01-29 16:24:42 -0800 | [diff] [blame] | 82 | EventServiceManager::getInstance().deleteSseSubscription(conn); | 
| AppaRao Puli | 5e44e3d | 2021-03-16 15:37:24 +0000 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
|  | 85 | inline void requestRoutesEventServiceSse(App& app) | 
|  | 86 | { | 
|  | 87 | // Note, this endpoint is given the same privilege level as creating a | 
|  | 88 | // subscription, because functionally, that's the operation being done | 
|  | 89 | BMCWEB_ROUTE(app, "/redfish/v1/EventService/SSE") | 
|  | 90 | .privileges(redfish::privileges::postEventDestinationCollection) | 
|  | 91 | .serverSentEvent() | 
|  | 92 | .onopen(createSubscription) | 
|  | 93 | .onclose(deleteSubscription); | 
|  | 94 | } | 
|  | 95 | } // namespace redfish |