/* 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 *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 }