/* 通过Router转发消息(对终端开发者不可见) Router -> MsgServer ROUTE_SEND_TOPIC_MSG_CMD arg0: Msg //消息内容 arg1: TopicName //群组名 arg2: ClientID //发送方用户ID arg3: ClientType //发送方终端类型,是client还是device */ func (self *ProtoProc) procRouteTopicMsg(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procRouteTopicMsg") var err error //send2Msg := cmd.GetArgs()[0] topicName := cmd.GetArgs()[1] //fromID := cmd.GetArgs()[2] //fromType := cmd.GetArgs()[3] // check whether the topic exist topicCacheData, err := self.msgServer.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist: %s", topicName, err.Error()) return common.TOPIC_NOT_EXIST } cmd.ChangeCmdName(protocol.IND_SEND_TOPIC_MSG_CMD) // exactly in this server, just broadcasting log.Warningf("topic %s has %d member(s) in this server", topicName, topicCacheData.AliveMemberNumMap[self.msgServer.cfg.LocalIP]) for _, mID := range topicCacheData.MemberList { if self.msgServer.sessions[mID.ID] != nil { self.msgServer.sessions[mID.ID].Send(libnet.Json(cmd)) if err != nil { log.Fatalln(err.Error()) } } } return nil }
/* client -> MsgServer REQ_ADD_2_TOPIC_CMD arg0: TopicName //群组名 arg1: NewClientID //用户ID arg2: NewClientName //用户在Topic中的Name, 对于device, 可以是儿子/女儿 MsgServer -> client RSP_ADD_2_TOPIC_CMD arg0: SUCCESS/FAILED arg1: TopicName arg2: ClientID arg3: ClientType */ func (self *ProtoProc) procAdd2Topic(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procAdd2Topic") var err error topicName := cmd.GetArgs()[0] mID := cmd.GetArgs()[1] mName := cmd.GetArgs()[2] ClientID := session.State.(*base.SessionState).ClientID ClientType := session.State.(*base.SessionState).ClientType mType := protocol.DEV_TYPE_CLIENT resp := protocol.NewCmdSimple(protocol.RSP_ADD_2_TOPIC_CMD) if len(cmd.GetArgs()) != 3 { err = common.SYNTAX_ERROR } else // only DEV_TYPE_CLIENT CAN create topic if ClientType != protocol.DEV_TYPE_CLIENT { err = common.DENY_ACCESS } else { // check whether the topic exist topicCacheData, _ := self.msgServer.topicCache.Get(topicName) if topicCacheData == nil { log.Infof("TOPIC %s not exist in CACHE", topicName) err = common.TOPIC_NOT_EXIST } else // only topic creater can do this if topicCacheData.CreaterID != ClientID { log.Warningf("ClientID %s is not creater of topic %s", ClientID, topicName) err = common.DENY_ACCESS } else { // New Member MUST be online sessionCacheData, _ := self.msgServer.sessionCache.Get(mID) if sessionCacheData == nil { log.Warningf("Client %s not online", mID) err = common.NOT_ONLINE } else { mType = sessionCacheData.ClientType member := mongo_store.NewMember(mID, mName, mType) err = self.msgServer.procJoinTopic(member, topicName) } } } if err != nil { resp.AddArg(err.Error()) } else { resp.AddArg(protocol.RSP_SUCCESS) } resp.AddArg(topicName) resp.AddArg(mID) resp.AddArg(mType) err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err }
func (self *ProtoProc) procLogin(cmd protocol.Cmd, session *libnet.Session) error { //log.Info("procLogin") var err error var uuid string var msgServer string ClientID := cmd.GetArgs()[0] ClientType := cmd.GetArgs()[1] ClientPwd := "" if len(cmd.GetArgs()) == 3 { ClientPwd = cmd.GetArgs()[2] } // get the session cache sessionCacheData, err := self.gateway.sessionCache.Get(ClientID) if sessionCacheData != nil { log.Warningf("ID %s already login", ClientID) msgServer = sessionCacheData.MsgServerAddr uuid = sessionCacheData.ID } else { // choose msg server and allocate UUID msgServer = self.procGetMinLoadMsgServer() uuid = common.NewV4().String() // get the session store to check whether registered sessionStoreData, _ := self.gateway.mongoStore.GetSessionFromCid(ClientID) if sessionStoreData == nil { log.Warningf("ID %s not registered", ClientID) // for store data sessionStoreData = mongo_store.NewSessionStoreData(ClientID, ClientPwd, ClientType) log.Info(sessionStoreData) common.StoreData(self.gateway.mongoStore, sessionStoreData) } // for cache data, MsgServer MUST update local & remote addr. sessionCacheData = redis_store.NewSessionCacheData(sessionStoreData, session.Conn().RemoteAddr().String(), msgServer, uuid) log.Info(sessionCacheData) self.gateway.sessionCache.Set(sessionCacheData) } // resp := protocol.NewCmdSimple(protocol.RSP_LOGIN_CMD) resp.AddArg(protocol.RSP_SUCCESS) resp.AddArg(uuid) resp.AddArg(msgServer) log.Info("Resp | ", resp) if session != nil { err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } session.Close() log.Info("client ", session.Conn().RemoteAddr().String(), " | close") } return nil }
/* client -> MsgServer REQ_KICK_TOPIC_CMD arg0: TopicName //群组名 arg1: NewClientID //待移除的成员用户ID MsgServer -> client RSP_KICK_TOPIC_CMD arg0: SUCCESS/FAILED */ func (self *ProtoProc) procKickTopic(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procKickTopic") var err error var topicCacheData *redis_store.TopicCacheData topicName := cmd.GetArgs()[0] mID := cmd.GetArgs()[1] ClientID := session.State.(*base.SessionState).ClientID ClientType := session.State.(*base.SessionState).ClientType resp := protocol.NewCmdSimple(protocol.RSP_KICK_TOPIC_CMD) if len(cmd.GetArgs()) != 2 { err = common.SYNTAX_ERROR goto ErrOut } // only DEV_TYPE_CLIENT CAN do this if ClientType != protocol.DEV_TYPE_CLIENT { err = common.DENY_ACCESS goto ErrOut } // check whether the topic exist topicCacheData, err = self.msgServer.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist", topicName) err = common.TOPIC_NOT_EXIST } else // only topic creater can do this if topicCacheData.CreaterID != ClientID { log.Warningf("ClientID %s is not creater of topic %s", ClientID, topicName) err = common.DENY_ACCESS } else { err = self.msgServer.procQuitTopic(mID, topicName) } ErrOut: if err != nil { resp.AddArg(err.Error()) } else { resp.AddArg(protocol.RSP_SUCCESS) } err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err }
func (self *ProtoProc) procRouteMessageP2P(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procRouteMessageP2P") var err error send2ID := cmd.GetArgs()[0] send2Msg := cmd.GetArgs()[1] fromID := cmd.GetArgs()[2] uuid := cmd.GetArgs()[3] _, err = common.GetSessionFromCID(self.msgServer.sessionCache, send2ID) if err != nil { log.Warningf("no ID : %s", send2ID) return err } resp := protocol.NewCmdSimple(protocol.RESP_MESSAGE_P2P_CMD) resp.AddArg(send2Msg) resp.AddArg(fromID) // add uuid resp.AddArg(uuid) if self.msgServer.sessions[send2ID] != nil { self.msgServer.sessions[send2ID].Send(libnet.Json(resp)) if err != nil { log.Fatalln(err.Error()) } } return nil }
func GetOfflineMsgFromOwnerName(storeOp interface{}, ownerName string) (*redis_store.OfflineMsgCacheData, error) { switch storeOp.(type) { case *redis_store.OfflineMsgCache: o, err := storeOp.(*redis_store.OfflineMsgCache).Get(ownerName) if err != nil { log.Warningf("no ownerName : %s", ownerName) return nil, err } if o != nil { log.Info(o) } return o, nil } return nil, NOTFOUNT // o ,err := offlineMsgCache.Get(ownerName) // if err != nil { // log.Warningf("no ownerName : %s", ownerName) // return nil, err // } // if o != nil { // log.Info(o) // } // return o, nil }
func GetTopicFromTopicName(storeOp interface{}, topicName string) (*redis_store.TopicCacheData, error) { switch storeOp.(type) { case *redis_store.TopicCache: topic, err := storeOp.(*redis_store.TopicCache).Get(topicName) if err != nil { log.Warningf("no topicName : %s", topicName) return nil, err } if topic != nil { log.Info(topic) } return topic, nil } return nil, NOTFOUNT // topic ,err := topicCache.Get(topicName) // if err != nil { // log.Warningf("no topicName : %s", topicName) // return nil, err // } // if topic != nil { // log.Info(topic) // } // return topic, nil }
func GetSessionFromCID(storeOp interface{}, ID string) (*redis_store.SessionCacheData, error) { switch storeOp.(type) { case *redis_store.SessionCache: session, err := storeOp.(*redis_store.SessionCache).Get(ID) if err != nil { log.Warningf("no ID : %s", ID) return nil, err } if session != nil { log.Info(session) } return session, nil } return nil, NOTFOUNT // session ,err := sessionCache.Get(ID) // if err != nil { // log.Warningf("no ID : %s", ID) // return nil, err // } // if session != nil { // log.Info(session) // } // return session, nil }
func (self *ProtoProc) procGetTopicList(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procGetTopicList") var err error resp := protocol.NewCmdSimple(protocol.RSP_GET_TOPIC_LIST_CMD) clientID := session.State.(*base.SessionState).ClientID //clientType := session.State.(*base.SessionState).ClientType sessionCacheData, err := self.msgServer.sessionCache.Get(clientID) if sessionCacheData == nil { log.Warningf("Client %s not online", clientID) err = common.NOT_ONLINE goto ErrOut } ErrOut: if err != nil { resp.AddArg(err.Error()) } else { resp.AddArg(protocol.RSP_SUCCESS) resp.AddArg(strconv.Itoa(len(sessionCacheData.TopicList))) for _, topic := range sessionCacheData.TopicList { resp.AddArg(topic) } } err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err }
func (self *ProtoProc) procGetTopicProfile(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procGetTopicProfile") var err error var topicCacheData *redis_store.TopicCacheData topicName := "<N/A>" resp := protocol.NewCmdSimple(protocol.RSP_GET_TOPIC_PROFILE_CMD) if len(cmd.GetArgs()) != 1 { err = common.SYNTAX_ERROR } else { topicName = cmd.GetArgs()[0] clientID := session.State.(*base.SessionState).ClientID //clientType := session.State.(*base.SessionState).ClientType // check whether the topic exist topicCacheData, err = self.msgServer.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist", topicName) err = common.TOPIC_NOT_EXIST } else if topicCacheData.MemberExist(clientID) == false { log.Warningf("%s not the member of topic %d", clientID, topicName) err = common.DENY_ACCESS } } if err != nil { resp.AddArg(err.Error()) resp.AddArg(topicName) } else { resp.AddArg(protocol.RSP_SUCCESS) resp.AddArg(topicName) resp.AddArg(topicCacheData.CreaterID) for _, member := range topicCacheData.MemberList { resp.AddArg(member.ID) resp.AddArg(member.Name) resp.AddArg(member.Type) } } err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err }
/* MsgServer -> Router REQ_SEND_P2P_MSG_CMD arg0: Sent2ID //接收方用户ID arg1: Msg //消息内容 arg2: FromID //发送方用户ID arg3: uuid //MsgServer分配的消息uuid */ func (self *ProtoProc) procSendMsgP2P(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procSendMsgP2P") var err error send2ID := cmd.GetArgs()[0] send2Msg := cmd.GetArgs()[1] log.Info(send2Msg) self.Router.readMutex.Lock() defer self.Router.readMutex.Unlock() cacheSession, err := self.Router.sessionCache.Get(send2ID) if cacheSession == nil || cacheSession.Alive == false { storeSession, err := self.Router.mongoStore.GetSessionFromCid(send2ID) if err != nil { log.Warningf("ID %s not registered, msg dropped", send2ID) return err } log.Info(storeSession) log.Warningf("ID registered but offline: %s", send2ID) cmd.ChangeCmdName(protocol.ROUTE_SEND_P2P_MSG_CMD) //ms := self.Router.cfg.MsgServerList[0] ms := session.Conn().RemoteAddr().String() err = self.Router.msgServerClientMap[ms].Send(libnet.Json(cmd)) if err != nil { log.Error("error:", err) return err } } else { log.Info(cacheSession.MsgServerAddr) cmd.ChangeCmdName(protocol.ROUTE_SEND_P2P_MSG_CMD) log.Info(cmd) err = self.Router.msgServerClientMap[cacheSession.MsgServerAddr].Send(libnet.Json(cmd)) if err != nil { log.Error("error:", err) return err } } return nil }
/* Router -> MsgServer ROUTE_SEND_TOPIC_MSG_CMD arg0: ClientID //发送方用户ID arg1: ClientType //发送方终端类型,是client还是device arg2: Msg //消息内容 arg3: TopicName //群组名, device无须提供 */ func (self *ProtoProc) procSendMsgTopic(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procSendMsgTopic") var err error ms := session.Conn().RemoteAddr().String() //send2Msg := cmd.GetArgs()[0] topicName := cmd.GetArgs()[1] //fromID := cmd.GetArgs()[2] //fromType := cmd.GetArgs()[3] // check whether the topic exist topicCacheData, err := self.Router.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist: %s", topicName, err.Error()) return err } cmd.ChangeCmdName(protocol.ROUTE_SEND_TOPIC_MSG_CMD) log.Info(protocol.ROUTE_SEND_TOPIC_MSG_CMD) log.Info(cmd) for ip, num := range topicCacheData.AliveMemberNumMap { if num > 0 { log.Warningf("topic %s has %d member(s) in ip %s", topicName, num, ip) if ip != ms { // not in this server, routing it err = self.Router.msgServerClientMap[ip].Send(libnet.Json(cmd)) if err != nil { log.Error("error:", err) return err } } } } return nil }
func DelSessionFromCID(storeOp interface{}, ID string) error { switch storeOp.(type) { case *redis_store.SessionCache: err := storeOp.(*redis_store.SessionCache).Delete(ID) if err != nil { log.Warningf("no ID : %s", ID) return err } } // err := sessionCache.Delete(ID) // if err != nil { // log.Warningf("no ID : %s", ID) // return err // } return NOTFOUNT }
func (self *ProtoProc) procSendMsgP2P(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procSendMsgP2P") var err error send2ID := cmd.GetArgs()[0] send2Msg := cmd.GetArgs()[1] log.Info(send2Msg) self.Router.readMutex.Lock() defer self.Router.readMutex.Unlock() cacheSession, err := common.GetSessionFromCID(self.Router.sessionCache, send2ID) if err != nil { log.Warningf("no ID in cache : %s", send2ID) storeSession, err := self.Router.mongoStore.GetSessionFromCid(mongo_store.DATA_BASE_NAME, mongo_store.TOPIC_INFO_COLLECTION, send2ID) if err != nil { return err } log.Info(storeSession.MsgServerAddr) cmd.ChangeCmdName(protocol.ROUTE_MESSAGE_P2P_CMD) err = self.Router.msgServerClientMap[storeSession.MsgServerAddr].Send(libnet.Json(cmd)) if err != nil { log.Error("error:", err) return err } } else { log.Info(cacheSession.MsgServerAddr) cmd.ChangeCmdName(protocol.ROUTE_MESSAGE_P2P_CMD) err = self.Router.msgServerClientMap[cacheSession.MsgServerAddr].Send(libnet.Json(cmd)) if err != nil { log.Error("error:", err) return err } } return nil }
func (self *MsgServer) procJoinTopic(member *mongo_store.Member, topicName string) error { log.Info("procJoinTopic") var err error // check whether the topic exist topicCacheData, err := self.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist", topicName) return common.TOPIC_NOT_EXIST } if topicCacheData.MemberExist(member.ID) { log.Warningf("ClientID %s exists in topic %s", member.ID, topicName) return common.MEMBER_EXIST } sessionCacheData, err := self.sessionCache.Get(member.ID) if sessionCacheData == nil { log.Warningf("Client %s not online", member.ID) return common.NOT_ONLINE } // Watch can only be added in ONE topic //fmt.Println("len of topic list of %s: %d", member.ID, len(sessionCacheData.TopicList)) if member.Type == protocol.DEV_TYPE_WATCH && len(sessionCacheData.TopicList) >= 1 { log.Warningf("Watch %s is in topic %s", member.ID, sessionCacheData.TopicList[0]) return common.DENY_ACCESS } // session cache and store sessionCacheData.AddTopic(topicName) err = self.sessionCache.Set(sessionCacheData) if err != nil { log.Error(err.Error()) return err } err = self.mongoStore.Set(sessionCacheData.SessionStoreData) if err != nil { log.Error(err.Error()) return err } // topic cache and store topicCacheData.AddMember(member) // update AliveMemberNumMap[server] if sessionCacheData.Alive { if v, ok := topicCacheData.AliveMemberNumMap[sessionCacheData.MsgServerAddr]; ok { topicCacheData.AliveMemberNumMap[sessionCacheData.MsgServerAddr] = v + 1 } else { topicCacheData.AliveMemberNumMap[sessionCacheData.MsgServerAddr] = 1 } } err = self.topicCache.Set(topicCacheData) if err != nil { log.Error(err.Error()) return err } err = self.mongoStore.Set(topicCacheData.TopicStoreData) if err != nil { log.Error(err.Error()) return err } return nil }
func (self *MsgServer) procQuitTopic(clientID string, topicName string) error { log.Info("procQuitTopic") var err error var topicCacheData *redis_store.TopicCacheData var sessionCacheData *redis_store.SessionCacheData var sessionStoreData *mongo_store.SessionStoreData // check whether the topic exist topicCacheData, err = self.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist", topicName) return common.TOPIC_NOT_EXIST } if !topicCacheData.MemberExist(clientID) { log.Warningf("member %s is not in topic %s", clientID, topicName) return common.NOT_MEMBER } // update topic cache and store topicCacheData.RemoveMember(clientID) err = self.topicCache.Set(topicCacheData) if err != nil { log.Error(err.Error()) return err } log.Infof("member %s removed from topic CACHE %s", clientID, topicName) err = self.mongoStore.Set(topicCacheData.TopicStoreData) if err != nil { log.Error(err.Error()) return err } log.Infof("member %s removed from topic STORE %s", clientID, topicName) // update session cache and store sessionCacheData, err = self.sessionCache.Get(clientID) if sessionCacheData != nil { log.Infof("remove topic %s from Client CACHE %s", topicName, clientID) sessionCacheData.RemoveTopic(topicName) err = self.sessionCache.Set(sessionCacheData) if err != nil { log.Error(err.Error()) return err } log.Infof("topic %s removed from Client CACHE %s", topicName, clientID) err = self.mongoStore.Set(sessionCacheData.SessionStoreData) if err != nil { log.Error(err.Error()) return err } log.Infof("topic %s removed from Client STORE %s", topicName, clientID) if sessionCacheData.Alive { // update AliveMemberNumMap[server] if v, ok := topicCacheData.AliveMemberNumMap[sessionCacheData.MsgServerAddr]; ok { if v > 0 { topicCacheData.AliveMemberNumMap[sessionCacheData.MsgServerAddr] = v - 1 } else { topicCacheData.AliveMemberNumMap[sessionCacheData.MsgServerAddr] = 0 } self.topicCache.Set(topicCacheData) } } } else { sessionStoreData, err = self.mongoStore.GetSessionFromCid(clientID) if sessionStoreData == nil { log.Warningf("ID %s not registered in STORE", clientID) } else { log.Infof("remove topic %s from Client STORE %s", topicName, clientID) sessionStoreData.RemoveTopic(topicName) err = self.mongoStore.Set(sessionStoreData) if err != nil { log.Error(err.Error()) return err } log.Infof("topic %s removed from Client STORE %s", topicName, clientID) } } return nil }
/* device/client -> MsgServer -> Router REQ_SEND_TOPIC_MSG_CMD arg0: Msg //消息内容 arg1: TopicName //群组名, device无须提供 返回给消息发送者的消息 MsgServer -> device/client RSP_SEND_TOPIC_MSG_CMD arg0: SUCCESS/FAILED 通过Router转发消息(对终端开发者不可见) Router -> MsgServer ROUTE_SEND_TOPIC_MSG_CMD arg0: Msg //消息内容 arg1: TopicName //群组名 arg2: ClientID //发送方用户ID arg3: ClientType //发送方终端类型,是client还是device 发送给消息接受者的消息 MsgServer -> device/client REQ_SEND_TOPIC_MSG_CMD arg0: Msg //消息内容 arg1: TopicName //群组名 arg2: ClientID //发送方用户ID arg3: ClientType //发送方终端类型,是client还是device */ func (self *ProtoProc) procSendTopicMsg(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procSendTopicMsg") var err error var topicName string var topicCacheData *redis_store.TopicCacheData var sessionCacheData *redis_store.SessionCacheData //var sessionStoreData *mongo_store.SessionStoreData msg := cmd.GetArgs()[0] resp := protocol.NewCmdSimple(protocol.RSP_SEND_TOPIC_MSG_CMD) ClientID := session.State.(*base.SessionState).ClientID ClientType := session.State.(*base.SessionState).ClientType if ClientType == protocol.DEV_TYPE_CLIENT { if len(cmd.GetArgs()) != 2 { err = common.SYNTAX_ERROR goto ErrOut } } else if len(cmd.GetArgs()) != 1 { err = common.SYNTAX_ERROR goto ErrOut } // get session cache sessionCacheData, err = self.msgServer.sessionCache.Get(ClientID) if sessionCacheData == nil { log.Errorf("ID %s cache missing", ClientID) err = common.NOT_ONLINE goto ErrOut } else if ClientType == protocol.DEV_TYPE_WATCH { topicName = sessionCacheData.GetTopics()[0] } else { topicName = cmd.GetArgs()[1] } // check whether the topic exist topicCacheData, err = self.msgServer.topicCache.Get(topicName) if topicCacheData == nil { log.Warningf("TOPIC %s not exist", topicName) err = common.TOPIC_NOT_EXIST } else { topic_msg_resp := protocol.NewCmdSimple(cmd.GetCmdName()) topic_msg_resp.AddArg(msg) topic_msg_resp.AddArg(topicName) topic_msg_resp.AddArg(ClientID) topic_msg_resp.AddArg(ClientType) if topicCacheData.AliveMemberNumMap[self.msgServer.cfg.LocalIP] > 1 { // exactly in this server, just broadcasting topic_msg_resp.ChangeCmdName(protocol.IND_SEND_TOPIC_MSG_CMD) log.Warningf("topic %s has %d member(s) in this server", topicName, topicCacheData.AliveMemberNumMap[self.msgServer.cfg.LocalIP]) for _, mID := range topicCacheData.MemberList { if mID.ID != ClientID && self.msgServer.sessions[mID.ID] != nil { self.msgServer.sessions[mID.ID].Send(libnet.Json(topic_msg_resp)) if err != nil { log.Fatalln(err.Error()) } } } } if self.msgServer.channels[protocol.SYSCTRL_SEND] != nil { //topic_msg_resp.ChangeCmdName(protocol.ROUTE_SEND_TOPIC_MSG_CMD) topic_msg_resp.ChangeCmdName(protocol.REQ_SEND_TOPIC_MSG_CMD) for ip, num := range topicCacheData.AliveMemberNumMap { if num > 0 { log.Warningf("topic %s has %d member(s) in ip %s", topicName, num, ip) if ip != self.msgServer.cfg.LocalIP { // not in this server, routing it _, err = self.msgServer.channels[protocol.SYSCTRL_SEND].Channel.Broadcast(libnet.Json(topic_msg_resp)) if err != nil { log.Error(err.Error()) } break } } } } } ErrOut: if err != nil { resp.AddArg(err.Error()) } else { resp.AddArg(protocol.RSP_SUCCESS) } err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err }
func (self *ProtoProc) procSendMessageP2P(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procSendMessageP2P") var err error send2ID := cmd.GetArgs()[0] send2Msg := cmd.GetArgs()[1] fromID := cmd.GetArgs()[2] store_session, err := common.GetSessionFromCID(self.msgServer.sessionCache, send2ID) if err != nil { log.Warningf("no ID : %s", send2ID) return err } uuid := common.NewV4().String() log.Info("uuid : ", uuid) uuidTmpMap := make(map[string]bool) uuidTmpMap[uuid] = false self.msgServer.p2pAckStatus[fromID] = uuidTmpMap if self.msgServer.sessions[send2ID] == nil { //offline log.Info(send2ID + " | is offline") exist, err := self.msgServer.offlineMsgCache.IsKeyExist(send2ID) if exist.(int64) == 0 { tmp := redis_store.NewOfflineMsgCacheData(send2ID) tmp.AddMsg(redis_store.NewOfflineMsgData(send2Msg, fromID, uuid)) self.msgServer.offlineMsgCache.Set(tmp) if err != nil { log.Error(err.Error()) return err } } else { omrd, err := common.GetOfflineMsgFromOwnerName(self.msgServer.offlineMsgCache, send2ID) if err != nil { log.Error(err.Error()) return err } omrd.AddMsg(redis_store.NewOfflineMsgData(send2Msg, fromID, uuid)) self.msgServer.offlineMsgCache.Set(omrd) if err != nil { log.Error(err.Error()) return err } } } if store_session.MsgServerAddr == self.msgServer.cfg.LocalIP { log.Info("in the same server") resp := protocol.NewCmdSimple(protocol.RESP_MESSAGE_P2P_CMD) resp.AddArg(send2Msg) resp.AddArg(fromID) // add uuid resp.AddArg(uuid) if self.msgServer.sessions[send2ID] != nil { self.msgServer.sessions[send2ID].Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } } } else { if self.msgServer.channels[protocol.SYSCTRL_SEND] != nil { //add uuid cmd.AddArg(uuid) _, err = self.msgServer.channels[protocol.SYSCTRL_SEND].Channel.Broadcast(libnet.Json(cmd)) if err != nil { log.Error(err.Error()) return err } } } return nil }
func (self *ProtoProc) procSendMessageP2P(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procSendMessageP2P") var err error var sessionCacheData *redis_store.SessionCacheData var sessionStoreData *mongo_store.SessionStoreData var uuid string var send2ID string var send2Msg string fromID := session.State.(*base.SessionState).ClientID resp := protocol.NewCmdSimple(protocol.RSP_SEND_P2P_MSG_CMD) if len(cmd.GetArgs()) != 2 { log.Warningf("syntax error: (id,msg) needed") err = common.SYNTAX_ERROR goto errout } send2ID = cmd.GetArgs()[0] send2Msg = cmd.GetArgs()[1] sessionCacheData, err = self.msgServer.sessionCache.Get(send2ID) if sessionCacheData == nil { sessionStoreData, err = self.msgServer.mongoStore.GetSessionFromCid(send2ID) if sessionStoreData == nil { log.Warningf("send2ID %s not found", send2ID) err = common.NOTFOUNT goto errout } } uuid = common.NewV4().String() log.Info("uuid : ", uuid) self.procP2PAckStatus(fromID, uuid, protocol.P2P_ACK_FALSE) if sessionCacheData == nil || sessionCacheData.Alive == false { //offline log.Info("procSendMessageP2P: " + send2ID + " | is offline") omrd, err := self.msgServer.offlineMsgCache.Get(send2ID) log.Info(omrd) if err != nil { log.Error(err.Error()) } if omrd == nil { omrd = redis_store.NewOfflineMsgCacheData(send2ID) } omrd.AddMsg(redis_store.NewOfflineMsgData(send2Msg, fromID, uuid)) err = self.msgServer.offlineMsgCache.Set(omrd) if err != nil { log.Error(err.Error()) goto errout } } else if sessionCacheData.MsgServerAddr == self.msgServer.cfg.LocalIP { log.Info("procSendMessageP2P: in the same server") req := protocol.NewCmdSimple(protocol.IND_SEND_P2P_MSG_CMD) req.AddArg(send2Msg) req.AddArg(fromID) // add uuid req.AddArg(uuid) if self.msgServer.sessions[send2ID] != nil { self.msgServer.sessions[send2ID].Send(libnet.Json(req)) if err != nil { log.Error(err.Error()) goto errout } self.procP2PAckStatus(fromID, uuid, protocol.P2P_ACK_SENT) } } else { log.Info("procSendMessageP2P: not in the same server") if self.msgServer.channels[protocol.SYSCTRL_SEND] != nil { cmd.AddArg(fromID) //add uuid cmd.AddArg(uuid) _, err = self.msgServer.channels[protocol.SYSCTRL_SEND].Channel.Broadcast(libnet.Json(cmd)) if err != nil { log.Error(err.Error()) goto errout } //self.procP2PAckStatus(fromID, uuid, protocol.P2P_ACK_SENT) } } errout: if err != nil { resp.AddArg(err.Error()) } else { resp.AddArg(protocol.RSP_SUCCESS) resp.AddArg(uuid) } err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err }
/* IND_ACK_P2P_STATUS_CMD arg0: uuid // 发送方知道uuid对应的已发送的消息已送达 arg1: SENT/READ // 发送方知道uuid对应的消息状态:已送达/已读 */ func (self *ProtoProc) procP2PAckStatus(fromID string, uuid string, status string) error { log.Info("procP2PAckStatus") //var err error p2psd, err := self.msgServer.p2pStatusCache.Get(fromID) if p2psd == nil { p2psd = redis_store.NewP2pStatusCacheData(fromID) } p2psd.Set(uuid, status) if status == protocol.P2P_ACK_FALSE { return nil } sessionCacheData, err := self.msgServer.sessionCache.Get(fromID) if sessionCacheData == nil { log.Warningf("no cache ID : %s, err: %s", fromID, err.Error()) sessionStoreData, err := self.msgServer.mongoStore.GetSessionFromCid(fromID) if sessionStoreData == nil { // not registered log.Warningf("no store ID : %s, err: %s", fromID, err.Error()) self.msgServer.p2pStatusCache.Delete(fromID) return err } } if sessionCacheData == nil || sessionCacheData.Alive == false { // offline log.Info(fromID + " | is offline") omrd, err := common.GetOfflineMsgFromOwnerName(self.msgServer.offlineMsgCache, fromID) log.Info(omrd) if err != nil { log.Error(err.Error()) return err } if omrd == nil { omrd = redis_store.NewOfflineMsgCacheData(fromID) } omrd.AddMsg(redis_store.NewOfflineMsgData(protocol.IND_ACK_P2P_STATUS_CMD /*fromID*/, status, uuid)) err = self.msgServer.offlineMsgCache.Set(omrd) if err != nil { log.Error(err.Error()) return err } } else { // online resp := protocol.NewCmdSimple(protocol.IND_ACK_P2P_STATUS_CMD) resp.AddArg(uuid) resp.AddArg(status) log.Info(fromID + " | is online") if sessionCacheData.MsgServerAddr == self.msgServer.cfg.LocalIP { log.Info("in the same server") if self.msgServer.sessions[fromID] != nil { self.msgServer.sessions[fromID].Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) return err } } } else { log.Info("not in the same server") if self.msgServer.channels[protocol.SYSCTRL_SEND] != nil { resp.AddArg(fromID) _, err = self.msgServer.channels[protocol.SYSCTRL_SEND].Channel.Broadcast(libnet.Json(resp)) if err != nil { log.Error(err.Error()) return err } } } } return nil }
func (self *ProtoProc) procLogin(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procLogin") var err error ClientID := cmd.GetArgs()[0] uuid := cmd.GetArgs()[1] resp := protocol.NewCmdSimple(protocol.RSP_LOGIN_CMD) // for cache data sessionCacheData, err := self.msgServer.sessionCache.Get(ClientID) if err != nil { log.Warningf("no ID : %s", ClientID) } else if sessionCacheData.ID != uuid { log.Warningf("ID(%s) & uuid(%s) not matched", ClientID, uuid) err = common.NOT_LOGIN } if err == nil { resp.AddArg(protocol.RSP_SUCCESS) } else { resp.AddArg(protocol.RSP_ERROR) } err2 := session.Send(libnet.Json(resp)) if err2 != nil { log.Error(err2.Error()) return err2 } if err != nil { return err } // update the session cache sessionCacheData.ClientAddr = session.Conn().RemoteAddr().String() sessionCacheData.MsgServerAddr = self.msgServer.cfg.LocalIP sessionCacheData.Alive = true self.msgServer.sessionCache.Set(sessionCacheData) log.Info(sessionCacheData) self.msgServer.procOffline(ClientID) self.msgServer.procOnline(ClientID) /* args := make([]string, 0) args = append(args, cmd.GetArgs()[0]) CCmd := protocol.NewCmdInternal(protocol.CACHE_SESSION_CMD, args, sessionCacheData) log.Info(CCmd) if self.msgServer.channels[protocol.SYSCTRL_CLIENT_STATUS] != nil { _, err = self.msgServer.channels[protocol.SYSCTRL_CLIENT_STATUS].Channel.Broadcast(libnet.Json(CCmd)) if err != nil { log.Error(err.Error()) return err } } // for store data sessionStoreData := mongo_store.SessionStoreData{ID, session.Conn().RemoteAddr().String(), self.msgServer.cfg.LocalIP, true} log.Info(sessionStoreData) args = make([]string, 0) args = append(args, cmd.GetArgs()[0]) CCmd = protocol.NewCmdInternal(protocol.STORE_SESSION_CMD, args, sessionStoreData) log.Info(CCmd) if self.msgServer.channels[protocol.STORE_CLIENT_INFO] != nil { _, err = self.msgServer.channels[protocol.STORE_CLIENT_INFO].Channel.Broadcast(libnet.Json(CCmd)) if err != nil { log.Error(err.Error()) return err } } */ self.msgServer.sessions[ClientID] = session self.msgServer.sessions[ClientID].State = base.NewSessionState(true, ClientID, sessionCacheData.ClientType) err = self.procOfflineMsg(session, ClientID) if err != nil { log.Error(err.Error()) return err } return nil }
func (self *ProtoProc) procJoinTopic(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procJoinTopic") var err error if len(cmd.GetArgs()) != 2 { return CMD_NOT_CORRECT } topicName := cmd.GetArgs()[0] clientID := cmd.GetArgs()[1] if self.msgServer.topics[topicName] == nil { log.Warning("no topic in this server :" + topicName) t, err := self.findTopicMsgAddr(topicName) if err != nil { log.Warningf("no topicName : %s", topicName) return err } resp := protocol.NewCmdSimple(protocol.LOCATE_TOPIC_MSG_ADDR_CMD) resp.AddArg(t.MsgServerAddr) resp.AddArg(topicName) err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) return err } return err } else { t, err := self.findTopicMsgAddr(topicName) if err != nil { log.Warningf("no topicName : %s", topicName) return err } resp := protocol.NewCmdSimple(protocol.LOCATE_TOPIC_MSG_ADDR_CMD) resp.AddArg(t.MsgServerAddr) resp.AddArg(topicName) err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) return err } } m := redis_store.NewMember(clientID) self.msgServer.topics[topicName].ClientIDList = append(self.msgServer.topics[topicName].ClientIDList, clientID) self.msgServer.topics[topicName].AddMember(m) self.msgServer.topics[topicName].Channel.Join(session, nil) args := make([]string, 0) args = append(args, topicName) CCmd := protocol.NewCmdInternal(protocol.CACHE_TOPIC_CMD, args, self.msgServer.topics[topicName].TSD) log.Info(CCmd) if self.msgServer.channels[protocol.SYSCTRL_TOPIC_STATUS] != nil { _, err = self.msgServer.channels[protocol.SYSCTRL_TOPIC_STATUS].Channel.Broadcast(libnet.Json(CCmd)) if err != nil { log.Error(err.Error()) return err } } // for store mongo //member := mongo_store.NewMember(clientID) //self.msgServer.topics[topicName].ClientIDList = append(self.msgServer.topics[topicName].ClientIDList, //clientID) //self.msgServer.topics[topicName].AddMember(member) //self.msgServer.topics[topicName].Channel.Join(session, nil) args = make([]string, 0) args = append(args, topicName) CCmd = protocol.NewCmdInternal(protocol.STORE_TOPIC_CMD, args, self.msgServer.topics[topicName].TSD) log.Info(CCmd) if self.msgServer.channels[protocol.STORE_TOPIC_INFO] != nil { _, err = self.msgServer.channels[protocol.STORE_TOPIC_INFO].Channel.Broadcast(libnet.Json(CCmd)) if err != nil { log.Error(err.Error()) return err } } return nil }