libe3 0.2.5
C++ library for E3AP RAN vendor integration
Loading...
Searching...
No Matches
dapp_subscription_state.hpp
Go to the documentation of this file.
1/**
2 * @file dapp_subscription_state.hpp
3 * @brief Per-instance state for the dApp role.
4 *
5 * Holds the dApp-assigned identifier (received from the RAN in the
6 * SetupResponse), the list of RAN functions the RAN advertised, and the
7 * subscriptions this dApp has actively negotiated.
8 *
9 * A dApp may hold MULTIPLE concurrent subscriptions — one per distinct
10 * RAN function. At most one subscription per (dapp, ran_function) pair,
11 * mirroring the RAN-side uniqueness in SubscriptionManager.
12 *
13 * This struct is held by E3Interface when config.role == E3Role::DAPP.
14 * It is the dApp-role counterpart of SubscriptionManager, which stays
15 * strictly RAN-side. Exactly one of `subscription_manager_` / `dapp_state_`
16 * is non-null on a given E3Interface instance.
17 *
18 * SPDX-FileCopyrightText: Copyright (c) 2026 Northeastern University
19 * SPDX-License-Identifier: Apache-2.0
20 */
21
22#ifndef LIBE3_DAPP_SUBSCRIPTION_STATE_HPP
23#define LIBE3_DAPP_SUBSCRIPTION_STATE_HPP
24
25#include "types.hpp"
26
27#include <cstdint>
28#include <mutex>
29#include <optional>
30#include <unordered_map>
31#include <vector>
32
33namespace libe3 {
34
36public:
38
41
42 /**
43 * @brief Store the assignment from a SetupResponse.
44 * Called once after a positive SetupResponse arrives.
45 */
46 void record_setup_response(uint32_t dapp_id,
47 std::vector<RanFunctionDef> functions) {
48 std::lock_guard<std::mutex> lock(mu_);
49 assigned_dapp_id = dapp_id;
50 remote_ran_functions = std::move(functions);
51 }
52
53 /**
54 * @brief Record a successful SubscriptionResponse.
55 * Idempotent: re-recording the same (rf_id, sub_id) is fine.
56 */
57 void record_subscription(uint32_t ran_function_id, uint32_t subscription_id) {
58 std::lock_guard<std::mutex> lock(mu_);
59 ran_function_to_subscription_id[ran_function_id] = subscription_id;
60 subscription_id_to_ran_function[subscription_id] = ran_function_id;
61 }
62
63 /**
64 * @brief Remove the subscription for a given RAN function.
65 * @return true if a subscription was removed; false if none existed.
66 */
67 bool remove_subscription_by_rf(uint32_t ran_function_id) {
68 std::lock_guard<std::mutex> lock(mu_);
69 auto it = ran_function_to_subscription_id.find(ran_function_id);
70 if (it == ran_function_to_subscription_id.end()) {
71 return false;
72 }
73 const uint32_t sub_id = it->second;
76 return true;
77 }
78
79 /**
80 * @brief Remove the subscription with a given subscription ID.
81 * @return true if a subscription was removed; false if none existed.
82 */
83 bool remove_subscription_by_id(uint32_t subscription_id) {
84 std::lock_guard<std::mutex> lock(mu_);
85 auto it = subscription_id_to_ran_function.find(subscription_id);
86 if (it == subscription_id_to_ran_function.end()) {
87 return false;
88 }
89 const uint32_t rf_id = it->second;
92 return true;
93 }
94
95 /**
96 * @brief Snapshot of active subscription IDs.
97 */
98 std::vector<uint32_t> active_subscriptions() const {
99 std::lock_guard<std::mutex> lock(mu_);
100 std::vector<uint32_t> out;
101 out.reserve(subscription_id_to_ran_function.size());
102 for (const auto& [sub_id, rf_id] : subscription_id_to_ran_function) {
103 (void)rf_id;
104 out.push_back(sub_id);
105 }
106 return out;
107 }
108
109 /**
110 * @brief Snapshot of RAN function IDs this dApp is currently subscribed to.
111 */
112 std::vector<uint32_t> subscribed_ran_functions() const {
113 std::lock_guard<std::mutex> lock(mu_);
114 std::vector<uint32_t> out;
115 out.reserve(ran_function_to_subscription_id.size());
116 for (const auto& [rf_id, sub_id] : ran_function_to_subscription_id) {
117 (void)sub_id;
118 out.push_back(rf_id);
119 }
120 return out;
121 }
122
123 /**
124 * @brief Look up subscription ID for a RAN function.
125 */
126 std::optional<uint32_t> subscription_id_for(uint32_t ran_function_id) const {
127 std::lock_guard<std::mutex> lock(mu_);
128 auto it = ran_function_to_subscription_id.find(ran_function_id);
129 if (it == ran_function_to_subscription_id.end()) return std::nullopt;
130 return it->second;
131 }
132
133 // -----------------------------------------------------------------------
134 // Public state members (kept public for direct inspection in tests and
135 // for handlers that need to update multiple fields atomically inside
136 // E3Interface). Callers MUST hold `mu` when reading or writing these
137 // directly; the helpers above already take the lock.
138 // -----------------------------------------------------------------------
139
140 mutable std::mutex mu;
141
142 /// Assigned by the RAN in SetupResponse. nullopt until setup completes.
143 std::optional<uint32_t> assigned_dapp_id;
144
145 /// RAN functions advertised by the RAN in SetupResponse.
146 std::vector<RanFunctionDef> remote_ran_functions;
147
148 /// rf_id -> sub_id
149 std::unordered_map<uint32_t, uint32_t> ran_function_to_subscription_id;
150 /// sub_id -> rf_id (reverse, used for SubscriptionDelete)
151 std::unordered_map<uint32_t, uint32_t> subscription_id_to_ran_function;
152
153private:
154 // Single mutex; the public-facing `mu` (above) is an alias for
155 // documentation and direct lock_guard use from E3Interface. We keep
156 // a single instance so this->mu_ and the public this->mu refer to the
157 // same lock. Internal helpers use mu_.
158 std::mutex& mu_ = mu;
159};
160
161} // namespace libe3
162
163#endif // LIBE3_DAPP_SUBSCRIPTION_STATE_HPP
std::vector< RanFunctionDef > remote_ran_functions
RAN functions advertised by the RAN in SetupResponse.
std::optional< uint32_t > assigned_dapp_id
Assigned by the RAN in SetupResponse. nullopt until setup completes.
DAppSubscriptionState & operator=(const DAppSubscriptionState &)=delete
std::unordered_map< uint32_t, uint32_t > ran_function_to_subscription_id
rf_id -> sub_id
std::optional< uint32_t > subscription_id_for(uint32_t ran_function_id) const
Look up subscription ID for a RAN function.
std::vector< uint32_t > subscribed_ran_functions() const
Snapshot of RAN function IDs this dApp is currently subscribed to.
void record_setup_response(uint32_t dapp_id, std::vector< RanFunctionDef > functions)
Store the assignment from a SetupResponse. Called once after a positive SetupResponse arrives.
std::unordered_map< uint32_t, uint32_t > subscription_id_to_ran_function
sub_id -> rf_id (reverse, used for SubscriptionDelete)
bool remove_subscription_by_id(uint32_t subscription_id)
Remove the subscription with a given subscription ID.
bool remove_subscription_by_rf(uint32_t ran_function_id)
Remove the subscription for a given RAN function.
std::vector< uint32_t > active_subscriptions() const
Snapshot of active subscription IDs.
void record_subscription(uint32_t ran_function_id, uint32_t subscription_id)
Record a successful SubscriptionResponse. Idempotent: re-recording the same (rf_id,...
DAppSubscriptionState(const DAppSubscriptionState &)=delete
E3AP Protocol Types - Vendor-neutral type definitions.