/// <summary>
        ///     request asynchronous
        ///     ordered by "serial"
        /// </summary>
        /// <param name="serial"></param>
        /// <param name="pack"></param>
        /// <returns></returns>
        private async Task <RpcResult> RequestAsync(ushort serial, RpcPackage pack)
        {
            var tcs = new TaskCompletionSource <RpcResult>();

            //  call back in logic service
            Action <bool, byte[]> cb =
                (b, bytes) => GlobalVarPool.Ins.Service.Perform(() =>
            {
                tcs.SetResult(new RpcResult(b, bytes));
            });

            // callback pool
            if (!_requestPool.TryAdd(serial, cb))
            {
                Logger.Ins.Error("Request of serial {0} already processing!", serial);
                return(RpcResult.Failure);
            }

            // send
            var sendRet = await SendAsync(PiSerializer.Serialize(pack));

            if (!sendRet)
            {
                Action <bool, byte[]> _;
                _requestPool.TryRemove(serial, out _);
                _ = _ ?? cb;

                _(false, null);
            }

            return(await tcs.Task);
        }
        /// <summary>
        /// 多播
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="proto"></param>
        /// <param name="sessions"></param>
        public void MultiCast <T>(T proto, IEnumerable <WebsocketSession> sessions) where T : IDataProtocol
        {
            var data = PiSerializer.Serialize(PackPush(proto));

            foreach (var session in sessions)
            {
                session.SendAsync(data);
            }
        }
        private async Task <RpcResult> Response(bool success, byte[] data, ushort serial)
        {
            var pack = new RpcPackage
            {
                Type    = ERpc.Response,
                Serial  = serial,
                Success = success,
                Data    = data,
            };

            return(await SendAsync(PiSerializer.Serialize(pack)));
        }
        /// <summary>
        /// </summary>
        /// <param name="proto"></param>
        /// <param name="cb"></param>
        /// <typeparam name="T"></typeparam>
        public void RequestAsync <T>(T proto, Action <bool, byte[]> cb) where T : IDataProtocol
        {
            var pack = PackRequest(proto);

            pack.Serial = GenerateSerial();

            if (!_requestPool.TryAdd(pack.Serial, cb))
            {
                Logger.Ins.Error("Request of serial {0} already processing!", pack.Serial);
                cb(false, null);
                return;
            }

            _host.Send(PiSerializer.Serialize(pack));
        }
 private static RpcPackage PackPush <T>(T proto) where T : IDataProtocol
 {
     return(new RpcPackage {
         Type = ERpc.Push, Data = PiSerializer.Serialize(proto)
     });
 }
 /// <summary>
 /// </summary>
 /// <param name="proto"></param>
 /// <typeparam name="T"></typeparam>
 public async Task <RpcResult> Push <T>(T proto) where T : IDataProtocol
 {
     return(await SendAsync(PiSerializer.Serialize(PackPush(proto))));
 }
        /// <summary>
        ///     send a proto asynchronous
        /// </summary>
        /// <param name="proto"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task <RpcResult> SendAsync <T>(T proto) where T : IDataProtocol
        {
            var data = PiSerializer.Serialize(proto);

            return(await SendAsync(data));
        }
        /// <summary>
        ///     asynchronous broadcast a proto
        /// </summary>
        /// <param name="proto"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public async Task <RpcResult> BroadcastAsync <T>(T proto) where T : IDataProtocol
        {
            var data = PiSerializer.Serialize(PackPush(proto));

            return(await BroadcastAsync(data));
        }