Merge branch 'main' into multi-tenant

This commit is contained in:
2024-09-30 19:25:19 +08:00
44 changed files with 9391 additions and 805 deletions

View File

@@ -1,15 +1,17 @@
# 版本发布日志
## 2.2409.1-20240925
## 2.2409.4-20240927
多租户修改如下:
- 新增 跟踪任务pcap文件获取接口
- 优化 socket消息接收跟踪任务推送ws
- 修复 历史告警同步判断存在错误
- 优化 redis数据scan数调整1000
- 修复 SMF在线订阅用户列表接口地址错误
- 修复 多语言SMSC原因0表示未知
- 新增 网元版本列表主动检查服务状态的版本
- 更新 UDM用户数据表字段
- ims在线用户显示异常
- admin和tenant角色只能单选
合并主线版本修改如下:
--## 2.2409.3-20240920
## 2.2409.3-20240920
- 修复 字典多语言序号重复问题
- 更新 UDM用户数据表SMSC参数配置属性字典数据和跟踪相关表

View File

@@ -135,7 +135,8 @@ omc:
# TLS Skip verify: true/false
# email/sms
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
# dataCoding: 0:UCS2, 1:ASCII, 2:LATIN1
# dataCoding: 0:GSM7BIT, 1:ASCII, 2:BINARY8BIT1, 3:LATIN1,
# 4:BINARY8BIT2, 6:CYRILLIC, 7:HEBREW, 8:UCS2
alarm:
alarmEmailForward:
enable: true

View File

@@ -69,7 +69,7 @@ omc:
access: "rw"
filter: ""
display: "Mobile List"
comment: ""
comment: "Multiple mobile separated by commas"
- name: "smscAddr"
type: "string"
value: ""
@@ -100,9 +100,9 @@ omc:
comment: ""
- name: "dataCoding"
type: "enum"
value: "ASCII"
value: "GSM7BIT"
access: "rw"
filter: '{"0":"UCS2","1":"ASCII","2":"LATIN1"}'
filter: '{"0":"GSM7BIT","1":"ASCII","2":"BINARY8BIT1","3":"LATIN1","4":"BINARY8BIT2","6":"CYRILLIC","7":"HEBREW","8":"UCS2"}'
display: "Data Coding"
comment: "Short message coding type"
- name: "serviceNumber"
@@ -111,4 +111,4 @@ omc:
access: "rw"
filter: "3~20"
display: "Service Number"
comment: "It is the source address and length is between 3 and 20"
comment: "It is the source address, the length is between 3 and 20"

View File

@@ -112,7 +112,7 @@ INSERT INTO `ne_config` VALUES (82, 'CBC', 'mmeProfile', 'MME Profile', 'array',
-- OMC parameter config
INSERT INTO `ne_config` VALUES (83, 'OMC', 'alarmEmailForward', 'Alarm Email Forward Interface', 'list', '[{\"access\":\"rw\",\"comment\":\"Is it enabled forward alarm with Email interface\",\"display\":\"Enable\",\"filter\":\"true;false\",\"name\":\"enable\",\"type\":\"bool\",\"value\":\"true\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"Email List\",\"filter\":\"\",\"name\":\"emailList\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"Email SMTP server\",\"display\":\"SMTP Server\",\"filter\":\"\",\"name\":\"smtp\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"Port\",\"filter\":\"0~65535\",\"name\":\"port\",\"type\":\"int\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"User\",\"filter\":\"\",\"name\":\"user\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"Password\",\"filter\":\"\",\"name\":\"password\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"If skip TLS verify (true/false)\",\"display\":\"TLS Skip Verify\",\"filter\":\"true;false\",\"name\":\"tlsSkipVerify\",\"type\":\"bool\",\"value\":\"true\"}]', 3, '', 1725505025649);
INSERT INTO `ne_config` VALUES (84, 'OMC', 'alarmSMSForward', 'Alarm SMS Forward Interface', 'list', '[{\"access\":\"rw\",\"comment\":\"Is it enabled forward alarm with SMS interface\",\"display\":\"Enable\",\"filter\":\"true;false\",\"name\":\"enable\",\"type\":\"bool\",\"value\":\"true\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"Mobile List\",\"filter\":\"\",\"name\":\"mobileList\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"The SMSC SMPP Address\",\"display\":\"SMSC Address\",\"filter\":\"\",\"name\":\"smscAddr\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"System ID\",\"filter\":\"\",\"name\":\"systemID\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"Password\",\"filter\":\"\",\"name\":\"password\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"System Type\",\"filter\":\"\",\"name\":\"systemType\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"Short message coding type\",\"display\":\"Data Coding\",\"filter\":\"{\\\"0\\\":\\\"UCS2\\\",\\\"1\\\":\\\"ASCII\\\",\\\"2\\\":\\\"LATIN1\\\"}\",\"name\":\"dataCoding\",\"type\":\"enum\",\"value\":\"ASCII\"},{\"access\":\"rw\",\"comment\":\"It is the source address and length between 3 and 20\",\"display\":\"Service Number\",\"filter\":\"3~20\",\"name\":\"serviceNumber\",\"type\":\"string\",\"value\":\"OMC\"}]', 4, '', 1726799142528);
INSERT INTO `ne_config` VALUES (84, 'OMC', 'alarmSMSForward', 'Alarm SMS Forward Interface', 'list', '[{\"access\":\"rw\",\"comment\":\"Is it enabled forward alarm with SMS interface\",\"display\":\"Enable\",\"filter\":\"true;false\",\"name\":\"enable\",\"type\":\"bool\",\"value\":\"true\"},{\"access\":\"rw\",\"comment\":\"Multiple mobile separated by commas\",\"display\":\"Mobile List\",\"filter\":\"\",\"name\":\"mobileList\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"The SMSC SMPP Address\",\"display\":\"SMSC Address\",\"filter\":\"\",\"name\":\"smscAddr\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"System ID\",\"filter\":\"\",\"name\":\"systemID\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"Password\",\"filter\":\"\",\"name\":\"password\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"\",\"display\":\"System Type\",\"filter\":\"\",\"name\":\"systemType\",\"type\":\"string\",\"value\":\"\"},{\"access\":\"rw\",\"comment\":\"Short message coding type\",\"display\":\"Data Coding\",\"filter\":\"{\\\"0\\\":\\\"GSM7BIT\\\",\\\"1\\\":\\\"ASCII\\\",\\\"2\\\":\\\"BINARY8BIT1\\\",\\\"3\\\":\\\"LATIN1\\\",\\\"4\\\":\\\"BINARY8BIT2\\\",\\\"6\\\":\\\"CYRILLIC\\\",\\\"7\\\":\\\"HEBREW\\\",\\\"8\\\":\\\"UCS2\\\"}\",\"name\":\"dataCoding\",\"type\":\"enum\",\"value\":\"GSM7BIT\"},{\"access\":\"rw\",\"comment\":\"It is the source address, the length is between 3 and 20\",\"display\":\"Service Number\",\"filter\":\"3~20\",\"name\":\"serviceNumber\",\"type\":\"string\",\"value\":\"OMC\"}]', 4, '', 1727664057261);
-- 更新 SMSC 配置 20240920
INSERT INTO `ne_config` VALUES (90, 'SMSC', 'system', 'System', 'list', '[{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"CDR Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"cdrFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"SM Validity\",\"filter\":\"0-2147483647\",\"name\":\"smValidity\",\"type\":\"int\",\"value\":\"259200\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"Log Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"logFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"Enable or disable resend pending SMS to unattainable local users.\",\"display\":\"Local Polling Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"localPollingFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"Enable or disable resend pending SMS to unattainable outbound roaming users.\",\"display\":\"Local Roaming Out Polling Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"localRoamingOutPollingFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"Enable or disable resend pending SMS to unattainable inbound roaming users.\",\"display\":\"Visitor Roaming In Polling Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"visitorRoamingInPollingFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"Enable or disable resend pending SMS to other unattainable users.\",\"display\":\"Other Polling Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"otherPollingFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"Define the maximum port number that the queue of pending SMS may grow to.\",\"display\":\"Polling Number\",\"filter\":\"0-64\",\"name\":\"pollingNumber\",\"type\":\"int\",\"value\":\"64\"},{\"access\":\"read-write\",\"comment\":\"Specify the priority parameter of SM_RP_PRI. true = High; false = Low.\",\"display\":\"Priority Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"priorityFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"Enable or disable TP-Reply-Path parameter in the SMS-DELIVER data unit.\",\"display\":\"TP Reply Path Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"tpReplyPathFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"SMSC Domain\",\"filter\":\"0~16\",\"name\":\"smscDomain\",\"type\":\"string\",\"value\":\"0.0.0.0\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"CSFB VoLTE Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"csfbVolteFlag\",\"type\":\"bool\",\"value\":\"1\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"Camel Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"camelFlag\",\"type\":\"bool\",\"value\":\"0\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"SCF Address\",\"filter\":\"0~16\",\"name\":\"scfAddress\",\"type\":\"string\",\"value\":\"0.0.0.0\"},{\"access\":\"read-write\",\"comment\":\"If add plus then set false\",\"display\":\"MT Id Format Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"mtIdFormatFlag\",\"type\":\"bool\",\"value\":\"0\"},{\"access\":\"read-write\",\"comment\":\"enable mcast sms\",\"display\":\"Mcast Flag\",\"filter\":\"{\\\"0\\\":\\\"false\\\",\\\"1\\\":\\\"true\\\"}\",\"name\":\"mcastFlag\",\"type\":\"bool\",\"value\":\"0\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"Log Level\",\"filter\":\"{\\\"0\\\":\\\"none\\\",\\\"1\\\":\\\"error\\\",\\\"2\\\":\\\"debug\\\"}\",\"name\":\"logLevel\",\"type\":\"enum\",\"value\":\"0\"},{\"access\":\"read-write\",\"comment\":\"The MB sizeof log file\",\"display\":\"Log Size\",\"filter\":\"1-1000\",\"name\":\"logSize\",\"type\":\"int\",\"value\":\"200\"},{\"access\":\"read-write\",\"comment\":\"The number of log file\",\"display\":\"Log Number\",\"filter\":\"1-20\",\"name\":\"logNum\",\"type\":\"int\",\"value\":\"10\"},{\"access\":\"read-write\",\"comment\":\"\",\"display\":\"Log Directory\",\"filter\":\"0~128\",\"name\":\"logDir\",\"type\":\"string\",\"value\":\"/var/log/\"}]', 1, '', 1726802301029);

View File

@@ -78,8 +78,8 @@ INSERT INTO `sys_dict_data` VALUES (1070, 1070, 'menu.ueUser.onlineIMS', 'IMS在
INSERT INTO `sys_dict_data` VALUES (1071, 1071, 'menu.ueUser.onlineUE', 'UE在线信息', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1072, 1072, 'menu.ueUser.base5G', '基站信息', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1073, 1073, 'menu.trace', '跟踪', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1074, 1074, 'menu.trace.task', '跟踪任务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.analysis', '信令分析', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1074, 1074, 'menu.trace.task', '网元跟踪任务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.analysis', '网元跟踪数据', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1076, 1076, 'menu.trace.pcap', '信令抓包', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1077, 1077, 'menu.fault', '监控', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1078, 1078, 'menu.config.backupManageRemark', '备份管理菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -254,9 +254,9 @@ INSERT INTO `sys_dict_data` VALUES (1520, 1520, 'dictType.sys_yes_no_remark', '
INSERT INTO `sys_dict_data` VALUES (1521, 1521, 'dictType.sys_oper_type_remark', '操作类型列表', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1522, 1522, 'dictType.sys_common_status_remark', '登录状态列表', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1523, 1523, 'dictType.trace_type_remark', '跟踪类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- INSERT INTO `sys_dict_data` VALUES (1524, 1524, 'dictType.operation_log_type_remark', '操作日志类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1525, 1525, 'dictType.alarm_status_remark', '告警日志状态类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- INSERT INTO `sys_dict_data` VALUES (1526, 1526, 'dictType.security_log_type_remark', '安全日志类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1524, 1524, 'dictType.alarm_status_remark', '告警日志状态类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1525, 1525, 'menu.trace.tshark', '信令分析', 'i18n_zh', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (1526, 1526, 'menu.trace.wireshark', '信令跟踪', 'i18n_zh', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (1527, 1527, 'dictType.ne_version_status_remark', '网元软件版本状态', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1528, 1528, 'dictType.i18n_en_remark', 'Internationalization - English', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (1529, 1529, 'dictType.i18n_zh_remark', 'Internationalization - Chinese', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -656,7 +656,7 @@ INSERT INTO `sys_dict_data` VALUES (2145, 2145, 'menu.system.user.editPost', '
INSERT INTO `sys_dict_data` VALUES (2146, 2146, 'menu.dashboard.smscCDR', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1717051745866, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2147, 2147, 'log.operate.title.smscCDR', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2148, 2148, 'menu.trace.pcapFile', '信令抓包文件', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
-- INSERT INTO `sys_dict_data` VALUES (2149, 2149, 'dictData.udm_sub_cn_type.2', '4G', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2149, 2149, 'menu.trace.taskAnalyze', '跟踪数据分析', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
-- INSERT INTO `sys_dict_data` VALUES (2150, 2150, 'dictData.udm_sub_cn_type.3', '5G&4G', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2151, 2151, 'menu.system.setting.doc', '系统使用文档', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2152, 2152, 'menu.system.setting.official', '官网链接', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
@@ -673,9 +673,9 @@ INSERT INTO `sys_dict_data` VALUES (2162, 2162, 'table.cdr_event_smf', '数据
INSERT INTO `sys_dict_data` VALUES (2163, 2163, 'table.cdr_event_smsc', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2164, 2164, 'menu.log.exportFile', '导出文件管理', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2165, 2165, 'menu.perf.kpiCReport', '自定义指标数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2166, 2166, 'menu.trace.taskHLR', '跟踪任务 HLR', 'i18n_zh', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2166, 2166, 'menu.trace.taskHLR', 'HLR 跟踪任务', 'i18n_zh', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2167, 2167, 'dictType.cdr_cause_code', 'CDR 响应原因代码类别类型', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2168, 2168, 'dictData.cdr_cause_code.0', '其他', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2168, 2168, 'dictData.cdr_cause_code.0', '未知错误', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2169, 2169, 'dictData.cdr_cause_code.8', '运营者要求禁止', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2170, 2170, 'dictData.cdr_cause_code.10', '呼叫禁止', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (2171, 2171, 'dictData.cdr_cause_code.21', '短信传输拒绝', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');

View File

@@ -78,8 +78,8 @@ INSERT INTO `sys_dict_data` VALUES (3070, 3070, 'menu.ueUser.onlineIMS', 'IMS On
INSERT INTO `sys_dict_data` VALUES (3071, 3071, 'menu.ueUser.onlineUE', 'UE Online Information', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3072, 3072, 'menu.ueUser.base5G', 'Radio Information', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3073, 3073, 'menu.trace', 'Trace', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3074, 3074, 'menu.trace.task', 'Trace Tasks', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, '');
INSERT INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.analysis', 'Signaling Analysis', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, '');
INSERT INTO `sys_dict_data` VALUES (3074, 3074, 'menu.trace.task', 'NE Trace Task', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, '');
INSERT INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.analysis', 'NE Trace Task Data', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, '');
INSERT INTO `sys_dict_data` VALUES (3076, 3076, 'menu.trace.pcap', 'Signaling Capture', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3077, 3077, 'menu.fault', 'Monitor', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3078, 3078, 'menu.config.backupManageRemark', 'Backup Management Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -254,9 +254,9 @@ INSERT INTO `sys_dict_data` VALUES (3520, 3520, 'dictType.sys_yes_no_remark', 'S
INSERT INTO `sys_dict_data` VALUES (3521, 3521, 'dictType.sys_oper_type_remark', 'Operation type list', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3522, 3522, 'dictType.sys_common_status_remark', 'Login Status List', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3523, 3523, 'dictType.trace_type_remark', 'Trace Types', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- INSERT INTO `sys_dict_data` VALUES (3524, 3524, 'dictType.operation_log_type_remark', 'Operation log type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3525, 3525, 'dictType.alarm_status_remark', 'Alarm Log Status Type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- INSERT INTO `sys_dict_data` VALUES (3526, 3526, 'dictType.security_log_type_remark', 'Security Log Type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3524, 3524, 'dictType.alarm_status_remark', 'Alarm Log Status Type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3525, 3525, 'menu.trace.tshark', 'Signaling Analysis', 'i18n_en', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (3526, 3526, 'menu.trace.wireshark', 'Signaling Trace', 'i18n_en', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (3527, 3527, 'dictType.ne_version_status_remark', 'Network element software version status', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3528, 3528, 'dictType.i18n_en_remark', 'Internationalization - English', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
INSERT INTO `sys_dict_data` VALUES (3529, 3529, 'dictType.i18n_en_remark', 'Internationalization - Chinese', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -656,7 +656,7 @@ INSERT INTO `sys_dict_data` VALUES (4145, 4145, 'menu.system.user.editPost', 'Mo
INSERT INTO `sys_dict_data` VALUES (4146, 4146, 'menu.dashboard.smscCDR', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4147, 4147, 'log.operate.title.smscCDR', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4148, 4148, 'menu.trace.pcapFile', 'Signaling Capture File', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, '');
-- INSERT INTO `sys_dict_data` VALUES (4149, 4149, 'dictData.udm_sub_cn_type.2', '4G', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4149, 4149, 'menu.trace.taskAnalyze', 'Tracking Data Analysis', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, '');
-- INSERT INTO `sys_dict_data` VALUES (4150, 4150, 'dictData.udm_sub_cn_type.3', '5G&4G', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4151, 4151, 'menu.system.setting.doc', 'System User Documentation', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4152, 4152, 'menu.system.setting.official', 'Official Website', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, '');
@@ -673,9 +673,9 @@ INSERT INTO `sys_dict_data` VALUES (4162, 4162, 'table.cdr_event_smf', 'Data CDR
INSERT INTO `sys_dict_data` VALUES (4163, 4163, 'table.cdr_event_smsc', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4164, 4164, 'menu.log.exportFile', 'Exported File Management', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4165, 4165, 'menu.perf.kpiCReport', 'Custom Indicator Data', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4166, 4166, 'menu.trace.taskHLR', 'Tracking Tasks HLR', 'i18n_en', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4166, 4166, 'menu.trace.taskHLR', 'HLR Trace Task', 'i18n_en', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4167, 4167, 'dictType.cdr_cause_code', 'CDR Response Reason Code Category Type', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4168, 4168, 'dictData.cdr_cause_code.0', 'Other', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4168, 4168, 'dictData.cdr_cause_code.0', 'Unknown Error', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4169, 4169, 'dictData.cdr_cause_code.8', 'OPERATOR_DETERMINED_BARRING', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4170, 4170, 'dictData.cdr_cause_code.10', 'CALL_BARRED', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
INSERT INTO `sys_dict_data` VALUES (4171, 4171, 'dictData.cdr_cause_code.21', 'SM Trans Reject', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');

View File

@@ -130,8 +130,8 @@ INSERT INTO `sys_menu` VALUES (2081, 'menu.ueUser.onlineUE', 5, 6, 'ue', 'neUser
INSERT INTO `sys_menu` VALUES (2082, 'menu.ueUser.base5G', 5, 7, 'base5G', 'neUser/base5G/index', '1', '0', 'M', '1', '1', 'neUser:base5G:index', 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.base5GRemark');
INSERT INTO `sys_menu` VALUES (2083, 'menu.trace', 2087, 30, 'traceManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.traceRemark');
INSERT INTO `sys_menu` VALUES (2084, 'menu.trace.task', 2083, 1, 'task', 'traceManage/task/index', '1', '0', 'M', '0', '1', 'traceManage:task:index', 'icon-chexiao', 'supervisor', 1700000000000, 'admin', 1713176976458, 'menu.trace.taskRemark');
INSERT INTO `sys_menu` VALUES (2085, 'menu.trace.analysis', 2083, 2, 'analysis', 'traceManage/analysis/index', '1', '0', 'M', '0', '1', 'traceManage:analysis:index', 'icon-gongnengjieshao', 'supervisor', 1700000000000, 'admin', 1713176987835, 'menu.trace.analysisRemark');
INSERT INTO `sys_menu` VALUES (2086, 'menu.trace.pcap', 2083, 3, 'pcap', 'traceManage/pcap/index', '1', '1', 'M', '1', '1', 'traceManage:pcap:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.trace.pcapRemark');
INSERT INTO `sys_menu` VALUES (2085, 'menu.trace.analysis', 2083, 4, 'analysis', 'traceManage/analysis/index', '1', '0', 'M', '0', '1', 'traceManage:analysis:index', 'icon-gongnengjieshao', 'supervisor', 1700000000000, 'admin', 1713176987835, 'menu.trace.analysisRemark');
INSERT INTO `sys_menu` VALUES (2086, 'menu.trace.pcap', 2083, 11, 'pcap', 'traceManage/pcap/index', '1', '1', 'M', '1', '1', 'traceManage:pcap:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.trace.pcapRemark');
INSERT INTO `sys_menu` VALUES (2087, 'menu.fault', 0, 2, 'faultManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-jinggao', 'supervisor', 1700000000000, NULL, 0, 'menu.faultRemark');
INSERT INTO `sys_menu` VALUES (2088, 'menu.fault.active', 2129, 1, 'active-alarm', 'faultManage/active-alarm/index', '1', '1', 'M', '1', '1', 'faultManage:active-alarm:index', 'icon-wenjian', 'supervisor', 1700000000000, NULL, 0, 'menu.fault.activemRemark');
INSERT INTO `sys_menu` VALUES (2089, 'menu.log', 0, 9, 'logManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-fuzhidaima', 'supervisor', 1700000000000, NULL, 0, 'menu.logRemark');
@@ -196,10 +196,13 @@ INSERT INTO `sys_menu` VALUES (2154, 'menu.ne.neConfigBackup', 4, 29, 'neConfigB
INSERT INTO `sys_menu` VALUES (2155, 'menu.common.delete', 2154, 1, '#', '', '1', '1', 'B', '1', '1', 'ne:neConfigBackup:remove', '#', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_menu` VALUES (2156, 'menu.common.edit', 2154, 2, '#', '', '1', '1', 'B', '1', '1', 'ne:neConfigBackup:edit', '#', 'supervisor', 1721902269805, '', 0, '');
INSERT INTO `sys_menu` VALUES (2157, 'menu.dashboard.smscCDR', 2140, 9, 'smscCDR', 'dashboard/smscCDR/index', '1', '0', 'M', '1', '1', 'dashboard:cdr:index', 'icon-paixu', 'supervisor', 1723107637982, 'supervisor', 1723107637982, '');
INSERT INTO `sys_menu` VALUES (2158, 'menu.trace.pcapFile', 2083, 4, 'pcap/inline/file', 'traceManage/pcap/file', '1', '1', 'M', '0', '1', 'traceManage:pcap:index', '#', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2158, 'menu.trace.pcapFile', 2083, 12, 'pcap/inline/file', 'traceManage/pcap/file', '1', '1', 'M', '0', '1', 'traceManage:pcap:index', '#', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2159, 'menu.log.exportFile', 2089, 100, 'exportFile', 'logManage/exportFile/index', '1', '1', 'M', '1', '1', 'logManage:exportFile:index', 'icon-wenjian', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2160, 'menu.perf.kpiCReport', 2099, 100, 'kpiCReport', 'perfManage/kpiCReport/index', '1', '1', 'M', '1', '1', 'perfManage:kpiCReport:index', 'icon-tubiaoku', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2161, 'menu.trace.taskHLR', 2083, 10, 'taskHLR', 'traceManage/task-hlr/index', '1', '0', 'M', '1', '1', 'traceManage:taskHLR:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2161, 'menu.trace.taskHLR', 2083, 6, 'taskHLR', 'traceManage/task-hlr/index', '1', '0', 'M', '1', '1', 'traceManage:taskHLR:index', 'icon-chexiao', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/inline/analyze', 'traceManage/task/analyze', '1', '0', 'M', '0', '1', 'traceManage:taskAnalyze:index', '#', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2163, 'menu.trace.tshark', 2083, 14, 'tshark', 'traceManage/tshark/index', '1', '0', 'M', '1', '1', 'traceManage:tshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, '');
INSERT INTO `sys_menu` VALUES (2164, 'menu.trace.wireshark', 2083, 16, 'wireshark', 'traceManage/wireshark/index', '1', '0', 'M', '1', '1', 'traceManage:wireshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, '');
-- tenant management for admin user
INSERT INTO `sys_menu` VALUES (10000, 'menu.security.tenant', 2113, 5, 'tenant', 'system/tenant/index', '1', '1', 'M', '1', '1', 'system:tenant:list', 'icon-yuzhanghao1', 'supervisor', 1700000000000, NULL, 0, 'menu.security.tenantRemark');

View File

@@ -245,6 +245,13 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2148);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2149);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2152);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2153);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2154);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2155);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2156);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2157);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2160);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 1);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 5);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 112);
@@ -295,6 +302,9 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2148);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2149);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2152);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2153);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2160);
INSERT IGNORE INTO `sys_role_menu` VALUES (5, 1);
INSERT IGNORE INTO `sys_role_menu` VALUES (5, 5);
INSERT IGNORE INTO `sys_role_menu` VALUES (5, 112);

View File

@@ -91,8 +91,8 @@ REPLACE INTO `sys_dict_data` VALUES (1070, 1070, 'menu.ueUser.onlineIMS', 'IMS
REPLACE INTO `sys_dict_data` VALUES (1071, 1071, 'menu.ueUser.onlineUE', 'UE在线信息', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1072, 1072, 'menu.ueUser.base5G', '基站信息', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1073, 1073, 'menu.trace', '跟踪', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1074, 1074, 'menu.trace.task', '跟踪任务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.analysis', '信令分析', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1074, 1074, 'menu.trace.task', '网元跟踪任务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.analysis', '网元跟踪数据', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1076, 1076, 'menu.trace.pcap', '信令抓包', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1077, 1077, 'menu.fault', '监控', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1078, 1078, 'menu.config.backupManageRemark', '备份管理菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -261,9 +261,9 @@ REPLACE INTO `sys_dict_data` VALUES (1520, 1520, 'dictType.sys_yes_no_remark', '
REPLACE INTO `sys_dict_data` VALUES (1521, 1521, 'dictType.sys_oper_type_remark', '操作类型列表', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1522, 1522, 'dictType.sys_common_status_remark', '登录状态列表', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1523, 1523, 'dictType.trace_type_remark', '跟踪类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- REPLACE INTO `sys_dict_data` VALUES (1524, 1524, 'dictType.operation_log_type_remark', '操作日志类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1525, 1525, 'dictType.alarm_status_remark', '告警日志状态类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- REPLACE INTO `sys_dict_data` VALUES (1526, 1526, 'dictType.security_log_type_remark', '安全日志类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1524, 1524, 'dictType.alarm_status_remark', '告警日志状态类型', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1525, 1525, 'menu.trace.tshark', '信令分析', 'i18n_zh', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (1526, 1526, 'menu.trace.wireshark', '信令跟踪', 'i18n_zh', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (1527, 1527, 'dictType.ne_version_status_remark', '网元软件版本状态', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1528, 1528, 'dictType.i18n_en_remark', 'Internationalization - English', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (1529, 1529, 'dictType.i18n_zh_remark', 'Internationalization - Chinese', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -680,9 +680,9 @@ REPLACE INTO `sys_dict_data` VALUES (2162, 2162, 'table.cdr_event_smf', '数据
REPLACE INTO `sys_dict_data` VALUES (2163, 2163, 'table.cdr_event_smsc', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2164, 2164, 'menu.log.exportFile', '导出文件管理', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2165, 2165, 'menu.perf.kpiCReport', '自定义指标数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2166, 2166, 'menu.trace.taskHLR', '跟踪任务 HLR', 'i18n_zh', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2166, 2166, 'menu.trace.taskHLR', 'HLR 跟踪任务', 'i18n_zh', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2167, 2167, 'dictType.cdr_cause_code', 'CDR 响应原因代码类别类型', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2168, 2168, 'dictData.cdr_cause_code.0', '其他', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2168, 2168, 'dictData.cdr_cause_code.0', '未知错误', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2169, 2169, 'dictData.cdr_cause_code.8', '运营者要求禁止', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2170, 2170, 'dictData.cdr_cause_code.10', '呼叫禁止', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (2171, 2171, 'dictData.cdr_cause_code.21', '短信传输拒绝', 'i18n_zh', '', '', '1', 'supervisor', 1725877564156, '', 0, '');

View File

@@ -89,8 +89,8 @@ REPLACE INTO `sys_dict_data` VALUES (3070, 3070, 'menu.ueUser.onlineIMS', 'IMS O
REPLACE INTO `sys_dict_data` VALUES (3071, 3071, 'menu.ueUser.onlineUE', 'UE Online Information', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3072, 3072, 'menu.ueUser.base5G', 'Radio Information', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3073, 3073, 'menu.trace', 'Trace', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3074, 3074, 'menu.trace.task', 'Trace Tasks', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.analysis', 'Signaling Analysis', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3074, 3074, 'menu.trace.task', 'NE Trace Task', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.analysis', 'NE Trace Task Data', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3076, 3076, 'menu.trace.pcap', 'Signaling Capture', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3077, 3077, 'menu.fault', 'Monitor', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3078, 3078, 'menu.config.backupManageRemark', 'Backup Management Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -255,9 +255,9 @@ REPLACE INTO `sys_dict_data` VALUES (3520, 3520, 'dictType.sys_yes_no_remark', '
REPLACE INTO `sys_dict_data` VALUES (3521, 3521, 'dictType.sys_oper_type_remark', 'Operation type list', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3522, 3522, 'dictType.sys_common_status_remark', 'Login Status List', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3523, 3523, 'dictType.trace_type_remark', 'Trace Types', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- REPLACE INTO `sys_dict_data` VALUES (3524, 3524, 'dictType.operation_log_type_remark', 'Operation log type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3525, 3525, 'dictType.alarm_status_remark', 'Alarm Log Status Type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
-- REPLACE INTO `sys_dict_data` VALUES (3526, 3526, 'dictType.security_log_type_remark', 'Security Log Type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3524, 3524, 'dictType.alarm_status_remark', 'Alarm Log Status Type', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3525, 3525, 'menu.trace.tshark', 'Signaling Analysis', 'i18n_en', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (3526, 3526, 'menu.trace.wireshark', 'Signaling Trace', 'i18n_en', '', '', '1', 'supervisor', 1727085393370, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (3527, 3527, 'dictType.ne_version_status_remark', 'Network element software version status', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3528, 3528, 'dictType.i18n_en_remark', 'Internationalization - English', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
REPLACE INTO `sys_dict_data` VALUES (3529, 3529, 'dictType.i18n_zh_remark', 'Internationalization - Chinese', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL);
@@ -675,9 +675,9 @@ REPLACE INTO `sys_dict_data` VALUES (4162, 4162, 'table.cdr_event_smf', 'Data CD
REPLACE INTO `sys_dict_data` VALUES (4163, 4163, 'table.cdr_event_smsc', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4164, 4164, 'menu.log.exportFile', 'Exported File Management', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4165, 4165, 'menu.perf.kpiCReport', 'Custom Indicator Data', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4166, 4166, 'menu.trace.taskHLR', 'Tracking Tasks HLR', 'i18n_en', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4166, 4166, 'menu.trace.taskHLR', 'HLR Trace Task', 'i18n_en', '', '', '1', 'supervisor', 1726626822538, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4167, 4167, 'dictType.cdr_cause_code', 'CDR Response Reason Code Category Type', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4168, 4168, 'dictData.cdr_cause_code.0', 'Other', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4168, 4168, 'dictData.cdr_cause_code.0', 'Unknown Error', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4169, 4169, 'dictData.cdr_cause_code.8', 'OPERATOR_DETERMINED_BARRING', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4170, 4170, 'dictData.cdr_cause_code.10', 'CALL_BARRED', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');
REPLACE INTO `sys_dict_data` VALUES (4171, 4171, 'dictData.cdr_cause_code.21', 'SM Trans Reject', 'i18n_en', '', '', '1', 'supervisor', 1725877564156, '', 0, '');

View File

@@ -113,8 +113,8 @@ REPLACE INTO `sys_menu` VALUES (2081, 'menu.ueUser.onlineUE', 5, 6, 'ue', 'neUse
REPLACE INTO `sys_menu` VALUES (2082, 'menu.ueUser.base5G', 5, 7, 'base5G', 'neUser/base5G/index', '1', '0', 'M', '1', '1', 'neUser:base5G:index', 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.base5GRemark');
REPLACE INTO `sys_menu` VALUES (2083, 'menu.trace', 2087, 30, 'traceManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.traceRemark');
REPLACE INTO `sys_menu` VALUES (2084, 'menu.trace.task', 2083, 1, 'task', 'traceManage/task/index', '1', '0', 'M', '0', '1', 'traceManage:task:index', 'icon-chexiao', 'supervisor', 1700000000000, 'admin', 1713176976458, 'menu.trace.taskRemark');
REPLACE INTO `sys_menu` VALUES (2085, 'menu.trace.analysis', 2083, 2, 'analysis', 'traceManage/analysis/index', '1', '0', 'M', '0', '1', 'traceManage:analysis:index', 'icon-gongnengjieshao', 'supervisor', 1700000000000, 'admin', 1713176987835, 'menu.trace.analysisRemark');
REPLACE INTO `sys_menu` VALUES (2086, 'menu.trace.pcap', 2083, 3, 'pcap', 'traceManage/pcap/index', '1', '1', 'M', '1', '1', 'traceManage:pcap:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.trace.pcapRemark');
REPLACE INTO `sys_menu` VALUES (2085, 'menu.trace.analysis', 2083, 4, 'analysis', 'traceManage/analysis/index', '1', '0', 'M', '0', '1', 'traceManage:analysis:index', 'icon-gongnengjieshao', 'supervisor', 1700000000000, 'admin', 1713176987835, 'menu.trace.analysisRemark');
REPLACE INTO `sys_menu` VALUES (2086, 'menu.trace.pcap', 2083, 11, 'pcap', 'traceManage/pcap/index', '1', '1', 'M', '1', '1', 'traceManage:pcap:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.trace.pcapRemark');
REPLACE INTO `sys_menu` VALUES (2087, 'menu.fault', 0, 2, 'faultManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-jinggao', 'supervisor', 1700000000000, NULL, 0, 'menu.faultRemark');
REPLACE INTO `sys_menu` VALUES (2088, 'menu.fault.active', 2129, 1, 'active-alarm', 'faultManage/active-alarm/index', '1', '1', 'M', '1', '1', 'faultManage:active-alarm:index', 'icon-wenjian', 'supervisor', 1700000000000, NULL, 0, 'menu.fault.activemRemark');
REPLACE INTO `sys_menu` VALUES (2089, 'menu.log', 0, 9, 'logManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-fuzhidaima', 'supervisor', 1700000000000, NULL, 0, 'menu.logRemark');
@@ -179,10 +179,13 @@ REPLACE INTO `sys_menu` VALUES (2154, 'menu.ne.neConfigBackup', 4, 29, 'neConfig
REPLACE INTO `sys_menu` VALUES (2155, 'menu.common.delete', 2154, 1, '#', '', '1', '1', 'B', '1', '1', 'ne:neConfigBackup:remove', '#', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2156, 'menu.common.edit', 2154, 2, '#', '', '1', '1', 'B', '1', '1', 'ne:neConfigBackup:edit', '#', 'supervisor', 1721902269805, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2157, 'menu.dashboard.smscCDR', 2140, 9, 'smscCDR', 'dashboard/smscCDR/index', '1', '0', 'M', '1', '1', 'dashboard:cdr:index', 'icon-paixu', 'supervisor', 1723107637982, 'supervisor', 1723107637982, '');
REPLACE INTO `sys_menu` VALUES (2158, 'menu.trace.pcapFile', 2083, 4, 'pcap/inline/file', 'traceManage/pcap/file', '1', '1', 'M', '0', '1', 'traceManage:pcap:index', '#', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2158, 'menu.trace.pcapFile', 2083, 12, 'pcap/inline/file', 'traceManage/pcap/file', '1', '1', 'M', '0', '1', 'traceManage:pcap:index', '#', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2159, 'menu.log.exportFile', 2089, 100, 'exportFile', 'logManage/exportFile/index', '1', '1', 'M', '1', '1', 'logManage:exportFile:index', 'icon-wenjian', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2160, 'menu.perf.kpiCReport', 2099, 100, 'kpiCReport', 'perfManage/kpiCReport/index', '1', '1', 'M', '1', '1', 'perfManage:kpiCReport:index', 'icon-tubiaoku', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2161, 'menu.trace.taskHLR', 2083, 10, 'taskHLR', 'traceManage/task-hlr/index', '1', '0', 'M', '1', '1', 'traceManage:taskHLR:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2161, 'menu.trace.taskHLR', 2083, 6, 'taskHLR', 'traceManage/task-hlr/index', '1', '0', 'M', '1', '1', 'traceManage:taskHLR:index', 'icon-chexiao', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/inline/analyze', 'traceManage/task/analyze', '1', '0', 'M', '0', '1', 'traceManage:taskAnalyze:index', '#', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2163, 'menu.trace.tshark', 2083, 14, 'tshark', 'traceManage/tshark/index', '1', '0', 'M', '1', '1', 'traceManage:tshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, '');
REPLACE INTO `sys_menu` VALUES (2164, 'menu.trace.wireshark', 2083, 16, 'wireshark', 'traceManage/wireshark/index', '1', '0', 'M', '1', '1', 'traceManage:wireshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, '');
-- multi-tenancy

View File

@@ -245,6 +245,12 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2148);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2149);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2152);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2153);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2154);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2155);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2156);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2157);
INSERT IGNORE INTO `sys_role_menu` VALUES (3, 2160);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 1);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 5);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 112);
@@ -295,6 +301,8 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2148);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2149);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2152);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2153);
INSERT IGNORE INTO `sys_role_menu` VALUES (4, 2160);
INSERT IGNORE INTO `sys_role_menu` VALUES (5, 1);
INSERT IGNORE INTO `sys_role_menu` VALUES (5, 5);
INSERT IGNORE INTO `sys_role_menu` VALUES (5, 112);

View File

@@ -89,12 +89,12 @@ func PostCDREventFrom(w http.ResponseWriter, r *http.Request) {
switch neInfo.NeType {
case "IMS":
if v, ok := cdrEvent.CDR["recordType"]; ok && (v == "MOC" || v == "MTSM") {
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_IMS_CDR+neInfo.NeId, cdrEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_IMS_CDR+neInfo.NeId, cdrEvent)
}
case "SMF":
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_SMF_CDR+neInfo.NeId, cdrEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_SMF_CDR+neInfo.NeId, cdrEvent)
case "SMSC":
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_SMSC_CDR+neInfo.NeId, cdrEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_SMSC_CDR+neInfo.NeId, cdrEvent)
}
}

View File

@@ -85,7 +85,7 @@ func PostUEEventFromAMF(c *gin.Context) {
// AMF没有RmUID直接推送
// 推送到ws订阅组
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_AMF_UE, ueEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, ueEvent)
services.ResponseStatusOK204NoContent(c.Writer)
}
@@ -124,7 +124,7 @@ func PostUEEvent(w http.ResponseWriter, r *http.Request) {
if neInfo.RmUID == ueEvent.RmUID {
// 推送到ws订阅组
if ueEvent.NeType == "MME" {
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_MME_UE+neInfo.NeId, ueEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+neInfo.NeId, ueEvent)
}
}

View File

@@ -595,7 +595,7 @@ func GetAlarmFromNF(w http.ResponseWriter, r *http.Request) {
exist, err := session.Table("alarm").
Where("ne_type=? and ne_id=? and alarm_id=? and alarm_status=1", alarmData.NeType, alarmData.NeId, alarmData.AlarmId).
Exist()
if err == nil || !exist {
if err != nil || !exist {
log.Infof("Not found active alarm: ne_id=%s, alarm_id=%s", alarmData.NeId, alarmData.AlarmId)
continue
}

View File

@@ -202,15 +202,7 @@ func newSubmitSM(phoneNumber string, message string) (*pdu.SubmitSM, error) {
submitSM := pdu.NewSubmitSM().(*pdu.SubmitSM)
submitSM.SourceAddr = srcAddr
submitSM.DestAddr = destAddr
dataCoding := data.UCS2
switch smsForward.DataCoding {
case config.CODING_UCS2:
dataCoding = data.UCS2
case config.CODING_ASCII:
dataCoding = data.ASCII
case config.CODING_LATIN1:
dataCoding = data.LATIN1
}
dataCoding := data.FromDataCoding(smsForward.DataCoding)
err = submitSM.Message.SetMessageWithEncoding(message, dataCoding)
if err != nil {
return nil, err
@@ -222,3 +214,27 @@ func newSubmitSM(phoneNumber string, message string) (*pdu.SubmitSM, error) {
return submitSM, nil
}
// const (
// // Short message data coding type
// SMS_CODING_GSM7BIT byte = iota
// SMS_CODING_ASCII
// SMS_CODING_BINARY8BIT1
// SMS_CODING_LATIN1
// SMS_CODING_BINARY8BIT2
// SMS_CODING_NODEF
// SMS_CODING_CYRILLIC
// SMS_CODING_HEBREW
// SMS_CODING_UCS2
// )
// var codingMap = map[byte]data.Encoding{
// SMS_CODING_GSM7BIT: data.GSM7BIT,
// SMS_CODING_ASCII: data.ASCII,
// SMS_CODING_BINARY8BIT1: data.BINARY8BIT1,
// SMS_CODING_LATIN1: data.LATIN1,
// SMS_CODING_BINARY8BIT2: data.BINARY8BIT2,
// SMS_CODING_CYRILLIC: data.CYRILLIC,
// SMS_CODING_HEBREW: data.HEBREW,
// SMS_CODING_UCS2: data.UCS2,
// }

View File

@@ -330,13 +330,13 @@ func PostKPIReportFromNF(w http.ResponseWriter, r *http.Request) {
if neInfo.RmUID == kpiData.RmUid {
// 推送到ws订阅组
wsService.NewWSSendImpl.ByGroupID(fmt.Sprintf("%s%s_%s", wsService.GROUP_KPI, neInfo.NeType, neInfo.NeId), kpiEvent)
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%s_%s", wsService.GROUP_KPI, neInfo.NeType, neInfo.NeId), kpiEvent)
// 推送自定义KPI到ws订阅组
wsService.NewWSSendImpl.ByGroupID(fmt.Sprintf("%s%s_%s", wsService.GROUP_KPI_C, neInfo.NeType, neInfo.NeId), kpiCEvent)
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%s_%s", wsService.GROUP_KPI_C, neInfo.NeType, neInfo.NeId), kpiCEvent)
if neInfo.NeType == "UPF" {
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI_UPF+neInfo.NeId, kpiEvent)
// 推送标识为12_RMUID, exp: 12_4400HXUPF001
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI_UPF+kpiReport.Task.NE.RmUID, kpiEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_KPI_UPF+neInfo.NeId, kpiEvent)
// 推送标识为12_RMUID, exp: 12_4400HXUPF001, for multi-tenancy
wsService.NewWSSend.ByGroupID(wsService.GROUP_KPI_UPF+kpiReport.Task.NE.RmUID, kpiEvent)
}
}
@@ -464,9 +464,9 @@ func PostGoldKPIFromNF(w http.ResponseWriter, r *http.Request) {
}
// 推送到ws订阅组
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI, kpiEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_KPI, kpiEvent)
if goldKpi.NEType == "UPF" {
wsService.NewWSSendImpl.ByGroupID(wsService.GROUP_KPI_UPF, kpiEvent)
wsService.NewWSSend.ByGroupID(wsService.GROUP_KPI_UPF, kpiEvent)
}
services.ResponseStatusOK204NoContent(w)

34
go.mod
View File

@@ -9,6 +9,7 @@ require (
github.com/go-resty/resty/v2 v2.14.0
github.com/go-sql-driver/mysql v1.8.1
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/gopacket/gopacket v1.2.0
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.3
github.com/gosnmp/gosnmp v1.38.0
@@ -45,11 +46,11 @@ require (
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/shirou/gopsutil/v3 v3.23.11 // indirect
github.com/sirupsen/logrus v1.4.2 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bytedance/sonic v1.12.1 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect // indirect
github.com/beorn7/perks v1.0.1 // indirect // indirect
github.com/bytedance/sonic v1.12.1 // indirect // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect // indirect
github.com/chenjiandongx/ginprom v0.0.0-20210617023641-6c809602c38a
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
@@ -73,10 +74,11 @@ require (
github.com/jinzhu/now v1.1.5 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/kr/fs v0.1.0 // indirect // indirect
github.com/leodido/go-urn v1.4.0 // indirect // indirect
github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect
github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
@@ -101,13 +103,15 @@ require (
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.3 // indirect
github.com/sagikazarmark/locafero v0.6.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect // indirect
github.com/shirou/gopsutil/v3 v3.23.11 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect // indirect
github.com/spf13/afero v1.11.0 // indirect // indirect
github.com/spf13/cast v1.7.0 // indirect // indirect
github.com/subosito/gotenv v1.6.0 // indirect // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect // indirect
github.com/tebeka/strftime v0.1.5 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect

6
go.sum
View File

@@ -124,6 +124,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gopacket/gopacket v1.2.0 h1:eXbzFad7f73P1n2EJHQlsKuvIMJjVXK5tXoSca78I3A=
github.com/gopacket/gopacket v1.2.0/go.mod h1:BrAKEy5EOGQ76LSqh7DMAr7z0NNPdczWm2GxCG7+I8M=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
@@ -350,6 +352,10 @@ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=

View File

@@ -150,16 +150,6 @@ type DbConfig struct {
Backup string `yaml:"backup"`
}
//type codingType int
const (
// Short message data coding type
CODING_UCS2 int = iota
CODING_ASCII
CODING_LATIN1
CODING_NODEF
)
type AlarmConfig struct {
SplitEventAlarm bool `yaml:"splitEventAlarm"`
//ForwardAlarm bool `yaml:"forwardAlarm"`
@@ -180,7 +170,7 @@ type AlarmConfig struct {
SystemID string `yaml:"systemID" json:"systemID"`
Password string `yaml:"password" json:"password"`
SystemType string `yaml:"systemType" json:"systemType"`
DataCoding int `yaml:"dataCoding" json:"dataCoding"`
DataCoding byte `yaml:"dataCoding" json:"dataCoding"`
ServiceNumber string `yaml:"serviceNumber" json:"serviceNumber"`
} `yaml:"alarmSMSForward"`
SMS struct {
@@ -399,8 +389,10 @@ func UpdateStructFromMap(s any, updates map[string]any) {
if field.Tag.Get("json") == key {
structField := v.FieldByName(field.Name)
if structField.IsValid() && structField.CanSet() {
if structField.Type() == reflect.TypeOf(value) {
structField.Set(reflect.ValueOf(value))
// Convert value to the appropriate type if necessary
convertedValue := reflect.ValueOf(value).Convert(structField.Type())
if structField.Type() == convertedValue.Type() {
structField.Set(convertedValue)
}
}
break

View File

@@ -132,7 +132,8 @@ omc:
# TLS Skip verify: true/false
# email/sms
# smProxy: sms(Short Message Service)/smsc(SMS Centre)
# dataCoding: 0:UCS2, 1:ASCII, 2:LATIN1
# dataCoding: 0:GSM7BIT, 1:ASCII, 2:BINARY8BIT1, 3:LATIN1,
# 4:BINARY8BIT2, 6:CYRILLIC, 7:HEBREW, 8:UCS2
alarm:
alarmEmailForward:
enable: true
@@ -144,10 +145,10 @@ alarm:
tlsSkipVerify: true
alarmSMSForward:
enable: true
mobileList:
smscAddr: "192.168.13.114:2775"
systemID: "omc"
password: "omc123"
mobileList: "1006,1008"
smscAddr: "192.168.14.212:2775"
systemID: "123456"
password: "123456"
systemType: "UTRAN"
dataCoding: 0
serviceNumber: "OMC"

View File

@@ -184,7 +184,7 @@ func GetKeys(source string, pattern string) ([]string, error) {
// 循环遍历获取匹配的键
for {
// 使用 SCAN 命令获取匹配的键
batchKeys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 100).Result()
batchKeys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 1000).Result()
if err != nil {
logger.Errorf("Failed to scan keys: %v", err)
return keys, err

View File

@@ -10,10 +10,10 @@ import (
// SocketTCP TCP服务端
type SocketTCP struct {
Addr string `json:"addr"` // 主机地址
Port int64 `json:"port"` // 端口
Listen *net.Listener `json:"listen"`
StopChan chan struct{} `json:"stop"` // 停止信号
Addr string `json:"addr"` // 主机地址
Port int64 `json:"port"` // 端口
Listener *net.TCPListener `json:"listener"`
StopChan chan struct{} `json:"stop"` // 停止信号
}
// New 创建TCP服务端
@@ -26,53 +26,52 @@ func (s *SocketTCP) New() (*SocketTCP, error) {
}
address := fmt.Sprintf("%s:%d", s.Addr, s.Port)
ln, err := net.Listen(proto, address)
// 解析 TCP 地址
tcpAddr, err := net.ResolveTCPAddr(proto, address)
if err != nil {
return nil, err
}
s.Listen = &ln
// 监听 TCP 地址
listener, err := net.ListenTCP(proto, tcpAddr)
if err != nil {
return nil, err
}
s.Listener = listener
s.StopChan = make(chan struct{}, 1)
return s, nil
}
// Close 关闭当前TCP服务端
func (s *SocketTCP) Close() {
if s.Listen != nil {
if s.Listener != nil {
s.StopChan <- struct{}{}
(*s.Listen).Close()
(*s.Listener).Close()
}
}
// Resolve 处理消息
func (s *SocketTCP) Resolve(bufferSize int, callback func([]byte, int)) error {
if s.Listen == nil {
func (s *SocketTCP) Resolve(callback func(conn *net.Conn)) error {
if s.Listener == nil {
return fmt.Errorf("tcp service not created")
}
ln := *s.Listen
buffer := make([]byte, bufferSize)
listener := *s.Listener
for {
select {
case <-s.StopChan:
return fmt.Errorf("udp service stop")
default:
conn, err := ln.Accept()
conn, err := listener.Accept()
if err != nil {
logger.Errorf("Error accepting connection: %v ", err)
continue
}
defer conn.Close()
// 读取数据
n, err := conn.Read(buffer)
if err != nil {
fmt.Println("Error reading from TCP connection:", err)
continue
}
callback(buffer, n)
// 处理连接
callback(&conn)
// 发送响应
if _, err = conn.Write([]byte("tcp>")); err != nil {

View File

@@ -50,29 +50,20 @@ func (s *SocketUDP) Close() {
}
// Resolve 处理消息
func (s *SocketUDP) Resolve(bufferSize int, callback func([]byte, int)) error {
func (s *SocketUDP) Resolve(callback func(*net.UDPConn)) error {
if s.Conn == nil {
return fmt.Errorf("udp service not created")
}
buffer := make([]byte, bufferSize)
for {
select {
case <-s.StopChan:
return fmt.Errorf("udp service stop")
default:
// 读取数据
n, addr, err := s.Conn.ReadFromUDP(buffer)
if err != nil {
fmt.Println("Error reading from UDP connection:", err)
continue
}
callback(buffer, n)
callback(s.Conn)
// 发送响应
if _, err = s.Conn.WriteToUDP([]byte("udp>"), addr); err != nil {
if _, err := s.Conn.WriteTo([]byte("udp>"), s.Conn.RemoteAddr()); err != nil {
fmt.Println("Error sending response:", err)
}
}

View File

@@ -293,7 +293,7 @@ func (s *SMFController) SubUserList(c *gin.Context) {
}
// 网元直连
data, err := neFetchlink.SMFSubInfo(neInfo, map[string]string{
data, err := neFetchlink.SMFSubInfoList(neInfo, map[string]string{
"imsi": query.IMSI,
"msisdn": query.MSISDN,
"upstate": query.Upstate,
@@ -306,24 +306,23 @@ func (s *SMFController) SubUserList(c *gin.Context) {
// 对数据进行处理去掉前缀并加入imsi拓展信息
rows := data["rows"].([]any)
arr := &rows
for i := range *arr {
item := (*arr)[i].(map[string]any)
if v, ok := item["imsi"]; ok && v != nil {
imsiStr := v.(string)
imsiStr = strings.TrimPrefix(imsiStr, "imsi-")
item["imsi"] = imsiStr
// 查UDM拓展信息
info := s.udmUserInfoService.SelectByIMSIAndNeID(imsiStr, "")
item["remark"] = info.Remark
}
if v, ok := item["msisdn"]; ok && v != nil {
item["msisdn"] = strings.TrimPrefix(v.(string), "msisdn-")
if len(rows) > 0 {
arr := &rows
for i := range *arr {
item := (*arr)[i].(map[string]any)
if v, ok := item["imsi"]; ok && v != nil {
imsiStr := v.(string)
imsiStr = strings.TrimPrefix(imsiStr, "imsi-")
item["imsi"] = imsiStr
// 查UDM拓展信息
info := s.udmUserInfoService.SelectByIMSIAndNeID(imsiStr, "")
item["remark"] = info.Remark
}
if v, ok := item["msisdn"]; ok && v != nil {
item["msisdn"] = strings.TrimPrefix(v.(string), "msisdn-")
}
}
}
c.JSON(200, result.Ok(map[string]any{
"total": data["total"],
"rows": data["rows"],
}))
c.JSON(200, result.Ok(data))
}

View File

@@ -10,15 +10,13 @@ import (
"be.ems/src/modules/network_element/model"
)
// SMFSubInfo SMF在线订阅用户列表信息
// SMFSubInfoList SMF在线订阅用户列表信息
//
// 查询参数 {"imsi":"360000100000130","msisdn":"8612300000130","upstate":"Inactive","pageNum":"1"}
//
// 返回结果 {"rows":[],"total":0}
func SMFSubInfo(neInfo model.NeInfo, data map[string]string) (map[string]any, error) {
// neUrl := "http://127.0.0.1:4523/m1/3157310-1528434-82b449ee/api/rest/ueManagement/v1/elementType/smf/objectType/ueInfo?apifoxApiId=150640017"
neUrl := fmt.Sprintf("http://%s:%s/api/rest/ueManagement/v1/elementType/smf/objectType/ueInfo", "172.16.20.150", "33030")
// neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/smf/objectType/ueInfo", neInfo.IP, neInfo.Port)
func SMFSubInfoList(neInfo model.NeInfo, data map[string]string) (map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/smf/objectType/ueInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["imsi"]; ok && v != "" {

View File

@@ -0,0 +1,111 @@
package controller
import (
"be.ems/src/framework/i18n"
"be.ems/src/framework/utils/ctx"
"be.ems/src/framework/vo/result"
traceService "be.ems/src/modules/trace/service"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 PacketController 结构体
var NewPacket = &PacketController{
packetService: traceService.NewPacket,
}
// 信令跟踪
//
// PATH /trace/packet
type PacketController struct {
packetService *traceService.Packet // 信令跟踪服务
}
// 网元跟踪网卡设备列表
//
// GET /devices
func (s *PacketController) Devices(c *gin.Context) {
data := s.packetService.NetworkDevices()
c.JSON(200, result.OkData(data))
}
// 网元跟踪开始
//
// POST /start
func (s *PacketController) Start(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
Device string `json:"device" binding:"required"` // 网卡设备
TaskNo string `json:"taskNo" binding:"required"` // 任务编号
Output string `json:"output" ` // 输出PCAP文件路径为空则不输出
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
msg, err := s.packetService.LiveStart(body.TaskNo, body.Device, body.Output)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
}
c.JSON(200, result.OkData(msg))
}
// 网元跟踪结束
//
// POST /stop
func (s *PacketController) Stop(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
TaskNo string `json:"taskNo" binding:"required"` // 任务编号
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
if err := s.packetService.LiveStop(body.TaskNo); err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
}
c.JSON(200, result.Ok(nil))
}
// 网元跟踪过滤
//
// PUT /filter
func (s *PacketController) Filter(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
TaskNo string `json:"taskNo" binding:"required"` // 任务编号
Expr string `json:"expr" binding:"required"` // 过滤表达式port 33030 or 33040
}
if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
if err := s.packetService.LiveFilter(body.TaskNo, body.Expr); err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
}
c.JSON(200, result.Ok(nil))
}
// 网元跟踪续期保活
//
// PUT /keep-alive
func (s *PacketController) KeepAlive(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
IntervalIn int `json:"intervalIn" ` // 服务续约的频率默认设置为60秒
Duration int `json:"duration" ` // 服务失效的时间默认设置为120秒
}
err := c.ShouldBindBodyWith(&body, binding.JSON)
if err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
c.JSON(200, result.Ok(nil))
}

View File

@@ -13,26 +13,24 @@ import (
"github.com/gin-gonic/gin/binding"
)
// 实例化控制层 TcpdumpController 结构体
var NewTcpdump = &TcpdumpController{
TcpdumpService: traceService.NewTCPdump,
// 实例化控制层 TCPdumpController 结构体
var NewTCPdump = &TCPdumpController{
tcpdumpService: traceService.NewTCPdump,
neInfoService: neService.NewNeInfoImpl,
}
// 信令抓包请求
// 信令抓包
//
// PATH /tcpdump
type TcpdumpController struct {
// 信令抓包服务
TcpdumpService *traceService.TCPdump
// 网元信息服务
neInfoService neService.INeInfo
type TCPdumpController struct {
tcpdumpService *traceService.TCPdump // 信令抓包服务
neInfoService neService.INeInfo // 网元信息服务
}
// 网元抓包PACP 开始
//
// POST /start
func (s *TcpdumpController) DumpStart(c *gin.Context) {
func (s *TCPdumpController) DumpStart(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
@@ -45,7 +43,7 @@ func (s *TcpdumpController) DumpStart(c *gin.Context) {
return
}
taskCode, err := s.TcpdumpService.DumpStart(body.NeType, body.NeId, body.Cmd)
taskCode, err := s.tcpdumpService.DumpStart(body.NeType, body.NeId, body.Cmd)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
@@ -56,7 +54,7 @@ func (s *TcpdumpController) DumpStart(c *gin.Context) {
// 网元抓包PACP 结束
//
// POST /stop
func (s *TcpdumpController) DumpStop(c *gin.Context) {
func (s *TCPdumpController) DumpStop(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
@@ -69,7 +67,7 @@ func (s *TcpdumpController) DumpStop(c *gin.Context) {
return
}
taskLog, err := s.TcpdumpService.DumpStop(body.NeType, body.NeId, body.TaskCode)
taskLog, err := s.tcpdumpService.DumpStop(body.NeType, body.NeId, body.TaskCode)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
@@ -80,7 +78,7 @@ func (s *TcpdumpController) DumpStop(c *gin.Context) {
// 网元抓包PACP 下载
//
// GET /download
func (s *TcpdumpController) DumpDownload(c *gin.Context) {
func (s *TCPdumpController) DumpDownload(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
NeType string `form:"neType" binding:"required"` // 网元类型
@@ -93,7 +91,7 @@ func (s *TcpdumpController) DumpDownload(c *gin.Context) {
return
}
zipFilePath, err := s.TcpdumpService.DumpDownload(query.NeType, query.NeID, query.TaskCode)
zipFilePath, err := s.tcpdumpService.DumpDownload(query.NeType, query.NeID, query.TaskCode)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return
@@ -110,7 +108,7 @@ func (s *TcpdumpController) DumpDownload(c *gin.Context) {
// UPF标准版内部抓包
//
// POST /upf
func (s *TcpdumpController) UPFTrace(c *gin.Context) {
func (s *TCPdumpController) UPFTrace(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var body struct {
NeType string `json:"neType" binding:"required"` // 网元类型
@@ -123,7 +121,7 @@ func (s *TcpdumpController) UPFTrace(c *gin.Context) {
return
}
msg, err := s.TcpdumpService.UPFTrace(body.NeType, body.NeId, body.Cmd)
msg, err := s.tcpdumpService.UPFTrace(body.NeType, body.NeId, body.Cmd)
if err != nil {
c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error())))
return

View File

@@ -1,6 +1,9 @@
package controller
import (
"fmt"
"path/filepath"
"runtime"
"strings"
"be.ems/src/framework/i18n"
@@ -129,3 +132,24 @@ func (s *TraceTaskController) Remove(c *gin.Context) {
msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows})
c.JSON(200, result.OkMsg(msg))
}
// 跟踪任务文件
//
// GET /filePull
func (s *TraceTaskController) FilePull(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var querys struct {
TraceId string `form:"traceId" binding:"required"`
}
if err := c.ShouldBindQuery(&querys); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
fileName := fmt.Sprintf("task_%s.pcap", querys.TraceId)
localFilePath := filepath.Join("/tmp/omc/trace", fileName)
if runtime.GOOS == "windows" {
localFilePath = fmt.Sprintf("C:%s", localFilePath)
}
c.FileAttachment(localFilePath, fileName)
}

View File

@@ -0,0 +1,191 @@
package service
import (
"context"
"fmt"
"os"
"strings"
"sync"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/vo"
"github.com/gopacket/gopacket"
"github.com/gopacket/gopacket/pcap"
"github.com/gopacket/gopacket/pcapgo"
)
// 实例化服务层 Packet 结构体
var NewPacket = &Packet{
taskMap: sync.Map{},
}
// 信令跟踪 服务层处理
type Packet struct {
taskMap sync.Map // 捕获任务
}
// task 任务信息
type task struct {
TaskNo string // 任务编号
Handle *pcap.Handle // 捕获句柄
File *os.File // 捕获信息输出文件句柄
Writer *pcapgo.Writer // 捕获信息输出句柄
Expire time.Time // 过期时间
context context.Context // 上下文 控制完成结束
}
// NetworkDevices 获取网卡设备信息
func (s *Packet) NetworkDevices() []vo.TreeSelect {
arr := make([]vo.TreeSelect, 0)
devices, err := pcap.FindAllDevs()
if err != nil {
logger.Errorf("interfaces find all devices err: %s", err.Error())
return arr
}
for _, device := range devices {
if len(device.Addresses) == 0 {
continue
}
lable := device.Description
if lable == "" {
lable = device.Name
}
item := vo.TreeSelect{
ID: device.Name,
Label: lable,
Children: []vo.TreeSelect{},
}
for _, address := range device.Addresses {
if address.IP != nil {
ip := address.IP.String()
item.Children = append(item.Children, vo.TreeSelect{ID: ip, Label: ip})
}
}
arr = append(arr, item)
}
return arr
}
// verifyDevice 检查网卡设备是否存在
func (s *Packet) verifyDevice(str string) (string, bool) {
devices, err := pcap.FindAllDevs()
if err != nil {
logger.Errorf("interfaces find all devices err: %s", err.Error())
return "", false
}
for _, device := range devices {
if len(device.Addresses) == 0 {
continue
}
if device.Name == str {
return device.Name, true
}
for _, address := range device.Addresses {
if address.IP.String() == str {
return device.Name, true
}
}
}
return "", false
}
// LiveStart 开始捕获数据
func (s *Packet) LiveStart(taskNo, deviceName, outputFile string) (string, error) {
if _, ok := s.taskMap.Load(taskNo); ok {
return "", fmt.Errorf("task no. %s already exist", taskNo)
}
// Verify the specified network interface exists
device, deviceOk := s.verifyDevice(deviceName)
if !deviceOk {
return "", fmt.Errorf("network device not exist: %s", deviceName)
}
snapshotLength := 262144
// open device
handle, err := pcap.OpenLive(device, int32(snapshotLength), true, pcap.BlockForever)
if err != nil {
logger.Errorf("open live err: %s", err.Error())
if strings.Contains(err.Error(), "operation not permitted") {
return "", fmt.Errorf("you don't have permission to capture on that/these device(s)")
}
return "", err
}
// write a new file
var w *pcapgo.Writer
var f *os.File
if outputFile != "" {
f, err = os.Create(outputFile)
if err != nil {
return "", err
}
w = pcapgo.NewWriter(f)
w.WriteFileHeader(uint32(snapshotLength), handle.LinkType())
}
// capture packets
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
packetSource.Lazy = false
packetSource.NoCopy = true
packetSource.DecodeStreamsAsDatagrams = true
// save tasks
ctx := context.Background()
task := &task{
TaskNo: taskNo,
Handle: handle,
File: f,
Writer: w,
Expire: time.Now().Add(time.Second * 120),
context: ctx,
}
s.taskMap.Store(taskNo, task)
// start capture
go func() {
for packet := range packetSource.PacketsCtx(ctx) {
if packet == nil {
continue
}
if packet.Metadata().Timestamp.Before(time.Now()) {
continue
}
if w != nil {
w.WritePacket(packet.Metadata().CaptureInfo, packet.Data())
}
fmt.Println(packet.Dump())
}
}()
return "task initiated", nil
}
// LiveFilter 捕获过滤
func (s *Packet) LiveFilter(taskNo, expr string) error {
info, ok := s.taskMap.Load(taskNo)
if !ok {
return fmt.Errorf("task no. %s not exist", taskNo)
}
return info.(*task).Handle.SetBPFFilter(expr)
}
// LiveStop 停止捕获数据
func (s *Packet) LiveStop(taskNo string) error {
info, ok := s.taskMap.Load(taskNo)
if !ok {
return fmt.Errorf("task no. %s not exist", taskNo)
}
info.(*task).context.Done()
info.(*task).Handle.Close()
if info.(task).File != nil {
info.(task).File.Close()
}
s.taskMap.Delete(taskNo)
return nil
}

View File

@@ -1,8 +1,10 @@
package service
import (
"encoding/base64"
"encoding/json"
"fmt"
"net"
"strings"
"be.ems/src/framework/config"
@@ -14,6 +16,7 @@ import (
neService "be.ems/src/modules/network_element/service"
"be.ems/src/modules/trace/model"
"be.ems/src/modules/trace/repository"
wsService "be.ems/src/modules/ws/service"
)
// 实例化数据层 TraceTask 结构体
@@ -57,16 +60,27 @@ func (r *TraceTask) CreateUDP() error {
}
// 接收处理UDP数据
go r.udpService.Resolve(2048, func(data []byte, n int) {
logger.Infof("socket UDP: %s", string(data))
mData, err := UDPDataHandler(data, n)
go r.udpService.Resolve(func(conn *net.UDPConn) {
// 读取数据
buf := make([]byte, 2048)
n, err := conn.Read(buf)
if err != nil {
logger.Errorf("error reading from UDP connection: %s", err.Error())
return
}
logger.Infof("socket UDP: %s", string(buf[:n]))
// logger.Infof("socket UDP Base64: %s", base64.StdEncoding.EncodeToString(buf[:n]))
mData, err := UDPDataHandler(buf, n)
if err != nil {
logger.Errorf("udp resolve data fail: %s", err.Error())
return
}
taskId := parse.Number(mData["taskId"])
// 插入数据库做记录
r.traceDataRepository.Insert(model.TraceData{
TaskId: parse.Number(mData["taskId"]),
TaskId: taskId,
IMSI: mData["imsi"].(string),
SrcAddr: mData["srcAddr"].(string),
DstAddr: mData["dstAddr"].(string),
@@ -82,6 +96,7 @@ func (r *TraceTask) CreateUDP() error {
// 推送文件
if v, ok := mData["pcapFile"]; ok && v != "" {
logger.Infof("pcapFile: %s", v)
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE, taskId), taskId)
}
})
@@ -92,16 +107,29 @@ func (r *TraceTask) CreateUDP() error {
return err
}
// 接收处理TCP数据
go tcpService.Resolve(1024, func(data []byte, n int) {
logger.Infof("socket TCP: %s", string(data))
mData, err := UDPDataHandler(data, n)
go tcpService.Resolve(func(conn *net.Conn) {
c := (*conn)
// 读取数据
buf := make([]byte, 2048)
n, err := c.Read(buf)
if err != nil {
logger.Errorf("error reading from TCP connection: %s", err.Error())
return
}
logger.Infof("socket TCP: %s", string(buf[:n]))
deData, _ := base64.StdEncoding.DecodeString(string(buf[:n]))
logger.Infof("socket TCP Base64: %s", deData)
mData, err := UDPDataHandler(deData, len(deData))
if err != nil {
logger.Errorf("tcp resolve data fail: %s", err.Error())
return
}
taskId := parse.Number(mData["taskId"])
// 插入数据库做记录
r.traceDataRepository.Insert(model.TraceData{
TaskId: parse.Number(mData["taskId"]),
TaskId: taskId,
IMSI: mData["imsi"].(string),
SrcAddr: mData["srcAddr"].(string),
DstAddr: mData["dstAddr"].(string),
@@ -117,6 +145,7 @@ func (r *TraceTask) CreateUDP() error {
// 推送文件
if v, ok := mData["pcapFile"]; ok && v != "" {
logger.Infof("pcapFile: %s", v)
wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE, taskId), taskId)
}
})
return nil

View File

@@ -5,6 +5,7 @@ import (
"encoding/binary"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
@@ -264,6 +265,9 @@ const versionMinor = 4
func writeEmptyPcap(filename string, timeStamp int64, length int, data []byte) error {
var err error
var file *os.File
if err := os.MkdirAll(filepath.Dir(filename), 0775); err != nil {
return err
}
if _, err = os.Stat(filename); os.IsNotExist(err) {
file, err = os.Create(filename)
// File Header
@@ -318,7 +322,7 @@ func writeEmptyPcap(filename string, timeStamp int64, length int, data []byte) e
// writePcap 写Pcap文件并返回文件路径
func writePcap(extHdr ExtHeader) string {
filePath := fmt.Sprintf("/tmp/trace_%d .pcap", extHdr.TaskId)
filePath := fmt.Sprintf("/tmp/omc/trace/task_%d.pcap", extHdr.TaskId)
if runtime.GOOS == "windows" {
filePath = fmt.Sprintf("C:%s", filePath)
}

View File

@@ -17,34 +17,61 @@ func Setup(router *gin.Engine) {
// 启动时需要的初始参数
InitLoad()
traceGroup := router.Group("/trace")
// 信令抓包
tcpdumpGroup := traceGroup.Group("/tcpdump")
tcpdumpGroup := router.Group("/trace/tcpdump")
{
tcpdumpGroup.POST("/start",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.tcpdump", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewTcpdump.DumpStart,
controller.NewTCPdump.DumpStart,
)
tcpdumpGroup.POST("/stop",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.tcpdump", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewTcpdump.DumpStop,
controller.NewTCPdump.DumpStop,
)
tcpdumpGroup.GET("/download",
middleware.PreAuthorize(nil),
controller.NewTcpdump.DumpDownload,
controller.NewTCPdump.DumpDownload,
)
tcpdumpGroup.POST("/upf",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.tcpdump", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewTcpdump.UPFTrace,
controller.NewTCPdump.UPFTrace,
)
}
// 信令跟踪
packetGroup := router.Group("/trace/packet")
{
packetGroup.GET("/devices",
middleware.PreAuthorize(nil),
controller.NewPacket.Devices,
)
packetGroup.POST("/start",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewPacket.Start,
)
packetGroup.POST("/stop",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewPacket.Stop,
)
packetGroup.PUT("/filter",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewPacket.Filter,
)
packetGroup.PUT("/keep-alive",
middleware.PreAuthorize(nil),
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.packet", collectlogs.BUSINESS_TYPE_OTHER)),
controller.NewPacket.KeepAlive,
)
}
// 跟踪任务 网元HLR (免登录)
taskHLRGroup := traceGroup.Group("/task/hlr")
taskHLRGroup := router.Group("/trace/task/hlr")
{
taskHLRGroup.GET("/list",
controller.NewTraceTaskHlr.List,
@@ -67,7 +94,7 @@ func Setup(router *gin.Engine) {
}
// 跟踪任务
taskGroup := traceGroup.Group("/task")
taskGroup := router.Group("/trace/task")
{
taskGroup.GET("/list",
middleware.PreAuthorize(nil),
@@ -92,10 +119,14 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.task", collectlogs.BUSINESS_TYPE_DELETE)),
controller.NewTraceTask.Remove,
)
taskGroup.GET("/filePull",
middleware.PreAuthorize(nil),
controller.NewTraceTask.FilePull,
)
}
// 跟踪数据
taskDataGroup := traceGroup.Group("/data")
taskDataGroup := router.Group("/trace/data")
{
taskDataGroup.GET("/list",
middleware.PreAuthorize(nil),

View File

@@ -21,8 +21,8 @@ import (
// NewWSController 实例化控制层 WSController 结构体
var NewWSController = &WSController{
wsService: service.NewWSImpl,
wsSendService: service.NewWSSendImpl,
wsService: service.NewWS,
wsSendService: service.NewWSSend,
neHostService: neService.NewNeHostImpl,
neInfoService: neService.NewNeInfoImpl,
}
@@ -32,9 +32,9 @@ var NewWSController = &WSController{
// PATH /ws
type WSController struct {
// WebSocket 服务
wsService service.IWS
wsService *service.WS
// WebSocket消息发送 服务
wsSendService service.IWSSend
wsSendService *service.WSSend
// 网元主机连接服务
neHostService neService.INeHost
// 网元信息服务

View File

@@ -1,32 +1,220 @@
package service
import (
"encoding/json"
"net/http"
"sync"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/generate"
"be.ems/src/framework/vo/result"
"be.ems/src/modules/ws/model"
"github.com/gorilla/websocket"
)
// IWS WebSocket通信 服务层接口
type IWS interface {
// UpgraderWs http升级ws请求
UpgraderWs(w http.ResponseWriter, r *http.Request) *websocket.Conn
var (
wsClients sync.Map // ws客户端 [clientId: client]
wsUsers sync.Map // ws用户对应的多个客户端id [uid:clientIds]
wsGroup sync.Map // ws组对应的多个客户端id [groupId:clientIds]
)
// ClientCreate 客户端新建
//
// uid 登录用户ID
// groupIDs 用户订阅组
// conn ws连接实例
// childConn 子连接实例
ClientCreate(uid string, groupIDs []string, conn *websocket.Conn, childConn any) *model.WSClient
// NewWS 实例化服务层 WS 结构体
var NewWS = &WS{}
// ClientClose 客户端关闭
ClientClose(clientID string)
// WS WebSocket通信 服务层处理
type WS struct{}
// ClientReadListen 客户端读取消息监听
// receiveType 根据接收类型进行消息处理
ClientReadListen(wsClient *model.WSClient, receiveType int)
// ClientWriteListen 客户端写入消息监听
ClientWriteListen(wsClient *model.WSClient)
// UpgraderWs http升级ws请求
func (s *WS) UpgraderWs(w http.ResponseWriter, r *http.Request) *websocket.Conn {
wsUpgrader := websocket.Upgrader{
Subprotocols: []string{"omc-ws"},
// 设置消息发送缓冲区大小byte如果这个值设置得太小可能会导致服务端在发送大型消息时遇到问题
WriteBufferSize: 1024,
// 消息包启用压缩
EnableCompression: true,
// ws握手超时时间
HandshakeTimeout: 5 * time.Second,
// ws握手过程中允许跨域
CheckOrigin: func(r *http.Request) bool {
return true
},
}
conn, err := wsUpgrader.Upgrade(w, r, nil)
if err != nil {
logger.Errorf("ws Upgrade err: %s", err.Error())
}
return conn
}
// ClientCreate 客户端新建
//
// uid 登录用户ID
// groupIDs 用户订阅组
// conn ws连接实例
// childConn 子连接实例
func (s *WS) ClientCreate(uid string, groupIDs []string, conn *websocket.Conn, childConn any) *model.WSClient {
// clientID也可以用其他方式生成只要能保证在所有服务端中都能保证唯一即可
clientID := generate.Code(16)
wsClient := &model.WSClient{
ID: clientID,
Conn: conn,
LastHeartbeat: time.Now().UnixMilli(),
BindUid: uid,
SubGroup: groupIDs,
MsgChan: make(chan []byte, 100),
StopChan: make(chan struct{}, 1), // 卡死循环标记
ChildConn: childConn,
}
// 存入客户端
wsClients.Store(clientID, wsClient)
// 存入用户持有客户端
if uid != "" {
if v, ok := wsUsers.Load(uid); ok {
uidClientIds := v.(*[]string)
*uidClientIds = append(*uidClientIds, clientID)
} else {
wsUsers.Store(uid, &[]string{clientID})
}
}
// 存入用户订阅组
if uid != "" && len(groupIDs) > 0 {
for _, groupID := range groupIDs {
if v, ok := wsGroup.Load(groupID); ok {
groupClientIds := v.(*[]string)
*groupClientIds = append(*groupClientIds, clientID)
} else {
wsGroup.Store(groupID, &[]string{clientID})
}
}
}
return wsClient
}
// ClientClose 客户端关闭
func (s *WS) ClientClose(clientID string) {
v, ok := wsClients.Load(clientID)
if !ok {
return
}
client := v.(*model.WSClient)
defer func() {
client.MsgChan <- []byte("ws:close")
client.StopChan <- struct{}{}
client.Conn.Close()
wsClients.Delete(clientID)
}()
// 客户端断线时自动踢出Uid绑定列表
if client.BindUid != "" {
if v, ok := wsUsers.Load(client.BindUid); ok {
uidClientIds := v.(*[]string)
if len(*uidClientIds) > 0 {
tempClientIds := make([]string, 0, len(*uidClientIds))
for _, v := range *uidClientIds {
if v != client.ID {
tempClientIds = append(tempClientIds, v)
}
}
*uidClientIds = tempClientIds
}
}
}
// 客户端断线时自动踢出已加入的组
if len(client.SubGroup) > 0 {
for _, groupID := range client.SubGroup {
v, ok := wsGroup.Load(groupID)
if !ok {
continue
}
groupClientIds := v.(*[]string)
if len(*groupClientIds) > 0 {
tempClientIds := make([]string, 0, len(*groupClientIds))
for _, v := range *groupClientIds {
if v != client.ID {
tempClientIds = append(tempClientIds, v)
}
}
*groupClientIds = tempClientIds
}
}
}
}
// ClientReadListen 客户端读取消息监听
// receiveType 根据接收类型进行消息处理
func (s *WS) ClientReadListen(wsClient *model.WSClient, receiveType int) {
defer func() {
if err := recover(); err != nil {
logger.Errorf("ws ReadMessage Panic Error: %v", err)
}
}()
for {
// 读取消息
messageType, msg, err := wsClient.Conn.ReadMessage()
if err != nil {
logger.Warnf("ws ReadMessage UID %s err: %s", wsClient.BindUid, err.Error())
s.ClientClose(wsClient.ID)
return
}
// fmt.Println(messageType, string(msg))
// 文本 只处理文本json
if messageType == websocket.TextMessage {
var reqMsg model.WSRequest
if err := json.Unmarshal(msg, &reqMsg); err != nil {
msgByte, _ := json.Marshal(result.ErrMsg("message format json error"))
wsClient.MsgChan <- msgByte
continue
}
// 接收器处理
switch receiveType {
case ReceiveCommont:
go NewWSReceive.Commont(wsClient, reqMsg)
case ReceiveShell:
go NewWSReceive.Shell(wsClient, reqMsg)
case ReceiveShellView:
go NewWSReceive.ShellView(wsClient, reqMsg)
case ReceiveTelnet:
go NewWSReceive.Telnet(wsClient, reqMsg)
}
}
}
}
// ClientWriteListen 客户端写入消息监听
func (s *WS) ClientWriteListen(wsClient *model.WSClient) {
defer func() {
if err := recover(); err != nil {
logger.Errorf("ws WriteMessage Panic Error: %v", err)
}
}()
// 发客户端id确认是否连接
msgByte, _ := json.Marshal(result.OkData(map[string]string{
"clientId": wsClient.ID,
}))
wsClient.MsgChan <- msgByte
// 消息发送监听
for msg := range wsClient.MsgChan {
// 关闭句柄
if string(msg) == "ws:close" {
wsClient.Conn.WriteMessage(websocket.CloseMessage, []byte{})
return
}
// 发送消息
err := wsClient.Conn.WriteMessage(websocket.TextMessage, msg)
if err != nil {
logger.Warnf("ws WriteMessage UID %s err: %s", wsClient.BindUid, err.Error())
s.ClientClose(wsClient.ID)
return
}
wsClient.LastHeartbeat = time.Now().UnixMilli()
}
}

View File

@@ -1,220 +0,0 @@
package service
import (
"encoding/json"
"net/http"
"sync"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/generate"
"be.ems/src/framework/vo/result"
"be.ems/src/modules/ws/model"
"github.com/gorilla/websocket"
)
var (
wsClients sync.Map // ws客户端 [clientId: client]
wsUsers sync.Map // ws用户对应的多个客户端id [uid:clientIds]
wsGroup sync.Map // ws组对应的多个客户端id [groupId:clientIds]
)
// NewWSImpl 实例化服务层 WSImpl 结构体
var NewWSImpl = &WSImpl{}
// WSImpl WebSocket通信 服务层处理
type WSImpl struct{}
// UpgraderWs http升级ws请求
func (s *WSImpl) UpgraderWs(w http.ResponseWriter, r *http.Request) *websocket.Conn {
wsUpgrader := websocket.Upgrader{
Subprotocols: []string{"omc-ws"},
// 设置消息发送缓冲区大小byte如果这个值设置得太小可能会导致服务端在发送大型消息时遇到问题
WriteBufferSize: 1024,
// 消息包启用压缩
EnableCompression: true,
// ws握手超时时间
HandshakeTimeout: 5 * time.Second,
// ws握手过程中允许跨域
CheckOrigin: func(r *http.Request) bool {
return true
},
}
conn, err := wsUpgrader.Upgrade(w, r, nil)
if err != nil {
logger.Errorf("ws Upgrade err: %s", err.Error())
}
return conn
}
// ClientCreate 客户端新建
//
// uid 登录用户ID
// groupIDs 用户订阅组
// conn ws连接实例
// childConn 子连接实例
func (s *WSImpl) ClientCreate(uid string, groupIDs []string, conn *websocket.Conn, childConn any) *model.WSClient {
// clientID也可以用其他方式生成只要能保证在所有服务端中都能保证唯一即可
clientID := generate.Code(16)
wsClient := &model.WSClient{
ID: clientID,
Conn: conn,
LastHeartbeat: time.Now().UnixMilli(),
BindUid: uid,
SubGroup: groupIDs,
MsgChan: make(chan []byte, 100),
StopChan: make(chan struct{}, 1), // 卡死循环标记
ChildConn: childConn,
}
// 存入客户端
wsClients.Store(clientID, wsClient)
// 存入用户持有客户端
if uid != "" {
if v, ok := wsUsers.Load(uid); ok {
uidClientIds := v.(*[]string)
*uidClientIds = append(*uidClientIds, clientID)
} else {
wsUsers.Store(uid, &[]string{clientID})
}
}
// 存入用户订阅组
if uid != "" && len(groupIDs) > 0 {
for _, groupID := range groupIDs {
if v, ok := wsGroup.Load(groupID); ok {
groupClientIds := v.(*[]string)
*groupClientIds = append(*groupClientIds, clientID)
} else {
wsGroup.Store(groupID, &[]string{clientID})
}
}
}
return wsClient
}
// ClientClose 客户端关闭
func (s *WSImpl) ClientClose(clientID string) {
v, ok := wsClients.Load(clientID)
if !ok {
return
}
client := v.(*model.WSClient)
defer func() {
client.MsgChan <- []byte("ws:close")
client.StopChan <- struct{}{}
client.Conn.Close()
wsClients.Delete(clientID)
}()
// 客户端断线时自动踢出Uid绑定列表
if client.BindUid != "" {
if v, ok := wsUsers.Load(client.BindUid); ok {
uidClientIds := v.(*[]string)
if len(*uidClientIds) > 0 {
tempClientIds := make([]string, 0, len(*uidClientIds))
for _, v := range *uidClientIds {
if v != client.ID {
tempClientIds = append(tempClientIds, v)
}
}
*uidClientIds = tempClientIds
}
}
}
// 客户端断线时自动踢出已加入的组
if len(client.SubGroup) > 0 {
for _, groupID := range client.SubGroup {
v, ok := wsGroup.Load(groupID)
if !ok {
continue
}
groupClientIds := v.(*[]string)
if len(*groupClientIds) > 0 {
tempClientIds := make([]string, 0, len(*groupClientIds))
for _, v := range *groupClientIds {
if v != client.ID {
tempClientIds = append(tempClientIds, v)
}
}
*groupClientIds = tempClientIds
}
}
}
}
// ClientReadListen 客户端读取消息监听
// receiveType 根据接收类型进行消息处理
func (s *WSImpl) ClientReadListen(wsClient *model.WSClient, receiveType int) {
defer func() {
if err := recover(); err != nil {
logger.Errorf("ws ReadMessage Panic Error: %v", err)
}
}()
for {
// 读取消息
messageType, msg, err := wsClient.Conn.ReadMessage()
if err != nil {
logger.Warnf("ws ReadMessage UID %s err: %s", wsClient.BindUid, err.Error())
s.ClientClose(wsClient.ID)
return
}
// fmt.Println(messageType, string(msg))
// 文本 只处理文本json
if messageType == websocket.TextMessage {
var reqMsg model.WSRequest
if err := json.Unmarshal(msg, &reqMsg); err != nil {
msgByte, _ := json.Marshal(result.ErrMsg("message format json error"))
wsClient.MsgChan <- msgByte
continue
}
// 接收器处理
switch receiveType {
case ReceiveCommont:
go NewWSReceiveImpl.Commont(wsClient, reqMsg)
case ReceiveShell:
go NewWSReceiveImpl.Shell(wsClient, reqMsg)
case ReceiveShellView:
go NewWSReceiveImpl.ShellView(wsClient, reqMsg)
case ReceiveTelnet:
go NewWSReceiveImpl.Telnet(wsClient, reqMsg)
}
}
}
}
// ClientWriteListen 客户端写入消息监听
func (s *WSImpl) ClientWriteListen(wsClient *model.WSClient) {
defer func() {
if err := recover(); err != nil {
logger.Errorf("ws WriteMessage Panic Error: %v", err)
}
}()
// 发客户端id确认是否连接
msgByte, _ := json.Marshal(result.OkData(map[string]string{
"clientId": wsClient.ID,
}))
wsClient.MsgChan <- msgByte
// 消息发送监听
for msg := range wsClient.MsgChan {
// 关闭句柄
if string(msg) == "ws:close" {
wsClient.Conn.WriteMessage(websocket.CloseMessage, []byte{})
return
}
// 发送消息
err := wsClient.Conn.WriteMessage(websocket.TextMessage, msg)
if err != nil {
logger.Warnf("ws WriteMessage UID %s err: %s", wsClient.BindUid, err.Error())
s.ClientClose(wsClient.ID)
return
}
wsClient.LastHeartbeat = time.Now().UnixMilli()
}
}

View File

@@ -1,6 +1,18 @@
package service
import "be.ems/src/modules/ws/model"
import (
"encoding/json"
"fmt"
"io"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/telnet"
"be.ems/src/framework/utils/ssh"
"be.ems/src/framework/vo/result"
"be.ems/src/modules/ws/model"
"be.ems/src/modules/ws/processor"
)
const (
ReceiveCommont = iota // Commont 接收通用业务处理
@@ -9,17 +21,245 @@ const (
ReceiveTelnet // Telnet 接收终端交互业务处理
)
// IWSReceive WebSocket消息接收处理 服务层接口
type IWSReceive interface {
// Commont 接收通用业务处理
Commont(client *model.WSClient, reqMsg model.WSRequest)
// 实例化服务层 WSReceive 结构体
var NewWSReceive = &WSReceive{}
// Shell 接收终端交互业务处理
Shell(client *model.WSClient, reqMsg model.WSRequest)
// WSReceive WebSocket消息接收处理 服务层处理
type WSReceive struct{}
// ShellView 接收查看文件终端交互业务处理
ShellView(client *model.WSClient, reqMsg model.WSRequest)
// Telnet 接收终端交互业务处理
Telnet(client *model.WSClient, reqMsg model.WSRequest)
// close 关闭服务连接
func (s *WSReceive) close(client *model.WSClient) {
// 主动关闭
resultByte, _ := json.Marshal(result.OkMsg("user initiated closure"))
client.MsgChan <- resultByte
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
NewWS.ClientClose(client.ID)
}
// Commont 接收通用业务处理
func (s *WSReceive) Commont(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws Commont UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "ps":
resByte, err = processor.GetProcessData(reqMsg.RequestID, reqMsg.Data)
case "net":
resByte, err = processor.GetNetConnections(reqMsg.RequestID, reqMsg.Data)
case "ims_cdr":
resByte, err = processor.GetCDRConnectByIMS(reqMsg.RequestID, reqMsg.Data)
case "smf_cdr":
resByte, err = processor.GetCDRConnectBySMF(reqMsg.RequestID, reqMsg.Data)
case "smsc_cdr":
resByte, err = processor.GetCDRConnectBySMSC(reqMsg.RequestID, reqMsg.Data)
case "amf_ue":
resByte, err = processor.GetUEConnectByAMF(reqMsg.RequestID, reqMsg.Data)
case "mme_ue":
resByte, err = processor.GetUEConnectByMME(reqMsg.RequestID, reqMsg.Data)
case "upf_tf":
resByte, err = processor.GetUPFTotalFlow(reqMsg.RequestID, reqMsg.Data)
case "ne_state":
resByte, err = processor.GetNeState(reqMsg.RequestID, reqMsg.Data)
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws Commont UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}
// Shell 接收终端交互业务处理
func (s *WSReceive) Shell(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws Shell UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "ssh":
// SSH会话消息接收写入会话
command := reqMsg.Data.(string)
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
_, err = sshClientSession.Write(command)
case "ssh_resize":
// SSH会话窗口重置
msgByte, _ := json.Marshal(reqMsg.Data)
var data struct {
Cols int `json:"cols"`
Rows int `json:"rows"`
}
err = json.Unmarshal(msgByte, &data)
if err == nil {
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
err = sshClientSession.Session.WindowChange(data.Rows, data.Cols)
}
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws Shell UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}
// ShellView 接收查看文件终端交互业务处理
func (s *WSReceive) ShellView(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws ShellView UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "cat", "tail":
var command string
if reqMsg.Type == "cat" {
command, err = processor.ParseCat(reqMsg.Data)
}
if reqMsg.Type == "tail" {
command, err = processor.ParseTail(reqMsg.Data)
}
if command != "" && err == nil {
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
_, err = sshClientSession.Write(command)
}
case "ctrl-c":
// 模拟按下 Ctrl+C
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
_, err = sshClientSession.Write("\u0003\n")
case "resize":
// 会话窗口重置
msgByte, _ := json.Marshal(reqMsg.Data)
var data struct {
Cols int `json:"cols"`
Rows int `json:"rows"`
}
err = json.Unmarshal(msgByte, &data)
if err == nil {
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
err = sshClientSession.Session.WindowChange(data.Rows, data.Cols)
}
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws ShellView UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}
// Telnet 接收终端交互业务处理
func (s *WSReceive) Telnet(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws Shell UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "telnet":
// Telnet会话消息接收写入会话
command := reqMsg.Data.(string)
telnetClientSession := client.ChildConn.(*telnet.TelnetClientSession)
_, err = telnetClientSession.Write(command)
case "telnet_resize":
// Telnet会话窗口重置
msgByte, _ := json.Marshal(reqMsg.Data)
var data struct {
Cols int `json:"cols"`
Rows int `json:"rows"`
}
err = json.Unmarshal(msgByte, &data)
if err == nil {
// telnetClientSession := client.ChildConn.(*telnet.TelnetClientSession)
// _ = telnetClientSession.WindowChange(data.Rows, data.Cols)
}
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws Shell UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}

View File

@@ -1,258 +0,0 @@
package service
import (
"encoding/json"
"fmt"
"io"
"time"
"be.ems/src/framework/logger"
"be.ems/src/framework/telnet"
"be.ems/src/framework/utils/ssh"
"be.ems/src/framework/vo/result"
"be.ems/src/modules/ws/model"
"be.ems/src/modules/ws/processor"
)
// 实例化服务层 WSReceiveImpl 结构体
var NewWSReceiveImpl = &WSReceiveImpl{}
// WSReceiveImpl WebSocket消息接收处理 服务层处理
type WSReceiveImpl struct{}
// Commont 接收通用业务处理
func (s *WSReceiveImpl) close(client *model.WSClient) {
// 主动关闭
resultByte, _ := json.Marshal(result.OkMsg("user initiated closure"))
client.MsgChan <- resultByte
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
NewWSImpl.ClientClose(client.ID)
}
// Commont 接收通用业务处理
func (s *WSReceiveImpl) Commont(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws Commont UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "ps":
resByte, err = processor.GetProcessData(reqMsg.RequestID, reqMsg.Data)
case "net":
resByte, err = processor.GetNetConnections(reqMsg.RequestID, reqMsg.Data)
case "ims_cdr":
resByte, err = processor.GetCDRConnectByIMS(reqMsg.RequestID, reqMsg.Data)
case "smf_cdr":
resByte, err = processor.GetCDRConnectBySMF(reqMsg.RequestID, reqMsg.Data)
case "smsc_cdr":
resByte, err = processor.GetCDRConnectBySMSC(reqMsg.RequestID, reqMsg.Data)
case "amf_ue":
resByte, err = processor.GetUEConnectByAMF(reqMsg.RequestID, reqMsg.Data)
case "mme_ue":
resByte, err = processor.GetUEConnectByMME(reqMsg.RequestID, reqMsg.Data)
case "upf_tf":
resByte, err = processor.GetUPFTotalFlow(reqMsg.RequestID, reqMsg.Data)
case "ne_state":
resByte, err = processor.GetNeState(reqMsg.RequestID, reqMsg.Data)
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws Commont UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}
// Shell 接收终端交互业务处理
func (s *WSReceiveImpl) Shell(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws Shell UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "ssh":
// SSH会话消息接收写入会话
command := reqMsg.Data.(string)
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
_, err = sshClientSession.Write(command)
case "ssh_resize":
// SSH会话窗口重置
msgByte, _ := json.Marshal(reqMsg.Data)
var data struct {
Cols int `json:"cols"`
Rows int `json:"rows"`
}
err = json.Unmarshal(msgByte, &data)
if err == nil {
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
err = sshClientSession.Session.WindowChange(data.Rows, data.Cols)
}
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws Shell UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}
// ShellView 接收查看文件终端交互业务处理
func (s *WSReceiveImpl) ShellView(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws ShellView UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "cat", "tail":
var command string
if reqMsg.Type == "cat" {
command, err = processor.ParseCat(reqMsg.Data)
}
if reqMsg.Type == "tail" {
command, err = processor.ParseTail(reqMsg.Data)
}
if command != "" && err == nil {
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
_, err = sshClientSession.Write(command)
}
case "ctrl-c":
// 模拟按下 Ctrl+C
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
_, err = sshClientSession.Write("\u0003\n")
case "resize":
// 会话窗口重置
msgByte, _ := json.Marshal(reqMsg.Data)
var data struct {
Cols int `json:"cols"`
Rows int `json:"rows"`
}
err = json.Unmarshal(msgByte, &data)
if err == nil {
sshClientSession := client.ChildConn.(*ssh.SSHClientSession)
err = sshClientSession.Session.WindowChange(data.Rows, data.Cols)
}
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws ShellView UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}
// Telnet 接收终端交互业务处理
func (s *WSReceiveImpl) Telnet(client *model.WSClient, reqMsg model.WSRequest) {
// 必传requestId确认消息
if reqMsg.RequestID == "" {
msg := "message requestId is required"
logger.Infof("ws Shell UID %s err: %s", client.BindUid, msg)
msgByte, _ := json.Marshal(result.ErrMsg(msg))
client.MsgChan <- msgByte
return
}
var resByte []byte
var err error
switch reqMsg.Type {
case "close":
s.close(client)
return
case "telnet":
// Telnet会话消息接收写入会话
command := reqMsg.Data.(string)
telnetClientSession := client.ChildConn.(*telnet.TelnetClientSession)
_, err = telnetClientSession.Write(command)
case "telnet_resize":
// Telnet会话窗口重置
msgByte, _ := json.Marshal(reqMsg.Data)
var data struct {
Cols int `json:"cols"`
Rows int `json:"rows"`
}
err = json.Unmarshal(msgByte, &data)
if err == nil {
// telnetClientSession := client.ChildConn.(*telnet.TelnetClientSession)
// _ = telnetClientSession.WindowChange(data.Rows, data.Cols)
}
default:
err = fmt.Errorf("message type %s not supported", reqMsg.Type)
}
if err != nil {
logger.Warnf("ws Shell UID %s err: %s", client.BindUid, err.Error())
msgByte, _ := json.Marshal(result.ErrMsg(err.Error()))
client.MsgChan <- msgByte
if err == io.EOF {
// 等待1s后关闭连接
time.Sleep(1 * time.Second)
client.StopChan <- struct{}{}
}
return
}
if len(resByte) > 0 {
client.MsgChan <- resByte
}
}

View File

@@ -1,10 +1,87 @@
package service
// IWSSend WebSocket消息发送处理 服务层接口
type IWSSend interface {
// ByClientID 给已知客户端发消息
ByClientID(clientID string, data any) error
import (
"encoding/json"
"fmt"
// ByGroupID 给订阅组的客户端发送消息
ByGroupID(gid string, data any) error
"be.ems/src/framework/vo/result"
"be.ems/src/modules/ws/model"
)
// 订阅组指定编号为支持服务器向客户端主动推送数据
const (
// 组号-其他
GROUP_OTHER = "0"
// 组号-跟踪任务数据变更 2_traceId
GROUP_TRACE = "2_"
// 组号-指标通用 10_neType_neId
GROUP_KPI = "10_"
// 组号-指标UPF 12_neId
GROUP_KPI_UPF = "12_"
// 组号-自定义KPI指标20_neType_neId
GROUP_KPI_C = "20_"
// 组号-IMS_CDR会话事件 1005_neId
GROUP_IMS_CDR = "1005_"
// 组号-SMF_CDR会话事件 1006_neId
GROUP_SMF_CDR = "1006_"
// 组号-SMSC_CDR会话事件 1007_neId
GROUP_SMSC_CDR = "1007_"
// 组号-AMF_UE会话事件
GROUP_AMF_UE = "1010"
// 组号-MME_UE会话事件 1011_neId
GROUP_MME_UE = "1011_"
)
// 实例化服务层 WSSend 结构体
var NewWSSend = &WSSend{}
// WSSend WebSocket消息发送处理 服务层处理
type WSSend struct{}
// ByClientID 给已知客户端发消息
func (s *WSSend) ByClientID(clientID string, data any) error {
v, ok := wsClients.Load(clientID)
if !ok {
return fmt.Errorf("no fount client ID: %s", clientID)
}
dataByte, err := json.Marshal(result.OkData(data))
if err != nil {
return err
}
client := v.(*model.WSClient)
if len(client.MsgChan) > 90 {
NewWS.ClientClose(client.ID)
return fmt.Errorf("msg chan over 90 will close client ID: %s", clientID)
}
client.MsgChan <- dataByte
return nil
}
// ByGroupID 给订阅组的客户端发送消息
func (s *WSSend) ByGroupID(groupID string, data any) error {
clientIds, ok := wsGroup.Load(groupID)
if !ok {
return fmt.Errorf("no fount Group ID: %s", groupID)
}
// 检查组内是否有客户端
ids := clientIds.(*[]string)
if len(*ids) == 0 {
return fmt.Errorf("no members in the group")
}
// 遍历给客户端发消息
for _, clientId := range *ids {
err := s.ByClientID(clientId, map[string]any{
"groupId": groupID,
"data": data,
})
if err != nil {
continue
}
}
return nil
}

View File

@@ -1,85 +0,0 @@
package service
import (
"encoding/json"
"fmt"
"be.ems/src/framework/vo/result"
"be.ems/src/modules/ws/model"
)
// 订阅组指定编号为支持服务器向客户端主动推送数据
const (
// 组号-其他
GROUP_OTHER = "0"
// 组号-指标通用 10_neType_neId
GROUP_KPI = "10_"
// 组号-指标UPF 12_neId
GROUP_KPI_UPF = "12_"
// 组号-自定义KPI指标20_neType_neId
GROUP_KPI_C = "20_"
// 组号-IMS_CDR会话事件 1005_neId
GROUP_IMS_CDR = "1005_"
// 组号-SMF_CDR会话事件 1006_neId
GROUP_SMF_CDR = "1006_"
// 组号-SMSC_CDR会话事件 1007_neId
GROUP_SMSC_CDR = "1007_"
// 组号-AMF_UE会话事件
GROUP_AMF_UE = "1010"
// 组号-MME_UE会话事件 1011_neId
GROUP_MME_UE = "1011_"
)
// 实例化服务层 WSSendImpl 结构体
var NewWSSendImpl = &WSSendImpl{}
// IWSSend WebSocket消息发送处理 服务层处理
type WSSendImpl struct{}
// ByClientID 给已知客户端发消息
func (s *WSSendImpl) ByClientID(clientID string, data any) error {
v, ok := wsClients.Load(clientID)
if !ok {
return fmt.Errorf("no fount client ID: %s", clientID)
}
dataByte, err := json.Marshal(result.OkData(data))
if err != nil {
return err
}
client := v.(*model.WSClient)
if len(client.MsgChan) > 90 {
NewWSImpl.ClientClose(client.ID)
return fmt.Errorf("msg chan over 90 will close client ID: %s", clientID)
}
client.MsgChan <- dataByte
return nil
}
// ByGroupID 给订阅组的客户端发送消息
func (s *WSSendImpl) ByGroupID(groupID string, data any) error {
clientIds, ok := wsGroup.Load(groupID)
if !ok {
return fmt.Errorf("no fount Group ID: %s", groupID)
}
// 检查组内是否有客户端
ids := clientIds.(*[]string)
if len(*ids) == 0 {
return fmt.Errorf("no members in the group")
}
// 遍历给客户端发消息
for _, clientId := range *ids {
err := s.ByClientID(clientId, map[string]any{
"groupId": groupID,
"data": data,
})
if err != nil {
continue
}
}
return nil
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

656
sshsvc/mibs/CINTEL-MIB.my Normal file
View File

@@ -0,0 +1,656 @@
--
-- CINTEL-MIB.my
-- MIB generated by MG-SOFT Visual MIB Builder Version 7.0 Build 209
-- Friday, December 16, 2011 at 15:52:13
--
CINTEL-MIB DEFINITIONS ::= BEGIN
IMPORTS
enterprises, TimeTicks, MODULE-IDENTITY
FROM SNMPv2-SMI
TEXTUAL-CONVENTION
FROM SNMPv2-TC;
-- 1.3.6.1.4.1.1379.2
cintelSS MODULE-IDENTITY
LAST-UPDATED "201706041222Z" -- June 04, 2017 at 12:22 GMT
ORGANIZATION
"CINTEL"
CONTACT-INFO
"cintel
support@cintel.com.cn"
DESCRIPTION
"The MIB module for cintel's Softswitch products."
REVISION "201706041223Z" -- June 04, 2017 at 12:23 GMT
DESCRIPTION
"This is the first release version of the MIB"
::= { cintelNS 2 }
--
-- Type definitions
--
AdminStateChoices ::= INTEGER
{
locked(0),
unlocked(1),
shutDown(2)
}
OperStateChoices ::= INTEGER
{
disable(0),
enable(1)
}
AvailStateChoices ::= INTEGER
{
inTest(0),
failed(1),
powerOff(2),
offLine(3),
onLine(4),
dependency(5),
degraded(6),
notInstalled(7)
}
--
-- Textual conventions
--
-- TEXTUAL-CONVENTION MACRO ::=
-- BEGIN
-- TYPE NOTATION ::=
-- DisplayPart
-- "STATUS" Status
-- "DESCRIPTION" Text
-- ReferPart
-- "SYNTAX" Syntax
--
-- VALUE NOTATION ::=
-- value(VALUE Syntax)
--
-- DisplayPart ::=
-- "DISPLAY-HINT" Text
-- | empty
--
-- Status ::=
-- "current"
-- | "deprecated"
-- | "obsolete"
--
-- ReferPart ::=
-- "REFERENCE" Text
-- | empty
--
-- -- -- uses the NVT ASCII character set
-- Text ::= """" string """"
--
-- Syntax ::=
-- type(ObjectSyntax)
-- | "BITS" "{" Kibbles "}"
-- Kibbles ::=
-- Kibble
-- | Kibbles "," Kibble
-- Kibble ::=
-- identifier "(" nonNegativeNumber ")"
-- END
DisplayString8 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"8a"
STATUS current
DESCRIPTION
"Represents textual information taken from the NVT ASCII
character set, as defined in pages 4, 10-11 of RFC 854.
To summarize RFC 854, the NVT ASCII repertoire specifies:
- the use of character codes 0-127 (decimal)
- the graphics characters (32-126) are interpreted as
US ASCII
- NUL, LF, CR, BEL, BS, HT, VT and FF have the special
meanings specified in RFC 854
- the other 25 codes have no standard interpretation
- the sequence 'CR LF' means newline
- the sequence 'CR NUL' means carriage-return
- an 'LF' not preceded by a 'CR' means moving to the
same column on the next line.
- the sequence 'CR x' for any x other than LF or NUL is
illegal. (Note that this also means that a string may
end with either 'CR LF' or 'CR NUL', but not with CR.)
Any object defined using this syntax may not exceed 255
characters in length."
SYNTAX OCTET STRING (SIZE (0..8))
DisplayString16 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"16a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 16 characters most."
SYNTAX OCTET STRING (SIZE (0..16))
DisplayString32 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"32a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 32 characters most."
SYNTAX OCTET STRING (SIZE (0..32))
DisplayString64 ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"64a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 64 characters most."
SYNTAX OCTET STRING (SIZE (0..64))
DisplayString ::= TEXTUAL-CONVENTION
DISPLAY-HINT
"255a"
STATUS current
DESCRIPTION
"A version of DisplayString that contains only 255 characters most."
SYNTAX OCTET STRING (SIZE (0..255))
RowStatus ::= TEXTUAL-CONVENTION
STATUS current
DESCRIPTION
"The RowStatus textual convention is used to manage the
creation and deletion of conceptual rows, and is used as the
value of the SYNTAX clause for the status column of a
conceptual row (as described in Section 7.7.1 of [2].)
The status column has six defined values:
- `active', which indicates that the conceptual row is
available for use by the managed device;
- `notInService', which indicates that the conceptual
row exists in the agent, but is unavailable for use by
the managed device (see NOTE below);
- `notReady', which indicates that the conceptual row
exists in the agent, but is missing information
necessary in order to be available for use by the
managed device;
- `createAndGo', which is supplied by a management
station wishing to create a new instance of a
conceptual row and to have its status automatically set
to active, making it available for use by the managed
device;
- `createAndWait', which is supplied by a management
station wishing to create a new instance of a
conceptual row (but not make it available for use by
the managed device); and,
- `destroy', which is supplied by a management station
wishing to delete all of the instances associated with
an existing conceptual row.
Whereas five of the six values (all except `notReady') may
be specified in a management protocol set operation, only
three values will be returned in response to a management
protocol retrieval operation: `notReady', `notInService' or
`active'. That is, when queried, an existing conceptual row
has only three states: it is either available for use by
the managed device (the status column has value `active');
it is not available for use by the managed device, though
the agent has sufficient information to make it so (the
status column has value `notInService'); or, it is not
available for use by the managed device, and an attempt to
make it so would fail because the agent has insufficient
information (the state column has value `notReady').
NOTE WELL
This textual convention may be used for a MIB table,
irrespective of whether the values of that table's
conceptual rows are able to be modified while it is
active, or whether its conceptual rows must be taken
out of service in order to be modified. That is, it is
the responsibility of the DESCRIPTION clause of the
status column to specify whether the status column must
not be `active' in order for the value of some other
column of the same conceptual row to be modified. If
such a specification is made, affected columns may be
changed by an SNMP set PDU if the RowStatus would not
be equal to `active' either immediately before or after
processing the PDU. In other words, if the PDU also
contained a varbind that would change the RowStatus
value, the column in question may be changed if the
RowStatus was not equal to `active' as the PDU was
received, or if the varbind sets the status to a value
other than 'active'.
Also note that whenever any elements of a row exist, the
RowStatus column must also exist.
To summarize the effect of having a conceptual row with a
status column having a SYNTAX clause value of RowStatus,
consider the following state diagram:
STATE
+--------------+-----------+-------------+-------------
| A | B | C | D
| |status col.|status column|
|status column | is | is |status column
ACTION |does not exist| notReady | notInService| is active
--------------+--------------+-----------+-------------+-------------
set status |noError ->D|inconsist- |inconsistent-|inconsistent-
column to | or | entValue| Value| Value
createAndGo |inconsistent- | | |
| Value| | |
--------------+--------------+-----------+-------------+-------------
set status |noError see 1|inconsist- |inconsistent-|inconsistent-
column to | or | entValue| Value| Value
createAndWait |wrongValue | | |
--------------+--------------+-----------+-------------+-------------
set status |inconsistent- |inconsist- |noError |noError
column to | Value| entValue| |
active | | | |
| | or | |
| | | |
| |see 2 ->D| ->D| ->D
--------------+--------------+-----------+-------------+-------------
set status |inconsistent- |inconsist- |noError |noError ->C
column to | Value| entValue| |
notInService | | | |
| | or | | or
| | | |
| |see 3 ->C| ->C|wrongValue
--------------+--------------+-----------+-------------+-------------
set status |noError |noError |noError |noError
column to | | | |
destroy | ->A| ->A| ->A| ->A
--------------+--------------+-----------+-------------+-------------
set any other |see 4 |noError |noError |see 5
column to some| | | |
value | | see 1| ->C| ->D
--------------+--------------+-----------+-------------+-------------
(1) goto B or C, depending on information available to the
agent.
(2) if other variable bindings included in the same PDU,
provide values for all columns which are missing but
required, then return noError and goto D.
(3) if other variable bindings included in the same PDU,
provide values for all columns which are missing but
required, then return noError and goto C.
(4) at the discretion of the agent, the return value may be
either:
inconsistentName: because the agent does not choose to
create such an instance when the corresponding
RowStatus instance does not exist, or
inconsistentValue: if the supplied value is
inconsistent with the state of some other MIB object's
value, or
noError: because the agent chooses to create the
instance.
If noError is returned, then the instance of the status
column must also be created, and the new state is B or C,
depending on the information available to the agent. If
inconsistentName or inconsistentValue is returned, the row
remains in state A.
(5) depending on the MIB definition for the column/table,
either noError or inconsistentValue may be returned.
NOTE: Other processing of the set request may result in a
response other than noError being returned, e.g.,
wrongValue, noCreation, etc.
Conceptual Row Creation
There are four potential interactions when creating a
conceptual row: selecting an instance-identifier which is
not in use; creating the conceptual row; initializing any
objects for which the agent does not supply a default; and,
making the conceptual row available for use by the managed
device.
Interaction 1: Selecting an Instance-Identifier
The algorithm used to select an instance-identifier varies
for each conceptual row. In some cases, the instance-
identifier is semantically significant, e.g., the
destination address of a route, and a management station
selects the instance-identifier according to the semantics.
In other cases, the instance-identifier is used solely to
distinguish conceptual rows, and a management station
without specific knowledge of the conceptual row might
examine the instances present in order to determine an
unused instance-identifier. (This approach may be used, but
it is often highly sub-optimal; however, it is also a
questionable practice for a naive management station to
attempt conceptual row creation.)
Alternately, the MIB module which defines the conceptual row
might provide one or more objects which provide assistance
in determining an unused instance-identifier. For example,
if the conceptual row is indexed by an integer-value, then
an object having an integer-valued SYNTAX clause might be
defined for such a purpose, allowing a management station to
issue a management protocol retrieval operation. In order
to avoid unnecessary collisions between competing management
stations, `adjacent' retrievals of this object should be
different.
Finally, the management station could select a pseudo-random
number to use as the index. In the event that this index
was already in use and an inconsistentValue was returned in
response to the management protocol set operation, the
management station should simply select a new pseudo-random
number and retry the operation.
A MIB designer should choose between the two latter
algorithms based on the size of the table (and therefore the
efficiency of each algorithm). For tables in which a large
number of entries are expected, it is recommended that a MIB
object be defined that returns an acceptable index for
creation. For tables with small numbers of entries, it is
recommended that the latter pseudo-random index mechanism be
used.
Interaction 2: Creating the Conceptual Row
Once an unused instance-identifier has been selected, the
management station determines if it wishes to create and
activate the conceptual row in one transaction or in a
negotiated set of interactions.
Interaction 2a: Creating and Activating the Conceptual Row
The management station must first determine the column
requirements, i.e., it must determine those columns for
which it must or must not provide values. Depending on the
complexity of the table and the management station's
knowledge of the agent's capabilities, this determination
can be made locally by the management station. Alternately,
the management station issues a management protocol get
operation to examine all columns in the conceptual row that
it wishes to create. In response, for each column, there
are three possible outcomes:
- a value is returned, indicating that some other
management station has already created this conceptual
row. We return to interaction 1.
- the exception `noSuchInstance' is returned,
indicating that the agent implements the object-type
associated with this column, and that this column in at
least one conceptual row would be accessible in the MIB
view used by the retrieval were it to exist. For those
columns to which the agent provides read-create access,
the `noSuchInstance' exception tells the management
station that it should supply a value for this column
when the conceptual row is to be created.
- the exception `noSuchObject' is returned, indicating
that the agent does not implement the object-type
associated with this column or that there is no
conceptual row for which this column would be
accessible in the MIB view used by the retrieval. As
such, the management station can not issue any
management protocol set operations to create an
instance of this column.
Once the column requirements have been determined, a
management protocol set operation is accordingly issued.
This operation also sets the new instance of the status
column to `createAndGo'.
When the agent processes the set operation, it verifies that
it has sufficient information to make the conceptual row
available for use by the managed device. The information
available to the agent is provided by two sources: the
management protocol set operation which creates the
conceptual row, and, implementation-specific defaults
supplied by the agent (note that an agent must provide
implementation-specific defaults for at least those objects
which it implements as read-only). If there is sufficient
information available, then the conceptual row is created, a
`noError' response is returned, the status column is set to
`active', and no further interactions are necessary (i.e.,
interactions 3 and 4 are skipped). If there is insufficient
information, then the conceptual row is not created, and the
set operation fails with an error of `inconsistentValue'.
On this error, the management station can issue a management
protocol retrieval operation to determine if this was
because it failed to specify a value for a required column,
or, because the selected instance of the status column
already existed. In the latter case, we return to
interaction 1. In the former case, the management station
can re-issue the set operation with the additional
information, or begin interaction 2 again using
`createAndWait' in order to negotiate creation of the
conceptual row.
NOTE WELL
Regardless of the method used to determine the column
requirements, it is possible that the management
station might deem a column necessary when, in fact,
the agent will not allow that particular columnar
instance to be created or written. In this case, the
management protocol set operation will fail with an
error such as `noCreation' or `notWritable'. In this
case, the management station decides whether it needs
to be able to set a value for that particular columnar
instance. If not, the management station re-issues the
management protocol set operation, but without setting
a value for that particular columnar instance;
otherwise, the management station aborts the row
creation algorithm.
Interaction 2b: Negotiating the Creation of the Conceptual
Row
The management station issues a management protocol set
operation which sets the desired instance of the status
column to `createAndWait'. If the agent is unwilling to
process a request of this sort, the set operation fails with
an error of `wrongValue'. (As a consequence, such an agent
must be prepared to accept a single management protocol set
operation, i.e., interaction 2a above, containing all of the
columns indicated by its column requirements.) Otherwise,
the conceptual row is created, a `noError' response is
returned, and the status column is immediately set to either
`notInService' or `notReady', depending on whether it has
sufficient information to make the conceptual row available
for use by the managed device. If there is sufficient
information available, then the status column is set to
`notInService'; otherwise, if there is insufficient
information, then the status column is set to `notReady'.
Regardless, we proceed to interaction 3.
Interaction 3: Initializing non-defaulted Objects
The management station must now determine the column
requirements. It issues a management protocol get operation
to examine all columns in the created conceptual row. In
the response, for each column, there are three possible
outcomes:
- a value is returned, indicating that the agent
implements the object-type associated with this column
and had sufficient information to provide a value. For
those columns to which the agent provides read-create
access (and for which the agent allows their values to
be changed after their creation), a value return tells
the management station that it may issue additional
management protocol set operations, if it desires, in
order to change the value associated with this column.
- the exception `noSuchInstance' is returned,
indicating that the agent implements the object-type
associated with this column, and that this column in at
least one conceptual row would be accessible in the MIB
view used by the retrieval were it to exist. However,
the agent does not have sufficient information to
provide a value, and until a value is provided, the
conceptual row may not be made available for use by the
managed device. For those columns to which the agent
provides read-create access, the `noSuchInstance'
exception tells the management station that it must
issue additional management protocol set operations, in
order to provide a value associated with this column.
- the exception `noSuchObject' is returned, indicating
that the agent does not implement the object-type
associated with this column or that there is no
conceptual row for which this column would be
accessible in the MIB view used by the retrieval. As
such, the management station can not issue any
management protocol set operations to create an
instance of this column.
If the value associated with the status column is
`notReady', then the management station must first deal with
all `noSuchInstance' columns, if any. Having done so, the
value of the status column becomes `notInService', and we
proceed to interaction 4.
Interaction 4: Making the Conceptual Row Available
Once the management station is satisfied with the values
associated with the columns of the conceptual row, it issues
a management protocol set operation to set the status column
to `active'. If the agent has sufficient information to
make the conceptual row available for use by the managed
device, the management protocol set operation succeeds (a
`noError' response is returned). Otherwise, the management
protocol set operation fails with an error of
`inconsistentValue'.
NOTE WELL
A conceptual row having a status column with value
`notInService' or `notReady' is unavailable to the
managed device. As such, it is possible for the
managed device to create its own instances during the
time between the management protocol set operation
which sets the status column to `createAndWait' and the
management protocol set operation which sets the status
column to `active'. In this case, when the management
protocol set operation is issued to set the status
column to `active', the values held in the agent
supersede those used by the managed device.
If the management station is prevented from setting the
status column to `active' (e.g., due to management station
or network failure) the conceptual row will be left in the
`notInService' or `notReady' state, consuming resources
indefinitely. The agent must detect conceptual rows that
have been in either state for an abnormally long period of
time and remove them. It is the responsibility of the
DESCRIPTION clause of the status column to indicate what an
abnormally long period of time would be. This period of
time should be long enough to allow for human response time
(including `think time') between the creation of the
conceptual row and the setting of the status to `active'.
In the absense of such information in the DESCRIPTION
clause, it is suggested that this period be approximately 5
minutes in length. This removal action applies not only to
newly-created rows, but also to previously active rows which
are set to, and left in, the notInService state for a
prolonged period exceeding that which is considered normal
for such a conceptual row.
Conceptual Row Suspension
When a conceptual row is `active', the management station
may issue a management protocol set operation which sets the
instance of the status column to `notInService'. If the
agent is unwilling to do so, the set operation fails with an
error of `wrongValue'. Otherwise, the conceptual row is
taken out of service, and a `noError' response is returned.
It is the responsibility of the DESCRIPTION clause of the
status column to indicate under what circumstances the
status column should be taken out of service (e.g., in order
for the value of some other column of the same conceptual
row to be modified).
Conceptual Row Deletion
For deletion of conceptual rows, a management protocol set
operation is issued which sets the instance of the status
column to `destroy'. This request may be made regardless of
the current value of the status column (e.g., it is possible
to delete conceptual rows which are either `notReady',
`notInService' or `active'.) If the operation succeeds,
then all instances associated with the conceptual row are
immediately removed."
SYNTAX INTEGER
{
active(1),
notInService(2),
notReady(3),
createAndGo(4),
createAndWait(5),
destroy(6)
}
-- the following two values are states:
-- these values may be read or written
-- the following value is a state:
-- this value may be read, but not written
-- the following three values are
-- actions: these values may be written,
-- but are never read
TimeStamp ::= TEXTUAL-CONVENTION
STATUS current
DESCRIPTION
"The value of the sysUpTime object at which a specific
occurrence happened. The specific occurrence must be
defined in the description of any object defined using this
type."
SYNTAX TimeTicks
--
-- Node definitions
--
-- 1.3.6.1.4.1.1379
cintelNS OBJECT IDENTIFIER ::= { enterprises 1379 }
END
--
-- CINTEL-MIB.my
--

Binary file not shown.