Commit 339451bf authored by Brickner_cp's avatar Brickner_cp

HTTP

parent 940895ae
......@@ -84,10 +84,10 @@ namespace PcapDotNet.Core.Test
// Compare packet to wireshark
ComparePacketsToWireshark(new[] { packet });
// BUG: Limited timestamp due to Wireshark bug: https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4766
// BUG: Limited timestamp due to Windows bug: https://connect.microsoft.com/VisualStudio/feedback/details/559198/net-4-datetime-tolocaltime-is-sometimes-wrong
// Now check different dates.
//packet = new Packet(new byte[14], new DateTime(2004,08,25,10,36,41, DateTimeKind.Utc).ToLocalTime(), DataLinkKind.Ethernet);
//ComparePacketsToWireshark(new[] { packet });
// packet = new Packet(new byte[14], new DateTime(2004,08,25,10,36,41, DateTimeKind.Utc).ToLocalTime(), DataLinkKind.Ethernet);
// ComparePacketsToWireshark(new[] { packet });
}
[TestMethod]
......@@ -128,7 +128,7 @@ namespace PcapDotNet.Core.Test
private static Packet CreateRandomPacket(Random random)
{
// BUG: Limited timestamp due to Wireshark bug: https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4766
// BUG: Limited timestamp due to Windows bug: https://connect.microsoft.com/VisualStudio/feedback/details/559198/net-4-datetime-tolocaltime-is-sometimes-wrong
DateTime packetTimestamp =
random.NextDateTime(new DateTime(2010,1,1), new DateTime(2010,12,31)).ToUniversalTime().ToLocalTime();
//random.NextDateTime(PacketTimestamp.MinimumPacketTimestamp, PacketTimestamp.MaximumPacketTimestamp).ToUniversalTime().ToLocalTime();
......
namespace PcapDotNet.Packets.Http
{
internal static class AsciiBytes
{
public const byte UpperA = (byte)'A';
public const byte UpperF = (byte)'F';
public const byte UpperZ = (byte)'Z';
public const byte LowerA = (byte)'a';
public const byte LowerF = (byte)'f';
public const byte LowerZ = (byte)'z';
public const byte Zero = (byte)'0';
public const byte Nine = (byte)'9';
public const byte Delete = 127; // DEL
public const byte CarriageReturn = 13; // CR
public const byte LineFeed = 10; // LF
public const byte Space = (byte)' '; // SP
public const byte HorizontalTab = 9; // HT
public const byte DoubleQuotationMark = (byte)'"';
public const byte LeftRoundBracket = (byte)'(';
public const byte RightRoundBracket = (byte)')';
public const byte LowerThan = (byte)'<';
public const byte BiggerThan = (byte)'>';
public const byte AtSign = (byte)'@';
public const byte Comma = (byte)',';
public const byte Semicolon = (byte)';';
public const byte Colon = (byte)':';
public const byte BackSlash = (byte)'\\';
public const byte Slash = (byte)'/';
public const byte LeftSquareBracket = (byte)'[';
public const byte RightSquareBracket = (byte)']';
public const byte QuestionMark = (byte)'?';
public const byte EqualsSign = (byte)'=';
public const byte LeftCurlyBracket = (byte)'{';
public const byte RightCurlyBracket = (byte)'}';
}
}
\ No newline at end of file
namespace PcapDotNet.Packets.Http
{
internal static class ByteExtensions
{
// CHAR
public static bool IsChar(this byte value)
{
return value <= 127;
}
// UPALPHA
public static bool IsUpAlpha(this byte value)
{
return value >= AsciiBytes.UpperA && value <= AsciiBytes.UpperZ;
}
// LOALPHA
public static bool IsLowerAlpha(this byte value)
{
return value >= AsciiBytes.LowerA && value <= AsciiBytes.LowerZ;
}
// ALPHA
public static bool IsAlpha(this byte value)
{
return value.IsUpAlpha() || value.IsLowerAlpha();
}
// DIGIT
public static bool IsDigit(this byte value)
{
return value >= AsciiBytes.Zero && value <= AsciiBytes.Nine;
}
// HEX
public static bool IsHexadecimalDigit(this byte value)
{
return value >= AsciiBytes.UpperA && value <= AsciiBytes.UpperF ||
value >= AsciiBytes.LowerA && value <= AsciiBytes.LowerF ||
value.IsDigit();
}
public static bool IsSpaceOrHorizontalTab(this byte value)
{
return value == AsciiBytes.Space || value == AsciiBytes.HorizontalTab;
}
// CTL
public static bool IsControl(this byte value)
{
return value <= 31 || value == AsciiBytes.Delete;
}
// separators
public static bool IsSeparator(this byte value)
{
switch (value)
{
case AsciiBytes.LeftRoundBracket:
case AsciiBytes.RightRoundBracket:
case AsciiBytes.LowerThan:
case AsciiBytes.BiggerThan:
case AsciiBytes.AtSign:
case AsciiBytes.Comma:
case AsciiBytes.Semicolon:
case AsciiBytes.Colon:
case AsciiBytes.BackSlash:
case AsciiBytes.DoubleQuotationMark:
case AsciiBytes.Slash:
case AsciiBytes.LeftSquareBracket:
case AsciiBytes.RightSquareBracket:
case AsciiBytes.QuestionMark:
case AsciiBytes.EqualsSign:
case AsciiBytes.LeftCurlyBracket:
case AsciiBytes.RightCurlyBracket:
case AsciiBytes.Space:
case AsciiBytes.HorizontalTab:
return true;
default:
return false;
}
}
// token
public static bool IsToken(this byte value)
{
return value.IsChar() && !value.IsControl() && !value.IsSeparator();
}
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace PcapDotNet.Packets.Http
{
public class HttpHeader
{
internal HttpHeader(IEnumerable<KeyValuePair<string, IEnumerable<byte>>> fields)
{
// int totalLength = offset + length;
// Datagram data = new Datagram(buffer, offset, totalLength - offset);
// Parse field-name = token
// string fieldName;
// if (!TryParseToken(buffer, offset, totalLength - offset, out fieldName))
// return;
// offset += fieldName.Length;
// data = new Datagram(buffer, offset, totalLength - offset);
// Parse ":"
// if (data.FirstOrDefault() != AsciiBytes.Colon)
// return;
//
// ++offset;
// Parse field-value
// if (!TryParseFieldValue(buffer, offset, totalLength - offset))
// return;
// data = new Datagram(buffer, offset, totalLength - offset);
// Parse field-value = *( field-content | LWS )
// IEnumerable<byte> fieldValue = new byte[0];
//
// int lwsCount = data.CountLinearWhiteSpaces();
// if (lwsCount != 0)
// {
// offset += lwsCount;
// data = new Datagram(buffer, offset, totalLength - offset);
// }
//
// int fieldContentCount;
// IEnumerable<byte> fieldContent = data.TakeFieldContent(out fieldContentCount);
//
// if (fieldContentCount != 0)
// {
// if (fieldValue.Any())
// fieldValue = fieldValue.Concat(AsciiBytes.Space);
// fieldValue = fieldValue.Concat(fieldContent);
// offset += fieldContentCount;
// }
// data.SkipWhile
// buffer..Take(count).TakeWhile(value => value.IsToken()).Count))
// Encoding.ASCII.GetString()
}
// private HttpHeaderPart _generalHeader;
// private HttpHeaderPart _requestHeader;
// private HttpHeaderPart _responseHeader;
// private HttpHeaderPart _entityHeader;
// private Dictionary<string, >
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PcapDotNet.Base;
namespace PcapDotNet.Packets.Http
{
internal class HttpParser
{
public HttpParser(byte[] buffer, int offset, int length)
{
_buffer = buffer;
_offset = offset;
_totalLength = offset + length;
Success = offset >= 0 && length >= 0 && offset + length <= buffer.Length;
}
public bool Success { get; private set; }
public HttpParser Token(out string token)
{
if (!Success)
{
token = null;
return this;
}
int tokenLength = Range.TakeWhile(value => value.IsToken()).Count();
if (tokenLength == 0)
{
token = null;
return Fail();
}
token = Encoding.ASCII.GetString(_buffer, _offset, tokenLength);
_offset += token.Length;
return this;
}
private HttpParser Single(byte value)
{
if (!Success)
return this;
if (Range.First() != value)
return Fail();
++_offset;
return this;
}
public HttpParser Colon()
{
return Single(AsciiBytes.Colon);
}
public HttpParser Space()
{
return Single(AsciiBytes.Space);
}
public HttpParser SkipLws()
{
while (true)
{
IEnumerable<byte> range = Range;
byte first = range.FirstOrDefault();
if (first.IsSpaceOrHorizontalTab()) // ( SP | HT )
++_offset;
else if (first == AsciiBytes.CarriageReturn) // CR
{
range = range.Skip(1);
if (range.FirstOrDefault() != AsciiBytes.LineFeed) // CR without LF
break;
// CRLF
range = range.Skip(1);
if (!range.FirstOrDefault().IsSpaceOrHorizontalTab()) // CRLF without ( SP | HT )
break;
// CRLF ( SP | HT )
_offset += 3;
}
else
break;
}
return this;
}
public HttpParser FieldContent(out IEnumerable<byte> fieldContent)
{
fieldContent = Range.TakeWhile(value => !value.IsSpaceOrHorizontalTab() && value != AsciiBytes.CarriageReturn);
_offset += fieldContent.Count();
return this;
}
public HttpParser FieldValue(out IEnumerable<byte> fieldValue)
{
if (!Success)
{
fieldValue = null;
return this;
}
SkipLws();
FieldContent(out fieldValue);
if (!fieldValue.Any())
return this;
while (Success)
{
IEnumerable<byte> fieldContent;
SkipLws();
FieldContent(out fieldContent);
if (!fieldContent.Any())
break;
fieldValue = fieldValue.Concat(AsciiBytes.Space).Concat(fieldContent);
}
return this;
}
private HttpParser Fail()
{
Success = false;
return this;
}
private IEnumerable<byte> Range
{
get { return _buffer.Range(_offset, _totalLength - _offset); }
}
private readonly byte[] _buffer;
private int _offset;
private readonly int _totalLength;
public HttpParser RequestUri()
{
throw new NotImplementedException();
}
public HttpParser Version()
{
throw new NotImplementedException();
}
public HttpParser CarraigeReturnLineFeed()
{
return Single(AsciiBytes.CarriageReturn).Single(AsciiBytes.LineFeed);
}
public HttpParser DecimalNumber(int numDigits, out int number)
{
var digits = Range.Take(numDigits).TakeWhile(value => value.IsDigit());
if (digits.Count() != numDigits)
{
number = 0;
return Fail();
}
number = digits.Select(value => value - AsciiBytes.Zero).Aggregate(0, (accumulated, value) => 10 * accumulated + value);
_offset += numDigits;
return this;
}
public HttpParser ReasonPhrase()
{
throw new NotImplementedException();
}
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Http
{
public class HttpRequestDatagram : HttpDatagram
{
internal HttpRequestDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
public override bool IsRequest
{
get { return true; }
}
internal override void ParseFirstLine(HttpParser parser)
{
string method;
parser.Token(out method).Space().RequestUri().Space().Version().CarraigeReturnLineFeed();
}
}
}
\ No newline at end of file
using System;
namespace PcapDotNet.Packets.Http
{
public class HttpResponseDatagram : HttpDatagram
{
internal HttpResponseDatagram(byte[] buffer, int offset, int length)
: base(buffer, offset, length)
{
}
public override bool IsRequest
{
get { return false; }
}
internal override void ParseFirstLine(HttpParser parser)
{
int statusCode;
parser.Version().Space().DecimalNumber(3, out statusCode).Space().ReasonPhrase().CarraigeReturnLineFeed();
}
}
}
\ No newline at end of file
......@@ -107,7 +107,13 @@
<Compile Include="Gre\GreSourceRouteEntryIp.cs" />
<Compile Include="Gre\GreSourceRouteEntryUnknown.cs" />
<Compile Include="Gre\GreVersion.cs" />
<Compile Include="Http\AsciiBytes.cs" />
<Compile Include="Http\ByteExtensions.cs" />
<Compile Include="Http\HttpDatagram.cs" />
<Compile Include="Http\HttpHeader.cs" />
<Compile Include="Http\HttpParser.cs" />
<Compile Include="Http\HttpRequestDatagram.cs" />
<Compile Include="Http\HttpResponseDatagram.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyDatagram.cs" />
<Compile Include="Icmp\IcmpAddressMaskReplyLayer.cs" />
<Compile Include="Icmp\IcmpAddressMaskRequestLayer.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