/// <summary> /// Handles an incomming raw Gds message. /// </summary> /// <param name="channel"></param> /// <param name="obj"></param> public void HandleIncoming(ISockNetChannel channel, ref object obj) { if (!(obj is ChunkedBuffer)) { return; } ChunkedBuffer stream = (ChunkedBuffer)obj; long startingPosition = stream.ReadPosition; try { GdsFrame frame = GdsFrame.ParseFrame(stream.Stream, channel.BufferPool); if (combineChunks) { if (frame.IsComplete) { UpdateChunk(ref chunkedFrame, frame, channel); obj = chunkedFrame; chunkedFrame = null; } else { UpdateChunk(ref chunkedFrame, frame, channel); } } else { obj = frame; } if (SockNetLogger.DebugEnabled) { SockNetLogger.Log(SockNetLogger.LogLevel.DEBUG, this, "Received Gds message. Body Size: {0}, Type: {1}, IsComplete: {2}", frame.Body.AvailableBytesToRead, Enum.GetName(typeof(GdsFrame.GdsFrameType), frame.Type), frame.IsComplete); } } catch (EndOfStreamException) { // frame isn't done stream.ReadPosition = startingPosition; } catch (ArgumentOutOfRangeException) { // frame isn't done stream.ReadPosition = startingPosition; } catch (Exception e) { SockNetLogger.Log(SockNetLogger.LogLevel.ERROR, this, "Unable to parse Gds message", e); } }
/// <summary> /// Updates the given chunked frame with a new frame. /// </summary> /// <param name="frame"></param> private static void UpdateChunk(ref GdsFrame chunkedFrame, GdsFrame frame, ISockNetChannel channel) { if (chunkedFrame == null) { chunkedFrame = frame; // set initial frame } else { if (frame.Type == GdsFrame.GdsFrameType.Ping || frame.Type == GdsFrame.GdsFrameType.Pong || frame.Type == GdsFrame.GdsFrameType.Close) { chunkedFrame = frame; } GdsFrame.GdsFrameType type = chunkedFrame.Type; ChunkedBuffer body = null; if (frame.Type == GdsFrame.GdsFrameType.BodyOnly || frame.Type == GdsFrame.GdsFrameType.Full) { if (type == GdsFrame.GdsFrameType.HeadersOnly) { type = GdsFrame.GdsFrameType.Full; } body = new ChunkedBuffer(channel.BufferPool); chunkedFrame.Body.DrainToStreamSync(body.Stream).Close(); frame.Body.DrainToStreamSync(body.Stream).Close(); } Dictionary<string, byte[]> headers = null; if (frame.Type == GdsFrame.GdsFrameType.HeadersOnly || frame.Type == GdsFrame.GdsFrameType.Full) { if (type == GdsFrame.GdsFrameType.BodyOnly) { type = GdsFrame.GdsFrameType.Full; } headers = new Dictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair<string, byte[]> kvp in chunkedFrame.Headers) { headers[kvp.Key] = kvp.Value; } foreach (KeyValuePair<string, byte[]> kvp in frame.Headers) { headers[kvp.Key] = kvp.Value; } } chunkedFrame.Dispose(); frame.Dispose(); chunkedFrame = GdsFrame.NewContentFrame(frame.StreamId, headers, false, body, frame.IsComplete); } }
public ChunkedBuffer ToBuffer(GdsFrame frame) { ObjectPool<byte[]> pool = new ObjectPool<byte[]>(() => { return new byte[1024]; }); ChunkedBuffer buffer = new ChunkedBuffer(pool); frame.Write(buffer.Stream); return buffer; }