5G-MAG Reference Tools - MBMS Middleware
Middleware.cpp
Go to the documentation of this file.
1 // 5G-MAG Reference Tools
2 // MBMS Middleware Process
3 //
4 // Copyright (C) 2021 Klaus Kühnhammer (Österreichische Rundfunksender GmbH & Co KG)
5 //
6 // Licensed under the License terms and conditions for use, reproduction, and
7 // distribution of 5G-MAG software (the “License”). You may not use this file
8 // except in compliance with the License. You may obtain a copy of the License at
9 // https://www.5g-mag.com/reference-tools. Unless required by applicable law or
10 // agreed to in writing, software distributed under the License is distributed on
11 // an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12 // or implied.
13 //
14 // See the License for the specific language governing permissions and limitations
15 // under the License.
16 //
17 #include "Middleware.h"
18 #include "spdlog/spdlog.h"
19 
27 MBMS_RT::Middleware::Middleware(boost::asio::io_service &io_service, const libconfig::Config &cfg,
28  const std::string &api_url,
29  const std::string &iface)
30  : _rp(cfg), _control(cfg), _cache(cfg, io_service), _api(cfg, api_url, _cache, &_service_announcement, _services),
31  _tick_interval(1), _timer(io_service, _tick_interval), _control_timer(io_service, _control_tick_interval),
32  _cfg(cfg), _interface(iface), _io_service(io_service) {
33  cfg.lookupValue("mw.seamless_switching.enabled", _seamless);
34  if (_seamless) {
35  spdlog::info("Seamless switching mode enabled");
36  }
37  cfg.lookupValue("mw.control_system.enabled", _control_system);
38  if (_control_system) {
39  int secs = 10;
40  cfg.lookupValue("mw.control_system.interval", secs);
41  _control_tick_interval = boost::posix_time::seconds(secs);
42  spdlog::info("Control System API enabled");
43  }
44 
46  _timer.async_wait(boost::bind(&Middleware::tick_handler, this)); //NOLINT
47  _control_timer.async_wait(boost::bind(&Middleware::control_tick_handler, this)); //NOLINT
48 }
49 
55  try {
56  bool local_service_enabled = false;
57  std::string local_bootstrap_file;
58 
59  _cfg.lookupValue("mw.local_service.enabled", local_service_enabled);
60  _cfg.lookupValue("mw.local_service.bootstrap_file", local_bootstrap_file);
61 
62  if (local_service_enabled && local_bootstrap_file != "") {
63  spdlog::info("Reading service announcement from file at {}", local_bootstrap_file);
64  std::ifstream ifs(local_bootstrap_file);
65  std::string sa_multipart((std::istreambuf_iterator<char>(ifs)),
66  (std::istreambuf_iterator<char>()));
67  std::string tmgi = "";
68  _cfg.lookupValue("mw.local_service.tmgi", tmgi);
69  std::string mcast_address = "";
70  _cfg.lookupValue("mw.local_service.mcast_address", mcast_address);
71 
72  _service_announcement = std::make_unique<MBMS_RT::ServiceAnnouncement>(_cfg, tmgi, mcast_address, 0, _interface,
73  _io_service, _cache, _seamless,
74  boost::bind(&Middleware::get_service, this,
75  _1), //NOLINT
76  boost::bind(&Middleware::set_service, this,
77  _1, _2)); //NOLINT
78  _service_announcement->parse_bootstrap(sa_multipart);
79 
80  return true;
81  }
82  return false;
83  } catch (...) {
84  return false;
85  }
86 }
87 
92  auto mchs = _rp.getMchInfo();
93  for (auto const &mch: mchs.as_array()) {
94  for (auto const &mtch: mch.at("mtchs").as_array()) {
95  auto tmgi = mtch.at("tmgi").as_string();
96  auto dest = mtch.at("dest").as_string();
97  unsigned tsi = 0;
98  _cfg.lookupValue("mw.service_announcement_tsi", tsi);
99  auto is_service_announcement = std::stoul(tmgi.substr(0, 6), nullptr, 16) < 0xF;
100  if (!dest.empty() && is_service_announcement && !_service_announcement) {
101  // automatically start receiving the service announcement
102  // 26.346 5.2.3.1.1 : the pre-defined TSI value shall be "0".
103  _service_announcement = std::make_unique<MBMS_RT::ServiceAnnouncement>(_cfg, tmgi, dest, tsi, _interface,
104  _io_service,
105  _cache, _seamless,
106  boost::bind(&Middleware::get_service,
107  this, _1),
108  boost::bind(&Middleware::set_service,
109  this, _1, _2)); //NOLINT
110  _service_announcement->start_flute_receiver(dest);
111  }
112  }
113  }
114 
115  _cache.check_file_expiry_and_cache_size();
116 
117  _timer.expires_at(_timer.expires_at() + _tick_interval);
118  _timer.async_wait(boost::bind(&Middleware::tick_handler, this)); //NOLINT
119 }
120 
125  if (_control_system) {
126  try {
127  auto status = _rp.getStatus();
128  auto cinr = status.at("cinr_db").as_double();
129  spdlog::debug("CINR ist {}", cinr);
130 
131  std::vector<std::string> tmgis;
132  auto services = _control.sendHello(cinr, tmgis);
133  for (const auto &ctrl_service: services.as_array()) {
134  spdlog::debug("control system sent service: {}", ctrl_service.serialize());
135  }
136  } catch (...) {}
137  }
138 
139 
140  _control_timer.expires_at(_control_timer.expires_at() + _control_tick_interval);
141  _control_timer.async_wait(boost::bind(&Middleware::control_tick_handler, this)); //NOLINT
142 }
143 
149 auto MBMS_RT::Middleware::get_service(const std::string &service_id) -> std::shared_ptr<Service> {
150  if (_services.find(service_id) != _services.end()) {
151  return _services[service_id];
152  } else {
153  return nullptr;
154  }
155 }
boost::posix_time::seconds _control_tick_interval
Definition: Middleware.h:52
Middleware(boost::asio::io_service &io_service, const libconfig::Config &cfg, const std::string &api_url, const std::string &iface)
Definition: Middleware.cpp:27
std::shared_ptr< Service > get_service(const std::string &service_id)
Definition: Middleware.cpp:149
void set_service(const std::string &service_id, std::shared_ptr< Service > service)
Definition: Middleware.h:38
bool _handle_local_service_announcement()
Definition: Middleware.cpp:54
boost::asio::deadline_timer _control_timer
Definition: Middleware.h:53
boost::asio::deadline_timer _timer
Definition: Middleware.h:60
static Config cfg
Global configuration object.
Definition: main.cpp:111