Commit 89d041b9 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

Merge branch 'release_v1.0' into 'develop'

Merge Release v1.0 into Develop

See merge request oai/oai-cn5g-smf!11
parents ef0b47fa 994a83df
......@@ -71,13 +71,13 @@ SMF =
);
};
APN_LIST = (
DNN_LIST = (
# IPV4_POOL, IPV6_POOL are index in IPV4_LIST, IPV6_LIST, PDN_TYPE choice in {IPv4, IPv6, IPv4v6}
{APN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1},
{APN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
{APN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
{APN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1},
{APN_NI = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1}
{DNN_NI = "default"; PDN_TYPE = "IPv4"; IPV4_POOL = 0; IPV6_POOL = -1},
{DNN_NI = "carrier.com"; PDN_TYPE = "IPv4"; IPV4_POOL = 1; IPV6_POOL = -1},
{DNN_NI = "apn2"; PDN_TYPE = "IPv4"; IPV4_POOL = 2; IPV6_POOL = -1},
{DNN_NI = "apn3"; PDN_TYPE = "IPv4"; IPV4_POOL = 3; IPV6_POOL = -1},
{DNN_NI = "apn4"; PDN_TYPE = "IPv4"; IPV4_POOL = 4; IPV6_POOL = -1}
);
# DNS address communicated to UEs
......@@ -97,12 +97,26 @@ SMF =
UDM :
{
IPV4_ADDRESS="@UDM_IPV4_ADDRESS@";
PORT = @UDM_PORT@; #should be removed (default 80)
PORT = @UDM_PORT@; #should be removed (default 80)
};
UPF_LIST = (
{IPV4_ADDRESS="@UPF_IPV4_ADDRESS@" ;}
);
LOCAL_CONFIGURATION :
{
USE_LOCAL_CONFIGURATION = "yes";
SESSION_MANAGEMENT_SUBSCRIPTION_LIST = (
{ NSSAI_SST = 222; NSSAI_SD = "123", DNN = "default", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
QOS_PROFILE_5QI = 6, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT",
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "20Mbps", SESSION_AMBR_DL = "22Mbps"},
{ NSSAI_SST = 222; NSSAI_SD = "123", DNN = "carrier.com", DEFAULT_SESSION_TYPE = "IPV4", DEFAULT_SSC_MODE = 1,
QOS_PROFILE_5QI = 7, QOS_PROFILE_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PRIORITY_LEVEL = 1, QOS_PROFILE_ARP_PREEMPTCAP = "NOT_PREEMPT",
QOS_PROFILE_ARP_PREEMPTVULN = "NOT_PREEMPTABLE", SESSION_AMBR_UL = "10Mbps", SESSION_AMBR_DL = "11Mbps"}
);
};
};
......@@ -43,10 +43,7 @@
#include "logger.hpp"
#include "Helpers.h"
extern "C" {
#include "multipartparser.h"
#include "dynamic_memory_check.h"
}
#include "simple_parser.hpp"
namespace oai {
namespace smf_server {
......@@ -141,91 +138,39 @@ void IndividualSMContextApi::update_sm_context_handler(
Logger::smf_api_server().info(
"Received a SM context update request from AMF.");
Logger::smf_api_server().debug("Request body: %s\n", request.body().c_str());
//find boundary
std::size_t found = request.body().find("Content-Type");
std::string boundary_str = request.body().substr(2, found - 4);
Logger::smf_api_server().debug("Boundary: %s", boundary_str.c_str());
SmContextUpdateMessage smContextUpdateMessage = { };
//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,
reinterpret_cast<const char*>(boundary_str.c_str()));
unsigned int str_len = request.body().length();
unsigned char *data = (unsigned char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) request.body().c_str(), str_len);
//if ((multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) != strlen(request.body().c_str())) or (!g_body_begin_called)){
if ((multipartparser_execute(&parser, &g_callbacks,
reinterpret_cast<const char*>(data), str_len)
!= strlen(request.body().c_str())) or (!g_body_begin_called)) {
Logger::smf_api_server().debug(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
//return;
}
//simple parser
simple_parser sp = { };
sp.parse(request.body());
free_wrapper((void**) &data);
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size());
part p0 = { };
part p1 = { };
if (size > 0) {
p0 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 1: %s", p0.body.c_str());
}
if (size > 1) {
p1 = g_parts.front();
g_parts.pop_front();
Logger::smf_api_server().debug("Request body, part 2: %s (%d bytes)",
p1.body.c_str(), p1.body.length());
//part p2 = g_parts.front(); g_parts.pop_front();
//Logger::smf_api_server().debug("Request body, part 3: \n %s",p2.body.c_str());
}
std::vector<mime_part> parts = { };
sp.get_mime_parts(parts);
uint8_t size = parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", size);
// Getting the body param
SmContextUpdateData smContextUpdateData = { };
try {
if (size > 0) {
nlohmann::json::parse(p0.body.c_str()).get_to(smContextUpdateData);
nlohmann::json::parse(parts[0].body.c_str()).get_to(smContextUpdateData);
} else {
nlohmann::json::parse(request.body().c_str()).get_to(smContextUpdateData);
}
smContextUpdateMessage.setJsonData(smContextUpdateData);
if (size > 1) {
if (smContextUpdateData.n2SmInfoIsSet()) {
//N2 SM (for Session establishment, or for session modification)
Logger::smf_api_server().debug("N2 SM information is set");
smContextUpdateMessage.setBinaryDataN2SmInformation(p1.body);
}
if (smContextUpdateData.n1SmMsgIsSet()) {
//N1 SM (for session modification, UE-initiated)
for (int i = 1; i < size; i++) {
if (parts[i].content_type.compare("application/vnd.3gpp.5gnas") == 0) {
smContextUpdateMessage.setBinaryDataN1SmMessage(parts[i].body);
Logger::smf_api_server().debug("N1 SM message is set");
smContextUpdateMessage.setBinaryDataN1SmMessage(p1.body);
} else if (parts[i].content_type.compare("application/vnd.3gpp.ngap")
== 0) {
smContextUpdateMessage.setBinaryDataN2SmInformation(parts[i].body);
Logger::smf_api_server().debug("N2 SM information is set");
}
}
// Getting the path params
auto smContextRef = request.param(":smContextRef").as<std::string>();
this->update_sm_context(smContextRef, smContextUpdateMessage, response);
......
......@@ -43,8 +43,9 @@
#include "logger.hpp"
#include "Helpers.h"
#include "simple_parser.hpp"
extern "C" {
#include "multipartparser.h"
#include "dynamic_memory_check.h"
}
......@@ -85,77 +86,34 @@ void SMContextsCollectionApi::post_sm_contexts_handler(
Logger::smf_api_server().debug("");
Logger::smf_api_server().info(
"Received a SM context create request from AMF.");
Logger::smf_api_server().debug("Request body: %s", request.body().c_str());
//find boundary
std::size_t found = request.body().find("Content-Type");
std::string boundary_str = request.body().substr(2, found - 4);
Logger::smf_api_server().debug("Boundary: %s", boundary_str.c_str());
SmContextMessage smContextMessage = { };
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,
reinterpret_cast<const char*>(boundary_str.c_str()));
unsigned int str_len = request.body().length();
unsigned char *data = (unsigned char*) malloc(str_len + 1);
memset(data, 0, str_len + 1);
memcpy((void*) data, (void*) request.body().c_str(), str_len);
//if ((multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) != strlen(request.body().c_str())) or (!g_body_begin_called)){
if ((multipartparser_execute(&parser, &g_callbacks,
reinterpret_cast<const char*>(data), str_len)
!= strlen(request.body().c_str())) or (!g_body_begin_called)) {
Logger::smf_api_server().debug(
"The received message can not be parsed properly!");
//TODO: fix this issue
//response.send(Pistache::Http::Code::Bad_Request, "");
//return;
}
free_wrapper((void**) &data);
//simple parser
simple_parser sp = { };
sp.parse(request.body());
uint8_t size = g_parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", g_parts.size());
std::vector<mime_part> parts = { };
sp.get_mime_parts(parts);
uint8_t size = parts.size();
Logger::smf_api_server().debug("Number of MIME parts %d", size);
//at least 2 parts for Json data and N1 (+ N2)
if (g_parts.size() < 2) {
if (size < 2) {
response.send(Pistache::Http::Code::Bad_Request, "");
return;
}
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() > 0) {
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(smContextCreateData);
nlohmann::json::parse(parts[0].body.c_str()).get_to(smContextCreateData);
smContextMessage.setJsonData(smContextCreateData);
smContextMessage.setBinaryDataN1SmMessage(p1.body);
if (parts[1].content_type.compare("application/vnd.3gpp.5gnas") == 0) {
smContextMessage.setBinaryDataN1SmMessage(parts[1].body);
} else if (parts[1].content_type.compare("application/vnd.3gpp.ngap")
== 0) {
smContextMessage.setBinaryDataN2SmInformation(parts[1].body);
}
this->post_sm_contexts(smContextMessage, response);
} catch (nlohmann::detail::exception &e) {
//send a 400 error
......
/*
* 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 Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* 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
*/
#ifndef FILE_AMF_SEEN
#define FILE_AMF_SEEN
#endif
......@@ -300,7 +300,11 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
dest),
scid(0),
response_code(0),
msg_type(0) {
msg_type(0),
procedure_type(
session_management_procedures_type_e::PROCEDURE_TYPE_UNKNOWN),
seid(0),
trxn_id(0) {
}
itti_n11_n1n2_message_transfer_response_status(
const itti_n11_n1n2_message_transfer_response_status &i)
......@@ -308,7 +312,10 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
itti_n11_msg(i),
scid(i.scid),
response_code(i.response_code),
msg_type(i.msg_type) {
msg_type(i.msg_type),
procedure_type(i.procedure_type),
seid(i.seid),
trxn_id(i.trxn_id) {
}
itti_n11_n1n2_message_transfer_response_status(
const itti_n11_n1n2_message_transfer_response_status &i,
......@@ -317,7 +324,10 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
itti_n11_msg(i, orig, dest),
scid(i.scid),
response_code(i.response_code),
msg_type(i.msg_type) {
msg_type(i.msg_type),
procedure_type(i.procedure_type),
seid(i.seid),
trxn_id(i.trxn_id) {
}
const char* get_msg_name() {
return "N11_SESSION_N1N2_MESSAGE_TRANSFER_RESPONSE_STATUS";
......@@ -339,10 +349,28 @@ class itti_n11_n1n2_message_transfer_response_status : public itti_n11_msg {
msg_type = type;
}
;
void set_procedure_type(session_management_procedures_type_e type) {
procedure_type = type;
}
;
void set_seid(const seid_t &s) {
seid = s;
}
;
void set_trxn_id(uint64_t t) {
trxn_id = t;
}
;
scid_t scid; //SM Context ID
int16_t response_code;
std::string cause;
uint8_t msg_type;
session_management_procedures_type_e procedure_type;
seid_t seid;
uint64_t trxn_id;
};
......@@ -396,8 +424,8 @@ class itti_n11_release_sm_context_request : public itti_n11_msg {
class itti_n11_release_sm_context_response : public itti_n11_msg {
public:
itti_n11_release_sm_context_response(const task_id_t orig,
const task_id_t dest,
Pistache::Http::ResponseWriter &response)
const task_id_t dest,
Pistache::Http::ResponseWriter &response)
:
itti_n11_msg(N11_SESSION_RELEASE_SM_CONTEXT_RESPONSE, orig, dest),
http_response(response.clone()),
......@@ -427,5 +455,30 @@ class itti_n11_release_sm_context_response : public itti_n11_msg {
};
//-----------------------------------------------------------------------------
class itti_n11_session_report_request : public itti_n11_msg {
public:
itti_n11_session_report_request(const task_id_t orig, const task_id_t dest)
:
itti_n11_msg(N11_SESSION_REPORT_RESPONSE, orig, dest),
res() {
}
itti_n11_session_report_request(const itti_n11_session_report_request &i)
:
itti_n11_msg(i) {
}
itti_n11_session_report_request(const itti_n11_session_report_request &i,
const task_id_t orig, const task_id_t dest)
:
itti_n11_msg(i, orig, dest),
res(i.res) {
}
const char* get_msg_name() {
return "N11_SESSION_REPORT_RESPONSE";
}
;
smf::pdu_session_report_response res;
};
#endif /* ITTI_MSG_N11_HPP_INCLUDED_ */
......@@ -705,4 +705,33 @@ class itti_n4_session_report_response : public itti_n4_msg {
pfcp::pfcp_session_report_response pfcp_ies;
};
//-----------------------------------------------------------------------------
class itti_n4_session_failure_indication : public itti_n4_msg {
public:
itti_n4_session_failure_indication(const task_id_t origin,
const task_id_t destination)
:
itti_n4_msg(N4_SESSION_REPORT_RESPONSE, origin, destination) {
}
itti_n4_session_failure_indication(const itti_n4_session_failure_indication &i)
:
itti_n4_msg(i) {
pfcp_ies = i.pfcp_ies;
}
itti_n4_session_failure_indication(const itti_n4_session_failure_indication &i,
const task_id_t orig, const task_id_t dest)
:
itti_n4_msg(i, orig, dest) {
pfcp_ies = i.pfcp_ies;
}
const char* get_msg_name() {
return typeid(itti_n4_session_failure_indication).name();
}
;
pfcp::pfcp_session_modification_request pfcp_ies;
};
#endif /* ITTI_MSG_N4_HPP_INCLUDED_ */
......@@ -28,7 +28,6 @@
typedef uint64_t supi64_t;
#define SUPI_64_FMT "%" SCNu64
//typedef imsi_t supi_t;
#define SUPI_DIGITS_MAX 15
......@@ -110,22 +109,23 @@ enum class http_response_codes_e {
//From 23.502
enum class session_management_procedures_type_e {
PDU_SESSION_ESTABLISHMENT_UE_REQUESTED = 0,
SERVICE_REQUEST_UE_TRIGGERED_STEP1 = 1,
SERVICE_REQUEST_UE_TRIGGERED_STEP2 = 2,
SERVICE_REQUEST_NETWORK_TRIGGERED = 3,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1 = 4,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2 = 5,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3 = 6,
PDU_SESSION_MODIFICATION_SMF_REQUESTED = 7,
PDU_SESSION_MODIFICATION_AN_REQUESTED = 8,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1 = 9,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2 = 10,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3 = 11,
PDU_SESSION_RELEASE_SMF_INITIATED = 12,
PDU_SESSION_RELEASE_AMF_INITIATED = 13,
PDU_SESSION_RELEASE_AN_INITIATED = 14,
PDU_SESSION_TEST = 15
PROCEDURE_TYPE_UNKNOWN = 0,
PDU_SESSION_ESTABLISHMENT_UE_REQUESTED = 1,
SERVICE_REQUEST_UE_TRIGGERED_STEP1 = 2,
SERVICE_REQUEST_UE_TRIGGERED_STEP2 = 3,
SERVICE_REQUEST_NETWORK_TRIGGERED = 4,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP1 = 5,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP2 = 6,
PDU_SESSION_MODIFICATION_UE_INITIATED_STEP3 = 7,
PDU_SESSION_MODIFICATION_SMF_REQUESTED = 8,
PDU_SESSION_MODIFICATION_AN_REQUESTED = 9,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP1 = 10,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP2 = 11,
PDU_SESSION_RELEASE_UE_REQUESTED_STEP3 = 12,
PDU_SESSION_RELEASE_SMF_INITIATED = 13,
PDU_SESSION_RELEASE_AMF_INITIATED = 14,
PDU_SESSION_RELEASE_AN_INITIATED = 15,
PDU_SESSION_TEST = 16
};
static const std::vector<std::string> session_management_procedures_type_e2str =
......@@ -191,6 +191,12 @@ static const std::vector<std::string> multipart_related_content_part_e2str = {
#define AMF_NUMBER_RETRIES 3
#define UDM_CURL_TIMEOUT_MS 100L
#define UDM_NUMBER_RETRIES 3
constexpr auto CURL_MIME_BOUNDARY = "----Boundary";
//for N1N2
#define BUF_LEN 512
//for PFCP
constexpr uint64_t SECONDS_SINCE_FIRST_EPOCH = 2208988800;
#endif
......@@ -36,6 +36,7 @@ set(CN_UTILS_SRC STATIC
${CMAKE_CURRENT_SOURCE_DIR}/pid_file.cpp
${CMAKE_CURRENT_SOURCE_DIR}/string.cpp
${CMAKE_CURRENT_SOURCE_DIR}/thread_sched.cpp
${CMAKE_CURRENT_SOURCE_DIR}/simple_parser.cpp
)
......
......@@ -363,62 +363,62 @@ std::string Utility::epc(const unsigned char *plmnid) {
return epc(mnc, mcc);
}
std::string Utility::apn_fqdn(const char *apnoi, const char *mnc,
std::string Utility::dnn_fqdn(const char *apnoi, const char *mnc,
const char *mcc) {
std::string s;
// '(.+)\.apn\.epc\.mnc(\d{3})\.mcc(\d{3})\.3gppnetworks\.org$'
s.append(apnoi).append(".apn.epc.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).
// '(.+)\.dnn\.epc\.mnc(\d{3})\.mcc(\d{3})\.3gppnetworks\.org$'
s.append(apnoi).append(".dnn.epc.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).
APPEND_3GPPNETWORK;
return s;
}
std::string Utility::apn_fqdn(const char *apnoi, const unsigned char *plmnid) {
std::string Utility::dnn_fqdn(const char *apnoi, const unsigned char *plmnid) {
PARSE_PLMNID(plmnid);
return apn_fqdn(apnoi, mnc, mcc);
return dnn_fqdn(apnoi, mnc, mcc);
}
std::string Utility::apn(const char *apnoi, const char *mnc, const char *mcc) {
std::string Utility::dnn(const char *apnoi, const char *mnc, const char *mcc) {
std::string s;
// '(.+)\.apn\.mnc(\d{3})\.mcc(\d{3})\.gprs$'}
s.append(apnoi).append(".apn.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).append(
// '(.+)\.dnn\.mnc(\d{3})\.mcc(\d{3})\.gprs$'}
s.append(apnoi).append(".dnn.").APPEND_MNC( mnc ).APPEND_MCC( mcc ).append(
"gprs");
return s;
}
std::string Utility::apn(const char *apnoi, const unsigned char *plmnid) {
std::string Utility::dnn(const char *apnoi, const unsigned char *plmnid) {
PARSE_PLMNID(plmnid);
return apn(apnoi, mnc, mcc);
return dnn(apnoi, mnc, mcc);
}
std::string Utility::apn_label(const std::string &apn) {
std::string apn_label = { };
std::string Utility::dnn_label(const std::string &dnn) {
std::string dnn_label = { };
bool to_count = true;
uint8_t counted = 0;
int index = 0;
apn_label.push_back('?');
dnn_label.push_back('?');
for (int i = 0; i < apn.length(); ++i) {
if (isalnum(apn[i]) || (apn[i] == '-')) {
apn_label.push_back(apn[i]);
for (int i = 0; i < dnn.length(); ++i) {
if (isalnum(dnn[i]) || (dnn[i] == '-')) {
dnn_label.push_back(dnn[i]);
counted++;
} else if (apn[i] == '.') {
apn_label.push_back('?');
} else if (dnn[i] == '.') {
dnn_label.push_back('?');
if (to_count) { // always true
apn_label[index] = counted;
dnn_label[index] = counted;
}
to_count = true;
counted = 0;
index = apn_label.length() - 1;
index = dnn_label.length() - 1;
}
}
if (to_count) {
apn_label[index] = counted;
dnn_label[index] = counted;
}
return apn_label;
return dnn_label;
}
......@@ -336,12 +336,12 @@ class Utility {
const unsigned char *plmnid);
static std::string epc(const char *mnc, const char *mcc);
static std::string epc(const unsigned char *plmnid);
static std::string apn_fqdn(const char *apnoi, const char *mnc,