/// <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));
        }
Exemple #5
0
 public static T As <T>(this byte[] bytes)
 {
     return(PiSerializer.DeserializeValue <T>(bytes));
 }
 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));
        }
        /// <summary>
        ///     bytes handler
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task OnMessage(byte[] data)
        {
            var pack = PiSerializer.Deserialize <RpcPackage>(data);

            switch (pack.Type)
            {
            case ERpc.Request:
            {
                try
                {
                    var rq = DataParser(pack.Data);
                    var rp = await _host.OnRequest(rq);

                    if (rp == null)
                    {
                        await Response(false, null, pack.Serial);
                    }
                    else
                    {
                        await Response(rp.Key, rp.Value, pack.Serial);
                    }
                }
                catch (Exception e)
                {
                    Logger.Ins.Error("Exception {0} : {1} when processing request {2}", e.Message,
                                     e.StackTrace, pack);
                    await Response(false, null, pack.Serial);
                }
                break;
            }

            case ERpc.Response:
            {
                try
                {
                    if (_requestPool.ContainsKey(pack.Serial))
                    {
                        var cb = _requestPool[pack.Serial];

                        Action <bool, byte[]> x;
                        if (!_requestPool.TryRemove(pack.Serial, out x))
                        {
                            Logger.Ins.Error("Remove response of serial {0} failed", pack.Serial);
                        }

                        cb(pack.Success, pack.Data);
                    }
                    else
                    {
                        Logger.Ins.Error("No target for response of serial {0}", pack.Serial);
                    }
                }
                catch (Exception e)
                {
                    Logger.Ins.Error("Exception {0} : {1} when processing response {2}", e.Message,
                                     e.StackTrace, pack);
                }
                break;
            }

            case ERpc.Push:
            {
                try
                {
                    var ps      = DataParser(pack.Data);
                    var success = await _host.OnPush(ps);

                    if (!success)
                    {
                        Logger.Ins.Error("Handle push {0} failed!", ps);
                    }
                }
                catch (Exception e)
                {
                    Logger.Ins.Error("Exception {0} : {1} when processing push {2}", e.Message,
                                     e.StackTrace, pack);
                }
            }
            break;

            default:
                Logger.Ins.Error("Invalid rpc type : {0} of  route : {1}", pack.Type, pack.Serial);
                _host.Close();
                break;
            }
        }