/* 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 *MsgServer) parseProtocol(cmd []byte, session *libnet.Session) error { var c protocol.CmdSimple // receive msg, that means client alive if session.State != nil { self.scanSessionMutex.Lock() session.State.(*base.SessionState).Alive = true self.scanSessionMutex.Unlock() } err := json.Unmarshal(cmd, &c) if err != nil { log.Error("error:", err) return err } pp := NewProtoProc(self) self.readMutex.Lock() defer self.readMutex.Unlock() log.Infof("[%s]->[%s]", session.Conn().RemoteAddr().String(), self.cfg.LocalIP) log.Info(c) switch c.GetCmdName() { case protocol.SEND_PING_CMD: err = pp.procPing(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.SUBSCRIBE_CHANNEL_CMD: pp.procSubscribeChannel(&c, session) case protocol.REQ_LOGIN_CMD: err = pp.procLogin(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_LOGOUT_CMD: err = pp.procLogout(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_SEND_P2P_MSG_CMD: err = pp.procSendMessageP2P(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.ROUTE_SEND_P2P_MSG_CMD: err = pp.procRouteMessageP2P(&c, session) if err != nil { log.Error("error:", err) return err } // p2p ack case protocol.IND_ACK_P2P_STATUS_CMD: err = pp.procP2pAck(&c, session) if err != nil { log.Error("error:", err) return err } // p2p ack case protocol.ROUTE_ACK_P2P_STATUS_CMD: err = pp.procP2pAck(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_SEND_TOPIC_MSG_CMD: err = pp.procSendTopicMsg(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.ROUTE_SEND_TOPIC_MSG_CMD: err = pp.procRouteTopicMsg(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_CREATE_TOPIC_CMD: err = pp.procCreateTopic(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_ADD_2_TOPIC_CMD: err = pp.procAdd2Topic(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_KICK_TOPIC_CMD: err = pp.procKickTopic(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_JOIN_TOPIC_CMD: err = pp.procJoinTopic(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_QUIT_TOPIC_CMD: err = pp.procQuitTopic(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_GET_TOPIC_LIST_CMD: err = pp.procGetTopicList(&c, session) if err != nil { log.Error("error:", err) return err } case protocol.REQ_GET_TOPIC_PROFILE_CMD: err = pp.procGetTopicProfile(&c, session) if err != nil { log.Error("error:", err) return err } } return err }
/* REQ_CREATE_TOPIC_CMD arg0: TopicName //群组名 arg1: ClientName //用户在Topic中的Name, 比如老爸/老妈 */ func (self *ProtoProc) procCreateTopic(cmd protocol.Cmd, session *libnet.Session) error { log.Info("procCreateTopic") var err error topicName := cmd.GetArgs()[0] ClientName := cmd.GetArgs()[1] ClientID := session.State.(*base.SessionState).ClientID ClientType := session.State.(*base.SessionState).ClientType resp := protocol.NewCmdSimple(protocol.RSP_CREATE_TOPIC_CMD) if len(cmd.GetArgs()) != 2 { 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 exist in CACHE", topicName) err = common.TOPIC_EXIST } else { log.Infof("TOPIC %s not exist in CACHE", topicName) topicStoreData, _ := self.msgServer.mongoStore.GetTopicFromCid(topicName) if topicStoreData != nil { log.Infof("TOPIC %s exist in STORE", topicName) err = common.TOPIC_EXIST } else { log.Infof("TOPIC %s not exist in STORE", topicName) // create the topic store log.Infof("Create topic %s in STORE", topicName) topicStoreData = mongo_store.NewTopicStoreData(topicName, ClientID) err = self.msgServer.mongoStore.Set(topicStoreData) if err != nil { log.Error(err.Error()) goto ErrOut } log.Infof("topic %s created in STORE", topicName) // create the topic cache log.Infof("Create topic %s in CACHE", topicName) topicCacheData = redis_store.NewTopicCacheData(topicStoreData) err = self.msgServer.topicCache.Set(topicCacheData) if err != nil { log.Error(err.Error()) goto ErrOut } log.Infof("topic %s created in CACHE", topicName) member := mongo_store.NewMember(ClientID, ClientName, ClientType) err = self.msgServer.procJoinTopic(member, topicName) } } } ErrOut: if err != nil { resp.AddArg(err.Error()) resp.AddArg(topicName) } else { resp.AddArg(protocol.RSP_SUCCESS) resp.AddArg(topicName) resp.AddArg(ClientName) } err = session.Send(libnet.Json(resp)) if err != nil { log.Error(err.Error()) } return err /* topicCacheData := redis_store.NewTopicCacheData(topicName, session.State.(*base.SessionState).ClientID, self.msgServer.cfg.LocalIP) t := protocol.NewTopic(topicName, self.msgServer.cfg.LocalIP, session.State.(*base.SessionState).ClientID, session) t.ClientIDList = append(t.ClientIDList, session.State.(*base.SessionState).ClientID) t.TSD = topicCacheData self.msgServer.topics[topicName] = t self.msgServer.topics[topicName].Channel = libnet.NewChannel(self.msgServer.server.Protocol()) self.msgServer.topics[topicName].Channel.Join(session, nil) log.Info(topicCacheData) args := make([]string, 0) args = append(args, topicName) CCmd := protocol.NewCmdInternal(protocol.CACHE_TOPIC_CMD, args, topicCacheData) m := redis_store.NewMember(session.State.(*base.SessionState).ClientID) CCmd.AnyData.(*redis_store.TopicCacheData).MemberList = append(CCmd.AnyData.(*redis_store.TopicCacheData).MemberList, m) 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 } } // store topic topicStoreData := mongo_store.NewTopicStoreData(topicName, session.State.(*base.SessionState).ClientID, self.msgServer.cfg.LocalIP) args = make([]string, 0) args = append(args, topicName) CCmd = protocol.NewCmdInternal(protocol.STORE_TOPIC_CMD, args, topicStoreData) member := mongo_store.NewMember(session.State.(*base.SessionState).ClientID) CCmd.AnyData.(*mongo_store.TopicStoreData).MemberList = append(CCmd.AnyData.(*mongo_store.TopicStoreData).MemberList, member) 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 }
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 }