Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
09b3784
Add basic HTTP server for Nmb2/MBS-1 reference point
davidjwbbc Apr 20, 2026
bbf3dde
User Service Announcement channel
Apr 24, 2026
d9971b3
Integrate User Service Announcement HTTP server with bundle compiler
davidjwbbc Apr 24, 2026
33714e7
Object Manifest Class
Apr 28, 2026
80dc07e
Carousel Object Manifest
May 12, 2026
97c9b6f
Event Notification: USER_SER_AD
May 18, 2026
6f0fb16
Add SDP generation for User Service Announcements and Move HTTP libra…
davidjwbbc Apr 30, 2026
d83b239
Bump version number to v1.0.0
davidjwbbc May 7, 2026
49d62b2
code cleanup and remove unused functions
May 19, 2026
c96f401
Prevent circular shared_ptr references between UserServiceAnnBundle a…
davidjwbbc May 20, 2026
a9a7943
Fix premature deletion of DistSession id.
davidjwbbc May 21, 2026
1be4cac
Fix memory leak of session id
davidjwbbc May 21, 2026
2413fda
Tidy up code
davidjwbbc May 21, 2026
ec92cfc
Fix whitespace in source files
davidjwbbc May 21, 2026
f96500c
Ignore meson wraplock file
davidjwbbc May 22, 2026
28ccbac
Fix issues with User Service Description and Object Manifest creation
davidjwbbc May 22, 2026
635de13
Documentation improvement
davidjwbbc May 22, 2026
25c8325
URL pct escape ids in URL when subscribing to MBSTF notifications
davidjwbbc May 27, 2026
2498bc6
Update User Service Announcements when a UserDataIngSession is deleted
davidjwbbc May 27, 2026
77592d1
Recognise MBSTF notifications for the User Service Announcement Channel
davidjwbbc May 27, 2026
56d5c59
Only send User Service Announcement Carousel manifest when it changes
davidjwbbc May 27, 2026
e632c0c
Remove HTTP server unit test as it has moved to rt-common-shared
davidjwbbc May 27, 2026
7c17f1d
Reset the list of included bundle files when reworking the bundle
davidjwbbc May 27, 2026
f18ad5c
Remove status var preventing deletion of a UserDataIngSession
davidjwbbc May 27, 2026
59e191f
Push pending notifications as soon as subscription comes in
davidjwbbc May 27, 2026
94d5fe0
Reworked User Service Announcement Channel thread to simplify operation
davidjwbbc May 27, 2026
cd33a46
Move User Service Announcement Bundle server configuration to mbsaf s…
davidjwbbc May 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
.*.swp
*.bak

# meson temporary files
subprojects/.wraplock

# common build directories
build
install
2 changes: 1 addition & 1 deletion ATTRIBUTION_NOTICE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
5G-MAG RT MBS Function uses the following open source software:
5G-MAG Reference Tools MBS Function uses the following open source software:

- open5gs - Opensource 5G Core implementation
available from https://open5gs.org/
Expand Down
6 changes: 3 additions & 3 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Meson module fs and its functions like fs.hash_file require atleast meson 0.59.0

project('rt-mbs-function', 'c', 'cpp',
version : '0.2.0',
version : '1.0.0',
license : '5G-MAG Public',
meson_version : '>= 1.4.0',
default_options : [
Expand All @@ -33,8 +33,8 @@ int main(int argc, char *argv[])
endif

open5gs_project=subproject('open5gs', required: true)
svc_consumers_project=subproject('rt-5gc-service-consumers',required:true)

common_shared_project=subproject('rt-common-shared', required: true)
svc_consumers_project=subproject('rt-5gc-service-consumers', required: true)

#subdir('lib')
subdir('src')
Expand Down
8 changes: 8 additions & 0 deletions src/mbsf/ActivePeriods.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ std::optional<std::list<std::shared_ptr<ServiceScheduleDesc> > > ActivePeriods::
return ret_val;
}

ActivePeriods::TimeRange ActivePeriods::activeTimeRange() const
{
if (m_actPeriodsTP.empty()) return TimeRange(std::nullopt, std::nullopt);
return TimeRange(m_actPeriodsTP.front().start, m_actPeriodsTP.back().end);
}

// private:

void ActivePeriods::convertActPeriods(const ActPeriodsType& act_periods,
const std::shared_ptr<ActivePeriodsBase> &old_active_periods,
UserDataIngSession &user_data_ing_session)
Expand Down
2 changes: 2 additions & 0 deletions src/mbsf/ActivePeriods.hh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public:
};
using ActPeriodsType = reftools::mbsf::MBSUserDataIngSession::ActPeriodsType;
using MbsDistSessStateType = reftools::mbsf::MBSDistributionSessionInfo::MbsDistSessStateType;
using TimeRange = ActivePeriodsBase::TimeRange;

ActivePeriods(const ActPeriodsType &act_periods, const std::shared_ptr<ActivePeriodsBase> &old_active_periods, UserDataIngSession &user_data_ing_session);
ActivePeriods(ActPeriodsType &&act_periods, const std::shared_ptr<ActivePeriodsBase> &old_active_periods, UserDataIngSession &user_data_ing_session);
Expand All @@ -68,6 +69,7 @@ public:
virtual const DistSessionState &currentState(const MbsDistSessStateType &dist_session_state) const;
virtual TimestampAndActiveFlag nextTransition() const;
virtual std::optional<std::list<std::shared_ptr<ServiceScheduleDesc> > > serviceScheduleDescriptions() const;
virtual TimeRange activeTimeRange() const;

private:
void convertActPeriods(const ActPeriodsType& act_periods, const std::shared_ptr<ActivePeriodsBase> &old_active_periods,
Expand Down
4 changes: 4 additions & 0 deletions src/mbsf/ActivePeriodsBase.hh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "ogs-sbi.h"

#include <chrono>
#include <optional>
#include <utility>

#include "openapi/model/DistSessionState.h"
#include "openapi/model/MBSDistributionSessionInfo.h"
Expand All @@ -43,13 +45,15 @@ public:
using TimestampAndActiveFlag = std::pair<std::optional<SysTimeMS>, DistSessionState >;
using ActPeriodsType = reftools::mbsf::MBSUserDataIngSession::ActPeriodsType;
using MbsDistSessStateType = reftools::mbsf::MBSDistributionSessionInfo::MbsDistSessStateType;
using TimeRange = std::pair<std::optional<SysTimeMS>, std::optional<SysTimeMS>>;

ActivePeriodsBase(const std::string &user_data_ing_sess_id) : m_id(user_data_ing_sess_id) {};

virtual ~ActivePeriodsBase() = default;
virtual const DistSessionState &currentState(const MbsDistSessStateType &dist_session_state) const = 0;
virtual TimestampAndActiveFlag nextTransition() const = 0;
virtual std::optional<std::list<std::shared_ptr<ServiceScheduleDesc> > > serviceScheduleDescriptions() const = 0;
virtual TimeRange activeTimeRange() const = 0;

protected:
std::string m_id;
Expand Down
9 changes: 7 additions & 2 deletions src/mbsf/ActivePeriodsRepRule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <list>
#include <memory>
#include <optional>
#include <iomanip>
#include <iostream>

#include "common.hh"
Expand Down Expand Up @@ -175,6 +176,12 @@ TimestampAndActiveFlag ActivePeriodsRepRule::nextTransition () const
return {std::nullopt, dist_session_state_inactive};
}

ActivePeriodsRepRule::TimeRange ActivePeriodsRepRule::activeTimeRange() const
{
if (!m_repetitionRule) return TimeRange(std::nullopt, std::nullopt);
return TimeRange(parse_date_time(m_repetitionRule->second->getStartTime()), std::nullopt);
}

std::optional<std::list<std::shared_ptr<ServiceScheduleDesc> > > ActivePeriodsRepRule::serviceScheduleDescriptions() const
{
if (!m_repetitionRule) return std::nullopt;
Expand Down Expand Up @@ -207,14 +214,12 @@ static std::optional<std::chrono::system_clock::time_point> parse_date_time(cons
std::istringstream ss(main_time);
ss >> std::get_time(&tm, "%Y-%m-%dT%H:%M:%S");
if (ss.fail()) {
ogs_info("PARSE TIME SS FAIL");
return std::nullopt;
}

std::time_t time = std::mktime(&tm);
if (time == -1) {

ogs_info("PARSE TIME MKTIME RETURNS -1");
return std::nullopt;
}

Expand Down
2 changes: 2 additions & 0 deletions src/mbsf/ActivePeriodsRepRule.hh
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ public:
using MbsDistSessStateType = reftools::mbsf::MBSDistributionSessionInfo::MbsDistSessStateType;
using RepetitionRule = reftools::mbsf::RepetitionRule;
using VersionedRepetitionRule = std::pair<int32_t, std::shared_ptr<RepetitionRule> >;
using TimeRange = ActivePeriodsBase::TimeRange;

ActivePeriodsRepRule(const ActPeriodsRepRuleType &act_periods_rep_rule, const std::shared_ptr<ActivePeriodsBase> &old_active_periods, UserDataIngSession &user_data_ingest_session);

virtual ~ActivePeriodsRepRule() {};
virtual const DistSessionState &currentState(const MbsDistSessStateType &dist_session_state) const;
virtual TimestampAndActiveFlag nextTransition() const;
virtual std::optional<std::list<std::shared_ptr<ServiceScheduleDesc> > > serviceScheduleDescriptions() const;
virtual TimeRange activeTimeRange() const;

private:
std::shared_ptr<VersionedRepetitionRule> m_repetitionRule;
Expand Down
2 changes: 2 additions & 0 deletions src/mbsf/AlwaysActive.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public:
using DistSessionState = ActivePeriodsBase::DistSessionState;
using ActPeriodsType = reftools::mbsf::MBSUserDataIngSession::ActPeriodsType;
using MbsDistSessStateType = reftools::mbsf::MBSDistributionSessionInfo::MbsDistSessStateType;
using TimeRange = ActivePeriodsBase::TimeRange;

AlwaysActive() = delete;
AlwaysActive(const std::string &user_data_ing_sess_id) : ActivePeriodsBase(user_data_ing_sess_id) {};
Expand All @@ -60,6 +61,7 @@ public:
virtual const DistSessionState &currentState(const MbsDistSessStateType &dist_session_state) const;
virtual TimestampAndActiveFlag nextTransition() const;
virtual std::optional<std::list<std::shared_ptr<ServiceScheduleDesc> > > serviceScheduleDescriptions() const;
virtual TimeRange activeTimeRange() const { return TimeRange{std::nullopt, std::nullopt}; };
};

MBSF_NAMESPACE_STOP
Expand Down
81 changes: 81 additions & 0 deletions src/mbsf/AnnouncementBundleIndexHandler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/******************************************************************************
* 5G-MAG Reference Tools: MBS Function: AnnouncementBundleIndexHandler class
******************************************************************************
* Copyright: (C)2026 British Broadcasting Corporation
* Author(s): David Waring <david.waring2@bbc.co.uk>
* License: 5G-MAG Public License v1
*
* Licensed under the License terms and conditions for use, reproduction, and
* distribution of 5G-MAG software (the “License”). You may not use this file
* except in compliance with the License. You may obtain a copy of the License at
* https://www.5g-mag.com/reference-tools. Unless required by applicable law or
* agreed to in writing, software distributed under the License is distributed on
* an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied.
*
* See the License for the specific language governing permissions and limitations
* under the License.
*/

#include <dirent.h>

#include <filesystem>
#include <list>
#include <string>
#include <vector>

#include "ogs-core.h"
#include "ogs-sbi.h"

#include "common.hh"
#include <DocrootHTTPRequestHandler.hh>
#include <HTTPResponse.hh>
#include <HTTPServer.hh>
#include "MultipartMime.hh"
#include "UserDataIngSession.hh"

#include "AnnouncementBundleIndexHandler.hh"

HTTPXPP_NAMESPACE_USING(DocrootHTTPRequestHandler);
HTTPXPP_NAMESPACE_USING(HTTPResponse);
HTTPXPP_NAMESPACE_USING(HTTPServer);

MBSF_NAMESPACE_START

HTTPResponse AnnouncementBundleIndexHandler::makeResponseForDir(const std::string &dir_path, const std::string &url_path, const HTTPServer &server)
{
if (url_path == "/" || url_path.starts_with("/.")) {
return server.makeResponse().statusCode(403);
}

std::filesystem::path dp(dir_path);
if (!dp.has_filename()) dp = dp.parent_path();
auto user_data_ing_sess_id = dp.filename().string();

MultipartMime bundle(MultipartMime::RELATED);

try {
auto user_dat_ing_session = UserDataIngSession::find(user_data_ing_sess_id);
auto &filenames = user_dat_ing_session->getUserServiceAnnBundleFilesList();
if (filenames.empty()) {
return server.makeResponse().statusCode(404);
}
for (const auto &filename : filenames) {
bundle.addFile(dp, filename);
}
} catch (std::out_of_range &ex) {
return server.makeResponse().statusCode(404);
}

HTTPResponse resp = server.makeResponse(bundle.body());
for (const auto &hdr : bundle.headers()) {
resp.addHeader(hdr.first, hdr.second);
}

return resp;
}

MBSF_NAMESPACE_STOP

/* vim:ts=8:sts=4:sw=4:expandtab:
*/
53 changes: 53 additions & 0 deletions src/mbsf/AnnouncementBundleIndexHandler.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#ifndef _MBSF_ANNOUNCEMENT_BUNDLE_INDEX_HANDLER_HH_
#define _MBSF_ANNOUNCEMENT_BUNDLE_INDEX_HANDLER_HH_
/******************************************************************************
* 5G-MAG Reference Tools: MBS Function: AnnouncementBundleIndexHandler class
******************************************************************************
* Copyright: (C)2026 British Broadcasting Corporation
* Author(s): David Waring <david.waring2@bbc.co.uk>
* License: 5G-MAG Public License v1
*
* Licensed under the License terms and conditions for use, reproduction, and
* distribution of 5G-MAG software (the “License”). You may not use this file
* except in compliance with the License. You may obtain a copy of the License at
* https://www.5g-mag.com/reference-tools. Unless required by applicable law or
* agreed to in writing, software distributed under the License is distributed on
* an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied.
*
* See the License for the specific language governing permissions and limitations
* under the License.
*/

#include <string>
#include <vector>

#include "common.hh"
#include <DocrootHTTPRequestHandler.hh>

HTTPXPP_NAMESPACE_START
class HTTPResponse;
class HTTPServer;
HTTPXPP_NAMESPACE_STOP

MBSF_NAMESPACE_START

class AnnouncementBundleIndexHandler : public HTTPXPP_NAMESPACE_NAME(DocrootHTTPRequestHandler::IndexHandler) {
public:
AnnouncementBundleIndexHandler() :HTTPXPP_NAMESPACE_NAME(DocrootHTTPRequestHandler::IndexHandler)() {};
AnnouncementBundleIndexHandler(const AnnouncementBundleIndexHandler &other) = delete;
AnnouncementBundleIndexHandler(AnnouncementBundleIndexHandler &&other) = delete;

virtual ~AnnouncementBundleIndexHandler() {};

AnnouncementBundleIndexHandler &operator=(const AnnouncementBundleIndexHandler &other) = delete;
AnnouncementBundleIndexHandler &operator=(AnnouncementBundleIndexHandler &&other) = delete;

virtual HTTPXPP_NAMESPACE_NAME(HTTPResponse) makeResponseForDir(const std::string &dir_path, const std::string &url_path, const HTTPXPP_NAMESPACE_NAME(HTTPServer) &server);
};

MBSF_NAMESPACE_STOP

/* vim:ts=8:sts=4:sw=4:expandtab:
*/
#endif /* _MBSF_ANNOUNCEMENT_BUNDLE_INDEX_HANDLER_HH_ */
83 changes: 83 additions & 0 deletions src/mbsf/CarouselObject.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/******************************************************************************
* 5G-MAG Reference Tools: MBS Function: MBS Carousel Object class
******************************************************************************
* Copyright: (C)2026 British Broadcasting Corporation
* Author(s): Dev Audsin <dev.audsin@bbc.co.uk>
* License: 5G-MAG Public License v1
*
* Licensed under the License terms and conditions for use, reproduction, and
* distribution of 5G-MAG software (the “License”). You may not use this file
* except in compliance with the License. You may obtain a copy of the License at
* https://www.5g-mag.com/reference-tools. Unless required by applicable law or
* agreed to in writing, software distributed under the License is distributed on
* an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied.
*
* See the License for the specific language governing permissions and limitations
* under the License.
*/

// Open5GS includes
#include "ogs-app.h"
#include "ogs-sbi.h"

// standard template library includes
#include <memory>
#include <stdexcept>
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <cstdint>
#include <iostream>

// App header includes
#include "common.hh"
#include "App.hh"
#include "Context.hh"

#include "openapi/model/Object.h"

// Header include for this class
#include "CarouselObject.hh"

using fiveg_mag_reftools::CJson;
using fiveg_mag_reftools::ModelException;
using reftools::mbsf::Object;

MBSF_NAMESPACE_START

CarouselObject::CarouselObject(CJson &json, bool as_request)
:m_object(new Object(json, as_request))
{
}

CarouselObject::CarouselObject(const std::shared_ptr<reftools::mbsf::Object> &object)
:m_object(object)
{
}

CarouselObject::CarouselObject(const std::string &locator, std::optional<int32_t > repetition_interval,
std::optional<int32_t > keep_updated_interval, std::optional<std::string > earliest_fetch_time)
{
m_object.reset(new Object());
m_object->setLocator(locator);
m_object->setRepetitionInterval(repetition_interval);
m_object->setKeepUpdatedInterval(keep_updated_interval);
m_object->setEarliestFetchTime(earliest_fetch_time);
}


CarouselObject::~CarouselObject()
{
}

CJson CarouselObject::json(bool as_request = false) const
{
return m_object->toJSON(as_request);
}

MBSF_NAMESPACE_STOP

/* vim:ts=8:sts=4:sw=4:expandtab:
*/

Loading