public int logout(string profile = "")
        {
            if (mState.HaveLogin())
            {
                _mGTWNw?.send(_mPro.en(CmdId.LogoutReq, profile));
                _mGTWNw?.close();
                _mGTWNw = null;
                mState.clearState(State.LOGIN);
                var rsp = new LogoutRsp();
                rsp.Status = ErrorCode.Ok;
                callback("logoutResponse", rsp);
            }

            if (mState.isHaveState(State.RECONNECT))
            {
                mState.clearState(State.RECONNECT);
            }

            if (mState.HaveInRoom())
            {
                _mHNw?.close();
                _mHNw = null;
                mState.clearState(State.ROOM);
            }

            if (mState.HaveInWatch())
            {
                _mWNw?.close();
                _mWNw = null;
                mState.clearState(State.WATCH);
            }

            return(0);
        }
        private void loginConnect()
        {
            _mGTWNw?.close();
            this._mGTWNw = new NW(MVS.Host.HOST_GATWAY_ADDR, this);
            var buf = this._mPro.en(CmdId.LoginReq, MVS.UserID, MVS.Token, MVS.GameID, MVS.Appkey, MVS.DeviceID);

            this.mState.SetLogin();
            this._mGTWNw.send(buf);
            Log.i("login,userID" + MVS.UserID + ", token:" + MVS.Token);
        }
        public void disconnect()
        {
            _mGTWNw?.close();
            _mGTWNw = null;

            _mWNw?.close();
            _mWNw = null;

            _mHNw?.close();
            _mHNw = null;
        }
        private void connectWatch(JoinWatchRoomRsp d)
        {
            BookInfo bookInfo = d.BookInfo;

            MVS.Host.HOST_WATCH_ADDR = MVS.getHotelUrl(bookInfo);
            MVS.WatchRoomID          = d.RoomID;
            frameWatchCache          = new Queue <LiveFrameDataNotify>();
            _mWNw = new NW(MVS.Host.HOST_WATCH_ADDR, this);
            var buf = _mPro.en(SDKWatchCmdID.EnterLiveRoomCmdid, bookInfo, d.RoomID, MVS.UserID, MVS.GameID, MVS.NodeID);

            _mWNw?.send(buf);
            lastJoinWatchRoomRsp = d;
        }
        private void connectHotel(JoinRoomRsp d)
        {
            BookInfo bookInfo = d.BookInfo;

            MVS.Host.HOST_HOTEL_ADDR = MVS.getHotelUrl(bookInfo);
            MVS.RoomID      = d.RoomInfo.RoomID;
            this.frameCache = new Queue <FrameDataNotify>();
            this._mHNw      = new NW(MVS.Host.HOST_HOTEL_ADDR, this);
            var buf = _mPro.en(SDKHotelCmdID.CheckinCmdid, bookInfo, d.RoomInfo, MVS.UserID, MVS.GameID);

            this._mHNw?.send(buf);
            this.lastJoinRoomRsp = d;
        }
        public void onErr(string host, int errCode, string errMsg)
        {
            if (errCode == 1006)
            {
                Log.w("connect.onErr:  code:{0},msg:{1}", host, errCode, errMsg);
            }

            if (errCode >= 1000)
            {
                if (host == MVS.Host.HOST_HOTEL_ADDR)
                {
                    _mHNw = null;
                    mState.clearState(State.ROOM);
                    Log.d("[INFO] [disconnect] hotel:{0}", host);
                }

                if (host == MVS.Host.HOST_WATCH_ADDR)
                {
                    _mWNw = null;
                    mState.clearState(State.WATCH);
                    Log.d("[INFO] [disconnect] watch :{0}", host);
                }

                if (host == MVS.Host.HOST_GATWAY_ADDR)
                {
                    _mGTWNw = null;
                    mState.clearState(State.LOGIN);

                    _mHNw?.close();
                    _mHNw = null;
                    mState.clearState(State.ROOM);

                    _mWNw?.close();
                    _mWNw = null;
                    mState.clearState(State.WATCH);

                    Log.d("[INFO] [disconnect] gateway:{0}", host);
                }
            }

            callback("errorResponse", errCode, errMsg);
        }
        public void onMsg(byte[] buf)
        {
            Pro.He header = _mPro.de(buf);
            if (header == null)
            {
                return;
            }

            Log.d("[INFO] onMsg.header.cmd:{0}", header.cmd);
            switch (header.cmd)
            {
            case (int)CmdId.LoginRsp:
                LoginRsp loginRsp = (LoginRsp)header.deserialization;
                if (loginRsp.Status == ErrorCode.Ok)
                {
                    mState.setState(State.LOGIN);
                }
                else
                {
                    Log.w("[WARN] login fail:{0}", loginRsp.Status);
                    mState.clearState(State.LOGIN);
                    return;
                }

                MVS.RoomID = (loginRsp.RoomID != 0 ? loginRsp.RoomID:MVS.RoomID);
                MVS.TeamID = (loginRsp.TeamID != 0 ? loginRsp.TeamID:MVS.TeamID);
                if (mState.isHaveState(State.RECONNECT))
                {
                    reconnect();
                }

                callback("loginResponse", loginRsp);
                break;

            case (int)CmdId.LogoutRsp:
                callback("logoutResponse", header.deserialization);
                break;

            case (int)CmdId.CreateRoomRsp:
                connectHotel((CreateRoomRsp)header.deserialization);
                break;

            case (int)CmdId.JoinRoomRsp:
                var joinRoomRsp = (JoinRoomRsp)header.deserialization;
                if (joinRoomRsp.Status != ErrorCode.Ok)
                {
                    Log.w("[WARN] fail, join room:{0}", joinRoomRsp);
                    mState.clearState(State.ROOM);
                    this.onErr("", (int)joinRoomRsp.Status, "join room fail:" + joinRoomRsp);
                    return;
                }

                connectHotel((JoinRoomRsp)header.deserialization);
                break;

            case (int)CmdId.NoticeUserJoinReq:
                callback("joinRoomNotify", ((NoticeJoin)header.deserialization).User);
                break;

            case (int)CmdId.JoinOverRsp:
                callback("joinOverResponse", (JoinOverRsp)header.deserialization);
                break;

            case (int)CmdId.JoinOverNotify:
                callback("joinOverNotify", (JoinOverNotify)header.deserialization);
                break;

            case (int)CmdId.JoinOpenRsp:
                callback("joinOpenResponse", (JoinOpenRsp)header.deserialization);
                break;

            case (int)CmdId.JoinOpenNotify:
                callback("joinOpenNotify", (JoinOpenNotify)header.deserialization);
                break;

            case (int)CmdId.SetRoomPropertyRsp:
                callback("setRoomPropertyResponse", (SetRoomPropertyRsp)header.deserialization);
                break;

            case (int)CmdId.NoticeRoomProperty:
                callback("setRoomPropertyNotify", (NoticeRoomProperty)header.deserialization);
                break;

            case (int)CmdId.RoomListExRsp:
                callback("getRoomListExResponse", (GetRoomListExRsp)header.deserialization);
                break;

            case (int)CmdId.GetRoomDetailRsp:
                callback("getRoomDetailResponse", (GetRoomDetailRsp)header.deserialization);
                break;

            case (int)SDKHotelCmdID.CheckinAckCmdid:
                if (lastJoinRoomRsp == null)
                {
                    Log.w("[WARN] lastJoinRoomRsp is null when hotel ack");
                    break;
                }

                if (lastJoinRoomRsp is JoinRoomRsp)
                {
                    List <PlayerInfo> userList = new List <PlayerInfo>();
                    var d = (JoinRoomRsp)lastJoinRoomRsp;
                    if (d.Users != null && d.Users.Count > 0)
                    {
                        IEnumerator <PlayerInfo> iterator = d.Users.GetEnumerator();
                        while (true)
                        {
                            bool result = iterator.MoveNext();
                            if (!result)
                            {
                                break;
                            }

                            userList.Add(iterator.Current);
                        }
                    }

                    callback("joinRoomResponse", (int)d.Status, userList, d.RoomInfo);
                }
                else if (lastJoinRoomRsp is CreateRoomRsp)
                {
                    var d = (CreateRoomRsp)lastJoinRoomRsp;
                    callback("createRoomResponse", d);
                }
                else if (lastJoinRoomRsp is TeamMatchResultNotify)
                {
                    callback("teamMatchResultNotify", lastJoinRoomRsp);
                }
                else
                {
                    Log.w("[warn] unknown hotel checkin:{0}", lastJoinRoomRsp);
                }

                break;


            case (int)SDKHotelCmdID.BroadcastAckCmdid:
                callback("sendEventResponse", ((BroadcastAck)header.deserialization).Status);
                break;

            case (int)SDKHotelCmdID.NotifyCmdid:
                Notify r = ((Notify)header.deserialization);
                callback("sendEventNotify", r.SrcUid, r.CpProto.ToByteArray());
                break;

            case (int)CmdId.LeaveRoomRsp:
                _mHNw?.close();
                _mHNw      = null;
                MVS.RoomID = 0;
                mState.clearState(State.ROOM);
                callback("leaveRoomResponse", ((LeaveRoomRsp)header.deserialization));
                break;

            case (int)CmdId.NoticeUserLeaveReq:
                callback("leaveRoomNotify", ((NoticeLeave)header.deserialization));
                break;

            case (int)SDKHotelCmdID.FrameBroadcastAckCmdid:
                //
                callback("sendFrameEventResponse", ((FrameBroadcastAck)header.deserialization));
                break;

            case (int)SDKHotelCmdID.FrameDataNotifyCmdid:
                frameCache.Enqueue((FrameDataNotify)header.deserialization);
                break;

            case (int)SDKHotelCmdID.FrameSyncNotifyCmdid:
                var frameData = new FrameDataNotify[frameCache.Count];
                for (var i = 0; i < frameCache.Count; i++)
                {
                    frameData[i] = frameCache.Dequeue();
                }

                callback("frameUpdate",
                         new MsFrameData(((FrameSyncNotify)header.deserialization).LastIdx, frameData));
                break;

            case (int)SDKHotelCmdID.SetFrameSyncRateNotifyCmdid:
                callback("setFrameSyncNotify", ((SetFrameSyncRateNotify)header.deserialization));
                break;

            case (int)SDKHotelCmdID.SetFrameSyncRateAckCmdid:
                callback("setFrameSyncResponse", ((SetFrameSyncRateAck)header.deserialization));
                break;

            case (int)CmdId.NoticeTeamNetworkState:
                callback("teamNetworkStateNotify", header.deserialization);
                break;

            case (int)CmdId.NoticeRoomNetworkState:
                callback("networkStateNotify", header.deserialization);
                break;

            //watch
            case (int)CmdId.GetWatchRoomsRsp:
                callback("getWatchRoomsResponse", (GetWatchRoomsRsp)header.deserialization);
                break;

            case (int)CmdId.JoinWatchRoomRsp:
                var rsp = (JoinWatchRoomRsp)header.deserialization;
                if (rsp.Status == ErrorCode.Ok)
                {
                    connectWatch(rsp);
                }
                else
                {
                    callback("errorResponse", rsp.Status, "join watch room is fail");
                }

                break;

            case (int)CmdId.JoinWatchRoomNotify:
                callback("joinWatchRoomNotify", (JoinWatchRoomNotify)header.deserialization);
                break;

            case (int)SDKWatchCmdID.EnterLiveRoomAckCmdid:
                mState.SetWatch();
                var liveEA = (EnterLiveRoomAck)header.deserialization;
                callback("joinWatchRoomResponse", liveEA);
                break;

            case (int)SDKWatchCmdID.EnterLiveRoomNotifyCmdid:
                callback("enterLiveRoomNotify", (EnterLiveRoomNotify)header.deserialization);
                break;

            case (int)CmdId.LeaveWatchRoomRsp:
                _mWNw?.close();
                _mWNw           = null;
                MVS.WatchRoomID = 0;
                mState.clearState(State.WATCH);
                callback("leaveWatchRoomResponse", (LeaveWatchRoomRsp)header.deserialization);
                break;

            case (int)CmdId.LeaveWatchRoomNotify:
                callback("leaveWatchRoomNotify", (LeaveWatchRoomNotify)header.deserialization);
                break;

            case (int)SDKWatchCmdID.ExitLiveRoomNotifyCmdid:
                callback("exitLiveRoomNotify", (ExitLiveRoomNotify)header.deserialization);
                break;

            case (int)SDKWatchCmdID.LiveBroadcastAckCmdid:
                callback("sendLiveEventResponse", (LiveBroadcastAck)header.deserialization);
                break;

            case (int)SDKWatchCmdID.LiveBroadcastNotifyCmdid:
                callback("sendLiveEventNotify", (LiveBroadcastNotify)header.deserialization);
                break;

            case (int)SDKWatchCmdID.LiveFrameDataNotifyCmdid:
                frameWatchCache.Enqueue((LiveFrameDataNotify)header.deserialization);
                break;

            case (int)SDKWatchCmdID.LiveFrameSyncNotifyCmdid:
                var frameLiveData = new LiveFrameDataNotify[frameWatchCache.Count];
                for (var i = 0; i < frameLiveData.Length; i++)
                {
                    frameLiveData[i] = frameWatchCache.Dequeue();
                }

                callback("liveFrameUpdate", (LiveFrameSyncNotify)header.deserialization, frameLiveData);
                break;

            case (int)SDKWatchCmdID.SetLiveOffsetAckCmdid:
                callback("setLiveOffsetResponse", (SetLiveOffsetAck)header.deserialization);
                break;

            case (int)SDKWatchCmdID.LiveOverNotifyCmdid:
                callback("liveOverNotify", (LiveOverNotify)header.deserialization);
                break;


            //team
            case (int)CmdId.TeamMatchRsp:
                callback("teamMatchResponse", (TeamMatchRsp)header.deserialization);
                break;

            case (int)CmdId.TeamMatchStartNotify:
                callback("teamMatchStartNotify", (TeamMatchStartNotify)header.deserialization);
                break;

            case (int)CmdId.TeamMatchResultNotify:
                var teamMatchResult = (TeamMatchResultNotify)header.deserialization;
                if (teamMatchResult.Status == ErrorCode.Ok)
                {
                    connectHotel(teamMatchResult);
                    mState.setState(State.ROOM);
                }
                else
                {
                    callback("teamMatchResultNotify", (TeamMatchResultNotify)header.deserialization);
                }


                break;

            case (int)CmdId.CancelTeamMatchRsp:
                callback("cancelTeamMatchResponse", (CancelTeamMatchRsp)header.deserialization);
                break;

            case (int)CmdId.CancelTeamMatchNotify:
                callback("cancelTeamMatchNotify", (CancelTeamMatchNotify)header.deserialization);
                break;

            case (int)CmdId.KickTeamMemberRsp:
                callback("kickTeamMemberResponse", (KickTeamMemberRsp)header.deserialization);
                break;

            case (int)CmdId.KickTeamMemberNotify:
                callback("kickTeamMemberNotify", header.deserialization);
                break;

            case (int)CmdId.SendTeamEventRsp:
                callback("sendTeamEventResponse", (SendTeamEventRsp)header.deserialization);
                break;

            case (int)CmdId.SendTeamEventNotify:
                callback("sendTeamEventNotify", (SendTeamEventNotify)header.deserialization);
                break;

            case (int)CmdId.LeaveTeamNotify:
                callback("leaveTeamNotify", (LeaveTeamNotify)header.deserialization);
                break;

            case (int)CmdId.LeaveTeamRsp:
                callback("leaveTeamResponse", (LeaveTeamRsp)header.deserialization);
                break;

            case (int)CmdId.JoinTeamNotify:
                callback("joinTeamNotify", (JoinTeamNotify)header.deserialization);
                break;

            case (int)CmdId.JoinTeamRsp:
                var joinTeamRsp = (JoinTeamRsp)header.deserialization;
                callback("joinTeamResponse", joinTeamRsp);
                if (joinTeamRsp.Status == ErrorCode.Ok)
                {
                    MVS.TeamID = joinTeamRsp.TeamInfo.TeamID;
                }

                break;

            case (int)CmdId.SetTeamPropertyRsp:
                callback("setTeamPropertyResponse", (SetTeamPropertyRsp)header.deserialization);
                break;

            case (int)CmdId.NoticeTeamProperty:
                callback("setTeamPropertyNotify", (NoticeTeamProperty)header.deserialization);
                break;

            case (int)CmdId.SetTeamUserProfileRsp:
                callback("setTeamUserProfileResponse", (SetTeamUserProfileRsp)header.deserialization);
                break;

            case (int)CmdId.NoticeTeamUserProfile:
                callback("setTeamUserProfileNotify", (NoticeTeamUserProfile)header.deserialization);
                break;

            case (int)CmdId.SetReconnectTimeoutRsp:
                callback("setReconnectTimeoutResponse", (SetReconnectTimeoutRsp)header.deserialization);
                break;

            case (int)CmdId.SetTeamReconnectTimeoutRsp:
                callback("setTeamReconnectTimeoutResponse", (SetTeamReconnectTimeoutRsp)header.deserialization);
                break;

            case (int)CmdId.CreateTeamRsp:
                MVS.TeamID = ((CreateTeamRsp)header.deserialization).TeamID;
                callback("createTeamResponse", header.deserialization);
                break;

            case (int)CmdId.KickPlayerRsp:
                callback("kickPlayerResponse", header.deserialization);
                break;

            case (int)CmdId.KickPlayerNotify:
                var k = (KickPlayerNotify)header.deserialization;
                callback("kickPlayerNotify", header.deserialization);
                if (MVS.UserID == k.UserID)
                {
                    _mHNw?.close();
                }

                break;
            }
        }