Commit cc0fd15f authored by Brickner_cp's avatar Brickner_cp

HTTP

parent fffd905c
......@@ -90,6 +90,11 @@ namespace PcapDotNet.Base
return sequence.SequenceToString(separator, string.Empty);
}
public static string SequenceToString<T>(this IEnumerable<T> sequence, char separator)
{
return sequence.SequenceToString(separator.ToString());
}
/// <summary>
/// Converts a sequence to a string by converting each element to a string.
/// </summary>
......
......@@ -13,6 +13,7 @@ using PcapDotNet.Packets;
using PcapDotNet.Packets.Arp;
using PcapDotNet.Packets.Ethernet;
using PcapDotNet.Packets.Gre;
using PcapDotNet.Packets.Http;
using PcapDotNet.Packets.Icmp;
using PcapDotNet.Packets.Igmp;
using PcapDotNet.Packets.IpV4;
......@@ -31,6 +32,10 @@ namespace PcapDotNet.Core.Test
private const string WiresharkDiretory = @"C:\Program Files\Wireshark\";
private const string WiresharkTsharkPath = WiresharkDiretory + @"tshark.exe";
private const bool IsRetry
// = true;
= false;
/// <summary>
/// Gets or sets the test context which provides
/// information about and functionality for the current test run.
......@@ -201,9 +206,6 @@ namespace PcapDotNet.Core.Test
private static void ComparePacketsToWireshark(IEnumerable<Packet> packets)
{
string pcapFilename = Path.GetTempPath() + "temp." + new Random().NextByte() + ".pcap";
const bool IsRetry
// = true;
= false;
#pragma warning disable 162
// ReSharper disable ConditionIsAlwaysTrueOrFalse
// ReSharper disable HeuristicUnreachableCode
......@@ -216,7 +218,10 @@ namespace PcapDotNet.Core.Test
const byte RetryNumber = 89;
pcapFilename = Path.GetTempPath() + "temp." + RetryNumber + ".pcap";
List<Packet> packetsList = new List<Packet>();
new OfflinePacketDevice(pcapFilename).Open().ReceivePackets(1000, packetsList.Add);
using (PacketCommunicator communicator = new OfflinePacketDevice(pcapFilename).Open())
{
communicator.ReceivePackets(-1, packetsList.Add);
}
packets = packetsList;
}
// ReSharper restore HeuristicUnreachableCode
......@@ -378,6 +383,16 @@ namespace PcapDotNet.Core.Test
}
break;
case "http":
PropertyInfo httpProperty = currentDatagram.GetType().GetProperty("Http");
if (httpProperty == null)
break;
{
currentDatagram = httpProperty.GetValue(currentDatagram);
CompareHttp(layer, (HttpDatagram)currentDatagram);
}
break;
default:
return;
}
......@@ -1340,5 +1355,158 @@ namespace PcapDotNet.Core.Test
MoreAssert.AreSequenceEqual(optionShows, option.GetWiresharkSubfieldStrings());
}
}
private static void CompareHttp(XElement httpElement, HttpDatagram httpDatagram)
{
string httpFieldName;
StringBuilder data = new StringBuilder();
bool isFirstEmptyName = true;
foreach (var field in httpElement.Fields())
{
if (field.Name() == "data" || field.Name() == "data.data")
{
if (field.Name() == "data")
field.AssertNoShow();
string previousData = data.ToString();
for (int i = 0; i != previousData.Length / 2; ++i)
{
byte value = Convert.ToByte(previousData.Substring(i * 2, 2), 16);
Assert.AreEqual(httpDatagram[i], value);
}
field.AssertValue(httpDatagram.Skip(previousData.Length / 2), field.Name());
continue;
}
string fieldShow = field.Show();
switch (field.Name())
{
case "http.request":
field.AssertShowDecimal(httpDatagram.IsRequest);
break;
case "http.response":
field.AssertShowDecimal(httpDatagram.IsResponse);
break;
case "":
data.Append(field.Value());
if (fieldShow == @"\r\n")
break;
else if (isFirstEmptyName)
{
CompareHttpFirstLine(field, httpDatagram);
isFirstEmptyName = false;
}
else if (fieldShow.StartsWith("Content-encoded entity body"))
{
break;
}
else if (fieldShow == "HTTP chunked response")
{
field.AssertValue(httpDatagram.Body);
}
else
{
int colonIndex = fieldShow.IndexOf(':');
MoreAssert.IsBiggerOrEqual(0, colonIndex, "Can't find colon in field with empty name");
if (httpDatagram.Header == null)
{
Assert.IsTrue(httpDatagram.IsRequest);
Assert.IsNull(httpDatagram.Version);
break;
}
httpFieldName = fieldShow.Substring(0, colonIndex);
string fieldValue = fieldShow.Substring(colonIndex + 1).SkipWhile(c => c == ' ').TakeWhile(c => c != '\\').SequenceToString();
string expectedFieldValue = httpDatagram.Header[httpFieldName].ValueString;
Assert.IsTrue(expectedFieldValue.Contains(fieldValue),
string.Format("{0} <{1}> doesn't contain <{2}>", field.Name(), expectedFieldValue, fieldValue));
}
break;
case "data.len":
field.AssertShowDecimal(httpDatagram.Length - data.Length / 2);
break;
case "http.host":
case "http.user_agent":
case "http.accept":
case "http.accept_language":
case "http.accept_encoding":
case "http.connection":
case "http.cookie":
case "http.cache_control":
case "http.content_encoding":
case "http.date":
case "http.referer":
case "http.last_modified":
case "http.server":
case "http.set_cookie":
case "http.location":
httpFieldName = field.Name().Substring(5).Replace('_', '-');
HttpField httpField = httpDatagram.Header[httpFieldName];
if (!field.Value().EndsWith("0d0a"))
Assert.IsNull(httpField);
else
{
string fieldValue = field.Show().Replace("\\\"", "\"");
string expectedFieldValue = httpField.ValueString;
Assert.IsTrue(expectedFieldValue.Contains(fieldValue),
string.Format("{0} <{1}> doesn't contain <{2}>", field.Name(), expectedFieldValue, fieldValue));
}
break;
case "http.content_length_header":
field.AssertShowDecimal(httpDatagram.Header.ContentLength.ContentLength.Value);
break;
case "http.content_type":
string[] mediaType = fieldShow.Split(new[] {';', ' ', '/'}, StringSplitOptions.RemoveEmptyEntries);
Assert.AreEqual(httpDatagram.Header.ContentType.MediaType, mediaType[0]);
Assert.AreEqual(httpDatagram.Header.ContentType.MediaSubType, mediaType[1]);
MoreAssert.AreSequenceEqual(httpDatagram.Header.ContentType.Parameters.Select(pair => pair.Key + '=' + pair.Value), mediaType.Skip(2));
break;
case "http.transfer_encoding":
field.AssertShow(httpDatagram.Header.TransferEncoding.TransferCodings.SequenceToString(','));
break;
default:
throw new InvalidOperationException("Invalid HTTP field " + field.Name());
}
}
}
private static void CompareHttpFirstLine(XElement httpFirstLineElement, HttpDatagram httpDatagram)
{
foreach (var field in httpFirstLineElement.Fields())
{
switch (field.Name())
{
case "http.request.method":
Assert.IsTrue(httpDatagram.IsRequest, field.Name() + " IsRequest");
field.AssertShow(((HttpRequestDatagram)httpDatagram).Method);
break;
case "http.request.uri":
Assert.IsTrue(httpDatagram.IsRequest, field.Name() + " IsRequest");
field.AssertShow(((HttpRequestDatagram)httpDatagram).Uri);
break;
case "http.request.version":
field.AssertShow(httpDatagram.Version.ToString());
break;
case "http.response.code":
Assert.IsTrue(httpDatagram.IsResponse, field.Name() + " IsResponse");
field.AssertShowDecimal(((HttpResponseDatagram)httpDatagram).StatusCode.Value);
break;
default:
throw new InvalidOperationException("Invalid HTTP first line field " + field.Name());
}
}
}
}
}
\ No newline at end of file
......@@ -47,6 +47,11 @@ namespace PcapDotNet.Core.Test
Assert.AreEqual(element.Name(), expectedName);
}
public static void AssertNoShow(this XElement element)
{
Assert.IsNull(element.Attribute("show"));
}
public static void AssertShow(this XElement element, string expectedValue, string message = null)
{
Assert.AreEqual(expectedValue, element.Show(), message ?? element.Name());
......@@ -134,7 +139,7 @@ namespace PcapDotNet.Core.Test
public static void AssertValue(this XElement element, string expectedValue, string message = null)
{
Assert.AreEqual(element.Value(), expectedValue, message ?? element.Name());
Assert.AreEqual(expectedValue, element.Value(), message ?? element.Name());
}
public static void AssertValue(this XElement element, IEnumerable<byte> expectedValue, string message = null)
......
......@@ -73,6 +73,13 @@ namespace PcapDotNet.Packets.Http
public string Name { get; private set; }
public ReadOnlyCollection<byte> Value { get; private set; }
public string ValueString
{
get
{
return _defaultEncoding.GetString(Value.ToArray());
}
}
public virtual bool Equals(HttpField other)
{
......@@ -86,12 +93,7 @@ namespace PcapDotNet.Packets.Http
public override string ToString()
{
return string.Format("{0}: {1}", Name, ValueToString());
}
protected virtual string ValueToString()
{
return _defaultEncoding.GetString(Value.ToArray());
return string.Format("{0}: {1}", Name, ValueString);
}
private static readonly Encoding _defaultEncoding = Encoding.GetEncoding(28591);
......
......@@ -20,6 +20,11 @@ namespace PcapDotNet.Packets.Http
{
}
public HttpField this[string fieldName]
{
get { return GetField<HttpField>(fieldName); }
}
public HttpTransferEncodingField TransferEncoding
{
get
......@@ -28,14 +33,6 @@ namespace PcapDotNet.Packets.Http
}
}
private T GetField<T>(string fieldName) where T : HttpField
{
HttpField field;
if (!_fields.TryGetValue(fieldName, out field))
return null;
return (T)field;
}
public HttpContentLengthField ContentLength
{
get
......@@ -97,6 +94,14 @@ namespace PcapDotNet.Packets.Http
_fields = mergedFields.ToDictionary(field => field.Key, field => HttpField.CreateField(field.Key, field.Value.ToArray()), StringComparer.InvariantCultureIgnoreCase);
}
private T GetField<T>(string fieldName) where T : HttpField
{
HttpField field;
if (!_fields.TryGetValue(fieldName, out field))
return null;
return (T)field;
}
private static readonly HttpHeader _empty = new HttpHeader();
private readonly Dictionary<string, HttpField> _fields = new Dictionary<string, HttpField>(StringComparer.InvariantCultureIgnoreCase);
}
......
......@@ -59,10 +59,10 @@ namespace PcapDotNet.Packets.Http
SetTransferCodings(match.GroupCapturesValues(RegexTransferCodingGroupName).ToArray());
}
protected override string ValueToString()
{
return TransferCodings == null ? string.Empty : TransferCodings.SequenceToString(",");
}
// protected override string ValueToString()
// {
// return TransferCodings == null ? string.Empty : TransferCodings.SequenceToString(",");
// }
private ReadOnlyCollection<string> _transferCodings;
......
......@@ -29,9 +29,9 @@ namespace PcapDotNet.TestUtils
"> Actual: <" + actual + ">. " + message);
}
public static void IsBiggerOrEqual<T>(T expectedMaximum, T actual) where T : IComparable<T>
public static void IsBiggerOrEqual<T>(T expectedMinimum, T actual) where T : IComparable<T>
{
IsBiggerOrEqual(expectedMaximum, actual, string.Empty);
IsBiggerOrEqual(expectedMinimum, actual, string.Empty);
}
public static void IsSmallerOrEqual<T>(T expectedMaximum, T actual, string message) where T : IComparable<T>
......
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