123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- #if (!UNITY_WEBGL || UNITY_EDITOR) && !BESTHTTP_DISABLE_ALTERNATE_SSL && !BESTHTTP_DISABLE_HTTP2
- using BestHTTP.PlatformSupport.Memory;
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace BestHTTP.Connections.HTTP2
- {
- interface IFrameDataView : IDisposable
- {
- long Length { get; }
- long Position { get; }
- void AddFrame(HTTP2FrameHeaderAndPayload frame);
- int ReadByte();
- int Read(byte[] buffer, int offset, int count);
- }
- abstract class CommonFrameView : IFrameDataView
- {
- public long Length { get; protected set; }
- public long Position { get; protected set; }
- protected List<HTTP2FrameHeaderAndPayload> frames = new List<HTTP2FrameHeaderAndPayload>();
- protected int currentFrameIdx = -1;
- protected byte[] data;
- protected UInt32 dataOffset;
- protected UInt32 maxOffset;
- public abstract void AddFrame(HTTP2FrameHeaderAndPayload frame);
- protected abstract long CalculateDataLengthForFrame(HTTP2FrameHeaderAndPayload frame);
- public virtual int Read(byte[] buffer, int offset, int count)
- {
- if (this.dataOffset >= this.maxOffset && !AdvanceFrame())
- return -1;
- int readCount = 0;
- while (count > 0)
- {
- long copyCount = Math.Min(count, this.maxOffset - this.dataOffset);
- Array.Copy(this.data, this.dataOffset, buffer, offset + readCount, copyCount);
- count -= (int)copyCount;
- readCount += (int)copyCount;
- this.dataOffset += (UInt32)copyCount;
- this.Position += copyCount;
- if (this.dataOffset >= this.maxOffset && !AdvanceFrame())
- break;
- }
- return readCount;
- }
- public virtual int ReadByte()
- {
- if (this.dataOffset >= this.maxOffset && !AdvanceFrame())
- return -1;
- byte data = this.data[this.dataOffset];
- this.dataOffset++;
- this.Position++;
- return data;
- }
- protected abstract bool AdvanceFrame();
- public virtual void Dispose()
- {
- for (int i = 0; i < this.frames.Count; ++i)
- if (this.frames[i].Payload != null && !this.frames[i].DontUseMemPool)
- BufferPool.Release(this.frames[i].Payload);
- this.frames.Clear();
- }
- public override string ToString()
- {
- var sb = new System.Text.StringBuilder("[CommonFrameView ");
- for (int i = 0; i < this.frames.Count; ++i) {
- sb.AppendFormat("{0} Payload: {1}\n", this.frames[i], this.frames[i].PayloadAsHex());
- }
- sb.Append("]");
- return sb.ToString();
- }
- }
- sealed class HeaderFrameView : CommonFrameView
- {
- public override void AddFrame(HTTP2FrameHeaderAndPayload frame)
- {
- if (frame.Type != HTTP2FrameTypes.HEADERS && frame.Type != HTTP2FrameTypes.CONTINUATION)
- throw new ArgumentException("HeaderFrameView - Unexpected frame type: " + frame.Type);
- this.frames.Add(frame);
- this.Length += CalculateDataLengthForFrame(frame);
- if (this.currentFrameIdx == -1)
- AdvanceFrame();
- }
- protected override long CalculateDataLengthForFrame(HTTP2FrameHeaderAndPayload frame)
- {
- switch (frame.Type)
- {
- case HTTP2FrameTypes.HEADERS:
- return HTTP2FrameHelper.ReadHeadersFrame(frame).HeaderBlockFragmentLength;
- case HTTP2FrameTypes.CONTINUATION:
- return frame.PayloadLength;
- }
- return 0;
- }
- protected override bool AdvanceFrame()
- {
- if (this.currentFrameIdx >= this.frames.Count - 1)
- return false;
- this.currentFrameIdx++;
- HTTP2FrameHeaderAndPayload frame = this.frames[this.currentFrameIdx];
- this.data = frame.Payload;
- switch (frame.Type)
- {
- case HTTP2FrameTypes.HEADERS:
- var header = HTTP2FrameHelper.ReadHeadersFrame(frame);
- this.dataOffset = header.HeaderBlockFragmentIdx;
- this.maxOffset = this.dataOffset + header.HeaderBlockFragmentLength;
- break;
- case HTTP2FrameTypes.CONTINUATION:
- this.dataOffset = 0;
- this.maxOffset = frame.PayloadLength;
- break;
- }
- return true;
- }
- }
- sealed class DataFrameView : CommonFrameView
- {
- public override void AddFrame(HTTP2FrameHeaderAndPayload frame)
- {
- if (frame.Type != HTTP2FrameTypes.DATA)
- throw new ArgumentException("HeaderFrameView - Unexpected frame type: " + frame.Type);
- this.frames.Add(frame);
- this.Length += CalculateDataLengthForFrame(frame);
- }
- protected override long CalculateDataLengthForFrame(HTTP2FrameHeaderAndPayload frame)
- {
- return HTTP2FrameHelper.ReadDataFrame(frame).DataLength;
- }
- protected override bool AdvanceFrame()
- {
- if (this.currentFrameIdx >= this.frames.Count - 1)
- return false;
- this.currentFrameIdx++;
- HTTP2FrameHeaderAndPayload frame = this.frames[this.currentFrameIdx];
- HTTP2DataFrame dataFrame = HTTP2FrameHelper.ReadDataFrame(frame);
- this.data = frame.Payload;
- this.dataOffset = dataFrame.DataIdx;
- this.maxOffset = dataFrame.DataIdx + dataFrame.DataLength;
- return true;
- }
- }
- sealed class FramesAsStreamView : Stream
- {
- public override bool CanRead { get { return true; } }
- public override bool CanSeek { get { return false; } }
- public override bool CanWrite { get { return false; } }
- public override long Length { get { return this.view.Length; } }
- public override long Position { get { return this.view.Position; } set { throw new NotSupportedException(); } }
- private IFrameDataView view;
- public FramesAsStreamView(IFrameDataView view)
- {
- this.view = view;
- }
- public void AddFrame(HTTP2FrameHeaderAndPayload frame)
- {
- this.view.AddFrame(frame);
- }
- public override int ReadByte()
- {
- return this.view.ReadByte();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- return this.view.Read(buffer, offset, count);
- }
- public override void Close()
- {
- base.Close();
- this.view.Dispose();
- }
- public override void Flush() {}
- public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); }
- public override void SetLength(long value) { throw new NotImplementedException(); }
- public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); }
- public override string ToString()
- {
- return this.view.ToString();
- }
- }
- }
- #endif
|