19 #include "seamless/SeamlessContentStream.h"
24 #include "spdlog/spdlog.h"
25 #include <boost/algorithm/string/join.hpp>
27 using web::json::value;
28 using web::http::methods;
30 using web::http::http_request;
31 using web::http::status_codes;
32 using web::http::experimental::listener::http_listener;
33 using web::http::experimental::listener::http_listener_config;
36 const std::unique_ptr<MBMS_RT::ServiceAnnouncement>* service_announcement,
37 const std::map<std::string, std::shared_ptr<Service>>& services )
41 , _service_announcement_h(service_announcement)
43 http_listener_config server_config;
44 if (url.rfind(
"https", 0) == 0) {
45 server_config.set_ssl_context_callback(
46 [&](boost::asio::ssl::context& ctx) {
47 std::string cert_file =
"/usr/share/5gmag-rt/cert.pem";
48 cfg.lookupValue(
"mw.http_server.cert", cert_file);
50 std::string key_file =
"/usr/share/5gmag-rt/key.pem";
51 cfg.lookupValue(
"mw.http_server.key", key_file);
53 ctx.set_options(boost::asio::ssl::context::default_workarounds);
54 ctx.use_certificate_chain_file(cert_file);
55 ctx.use_private_key_file(key_file, boost::asio::ssl::context::pem);
61 _api_key =
"106cd60-76c8-4c37-944c-df21aa690c1e";
62 cfg.lookupValue(
"mw.http_server.api_key.key",
_api_key);
68 _listener = std::make_unique<http_listener>(
80 auto uri = message.relative_uri();
81 spdlog::debug(
"request for {}", uri.to_string() );
82 auto paths = uri::split_path(uri::decode(message.relative_uri().path()));
83 if (_require_bearer_token &&
84 (message.headers()[
"Authorization"] !=
"Bearer " + _api_key)) {
85 message.reply(status_codes::Unauthorized);
90 message.reply(status_codes::NotFound);
92 if (paths[0] == _api_path) {
93 if (paths[1] ==
"service_announcement") {
94 if (*_service_announcement_h) {
95 std::vector<value> items;
96 for (
const auto& item : (*_service_announcement_h)->items()) {
97 if (item.content_type !=
"application/mbms-envelope+xml") {
99 i[
"location"] = value(item.uri);
100 i[
"type"] = value(item.content_type);
101 i[
"valid_from"] = value(item.valid_from);
102 i[
"valid_until"] = value(item.valid_until);
103 i[
"version"] = value(item.version);
104 i[
"content"] = value(item.content);
109 sa[
"id"] = value((*_service_announcement_h)->toi());
110 sa[
"content"] = value((*_service_announcement_h)->content());
111 sa[
"items"] = value::array(items);
112 message.reply(status_codes::OK, sa);
115 message.reply(status_codes::NotFound);
118 }
else if (paths[1] ==
"files") {
119 std::vector<value> files;
120 for (
const auto& item : _cache.item_map()) {
122 f[
"source"] = value(item.second->item_source_as_string());
123 f[
"location"] = value(item.second->content_location());
124 f[
"content_length"] = value(item.second->content_length());
125 f[
"received_at"] = value(item.second->received_at());
126 if (item.second->received_at() == 0) {
127 f[
"age"] = value(10000);
129 f[
"age"] = value(time(
nullptr) - item.second->received_at());
133 message.reply(status_codes::OK, value::array(files));
135 }
else if (paths[1] ==
"services") {
136 std::vector<value> services;
137 for (
const auto& service : _services) {
138 auto s = service.second;
141 std::vector<value> names;
142 for (
const auto& name : s->names()) {
144 n[
"lang"] = value(name.first);
145 n[
"name"] = value(name.second);
148 ser[
"names"] = value::array(names);
149 ser[
"protocol"] = value(s->delivery_protocol_string());
150 ser[
"manifest_path"] = value(s->manifest_path());
152 std::vector<value> streams;
153 for (
const auto& stream : s->content_streams()) {
155 s[
"base"] = value(stream.second->base());
156 s[
"type"] = value(stream.second->stream_type_string());
157 s[
"flute_info"] = value(stream.second->flute_info());
158 s[
"resolution"] = value(stream.second->resolution());
159 s[
"codecs"] = value(stream.second->codecs());
160 s[
"bandwidth"] = value(stream.second->bandwidth());
161 s[
"frame_rate"] = value(stream.second->frame_rate());
162 s[
"playlist_path"] = value(stream.second->playlist_path());
164 s[
"cdn_ept"] = value(std::dynamic_pointer_cast<SeamlessContentStream>(stream.second)->cdn_endpoint());
166 s[
"cdn_ept"] = value(
"n/a");
168 streams.push_back(s);
170 ser[
"streams"] = value::array(streams);
172 services.push_back(ser);
174 message.reply(status_codes::OK, value::array(services));
177 message.reply(status_codes::NotFound);
181 auto path = uri.to_string().erase(0,1);
182 spdlog::debug(
"checking for file at path {}", path );
184 auto it = _cache.item_map().find(path);
185 if (it != _cache.item_map().cend()) {
186 if (it->second->buffer() !=
nullptr) {
187 web::http::http_response response(status_codes::OK);
188 response.headers().add(U(
"RT-MBMS-MW-File-Origin"), it->second->item_source_as_string());
189 auto instream = Concurrency::streams::rawptr_stream<uint8_t>::open_istream((uint8_t*)it->second->buffer(), it->second->content_length());
190 response.set_body(instream);
191 message.reply(response);
193 message.reply(status_codes::NotFound);
196 message.reply(status_codes::NotFound);
203 if (_require_bearer_token &&
204 (message.headers()[
"Authorization"] !=
"Bearer " + _api_key)) {
205 message.reply(status_codes::Unauthorized);
209 auto paths = uri::split_path(uri::decode(message.relative_uri().path()));
211 message.reply(status_codes::NotFound);
RestHandler(const libconfig::Config &cfg, const std::string &url, const CacheManagement &cache, const std::unique_ptr< MBMS_RT::ServiceAnnouncement > *service_announcement, const std::map< std::string, std::shared_ptr< MBMS_RT::Service >> &services)
Default constructor.
void put(web::http::http_request message)
std::unique_ptr< web::http::experimental::listener::http_listener > _listener
void get(web::http::http_request message)
virtual ~RestHandler()
Default destructor.
bool _require_bearer_token
static Config cfg
Global configuration object.