func (self *ProtoProc) procOfflineMsg(session *libnet.Session, ID string) error {
	var err error
	exist, err := self.msgServer.offlineMsgStore.IsKeyExist(ID)
	if exist.(int64) == 0 {
		return err
	} else {
		omrd, err := common.GetOfflineMsgFromOwnerName(self.msgServer.offlineMsgStore, ID)
		if err != nil {
			glog.Error(err.Error())
			return err
		}
		for _, v := range omrd.MsgList {
			resp := protocol.NewCmdSimple(protocol.RESP_MESSAGE_P2P_CMD)
			resp.AddArg(v.Msg)
			resp.AddArg(v.FromID)

			if self.msgServer.sessions[ID] != nil {
				self.msgServer.sessions[ID].Send(libnet.Json(resp))
				if err != nil {
					glog.Error(err.Error())
					return err
				}
			}
		}

		omrd.ClearMsg()
		self.msgServer.offlineMsgStore.Set(omrd)
	}

	return err
}
/*
   发送给消息接受者的消息
   MsgServer -> device/client
       REQ_SEND_P2P_MSG_CMD
       arg0: Msg           //消息内容
       arg1: FromID        //发送方用户ID
       arg2: uuid          //MsgServer分配的消息uuid,可选,如果提供了则须IND_ACK_P2P_STATUS_CMD(ClientID, uuid)
*/
func (self *ProtoProc) procOfflineMsg(session *libnet.Session, ID string) error {
	var err error
	exist, err := self.msgServer.offlineMsgCache.IsKeyExist(ID)
	if exist.(int64) == 0 {
		return err
	} else {
		omrd, err := common.GetOfflineMsgFromOwnerName(self.msgServer.offlineMsgCache, ID)
		if err != nil {
			log.Error(err.Error())
			return err
		}
		for _, v := range omrd.MsgList {
			if v.Msg == protocol.IND_ACK_P2P_STATUS_CMD {
				resp := protocol.NewCmdSimple(protocol.IND_ACK_P2P_STATUS_CMD)
				resp.AddArg(v.Uuid)
				resp.AddArg(v.FromID) // v.FromID is status
				if self.msgServer.sessions[ID] != nil {
					self.msgServer.sessions[ID].Send(libnet.Json(resp))
					if err != nil {
						log.Error(err.Error())
						return err
					}
				}
			} else {
				resp := protocol.NewCmdSimple(protocol.IND_SEND_P2P_MSG_CMD)
				resp.AddArg(v.Msg)
				resp.AddArg(v.FromID)
				resp.AddArg(v.Uuid)

				if self.msgServer.sessions[ID] != nil {
					self.msgServer.sessions[ID].Send(libnet.Json(resp))
					if err != nil {
						log.Error(err.Error())
						return err
					} else {
						self.procP2PAckStatus(v.FromID, v.Uuid, protocol.P2P_ACK_SENT)
					}
				}
			}
		}

		omrd.ClearMsg()
		self.msgServer.offlineMsgCache.Set(omrd)
	}

	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) procSendMessageP2P(cmd protocol.Cmd, session *libnet.Session) error {
	glog.Info("procSendMessageP2P")
	var err error
	send2ID := cmd.GetArgs()[0]
	send2Msg := cmd.GetArgs()[1]
	fromID := cmd.GetArgs()[2]
	store_session, err := common.GetSessionFromCID(self.msgServer.sessionStore, send2ID)
	if err != nil {
		glog.Warningf("no ID : %s", send2ID)

		return err
	}

	if self.msgServer.sessions[send2ID] == nil {
		//offline
		glog.Info(send2ID + " | is offline")
		exist, err := self.msgServer.offlineMsgStore.IsKeyExist(send2ID)
		if exist.(int64) == 0 {
			tmp := storage.NewOfflineMsgStoreData(send2ID)
			tmp.AddMsg(storage.NewOfflineMsgData(send2Msg, fromID))

			self.msgServer.offlineMsgStore.Set(tmp)
			if err != nil {
				glog.Error(err.Error())
				return err
			}
		} else {
			omrd, err := common.GetOfflineMsgFromOwnerName(self.msgServer.offlineMsgStore, send2ID)
			if err != nil {
				glog.Error(err.Error())
				return err
			}
			omrd.AddMsg(storage.NewOfflineMsgData(send2Msg, fromID))
			self.msgServer.offlineMsgStore.Set(omrd)
			if err != nil {
				glog.Error(err.Error())
				return err
			}
		}
	}

	if store_session.MsgServerAddr == self.msgServer.cfg.LocalIP {
		glog.Info("in the same server")
		resp := protocol.NewCmdSimple(protocol.RESP_MESSAGE_P2P_CMD)
		resp.AddArg(send2Msg)
		resp.AddArg(fromID)

		if self.msgServer.sessions[send2ID] != nil {
			self.msgServer.sessions[send2ID].Send(libnet.Json(resp))
			if err != nil {
				glog.Error(err.Error())
			}
		}
	} else {
		if self.msgServer.channels[protocol.SYSCTRL_SEND] != nil {
			_, err = self.msgServer.channels[protocol.SYSCTRL_SEND].Channel.Broadcast(libnet.Json(cmd))
			if err != nil {
				glog.Error(err.Error())
				return err
			}
		}
	}

	return nil
}
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
}