Commit b39e7b78 authored by Brickner_cp's avatar Brickner_cp

HTTP

parent 65032c0f
......@@ -2,6 +2,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using PcapDotNet.Base;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.IpV4;
......@@ -150,7 +151,12 @@ namespace PcapDotNet.Packets
public override string ToString()
{
return _buffer.Range(StartOffset, Length).BytesSequenceToHexadecimalString();
return Buffer.Range(StartOffset, Length).BytesSequenceToHexadecimalString();
}
public string ToString(Encoding encoding)
{
return encoding.GetString(Buffer, StartOffset, Length);
}
internal void Write(byte[] buffer, int offset)
......
......@@ -217,6 +217,23 @@ namespace PcapDotNet.Packets.Http
return _header;
}
}
public Datagram Body
{
get
{
if (_body == null)
{
ParseHeader();
if (_bodyOffset != null)
{
int bodyOffsetValue = _bodyOffset.Value;
_body = new Datagram(Buffer, StartOffset + bodyOffsetValue, Length - bodyOffsetValue);
}
}
return _body;
}
}
internal static HttpDatagram CreateDatagram(byte[] buffer, int offset, int length)
{
......@@ -260,6 +277,11 @@ namespace PcapDotNet.Packets.Http
HttpParser parser = new HttpParser(Buffer, StartOffset + headerOffsetValue, Length - headerOffsetValue);
while (parser.Success)
{
if (parser.CarraigeReturnLineFeed().Success)
{
_bodyOffset = parser.Offset - StartOffset;
break;
}
string fieldName;
IEnumerable<byte> fieldValue;
parser.Token(out fieldName).Colon().FieldValue(out fieldValue).CarraigeReturnLineFeed();
......@@ -273,8 +295,11 @@ namespace PcapDotNet.Packets.Http
private bool _isParsedFirstLine;
private bool _isParsedHeader;
private int? _headerOffset;
private int? _bodyOffset;
private HttpVersion _version;
private HttpHeader _header;
private Datagram _body;
}
......
......@@ -9,6 +9,18 @@ namespace PcapDotNet.Packets.Http
{
public class HttpField : IEquatable<HttpField>
{
public static HttpField CreateField(string fieldName, byte[] fieldValue)
{
switch (fieldName)
{
case HttpTransferEncodingField.Name:
return new HttpTransferEncodingField(fieldValue);
default:
return new HttpField(fieldName, fieldValue.ToArray());
}
}
public HttpField(string name, string value)
: this(name, value, _defaultEncoding)
{
......
......@@ -50,7 +50,7 @@ namespace PcapDotNet.Packets.Http
mergedFields[fieldName] = fieldValue.Concat(AsciiBytes.Comma).Concat(field.Value);
}
_fields = mergedFields.ToDictionary(field => field.Key, field => new HttpField(field.Key, field.Value));
_fields = mergedFields.ToDictionary(field => field.Key, field => HttpField.CreateField(field.Key, field.Value.ToArray()));
}
public IEnumerator<HttpField> GetEnumerator()
......
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Http
{
public class HttpTransferCoding
{
public HttpTransferCoding(string codingName, ReadOnlyCollection<HttpParameter> parameters)
{
CodingName = codingName;
Parameters = parameters;
}
public string CodingName { get; private set; }
public ReadOnlyCollection<HttpParameter> Parameters { get; private set; }
}
public class HttpParameter
{
public HttpParameter(string attribute, Datagram value)
{
Attribute = attribute;
Value = value;
}
public string Attribute { get; private set; }
public Datagram Value { get; private set; }
}
internal class HttpParser
{
public HttpParser(byte[] buffer)
......@@ -28,7 +53,7 @@ namespace PcapDotNet.Packets.Http
get { return _offset; }
}
public HttpParser Token(out string token)
public HttpParser Token(out Datagram token)
{
if (!Success)
{
......@@ -42,12 +67,20 @@ namespace PcapDotNet.Packets.Http
token = null;
return Fail();
}
token = Encoding.ASCII.GetString(_buffer, _offset, tokenLength);
token = new Datagram(_buffer, _offset, tokenLength);
_offset += token.Length;
return this;
}
public HttpParser Token(out string token)
{
Datagram bytesToken;
Token(out bytesToken);
token = Success ? bytesToken.ToString(Encoding.ASCII) : null;
return this;
}
public HttpParser Colon()
{
return Bytes(AsciiBytes.Colon);
......@@ -230,6 +263,127 @@ namespace PcapDotNet.Packets.Http
return this;
}
public HttpParser CommaSeparated<T>(Func<T> commaSeparatedParsing, out List<T> commaSeparated)
{
commaSeparated = new List<T>();
bool more = true;
while (Success && more)
{
commaSeparated.Add(commaSeparatedParsing());
SkipLws();
more = false;
while (IsNext(AsciiBytes.Comma))
{
++_offset;
more = true;
SkipLws();
}
}
if (!Success)
commaSeparated = null;
return this;
}
public HttpTransferCoding TransferCoding()
{
string codingName;
Token(out codingName);
List<HttpParameter> parameters = new List<HttpParameter>();
while (Success && IsNext(AsciiBytes.Semicolon))
{
++_offset;
HttpParameter parameter;
Parameter(out parameter);
}
return Success ? new HttpTransferCoding(codingName, parameters.AsReadOnly()) : null;
}
public HttpParser Parameter(out HttpParameter parameter)
{
string attribute;
Token(out attribute).Bytes(AsciiBytes.EqualsSign);
Datagram value;
if (IsNext(AsciiBytes.DoubleQuotationMark))
QuotedString(out value);
else
Token(out value);
parameter = Success ? new HttpParameter(attribute, value) : null;
return this;
}
public HttpParser QuotedString(out Datagram quotedString)
{
quotedString = null;
int startOffset = _offset;
// Parse first "
if (!Bytes(AsciiBytes.DoubleQuotationMark).Success)
return this;
while (IsNext())
{
byte next = Next();
// Parse last "
if (next == AsciiBytes.DoubleQuotationMark)
{
++_offset;
quotedString = new Datagram(_buffer, startOffset, _offset - startOffset);
return this;
}
// Parse \char
if (next == AsciiBytes.BackSlash && IsNextNext() && NextNext().IsChar())
_offset += 2;
else
{
// parse text
int original = _offset;
SkipLws();
if (original == _offset)
{
// text isn't LWS - parse a byte that isn't control
if (!next.IsControl())
++_offset;
else
return Fail(); // illegal byte
}
}
}
// no " found
return Fail();
}
private bool IsNextNext()
{
return _offset + 1 < _totalLength;
}
private bool IsNext()
{
return _offset < _totalLength;
}
private byte Next()
{
return _buffer[_offset];
}
private byte NextNext()
{
return _buffer[_offset + 1];
}
private bool IsNext(byte next)
{
return (IsNext() && Next() == next);
}
private HttpParser Fail()
{
Success = false;
......
using System;
using System.Collections.Generic;
namespace PcapDotNet.Packets.Http
{
public class HttpTransferEncodingField : HttpField
{
public const string Name = "Transfer-Encoding";
public HttpTransferEncodingField(byte[] fieldValue)
: base(Name, fieldValue)
{
HttpParser parser = new HttpParser(fieldValue);
List<HttpTransferCoding> transferCodings;
parser.CommaSeparated(parser.TransferCoding, out transferCodings);
}
}
}
\ No newline at end of file
......@@ -117,6 +117,7 @@
<Compile Include="Http\HttpParser.cs" />
<Compile Include="Http\HttpRequestDatagram.cs" />
<Compile Include="Http\HttpResponseDatagram.cs" />
<Compile Include="Http\HttpTransferEncodingField.cs" />
<Compile Include="Http\HttpVersion.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyDatagram.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyLayer.cs" />
......
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