diff --git a/api/close.go b/api/close.go deleted file mode 100644 index f007fd5..0000000 --- a/api/close.go +++ /dev/null @@ -1,15 +0,0 @@ -package api - -import ( - "github.com/aceld/zinx/ziface" - "github.com/aceld/zinx/znet" -) - -// CloseApi 关闭连接API -type CloseApi struct { - znet.BaseRouter -} - -func (*CloseApi) Handle(request ziface.IRequest) { - request.GetConnection().Stop() -} diff --git a/api/heart_beat.go b/api/heart_beat.go deleted file mode 100644 index a668239..0000000 --- a/api/heart_beat.go +++ /dev/null @@ -1,42 +0,0 @@ -package api - -import ( - "github.com/aceld/zinx/ziface" - "github.com/aceld/zinx/zlog" - "github.com/aceld/zinx/znet" - "omc/omc" -) - -// HeartBeatApi 心跳请求 -type HeartBeatApi struct { - znet.BaseRouter -} - -func (*HeartBeatApi) Handle(request ziface.IRequest) { - // 解包 - msgBody := omc.MsgBody{ - RawData: request.GetData(), - Msg: make(map[string]string, 0), - } - if err := msgBody.Decode(); err != nil { - zlog.Ins().ErrorF("inlaid message body %s", err.Error()) - request.GetConnection().SendMsg(omc.AckHeartBeat, omc.ErrorMsg("ackHeartBeat", "", "inlaid message body")) - return - } - - reqId, ok := msgBody.Msg["reqId"] - if !ok { - zlog.Ins().ErrorF("missing parameter of message body") - request.GetConnection().SendMsg(omc.AckHeartBeat, omc.ErrorMsg("ackHeartBeat", "", "missing parameter of message body")) - return - } - - //ack - ackBody := omc.MsgBody{ - MsgName: "ackHeartBeat", - Msg: make(map[string]string, 0), - } - ackBody.Msg["reqId"] = reqId - ackBody.Pack() - request.GetConnection().SendMsg(omc.AckHeartBeat, ackBody.RawData) -} diff --git a/api/login.go b/api/login.go deleted file mode 100644 index 656f2a5..0000000 --- a/api/login.go +++ /dev/null @@ -1,176 +0,0 @@ -package api - -import ( - "encoding/hex" - "github.com/aceld/zinx/ziface" - "github.com/aceld/zinx/zlog" - "github.com/aceld/zinx/znet" - "github.com/google/uuid" - "omc/core" - "omc/omc" - "omc/service" - "strings" -) - -// LoginApi 登录API -type LoginApi struct { - znet.BaseRouter -} - -// Handle Login reqLoginAlarm;user=yiy;key=qw#$@;type=msg -func (*LoginApi) Handle(request ziface.IRequest) { - // 登录消息处理 - msgBody := omc.MsgBody{ - RawData: request.GetData(), - Msg: make(map[string]string, 0), - } - if err := msgBody.Decode(); err != nil { - zlog.Ins().ErrorF("inlaid message body %s", err.Error()) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "inlaid message body")) - return - } - - user, userOK := msgBody.Msg["user"] - pw, pwOK := msgBody.Msg["key"] - tp, tpOK := msgBody.Msg["type"] - if !userOK || !pwOK || !tpOK { - zlog.Ins().ErrorF("missing parameter of message body") - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "missing parameter of message body")) - return - } - m := core.GetManager(request.GetConnection().GetName()) - if m == nil { - zlog.Ins().ErrorF("server internal error") - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "server internal error")) - return - } - uID, err := request.GetConnection().GetProperty("UID") - if err != nil { - zlog.Ins().ErrorF("GetProperty UID error %s", err) - request.GetConnection().Stop() - return - } - - //登录信息check - if err := service.UserLogin(user, pw); err != nil { - zlog.Ins().ErrorF("LoginFail %s", err) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "Incorrect username and password")) - isClose, _ := m.LoginFail(uID.(string)) //登录错误超过3次,断开连接 - if isClose { - request.GetConnection().Stop() - return - } - return - } - - //manager 更新 - if err := m.LoginSuccess(uID.(string), user, tp); err != nil { - zlog.Ins().ErrorF("manager:%s", err) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", err.Error())) - return - } - zlog.Ins().InfoF("user login loginSuccess,username:%s, type:%s, channel:%s", user, tp, request.GetConnection().GetName()) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.SuccessMsg("ackLoginAlarm", "", "")) -} - -// CMCALoginSeq 登录API - -type CMCALoginSeq struct { - znet.BaseRouter -} - -//reqCMCALoginSeq - -func (*CMCALoginSeq) Handle(request ziface.IRequest) { - uid := uuid.New() - seqNo := hex.EncodeToString(uid[0:]) - seqNo = strings.ToUpper(seqNo) - //发送文件同步信息 - ackBody := omc.MsgBody{ - MsgName: "ackCMCALoginSeq", - Msg: make(map[string]string, 0), - } - ackBody.Msg["seqNo"] = seqNo - ackBody.Pack() - m := core.GetManager(request.GetConnection().GetName()) - uID, err := request.GetConnection().GetProperty("UID") - if err != nil { - zlog.Ins().ErrorF("GetProperty UID error %s", err) - request.GetConnection().Stop() - return - } - if m == nil { - zlog.Ins().ErrorF("server internal error") - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "server internal error")) - return - } - m.SetSeqNo(uID.(string), seqNo) - - request.GetConnection().SendMsg(omc.AckCMCALoginSeq, ackBody.RawData) -} - -// - -type CMCALoginAlarm struct { - znet.BaseRouter -} - -//reqCMCALoginSeq -//reqCMCALoginAlarm;user=yiy;key=12313121213123;cert=AAAAAAAAAA;type=msg - -func (*CMCALoginAlarm) Handle(request ziface.IRequest) { - // 登录消息处理 - msgBody := omc.MsgBody{ - RawData: request.GetData(), - Msg: make(map[string]string, 0), - } - if err := msgBody.Decode(); err != nil { - zlog.Ins().ErrorF("inlaid message body %s", err.Error()) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "inlaid message body")) - return - } - - user, userOK := msgBody.Msg["user"] - key, keyOK := msgBody.Msg["key"] - cert, certOK := msgBody.Msg["cert"] - tp, tpOK := msgBody.Msg["type"] - if !userOK || !keyOK || certOK || !tpOK { - zlog.Ins().ErrorF("missing parameter of message body") - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "missing parameter of message body")) - return - } - m := core.GetManager(request.GetConnection().GetName()) - if m == nil { - zlog.Ins().ErrorF("server internal error") - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "server internal error")) - return - } - uID, err := request.GetConnection().GetProperty("UID") - if err != nil { - zlog.Ins().ErrorF("GetProperty UID error %s", err) - request.GetConnection().Stop() - return - } - - //登录信息check - seqNo := m.GetUserByPID(uID.(string)).SeqNo - if ok, err := service.CMCALogin(seqNo, key, cert); !ok || err != nil { - zlog.Ins().ErrorF("LoginFail %s", err) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", "Incorrect username and password")) - isClose, _ := m.LoginFail(uID.(string)) //登录错误超过3次,断开连接 - if isClose { - request.GetConnection().Stop() - return - } - return - } - - //manager 更新 - if err := m.LoginSuccess(uID.(string), user, tp); err != nil { - zlog.Ins().ErrorF("manager:%s", err) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.ErrorMsg("ackLoginAlarm", "", err.Error())) - return - } - zlog.Ins().InfoF("user login loginSuccess,username:%s, type:%s, channel:%s", user, tp, request.GetConnection().GetName()) - request.GetConnection().SendMsg(omc.AckLoginAlarm, omc.SuccessMsg("ackLoginAlarm", "", "")) -} diff --git a/api/req_sync_alarm.go b/api/req_sync_alarm.go deleted file mode 100644 index 6454adb..0000000 --- a/api/req_sync_alarm.go +++ /dev/null @@ -1,61 +0,0 @@ -package api - -import ( - "github.com/aceld/zinx/ziface" - "github.com/aceld/zinx/zlog" - "github.com/aceld/zinx/znet" - "omc/core" - "omc/omc" - "omc/service" - "strconv" -) - -// SyncAlarmApi 消息方式同步告警请求 -type SyncAlarmApi struct { - znet.BaseRouter -} - -func (*SyncAlarmApi) Handle(request ziface.IRequest) { - // 消息处理 - checker := []string{"reqId", "alarmSeq"} - msg, err := core.APIDecode(request, checker) - if err != nil { - zlog.Ins().ErrorF("inlaid message body %s", err.Error()) - request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, omc.ErrorMsg("ackSyncAlarmMsg", "", err.Error())) - return - } - //管理模块 - m := core.GetManager(request.GetConnection().GetName()) - if m == nil { - zlog.Ins().ErrorF("server internal error") - request.GetConnection().SendMsg(omc.AckSyncAlarmFile, omc.ErrorMsg("ackSyncAlarmFile", msg.Msg["reqId"], "server internal error")) - return - } - - // 检查用户是否登录 - u := m.GetUserByPID(msg.UID) - if !u.LoginState || u.AlarmType != omc.MSG { - zlog.Ins().ErrorF("no permissions ") - request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, omc.ErrorMsg("ackSyncAlarmMsg", msg.Msg["reqId"], "no permissions")) - return - } - - alarmSeq, err := strconv.Atoi(msg.Msg["alarmSeq"]) - if err != nil || alarmSeq < 1 { - zlog.Ins().ErrorF("invalid parameter of message body") - request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, omc.ErrorMsg("ackSyncAlarmMsg", msg.Msg["reqId"], "invalid parameter of message body")) - return - } - - //check alarmSeq 是否存在 - neBind, _ := core.ConvertBindFlag(m.BindFlag) - alarms, _ := service.GetRealTimeAlarm(neBind.NeType, neBind.NeId, int32(alarmSeq)) - if len(alarms) == 0 { - request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, omc.ErrorMsg("ackSyncAlarmMsg", msg.Msg["reqId"], "alarm seq does not exist")) - return - } - //更新实时上报的alarm seq - m.UpdateAlarmSeq(int32(alarmSeq)) - request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, omc.SuccessMsg("ackSyncAlarmMsg", msg.Msg["reqId"], "")) - -} diff --git a/assets/nbi_alarm/nbi_alarm.2023-08-21-205716.zip b/assets/nbi_alarm/nbi_alarm.2023-08-21-205716.zip new file mode 100644 index 0000000..2136736 Binary files /dev/null and b/assets/nbi_alarm/nbi_alarm.2023-08-21-205716.zip differ diff --git a/client_robot.go b/client_robot.go index 7ab6376..c041c19 100644 --- a/client_robot.go +++ b/client_robot.go @@ -6,15 +6,15 @@ import ( "encoding/hex" "errors" "fmt" + "io" + "net" + "omc/handle/model" + "time" + "github.com/aceld/zinx/zconf" "github.com/aceld/zinx/zlog" "gorm.io/driver/mysql" "gorm.io/gorm" - "io" - "net" - "omc/model" - "omc/omc" - "time" ) type Message struct { @@ -156,7 +156,7 @@ func (this *TcpClient) Start() { //data = "reqSyncAlarmFile;reqId=35;alarmSeq=2000;syncSource=1" //data = "reqSyncAlarmFile;reqId=33;startTime=2023-01-08 00:00:00;syncSource=0" data = "reqSyncAlarmFile;reqId=34;startTime=2023-01-08 16:07:00;endTime=2023-07-19 23:59:59;syncSource=1" - this.SendMsg(omc.ReqSyncAlarmFile, []byte(data)) + this.SendMsg(11, []byte(data)) go this.Receive() } diff --git a/conf/global.go b/conf/global.go index 6d966a7..befca11 100644 --- a/conf/global.go +++ b/conf/global.go @@ -11,14 +11,16 @@ import ( "github.com/aceld/zinx/zlog" ) +type Channel struct { + TCPPort int `json:"tcp_port"` //当前通道的TCP监听端口 + BindFlag string `json:"bind_flag"` //当前通道bind 的网元信息 + Province string `json:"province"` //网元所在省份 + DeviceCode string `json:"device_code"` //主机编码 四位,每1位可用0-9、A-Z编码 +} + type Config struct { // 网元通道 - Channel []struct { - TCPPort int `json:"tcp_port"` //当前通道的TCP监听端口 - BindFlag string `json:"bind_flag"` //当前通道bind 的网元信息 - Province string `json:"province"` //网元所在省份 - DeviceCode string `json:"device_code"` //主机编码 四位,每1位可用0-9、A-Z编码 - } `json:"channel"` + Channel []Channel `json:"channel"` // 数据库连接 Mysql string `json:"mysql"` diff --git a/conf/nbi_alarm_agent.json b/conf/nbi_alarm_agent.json index a66a477..cb6a5fc 100644 --- a/conf/nbi_alarm_agent.json +++ b/conf/nbi_alarm_agent.json @@ -2,39 +2,9 @@ "channel": [ { "tcp_port": 31232, - "bind_flag": "SMF#1101RJHX1SMF01", + "bind_flag": "SMF#SZ_02", "province": "BJ", "device_code": "0001" - }, - { - "tcp_port": 31233, - "bind_flag": "UDM#1101RJHX1UDM01", - "province": "BJ", - "device_code": "0002" - }, - { - "tcp_port": 31234, - "bind_flag": "AUSF#1101RJHX1AUF01", - "province": "BJ", - "device_code": "0003" - }, - { - "tcp_port": 31235, - "bind_flag": "AMF#1101RJHX1AMF01", - "province": "BJ", - "device_code": "0004" - }, - { - "tcp_port": 31236, - "bind_flag": "UPF#1101RJHX1UPF01", - "province": "BJ", - "device_code": "0005" - }, - { - "tcp_port": 31237, - "bind_flag": "AMF#1101RJHX1AMF03", - "province": "BJ", - "device_code": "0006" } ], diff --git a/core/consts/consts.go b/core/consts/consts.go new file mode 100644 index 0000000..a5ba95f --- /dev/null +++ b/core/consts/consts.go @@ -0,0 +1,7 @@ +package consts + +//定义user type +const ( + MSG = "msg" + FILE = "ftp" +) diff --git a/db/mysql.go b/core/db/mysql.go similarity index 99% rename from db/mysql.go rename to core/db/mysql.go index b503d8e..26c4135 100644 --- a/db/mysql.go +++ b/core/db/mysql.go @@ -1,10 +1,11 @@ package db import ( + "omc/conf" + "github.com/aceld/zinx/zlog" "gorm.io/driver/mysql" "gorm.io/gorm" - "omc/conf" ) var Client *gorm.DB diff --git a/decoder/decode_omc.go b/core/decoder/decode_omc.go similarity index 100% rename from decoder/decode_omc.go rename to core/decoder/decode_omc.go diff --git a/dpack/datapack_omc.go b/core/dpack/datapack_omc.go similarity index 100% rename from dpack/datapack_omc.go rename to core/dpack/datapack_omc.go diff --git a/core/emun/orig_severity.go b/core/emun/orig_severity.go new file mode 100644 index 0000000..3b726bd --- /dev/null +++ b/core/emun/orig_severity.go @@ -0,0 +1,16 @@ +package emun + +func OrigSeverity(os string) int32 { + switch os { + case "Critical": + return 1 + case "Major": + return 2 + case "Minor": + return 3 + case "Warning": + return 4 + default: + return 0 + } +} diff --git a/lib/file.go b/core/file/file.go similarity index 99% rename from lib/file.go rename to core/file/file.go index 883d040..6d02b14 100644 --- a/lib/file.go +++ b/core/file/file.go @@ -1,4 +1,4 @@ -package lib +package file import ( "os" diff --git a/lib/file_test.go b/core/file/file_test.go similarity index 96% rename from lib/file_test.go rename to core/file/file_test.go index a2b9890..faa1bdd 100644 --- a/lib/file_test.go +++ b/core/file/file_test.go @@ -1,4 +1,4 @@ -package lib +package file import ( "fmt" diff --git a/core/heart_beat.go b/core/heart_beat/heart_beat.go similarity index 92% rename from core/heart_beat.go rename to core/heart_beat/heart_beat.go index 5ac2967..ee54237 100644 --- a/core/heart_beat.go +++ b/core/heart_beat/heart_beat.go @@ -1,10 +1,12 @@ -package core +package heartbeat import ( "github.com/aceld/zinx/ziface" "github.com/aceld/zinx/zlog" ) +var HeadBeatMsgID uint32 = 255 + // MyHeartBeatMsg 用户自定义的心跳检测消息处理方法 func MyHeartBeatMsg(conn ziface.IConnection) []byte { return []byte("heartbeat, I am server, I am alive") diff --git a/core/interceptor/global.go b/core/interceptor/global.go new file mode 100644 index 0000000..606d4b0 --- /dev/null +++ b/core/interceptor/global.go @@ -0,0 +1,42 @@ +package interceptor + +import ( + "encoding/hex" + "fmt" + "omc/core/parse" + "time" + + "github.com/aceld/zinx/ziface" +) + +type GlobalInterceptor struct{} + +func (m *GlobalInterceptor) Intercept(chain ziface.IChain) ziface.IcResp { + request := chain.Request() //从责任链中获取当前拦截器的输入数据 + + // 这一层是自定义拦截器处理逻辑,这里只是简单打印输入 + iRequest := request.(ziface.IRequest) //注意:由于Zinx的Request类型,这里需要做一下断言转换 + + fmt.Println("\n\n=========自定义拦截器=====") + + body, err := parse.RequestBodyDecode(iRequest, nil) + fmt.Printf("消息ID: %v \n", iRequest.GetMsgID()) + fmt.Printf("原始数据: %v \n", body.RawData) + fmt.Printf("原始字符: %v \n", hex.EncodeToString(body.RawData)) + fmt.Printf("原始字符: %v \n", string(body.RawData)) + fmt.Printf("用户ID: %v \n", body.UID) + fmt.Printf("收到消息: %v %v \n", body.Name, body.Data) + fmt.Printf("错误:%v \n", err) + + // return chain.Proceed(chain.Request()) //进入并执行下一个拦截器 + + iMessage := chain.GetIMessage() + resp := chain.ProceedWithIMessage(iMessage, iRequest) + fmt.Printf("目标消息ID: %v \n", iMessage.GetMsgID()) + fmt.Printf("收到消息长度: %v \n", iMessage.GetDataLen()) + fmt.Printf("信息时间:%v \n", time.Now().String()) + + fmt.Print("=========自定义拦截器=====\n\n\n") + + return resp +} diff --git a/core/manage/manage.go b/core/manage/manage.go new file mode 100644 index 0000000..177b5f3 --- /dev/null +++ b/core/manage/manage.go @@ -0,0 +1,51 @@ +package manage + +import ( + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" +) + +// OnConnectionAdd 当客户端建立连接的时候的hook函数 +func OnConnectionAdd(conn ziface.IConnection) { + //创建一个user + + user := NewUser(conn, conn.RemoteAddrString()) + //将当前新上线玩家添加到ChannelManager中 + m := GetManager(conn.GetName()) + if m == nil { + zlog.Ins().ErrorF("server internal error in GetManager") + conn.Stop() + return + } + m.AddUser(user) + + //将该连接绑定属性PID + conn.SetProperty("UID", user.UID) + + zlog.Ins().InfoF("====> User uID = %s", user.UID, " arrived ====", "") +} + +// OnConnectionLost 当客户端断开连接的时候的hook函数 +func OnConnectionLost(conn ziface.IConnection) { + //获取当前连接的PID属性 + uID, _ := conn.GetProperty("UID") + var userID string + if uID != nil { + userID = uID.(string) + } + + //根据pID获取对应usr + m := GetManager(conn.GetName()) + if m == nil { + zlog.Ins().ErrorF("server internal error in GetManager") + return + } + user := m.GetUserByPID(userID) + + //触发玩家下线业务 + if user != nil { + user.LostConnection(m) + } + + zlog.Ins().InfoF("====> User %s-%s", user.UID, user.UserName, " left =====") +} diff --git a/core/user.go b/core/manage/user.go similarity index 97% rename from core/user.go rename to core/manage/user.go index cc62852..6c8fb4b 100644 --- a/core/user.go +++ b/core/manage/user.go @@ -1,7 +1,8 @@ -package core +package manage import ( "fmt" + "github.com/aceld/zinx/ziface" "github.com/google/uuid" ) @@ -46,5 +47,4 @@ func (p *User) SendMsg(msgID uint32, msg []byte) { return } - return } diff --git a/core/user_manager.go b/core/manage/user_manager.go similarity index 92% rename from core/user_manager.go rename to core/manage/user_manager.go index 3504bfb..b14f19d 100644 --- a/core/user_manager.go +++ b/core/manage/user_manager.go @@ -1,15 +1,17 @@ -package core +package manage import ( "errors" - "github.com/aceld/zinx/zlog" - "omc/db" - "omc/model" - "omc/omc" - "omc/service" + "omc/core/consts" + "omc/core/db" + "omc/core/parse" + "omc/handle/model" + "omc/handle/service" "strings" "sync" "time" + + "github.com/aceld/zinx/zlog" ) /* @@ -65,7 +67,7 @@ func (wm *ChannelManager) Talk(msgID uint32, msg []byte) { //3. 向所有的user发送消息 for _, user := range users { - if user.LoginState && user.AlarmType == omc.MSG { + if user.LoginState && user.AlarmType == consts.MSG { user.SendMsg(msgID, msg) } } @@ -77,7 +79,7 @@ func (wm *ChannelManager) LoginSuccess(UID, name, tp string) error { defer wm.pLock.Unlock() //判断是否重复登录 for _, v := range wm.User { - if v.UserName == name && v.AlarmType == tp && v.LoginState == true { + if v.UserName == name && v.AlarmType == tp && v.LoginState { return errors.New("repeat login for the same account") } } @@ -147,7 +149,7 @@ func (wm *ChannelManager) GetAllUser() []*User { //添加切片 for _, v := range wm.User { - if v.LoginState && v.AlarmType == omc.MSG { + if v.LoginState && v.AlarmType == consts.MSG { User = append(User, v) } } @@ -162,7 +164,7 @@ func (wm *ChannelManager) RealTimeAlarm() { //查询 var newAlarmSeq = wm.AlarmSeq var alarms []service.OmcAlarm - neBind, _ := ConvertBindFlag(wm.BindFlag) + neBind, _ := parse.ConvertBindFlag(wm.BindFlag) if wm.AlarmSeq == 0 { newAlarmSeq = service.GetLastAlarmSeq(neBind.NeType, neBind.NeId) @@ -180,7 +182,7 @@ func (wm *ChannelManager) RealTimeAlarm() { } var users []string for _, user := range wm.User { - if user.LoginState && user.AlarmType == omc.MSG { + if user.LoginState && user.AlarmType == consts.MSG { userInfo := strings.Join([]string{user.UserName, user.RemoteIp}, ";") users = append(users, userInfo) } @@ -220,7 +222,7 @@ func (wm *ChannelManager) SendAlarm(alarms []service.OmcAlarm) error { //生产告警内容 data := service.GenAlarm(v) //发送告警内容 - wm.Talk(omc.RealTimeAlarm, data) + wm.Talk(0, data) } return nil } diff --git a/core/model/body.go b/core/model/body.go new file mode 100644 index 0000000..d8da77d --- /dev/null +++ b/core/model/body.go @@ -0,0 +1,9 @@ +package model + +// 请求数据 +type Body struct { + UID string // 连接实例ID + RawData []byte // 原始数据 + Name string // 请求名 + Data map[string]string // 数据Key +} diff --git a/core/parse/parse.go b/core/parse/parse.go new file mode 100644 index 0000000..c570f9b --- /dev/null +++ b/core/parse/parse.go @@ -0,0 +1,110 @@ +package parse + +import ( + "errors" + "fmt" + "omc/core/model" + "strings" + + "github.com/aceld/zinx/ziface" +) + +// 网元类型#网元标记 +type NeBind struct { + NeType string + NeId string +} + +// 转换解析服务端绑定的网元 +func ConvertBindFlag(bindFlag string) (NeBind, error) { + var neBind NeBind + nb := strings.Split(bindFlag, "#") + if len(nb) != 2 { + return neBind, errors.New("ne bind flag invalid") + } + neBind.NeType = nb[0] + neBind.NeId = nb[1] + return neBind, nil +} + +// RequestBodyDecode 请求消息解析 +// checker 检查参数必传 +func RequestBodyDecode(request ziface.IRequest, checker []string) (model.Body, error) { + // 消息处理 + body := model.Body{} + err := Decode(request.GetData(), &body) + if err != nil { + return body, errors.New("inlaid message body") + } + + // 检查key + if len(checker) > 0 { + for _, v := range checker { + if _, ok := body.Data[v]; !ok { + return body, errors.New("missing parameter of message body : " + v) + } + } + } + + // 当前连接实例ID + uID, err := request.GetConnection().GetProperty("UID") + if err != nil { + request.GetConnection().Stop() + return body, errors.New("server internal error") + } + body.UID = uID.(string) + return body, nil +} + +// Decode 数据解析 +// reqLoginAlarm;user=yiy;key=qw#$@;type=msg +func Decode(data []byte, body *model.Body) error { + body.RawData = data + + multi := strings.Split(string(data), ";") + if len(multi) < 1 { + return errors.New("invalid msg body") + } + + // 获取函数名 + if multi[0] != "" { + name := multi[0] + + idx := strings.LastIndex(name, "\x14") + if idx == -1 { + idx = strings.LastIndex(name, "\x00") + } + + if idx > 0 { + name = name[idx+1:] + name = strings.Replace(name, "\"", "", 1) + name = strings.Replace(name, "'", "", 1) + name = strings.Replace(name, "#", "", 1) + } + body.Name = name + } + + // 解析data KEY + body.Data = make(map[string]string) + for i := 1; i < len(multi); i++ { + m := strings.Split(multi[i], "=") + if len(m) != 2 { + return errors.New("invalid msg body") + } + body.Data[m[0]] = m[1] + } + + return nil +} + +// Pack 数据压缩 +func Pack(name string, data map[string]string) []byte { + var multi []string + multi = append(multi, name) + for i, v := range data { + item := fmt.Sprintf("%s=%s", i, v) + multi = append(multi, item) + } + raw := strings.Join(multi, ";") + return []byte(raw) +} diff --git a/core/result.go b/core/result.go new file mode 100644 index 0000000..84b0734 --- /dev/null +++ b/core/result.go @@ -0,0 +1,34 @@ +package core + +import ( + "omc/core/parse" +) + +// Result +// 配合 request.GetConnection().SendMsg() +func Result(name string, data map[string]string) []byte { + return parse.Pack(name, data) +} + +// ResultError ackLoginAlarm;result=fail;resDesc=username-error +// request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, core.ResultError("ackSyncAlarmMsg", err.Error(), "")) +func ResultError(name string, desc, reqID string) []byte { + data := map[string]string{ + "result": "fail", + "reqId": reqID, + "resDesc": desc, + } + + return Result(name, data) +} + +// request.GetConnection().SendMsg(omc.AckSyncAlarmMsg, core.ResultSuccess("ackSyncAlarmMsg", err.Error(), "")) +func ResultSuccess(name string, desc, reqID string) []byte { + data := map[string]string{ + "result": "succ", + "reqId": reqID, + "resDesc": desc, + } + + return Result(name, data) +} diff --git a/core/utils.go b/core/utils.go deleted file mode 100644 index 9c436a8..0000000 --- a/core/utils.go +++ /dev/null @@ -1,48 +0,0 @@ -package core - -import ( - "errors" - "github.com/aceld/zinx/ziface" - "omc/omc" - "strings" -) - -type NeBind struct { - NeType string - NeId string -} - -func ConvertBindFlag(bindFlag string) (NeBind, error) { - var neBind NeBind - nb := strings.Split(bindFlag, "#") - if len(nb) != 2 { - return neBind, errors.New("ne bind flag invalid") - } - neBind.NeType = nb[0] - neBind.NeId = nb[1] - return neBind, nil -} - -// APIDecode 消息解析 -func APIDecode(request ziface.IRequest, checker []string) (*omc.MsgBody, error) { - // 消息处理 - msgBody := omc.MsgBody{ - RawData: request.GetData(), - Msg: make(map[string]string, 0), - } - if err := msgBody.Decode(); err != nil { - return nil, errors.New("inlaid message body") - } - for _, v := range checker { - if _, ok := msgBody.Msg[v]; !ok { - return nil, errors.New("missing parameter of message body") - } - } - uID, err := request.GetConnection().GetProperty("UID") - if err != nil { - request.GetConnection().Stop() - return nil, errors.New("server internal error") - } - msgBody.UID = uID.(string) - return &msgBody, nil -} diff --git a/lib/password.go b/core/utils/bcrypt.go similarity index 96% rename from lib/password.go rename to core/utils/bcrypt.go index 7ebf1eb..75aa7ae 100644 --- a/lib/password.go +++ b/core/utils/bcrypt.go @@ -1,4 +1,4 @@ -package lib +package utils import "golang.org/x/crypto/bcrypt" diff --git a/core/utils/strrand.go b/core/utils/strrand.go new file mode 100644 index 0000000..14d2a42 --- /dev/null +++ b/core/utils/strrand.go @@ -0,0 +1,25 @@ +package utils + +import ( + "math/rand" + "time" +) + +// 生成编号 SeqNo 0-9A-Z +func SeqNo(length int) string { + items := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"} + + // 创建基于时间的随机生成器 + source := rand.NewSource(time.Now().UnixNano()) + rng := rand.New(source) + + // 生成32位长度的字符串值 + result := "" + for i := 0; i < length; i++ { + randomIndex := rng.Intn(len(items)) + randomItem := items[randomIndex] + result += randomItem + } + + return result +} diff --git a/handle/api/close_conn_alarm.go b/handle/api/close_conn_alarm.go new file mode 100644 index 0000000..b000215 --- /dev/null +++ b/handle/api/close_conn_alarm.go @@ -0,0 +1,22 @@ +package api + +import ( + "omc/core" + + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/znet" +) + +var CloseConnAlarmMsgID uint32 = 10 +var CloseConnAlarmMsgType uint32 = 10 +var CloseConnAlarmMsgName string = "closeConnAlarm" + +// closeConnAlarm 关闭连接 +type CloseConnAlarm struct { + znet.BaseRouter +} + +func (s *CloseConnAlarm) Handle(request ziface.IRequest) { + request.GetConnection().Stop() + request.GetConnection().SendMsg(CloseConnAlarmMsgType, core.ResultSuccess(CloseConnAlarmMsgName, "", "")) +} diff --git a/handle/api/req_cmca_login_alarm.go b/handle/api/req_cmca_login_alarm.go new file mode 100644 index 0000000..34b8103 --- /dev/null +++ b/handle/api/req_cmca_login_alarm.go @@ -0,0 +1,46 @@ +package api + +import ( + "omc/core" + "omc/core/manage" + "omc/core/utils" + + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" + "github.com/aceld/zinx/znet" +) + +var ReqCMCALoginAlarmMsgID uint32 = 11 +var ReqCMCALoginAlarmMsgType uint32 = 11 +var ReqCMCALoginAlarmMsgName string = "reqCMCALoginAlarm" + +// reqCMCALoginAlarm CMCA认证方式登录 +type ReqCMCALoginAlarm struct { + znet.BaseRouter +} + +func (*ReqCMCALoginAlarm) Handle(request ziface.IRequest) { + + // 获取当前请求的通道 + m := manage.GetManager(request.GetConnection().GetName()) + if m == nil { + zlog.Ins().ErrorF("server internal error") + request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.ResultError(ReqLoginAlarmMsgName, "server internal error", "")) + return + } + uid, err := request.GetConnection().GetProperty("UID") + if err != nil { + zlog.Ins().ErrorF("GetProperty UID error %s", err) + request.GetConnection().Stop() + return + } + // seqNo 32位长度 0-9A-Z + seqNo := utils.SeqNo(32) + m.SetSeqNo(uid.(string), seqNo) + + // 发送信息 + msgData := map[string]string{ + "seqNo": seqNo, + } + request.GetConnection().SendMsg(ReqCMCALoginAlarmMsgType, core.Result(ReqCMCALoginAlarmMsgName, msgData)) +} diff --git a/handle/api/req_cmca_login_seq copy.go b/handle/api/req_cmca_login_seq copy.go new file mode 100644 index 0000000..e72870a --- /dev/null +++ b/handle/api/req_cmca_login_seq copy.go @@ -0,0 +1,83 @@ +package api + +// import ( +// "omc/core" +// "omc/core/manage" +// "omc/core/parse" +// "omc/handle/service" + +// "github.com/aceld/zinx/ziface" +// "github.com/aceld/zinx/zlog" +// "github.com/aceld/zinx/znet" +// ) + +// var ReqCMCALoginSeqMsgID uint32 = 12 +// var ReqCMCALoginSeqMsgType uint32 = 13 +// var ReqCMCALoginSeqMsgName string = "ackCMCALoginSeq" + +// // reqCMCALoginSeq CMCA认证方式登录随机码 +// type ReqCMCALoginSeq struct { +// znet.BaseRouter +// } + +// // reqCMCALoginAlarm;user=omc;key=base64Key;cert=cer;type=msg" +// func (s *ReqCMCALoginSeq) Handle(request ziface.IRequest) { +// // 登录消息处理 +// body, err := parse.RequestBodyDecode(request, []string{"user", "key", "cert", "type"}) +// if err != nil { +// zlog.Ins().ErrorF("inlaid message body %s", err.Error()) +// request.GetConnection().SendMsg(ReqCMCALoginSeqMsgType, core.ResultError(ReqCMCALoginSeqMsgName, err.Error(), "")) +// return +// } + +// // 获取当前请求的通道 +// m := manage.GetManager(request.GetConnection().GetName()) +// if m == nil { +// zlog.Ins().ErrorF("server internal error") +// request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.ResultError(ReqLoginAlarmMsgName, "server internal error", "")) +// return +// } +// uid, err := request.GetConnection().GetProperty("UID") +// if err != nil { +// zlog.Ins().ErrorF("GetProperty UID error %s", err) +// request.GetConnection().Stop() +// return +// } + +// // 账户和消息类型 +// username := body.Data["key"] +// tp := body.Data["type"] + +// //登录信息check +// seqNo := m.GetUserByPID(uid.(string)).SeqNo +// if ok, err := service.CMCALogin(seqNo, username, body.Data["cert"]); !ok || err != nil { +// zlog.Ins().ErrorF("LoginFail %s", err) +// request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.Result(ReqLoginAlarmMsgName, map[string]string{ +// "result": "autherror", +// "resDesc": err.Error(), +// })) +// // 已登录的,登录错误超过3次,断开连接 +// if uid != nil || uid != "" { +// isClose, _ := m.LoginFail(uid.(string)) +// if isClose { +// request.GetConnection().Stop() +// return +// } +// } +// return +// } + +// // manager 用户登录更新 +// err = m.LoginSuccess(uid.(string), username, tp) +// if err != nil { +// zlog.Ins().ErrorF("manager:%s", err) +// request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.Result(ReqLoginAlarmMsgName, map[string]string{ +// "result": "autherror", +// "resDesc": err.Error(), +// })) +// return +// } + +// zlog.Ins().InfoF("user login loginSuccess,username:%s, type:%s, channel:%s", username, tp, request.GetConnection().GetName()) +// request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.ResultSuccess(ReqLoginAlarmMsgName, "", "")) +// } diff --git a/handle/api/req_cmca_login_seq.go b/handle/api/req_cmca_login_seq.go new file mode 100644 index 0000000..2ea2456 --- /dev/null +++ b/handle/api/req_cmca_login_seq.go @@ -0,0 +1,47 @@ +package api + +import ( + "omc/core" + "omc/core/manage" + "omc/core/utils" + + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" + "github.com/aceld/zinx/znet" +) + +var ReqCMCALoginSeqMsgID uint32 = 12 +var ReqCMCALoginSeqMsgType uint32 = 13 +var ReqCMCALoginSeqMsgName string = "ackCMCALoginSeq" + +// reqCMCALoginSeq CMCA认证方式登录随机码 +type ReqCMCALoginSeq struct { + znet.BaseRouter +} + +// reqCMCALoginAlarm;user=omc;key=base64Key;cert=cer;type=msg" +func (s *ReqCMCALoginSeq) Handle(request ziface.IRequest) { + + // 获取当前请求的通道 + m := manage.GetManager(request.GetConnection().GetName()) + if m == nil { + zlog.Ins().ErrorF("server internal error") + request.GetConnection().SendMsg(ReqCMCALoginSeqMsgType, core.ResultError(ReqCMCALoginSeqMsgName, "server internal error", "")) + return + } + uid, err := request.GetConnection().GetProperty("UID") + if err != nil { + zlog.Ins().ErrorF("GetProperty UID error %s", err) + request.GetConnection().Stop() + return + } + // seqNo 32位长度 0-9A-Z + seqNo := utils.SeqNo(32) + m.SetSeqNo(uid.(string), seqNo) + + // 发送信息 + msgData := map[string]string{ + "seqNo": seqNo, + } + request.GetConnection().SendMsg(ReqCMCALoginSeqMsgType, core.Result(ReqCMCALoginSeqMsgName, msgData)) +} diff --git a/handle/api/req_heart_beat.go b/handle/api/req_heart_beat.go new file mode 100644 index 0000000..61923cb --- /dev/null +++ b/handle/api/req_heart_beat.go @@ -0,0 +1,40 @@ +package api + +import ( + "omc/core" + "omc/core/parse" + + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" + "github.com/aceld/zinx/znet" +) + +var ReqHeartBeatMsgID uint32 = 8 +var ReqHeartBeatMsgType uint32 = 9 +var ReqHeartBeatName string = "ackHeartBeat" + +// ReqHeartBeat 心跳 +type ReqHeartBeat struct { + znet.BaseRouter +} + +// reqHeartBeat;reqId=12 +func (s *ReqHeartBeat) Handle(request ziface.IRequest) { + // 解包 + body, err := parse.RequestBodyDecode(request, nil) + if err != nil { + zlog.Ins().ErrorF("inlaid message body %s", err.Error()) + request.GetConnection().SendMsg(ReqHeartBeatMsgType, core.ResultError(ReqHeartBeatName, "inlaid message body", "")) + return + } + + reqId, ok := body.Data["reqId"] + if !ok { + zlog.Ins().ErrorF("missing parameter of message body") + request.GetConnection().SendMsg(ReqHeartBeatMsgType, core.ResultError(ReqHeartBeatName, "missing parameter of message body", "")) + return + } + + //ack + request.GetConnection().SendMsg(ReqHeartBeatMsgType, core.ResultSuccess(ReqHeartBeatName, "ok", reqId)) +} diff --git a/handle/api/req_login_alarm.go b/handle/api/req_login_alarm.go new file mode 100644 index 0000000..291ffcc --- /dev/null +++ b/handle/api/req_login_alarm.go @@ -0,0 +1,81 @@ +package api + +import ( + "omc/core" + "omc/core/manage" + "omc/core/parse" + "omc/handle/service" + + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" + "github.com/aceld/zinx/znet" +) + +var ReqLoginAlarmMsgID uint32 = 1 +var ReqLoginAlarmMsgType uint32 = 2 +var ReqLoginAlarmMsgName string = "ackLoginAlarm" + +// reqLoginAlarm 登录 +type ReqLoginAlarm struct { + znet.BaseRouter +} + +// reqLoginAlarm;user=omc;key=omc;type=msg +func (s *ReqLoginAlarm) Handle(request ziface.IRequest) { + // 登录消息处理 + body, err := parse.RequestBodyDecode(request, []string{"user", "key", "type"}) + // 账户密码 + username := body.Data["user"] + key := body.Data["key"] + if err != nil || username == "" || key == "" { + zlog.Ins().ErrorF("inlaid message body %s", err.Error()) + request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.ResultError(ReqLoginAlarmMsgName, "inlaid message body", "")) + return + } + + // 获取当前请求的通道 + m := manage.GetManager(request.GetConnection().GetName()) + if m == nil { + zlog.Ins().ErrorF("server internal error") + request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.ResultError(ReqLoginAlarmMsgName, "server internal error", "")) + return + } + uid, err := request.GetConnection().GetProperty("UID") + if err != nil { + zlog.Ins().ErrorF("GetProperty UID error %s", err) + request.GetConnection().Stop() + return + } + + // 登录信息 + err = service.UserLogin(username, key) + if err != nil { + zlog.Ins().ErrorF("LoginFail %s", err) + request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.Result(ReqLoginAlarmMsgName, map[string]string{ + "result": "autherror", + "resDesc": err.Error(), + })) + // 已登录的,登录错误超过3次,断开连接 + if uid != nil || uid != "" { + isClose, _ := m.LoginFail(uid.(string)) + if isClose { + request.GetConnection().Stop() + return + } + } + return + } + + // manager 用户登录更新 + err = m.LoginSuccess(uid.(string), username, key) + if err != nil { + zlog.Ins().ErrorF("manager:%s", err) + request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.Result(ReqLoginAlarmMsgName, map[string]string{ + "result": "autherror", + "resDesc": err.Error(), + })) + return + } + zlog.Ins().InfoF("user login loginSuccess,username:%s, type:%s, channel:%s", username, key, request.GetConnection().GetName()) + request.GetConnection().SendMsg(ReqLoginAlarmMsgType, core.ResultSuccess(ReqLoginAlarmMsgName, "", "")) +} diff --git a/api/req_sync_alarm_file.go b/handle/api/req_sync_alarm_file.go similarity index 50% rename from api/req_sync_alarm_file.go rename to handle/api/req_sync_alarm_file.go index bb54b62..7953377 100644 --- a/api/req_sync_alarm_file.go +++ b/handle/api/req_sync_alarm_file.go @@ -2,47 +2,56 @@ package api import ( "fmt" + "omc/conf" + "omc/core" + "omc/core/consts" + "omc/core/file" + "omc/core/manage" + "omc/core/parse" + "omc/handle/service" + "strconv" + "time" + "github.com/aceld/zinx/ziface" "github.com/aceld/zinx/zlog" "github.com/aceld/zinx/znet" - "omc/conf" - "omc/core" - "omc/lib" - "omc/omc" - "omc/service" - "strconv" - "time" ) +var ackSyncAlarmFileMsgID uint32 = 6 +var ackSyncAlarmFileMsgName string = "ackSyncAlarmFile" + // SyncAlarmFileApi 文件方式同步告警请求 type SyncAlarmFileApi struct { znet.BaseRouter } // Handle -//reqSyncAlarmFile;reqId=33;startTime=2014-11-27 10:00:00;endTime=2014-11-27 10:30:00; syncSource =0 +// reqSyncAlarmFile;reqId=33;startTime=2014-11-27 10:00:00;endTime=2014-11-27 10:30:00; syncSource =0 func (*SyncAlarmFileApi) Handle(request ziface.IRequest) { // 消息处理 checker := []string{"reqId", "syncSource"} - msg, err := core.APIDecode(request, checker) + body, err := parse.RequestBodyDecode(request, checker) if err != nil { zlog.Ins().ErrorF("inlaid message body %s", err.Error()) - request.GetConnection().SendMsg(omc.AckSyncAlarmFile, omc.ErrorMsg("ackSyncAlarmFile", "", err.Error())) + request.GetConnection().SendMsg(ackSyncAlarmFileMsgID, core.ResultError(ackSyncAlarmFileMsgName, err.Error(), "")) return } + + reqId := body.Data["reqId"] + //管理模块 - m := core.GetManager(request.GetConnection().GetName()) + m := manage.GetManager(request.GetConnection().GetName()) if m == nil { zlog.Ins().ErrorF("server internal error") - request.GetConnection().SendMsg(omc.AckSyncAlarmFile, omc.ErrorMsg("ackSyncAlarmFile", msg.Msg["reqId"], "server internal error")) + request.GetConnection().SendMsg(ackSyncAlarmFileMsgID, core.ResultError(ackSyncAlarmFileMsgName, "server internal error", reqId)) return } // 检查用户是否登录 - u := m.GetUserByPID(msg.UID) - if !u.LoginState || u.AlarmType != omc.FILE { + u := m.GetUserByPID(body.UID) + if !u.LoginState || u.AlarmType != consts.FILE { zlog.Ins().ErrorF("no permissions ") - request.GetConnection().SendMsg(omc.AckSyncAlarmFile, omc.ErrorMsg("ackSyncAlarmFile", msg.Msg["reqId"], "no permissions")) + request.GetConnection().SendMsg(ackSyncAlarmFileMsgID, core.ResultError(ackSyncAlarmFileMsgName, "no permissions", reqId)) return } //查询需要上报的告警信息 @@ -50,36 +59,36 @@ func (*SyncAlarmFileApi) Handle(request ziface.IRequest) { end := "" syncSource := "" alarmSeq := 0 - fmt.Println("msg.Msg:", msg.Msg) + fmt.Println("body.Data:", body.Data) //map[alarmSeq:1 reqId:35 syncSource:1] // map[endTime:2023-07-15 23:59:59 reqId:34 startTime:2023-01-08 16:07:00 syncSource:0] - if v, ok := msg.Msg["startTime"]; ok { + if v, ok := body.Data["startTime"]; ok { start = v } - if v, ok := msg.Msg["endTime"]; ok { + if v, ok := body.Data["endTime"]; ok { end = v } - if v, ok := msg.Msg["syncSource"]; ok { + if v, ok := body.Data["syncSource"]; ok { syncSource = v } - if v, ok := msg.Msg["alarmSeq"]; ok { + if v, ok := body.Data["alarmSeq"]; ok { if seq, err := strconv.Atoi(v); err == nil { alarmSeq = seq } } - neBind, _ := core.ConvertBindFlag(m.BindFlag) + neBind, _ := parse.ConvertBindFlag(m.BindFlag) alarms, err := service.GetAlarm(neBind.NeType, neBind.NeId, start, end, syncSource, alarmSeq) if err != nil || len(alarms) == 0 { - request.GetConnection().SendMsg(omc.AckSyncAlarmFile, omc.ErrorMsg("ackSyncAlarmFile", msg.Msg["reqId"], "not find record")) + request.GetConnection().SendMsg(ackSyncAlarmFileMsgID, core.ResultError(ackSyncAlarmFileMsgName, "not find record", reqId)) return } //ack - request.GetConnection().SendMsg(omc.AckSyncAlarmFile, omc.SuccessMsg("ackSyncAlarmFile", msg.Msg["reqId"], "")) + request.GetConnection().SendMsg(ackSyncAlarmFileMsgID, core.ResultSuccess(ackSyncAlarmFileMsgName, "", reqId)) //打包结果文件 //打包生成文件 - var meta lib.FileMeta + var meta file.FileMeta meta.DirRoot = conf.OmcConf.FTPRoot meta.Province = m.Province meta.DeviceCode = m.DeviceCode diff --git a/handle/api/req_sync_alarm_msg.go b/handle/api/req_sync_alarm_msg.go new file mode 100644 index 0000000..77f4b9a --- /dev/null +++ b/handle/api/req_sync_alarm_msg.go @@ -0,0 +1,69 @@ +package api + +import ( + "omc/core" + "omc/core/manage" + "omc/core/parse" + "omc/handle/service" + "strconv" + + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/zlog" + "github.com/aceld/zinx/znet" +) + +var ReqSyncAlarmMsgID uint32 = 3 +var ReqSyncAlarmMsgType uint32 = 4 +var ReqSyncAlarmMsgName string = "ackSyncAlarmMsg" + +// reqSyncAlarmMsg 消息同步 +type ReqSyncAlarmMsg struct { + znet.BaseRouter +} + +// reqSyncAlarmMsg +func (s *ReqSyncAlarmMsg) Handle(request ziface.IRequest) { + // 消息处理 + checker := []string{"reqId", "alarmSeq"} + body, err := parse.RequestBodyDecode(request, checker) + reqId := body.Data["reqId"] + if err != nil || reqId == "" { + zlog.Ins().ErrorF("inlaid message body %s", err.Error()) + request.GetConnection().SendMsg(ReqSyncAlarmMsgType, core.ResultError(ReqSyncAlarmMsgName, err.Error(), "")) + return + } + + //管理模块 + m := manage.GetManager(request.GetConnection().GetName()) + if m == nil { + zlog.Ins().ErrorF("server internal error") + request.GetConnection().SendMsg(ReqSyncAlarmMsgType, core.ResultError(ReqSyncAlarmMsgName, "server internal error", reqId)) + return + } + + // 检查用户是否登录 + u := m.GetUserByPID(body.UID) + if !u.LoginState { + zlog.Ins().ErrorF("no permissions ") + request.GetConnection().SendMsg(ReqSyncAlarmMsgType, core.ResultError(ReqSyncAlarmMsgName, "no permissions", reqId)) + return + } + + alarmSeq, err := strconv.Atoi(body.Data["alarmSeq"]) + if err != nil || alarmSeq < 1 { + zlog.Ins().ErrorF("invalid parameter of message body") + request.GetConnection().SendMsg(ReqSyncAlarmMsgType, core.ResultError(ReqSyncAlarmMsgName, "invalid parameter of message body", reqId)) + return + } + + //check alarmSeq 是否存在 + neBind, _ := parse.ConvertBindFlag(m.BindFlag) + alarms, _ := service.GetRealTimeAlarm(neBind.NeType, neBind.NeId, int32(alarmSeq)) + if len(alarms) == 0 { + request.GetConnection().SendMsg(ReqSyncAlarmMsgType, core.ResultError(ReqSyncAlarmMsgName, "alarm seq does not exist", reqId)) + return + } + //更新实时上报的alarm seq + m.UpdateAlarmSeq(int32(alarmSeq)) + request.GetConnection().SendMsg(ReqSyncAlarmMsgType, core.ResultSuccess(ReqSyncAlarmMsgName, "ok", reqId)) +} diff --git a/model/alarm.go b/handle/model/alarm.go similarity index 100% rename from model/alarm.go rename to handle/model/alarm.go diff --git a/model/nbi_alarm_log.go b/handle/model/nbi_alarm_log.go similarity index 100% rename from model/nbi_alarm_log.go rename to handle/model/nbi_alarm_log.go diff --git a/model/user.go b/handle/model/user.go similarity index 100% rename from model/user.go rename to handle/model/user.go diff --git a/service/login.go b/handle/service/login.go similarity index 78% rename from service/login.go rename to handle/service/login.go index 4f49feb..249d63b 100644 --- a/service/login.go +++ b/handle/service/login.go @@ -5,22 +5,25 @@ import ( "encoding/base64" "encoding/pem" "errors" - "github.com/aceld/zinx/zlog" "omc/ca" "omc/conf" - "omc/db" - "omc/lib" - "omc/model" + "omc/core/db" + "omc/core/utils" + "omc/handle/model" + + "github.com/aceld/zinx/zlog" ) -func UserLogin(name, pw string) error { +// UserLogin 用户登录 +func UserLogin(name, passwd string) error { // 用户名密码校验 var user model.User - if err := db.Client.Model(&model.User{}).Where("account_id=?", name).First(&user).Error; err != nil { + err := db.Client.Model(&model.User{}).Where("account_id=?", name).First(&user).Error + if err != nil { return err } - if err := lib.Compare(user.Password, pw); err != nil { + if err := utils.Compare(user.Password, passwd); err != nil { zlog.Ins().ErrorF("Password Login[%s]:%s", name, err) return errors.New("incorrect username and password") } diff --git a/service/real_time_alarm.go b/handle/service/real_time_alarm.go similarity index 96% rename from service/real_time_alarm.go rename to handle/service/real_time_alarm.go index f74c6c1..42dc8ce 100644 --- a/service/real_time_alarm.go +++ b/handle/service/real_time_alarm.go @@ -2,10 +2,11 @@ package service import ( "encoding/json" + "omc/core/db" + "omc/core/emun" + "omc/handle/model" + "github.com/aceld/zinx/zlog" - "omc/db" - "omc/model" - "omc/omc" ) type OmcAlarm struct { @@ -44,7 +45,7 @@ func GetRealTimeAlarm(neType, neId string, alarmSeq int32) ([]OmcAlarm, error) { item.AlarmTitle = v.AlarmTitle item.AlarmStatus = int32(v.AlarmStatus) item.AlarmType = v.AlarmType - item.OrigSeverity = omc.OrigSeverity(v.OrigSeverity) + item.OrigSeverity = emun.OrigSeverity(v.OrigSeverity) item.EventTime = v.EventTime.Format("2006-01-02 15:04:05") item.AlarmId = v.AlarmId item.SpecificProblemID = v.SpecificProblemID diff --git a/service/sysn_alarm_file.go b/handle/service/sysn_alarm_file.go similarity index 88% rename from service/sysn_alarm_file.go rename to handle/service/sysn_alarm_file.go index 91a3b3c..aa3842c 100644 --- a/service/sysn_alarm_file.go +++ b/handle/service/sysn_alarm_file.go @@ -5,15 +5,19 @@ import ( "encoding/binary" "encoding/json" "errors" - "github.com/aceld/zinx/ziface" - "omc/db" - "omc/lib" - "omc/model" - "omc/omc" + "omc/core" + "omc/core/db" + "omc/core/emun" + "omc/core/file" + "omc/handle/model" "time" + + "github.com/aceld/zinx/ziface" ) -func GenFile(request ziface.IRequest, meta *lib.FileMeta, data []OmcAlarm) { +var AckSyncAlarmFileResultMsgID uint32 = 9 + +func GenFile(request ziface.IRequest, meta *file.FileMeta, data []OmcAlarm) { //生成文件内容 dataBuff := bytes.NewBuffer([]byte{}) for _, v := range data { @@ -23,22 +27,19 @@ func GenFile(request ziface.IRequest, meta *lib.FileMeta, data []OmcAlarm) { binary.Write(dataBuff, binary.BigEndian, '\n') } - file, err := lib.GenFile(meta, dataBuff.Bytes()) + file, err := file.GenFile(meta, dataBuff.Bytes()) if err != nil { return } //发送文件同步信息 - ackBody := omc.MsgBody{ - MsgName: "ackSyncOmcAlarmFileResult", - Msg: make(map[string]string, 0), - } - ackBody.Msg["reqId"] = meta.ReqId - ackBody.Msg["result"] = "succ" - ackBody.Msg["fileName"] = file - ackBody.Msg["resDesc"] = "" - ackBody.Pack() - request.GetConnection().SendMsg(omc.AckSyncAlarmFileResult, ackBody.RawData) + msgData := core.Result("ackSyncOmcAlarmFileResult", map[string]string{ + "reqId": meta.ReqId, + "result": "succ", + "fileName": file, + "resDesc": "", + }) + request.GetConnection().SendMsg(AckSyncAlarmFileResultMsgID, msgData) } // GetAlarmOfAlarmSeq 获取告警信息 @@ -56,7 +57,7 @@ func GetAlarmOfAlarmSeq(neType, neId string, alarmSeq int) ([]OmcAlarm, error) { item.AlarmTitle = v.AlarmTitle item.AlarmStatus = int32(v.AlarmStatus) item.AlarmType = v.AlarmType - item.OrigSeverity = omc.OrigSeverity(v.OrigSeverity) + item.OrigSeverity = emun.OrigSeverity(v.OrigSeverity) item.EventTime = v.EventTime.Format("2006-01-02 15:04:05") item.AlarmId = v.AlarmId item.SpecificProblemID = v.SpecificProblemID @@ -130,7 +131,7 @@ func GetAlarmOfEventTime(neType, neId, startTime, endTime string) ([]OmcAlarm, e item.AlarmTitle = v.AlarmTitle item.AlarmStatus = int32(v.AlarmStatus) item.AlarmType = v.AlarmType - item.OrigSeverity = omc.OrigSeverity(v.OrigSeverity) + item.OrigSeverity = emun.OrigSeverity(v.OrigSeverity) item.EventTime = v.EventTime.Format("2006-01-02 15:04:05") item.AlarmId = v.AlarmId item.SpecificProblemID = v.SpecificProblemID @@ -187,7 +188,7 @@ func GetAlarmOfLog(neType, neId, startTime, endTime string) ([]OmcAlarm, error) item.AlarmTitle = v.AlarmTitle item.AlarmStatus = int32(v.AlarmStatus) item.AlarmType = v.AlarmType - item.OrigSeverity = omc.OrigSeverity(v.OrigSeverity) + item.OrigSeverity = emun.OrigSeverity(v.OrigSeverity) item.EventTime = v.EventTime.Format("2006-01-02 15:04:05") item.AlarmId = v.AlarmId item.SpecificProblemID = v.SpecificProblemID diff --git a/nb_alarm_agent.go b/nb_alarm_agent.go index a09657f..83e43ea 100644 --- a/nb_alarm_agent.go +++ b/nb_alarm_agent.go @@ -6,124 +6,31 @@ import ( "github.com/aceld/zinx/zutils/commandline/args" "omc/conf" + "omc/core/db" + "omc/core/manage" + "omc/router" - api2 "omc/api" - "omc/core" - "omc/db" - "omc/decoder" - "omc/dpack" - "omc/omc" "os" "os/signal" - "time" - "github.com/aceld/zinx/zconf" - "github.com/aceld/zinx/ziface" "github.com/aceld/zinx/zlog" - "github.com/aceld/zinx/znet" ) -// OnConnectionAdd 当客户端建立连接的时候的hook函数 -func OnConnectionAdd(conn ziface.IConnection) { - //创建一个user - - user := core.NewUser(conn, conn.RemoteAddrString()) - //将当前新上线玩家添加到ChannelManager中 - m := core.GetManager(conn.GetName()) - if m == nil { - zlog.Ins().ErrorF("server internal error in GetManager") - conn.Stop() - return - } - m.AddUser(user) - - //将该连接绑定属性PID - conn.SetProperty("UID", user.UID) - - zlog.Ins().InfoF("====> User uID = %s", user.UID, " arrived ====", "") -} - -// OnConnectionLost 当客户端断开连接的时候的hook函数 -func OnConnectionLost(conn ziface.IConnection) { - //获取当前连接的PID属性 - uID, _ := conn.GetProperty("UID") - var userID string - if uID != nil { - userID = uID.(string) - } - - //根据pID获取对应usr - m := core.GetManager(conn.GetName()) - if m == nil { - zlog.Ins().ErrorF("server internal error in GetManager") - return - } - user := m.GetUserByPID(userID) - - //触发玩家下线业务 - if user != nil { - user.LostConnection(m) - } - - zlog.Ins().InfoF("====> User %s-%s", user.UID, user.UserName, " left =====") - -} - // go run nb_alarm_agent.go -c conf\nbi_alarm_agent.json func main() { - //配置初始化 + // 配置初始化 conf.Init(args.Args.ConfigFile) + // 初始数据库 db.Init() + //创建服务器句柄 for _, cg := range conf.OmcConf.Channel { - serverName := fmt.Sprintf("omc-tcp-Server-port:%d", cg.TCPPort) + serverName := fmt.Sprintf("%s:%d", cg.BindFlag, cg.TCPPort) //注册用户管理模块 - m := core.NewManager(serverName, cg.BindFlag, cg.Province, cg.DeviceCode) - - //new 一个TCP服务 - s := znet.NewUserConfServer(&zconf.Config{ - TCPPort: cg.TCPPort, - Name: serverName, - Host: "0.0.0.0", - MaxConn: conf.OmcConf.MaxConn, - WorkerPoolSize: uint32(conf.OmcConf.WorkerPoolSize), - HeartbeatMax: conf.OmcConf.HeartbeatMax, - LogDir: conf.OmcConf.LogDir, - LogFile: conf.OmcConf.LogFile, - }) - - //注册客户端连接建立和丢失函数 - s.SetOnConnStart(OnConnectionAdd) - s.SetOnConnStop(OnConnectionLost) - - //注册路由 - s.AddRouter(omc.ReqLoginAlarm, &api2.LoginApi{}) - s.AddRouter(omc.ReqHeartBeat, &api2.HeartBeatApi{}) - s.AddRouter(omc.CloseConnAlarm, &api2.CloseApi{}) - s.AddRouter(omc.ReqSyncAlarmMsg, &api2.SyncAlarmApi{}) - s.AddRouter(omc.ReqSyncAlarmFile, &api2.SyncAlarmFileApi{}) - s.AddRouter(omc.ReqCMCALoginSeq, &api2.SyncAlarmFileApi{}) - s.AddRouter(omc.ReqCMCALoginAlarm, &api2.SyncAlarmFileApi{}) - - s.AddRouter(290, &api2.ServerRouter{}) - - //添加LTV数据格式Decoder - s.SetDecoder(decoder.NewOmcDecoder()) - //添加LTV数据格式的Pack封包Encoder - s.SetPacket(dpack.NewDataPack()) - - // (启动心跳检测) - s.StartHeartBeatWithOption(60*time.Second, &ziface.HeartBeatOption{ - MakeMsg: core.MyHeartBeatMsg, - OnRemoteNotAlive: core.MyOnRemoteNotAlive, - Router: &api2.HeartBeatApi{}, - HeadBeatMsgID: uint32(0xFF), - }) - // 设置默认的心跳发送函数 - heart := s.GetHeartBeat() - heart.SetHeartbeatFunc(core.MyHeartBeat) + m := manage.NewManager(serverName, cg.BindFlag, cg.Province, cg.DeviceCode) //启动服务 + s := router.LoadServer(cg) go s.Serve() //启动实时告警 diff --git a/omc/msg.go b/omc/msg.go deleted file mode 100644 index a5980d1..0000000 --- a/omc/msg.go +++ /dev/null @@ -1,31 +0,0 @@ -package omc - -// ErrorMsg ackLoginAlarm;result=fail;resDesc=username-error -func ErrorMsg(msgType string, reqID string, desc string) []byte { - msgBody := MsgBody{ - MsgName: msgType, - Msg: make(map[string]string, 0), - } - if reqID != "" { - msgBody.Msg["reqId"] = reqID - } - msgBody.Msg["result"] = "fail" - msgBody.Msg["resDesc"] = desc - msgBody.Pack() - return msgBody.RawData -} - -func SuccessMsg(msgType string, reqID string, desc string) []byte { - msgBody := MsgBody{ - MsgName: msgType, - Msg: make(map[string]string, 0), - } - if reqID != "" { - msgBody.Msg["reqId"] = reqID - } - msgBody.Msg["result"] = "succ" - msgBody.Msg["resDesc"] = desc - - msgBody.Pack() - return msgBody.RawData -} diff --git a/omc/omc_pack.go b/omc/omc_pack.go deleted file mode 100644 index 03bf8e6..0000000 --- a/omc/omc_pack.go +++ /dev/null @@ -1,45 +0,0 @@ -package omc - -import ( - "errors" - "fmt" - "strings" -) - -type MsgBody struct { - UID string - RawData []byte - MsgName string - Msg map[string]string -} - -// Decode -//reqLoginAlarm;user=yiy;key=qw#$@;type=msg -func (o *MsgBody) Decode() error { - multi := strings.Split(string(o.RawData), ";") - if len(multi) < 1 { - return errors.New("invalid msg body") - } - for i := 1; i < len(multi); i++ { - m := strings.Split(multi[i], "=") - if len(m) != 2 { - return errors.New("invalid msg body") - } - o.Msg[m[0]] = m[1] - } - return nil -} - -// Pack -//reqLoginAlarm;user=yiy;key=qw#$@;type=msg -func (o *MsgBody) Pack() error { - var multi []string - multi = append(multi, o.MsgName) - for i, v := range o.Msg { - item := fmt.Sprintf("%s=%s", i, v) - multi = append(multi, item) - } - raw := strings.Join(multi, ";") - o.RawData = []byte(raw) - return nil -} diff --git a/omc/omc_type.go b/omc/omc_type.go deleted file mode 100644 index 92e28d9..0000000 --- a/omc/omc_type.go +++ /dev/null @@ -1,39 +0,0 @@ -package omc - -const ( - RealTimeAlarm = 0 - ReqLoginAlarm = 1 - AckLoginAlarm = 2 - ReqSyncAlarmMsg = 3 - AckSyncAlarmMsg = 4 - ReqSyncAlarmFile = 5 - AckSyncAlarmFile = 6 - AckSyncAlarmFileResult = 7 - ReqHeartBeat = 8 - AckHeartBeat = 9 - CloseConnAlarm = 10 - ReqCMCALoginAlarm = 11 - ReqCMCALoginSeq = 12 - AckCMCALoginSeq = 13 -) - -//定义user type -const ( - MSG = "msg" - FILE = "ftp" -) - -func OrigSeverity(os string) int32 { - switch os { - case "Critical": - return 1 - case "Major": - return 2 - case "Minor": - return 3 - case "Warning": - return 4 - default: - return 0 - } -} diff --git a/router/router.go b/router/router.go new file mode 100644 index 0000000..aa678be --- /dev/null +++ b/router/router.go @@ -0,0 +1,82 @@ +package router + +import ( + "fmt" + "omc/conf" + "omc/core/decoder" + "omc/core/dpack" + heartbeat "omc/core/heart_beat" + "omc/core/interceptor" + "omc/core/manage" + "omc/handle/api" + "time" + + "github.com/aceld/zinx/zconf" + "github.com/aceld/zinx/ziface" + "github.com/aceld/zinx/znet" +) + +const ( + RealTimeAlarm = 0 + ReqLoginAlarm = 1 + AckLoginAlarm = 2 + ReqSyncAlarmMsg = 3 + AckSyncAlarmMsg = 4 + ReqSyncAlarmFile = 5 + AckSyncAlarmFile = 6 + AckSyncAlarmFileResult = 7 + ReqHeartBeat = 8 + AckHeartBeat = 9 + CloseConnAlarm = 10 + ReqCMCALoginAlarm = 11 + ReqCMCALoginSeq = 12 + AckCMCALoginSeq = 13 +) + +func LoadServer(cg conf.Channel) ziface.IServer { + serverName := fmt.Sprintf("%s:%d", cg.BindFlag, cg.TCPPort) + + //new 一个TCP服务 + s := znet.NewUserConfServer(&zconf.Config{ + TCPPort: cg.TCPPort, + Name: serverName, + Host: "0.0.0.0", + MaxConn: conf.OmcConf.MaxConn, + WorkerPoolSize: uint32(conf.OmcConf.WorkerPoolSize), + HeartbeatMax: conf.OmcConf.HeartbeatMax, + LogDir: conf.OmcConf.LogDir, + LogFile: conf.OmcConf.LogFile, + }) + + //注册客户端连接建立和丢失函数 + s.SetOnConnStart(manage.OnConnectionAdd) + s.SetOnConnStop(manage.OnConnectionLost) + + //添加LTV数据格式Decoder + s.SetDecoder(decoder.NewOmcDecoder()) + //添加LTV数据格式的Pack封包Encoder + s.SetPacket(dpack.NewDataPack()) + + // (启动心跳检测) + s.StartHeartBeatWithOption(60*time.Second, &ziface.HeartBeatOption{ + MakeMsg: heartbeat.MyHeartBeatMsg, + OnRemoteNotAlive: heartbeat.MyOnRemoteNotAlive, + Router: &api.ReqHeartBeat{}, + HeadBeatMsgID: api.ReqHeartBeatMsgID, + }) + // 设置默认的心跳发送函数 + heart := s.GetHeartBeat() + heart.SetHeartbeatFunc(heartbeat.MyHeartBeat) + + // 添加自定义拦截器 + s.AddInterceptor(&interceptor.GlobalInterceptor{}) + + //注册路由 ================ + s.AddRouter(api.ReqLoginAlarmMsgID, &api.ReqLoginAlarm{}) + s.AddRouter(api.ReqCMCALoginSeqMsgID, &api.ReqCMCALoginSeq{}) + s.AddRouter(api.ReqCMCALoginAlarmMsgID, &api.ReqCMCALoginAlarm{}) + s.AddRouter(api.ReqSyncAlarmMsgID, &api.ReqSyncAlarmMsg{}) + s.AddRouter(api.CloseConnAlarmMsgID, &api.CloseConnAlarm{}) + + return s +}