private /*async ValueTask*/ void OnReceiveMessage(BytesSegment frame, bool isEnd) { if (!isEnd) { if (pending != null) { pending.Append(frame); } pending = frame; } else { //检查有没有前面的消息帧 if (pending != null) { pending.Append(frame); pending = null; } //开始读取消息标识并从挂起请求中查找 var msgId = ReadMsgIdFromResponse(frame.First); if (waits.TryGetValue(msgId, out PooledTaskSource <object> tcs)) { tcs.SetResult(frame); //注意为最后一包 } else { BytesSegment.ReturnAll(frame.First); } } }
internal async ValueTask OnReceiveMessage(BytesSegment frame, bool isEnd) { if (!isEnd) { if (pending != null) { pending.Append(frame); } pending = frame; } else { //检查有没有前面的消息帧 if (pending != null) { pending.Append(frame); pending = null; } //开始读取消息 int msgId = 0; string service = null; //TODO:优化不创建string int offset = 0; //偏移量至参数数组开始,不包含[Token Exception requireError = null; try { offset = InvokeHelper.ReadRequireHead(frame.First, ref msgId, ref service); if (offset == -1) //没有参数 { BytesSegment.ReturnOne(frame); } } catch (Exception ex) { requireError = ex; BytesSegment.ReturnAll(frame); //读消息头异常归还缓存块 } if (requireError != null) { Log.Warn(string.Format("收到无效的Api调用请求: {0}", requireError.Message)); await SendInvokeResponse(msgId, AnyValue.From(requireError)); return; } _ = ProcessInvokeRequire(msgId, service, frame, offset); //no need await } }
private ReadOnlySequence <byte> BuildDescription(IPlayer player, IEnumerable <ITile> descriptionTiles) { byte currentSkipCount = byte.MaxValue; var firstSegment = new BytesSegment(ReadOnlyMemory <byte> .Empty); BytesSegment lastSegment = firstSegment; foreach (var tile in descriptionTiles) { var segmentsFromTile = this.tileDescriptor.DescribeTileForPlayer(player, tile); // See if we actually have segments to append. if (segmentsFromTile != null && segmentsFromTile.Any()) { if (currentSkipCount < byte.MaxValue) { lastSegment = lastSegment.Append(new byte[] { currentSkipCount, byte.MaxValue }); } foreach (var segment in segmentsFromTile) { lastSegment.Append(segment); lastSegment = segment; } currentSkipCount = byte.MinValue; continue; } if (++currentSkipCount == byte.MaxValue) { lastSegment = lastSegment.Append(new byte[] { byte.MaxValue, byte.MaxValue }); } } if (++currentSkipCount < byte.MaxValue) { lastSegment = lastSegment.Append(new byte[] { currentSkipCount, byte.MaxValue }); } return(new ReadOnlySequence <byte>(firstSegment, 0, lastSegment, lastSegment.Memory.Length)); }
public void ReadObject(BinSerializer bs) { Source = (InvokeSource)bs.ReadByte(); Protocol = (InvokeProtocol)bs.ReadByte(); long hv = 0; unsafe { var span = new Span <byte>(&hv, 8); bs.Stream.Read(span); } WaitHandle = new IntPtr(hv); if (Protocol == InvokeProtocol.Bin) { SourceMsgId = bs.ReadInt32(); Error = (InvokeResponseError)bs.ReadByte(); var temp = new AnyValue(); temp.ReadObject(bs); Result = temp; //Don't use Result.ReadObject(bs) } else { //注意将子进程已序列化的结果读到缓存块内,缓存块由相应的通道处理并归还 var stream = (MessageReadStream)bs.Stream; BytesSegment cur = null; int len; while (stream.HasData) { var temp = BytesSegment.Rent(); len = bs.Stream.Read(temp.Buffer.AsSpan()); temp.Length = len; if (cur != null) { cur.Append(temp); } cur = temp; } Result = AnyValue.From(cur.First); } }
public async Task Invoke(HttpContext context) { //暂简单处理,读请求数据至缓存块,然后走与WebSocket相同的流程 //待实现Utf8JsonReaderStream后再修改 int bytesRead = 0; int totalBytes = (int)context.Request.ContentLength.Value; BytesSegment frame = null; while (bytesRead < totalBytes) //TODO:读错误归还缓存块 { var temp = BytesSegment.Rent(); int len = await context.Request.Body.ReadAsync(temp.Buffer.AsMemory()); temp.Length = len; bytesRead += len; if (frame != null) { frame.Append(temp); } frame = temp; } //1. 解析请求头 int msgId = 0; string service = null; //TODO:优化不创建string int offset = 0; //偏移量至参数数组开始,不包含[Token AnyValue res = AnyValue.Empty; try { offset = InvokeHelper.ReadRequireHead(frame.First, ref msgId, ref service); if (offset == -1) //没有参数 { BytesSegment.ReturnOne(frame); } } catch (Exception ex) { res = AnyValue.From(ex); BytesSegment.ReturnAll(frame); //读消息头异常归还缓存块 Log.Warn($"收到无效的Api调用请求: {ex.Message}\n{ex.StackTrace}"); } //2. 设置当前会话并调用服务 if (res.ObjectValue == null) { var webSession = context.Session.LoadWebSession(); RuntimeContext.Current.CurrentSession = webSession; try { var hostCtx = (HostRuntimeContext)RuntimeContext.Current; res = await hostCtx.InvokeByClient(service, 0, InvokeArgs.From(frame, offset)); } catch (Exception ex) { Log.Warn($"调用服务异常: {ex.Message}\n{ex.StackTrace}"); res = AnyValue.From(ex); } } //3. 返回结果,注意:FileResult特殊类型统一由BlobController处理 context.Response.ContentType = "application/json"; if (res.Type == AnyValueType.Object && res.ObjectValue is BytesSegment) { var cur = (ReadOnlySequenceSegment <byte>)res.ObjectValue; try { while (cur != null) { await context.Response.Body.WriteAsync(cur.Memory); cur = cur.Next; } } catch (Exception ex) { Log.Warn($"Send InvokeResponse to ajax error: {ex.Message}"); } finally { BytesSegment.ReturnAll((BytesSegment)res.ObjectValue); //注意归还缓存块 } } else { res.SerializeAsInvokeResponse(context.Response.Body, 0);//TODO:序列化错误处理 } }