Commit 55dce1dd authored by Brickner_cp's avatar Brickner_cp

HTTP

parent e18d30c8
......@@ -198,65 +198,61 @@ namespace PcapDotNet.Packets.Http
/// </summary>
public abstract class HttpDatagram : Datagram
{
internal class ParseInfoBase
{
public int Length { get; set; }
public HttpVersion Version { get; set; }
public HttpHeader Header { get; set; }
public Datagram Body { get; set; }
}
public abstract bool IsRequest { get; }
public bool IsResponse { get { return !IsRequest; } }
public HttpVersion Version
{
get
public HttpVersion Version { get; private set;}
public HttpHeader Header { get; private set;}
public Datagram Body { get; private set; }
internal static HttpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{
ParseFirstLine();
return _version;
}
if (length >= _httpSlash.Length && buffer.SequenceEqual(offset, _httpSlash, 0, _httpSlash.Length))
return new HttpResponseDatagram(buffer, offset, length);
return new HttpRequestDatagram(buffer, offset, length);
}
public HttpHeader Header
{
get
internal HttpDatagram(byte[] buffer, int offset, int length,
HttpVersion version, HttpHeader header, Datagram body)
: base(buffer, offset, length)
{
ParseHeader();
return _header;
}
Version = version;
Header = header;
Body = body;
}
public Datagram Body
{
get
{
if (_body == null)
{
ParseHeader();
if (_bodyOffset != null)
internal static Datagram ParseBody(byte[] buffer, int offset, int length,
bool isBodyPossible, HttpHeader header)
{
int bodyOffsetValue = _bodyOffset.Value;
if (!IsBodyPossible)
{
_body = Empty;
return _body;
}
if (!isBodyPossible)
return Empty;
HttpTransferEncodingField transferEncodingField = Header.TransferEncoding;
HttpTransferEncodingField transferEncodingField = header.TransferEncoding;
if (transferEncodingField != null)
{
if (transferEncodingField.TransferCodings.Any(coding => coding != "identity"))
{
_body = ReadChunked();
return _body;
}
return ParseChunkedBody(buffer, offset, length);
}
HttpContentLengthField contentLengthField = Header.ContentLength;
HttpContentLengthField contentLengthField = header.ContentLength;
if (contentLengthField != null)
{
uint? contentLength = contentLengthField.ContentLength;
if (contentLength != null)
{
_body = new Datagram(Buffer, StartOffset + bodyOffsetValue, Math.Min((int)contentLength.Value, Length - bodyOffsetValue));
return _body;
}
return new Datagram(buffer, offset, Math.Min((int)contentLength.Value, length));
}
HttpContentTypeField contentTypeField = Header.ContentType;
HttpContentTypeField contentTypeField = header.ContentType;
if (contentTypeField != null)
{
if (contentTypeField.MediaType == "multipart" &&
......@@ -266,26 +262,21 @@ namespace PcapDotNet.Packets.Http
if (boundary != null)
{
byte[] lastBoundaryBuffer = Encoding.ASCII.GetBytes(string.Format("--{0}--\r\n", boundary));
int lastBoundaryOffset = Buffer.Find(StartOffset + bodyOffsetValue, Length - bodyOffsetValue, lastBoundaryBuffer);
int lastBoundaryOffset = buffer.Find(offset, length, lastBoundaryBuffer);
int lastBoundaryEnd = lastBoundaryOffset + lastBoundaryBuffer.Length;
_body = new Datagram(Buffer, StartOffset + bodyOffsetValue,
Math.Min(lastBoundaryEnd - StartOffset - bodyOffsetValue, Length - bodyOffsetValue));
return _body;
return new Datagram(buffer, offset,
Math.Min(lastBoundaryEnd - offset, length));
}
}
}
_body = new Datagram(Buffer, StartOffset + bodyOffsetValue, Length - bodyOffsetValue);
}
}
return _body;
}
return new Datagram(buffer, offset, length);
}
private Datagram ReadChunked()
private static Datagram ParseChunkedBody(byte[] buffer, int offset, int length)
{
List<Datagram> contentData = new List<Datagram>();
HttpParser parser = new HttpParser(Buffer, StartOffset + _bodyOffset.Value, Length - _bodyOffset.Value);
HttpParser parser = new HttpParser(buffer, offset, length);
uint? chunkSize;
while (parser.HexadecimalNumber(out chunkSize).SkipChunkExtensions().CarriageReturnLineFeed().Success)
{
......@@ -293,13 +284,13 @@ namespace PcapDotNet.Packets.Http
if (chunkSizeValue == 0)
{
int? endOffset;
HttpHeader trailerHeader = new HttpHeader(GetHeaderFields(out endOffset, Buffer, parser.Offset, Buffer.Length - parser.Offset));
HttpHeader trailerHeader = new HttpHeader(GetHeaderFields(out endOffset, buffer, parser.Offset, buffer.Length - parser.Offset));
parser.CarriageReturnLineFeed();
break;
}
int actualChunkSize = (int)Math.Min(chunkSizeValue, Buffer.Length - parser.Offset);
contentData.Add(new Datagram(Buffer, parser.Offset, actualChunkSize));
int actualChunkSize = (int)Math.Min(chunkSizeValue, buffer.Length - parser.Offset);
contentData.Add(new Datagram(buffer, parser.Offset, actualChunkSize));
parser.Skip(actualChunkSize);
parser.CarriageReturnLineFeed();
}
......@@ -314,58 +305,10 @@ namespace PcapDotNet.Packets.Http
}
Datagram content = new Datagram(contentBuffer);
return new Datagram(Buffer, StartOffset + _bodyOffset.Value, parser.Offset - StartOffset);
}
protected abstract bool IsBodyPossible { get; }
internal static HttpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{
if (length >= _httpSlash.Length && buffer.SequenceEqual(offset, _httpSlash, 0, _httpSlash.Length))
return new HttpResponseDatagram(buffer, offset, length);
return new HttpRequestDatagram(buffer, offset, length);
}
internal HttpDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
internal void ParseFirstLine()
{
if (_isParsedFirstLine)
return;
_isParsedFirstLine = true;
ParseSpecificFirstLine(out _version, out _headerOffset);
}
internal abstract void ParseSpecificFirstLine(out HttpVersion version, out int? headerOffset);
private void ParseHeader()
{
if (_isParsedHeader)
return;
_isParsedHeader = true;
ParseFirstLine();
if (_headerOffset == null)
return;
_header = new HttpHeader(GetHeaderFields());
}
private List<KeyValuePair<string, IEnumerable<byte>>> GetHeaderFields()
{
int headerOffsetValue = _headerOffset.Value;
int? endOffset;
var result = GetHeaderFields(out endOffset, Buffer, StartOffset + headerOffsetValue, Length - headerOffsetValue);
if (endOffset != null)
_bodyOffset = endOffset.Value - StartOffset;
return result;
return new Datagram(buffer, offset, parser.Offset - offset);
}
private static List<KeyValuePair<string, IEnumerable<byte>>> GetHeaderFields(out int? endOffset, byte[] buffer, int offset, int length)
internal static List<KeyValuePair<string, IEnumerable<byte>>> GetHeaderFields(out int? endOffset, byte[] buffer, int offset, int length)
{
endOffset = null;
var headerFields = new List<KeyValuePair<string, IEnumerable<byte>>>();
......
......@@ -4,9 +4,10 @@ namespace PcapDotNet.Packets.Http
{
public class HttpRequestDatagram : HttpDatagram
{
internal HttpRequestDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
private class ParseInfo : ParseInfoBase
{
public string Method { get; set; }
public string Uri { get; set; }
}
public override bool IsRequest
......@@ -14,37 +15,60 @@ namespace PcapDotNet.Packets.Http
get { return true; }
}
public string Method
{
get
public string Method { get; private set; }
public string Uri { get; private set; }
internal HttpRequestDatagram(byte[] buffer, int offset, int length)
: this(buffer, offset, Parse(buffer, offset, length))
{
ParseFirstLine();
return _method;
}
}
public string Uri
{
get
private HttpRequestDatagram(byte[] buffer, int offset, ParseInfo parseInfo)
:base(buffer, offset, parseInfo.Length, parseInfo.Version, parseInfo.Header, parseInfo.Body)
{
ParseFirstLine();
return _uri;
}
Method = parseInfo.Method;
Uri = parseInfo.Uri;
}
protected override bool IsBodyPossible
private static ParseInfo Parse(byte[] buffer, int offset, int length)
{
get { return Header.ContentLength != null; }
// First Line
HttpParser parser = new HttpParser(buffer, offset, length);
string method;
string uri;
HttpVersion version;
parser.Token(out method).Space().RequestUri(out uri).Space().Version(out version).CarriageReturnLineFeed();
ParseInfo parseInfo = new ParseInfo
{
Length = length,
Version = version,
Method = method,
Uri = uri,
};
if (!parser.Success)
return parseInfo;
int firstLineLength = parser.Offset - offset;
// Header
int? endHeaderOffset;
HttpHeader header = new HttpHeader(GetHeaderFields(out endHeaderOffset, buffer, offset + firstLineLength, length - firstLineLength));
parseInfo.Header = header;
if (endHeaderOffset == null)
return parseInfo;
int headerLength = endHeaderOffset.Value - offset - firstLineLength;
// Body
Datagram body = ParseBody(buffer, offset + firstLineLength + headerLength, length - firstLineLength - headerLength, IsBodyPossible(header), header);
parseInfo.Body = body;
parseInfo.Length = firstLineLength + headerLength + body.Length;
return parseInfo;
}
internal override void ParseSpecificFirstLine(out HttpVersion version, out int? headerOffset)
private static bool IsBodyPossible(HttpHeader header)
{
HttpParser parser = new HttpParser(Buffer, StartOffset, Length);
parser.Token(out _method).Space().RequestUri(out _uri).Space().Version(out version).CarriageReturnLineFeed();
headerOffset = parser.Success ? (int?)(parser.Offset - StartOffset) : null;
return header.ContentLength != null;
}
private string _uri;
private string _method;
}
}
\ No newline at end of file
......@@ -5,9 +5,10 @@ namespace PcapDotNet.Packets.Http
{
public class HttpResponseDatagram : HttpDatagram
{
internal HttpResponseDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
private class ParseInfo : ParseInfoBase
{
public Datagram ReasonPhrase { get; set; }
public uint? StatusCode{ get; set;}
}
public override bool IsRequest
......@@ -15,45 +16,65 @@ namespace PcapDotNet.Packets.Http
get { return false; }
}
public uint? StatusCode
{
get
public uint? StatusCode{get; private set;}
public Datagram ReasonPhrase { get; private set;}
internal HttpResponseDatagram(byte[] buffer, int offset, int length)
: this(buffer, offset, Parse(buffer, offset, length))
{
ParseFirstLine();
return _statusCode;
}
private HttpResponseDatagram(byte[] buffer, int offset, ParseInfo parseInfo)
:base(buffer, offset, parseInfo.Length, parseInfo.Version, parseInfo.Header, parseInfo.Body)
{
StatusCode = parseInfo.StatusCode;
ReasonPhrase = parseInfo.ReasonPhrase;
}
public Datagram ReasonPhrase
private static ParseInfo Parse(byte[] buffer, int offset, int length)
{
get
// First Line
HttpParser parser = new HttpParser(buffer, offset, length);
HttpVersion version;
uint? statusCode;
Datagram reasonPhrase;
parser.Version(out version).Space().DecimalNumber(3, out statusCode).Space().ReasonPhrase(out reasonPhrase).CarriageReturnLineFeed();
ParseInfo parseInfo = new ParseInfo
{
ParseFirstLine();
return _reasonPhrase;
}
Length = length,
Version = version,
StatusCode = statusCode,
ReasonPhrase = reasonPhrase
};
if (!parser.Success)
return parseInfo;
int firstLineLength = parser.Offset - offset;
// Header
int? endHeaderOffset;
HttpHeader header = new HttpHeader(GetHeaderFields(out endHeaderOffset, buffer, offset + firstLineLength, length - firstLineLength));
parseInfo.Header = header;
if (endHeaderOffset == null)
return parseInfo;
int headerLength = endHeaderOffset.Value - offset - firstLineLength;
// Body
Datagram body = ParseBody(buffer, offset + firstLineLength + headerLength, length - firstLineLength - headerLength, IsBodyPossible(statusCode.Value), header);
parseInfo.Body = body;
parseInfo.Length = firstLineLength + headerLength + body.Length;
return parseInfo;
}
protected override bool IsBodyPossible
private static bool IsBodyPossible(uint statusCode)
{
get
{
uint statusCodeValue = StatusCode.Value;
if (statusCodeValue >= 100 && statusCodeValue <= 199 || statusCodeValue == 204 || statusCodeValue == 205 || statusCodeValue == 304)
if (statusCode >= 100 && statusCode <= 199 || statusCode == 204 || statusCode == 205 || statusCode == 304)
return false;
// if (IsResponseToHeadRequest)
// return false;
return true;
}
}
internal override void ParseSpecificFirstLine(out HttpVersion version, out int? headerOffset)
{
HttpParser parser = new HttpParser(Buffer, StartOffset, Length);
parser.Version(out version).Space().DecimalNumber(3, out _statusCode).Space().ReasonPhrase(out _reasonPhrase).CarriageReturnLineFeed();
headerOffset = parser.Success ? (int?)(parser.Offset - StartOffset) : null;
}
private uint? _statusCode;
private Datagram _reasonPhrase;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment