You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
7.0 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CoreAgent.ProtocolClient.Context;
using CoreAgent.ProtocolClient.Enums;
using CoreAgent.ProtocolClient.Models;
namespace CoreAgent.ProtocolClient.BuildProtocolParser
{
public class NASProtocolParser : IGeneralProtocolParser
{
private readonly ProtocolClientContext context;
public NASProtocolParser(ProtocolClientContext context)
{
this.context = context;
}
public void GeneralParse(ref BuildProtocolLog log)
{
var nasInfoMatch = ProtocolLogPatterns.RegExpInfo1.Match(log.Message);
if (nasInfoMatch.Success)
{
var info = context.UeIdentifier.StringToId(nasInfoMatch.Groups[1].Value);
if (info == -1)
return;
log.Info = info;
log.Message = nasInfoMatch.Groups[2].Value;
ProcessNasLog(log);
}
}
/// <summary>
/// 处理NAS日志
/// </summary>
private void ProcessNasLog(BuildProtocolLog log)
{
if (log?.Data == null || !log.UeId.HasValue)
return;
var messageType = log.Message.ToLowerInvariant();
switch (messageType)
{
case "attach accept":
BuildPLMNFromComponents(log);
ProcessTmsiFromLog(log, ProtocolLogPatterns.RegExpNAS_TMSI, TmsiType.Accept);
break;
case "registration accept":
BuildPLMNFromComponents(log);
ProcessTmsiFromLog(log, ProtocolLogPatterns.RegExpNAS_5GTMSI, TmsiType.Accept);
break;
case "attach request":
ProcessImsiFromLog(log);
ProcessTmsiFromLog(log, ProtocolLogPatterns.RegExpNAS_TMSI, TmsiType.Request);
break;
case "service request":
ProcessTmsiFromLog(log, ProtocolLogPatterns.RegExpNAS_5GTMSI, TmsiType.ServiceRequest);
break;
case "identity response":
ProcessImsiFromLog(log);
break;
case "registration request":
ProcessImsiFromLog(log);
//BuildPLMNFromComponents(log);
ProcessTmsiFromLog(log, ProtocolLogPatterns.RegExpNAS_5GTMSI, TmsiType.Request);
break;
}
}
/// <summary>
/// 从日志中处理TMSI信息
/// </summary>
private void ProcessTmsiFromLog(BuildProtocolLog log, Regex tmsiPattern, TmsiType type)
{
var tmsiMatch = tmsiPattern.FindData(log.Data);
if (tmsiMatch?.Success != true || !log.UeId.HasValue)
return;
var tmsiValue = tmsiMatch.Groups[1].Value;
var ueId = log.UeId.Value;
switch (type)
{
case TmsiType.Accept:
context.UeIdentifier.SetTmsi(ueId, tmsiValue);
break;
case TmsiType.Request:
context.UeIdentifier.SetRequestTmsi(ueId, tmsiValue);
break;
case TmsiType.ServiceRequest:
context.UeIdentifier.SetSrTmsi(ueId, tmsiValue);
break;
}
}
/// <summary>
/// 从日志中处理IMSI信息
/// </summary>
private void ProcessImsiFromLog(BuildProtocolLog log)
{
var imsi = ExtractImsiFromLog(log);
if (!string.IsNullOrWhiteSpace(imsi) && log.UeId.HasValue)
{
context.UeIdentifier.SetImsi(log.UeId.Value, imsi);
}
}
/// <summary>
/// 从日志中提取IMSI信息
/// </summary>
private string ExtractImsiFromLog(BuildProtocolLog log)
{
// 优先尝试直接获取IMSI
var imsi = ExtractValueFromLog(log.Data, ProtocolLogPatterns.RegIMSIPattern);
if (!string.IsNullOrWhiteSpace(imsi))
return imsi;
// 如果直接获取失败,尝试从MSIN、MNC、MCC构建
return BuildIMSIFromComponents(log);
}
/// <summary>
/// 从日志数据中提取指定正则表达式的第一个匹配值
/// </summary>
private string ExtractValueFromLog(List<string> data, Regex pattern)
{
return data?.Select(line => pattern.Match(line))
.Where(match => match.Success)
.Select(match => match.Groups[1].Value)
.FirstOrDefault() ?? string.Empty;
}
/// <summary>
/// 根据 MSIN、MNC 和 MCC 构建 IMSI(International Mobile Subscriber Identity)
/// </summary>
/// <param name="log">协议日志</param>
/// <returns>完整的 IMSI 字符串,如果组件不完整则返回空字符串</returns>
private string BuildIMSIFromComponents(BuildProtocolLog log)
{
var components = ExtractPLMNComponents(log);
// 检查所有组件是否都存在
if (string.IsNullOrWhiteSpace(components.Msin) ||
string.IsNullOrWhiteSpace(components.Mnc) ||
string.IsNullOrWhiteSpace(components.Mcc))
return string.Empty;
context.UeIdentifier.SetPlmn(log!.UeId.Value, components.Mcc + components.Mnc);
return components.Mcc + components.Mnc + components.Msin;
}
/// <summary>
/// 根据 MCC 和 MNC 构建 PLMN(Public Land Mobile Network)
/// </summary>
/// <param name="log">协议日志</param>
/// <returns>完整的 PLMN 字符串,如果组件不完整则返回空字符串</returns>
private string BuildPLMNFromComponents(BuildProtocolLog log)
{
var components = ExtractPLMNComponents(log);
// 检查所有组件是否都存在
if (string.IsNullOrWhiteSpace(components.Mnc) || string.IsNullOrWhiteSpace(components.Mcc))
return string.Empty;
context.UeIdentifier.SetPlmn(log!.UeId.Value, components.Mcc + components.Mnc);
return components.Mcc + components.Mnc;
}
/// <summary>
/// 从日志中提取PLMN相关组件(MCC、MNC、MSIN)
/// </summary>
/// <param name="log">协议日志</param>
/// <returns>包含MCC、MNC、MSIN的组件结构</returns>
private (string Mcc, string Mnc, string Msin) ExtractPLMNComponents(BuildProtocolLog log)
{
var mcc = ExtractValueFromLog(log.Data, ProtocolLogPatterns.RegMccPattern);
var mnc = ExtractValueFromLog(log.Data, ProtocolLogPatterns.RegMncPattern);
var msin = ExtractValueFromLog(log.Data, ProtocolLogPatterns.RegMSINPattern);
return (mcc, mnc, msin);
}
}
}