private void SendEvents(List <object> items)
        {
            long salt = this.GenSalt();

            IDictionary <string, object> payload = new Dictionary <string, object>();

            payload.Add("pid", this._pid);
            payload.Add("sign", this.GenSign(salt));
            payload.Add("salt", salt);
            payload.Add("events", items);

            MemoryStream outputStream = new MemoryStream();

            MsgPack.Serialize(payload, outputStream);
            outputStream.Position = 0;

            byte[] bytes = outputStream.ToArray();

            FPData data = new FPData();

            data.SetFlag(0x1);
            data.SetMtype(0x1);
            data.SetMethod("adds");
            data.SetPayload(bytes);

            RUMClient self = this;

            this.SendQuest(data, (cbd) => {
                self._rumEvent.RemoveFromCache(items);

                Exception ex = cbd.GetException();

                if (ex != null)
                {
                    self.GetEvent().FireEvent(new EventData("error", ex));
                    self._rumEvent.WriteEvents(items);
                    return;
                }
            }, RUMConfig.SENT_TIMEOUT);
        }
        private void SendPing(long timestamp)
        {
            if (this._lastPingTime == 0)
            {
                return;
            }

            if (timestamp - this._lastPingTime < RUMConfig.PING_INTERVAL)
            {
                return;
            }

            this._lastPingTime += RUMConfig.PING_INTERVAL;

            if (this._debug)
            {
                Debug.Log("[RUM] ping...");
            }

            long lastEid   = this._pingEid;
            int  lastCount = this._writeCount;

            this._writeCount = 0;
            this._pingEid    = MidGenerator.Gen();

            long salt = this.GenSalt();

            IDictionary <string, object> payload = new Dictionary <string, object>();

            payload.Add("pid", this._pid);
            payload.Add("sign", this.GenSign(salt));
            payload.Add("salt", salt);
            payload.Add("uid", this._uid);
            payload.Add("rid", this._rumEvent.GetRumId());
            payload.Add("sid", this._session);
            payload.Add("cv", this._configVersion);
            payload.Add("pt", this._pingLatency);
            payload.Add("ss", this._rumEvent.GetStorageSize());
            payload.Add("wc", lastCount);
            payload.Add("feid", lastEid);
            payload.Add("teid", this._pingEid);

            MemoryStream outputStream = new MemoryStream();

            MsgPack.Serialize(payload, outputStream);
            outputStream.Position = 0;

            byte[] bytes = outputStream.ToArray();

            FPData data = new FPData();

            data.SetFlag(0x1);
            data.SetMtype(0x1);
            data.SetMethod("ping");
            data.SetPayload(bytes);

            long      pingTime = timestamp;
            RUMClient self     = this;

            this.SendQuest(data, (cbd) => {
                self._pingLatency = Convert.ToInt32(ThreadPool.Instance.GetMilliTimestamp() - pingTime);

                Exception ex = cbd.GetException();

                if (ex != null)
                {
                    self.GetEvent().FireEvent(new EventData("error", ex));
                    return;
                }

                IDictionary <string, object> dict = (IDictionary <string, object>)cbd.GetPayload();

                if (self._debug)
                {
                    Debug.Log("[RUM] ping: " + Json.SerializeToString(dict));
                }

                self._rumEvent.SetTimestamp(Convert.ToInt64(dict["ts"]));
                self._rumEvent.SetSizeLimit(Convert.ToInt32(dict["bw"]));

                int cv = Convert.ToInt32(dict["cv"]);

                if (self._configVersion != cv || (cv == 0 && !self._rumEvent.HasConfig()))
                {
                    self._configVersion = cv;
                    this.LoadConfig();
                }
            }, RUMConfig.PING_INTERVAL);
        }
        private void LoadConfig()
        {
            if (this._debug)
            {
                Debug.Log("[RUM] load config...");
            }

            long salt = this.GenSalt();

            IDictionary <string, object> payload = new Dictionary <string, object>();

            payload.Add("pid", this._pid);
            payload.Add("sign", this.GenSign(salt));
            payload.Add("salt", salt);
            payload.Add("uid", this._uid);
            payload.Add("rid", this._rumEvent.GetRumId());

            payload.Add("lang", RUMPlatform.Instance.GetLang());
            payload.Add("manu", RUMPlatform.Instance.GetManu());
            payload.Add("model", RUMPlatform.Instance.GetModel());
            payload.Add("os", RUMPlatform.Instance.GetOS());
            payload.Add("osv", RUMPlatform.Instance.GetOSV());
            payload.Add("nw", RUMPlatform.Instance.GetNetwork());
            payload.Add("carrier", RUMPlatform.Instance.GetCarrier());
            payload.Add("from", RUMPlatform.Instance.GetFrom());
            payload.Add("appv", this._appv);

            MemoryStream outputStream = new MemoryStream();

            MsgPack.Serialize(payload, outputStream);
            outputStream.Position = 0;

            byte[] bytes = outputStream.ToArray();

            FPData data = new FPData();

            data.SetFlag(0x1);
            data.SetMtype(0x1);
            data.SetMethod("getconfig");
            data.SetPayload(bytes);

            RUMClient self = this;

            this.SendQuest(data, (cbd) => {
                Exception ex = cbd.GetException();

                if (ex != null)
                {
                    self._configVersion = 0;
                    self.GetEvent().FireEvent(new EventData("error", ex));
                    return;
                }

                IDictionary <string, object> dict = (IDictionary <string, object>)cbd.GetPayload();

                if (self._debug)
                {
                    Debug.Log("[RUM] load config: " + Json.SerializeToString(dict));
                }

                self._rumEvent.UpdateConfig((IDictionary <string, object>)dict["events"]);
            }, RUMConfig.SENT_TIMEOUT);
        }
        public void Connect(string endpoint, bool clearRumId, bool clearEvents)
        {
            if (this._baseClient != null)
            {
                this.GetEvent().FireEvent(new EventData("error", new Exception("client has been init!")));
                return;
            }

            if (clearRumId)
            {
                this._rumEvent.ClearRumId();
            }

            if (clearEvents)
            {
                this._rumEvent.ClearEvents();
            }

            if (this._debug)
            {
                Debug.Log("[RUM] init: " + endpoint);
            }

            this.OpenEvent();

            RUMClient self = this;

            ThreadPool.Instance.StartTimerThread();

            this._baseClient = new FPClient(endpoint, false, RUMConfig.CONNCT_INTERVAL);

            this._baseClient.GetEvent().AddListener("connect", (evd) => {
                if (self._debug)
                {
                    Debug.Log("[RUM] connect on rum agent!");
                }

                self.GetEvent().FireEvent(new EventData("ready"));

                self.StartPing();
                self.StartSend();
            });

            this._baseClient.GetEvent().AddListener("close", (evd) => {
                if (self._debug)
                {
                    Debug.Log("[RUM] close from rum agent!");
                }

                self.StopPing();
                self.StopSend();

                self._lastConnectTime = ThreadPool.Instance.GetMilliTimestamp();
                self.GetEvent().FireEvent(new EventData("close"));
            });

            this._baseClient.GetEvent().AddListener("error", (evd) => {
                if (self._debug)
                {
                    Debug.Log("[RUM] error: " + evd.GetException().Message);
                }

                self.GetEvent().FireEvent(new EventData("error", evd.GetException()));
            });

            this._baseClient.GetEvent().AddListener("second", (evd) => {
                self.OnSecond(evd.GetTimestamp());
            });

            this._baseClient.Connect();
        }