Commit 028e90e8 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

add multipart parser

parent ec9b1e81
/**
* Nsmf_PDUSession
* SMF PDU Session 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.
*/
* Nsmf_PDUSession
* SMF PDU Session 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.
*/
#include "SMContextsCollectionApi.h"
#include "logger.hpp"
#include "Helpers.h"
extern "C" {
#include "multipartparser.h"
}
#include <cassert>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <list>
#include <map>
#include <string>
#define BOUNDARY "----Boundary"
typedef struct part {
std::map<std::string,std::string> headers;
std::string body;
} part;
static multipartparser_callbacks g_callbacks;
static bool g_body_begin_called;
static std::string g_header_name;
static std::string g_header_value;
static std::list<part> g_parts;
static bool g_body_end_called;
static void init_globals()
{
g_body_begin_called = false;
g_header_name.clear();
g_header_value.clear();
g_parts.clear();
g_body_end_called = false;
}
static int on_body_begin(multipartparser* /*parser*/)
{
g_body_begin_called = true;
return 0;
}
static int on_part_begin(multipartparser* /*parser*/)
{
g_parts.push_back(part());
return 0;
}
static void on_header_done()
{
g_parts.back().headers[g_header_name] = g_header_value;
g_header_name.clear();
g_header_value.clear();
}
static int on_header_field(multipartparser* /*parser*/, const char* data, size_t size)
{
if (g_header_value.size() > 0)
on_header_done();
g_header_name.append(data, size);
return 0;
}
static int on_header_value(multipartparser* /*parser*/, const char* data, size_t size)
{
g_header_value.append(data, size);
return 0;
}
static int on_headers_complete(multipartparser* /*parser*/)
{
if (g_header_value.size() > 0)
on_header_done();
return 0;
}
static int on_data(multipartparser* /*parser*/, const char* data, size_t size)
{
g_parts.back().body.append(data, size);
return 0;
}
static int on_part_end(multipartparser* /*parser*/)
{
return 0;
}
static int on_body_end(multipartparser* /*parser*/)
{
g_body_end_called = true;
return 0;
}
namespace oai {
namespace smf_server {
......@@ -21,46 +115,81 @@ using namespace oai::smf_server::helpers;
using namespace oai::smf_server::model;
SMContextsCollectionApi::SMContextsCollectionApi(std::shared_ptr<Pistache::Rest::Router> rtr) {
router = rtr;
router = rtr;
}
void SMContextsCollectionApi::init() {
setupRoutes();
setupRoutes();
}
void SMContextsCollectionApi::setupRoutes() {
using namespace Pistache::Rest;
using namespace Pistache::Rest;
Routes::Post(*router, base + "/sm-contexts", Routes::bind(&SMContextsCollectionApi::post_sm_contexts_handler, this));
Routes::Post(*router, base + "/sm-contexts", Routes::bind(&SMContextsCollectionApi::post_sm_contexts_handler, this));
// Default handler, called when a route is not found
router->addCustomHandler(Routes::bind(&SMContextsCollectionApi::sm_contexts_collection_api_default_handler, this));
// Default handler, called when a route is not found
router->addCustomHandler(Routes::bind(&SMContextsCollectionApi::sm_contexts_collection_api_default_handler, this));
}
void SMContextsCollectionApi::post_sm_contexts_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
// Getting the body param
std::cout <<"received a SM context create request" << request.body() <<std::endl;
// Getting the body param
Logger::smf_api_server().debug("[SMF API] Received a SM context create request %s",request.body().c_str());
SmContextMessage smContextMessage;
try {
nlohmann::json::parse(request.body()).get_to(smContextMessage);
this->post_sm_contexts(smContextMessage, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
SmContextCreateData smContextCreateData;
//step 1. use multipartparser to decode the request
multipartparser_callbacks_init(&g_callbacks);
g_callbacks.on_body_begin = &on_body_begin;
g_callbacks.on_part_begin = &on_part_begin;
g_callbacks.on_header_field = &on_header_field;
g_callbacks.on_header_value = &on_header_value;
g_callbacks.on_headers_complete = &on_headers_complete;
g_callbacks.on_data = &on_data;
g_callbacks.on_part_end = &on_part_end;
g_callbacks.on_body_end = &on_body_end;
multipartparser parser;
init_globals();
multipartparser_init(&parser, BOUNDARY);
assert(multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) == strlen(request.body().c_str()));
assert(g_body_begin_called);
//at least 2 parts for Json data and N1 (+ N2)
assert(g_parts.size() >= 2);
part p0 = g_parts.front(); g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 1: \n%s", p0.body.c_str());
part p1 = g_parts.front(); g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 2: \n %s",p1.body.c_str());
if (g_parts.size() == 3) {
part p2 = g_parts.front(); g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 3: \n %s",p2.body.c_str());
}
//step 2. process the request
try {
//nlohmann::json::parse(p0.body.c_str()).get_to(smContextMessage);
nlohmann::json::parse(p0.body.c_str()).get_to(smContextCreateData);
smContextMessage.setJsonData(smContextCreateData);
smContextMessage.setBinaryDataN1SmMessage(p1.body.c_str());
this->post_sm_contexts(smContextMessage, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
response.send(Pistache::Http::Code::Bad_Request, e.what());
return;
} catch (std::exception &e) {
//send a 500 error
response.send(Pistache::Http::Code::Internal_Server_Error, e.what());
return;
}
}
void SMContextsCollectionApi::sm_contexts_collection_api_default_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
response.send(Pistache::Http::Code::Not_Found, "The requested method does not exist");
response.send(Pistache::Http::Code::Not_Found, "The requested method does not exist");
}
}
......
......@@ -35,11 +35,7 @@ SMContextsCollectionApiImpl::SMContextsCollectionApiImpl(std::shared_ptr<Pistach
void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smContextMessage, Pistache::Http::ResponseWriter &response) {
Logger::smf_api_server().info("post_sm_contexts...");
std::string ngap_msg_str = "hello world";
m_smf_app->create_n2_sm_information(NULL, 0, 0, ngap_msg_str);
return ;
Logger::smf_api_server().info("[SMF API] Process SmContextMessage ...");
//decode NAS message and assign the necessary informations to smf::pdu_session_create_sm_context_request
//and pass this message to SMF to handle this message
......@@ -49,13 +45,9 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
SmContextCreateData smContextCreateData = smContextMessage.getJsonData();
std::string n1_sm_msg = smContextMessage.getBinaryDataN1SmMessage();
//FOR DEBUG ONLY!!, GENERATE A PDU SESSION ESTABLISHMENT MESSAGE HERE!!
//sm_encode_establishment_request();
//sm_encode_all();//Generate all required HEX files to "oai-cn5g-smf/build/smf/build/sm_encode_file/ *.txt"
m_smf_app->create_n1_sm_container(PDU_SESSION_ESTABLISHMENT_REQUEST, n1_sm_msg);
std::string n1_sm_msg_hex;
m_smf_app->convert_string_2_hex(n1_sm_msg, n1_sm_msg_hex);
Logger::smf_api_server().debug("smContextMessage, n1 sm msg %s",n1_sm_msg.c_str());
Logger::smf_api_server().debug("smContextMessage, N1 SM message: %s",n1_sm_msg.c_str());
//Step1. Decode N1 SM container into decoded nas msg
int decoder_rc = m_smf_app->decode_nas_message_n1_sm_container(decoded_nas_msg, n1_sm_msg_hex);
......@@ -85,35 +77,48 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
return;
}
Logger::smf_api_server().debug("nas header decode extended_protocol_discriminator %d, security_header_type:%d,sequence_number:%d,message_authentication_code:%d\n",
Logger::smf_api_server().debug("NAS header information: extended_protocol_discriminator %d, security_header_type:%d,sequence_number:%d,message_authentication_code:%d\n",
decoded_nas_msg.header.extended_protocol_discriminator,
decoded_nas_msg.header.security_header_type,
decoded_nas_msg.header.sequence_number,
decoded_nas_msg.header.message_authentication_code);
//Step 2. Create a pdu_session_create_sm_context_request message and store the necessary information
Logger::smf_api_server().debug("Create a pdu_session_create_sm_context_request message and store the necessary information\n");
smf::pdu_session_create_sm_context_request sm_context_req_msg = {};
//"/nsmf-pdusession/v1";
//set api root to be used as location header in HTTP response
sm_context_req_msg.set_api_root(m_address + base + "/sm-contexts");
//supi
supi_t supi = {.length = 0};
smf_string_to_supi(&supi, smContextCreateData.getSupi().c_str());
std::size_t pos = smContextCreateData.getSupi().find("-");
std::string supi_str = smContextCreateData.getSupi().substr(pos +1);
std::string supi_prefix = smContextCreateData.getSupi().substr(0, pos);
smf_string_to_supi(&supi, supi_str.c_str());
sm_context_req_msg.set_supi(supi);
Logger::smf_api_server().info("Supi %s", smContextCreateData.getSupi().c_str());
sm_context_req_msg.set_supi_prefix(supi_prefix);
Logger::smf_api_server().debug("SmContextCreateData, supi %s, prefix %s, imsi %s \n", smContextCreateData.getSupi().c_str(), supi_prefix.c_str(), supi_str.c_str());
//dnn
sm_context_req_msg.set_dnn(smContextCreateData.getDnn());
Logger::smf_api_server().debug("SmContextCreateData, dnn %s \n", smContextCreateData.getDnn().c_str());
sm_context_req_msg.set_dnn(smContextCreateData.getDnn().c_str());
//S-Nssai
snssai_t snssai(smContextCreateData.getSNssai().getSst(), smContextCreateData.getSNssai().getSd());
Logger::smf_api_server().debug("SmContextCreateData, S-NSSAI sst %d, sd %s\n", smContextCreateData.getSNssai().getSst(), smContextCreateData.getSNssai().getSd().c_str());
snssai_t snssai(smContextCreateData.getSNssai().getSst(), smContextCreateData.getSNssai().getSd().c_str());
sm_context_req_msg.set_snssai(snssai);
//PDU session ID
Logger::smf_api_server().debug("SmContextCreateData, PDU SessionID %d \n", smContextCreateData.getPduSessionId());
sm_context_req_msg.set_pdu_session_id(smContextCreateData.getPduSessionId());
//AMF ID
sm_context_req_msg.set_serving_nf_id(smContextCreateData.getServingNfId()); //TODO: should be verified that AMF ID is stored in GUAMI or ServingNfId
Logger::smf_api_server().debug("SmContextCreateDatea, ServingNfId %s\n", smContextCreateData.getServingNfId().c_str());
sm_context_req_msg.set_serving_nf_id(smContextCreateData.getServingNfId().c_str()); //TODO: should be verified that AMF ID is stored in GUAMI or ServingNfId
//Request Type
Logger::smf_api_server().debug("SmContextCreateData, RequestType %s\n", smContextCreateData.getRequestType().c_str());
sm_context_req_msg.set_request_type(smContextCreateData.getRequestType());
//PCF ID
// Priority Access
......@@ -122,29 +127,41 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
// PEI
// GPSI
// UE presence in LADN service area
// DNN Selection Mode
sm_context_req_msg.set_dnn_selection_mode(smContextCreateData.getSelMode());
Logger::smf_api_server().debug("SmContextCreateData, SelMode %s\n", smContextCreateData.getSelMode().c_str());
sm_context_req_msg.set_dnn_selection_mode(smContextCreateData.getSelMode().c_str());
//Subscription for PDU Session Status Notification
// Trace requirement
//From N1 Container (NAS)
//Extended protocol discriminator (Mandatory)
//Extended protocol discriminator (Mandatory)
Logger::smf_api_server().debug("SmContextCreateData, Extended protocol discriminator \n");
sm_context_req_msg.set_epd(decoded_nas_msg.header.extended_protocol_discriminator);
//PDU session ID (Mandatory)
Logger::smf_api_server().debug("SmContextCreateData, PDU session identity %d\n", decoded_nas_msg.plain.sm.header.pdu_session_identity);
sm_context_req_msg.set_pdu_session_id(decoded_nas_msg.plain.sm.header.pdu_session_identity);
//PTI (Mandatory)
Logger::smf_api_server().debug("SmContextCreateData, Procedure transaction ID %d\n", decoded_nas_msg.plain.sm.header.procedure_transaction_identity);
procedure_transaction_id_t pti = {.procedure_transaction_id = decoded_nas_msg.plain.sm.header.procedure_transaction_identity};
sm_context_req_msg.set_pti(pti);
//Message type (Mandatory) (PDU SESSION ESTABLISHMENT REQUEST message identity)
Logger::smf_api_server().debug("SmContextCreateData, Message Type %d\n", decoded_nas_msg.plain.sm.header.message_type);
sm_context_req_msg.set_message_type(decoded_nas_msg.plain.sm.header.message_type);
//Integrity protection maximum data rate (Mandatory)
//PDU session type (Optional)
Logger::smf_api_server().debug("SmContextCreateData, Message Type %d\n", PDN_TYPE_E_IPV4);
sm_context_req_msg.set_pdu_session_type(PDN_TYPE_E_IPV4);
if (decoded_nas_msg.plain.sm.header.message_type == PDU_SESSION_ESTABLISHMENT_REQUEST){
sm_context_req_msg.set_pdu_session_type(decoded_nas_msg.plain.sm.specific_msg.pdu_session_establishment_request._pdusessiontype.pdu_session_type_value);
//TODO: Disable this command temporarily since can't get this info from tester
//sm_context_req_msg.set_pdu_session_type(decoded_nas_msg.plain.sm.specific_msg.pdu_session_establishment_request._pdusessiontype.pdu_session_type_value);
}
//SSC mode (Optional)
......@@ -156,14 +173,9 @@ void SMContextsCollectionApiImpl::post_sm_contexts(const SmContextMessage &smCon
//Extended protocol configuration options (Optional) e.g, FOR DHCP
//Step 3. Handle the pdu_session_create_sm_context_request message in smf_app
//itti_n11_create_sm_context_request *itti_msg = new itti_n11_create_sm_context_request(TASK_SMF_N11, TASK_SMF_APP, response);
//itti_msg->req = sm_context_req_msg;
// std::shared_ptr<itti_n11_create_sm_context_request> i = std::shared_ptr<itti_n11_create_sm_context_request>(itti_msg);
std::shared_ptr<itti_n11_create_sm_context_request> itti_msg = std::make_shared<itti_n11_create_sm_context_request>(TASK_SMF_N11, TASK_SMF_APP, response);
itti_msg->req = sm_context_req_msg;
m_smf_app->handle_amf_msg(itti_msg);
std::shared_ptr<itti_n11_create_sm_context_request> itti_msg = std::make_shared<itti_n11_create_sm_context_request>(TASK_SMF_N11, TASK_SMF_APP, response);
itti_msg->req = sm_context_req_msg;
m_smf_app->handle_amf_msg(itti_msg);
}
......
......@@ -23,10 +23,8 @@
#ifndef FILE_SMF_SEEN
#define FILE_SMF_SEEN
#include"3gpp_29.274.h"
typedef uint64_t supi64_t;
#define SUPI_64_FMT "%" SCNu64
//typedef imsi_t supi_t;
......@@ -38,10 +36,8 @@ typedef struct {
char data[SUPI_DIGITS_MAX + 1];
} supi_t;
static void
smf_string_to_supi (supi_t * const supi,
char const * const supi_str)
smf_string_to_supi (supi_t * const supi, char const * const supi_str)
{
//strncpy(supi->data, supi_str, SUPI_DIGITS_MAX + 1);
memcpy((void *) supi->data, (void *) supi_str, SUPI_DIGITS_MAX + 1);
......@@ -49,6 +45,13 @@ smf_string_to_supi (supi_t * const supi,
return;
}
static std::string
smf_supi_to_string (supi_t const supi)
{
std::string supi_str;
supi_str.assign(supi.data, SUPI_DIGITS_MAX+1);
return supi_str;
}
static uint64_t
smf_supi_to_u64 (supi_t supi)
......@@ -61,9 +64,10 @@ smf_supi_to_u64 (supi_t supi)
typedef struct s_nssai // section 28.4, TS23.003
{
uint8_t sST;
uint32_t sD:24;
s_nssai(const uint8_t& sst, const uint32_t sd) : sST(sst), sD(sd) {}
//uint32_t sD:24;
std::string sD;
//s_nssai(const uint8_t& sst, const uint32_t sd) : sST(sst), sD(sd) {}
s_nssai(const uint8_t& sst, const std::string sd) : sST(sst), sD(sd) {}
s_nssai(): sST(),sD() {}
s_nssai(const s_nssai& p) : sST(p.sST), sD(p.sD) {}
......@@ -71,8 +75,6 @@ typedef struct s_nssai // section 28.4, TS23.003
typedef uint8_t pdu_session_id;
//should move to 24.501
enum pdu_session_type_e {
......
......@@ -105,7 +105,7 @@ extern "C" {
// 9.11.3.47 Request type
typedef uint8_t request_type_t;
//typedef std::string request_type_t;
enum request_type_e {
INITIAL_REQUEST = 1,
......
......@@ -329,7 +329,7 @@ int nas_message_decode (
}
if (bytes < 0) {
return bytes;
//TODO: commented for testing purpose return bytes;
//OAILOG_FUNC_RETURN (LOG_NAS, bytes);
}
......
......@@ -319,6 +319,7 @@ file(GLOB NAS_src_files
${SRC_TOP_DIR}/utils/dynamic_memory_check.c
${SRC_TOP_DIR}/utils/backtrace.c
${SRC_TOP_DIR}/utils/bstr/*.c
${SRC_TOP_DIR}/utils/multipartparser.c
${SRC_TOP_DIR}/nas/security/*.c
${SRC_TOP_DIR}/common/*.c
${SRC_TOP_DIR}/ngap/messages/*.c
......
......@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include "async_shell_cmd.hpp"
#include "common_defs.h"
#include "itti.hpp"
......@@ -27,7 +28,6 @@
#include "pistache/http.h"
#include "pistache/router.h"
#include <iostream>
#include <thread>
#include <signal.h>
......@@ -123,12 +123,9 @@ int main(int argc, char **argv)
//SMF API server
//Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(8080));
Pistache::Address addr(std::string(inet_ntoa (*((struct in_addr *)&smf_cfg.n11.addr4))) , Pistache::Port(smf_cfg.n11.port));
SMFApiServer smfApiServer(addr, smf_app_inst);
smfApiServer.init(2);
//smfApiServer.start();
//smfApiServer.shutdown();
std::thread smf_api_manager(&SMFApiServer::start, smfApiServer);
FILE *fp = NULL;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment