Commit 74d26e15 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

add NFDiscovery

parent 6b206342
/**
* NRF NFDiscovery Service
* NRF NFDiscovery Service. © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
* NRF NFDiscovery Service. © 2019, 3GPP Organizational Partners (ARIB, ATIS,
* CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
* NOTE: This class is auto generated by OpenAPI Generator
* (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
* the class manually.
*/
#include "DiscNFInstancesStoreApiImpl.h"
#include <set>
#include "3gpp_29.500.h"
#include "logger.hpp"
namespace oai {
namespace nrf {
......@@ -23,11 +26,9 @@ using namespace oai::nrf::app;
DiscNFInstancesStoreApiImpl::DiscNFInstancesStoreApiImpl(
std::shared_ptr<Pistache::Rest::Router> rtr, nrf_app *nrf_app_inst,
std::string address)
:
DiscNFInstancesStoreApi(rtr),
m_nrf_app(nrf_app_inst),
m_address(address) {
}
: DiscNFInstancesStoreApi(rtr),
m_nrf_app(nrf_app_inst),
m_address(address) {}
void DiscNFInstancesStoreApiImpl::search_nf_instances(
const Pistache::Optional<std::string> &targetNfType,
......@@ -78,10 +79,60 @@ void DiscNFInstancesStoreApiImpl::search_nf_instances(
const Pistache::Optional<bool> &upfUeIpAddrInd,
const Pistache::Optional<Pistache::Http::Header::Raw> &ifNoneMatch,
Pistache::Http::ResponseWriter &response) {
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
}
Logger::nrf_sbi().info(
"Got a request to discover the set of NF instances that satisfies a "
"number of input query parameters");
}
}
std::string target_nf_type = {};
if (!targetNfType.isEmpty()) {
target_nf_type = targetNfType.get();
Logger::nrf_sbi().debug("\tTarget NF type: %s", target_nf_type.c_str());
}
std::string requester_nf_type = {};
if (!requesterNfType.isEmpty()) {
requester_nf_type = requesterNfType.get();
Logger::nrf_sbi().debug("\tRequested NF type: %s",
requester_nf_type.c_str());
}
std::string requester_nf_instance_id = {};
if (!requesterNfInstanceId.isEmpty()) {
requester_nf_instance_id = requesterNfInstanceId.get();
Logger::nrf_sbi().debug("\tRequested NF instance id: %s",
requester_nf_instance_id.c_str());
}
int http_code = 0;
ProblemDetails problem_details = {};
std::string search_id = {};
m_nrf_app->handle_search_nf_instances(target_nf_type, requester_nf_type,
requester_nf_instance_id, search_id,
http_code, 1, problem_details);
nlohmann::json json_data = {};
std::string content_type = "application/json";
std::shared_ptr<nrf_search_result> search_result = {};
m_nrf_app->find_search_result(search_id, search_result);
if (http_code != HTTP_STATUS_CODE_200_OK) {
to_json(json_data, problem_details);
content_type = "application/problem+json";
} else {
// convert the profile to Json
if (search_result != nullptr) search_result.get()->to_json(json_data);
}
Logger::nrf_sbi().debug("Json data: %s", json_data.dump().c_str());
// content type
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(content_type));
response.send(Pistache::Http::Code(http_code), json_data.dump().c_str());
}
} // namespace api
} // namespace nrf
} // namespace oai
/**
* NRF NFManagement Service
* NRF NFManagement Service. © 2019, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
* NRF NFManagement Service. © 2019, 3GPP Organizational Partners (ARIB, ATIS,
* CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
* NOTE: This class is auto generated by OpenAPI Generator
* (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
* the class manually.
*/
#include "NFInstancesStoreApiImpl.h"
#include "logger.hpp"
#include "3gpp_29.500.h"
#include "logger.hpp"
namespace oai {
namespace nrf {
......@@ -24,42 +25,34 @@ using namespace oai::nrf::app;
NFInstancesStoreApiImpl::NFInstancesStoreApiImpl(
std::shared_ptr<Pistache::Rest::Router> rtr, nrf_app *nrf_app_inst,
std::string address)
:
NFInstancesStoreApi(rtr),
m_nrf_app(nrf_app_inst),
m_address(address) {
}
: NFInstancesStoreApi(rtr), m_nrf_app(nrf_app_inst), m_address(address) {}
void NFInstancesStoreApiImpl::get_nf_instances(
const Pistache::Optional<std::string> &nfType,
const Pistache::Optional<int32_t> &limit,
Pistache::Http::ResponseWriter &response) {
Logger::nrf_sbi().info(
"Got a request to retrieve a collection of NF Instances");
std::string nf_type = { };
std::string nf_type = {};
if (!nfType.isEmpty()) {
nf_type = nfType.get();
Logger::nrf_sbi().debug(
".........................................NF type: %s",
nf_type.c_str());
Logger::nrf_sbi().debug("\tNF type: %s", nf_type.c_str());
}
uint32_t limit_item = 0;
if (!limit.isEmpty()) {
limit_item = limit.get();
Logger::nrf_sbi().debug(
".........................................Limit number of items: %d",
limit_item);
Logger::nrf_sbi().debug("\tLimit number of items: %d", limit_item);
}
int http_code = 0;
std::vector<std::string> uris = {};
ProblemDetails problem_details = {};
m_nrf_app->handle_get_nf_instances(nf_type, uris, limit_item, http_code, 1, problem_details);
m_nrf_app->handle_get_nf_instances(nf_type, uris, limit_item, http_code, 1,
problem_details);
nlohmann::json json_data = {};
//TODO: std::string content_type = "application/3gppHal+json";
// TODO: std::string content_type = "application/3gppHal+json";
std::string content_type = "application/json";
if (http_code != HTTP_STATUS_CODE_200_OK) {
......@@ -70,8 +63,8 @@ void NFInstancesStoreApiImpl::get_nf_instances(
json_data["_links"]["item"] = nlohmann::json::array();
json_data["_links"]["self"] = "";
for (auto u : uris) {
nlohmann::json json_item = {};
json_item["href"] = u;
nlohmann::json json_item = {};
json_item["href"] = u;
json_data["_links"]["item"].push_back(json_item);
}
}
......@@ -82,14 +75,12 @@ void NFInstancesStoreApiImpl::get_nf_instances(
response.headers().add<Pistache::Http::Header::ContentType>(
Pistache::Http::Mime::MediaType(content_type));
response.send(Pistache::Http::Code(http_code), json_data.dump().c_str());
}
void NFInstancesStoreApiImpl::options_nf_instances(
Pistache::Http::ResponseWriter &response) {
response.send(Pistache::Http::Code::Ok, "Do some magic\n");
}
}
}
}
} // namespace api
} // namespace nrf
} // namespace oai
......@@ -32,6 +32,7 @@ add_library (NRF STATIC
nrf_profile.cpp
nrf_subscription.cpp
nrf_client.cpp
nrf_search_result.cpp
task_manager.cpp
nrf_event.cpp
)
......
......@@ -40,6 +40,7 @@
#include "logger.hpp"
#include "nrf_client.hpp"
#include "nrf_config.hpp"
#include "nrf_search_result.hpp"
using namespace oai::nrf::app;
using namespace oai::nrf::model;
......@@ -53,7 +54,8 @@ nrf_client *nrf_client_inst = nullptr;
nrf_app::nrf_app(const std::string &config_file, nrf_event &ev)
: m_event_sub(ev),
m_instance_id2nrf_profile(),
m_instance_id2nrf_subscription() {
m_subscription_id2nrf_subscription(),
m_search_id2search_result() {
Logger::nrf_app().startup("Starting...");
try {
......@@ -480,6 +482,66 @@ void nrf_app::handle_update_subscription(
}
}
//------------------------------------------------------------------------------
void nrf_app::handle_search_nf_instances(
const std::string &target_nf_type, const std::string &requester_nf_type,
const std::string &requester_nf_instance_id, std::string &search_id,
int &http_code, const uint8_t http_version,
ProblemDetails &problem_details) {
Logger::nrf_app().info(
"Handle NFDiscover to discover the set of NF Instances (HTTP version %d)",
http_version);
// Check if requester is allowed to discover the NF services
if (!is_service_discover_allowed(requester_nf_instance_id,
requester_nf_type)) {
http_code = HTTP_STATUS_CODE_403_FORBIDDEN;
Logger::nrf_app().debug(
"Requester (instance id %s) is not allowed to discover the NF "
"instances",
requester_nf_instance_id.c_str());
problem_details.setCause(
protocol_application_error_e2str[MODIFICATION_NOT_ALLOWED]);
return;
}
nf_type_t target_type = api_conv::string_to_nf_type(target_nf_type);
nf_type_t requester_type = api_conv::string_to_nf_type(requester_nf_type);
if ((target_type == NF_TYPE_UNKNOWN) or (requester_type == NF_TYPE_UNKNOWN)) {
Logger::nrf_app().debug("Unknown target type/requester type");
http_code = HTTP_STATUS_CODE_400_BAD_REQUEST;
problem_details.setCause(
protocol_application_error_e2str[OPTIONAL_IE_INCORRECT]);
return;
}
Logger::nrf_app().debug(
"target nf type %s, requester nf type %s, requester nf instance id %s",
target_nf_type.c_str(), requester_nf_type.c_str(),
requester_nf_instance_id.c_str());
std::shared_ptr<nrf_search_result> ss = std::make_shared<nrf_search_result>();
// generate a search ID and assign to the search result
generate_search_id(search_id);
ss.get()->set_search_id(search_id);
// set search result
std::vector<std::shared_ptr<nrf_profile>> profiles = {};
find_nf_profiles(target_type, profiles);
if (profiles.size() > 0) {
ss.get()->set_nf_instances(profiles);
}
// set validity period
ss.get()->set_validity_period(100000); // 100s
// add to the DB
add_search_result(search_id, ss);
Logger::nrf_app().debug("Added a search result with ID %s to the DB",
search_id.c_str());
ss.get()->display();
http_code = HTTP_STATUS_CODE_200_OK;
}
//------------------------------------------------------------------------------
bool nrf_app::add_nf_profile(const std::string &profile_id,
const std::shared_ptr<nrf_profile> &p) {
......@@ -610,30 +672,30 @@ bool nrf_app::remove_nf_profile(const std::string &profile_id) {
//------------------------------------------------------------------------------
bool nrf_app::add_subscription(const std::string &sub_id,
const std::shared_ptr<nrf_subscription> &s) {
std::unique_lock lock(m_instance_id2nrf_subscription);
std::unique_lock lock(m_subscription_id2nrf_subscription);
/*
//if profile with this id exist, update
if (instance_id2nrf_subscription.count(sub_id) > 0) {
if (subscrition_id2nrf_subscription.count(sub_id) > 0) {
Logger::nrf_app().info(
"Update a subscription to the list (Subscription ID %s)",
sub_id.c_str());
instance_id2nrf_subscription.at(sub_id) = s;
subscrition_id2nrf_subscription.at(sub_id) = s;
} else {
//if not, add to the list
Logger::nrf_app().info(
"Insert a subscription to the list (Subscription ID %s)",
sub_id.c_str());
instance_id2nrf_subscription.emplace(sub_id, s);
subscrition_id2nrf_subscription.emplace(sub_id, s);
}*/
// Create or update if subscription exist
instance_id2nrf_subscription[sub_id] = s;
subscrition_id2nrf_subscription[sub_id] = s;
return true;
}
//------------------------------------------------------------------------------
bool nrf_app::remove_subscription(const std::string &sub_id) {
std::unique_lock lock(m_instance_id2nrf_subscription);
if (instance_id2nrf_subscription.erase(sub_id)) {
std::unique_lock lock(m_subscription_id2nrf_subscription);
if (subscrition_id2nrf_subscription.erase(sub_id)) {
Logger::nrf_app().info("Removed subscription (ID %s) from the list",
sub_id.c_str());
return true;
......@@ -649,9 +711,9 @@ std::shared_ptr<nrf_subscription> nrf_app::find_subscription(
const std::string &sub_id) const {
// Logger::nrf_app().info("Find a subscription with ID %s", sub_id.c_str());
std::shared_lock lock(m_instance_id2nrf_subscription);
if (instance_id2nrf_subscription.count(sub_id) > 0) {
return instance_id2nrf_subscription.at(sub_id);
std::shared_lock lock(m_subscription_id2nrf_subscription);
if (subscrition_id2nrf_subscription.count(sub_id) > 0) {
return subscrition_id2nrf_subscription.at(sub_id);
} else {
Logger::nrf_app().info("Subscription (ID %s) not found", sub_id.c_str());
return nullptr;
......@@ -812,7 +874,7 @@ void nrf_app::get_subscription_list(const std::string &profile_id,
return;
}
for (auto s : instance_id2nrf_subscription) {
for (auto s : subscrition_id2nrf_subscription) {
Logger::nrf_app().info("\tVerifying subscription, subscription id %s",
s.first.c_str());
std::string uri;
......@@ -907,3 +969,38 @@ void nrf_app::get_subscription_list(const std::string &profile_id,
}
// TODO:
}
//------------------------------------------------------------------------------
bool nrf_app::is_service_discover_allowed(
const std::string &requester_instance_id,
const std::string &requester_nf_type) {
// TODO:
return true;
}
//------------------------------------------------------------------------------
void nrf_app::generate_search_id(std::string &search_id) {
search_id = std::to_string(search_id_generator.get_uid());
}
//------------------------------------------------------------------------------
bool nrf_app::add_search_result(const std::string &id,
const std::shared_ptr<nrf_search_result> &s) {
std::unique_lock lock(m_search_id2search_result);
// Create or update if search result exist
search_id2search_result[id] = s;
return true;
}
bool nrf_app::find_search_result(const std::string &search_id,
std::shared_ptr<nrf_search_result> &s) const {
std::shared_lock lock(m_search_id2search_result);
if (search_id2search_result.count(search_id) > 0) {
s = search_id2search_result.at(search_id);
return true;
} else {
Logger::nrf_app().info("Search result (ID %s) not found",
search_id.c_str());
return false;
}
}
......@@ -37,6 +37,7 @@
#include "SubscriptionData.h"
#include "nrf_event.hpp"
#include "nrf_profile.hpp"
#include "nrf_search_result.hpp"
#include "nrf_subscription.hpp"
#include "uint_generator.hpp"
......@@ -172,6 +173,25 @@ class nrf_app {
int &http_code, const uint8_t http_version,
ProblemDetails &problem_details);
/*
* Handle NFDiscover to discover the set of NF Instances
* @param [const std::string &] target_nf_type: target NF type
* @param [const std::string &] requester_nf_type: Requester NF type
* @param [const std::string &] requester_nf_instance_id: Requester NF
* instance id
* @param [std::string &] search_id: Store search result ID
* @param [int &] http_code: HTTP code used to return to the consumer
* @param [const uint8_t] http_version: HTTP version
* @param [ProblemDetails &] problem_details: Store details of the error
* @return void
*/
void handle_search_nf_instances(const std::string &target_nf_type,
const std::string &requester_nf_type,
const std::string &requester_nf_instance_id,
std::string &search_id,
int &http_code, const uint8_t http_version,
ProblemDetails &problem_details);
/*
* Insert a nrf profile
* @param [const std::string &] profile_id: Profile ID
......@@ -360,16 +380,55 @@ class nrf_app {
const uint8_t &notification_type,
std::vector<std::string> &uris) const;
/*
* Verify whether the requester is allowed to discover the NF services
* @param [const std::string &] requester_instance_id: Requester instance ID
* @param [const std::string &] requester_nf_type: Requester nf type
* @return void
*/
bool is_service_discover_allowed(const std::string &requester_instance_id,
const std::string &requester_nf_type);
/*
* Generate an unique ID for the search result
* @param [const std::string &] search_id: the generated search ID
* @return void
*/
void generate_search_id(std::string &search_id);
/*
* Add a search result to the DB
* @param [const std::string &] id: Search ID
* @param [const std::shared_ptr<nrf_search_result> &] s: Pointer to the search result
* @return void
*/
bool add_search_result(const std::string &id,
const std::shared_ptr<nrf_search_result> &s);
/*
* Find a search result with its ID
* @param [const std::string &] search_id: Search ID
* @param [std::shared_ptr<nrf_search_result> &] s: Pointer to the search result
* @return true if found, otherwise false
*/
bool find_search_result(const std::string &search_id,
std::shared_ptr<nrf_search_result> &p) const;
private:
std::map<std::string, std::shared_ptr<nrf_profile>> instance_id2nrf_profile;
mutable std::shared_mutex m_instance_id2nrf_profile;
std::map<std::string, std::shared_ptr<nrf_subscription>>
instance_id2nrf_subscription;
mutable std::shared_mutex m_instance_id2nrf_subscription;
subscrition_id2nrf_subscription;
mutable std::shared_mutex m_subscription_id2nrf_subscription;
nrf_event &m_event_sub;
util::uint_generator<uint32_t> evsub_id_generator;
std::vector<bs2::connection> connections;
util::uint_generator<uint32_t> search_id_generator;
std::map<std::string, std::shared_ptr<nrf_search_result>>
search_id2search_result;
mutable std::shared_mutex m_search_id2search_result;
};
} // namespace app
} // namespace nrf
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.openairinterface.org/?page_id=698
*
* 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.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file nrf_search_result.cpp
\brief
\author Tien-Thinh NGUYEN
\company Eurecom
\date 2020
\email: Tien-Thinh.Nguyen@eurecom.fr
*/
#include "nrf_search_result.hpp"
#include <nlohmann/json.hpp>
#include "logger.hpp"
using namespace oai::nrf::app;
//------------------------------------------------------------------------------
void nrf_search_result::set_search_id(const std::string &id) { search_id = id; }
//------------------------------------------------------------------------------
void nrf_search_result::get_search_id(std::string &id) const { id = search_id; }
std::string nrf_search_result::get_search_id() const { return search_id; }
void nrf_search_result::set_nf_instances(
const std::vector<std::shared_ptr<nrf_profile>> &instances) {
nf_instances = instances;
}
void nrf_search_result::add_nf_instance(
const std::shared_ptr<nrf_profile> &instance) {
nf_instances.push_back(instance);
}
void nrf_search_result::get_nf_instances(
std::vector<std::shared_ptr<nrf_profile>> &instances) const {
instances = nf_instances;
}
std::vector<std::shared_ptr<nrf_profile>> nrf_search_result::get_nf_instances()
const {
return nf_instances;
}
void nrf_search_result::set_validity_period(const uint64_t &p) {
validity_period = p;
}
void nrf_search_result::get_validity_period(uint64_t &p) const {
p = validity_period;
}
uint64_t nrf_search_result::get_validity_period() const {
return validity_period;
}
//------------------------------------------------------------------------------
void nrf_search_result::display() {
Logger::nrf_app().debug("Search result information");
Logger::nrf_app().debug("\tSearch ID: %s", search_id.c_str());
Logger::nrf_app().debug("\tValidity period: %d", validity_period);
Logger::nrf_app().debug("\tNF instances information");
for (auto n : nf_instances) {
n.get()->display();
}
}
//------------------------------------------------------------------------------
void nrf_search_result::to_json(nlohmann::json &data) const {
data = {};
data["validityPeriod"] = validity_period;
data["nfInstances"] = nlohmann::json::array();
for (auto instance : nf_instances) {
nlohmann::json instance_json = {};
instance.get()->to_json(instance_json);
data["nfInstances"].push_back(instance_json);
}
data["searchId"] = search_id;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.openairinterface.org/?page_id=698
*
* 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.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance: