Commit 4f5e654e authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'show_binary_content_http_msg' into develop

parents 54340091 7ff49b51
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <curl/curl.h> #include <curl/curl.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "dynamic_memory_check.h"
#include "amf_n1.hpp" #include "amf_n1.hpp"
#include "itti.hpp" #include "itti.hpp"
#include "itti_msg_amf_app.hpp" #include "itti_msg_amf_app.hpp"
...@@ -43,6 +44,7 @@ ...@@ -43,6 +44,7 @@
#include "SMContextsCollectionApi.h" #include "SMContextsCollectionApi.h"
#include "ApiConfiguration.h" #include "ApiConfiguration.h"
#include "ApiClient.h" #include "ApiClient.h"
#include "mime_parser.hpp"
using namespace oai::smf::model; using namespace oai::smf::model;
using namespace oai::smf::api; using namespace oai::smf::api;
...@@ -253,7 +255,7 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer &smf) { ...@@ -253,7 +255,7 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer &smf) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void amf_n11::handle_pdu_session_initial_request(std::string supi, std::shared_ptr<pdu_session_context> psc, std::string smf_addr, bstring sm_msg, std::string dnn) { void amf_n11::handle_pdu_session_initial_request(std::string supi, std::shared_ptr<pdu_session_context> psc, std::string smf_addr, bstring sm_msg, std::string dnn) {
//TODO: Remove hardcoded values //TODO: Remove hardcoded values
std::string remote_uri = smf_addr + "/nsmf-pdusession/v1/sm-contexts"; //TODO std::string remote_uri = smf_addr + "/nsmf-pdusession/v1/sm-contexts"; //TODO
nlohmann::json pdu_session_establishment_request; nlohmann::json pdu_session_establishment_request;
pdu_session_establishment_request["supi"] = supi.c_str(); pdu_session_establishment_request["supi"] = supi.c_str();
pdu_session_establishment_request["pei"] = "imei-200000000000001"; pdu_session_establishment_request["pei"] = "imei-200000000000001";
...@@ -262,11 +264,11 @@ void amf_n11::handle_pdu_session_initial_request(std::string supi, std::shared_p ...@@ -262,11 +264,11 @@ void amf_n11::handle_pdu_session_initial_request(std::string supi, std::shared_p
pdu_session_establishment_request["sNssai"]["sst"] = psc.get()->snssai.sST; pdu_session_establishment_request["sNssai"]["sst"] = psc.get()->snssai.sST;
pdu_session_establishment_request["sNssai"]["sd"] = psc.get()->snssai.sD; pdu_session_establishment_request["sNssai"]["sd"] = psc.get()->snssai.sD;
pdu_session_establishment_request["pduSessionId"] = psc.get()->pdu_session_id; pdu_session_establishment_request["pduSessionId"] = psc.get()->pdu_session_id;
pdu_session_establishment_request["requestType"] = "INITIAL_REQUEST"; //TODO: from SM_MSG pdu_session_establishment_request["requestType"] = "INITIAL_REQUEST"; //TODO: from SM_MSG
pdu_session_establishment_request["servingNfId"] = "servingNfId"; pdu_session_establishment_request["servingNfId"] = "servingNfId";
pdu_session_establishment_request["servingNetwork"]["mcc"] = psc.get()->plmn.mcc; pdu_session_establishment_request["servingNetwork"]["mcc"] = psc.get()->plmn.mcc;
pdu_session_establishment_request["servingNetwork"]["mnc"] = psc.get()->plmn.mnc; pdu_session_establishment_request["servingNetwork"]["mnc"] = psc.get()->plmn.mnc;
pdu_session_establishment_request["anType"] = "3GPP_ACCESS"; //TODO pdu_session_establishment_request["anType"] = "3GPP_ACCESS"; //TODO
pdu_session_establishment_request["smContextStatusUri"] = "smContextStatusUri"; pdu_session_establishment_request["smContextStatusUri"] = "smContextStatusUri";
pdu_session_establishment_request["n1MessageContainer"]["n1MessageClass"] = "SM"; pdu_session_establishment_request["n1MessageContainer"]["n1MessageClass"] = "SM";
...@@ -346,50 +348,44 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std: ...@@ -346,50 +348,44 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std:
//TODO: //TODO:
} }
mime_parser parser = { };
std::string body;
if ((n1SmMsg.size() > 0) and (n2SmMsg.size() > 0)) {
//prepare the body content for Curl
parser.create_multipart_related_content(body, jsonData, CURL_MIME_BOUNDARY, n1SmMsg, n2SmMsg);
} else if (n1SmMsg.size() > 0) { //only N1 content
//prepare the body content for Curl
parser.create_multipart_related_content(body, jsonData, CURL_MIME_BOUNDARY, n1SmMsg, multipart_related_content_part_e::NAS);
} else if (n2SmMsg.size() > 0) { //only N2 content
//prepare the body content for Curl
parser.create_multipart_related_content(body, jsonData, CURL_MIME_BOUNDARY, n2SmMsg, multipart_related_content_part_e::NGAP);
}
Logger::amf_n11().debug("Send HTTP message to SMF with body %s", body.c_str());
uint32_t str_len = body.length();
char *body_data = (char*) malloc(str_len + 1);
memset(body_data, 0, str_len + 1);
memcpy((void*) body_data, (void*) body.c_str(), str_len);
curl_global_init (CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init(); CURL *curl = curl_easy_init();
if (curl) { if (curl) {
CURLcode res; CURLcode res = { };
struct curl_slist *headers = nullptr; struct curl_slist *headers = nullptr;
struct curl_slist *slist = nullptr;
curl_mime *mime;
curl_mime *alt;
curl_mimepart *part;
//headers = curl_slist_append(headers, "charsets: utf-8"); std::string content_type = "content-type: multipart/related; boundary=" + std::string(CURL_MIME_BOUNDARY);
headers = curl_slist_append(headers, "content-type: multipart/related"); headers = curl_slist_append(headers, content_type.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, remoteUri.c_str()); curl_easy_setopt(curl, CURLOPT_URL, remoteUri.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, SMF_CURL_TIMEOUT_MS);
curl_easy_setopt(curl, CURLOPT_INTERFACE, amf_cfg.n11.if_name.c_str());
mime = curl_mime_init(curl);
alt = curl_mime_init(curl);
//part with N1N2MessageTransferReqData (JsonData)
part = curl_mime_addpart(mime);
curl_mime_data(part, jsonData.c_str(), CURL_ZERO_TERMINATED);
curl_mime_type(part, "application/json");
if (n1SmMsg != "") {
unsigned char *n1_msg_hex = format_string_as_hex(n1SmMsg);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), n1SmMsg.length() / 2);
curl_mime_type(part, "application/vnd.3gpp.5gnas");
//curl_mime_name (part, "n1SmMsg");
}
if (n2SmMsg != "") {
unsigned char *n2_msg_hex = format_string_as_hex(n2SmMsg);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), n2SmMsg.length() / 2);
curl_mime_type(part, "application/vnd.3gpp.ngap");
//curl_mime_name (part, "n2SmMsg");
}
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
// Response information. // Response information.
long httpCode(0); long httpCode = { 0 };
std::unique_ptr < std::string > httpData(new std::string()); std::unique_ptr < std::string > httpData(new std::string());
std::unique_ptr < std::string > httpHeaderData(new std::string()); std::unique_ptr < std::string > httpHeaderData(new std::string());
...@@ -398,12 +394,15 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std: ...@@ -398,12 +394,15 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std:
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
curl_easy_setopt(curl, CURLOPT_HEADERDATA, httpHeaderData.get()); curl_easy_setopt(curl, CURLOPT_HEADERDATA, httpHeaderData.get());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_data);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
//get cause from the response //get cause from the response
std::string response = *httpData.get(); std::string response = *httpData.get();
std::string jsonData = ""; std::string json_data_response = "";
std::string n1sm = ""; std::string n1sm = "";
std::string n2sm = ""; std::string n2sm = "";
bool is_response_ok = true; bool is_response_ok = true;
...@@ -413,9 +412,9 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std: ...@@ -413,9 +412,9 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std:
//free curl before returning //free curl before returning
curl_slist_free_all(headers); curl_slist_free_all(headers);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_mime_free(mime);
return; return;
} }
if (httpCode != 200 && httpCode != 201 && httpCode != 204) { if (httpCode != 200 && httpCode != 201 && httpCode != 204) {
is_response_ok = false; is_response_ok = false;
if (response.size() < 1) { if (response.size() < 1) {
...@@ -423,12 +422,12 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std: ...@@ -423,12 +422,12 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std:
//TODO: send context response error //TODO: send context response error
return; return;
} }
if (!(multipart_parser(response, json_data_response, n1sm, n2sm))) {
if (!(multipart_parser(response, jsonData, n1sm, n2sm))) { Logger::amf_n11().error("Could not get N1/N2 content from the response");
Logger::amf_n11().error("Could not get the cause from the response"); //TODO:
} }
} else { } else {
//store location of created context //store location of the created context
std::string header_response = *httpHeaderData.get(); std::string header_response = *httpHeaderData.get();
std::string CRLF = "\r\n"; std::string CRLF = "\r\n";
std::size_t location_pos = header_response.find("Location"); std::size_t location_pos = header_response.find("Location");
...@@ -437,24 +436,37 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std: ...@@ -437,24 +436,37 @@ void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, std:
Logger::amf_n11().info("Location of the SMF context created: %s", location.c_str()); Logger::amf_n11().info("Location of the SMF context created: %s", location.c_str());
psc.get()->smf_context_location = location; psc.get()->smf_context_location = location;
} }
nlohmann::json response_data;
nlohmann::json response_data = { };
bstring n1sm_hex; bstring n1sm_hex;
if (!is_response_ok) { if (!is_response_ok) {
response_data = nlohmann::json::parse(jsonData); try {
Logger::amf_n11().debug("Get response with jsonData: %s", jsonData.c_str()); response_data = nlohmann::json::parse(json_data_response);
msg_str_2_msg_hex(n1sm.substr(0, n1sm.length() - 2), n1sm_hex); //pdu session establishment reject bugs from SMF } catch (nlohmann::json::exception &e) {
Logger::amf_n11().warn("Could not get Json content from the response");
//Set the default Cause
response_data["error"]["cause"] = "504 Gateway Timeout";
}
Logger::amf_n11().debug("Get response with jsonData: %s", json_data_response.c_str());
msg_str_2_msg_hex(n1sm.substr(0, n1sm.length() - 2), n1sm_hex); //pdu session establishment reject bugs from SMF
print_buffer("amf_n11", "Get response with n1sm:", (uint8_t*) bdata(n1sm_hex), blength(n1sm_hex)); print_buffer("amf_n11", "Get response with n1sm:", (uint8_t*) bdata(n1sm_hex), blength(n1sm_hex));
std::string cause = response_data["error"]["cause"]; std::string cause = response_data["error"]["cause"];
Logger::amf_n11().error("Call Network Function services failure"); Logger::amf_n11().error("Call Network Function services failure");
Logger::amf_n11().info("Cause value: %s", cause.c_str()); Logger::amf_n11().debug("Cause value: %s", cause.c_str());
if (!cause.compare("DNN_DENIED")) if (!cause.compare("DNN_DENIED"))
handle_post_sm_context_response_error(httpCode, cause, n1sm_hex, supi, pdu_session_id); handle_post_sm_context_response_error(httpCode, cause, n1sm_hex, supi, pdu_session_id);
} }
curl_slist_free_all(headers); curl_slist_free_all(headers);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_mime_free(mime);
} }
curl_global_cleanup();
if (body_data != nullptr) {
free(body_data);
body_data = NULL;
}
} }
...@@ -95,6 +95,12 @@ enum class http_response_codes_e { ...@@ -95,6 +95,12 @@ enum class http_response_codes_e {
}; };
//for CURL
#define SMF_CURL_TIMEOUT_MS 100L
#define SMF_NUMBER_RETRIES 3
constexpr auto CURL_MIME_BOUNDARY = "----Boundary";
#endif #endif
...@@ -314,6 +314,8 @@ include_directories(${SRC_TOP_DIR}/itti) ...@@ -314,6 +314,8 @@ include_directories(${SRC_TOP_DIR}/itti)
include_directories(${SRC_TOP_DIR}/itti/msgs) include_directories(${SRC_TOP_DIR}/itti/msgs)
include_directories(${SRC_TOP_DIR}/common) include_directories(${SRC_TOP_DIR}/common)
include_directories(${SRC_TOP_DIR}/common/unicode) include_directories(${SRC_TOP_DIR}/common/unicode)
include_directories(${SRC_TOP_DIR}/utils)
include_directories(${SRC_TOP_DIR}/utils/bstr)
include_directories(${SRC_TOP_DIR}/contexts) include_directories(${SRC_TOP_DIR}/contexts)
include_directories(${SRC_TOP_DIR}/nas/ies) include_directories(${SRC_TOP_DIR}/nas/ies)
include_directories(${SRC_TOP_DIR}/nas/common) include_directories(${SRC_TOP_DIR}/nas/common)
...@@ -333,8 +335,6 @@ include_directories(${SRC_TOP_DIR}/sbi/smf_client/model) ...@@ -333,8 +335,6 @@ include_directories(${SRC_TOP_DIR}/sbi/smf_client/model)
include_directories(${SRC_TOP_DIR}/sctp) include_directories(${SRC_TOP_DIR}/sctp)
include_directories(${SRC_TOP_DIR}/secu_algorithms/5gaka) include_directories(${SRC_TOP_DIR}/secu_algorithms/5gaka)
include_directories(${SRC_TOP_DIR}/secu_algorithms/nas_enc_int) include_directories(${SRC_TOP_DIR}/secu_algorithms/nas_enc_int)
include_directories(${SRC_TOP_DIR}/utils)
include_directories(${SRC_TOP_DIR}/utils/bstr)
add_executable(amf add_executable(amf
${SRC_TOP_DIR}/oai-amf/main.cpp ${SRC_TOP_DIR}/oai-amf/main.cpp
......
...@@ -29,6 +29,7 @@ include_directories(${SRC_TOP_DIR}/utils/bstr) ...@@ -29,6 +29,7 @@ include_directories(${SRC_TOP_DIR}/utils/bstr)
add_library (AMF_UTILS STATIC add_library (AMF_UTILS STATIC
${CMAKE_CURRENT_SOURCE_DIR}/backtrace.c ${CMAKE_CURRENT_SOURCE_DIR}/backtrace.c
${CMAKE_CURRENT_SOURCE_DIR}/conversions.c ${CMAKE_CURRENT_SOURCE_DIR}/conversions.c
${CMAKE_CURRENT_SOURCE_DIR}/dynamic_memory_check.c
${CMAKE_CURRENT_SOURCE_DIR}/hex_string_convert.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hex_string_convert.cpp
${CMAKE_CURRENT_SOURCE_DIR}/http_multi_parser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/http_multi_parser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/if.cpp ${CMAKE_CURRENT_SOURCE_DIR}/if.cpp
......
/*
* Copyright (c) 2015, EURECOM (www.eurecom.fr)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of the FreeBSD Project.
*/
#include <stdlib.h>
#include "dynamic_memory_check.h"
#include "assertions.h"
//------------------------------------------------------------------------------
void free_wrapper(void **ptr)
{
// for debug only
AssertFatal(ptr, "Trying to free NULL ptr");
if (ptr) {
free(*ptr);
*ptr = NULL;
}
}
//------------------------------------------------------------------------------
void bdestroy_wrapper(bstring *b)
{
if ((b) && (*b)) {
bdestroy(*b);
*b = NULL;
}
}
/*
* 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 dynamic_memory_check.h
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_DYNAMIC_MEMORY_CHECK_SEEN
#define FILE_DYNAMIC_MEMORY_CHECK_SEEN
# include "bstrlib.h"
void free_wrapper(void **ptr) __attribute__ ((hot));
void bdestroy_wrapper(bstring *b);
#endif /* FILE_DYNAMIC_MEMORY_CHECK_SEEN */
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