using System.Collections.Immutable;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
namespace LTEMvcApp.Models;
///
/// LTE客户端类 - 对应JavaScript中的lte.client对象
///
public class LTEClient
{
#region 常量定义
///
/// HFN回绕阈值
///
private const int HFN_WRAP_THRESHOLD = 512;
///
/// 最大日志数量
///
private const int LOGS_MAX = 2000000;
#endregion
#region 正则表达式
///
/// PHY层日志正则表达式
///
private static readonly Regex RegExpPhy = new(@"^([a-f0-9\-]+)\s+([a-f0-9\-]+)\s+([\d\.\-]+) (\w+): (.+)", RegexOptions.Compiled);
///
/// 信息1正则表达式
///
private static readonly Regex RegExpInfo1 = new(@"^([\w\-]+): (.+)", RegexOptions.Compiled);
///
/// 信息2正则表达式
///
private static readonly Regex RegExpInfo2 = new(@"^([\w]+) (.+)", RegexOptions.Compiled);
///
/// IP日志正则表达式
///
private static readonly Regex RegExpIP = new(@"^(len=\d+)\s+(\S+)\s+(.*)", RegexOptions.Compiled);
///
/// IPsec日志正则表达式
///
private static readonly Regex RegExpIPsec = new(@"^len=(\d+)\s+(.*)", RegexOptions.Compiled);
///
/// SDU长度正则表达式
///
private static readonly Regex RegExpSDULen = new(@"SDU_len=(\d+)", RegexOptions.Compiled);
///
/// SIP日志正则表达式
///
private static readonly Regex RegExpSIP = new(@"^([:\.\[\]\da-f]+)\s+(\S+) (.+)", RegexOptions.Compiled);
///
/// 媒体请求正则表达式
///
private static readonly Regex RegExpMediaReq = new(@"^(\S+) (.+)", RegexOptions.Compiled);
///
/// 信号记录正则表达式
///
private static readonly Regex RegExpSignalRecord = new(@"Link:\s([\w\d]+)@(\d+)", RegexOptions.Compiled);
///
/// 小区ID正则表达式
///
private static readonly Regex RegExpCellID = new(@"^([a-f0-9\-]+) (.+)", RegexOptions.Compiled);
///
/// RRC UE ID正则表达式
///
private static readonly Regex RegExpRRC_UE_ID = new(@"Changing UE_ID to 0x(\d+)", RegexOptions.Compiled);
///
/// RRC TMSI正则表达式
///
private static readonly Regex RegExpRRC_TMSI = new(@"(5G|m)-TMSI '([\dA-F]+)'H", RegexOptions.Compiled);
///
/// RRC新ID正则表达式
///
private static readonly Regex RegExpRRC_NEW_ID = new(@"newUE-Identity (['\dA-FH]+)", RegexOptions.Compiled);
///
/// RRC CRNTI正则表达式
///
private static readonly Regex RegExpRRC_CRNTI = new(@"c-RNTI '([\dA-F]+)'H", RegexOptions.Compiled);
///
/// NAS TMSI正则表达式
///
private static readonly Regex RegExpNAS_TMSI = new(@"m-TMSI = 0x([\da-f]+)", RegexOptions.Compiled);
///
/// NAS 5G TMSI正则表达式
///
private static readonly Regex RegExpNAS_5GTMSI = new(@"5G-TMSI = 0x([\da-f]+)", RegexOptions.Compiled);
///
/// RRC频段组合正则表达式
///
private static readonly Regex RegExpRRC_BC = new(@"(EUTRA|MRDC|NR|NRDC) band combinations", RegexOptions.Compiled);
///
/// PDCCH正则表达式
///
private static readonly Regex RegExpPDCCH = new(@"^\s*(.+)=(\d+)$", RegexOptions.Compiled);
///
/// S1/NGAP正则表达式
///
private static readonly Regex RegExpS1NGAP = new(@"^([\da-f\-]+)\s+([\da-f\-]+) (([^\s]+) .+)", RegexOptions.Compiled);
///
/// 十六进制转储正则表达式
///
private static readonly Regex RegExpHexDump = new(@"^[\da-f]+:(\s+[\da-f]{2}){1,16}\s+.{1,16}$", RegexOptions.Compiled);
#endregion
#region 基础属性
///
/// 客户端ID
///
public int ClientId { get; set; }
///
/// 客户端名称
///
public string Name { get; set; } = string.Empty;
///
/// 客户端配置
///
public ClientConfig Config { get; set; } = new();
///
/// 客户端状态
///
public ClientState State { get; set; } = ClientState.Stop;
///
/// 版本信息
///
public string? Version { get; set; }
///
/// 许可证信息
///
public string? License { get; set; }
///
/// 模型类型
///
public string? Model { get; set; }
///
/// 是否有信号记录
///
public bool HasSignalRecord { get; set; }
#endregion
#region 日志相关属性
///
/// 日志列表
///
public List Logs { get; set; } = new();
///
/// 日志数量
///
public int LogCount => Logs.Count;
///
/// 是否已过滤
///
public bool Filtered { get; set; }
///
/// 重置标志
///
public bool ResetFlag { get; set; }
#endregion
#region 解析器状态
///
/// 最后HARQ信息
///
public Dictionary> LastHarq { get; set; } = new();
///
/// 最后NB HARQ信息
///
public Dictionary>> LastNbHarq { get; set; } = new();
///
/// 帧信息
///
public FrameInfo Frame { get; set; } = new();
///
/// TMSI到UE ID的映射
///
public Dictionary TmsiToUeId { get; set; } = new();
///
/// RNTI到UE ID的映射
///
public Dictionary RntiToUeId { get; set; } = new();
///
/// UE列表
///
public Dictionary UeList { get; set; } = new();
///
/// 最后时间戳
///
public long LastTimestamp { get; set; }
///
/// 时间戳偏移
///
public long TimestampOffset { get; set; }
///
/// 最后小区
///
public int? LastCell { get; set; }
#endregion
#region 功能标志
///
/// 是否有小区信息
///
public bool HasCell { get; set; }
///
/// 是否有物理层信息
///
public bool HasPhy { get; set; }
///
/// 是否有数据
///
public bool HasData { get; set; }
///
/// 是否有RNTI
///
public bool HasRnti { get; set; }
///
/// 是否有资源块
///
public bool HasRb { get; set; }
#endregion
#region 参数和组件
///
/// 参数信息
///
public Dictionary Parameters { get; set; } = new();
///
/// 组件列表
///
public Dictionary Components { get; set; } = new();
#endregion
#region 依赖注入
///
/// 日志管理器
///
private readonly LogsManager _lteLogs;
///
/// 获取日志管理器实例
///
public LogsManager LogsManager => _lteLogs;
#endregion
#region 构造函数
public LTEClient(ClientConfig config, LogsManager logsManager)
{
Config = config;
Name = config.Name;
ClientId = GenerateClientId();
_lteLogs = logsManager;
ResetParserState();
}
///
/// 使用名称创建客户端
///
/// 客户端名称
/// 日志管理器
public LTEClient(string name, LogsManager logsManager)
{
Config = new ClientConfig { Name = name, Enabled = true };
Name = name;
ClientId = GenerateClientId();
_lteLogs = logsManager;
ResetParserState();
}
#endregion
#region 客户端控制方法
///
/// 启动客户端
///
public void Start()
{
SetState(ClientState.Start);
}
///
/// 停止客户端
///
public void Stop()
{
SetState(ClientState.Stop);
}
///
/// 销毁客户端
///
public void Destroy()
{
SetState(ClientState.Destroy);
}
#endregion
#region 日志管理方法
///
/// 重置日志
///
public void ResetLogs()
{
if (LogCount > 0)
{
ResetFlag = true;
Logs.Clear();
ResetParserState();
HasCell = false;
HasPhy = false;
HasData = false;
HasRnti = false;
HasRb = false;
HasSignalRecord = false;
}
}
///
/// 添加日志
///
public void AddLog(LTELog log)
{
// 检查时间戳回绕
var timestamp = log.Timestamp + TimestampOffset;
if (timestamp < LastTimestamp - 100)
{
Console.WriteLine($"Log wrap by {LastTimestamp - timestamp}");
timestamp += 86400000; // 24小时
TimestampOffset += 86400000;
}
LastTimestamp = log.Timestamp = timestamp;
log.Client = this;
log.Id = GenerateLogId();
}
#endregion
#region 工具方法
///
/// 设置头信息
///
public void SetHeaders(string[] headers)
{
// 实现头信息设置逻辑
}
///
/// 初始化模型猜测
///
public void LogModelGuessInit()
{
if (string.IsNullOrEmpty(Config.Model))
{
// 尝试所有模型
var modelList = new List { "RUE", "UE", "PROBE", "ENB", "N3IWF", "MBMSGW", "MME", "IMS", "LICENSE", "MONITOR" };
if (!TryModelHint(modelList))
{
SetModel("MME"); // 默认模型
}
// 初始化模型猜测字典
_modelGuess = new Dictionary();
var layerConfig = GetLayerConfig();
foreach (var layer in layerConfig.Keys)
{
_modelGuess[layer] = false;
}
}
}
///
/// 模型猜测字典
///
private Dictionary? _modelGuess;
///
/// 获取层配置
///
/// 层配置字典
private Dictionary GetLayerConfig()
{
// 这里应该从 LogsManager 获取层配置
// 暂时返回一个基本的层配置
return new Dictionary
{
{ "PHY", new { Color = "#606070" } },
{ "MAC", new { Color = "#10A0FF" } },
{ "RLC", new { Color = "#FFFF80" } },
{ "PDCP", new { Color = "#B0D0B0" } },
{ "RRC", new { Color = "#00FF60" } },
{ "NAS", new { Color = "#90FFC0" } },
{ "GTPU", new { Color = "#FF80FF" } },
{ "GTPC", new { Color = "#FFC0FF" } },
{ "IP", new { Color = "#E0E0E0" } },
{ "S1AP", new { Color = "#80FF00" } },
{ "NGAP", new { Color = "#5DD122" } },
{ "X2AP", new { Color = "#FF8000" } },
{ "XnAP", new { Color = "#FFB020" } },
{ "M2AP", new { Color = "#7F675B" } },
{ "IMS", new { Color = "#C0FF80" } },
{ "CX", new { Color = "#F49542" } },
{ "RX", new { Color = "#D4A190" } },
{ "COM", new { Color = "#C000FF" } },
{ "SIP", new { Color = "#C080FF" } },
{ "MEDIA", new { Color = "#800040" } },
{ "RTP", new { Color = "#FF00C0" } },
{ "PROD", new { Color = "#80C0FF" } },
{ "S6", new { Color = "#F44B42" } },
{ "S13", new { Color = "#D6F953" } },
{ "SGsAP", new { Color = "#FF7DB8" } },
{ "SBcAP", new { Color = "#8FA00F" } },
{ "N8", new { Color = "#106020" } },
{ "N12", new { Color = "#602020" } },
{ "N13", new { Color = "#202060" } },
{ "N17", new { Color = "#D6F953" } },
{ "N50", new { Color = "#8FA00F" } },
{ "MMS", new { Color = "#B4D98F" } },
{ "HTTP2", new { Color = "#644824" } },
{ "LCSAP", new { Color = "#cfd50d" } },
{ "LPPa", new { Color = "#0dcfd5" } },
{ "NL1", new { Color = "#d040cf" } },
{ "NRPPa", new { Color = "#0dd5cf" } },
{ "IKEV2", new { Color = "#C0B732" } },
{ "SWU", new { Color = "#101080" } },
{ "NWU", new { Color = "#2080B8" } },
{ "IPSEC", new { Color = "#F04010" } },
{ "N3IWF", new { Color = "#C080C0" } },
{ "TRX", new { Color = "#42C0a0" } },
{ "MON", new { Color = "#C0C080" } },
{ "EVENT", new { Color = "#80C0FF" } },
{ "ALARM", new { Color = "#FF8040" } },
{ "LIC", new { Color = "#ff80c0" } },
{ "OTS", new { Color = "#8080FF" } },
{ "ERROR", new { Color = "#ff0000" } }
};
}
///
/// 模型猜测
///
/// 日志列表
public void LogModelGuess(List> logs)
{
var modelGuess = _modelGuess;
if (modelGuess == null)
return;
// 标记所有出现的层
foreach (var log in logs)
{
if (log.TryGetValue("layer", out var layer) && layer is string layerStr)
{
modelGuess[layerStr] = true;
}
}
// 尝试根据层配置确定模型
var modelList = new List { "RUE", "UE", "PROBE", "ENB", "N3IWF", "MBMSGW", "MME", "IMS", "LICENSE", "MONITOR" };
var availableModels = new List(modelList);
// 根据层配置过滤模型
foreach (var layer in modelGuess.Keys)
{
if (!modelGuess[layer]) continue;
var layerConfig = GetLayerConfig();
if (layerConfig.TryGetValue(layer, out var config))
{
// 这里应该检查层的方向配置来过滤模型
// 暂时简化处理
var layerDir = GetLayerDirection(layer);
if (layerDir != null)
{
// 移除不支持的模型
availableModels.RemoveAll(model => !layerDir.ContainsKey(model));
}
}
// 如果只剩下一个模型,直接设置
if (availableModels.Count <= 1)
break;
}
// 如果找到了合适的模型,设置它
if (availableModels.Count > 0 && availableModels.Count < modelList.Count)
{
SetModel(availableModels[0]);
_modelGuess = null; // 清除猜测字典
}
}
///
/// 获取层方向配置
///
/// 层名称
/// 方向配置字典
private Dictionary? GetLayerDirection(string layer)
{
// 这里应该从 LogsManager 获取层的方向配置
// 暂时返回一个基本的配置
return layer switch
{
"PHY" => new Dictionary { { "UE", 2 }, { "PROBE", 3 }, { "ENB", 1 } },
"MAC" => new Dictionary { { "UE", 2 }, { "PROBE", 3 }, { "ENB", 1 } },
"RLC" => new Dictionary { { "UE", 2 }, { "PROBE", 3 }, { "ENB", 1 } },
"PDCP" => new Dictionary { { "UE", 2 }, { "PROBE", 3 }, { "ENB", 1 } },
"RRC" => new Dictionary { { "UE", 2 }, { "PROBE", 3 }, { "ENB", 1 } },
"NAS" => new Dictionary { { "UE", 2 }, { "PROBE", 3 }, { "ENB", 3 }, { "N3IWF", 3 }, { "MME", 1 } },
"GTPU" => new Dictionary { { "ENB", 2 }, { "N3IWF", 2 }, { "MME", 1 }, { "MBMSGW", 1 }, { "UE", 1 }, { "RUE", 2 } },
"GTPC" => new Dictionary { { "MME", 2 } },
"IP" => new Dictionary { { "RUE", 2 }, { "UE", 2 }, { "N3IWF", 3 }, { "PROBE", 3 }, { "MME", 3 } },
"S1AP" => new Dictionary { { "ENB", 2 }, { "MME", 1 } },
"NGAP" => new Dictionary { { "ENB", 2 }, { "MME", 1 }, { "N3IWF", 2 } },
"X2AP" => new Dictionary { { "ENB", 2 } },
"XnAP" => new Dictionary { { "ENB", 2 } },
"M2AP" => new Dictionary { { "ENB", 2 }, { "MBMSGW", 1 } },
"IMS" => new Dictionary { { "MME", 2 }, { "IMS", 1 } },
"CX" => new Dictionary { { "MME", 2 }, { "IMS", 1 } },
"RX" => new Dictionary { { "MME", 2 }, { "IMS", 1 } },
"COM" => new Dictionary { { "*", 2 } },
"SIP" => new Dictionary { { "IMS", 1 } },
"MEDIA" => new Dictionary { { "IMS", 1 } },
"RTP" => new Dictionary { { "IMS", 1 } },
"PROD" => new Dictionary { },
"S6" => new Dictionary { { "MME", 2 } },
"S13" => new Dictionary { { "MME", 2 } },
"SGsAP" => new Dictionary { { "MME", 2 } },
"SBcAP" => new Dictionary { { "MME", 2 } },
"N8" => new Dictionary { { "MME", 2 } },
"N12" => new Dictionary { { "MME", 2 } },
"N13" => new Dictionary { { "MME", 2 } },
"N17" => new Dictionary { { "MME", 2 } },
"N50" => new Dictionary { { "MME", 2 } },
"MMS" => new Dictionary { { "MME", 2 } },
"HTTP2" => new Dictionary { { "MME", 2 } },
"LCSAP" => new Dictionary { { "MME", 2 } },
"LPPa" => new Dictionary { { "ENB", 2 }, { "MME", 3 } },
"NL1" => new Dictionary { { "MME", 2 } },
"NRPPa" => new Dictionary { { "ENB", 2 }, { "MME", 3 } },
"IKEV2" => new Dictionary { { "UE", 2 }, { "MME", 1 }, { "N3IWF", 1 } },
"SWU" => new Dictionary { { "UE", 2 }, { "MME", 1 } },
"NWU" => new Dictionary { { "UE", 2 }, { "MME", 1 } },
"IPSEC" => new Dictionary { { "UE", 2 }, { "IMS", 1 }, { "N3IWF", 1 }, { "MME", 1 } },
"N3IWF" => new Dictionary { { "UE", 2 }, { "N3IWF", 1 } },
"TRX" => new Dictionary { { "UE", 2 }, { "ENB", 1 } },
"MON" => new Dictionary { },
"EVENT" => new Dictionary { },
"ALARM" => new Dictionary { },
"LIC" => new Dictionary { { "LICENSE", 1 } },
"OTS" => new Dictionary { },
"ERROR" => new Dictionary { },
_ => null
};
}
///
/// 方向转换
///
public int DirConvert(LTELog log)
{
// 实现方向转换逻辑
return 0;
}
///
/// 字符串转ID - 委托给LogsManager
///
public int StringToId(string str)
{
return _lteLogs.String2Id(str);
}
///
/// ID转字符串 - 委托给LogsManager
///
public string IdToString(int id)
{
return _lteLogs.Id2String(id);
}
#endregion
#region 日志解析方法
///
/// 解析日志列表 - 对应JavaScript的_logListParse方法
///
/// 日志列表
/// 是否为WebSocket消息
public void ParseLogList(List logs, bool isWebSocket = false)
{
var length = logs.Count;
for (int i = 0; i < length; i++)
{
var log = logs[i];
log.Message = log.Message + "";
AddLog(log);
// 解析消息
switch (log.Layer)
{
case "PHY":
if (!ParsePhyLog(log, log.Message, isWebSocket)) continue;
ProcessPhyLog(log);
break;
case "RRC":
ParseCellId(log, isWebSocket);
var rrcUeIdMatch = RegExpRRC_UE_ID.Match(log.Message);
if (rrcUeIdMatch.Success)
{
SetSameUe(log, int.Parse(rrcUeIdMatch.Groups[1].Value, System.Globalization.NumberStyles.HexNumber));
continue;
}
var infoMatch = RegExpInfo1.Match(log.Message);
if (infoMatch.Success)
{
if (!SetLogInfo(log, infoMatch.Groups[1].Value)) continue;
log.Message = infoMatch.Groups[2].Value;
ProcessRrcLog(log);
}
var bcMatch = RegExpRRC_BC.Match(log.Message);
if (bcMatch.Success)
{
try
{
var data = log.GetDataString();
var jsonData = JsonConvert.DeserializeObject