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
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);
|
|
}
|
|
}
|
|
}
|
|
|