/// <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)); }
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; } }