Commit 3fa12767 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Fix conflict

parents 824b4f0a c99d5a7f
...@@ -9,7 +9,11 @@ OPENAIR-CN-5G is an implementation of the 3GPP specifications for the 5G Core Ne ...@@ -9,7 +9,11 @@ OPENAIR-CN-5G is an implementation of the 3GPP specifications for the 5G Core Ne
At the moment, it contains the following network elements: At the moment, it contains the following network elements:
* Access and Mobility Management Function (**AMF**) * Access and Mobility Management Function (**AMF**)
* Authentication Server Management Function (**AUSF**)
* Network Repository Function (**NRF**)
* Session Management Function (**SMF**) * Session Management Function (**SMF**)
* Unified Data Management (**UDM**)
* Unified Data Repository (**UDR**)
* User Plane Function (**UPF**) * User Plane Function (**UPF**)
Each has its own repository: this repository (`oai-cn5g-smf`) is meant for SMF. Each has its own repository: this repository (`oai-cn5g-smf`) is meant for SMF.
......
...@@ -179,7 +179,7 @@ pipeline { ...@@ -179,7 +179,7 @@ pipeline {
echo "Maybe a previous build went wrong" echo "Maybe a previous build went wrong"
} }
// In case of push to `develop` branch we build from scratch // In case of push to `develop` branch we build from scratch
myShCmd('docker build --no-cache --target oai-smf --tag oai-smf:' + smf_tag + ' --file docker/Dockerfile.ubuntu18.04 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > archives/smf_docker_image_build.log 2>&1', rem_u18_host_flag, rem_u18_host_user, rem_u18_host) myShCmd('docker build --no-cache --target oai-smf --tag oai-smf:' + smf_tag + ' --file docker/Dockerfile.smf.ubuntu18 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > archives/smf_docker_image_build.log 2>&1', rem_u18_host_flag, rem_u18_host_user, rem_u18_host)
} }
if ("MERGE".equals(env.gitlabActionType)) { if ("MERGE".equals(env.gitlabActionType)) {
try { try {
...@@ -235,7 +235,7 @@ pipeline { ...@@ -235,7 +235,7 @@ pipeline {
myShCmd('mkdir -p tmp/ca tmp/entitlement', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host) myShCmd('mkdir -p tmp/ca tmp/entitlement', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host)
myShCmd('cp /etc/pki/entitlement/*pem tmp/entitlement', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host) myShCmd('cp /etc/pki/entitlement/*pem tmp/entitlement', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host)
myShCmd('sudo cp /etc/rhsm/ca/redhat-uep.pem tmp/ca', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host) myShCmd('sudo cp /etc/rhsm/ca/redhat-uep.pem tmp/ca', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host)
myShCmd('sudo podman build --no-cache --target oai-smf --tag oai-smf:' + smf_tag + ' --file docker/Dockerfile.smf.rhel8.2 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > archives/smf_podman_image_build.log 2>&1', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host) myShCmd('sudo podman build --no-cache --target oai-smf --tag oai-smf:' + smf_tag + ' --file docker/Dockerfile.smf.rhel8 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > archives/smf_podman_image_build.log 2>&1', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host)
myShCmd('sudo podman image ls >> archives/smf_podman_image_build.log', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host) myShCmd('sudo podman image ls >> archives/smf_podman_image_build.log', rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host)
if ("MERGE".equals(env.gitlabActionType)) { if ("MERGE".equals(env.gitlabActionType)) {
myShCmd('sudo podman image tag oai-smf:' + smf_tag + ' oai-smf:' + rhel_smf_tag, rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host) myShCmd('sudo podman image tag oai-smf:' + smf_tag + ' oai-smf:' + rhel_smf_tag, rem_rhel_host_flag, rem_rhel_host_user, rem_rhel_host)
......
...@@ -143,7 +143,6 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -143,7 +143,6 @@ void IndividualSMContextApiImpl::update_sm_context(
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
mime_parser parser = {};
std::string body = {}; std::string body = {};
std::string json_format; std::string json_format;
...@@ -153,7 +152,7 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -153,7 +152,7 @@ void IndividualSMContextApiImpl::update_sm_context(
if (sm_context_response.n1_sm_msg_is_set() and if (sm_context_response.n1_sm_msg_is_set() and
sm_context_response.n2_sm_info_is_set()) { sm_context_response.n2_sm_info_is_set()) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format); sm_context_response.get_n2_sm_information(), json_format);
...@@ -161,7 +160,7 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -161,7 +160,7 @@ void IndividualSMContextApiImpl::update_sm_context(
Pistache::Http::Mime::MediaType( Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY))); "multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
} else if (sm_context_response.n1_sm_msg_is_set()) { } else if (sm_context_response.n1_sm_msg_is_set()) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
multipart_related_content_part_e::NAS, json_format); multipart_related_content_part_e::NAS, json_format);
...@@ -169,7 +168,7 @@ void IndividualSMContextApiImpl::update_sm_context( ...@@ -169,7 +168,7 @@ void IndividualSMContextApiImpl::update_sm_context(
Pistache::Http::Mime::MediaType( Pistache::Http::Mime::MediaType(
"multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY))); "multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY)));
} else if (sm_context_response.n2_sm_info_is_set()) { } else if (sm_context_response.n2_sm_info_is_set()) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n2_sm_information(), sm_context_response.get_n2_sm_information(),
multipart_related_content_part_e::NGAP, json_format); multipart_related_content_part_e::NGAP, json_format);
......
...@@ -103,7 +103,6 @@ void SMContextsCollectionApiImpl::post_sm_contexts( ...@@ -103,7 +103,6 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
mime_parser parser = {};
std::string json_format = {}; std::string json_format = {};
std::string body = {}; std::string body = {};
...@@ -112,7 +111,7 @@ void SMContextsCollectionApiImpl::post_sm_contexts( ...@@ -112,7 +111,7 @@ void SMContextsCollectionApiImpl::post_sm_contexts(
if (sm_context_response.n1_sm_msg_is_set()) { // add N1 container if if (sm_context_response.n1_sm_msg_is_set()) { // add N1 container if
// available // available
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
multipart_related_content_part_e::NAS, json_format); multipart_related_content_part_e::NAS, json_format);
......
...@@ -420,7 +420,6 @@ void smf_http2_server::update_sm_context_handler( ...@@ -420,7 +420,6 @@ void smf_http2_server::update_sm_context_handler(
Logger::smf_api_server().debug("Got result for promise ID %d", promise_id); Logger::smf_api_server().debug("Got result for promise ID %d", promise_id);
nlohmann::json json_data = {}; nlohmann::json json_data = {};
mime_parser parser = {};
std::string body = {}; std::string body = {};
header_map h = {}; header_map h = {};
std::string json_format = {}; std::string json_format = {};
...@@ -431,7 +430,7 @@ void smf_http2_server::update_sm_context_handler( ...@@ -431,7 +430,7 @@ void smf_http2_server::update_sm_context_handler(
if (sm_context_response.n1_sm_msg_is_set() and if (sm_context_response.n1_sm_msg_is_set() and
sm_context_response.n2_sm_info_is_set()) { sm_context_response.n2_sm_info_is_set()) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
sm_context_response.get_n2_sm_information(), json_format); sm_context_response.get_n2_sm_information(), json_format);
...@@ -439,7 +438,7 @@ void smf_http2_server::update_sm_context_handler( ...@@ -439,7 +438,7 @@ void smf_http2_server::update_sm_context_handler(
"content-type", header_value{"multipart/related; boundary=" + "content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)}); std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n1_sm_msg_is_set()) { } else if (sm_context_response.n1_sm_msg_is_set()) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n1_sm_message(), sm_context_response.get_n1_sm_message(),
multipart_related_content_part_e::NAS, json_format); multipart_related_content_part_e::NAS, json_format);
...@@ -447,7 +446,7 @@ void smf_http2_server::update_sm_context_handler( ...@@ -447,7 +446,7 @@ void smf_http2_server::update_sm_context_handler(
"content-type", header_value{"multipart/related; boundary=" + "content-type", header_value{"multipart/related; boundary=" +
std::string(CURL_MIME_BOUNDARY)}); std::string(CURL_MIME_BOUNDARY)});
} else if (sm_context_response.n2_sm_info_is_set()) { } else if (sm_context_response.n2_sm_info_is_set()) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_data.dump(), CURL_MIME_BOUNDARY, body, json_data.dump(), CURL_MIME_BOUNDARY,
sm_context_response.get_n2_sm_information(), sm_context_response.get_n2_sm_information(),
multipart_related_content_part_e::NGAP, json_format); multipart_related_content_part_e::NGAP, json_format);
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#include "logger.hpp" #include "logger.hpp"
#include "conversions.hpp" #include "conversions.hpp"
extern "C" {
#include "dynamic_memory_check.h"
}
bool mime_parser::parse(const std::string& str) { bool mime_parser::parse(const std::string& str) {
std::string CRLF = "\r\n"; std::string CRLF = "\r\n";
Logger::smf_app().debug("Parsing the message with Simple Parser"); Logger::smf_app().debug("Parsing the message with Simple Parser");
...@@ -127,6 +131,10 @@ void mime_parser::create_multipart_related_content( ...@@ -127,6 +131,10 @@ void mime_parser::create_multipart_related_content(
body.append(CRLF); body.append(CRLF);
body.append(std::string((char*) n2_msg_hex, n2_message.length() / 2) + CRLF); body.append(std::string((char*) n2_msg_hex, n2_message.length() / 2) + CRLF);
body.append("--" + boundary + "--" + CRLF); body.append("--" + boundary + "--" + CRLF);
// free memory
free_wrapper((void**) &n1_msg_hex);
free_wrapper((void**) &n2_msg_hex);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
...@@ -158,4 +166,7 @@ void mime_parser::create_multipart_related_content( ...@@ -158,4 +166,7 @@ void mime_parser::create_multipart_related_content(
body.append(CRLF); body.append(CRLF);
body.append(std::string((char*) msg_hex, message.length() / 2) + CRLF); body.append(std::string((char*) msg_hex, message.length() / 2) + CRLF);
body.append("--" + boundary + "--" + CRLF); body.append("--" + boundary + "--" + CRLF);
// free memory
free_wrapper((void**) &msg_hex);
} }
...@@ -62,7 +62,7 @@ class mime_parser { ...@@ -62,7 +62,7 @@ class mime_parser {
* @param [const std::string&] str: input string * @param [const std::string&] str: input string
* @return String represents string in hex format * @return String represents string in hex format
*/ */
unsigned char* format_string_as_hex(const std::string& str); static unsigned char* format_string_as_hex(const std::string& str);
/* /*
* Create HTTP body content for multipart/related message * Create HTTP body content for multipart/related message
...@@ -73,7 +73,7 @@ class mime_parser { ...@@ -73,7 +73,7 @@ class mime_parser {
* @param [std::string] n2_message: N2 (NGAP) part * @param [std::string] n2_message: N2 (NGAP) part
* @return void * @return void
*/ */
void create_multipart_related_content( void static create_multipart_related_content(
std::string& body, const std::string& json_part, std::string& body, const std::string& json_part,
const std::string boundary, const std::string& n1_message, const std::string boundary, const std::string& n1_message,
const std::string& n2_message, const std::string& n2_message,
...@@ -88,7 +88,7 @@ class mime_parser { ...@@ -88,7 +88,7 @@ class mime_parser {
* @param [uint8_t] content_type: 1 for NAS content, else NGAP content * @param [uint8_t] content_type: 1 for NAS content, else NGAP content
* @return void * @return void
*/ */
void create_multipart_related_content( void static create_multipart_related_content(
std::string& body, const std::string& json_part, std::string& body, const std::string& json_part,
const std::string boundary, const std::string& message, const std::string boundary, const std::string& message,
const multipart_related_content_part_e content_type, const multipart_related_content_part_e content_type,
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "logger.hpp" #include "logger.hpp"
#include "msg_pfcp.hpp" #include "msg_pfcp.hpp"
#include "serializable.hpp" #include "serializable.hpp"
#include "string.hpp"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <cstring> #include <cstring>
...@@ -868,11 +869,14 @@ class pfcp_fteid_ie : public pfcp_ie { ...@@ -868,11 +869,14 @@ class pfcp_fteid_ie : public pfcp_ie {
class pfcp_network_instance_ie : public pfcp_ie { class pfcp_network_instance_ie : public pfcp_ie {
public: public:
std::string network_instance; std::string network_instance;
std::string network_instance_dotted;
//-------- //--------
explicit pfcp_network_instance_ie(const pfcp::network_instance_t& b) explicit pfcp_network_instance_ie(const pfcp::network_instance_t& b)
: pfcp_ie(PFCP_IE_NETWORK_INSTANCE) { : pfcp_ie(PFCP_IE_NETWORK_INSTANCE) {
network_instance = b.network_instance; network_instance = b.network_instance;
util::string_to_dotted(network_instance, network_instance_dotted);
network_instance = network_instance_dotted;
tlv.set_length(network_instance.size()); tlv.set_length(network_instance.size());
} }
//-------- //--------
......
...@@ -23,6 +23,7 @@ include_directories(${SRC_TOP_DIR}/common) ...@@ -23,6 +23,7 @@ include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/itti) include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/common/msg) include_directories(${SRC_TOP_DIR}/common/msg)
include_directories(${SRC_TOP_DIR}/common/utils) include_directories(${SRC_TOP_DIR}/common/utils)
include_directories(${SRC_TOP_DIR}/common/utils/bstr)
include_directories(${SRC_TOP_DIR}/oai_smf) include_directories(${SRC_TOP_DIR}/oai_smf)
include_directories(${SRC_TOP_DIR}/pfcp) include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/udp) include_directories(${SRC_TOP_DIR}/udp)
......
...@@ -363,6 +363,13 @@ smf_app::smf_app(const std::string& config_file) ...@@ -363,6 +363,13 @@ smf_app::smf_app(const std::string& config_file)
Logger::smf_app().startup("Started"); Logger::smf_app().startup("Started");
} }
//------------------------------------------------------------------------------
smf_app::~smf_app() {
Logger::smf_app().debug("Delete SMF_APP instance...");
// TODO: Unregister NRF
if (smf_n4_inst) delete smf_n4_inst;
if (smf_sbi_inst) delete smf_sbi_inst;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void smf_app::start_upf_association(const pfcp::node_id_t& node_id) { void smf_app::start_upf_association(const pfcp::node_id_t& node_id) {
std::time_t time_epoch = std::time(nullptr); std::time_t time_epoch = std::time(nullptr);
......
...@@ -206,11 +206,7 @@ class smf_app { ...@@ -206,11 +206,7 @@ class smf_app {
public: public:
explicit smf_app(const std::string& config_file); explicit smf_app(const std::string& config_file);
smf_app(smf_app const&) = delete; smf_app(smf_app const&) = delete;
virtual ~smf_app();
virtual ~smf_app() {
Logger::smf_app().debug("Delete SMF_APP instance...");
// TODO: Unregister NRF
}
void operator=(smf_app const&) = delete; void operator=(smf_app const&) = delete;
......
...@@ -192,7 +192,6 @@ void smf_sbi::send_n1n2_message_transfer_request( ...@@ -192,7 +192,6 @@ void smf_sbi::send_n1n2_message_transfer_request(
"Send Communication_N1N2MessageTransfer to AMF (HTTP version %d)", "Send Communication_N1N2MessageTransfer to AMF (HTTP version %d)",
sm_context_res->http_version); sm_context_res->http_version);
mime_parser parser = {};
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string body; std::string body;
...@@ -201,12 +200,12 @@ void smf_sbi::send_n1n2_message_transfer_request( ...@@ -201,12 +200,12 @@ void smf_sbi::send_n1n2_message_transfer_request(
// Add N2 content if available // Add N2 content if available
auto n2_sm_found = json_data.count("n2InfoContainer"); auto n2_sm_found = json_data.count("n2InfoContainer");
if (n2_sm_found > 0) { if (n2_sm_found > 0) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_part, CURL_MIME_BOUNDARY, body, json_part, CURL_MIME_BOUNDARY,
sm_context_res->res.get_n1_sm_message(), sm_context_res->res.get_n1_sm_message(),
sm_context_res->res.get_n2_sm_information()); sm_context_res->res.get_n2_sm_information());
} else { } else {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_part, CURL_MIME_BOUNDARY, body, json_part, CURL_MIME_BOUNDARY,
sm_context_res->res.get_n1_sm_message(), sm_context_res->res.get_n1_sm_message(),
multipart_related_content_part_e::NAS); multipart_related_content_part_e::NAS);
...@@ -292,7 +291,6 @@ void smf_sbi::send_n1n2_message_transfer_request( ...@@ -292,7 +291,6 @@ void smf_sbi::send_n1n2_message_transfer_request(
sm_session_modification) { sm_session_modification) {
Logger::smf_sbi().debug("Send Communication_N1N2MessageTransfer to AMF"); Logger::smf_sbi().debug("Send Communication_N1N2MessageTransfer to AMF");
mime_parser parser = {};
std::string body; std::string body;
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string json_part; std::string json_part;
...@@ -302,12 +300,12 @@ void smf_sbi::send_n1n2_message_transfer_request( ...@@ -302,12 +300,12 @@ void smf_sbi::send_n1n2_message_transfer_request(
// add N2 content if available // add N2 content if available
auto n2_sm_found = json_data.count("n2InfoContainer"); auto n2_sm_found = json_data.count("n2InfoContainer");
if (n2_sm_found > 0) { if (n2_sm_found > 0) {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_part, CURL_MIME_BOUNDARY, body, json_part, CURL_MIME_BOUNDARY,
sm_session_modification->msg.get_n1_sm_message(), sm_session_modification->msg.get_n1_sm_message(),
sm_session_modification->msg.get_n2_sm_information()); sm_session_modification->msg.get_n2_sm_information());
} else { } else {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_part, CURL_MIME_BOUNDARY, body, json_part, CURL_MIME_BOUNDARY,
sm_session_modification->msg.get_n1_sm_message(), sm_session_modification->msg.get_n1_sm_message(),
multipart_related_content_part_e::NAS); multipart_related_content_part_e::NAS);
...@@ -360,7 +358,6 @@ void smf_sbi::send_n1n2_message_transfer_request( ...@@ -360,7 +358,6 @@ void smf_sbi::send_n1n2_message_transfer_request(
"Send Communication_N1N2MessageTransfer to AMF (Network-initiated " "Send Communication_N1N2MessageTransfer to AMF (Network-initiated "
"Service Request)"); "Service Request)");
mime_parser parser = {};
std::string n2_message = report_msg->res.get_n2_sm_information(); std::string n2_message = report_msg->res.get_n2_sm_information();
nlohmann::json json_data = {}; nlohmann::json json_data = {};
std::string body; std::string body;
...@@ -371,11 +368,11 @@ void smf_sbi::send_n1n2_message_transfer_request( ...@@ -371,11 +368,11 @@ void smf_sbi::send_n1n2_message_transfer_request(
auto n1_sm_found = json_data.count("n1MessageContainer"); auto n1_sm_found = json_data.count("n1MessageContainer");
if (n1_sm_found > 0) { if (n1_sm_found > 0) {
std::string n1_message = report_msg->res.get_n1_sm_message(); std::string n1_message = report_msg->res.get_n1_sm_message();
// Prepare the body content for Curl // prepare the body content for Curl
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_part, CURL_MIME_BOUNDARY, n1_message, n2_message); body, json_part, CURL_MIME_BOUNDARY, n1_message, n2_message);
} else { } else {
parser.create_multipart_related_content( mime_parser::create_multipart_related_content(
body, json_part, CURL_MIME_BOUNDARY, n2_message, body, json_part, CURL_MIME_BOUNDARY, n2_message,
multipart_related_content_part_e::NGAP); multipart_related_content_part_e::NGAP);
} }
......
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