* Copyright (c) 2025-2026 Huawei Device Co., Ltd.
* Licensed 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.
*/
#include "nrunsolicitedmsgparser.h"
#include "cellular_data_client.h"
#include "core_service_client.h"
#include "networkslicemanager.h"
#include "state_utils.h"
namespace OHOS {
namespace NetManagerStandard {
static constexpr int MODEM_ID = 0;
static constexpr uint8_t MSG_MANAGE_UE_POLICY_COMMAND = 1;
static constexpr uint8_t MSG_MANAGE_UE_POLICY_COMPLETE = 0;
static constexpr uint8_t MSG_MANAGE_UE_POLICY_COMMAND_REJECT = 1;
static constexpr uint8_t MSG_UE_STATE_INDICATION = 2;
static constexpr uint8_t SPACELENGTH = 4;
static constexpr uint8_t NSSAI_TYPE_DEFAULT_CONFIGURED_REJECT_CONFIGURED_ALLOWED_NSSAI = 3;
static constexpr uint8_t UE_POLICY_PART_TYPE_URSP = 1;
static std::string REPORTURSP_PATH = "/system/profile/reportUrsp.json";
static std::string DEFAULT_PLMN = "00101";
NrUnsolicitedMsgParser& NrUnsolicitedMsgParser::GetInstance()
{
static NrUnsolicitedMsgParser instance;
return instance;
}
NrUnsolicitedMsgParser::NrUnsolicitedMsgParser()
{
NETMGR_EXT_LOG_I("init NrUnsolicitedMsgParser start");
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("NrUnsolicitedMsgParser sUrspConfig_ = nullptr");
sUrspConfig_ = std::make_shared<UrspConfig>(UrspConfig::GetInstance());
}
GetSubscriberIdAndUrspFromFile();
NETMGR_EXT_LOG_I("init NrUnsolicitedMsgParser end");
}
void NrUnsolicitedMsgParser::GetSubscriberIdAndUrspFromFile()
{
NETMGR_EXT_LOG_I("nrunsolicited:Enter getSubscriberIdAndUrspFromFile");
if (mSubscriberId.empty()) {
NETMGR_EXT_LOG_E("imsi null");
return;
}
std::unordered_map<std::string, UePolicy> uePolicyMaptmp = ReadObjectFromJsonFile(REPORTURSP_PATH);
if (uePolicyMaptmp.empty()) {
NETMGR_EXT_LOG_I("nrunsolicited:read ue policy from file failed");
WriteObjectToJsonFile(REPORTURSP_PATH, uePolicyMap);
SendUePolicySectionIdentifier();
return;
}
uePolicyMap = uePolicyMaptmp;
if (uePolicyMap.empty()) {
return;
}
UpdateUrspRules();
}
void NrUnsolicitedMsgParser::HandleSimStateChanged()
{
NETMGR_EXT_LOG_E("enter handleSimStateChanged isAllowedNssaiSync = %{public}d", isAllowedNssaiSync);
SyncSubscriberId();
if (!isAllowedNssaiSync) {
GetNetworkSliceAllowedNssai();
}
GetNetworkSliceEhplmn();
}
void NrUnsolicitedMsgParser::SyncSubscriberId()
{
int32_t slotId = StateUtils::GetPrimarySlotId();
NETMGR_EXT_LOG_I("NrUnsolicitedMsgParser slotId = %{public}d", slotId);
std::u16string imsi;
Telephony::CoreServiceClient::GetInstance().GetIMSI(slotId, imsi);
if (imsi.empty()) {
NETMGR_EXT_LOG_E("syncSubscriberId fail, imsi null");
return;
}
std::string imsistr = Str16ToStr8(imsi);
std::string encryptImsi = GetSha256Str(imsistr);
if (mSubscriberId.empty()) {
mSubscriberId = encryptImsi;
return;
}
if (mSubscriberId == encryptImsi) {
return;
}
mSubscriberId = encryptImsi;
uePolicyMap = std::unordered_map<std::string, UePolicy>(NetworkSliceCommConfig::HASH_MAP_DEFAULT_CAPACITY);
WriteObjectToJsonFile(REPORTURSP_PATH, uePolicyMap);
SendUePolicySectionIdentifier();
UpdateUrspRules();
SendUrspUpdate();
auto networkSliceManager = DelayedSingleton<NetworkSliceManager>::GetInstance();
if (networkSliceManager != nullptr) {
networkSliceManager->onUrspAvailableStateChanged();
}
}
void NrUnsolicitedMsgParser::GetNetworkSliceAllowedNssai()
{
NETMGR_EXT_LOG_E("GetNetworkSliceAllowedNssai");
int32_t slotId = StateUtils::GetPrimarySlotId();
std::u16string operatorNumeric;
Telephony::CoreServiceClient::GetInstance().GetSimOperatorNumeric(slotId, operatorNumeric);
std::string plmn = Str16ToStr8(operatorNumeric);
if (plmn == "") {
NETMGR_EXT_LOG_E("GetPlmn fail");
return;
}
NETMGR_EXT_LOG_E("NrUnsolicitedMsgParser GetNetworkSliceAllowedNssai plmn = %{public}s", plmn.c_str());
std::vector<uint8_t> plmns = ConvertstringTouInt8Vector(plmn);
std::vector<uint8_t> buffer;
buffer.push_back(plmns.size());
for (size_t i = 0; i < plmns.size(); ++i) {
buffer.push_back(plmns[i]);
}
buffer.push_back(NSSAI_TYPE_DEFAULT_CONFIGURED_REJECT_CONFIGURED_ALLOWED_NSSAI);
Telephony::CellularDataClient::GetInstance().GetNetworkSliceAllowedNssai(MODEM_ID, buffer);
isAllowedNssaiSync = true;
}
void NrUnsolicitedMsgParser::GetNetworkSliceEhplmn()
{
NETMGR_EXT_LOG_I("GetNetworkSliceEhplmn");
Telephony::CellularDataClient::GetInstance().GetNetworkSliceEhplmn(MODEM_ID);
}
void NrUnsolicitedMsgParser::WriteObjectToJsonFile(const std::string& fileName,
std::unordered_map<std::string, UePolicy>& obj)
{
if (fileName.empty()) {
return;
}
NETMGR_EXT_LOG_I("WriteObjectToJsonFile:%{public}s", fileName.c_str());
nlohmann::json j = nlohmann::json::object();
for (const auto& pair : obj) {
std::string plmn = pair.first;
NETMGR_EXT_LOG_I("WriteObjectToJsonFile plmn = %{public}s", plmn.c_str());
UePolicy uePolicy = pair.second;
nlohmann::json uePolicyJson = uePolicy.to_json();
j[plmn] = uePolicyJson;
}
std::fstream f;
f.open(fileName, std::ios::out);
if (!f.is_open()) {
NETMGR_EXT_LOG_E("file not opened! ");
} else {
f << j.dump(SPACELENGTH);
f.close();
}
}
std::unordered_map<std::string, UePolicy> NrUnsolicitedMsgParser::ReadObjectFromJsonFile(const std::string& fileName)
{
std::ifstream file(fileName);
if (!file.is_open()) {
NETMGR_EXT_LOG_E("failed to open file ");
return {};
}
NETMGR_EXT_LOG_I("ReadObjectFromJsonFile");
nlohmann::json j;
file >> j;
if (j.empty()) {
return {};
}
std::unordered_map<std::string, UePolicy> uePolicies;
for (const auto& item : j.items()) {
const std::string& plmn = item.key();
const nlohmann::json& policyJson = item.value();
UePolicy uePolicy;
uePolicy.from_json(policyJson);
uePolicies[plmn] = uePolicy;
}
if (file.is_open()) {
file.close();
}
return uePolicies;
}
void NrUnsolicitedMsgParser::UpdateUrspRules()
{
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("sUrspConfig == null");
return;
}
NETMGR_EXT_LOG_I("UpdateUrspRules");
std::string plmn;
UePolicy uePolicy;
PolicyInstruction policyInstruction;
sUrspConfig_->ClearUrspRules();
for (const auto& entry : uePolicyMap) {
std::string plmn = entry.first;
const UePolicy& uePolicy = entry.second;
std::vector<UrspRule> urspRules;
for (const auto& instructionEntry : uePolicy.policyInstructionMap) {
PolicyInstruction policyInstruction = instructionEntry.second;
for (size_t i = 0; i < policyInstruction.urspRules.size(); ++i) {
urspRules.push_back(policyInstruction.urspRules[i]);
}
}
sUrspConfig_->setUrspRules(plmn, urspRules);
}
sUrspConfig_->DumpUePolicyMap();
sUrspConfig_->SaveTrafficDescriptorWhiteListToDb();
}
void NrUnsolicitedMsgParser::SendUrspUpdate()
{
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("sendUrspUpdate, mUrspConfig == null");
return;
}
std::string plmn = GetHplmn();
NETMGR_EXT_LOG_I("SendUrspUpdate GetHplmn = %{public}s", plmn.c_str());
SelectedRouteDescriptor routeRule = sUrspConfig_->GetMatchAllUrspRule(plmn);
std::map<std::string, std::string> data;
data["routeBitmap"] = std::to_string(routeRule.getRouteBitmap());
NETMGR_EXT_LOG_I("SendUrspUpdate routeBitmap = %{public}s", data["routeBitmap"].c_str());
if ((routeRule.getRouteBitmap() & 0x01) == 0x01) {
data["sscMode"] = std::to_string(routeRule.getSscMode());
if (routeRule.getPduSessionType() != -1) {
data["pduSessionType"] = std::to_string(routeRule.getPduSessionType());
}
data["sNssai"] = routeRule.getSnssai();
data["dnn"] = routeRule.getDnn();
data["urspPrecedence"] = std::to_string(routeRule.getUrspPrecedence());
}
std::shared_ptr<std::map<std::string, std::string>> msg =
std::make_shared<std::map<std::string, std::string>>(data);
Singleton<NetworkSliceMsgCenter>::GetInstance().Publish(EVENT_URSP_CHANGED, msg);
}
std::string NrUnsolicitedMsgParser::GetHplmn()
{
return (mEhplmns.size() > 0) ? mEhplmns[0] : DEFAULT_PLMN;
}
void NrUnsolicitedMsgParser::GetAllowedNssaiFromUnsolData(std::vector<uint8_t> buffer)
{
sAllowedNssaiConfig_->DecodeAllowedNssai(buffer);
}
void NrUnsolicitedMsgParser::GetEhplmnFromUnsolData(std::vector<uint8_t> buffer)
{
if (buffer.empty()) {
NETMGR_EXT_LOG_E("GetEhplmnFromUnsolData failed, invalid buffer");
return;
}
NETMGR_EXT_LOG_I("start GetEhplmnFromUnsolData");
int inputLen = (int)buffer.size();
mEhplmns.clear();
std::string ehplmn = "";
std::vector<std::string> values;
int i;
for (i = 0; i < inputLen; ++i) {
ehplmn += static_cast<char>(buffer[i]);
}
values = Split(ehplmn, ",");
for (i = 0; i < (int)values.size(); ++i) {
mEhplmns.push_back(values[i]);
}
for (i = 0; i < (int)mEhplmns.size(); ++i) {
NETMGR_EXT_LOG_I("mEhplmn[%{public}d] = %{public}s", i, mEhplmns[i].c_str());
}
}
void NrUnsolicitedMsgParser::GetUrspFromUnsolData(std::vector<uint8_t> buffer)
{
if (buffer.empty()) {
NETMGR_EXT_LOG_E("getUrspFromUnsolData failed, invalid buffer");
return;
}
if (buffer.size() < NetworkSliceCommConfig::LEN_THREE_BYTE) {
return;
}
int startIndex = 0;
const uint8_t pti = buffer[startIndex++];
const uint8_t segmentNum = buffer[startIndex++];
if (segmentNum < 1) {
return;
}
const uint8_t segmentIndex = buffer[startIndex++];
if (segmentNum == 1) {
DecodeUrspFromUnsolData(startIndex, buffer);
return;
}
if (mMultipleBufferMap.find(pti) == mMultipleBufferMap.end()) {
MultipleBuffer multipleBuffer;
multipleBuffer.segmentNum = segmentNum;
multipleBuffer.bufferSegmentMap[segmentIndex] = buffer;
multipleBuffer.totalBufferLen += (int(buffer.size()) - startIndex);
mMultipleBufferMap[pti] = multipleBuffer;
} else {
MultipleBuffer multipleBuffer = mMultipleBufferMap[pti];
if (segmentNum != multipleBuffer.segmentNum || segmentIndex > segmentNum || segmentIndex <= 0) {
NETMGR_EXT_LOG_E("segmentNum or segmentIndex invalid");
return;
}
if (multipleBuffer.bufferSegmentMap.find(segmentIndex) != multipleBuffer.bufferSegmentMap.end()) {
NETMGR_EXT_LOG_E("segmentIndex already exist");
return;
}
multipleBuffer.bufferSegmentMap[segmentIndex] = buffer;
multipleBuffer.totalBufferLen += (int(buffer.size()) - startIndex);
if (multipleBuffer.bufferSegmentMap.size() == segmentNum) {
std::vector<uint8_t> combinationBuffer(multipleBuffer.totalBufferLen);
for (int index = 1; index <= segmentNum; ++index) {
std::vector<uint8_t> tmpvec = multipleBuffer.bufferSegmentMap[static_cast<uint8_t>(index)];
combinationBuffer.insert(combinationBuffer.end(), tmpvec.begin(), tmpvec.end());
}
startIndex = 0;
DecodeUrspFromUnsolData(startIndex, combinationBuffer);
mMultipleBufferMap.erase(pti);
}
}
}
void NrUnsolicitedMsgParser::DecodeUrspFromUnsolData(int& startIndex, std::vector<uint8_t> buffer)
{
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("DecodeUrspFromUnsolData, sUrspConfig_ == nullptr");
return;
}
if (buffer.empty()) {
NETMGR_EXT_LOG_E("getursp failed, invalid buffer");
return;
}
NETMGR_EXT_LOG_I("start decode ursp, buffer.remaining() = [%{public}d]", (int)buffer.size());
int inputLen = (int(buffer.size()) - startIndex);
if (inputLen < NetworkSliceCommConfig::LEN_SHORT) {
NETMGR_EXT_LOG_E("inputLen < NetworkSliceCommConfig::LEN_SHORT");
return;
}
short version = GetShort(startIndex, buffer, true);
NETMGR_EXT_LOG_I("ursp version = [%{public}d]", version);
if (version == NetworkSliceCommConfig::URSP_VERSION_1510
|| version == NetworkSliceCommConfig::URSP_VERSION_1520) {
sUrspConfig_->SetUrspVersion(version);
} else {
NETMGR_EXT_LOG_E("version is invalid = %{public}d", version);
return;
}
inputLen -= NetworkSliceCommConfig::LEN_SHORT;
if (inputLen < NetworkSliceCommConfig::LEN_INT) {
NETMGR_EXT_LOG_E("inputLen < NetworkSliceCommConfig::LEN_INT");
return;
}
uint8_t pti = buffer[startIndex++];
inputLen -= NetworkSliceCommConfig::LEN_BYTE;
if (buffer[startIndex++] != MSG_MANAGE_UE_POLICY_COMMAND) {
NETMGR_EXT_LOG_E("buffer.get() != MSG_MANAGE_UE_POLICY_COMMAND");
return;
}
inputLen -= NetworkSliceCommConfig::LEN_BYTE;
std::unordered_map<std::string, UePolicy> decodeUePolicyMap;
if (!DecodePolicySectionList(inputLen, startIndex, buffer, decodeUePolicyMap)) {
return;
}
NETMGR_EXT_LOG_I("end decode ursp = [%{public}d]", pti);
HandleDecodeResult(pti, decodeUePolicyMap);
}
void NrUnsolicitedMsgParser::HandleDecodeResult(uint8_t pti,
std::unordered_map<std::string, UePolicy>& decodeUePolicyMap)
{
NETMGR_EXT_LOG_I("HandleDecodeResult");
UePolicyRejectMsg uePolicyRejectMsg;
if (!isUePolicyLegal(decodeUePolicyMap, uePolicyRejectMsg)) {
NETMGR_EXT_LOG_I("NrUnsolicitedMsgParser::ue policy illegal");
SndManageUePolicyCommandReject(pti, uePolicyRejectMsg);
return;
}
SndManageUePolicyComplete(pti);
AddNewUePolicy(decodeUePolicyMap);
SendUePolicySectionIdentifier();
SendImsRsdList();
WriteObjectToJsonFile(REPORTURSP_PATH, uePolicyMap);
UpdateUrspRules();
SendUrspUpdate();
DelayedSingleton<NetworkSliceManager>::GetInstance()->onUrspAvailableStateChanged();
}
void NrUnsolicitedMsgParser::SndManageUePolicyComplete(uint8_t pti)
{
NETMGR_EXT_LOG_I("SndManageUePolicyComplete, ModemID:%{public}d, MSGID:%{public}d",
MODEM_ID, MSG_MANAGE_UE_POLICY_COMPLETE);
std::vector<uint8_t> buffer;
buffer.push_back(pti);
buffer.push_back(MSG_MANAGE_UE_POLICY_COMPLETE);
Telephony::CellularDataClient::GetInstance().SendUrspDecodeResult(MODEM_ID, buffer);
}
void NrUnsolicitedMsgParser::SndManageUePolicyCommandReject(uint8_t pti,
UePolicyRejectMsg uePolicyRejectMsg)
{
NETMGR_EXT_LOG_I("SndManageUePolicyCommandReject");
std::vector<uint8_t> buffer;
int32_t startlen = 0;
buffer.push_back(pti);
startlen++;
buffer.push_back(MSG_MANAGE_UE_POLICY_COMMAND_REJECT);
startlen++;
PutShort(buffer, uePolicyRejectMsg.totalLen);
startlen += NetworkSliceCommConfig::LEN_SHORT;
for (int i = 0; i < (int)uePolicyRejectMsg.uePolicyRejects.size(); ++i) {
buffer.push_back(static_cast<uint8_t>(uePolicyRejectMsg.uePolicyRejects.size()));
startlen++;
for (int j = 0; j < PLMN_LEN; ++j) {
buffer.push_back(uePolicyRejectMsg.uePolicyRejects[i].plmn[j]);
startlen++;
}
std::vector<UePolicyResult> uePolicyResults = uePolicyRejectMsg.uePolicyRejects[i].uePolicyResult;
for (int j = 0; j < (int)uePolicyResults.size(); ++j) {
PutShort(buffer, uePolicyResults[j].upsc);
startlen += NetworkSliceCommConfig::LEN_SHORT;
PutShort(buffer, uePolicyResults[j].failedInstructionOrder);
startlen += NetworkSliceCommConfig::LEN_SHORT;
buffer.push_back(uePolicyResults[j].cause);
startlen++;
}
}
Telephony::CellularDataClient::GetInstance().SendUrspDecodeResult(MODEM_ID, buffer);
}
void NrUnsolicitedMsgParser::SendUePolicySectionIdentifier()
{
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("SendUePolicySectionIdentifier sUrspConfig_ == nullptr ");
return;
}
short upsiListLen = 0;
for (const auto& entry : uePolicyMap) {
const UePolicy& uePolicy = entry.second;
upsiListLen = (short)(upsiListLen + NetworkSliceCommConfig::LEN_SHORT + PLMN_LEN
+ NetworkSliceCommConfig::LEN_SHORT * uePolicy.policyInstructionMap.size());
}
uint16_t allocateLen = NetworkSliceCommConfig::LEN_BYTE + NetworkSliceCommConfig::LEN_BYTE
+ NetworkSliceCommConfig::LEN_SHORT + upsiListLen
+ NetworkSliceCommConfig::LEN_BYTE + NetworkSliceCommConfig::LEN_BYTE + NetworkSliceCommConfig::LEN_SHORT;
std::vector<uint8_t> buffer;
int32_t startlen = 0;
buffer.push_back(0);
startlen++;
buffer.push_back(MSG_UE_STATE_INDICATION);
startlen++;
PutShort(buffer, upsiListLen);
startlen += NetworkSliceCommConfig::LEN_SHORT;
for (const auto& entry : uePolicyMap) {
const UePolicy& uePolicy = entry.second;
uint8_t upsiSublistLen = (uint8_t)(PLMN_LEN
+ NetworkSliceCommConfig::LEN_SHORT * uePolicy.policyInstructionMap.size());
PutShort(buffer, upsiSublistLen);
startlen += NetworkSliceCommConfig::LEN_SHORT;
for (int i = 0; i < PLMN_LEN; ++i) {
buffer.push_back(uePolicy.plmn[i]);
startlen++;
}
for (const auto& instructionEntry : uePolicy.policyInstructionMap) {
PutShort(buffer, instructionEntry.first);
startlen += NetworkSliceCommConfig::LEN_SHORT;
}
}
buffer.push_back(1);
startlen++;
buffer.push_back(0);
startlen++;
PutShort(buffer, sUrspConfig_->GetSuccUrspVersion());
startlen += NetworkSliceCommConfig::LEN_SHORT;
Telephony::CellularDataClient::GetInstance().SendUePolicySectionIdentifier(MODEM_ID, buffer);
}
void NrUnsolicitedMsgParser::SendImsRsdList()
{
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("SendImsRsdList sUrspConfig_ == nullptr ");
return;
}
if (!sUrspConfig_->mImsRsdsMap.empty()) {
NETMGR_EXT_LOG_I("GetImsRsdList mImsRsdsMap is not empty");
}
std::vector<uint8_t> rsdBytes = sUrspConfig_->GetImsRsdList();
if (!rsdBytes.empty()) {
NETMGR_EXT_LOG_I("NrUnsolicitedMsgParser::SendImsRsdList");
Telephony::CellularDataClient::GetInstance().SendImsRsdList(MODEM_ID, rsdBytes);
}
}
void NrUnsolicitedMsgParser::AddNewUePolicy(std::unordered_map<std::string, UePolicy>& decodeUePolicyMap)
{
NETMGR_EXT_LOG_I("AddNewUePolicy");
* Upon receipt of the MANAGE UE POLICY COMMAND message,
* for each instruction included in the UE policy section management list IE,
* the UE shall:
* a)store the received UE policy section of the instruction,
* if the UE has no stored UE policy section associated with the same UPSI
* as the UPSI associated with the instruction;
* b)replace the stored UE policy section with the received UE policy section of the instruction,
* if the UE has a stored UE policy section associated with the same UPSI as the UPSI associated
* with the instruction; or
* c)delete the stored UE policy section, if the UE has a stored UE policy section associated with
* the same UPSI as the UPSI associated with the instruction and the UE policy section contents of
* the instruction is empty.
*/
for (const auto& entry : decodeUePolicyMap) {
std::string plmn = entry.first;
NETMGR_EXT_LOG_I("AddNewUePolicy plmn = %{public}s", plmn.c_str());
UePolicy uePolicy = entry.second;
if (uePolicyMap.find(plmn) == uePolicyMap.end()) {
uePolicyMap[plmn] = uePolicy;
continue;
}
std::unordered_map<short, PolicyInstruction>& oldUePolicy = uePolicyMap[plmn].policyInstructionMap;
for (const auto& instructionEntry : uePolicy.policyInstructionMap) {
short upsc = instructionEntry.first;
if (oldUePolicy.find(upsc) == oldUePolicy.end()) {
oldUePolicy[upsc] = instructionEntry.second;
continue;
}
if (!instructionEntry.second.hasUrspType) {
oldUePolicy.erase(upsc);
continue;
}
oldUePolicy.erase(upsc);
oldUePolicy[upsc] = instructionEntry.second;
}
if (oldUePolicy.empty()) {
uePolicyMap.erase(plmn);
}
}
}
bool NrUnsolicitedMsgParser::isUePolicyLegal(std::unordered_map<std::string, UePolicy>& decodeUePolicyMap,
UePolicyRejectMsg& uePolicyRejectMsg)
{
for (const auto& entry : decodeUePolicyMap) {
const std::string& plmn = entry.first;
if (isPlmnInHplmn(plmn)) {
continue;
}
const UePolicy& uePolicy = entry.second;
UePolicyReject uePolicyReject;
std::copy(uePolicy.plmn.begin(), uePolicy.plmn.begin() + PLMN_LEN, std::back_inserter(uePolicyReject.plmn));
for (const auto& instructionEntry : uePolicy.instructionOrderMap) {
UePolicyResult uePolicyResult;
uePolicyResult.upsc = instructionEntry.second;
uePolicyResult.failedInstructionOrder = instructionEntry.first;
uePolicyResult.cause = CAUSE_PROTOCOL_ERROR;
uePolicyReject.uePolicyResult.push_back(uePolicyResult);
uePolicyRejectMsg.totalLen += RESULT_LEN;
}
uePolicyRejectMsg.uePolicyRejects.push_back(uePolicyReject);
uePolicyRejectMsg.totalLen += NetworkSliceCommConfig::LEN_BYTE + PLMN_LEN;
}
if (!uePolicyRejectMsg.uePolicyRejects.empty()) {
return false;
}
return true;
}
bool NrUnsolicitedMsgParser::isPlmnInHplmn(std::string plmn)
{
if (mEhplmns.empty()) {
mEhplmns.push_back(DEFAULT_PLMN);
}
if (mEhplmns.empty()) {
NETMGR_EXT_LOG_I("mEhplmns == null");
return false;
}
NETMGR_EXT_LOG_I("mEhplmns.size() = %{public}d", (int)mEhplmns.size());
if (mEhplmns.size() > 0 && plmn == mEhplmns[0]) {
return true;
}
return false;
}
bool NrUnsolicitedMsgParser::DecodePolicySectionList(int inputLen, int& startIndex, std::vector<uint8_t> buffer,
std::unordered_map<std::string, UePolicy>& decodeUePolicyMap)
{
NETMGR_EXT_LOG_I("DecodePolicySectionList");
int len = inputLen;
short subLen_short = GetShort(startIndex, buffer);
len -= NetworkSliceCommConfig::LEN_SHORT;
if (ConvertUnsignedShort2Int(subLen_short) != len) {
NETMGR_EXT_LOG_E("buffer.getShort() != len, %{public}d != %{public}d",
ConvertUnsignedShort2Int(subLen_short), len);
return false;
}
while (len > 0) {
if ((int(buffer.size()) - startIndex) < NetworkSliceCommConfig::LEN_SHORT) {
NETMGR_EXT_LOG_E("buffer.remaining() is not enough when get sublist length");
return false;
}
subLen_short = GetShort(startIndex, buffer);
int subLen = ConvertUnsignedShort2Int(subLen_short);
if (((int(buffer.size()) - startIndex) < subLen) ||
(len < (NetworkSliceCommConfig::LEN_SHORT + subLen))) {
NETMGR_EXT_LOG_I("size = %{public}d, subLen = %{public}d, Len = %{public}d",
(int(buffer.size()) - startIndex), subLen, len);
NETMGR_EXT_LOG_E("buffer.remaining() or len is not enough when decode policy section list");
return false;
}
len = len - NetworkSliceCommConfig::LEN_SHORT - subLen;
if (!DecodePolicySection(subLen, startIndex, buffer, decodeUePolicyMap)) {
NETMGR_EXT_LOG_E("decodePolicySection(subLen, buffer) is false");
return false;
}
}
return true;
}
bool NrUnsolicitedMsgParser::DecodePolicySection(int inputLen, int& startIndex, std::vector<uint8_t> buffer,
std::unordered_map<std::string, UePolicy>& decodeUePolicyMap)
{
std::vector<uint8_t> plmns;
int len = inputLen;
if (len < NetworkSliceCommConfig::LEN_THREE_BYTE) {
NETMGR_EXT_LOG_E("len < NetworkSliceCommConfig::LEN_THREE_BYTE");
return false;
}
plmns.push_back(buffer[startIndex]);
plmns.push_back(buffer[startIndex + ARRAY_INDEX_1]);
plmns.push_back(buffer[startIndex + ARRAY_INDEX_2]);
startIndex += NetworkSliceCommConfig::LEN_THREE_BYTE;
len -= NetworkSliceCommConfig::LEN_THREE_BYTE;
std::string plmn = PlmnToString(plmns);
NETMGR_EXT_LOG_I("DecodePolicySection::PLMN = %{public}s", plmn.c_str());
if (plmn == "") {
return false;
}
UePolicy uePolicy;
if (decodeUePolicyMap.find(plmn) != decodeUePolicyMap.end()) {
uePolicy = decodeUePolicyMap[plmn];
} else {
uePolicy.plmn = plmns;
}
short instructionOrder = 0;
while (len > 0) {
if ((int(buffer.size()) - startIndex) < NetworkSliceCommConfig::LEN_SHORT) {
NETMGR_EXT_LOG_E("buffer.remaining() < NetworkSliceCommConfig::LEN_SHORT");
return false;
}
short subLen_short = GetShort(startIndex, buffer);
int subLen = ConvertUnsignedShort2Int(subLen_short);
if ((int(buffer.size()) - startIndex) < subLen || (len < (NetworkSliceCommConfig::LEN_SHORT + subLen))) {
NETMGR_EXT_LOG_E("(buffer.remaining() < subLen) || (len < (NetworkSliceCommConfig::LEN_SHORT + subLen))");
return false;
}
len = len - NetworkSliceCommConfig::LEN_SHORT - subLen;
instructionOrder++;
if (!DecodeInstruction(subLen, startIndex, buffer, uePolicy, instructionOrder)) {
NETMGR_EXT_LOG_E("decodeInstruction(subLen, buffer, uePolicy) is false");
return false;
}
}
if (decodeUePolicyMap.find(plmn) == decodeUePolicyMap.end()) {
decodeUePolicyMap[plmn] = uePolicy;
}
if (uePolicy.policyInstructionMap.empty()) {
decodeUePolicyMap.erase(plmn);
}
return true;
}
bool NrUnsolicitedMsgParser::DecodeInstruction(int inputLen, int& startIndex, std::vector<uint8_t> buffer,
UePolicy& uePolicy, short instructionOrder)
{
NETMGR_EXT_LOG_I("DecodeInstruction");
PolicyInstruction policyInstruction;
int len = inputLen;
if (len < NetworkSliceCommConfig::LEN_SHORT) {
NETMGR_EXT_LOG_E("len < NetworkSliceCommConfig::LEN_SHORT");
return false;
}
short upsc = GetShort(startIndex, buffer);
len -= NetworkSliceCommConfig::LEN_SHORT;
NETMGR_EXT_LOG_E("upsc = %{public}d, len = %{public}d", upsc, len);
if (uePolicy.policyInstructionMap.find(upsc) != uePolicy.policyInstructionMap.end()) {
policyInstruction = uePolicy.policyInstructionMap[upsc];
policyInstruction.hasUrspType = false;
policyInstruction.urspRules.clear();
} else {
PolicyInstruction newPolicyInstruction;
newPolicyInstruction.hasUrspType = false;
uePolicy.policyInstructionMap[upsc] = newPolicyInstruction;
}
while (len > 0) {
if ((int(buffer.size()) - startIndex) < NetworkSliceCommConfig::LEN_SHORT) {
NETMGR_EXT_LOG_E("buffer.size() < NetworkSliceCommConfig::LEN_SHORT");
return false;
}
short subLen_short = GetShort(startIndex, buffer);
int subLen = ConvertUnsignedShort2Int(subLen_short);
if (((int(buffer.size()) - startIndex) < subLen) || (len < (NetworkSliceCommConfig::LEN_SHORT + subLen))) {
NETMGR_EXT_LOG_I("size = %{public}d, subLen = %{public}d, Len = %{public}d",
(int(buffer.size()) - startIndex), subLen, len);
NETMGR_EXT_LOG_E("(buffer.size() < subLen) || (len < (NetworkSliceCommConfig::LEN_SHORT + subLen))");
return false;
}
len = len - NetworkSliceCommConfig::LEN_SHORT - subLen;
if (!DecodeUePolicyPart(subLen, startIndex, buffer, policyInstruction)) {
NETMGR_EXT_LOG_E("decodeUePolicyPart(subLen, buffer, policyInstruction.urspRules) is false");
return false;
}
}
uePolicy.policyInstructionMap[upsc] = policyInstruction;
if (policyInstruction.hasUrspType) {
uePolicy.instructionOrderMap[instructionOrder] = upsc;
}
return true;
}
bool NrUnsolicitedMsgParser::DecodeUePolicyPart(int inputLen, int& startIndex,
std::vector<uint8_t> buffer, PolicyInstruction& policyInstruction)
{
NETMGR_EXT_LOG_I("DecodeUePolicyPart");
uint8_t uePolicyType;
std::vector<uint8_t> dsts;
int len = inputLen;
if (len < NetworkSliceCommConfig::LEN_BYTE) {
NETMGR_EXT_LOG_E("len < NetworkSliceCommConfig::LEN_BYTE");
return false;
}
uePolicyType = buffer[startIndex] & 0x0F;
startIndex += NetworkSliceCommConfig::LEN_BYTE;
len -= NetworkSliceCommConfig::LEN_BYTE;
if (uePolicyType != UE_POLICY_PART_TYPE_URSP) {
NETMGR_EXT_LOG_I("uePolicyType != UE_POLICY_PART_TYPE_URSP, %{public}d != %{public}d",
uePolicyType, UE_POLICY_PART_TYPE_URSP);
dsts = std::vector<uint8_t>(len);
for (int i = 0; i < len; ++i) {
dsts[i] = buffer[startIndex];
startIndex++;
}
return true;
}
policyInstruction.hasUrspType = true;
if (sUrspConfig_ == nullptr) {
NETMGR_EXT_LOG_E("mUrspConfig == null");
return false;
}
if (!sUrspConfig_->DecodeUrspRules(len, startIndex, buffer, policyInstruction.urspRules)) {
NETMGR_EXT_LOG_E("mUrspConfig->decodeUrspRules(subLen, buffer, urspRules) is false");
return false;
}
return true;
}
std::string NrUnsolicitedMsgParser::PlmnToString(const std::vector<uint8_t>& plmns)
{
std::string plmn;
std::string firstByte = ByteToHexStr(plmns[ARRAY_INDEX_0] & CONVERT_INT_AND_BYTE);
plmn += std::to_string(std::stoi(firstByte) % RADIX);
plmn += std::to_string(std::stoi(firstByte) / RADIX);
std::string secondByte = ByteToHexStr(plmns[ARRAY_INDEX_1] & CONVERT_INT_AND_BYTE);
bool isThreeDigitsForMnc = true;
if (secondByte.find("f") == 0) {
secondByte = "0" + secondByte.substr(1);
isThreeDigitsForMnc = false;
}
plmn += std::to_string(std::stoi(secondByte) % RADIX);
std::string thirdByte = ByteToHexStr(plmns[ARRAY_INDEX_2] & CONVERT_INT_AND_BYTE);
plmn += std::to_string(std::stoi(thirdByte) % RADIX);
plmn += std::to_string(std::stoi(thirdByte) / RADIX);
if (isThreeDigitsForMnc) {
plmn += std::to_string(std::stoi(secondByte) / RADIX);
}
NETMGR_EXT_LOG_I("NrUnsolicitedMsgParser::PlmnToString is %{public}s", plmn.c_str());
return plmn;
}
}
}