Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1233 → Rev 1234

/TCPproxy/trunk/MainForm.cs
20,6 → 20,7
// - do not store intermediate info, just row packets and the parsed fragments to display
// - make the text fragment store switchable
// - set locks during log writing (?)
// - show '100 (Continue)' response info
namespace TCPproxy
{
public class MainForm : Form
1429,17 → 1430,17
string title = http.ToString();
if(httpData.Node.Text != title) httpData.Node.Text = title;
 
if(!httpData.RequestXmlShown && http.RequestXml != null)
if(!httpData.RequestXmlShown && http.Request.Xml != null)
{
httpData.RequestXmlShown = true;
AddXmlNode(httpData.Node, "Request XML", http.RequestXml);
AddXmlNode(httpData.Node, "Request XML", http.Request.Xml);
if(autoExpand) httpData.Node.Expand();
}
 
if(!httpData.ResponseXmlShown && http.ResponseXml != null)
if(!httpData.ResponseXmlShown && http.Response.Xml != null)
{
httpData.ResponseXmlShown = true;
AddXmlNode(httpData.Node, "Response XML", http.ResponseXml);
AddXmlNode(httpData.Node, "Response XML", http.Response.Xml);
if(autoExpand) httpData.Node.Expand();
}
 
1758,34 → 1759,30
 
private class HttpNodeData : TreeNodeData
{
private class MarkerSet
{
public object start;
public object method;
public object uri;
public object version;
public object status;
public object transferEncoding;
public object length;
public object contentEncoding;
public object contentType;
public object charset;
public object headers;
public object body;
public IEnumerator headersEnum;
}
 
private HttpMessage http;
private bool requestXmlShown = false;
private bool responseXmlShown = false;
 
private object stateMarker = null;
private object requestStartMarker = null;
private object requestMethodMarker = null;
private object requestUriMarker = null;
private object requestVersionMarker = null;
private object requestTransferEncodingMarker = null;
private object requestLengthMarker = null;
private object requestContentEncodingMarker = null;
private object requestContentTypeMarker = null;
private object requestCharsetMarker = null;
private object requestHeadersMarker = null;
private object responseStartMarker = null;
private object responseVersionMarker = null;
private object responseStatusMarker = null;
private object responseTransferEncodingMarker = null;
private object responseLengthMarker = null;
private object responseContentEncodingMarker = null;
private object responseContentTypeMarker = null;
private object responseCharsetMarker = null;
private object responseHeadersMarker = null;
private object requestBodyMarker = null;
private object responseBodyMarker = null;
private IEnumerator requestHeadersEnum = null;
private IEnumerator responseHeadersEnum = null;
private object stateMarker = null;
private MarkerSet requestMarkers = new MarkerSet();
private MarkerSet responseMarkers = new MarkerSet();
 
public HttpMessage Http
{
1836,196 → 1833,185
}
}
 
protected override void InitView()
private string VersionToString(HttpVersion version)
{
try
switch(version)
{
lock(http)
{
owner.messagesBox.Clear();
case HttpVersion.V0_9: return "HTTP/0.9";
case HttpVersion.V1_0: return "HTTP/1.0";
default: return "HTTP/1.1";
}
}
 
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText("Complete: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
stateMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestComplete && http.ResponseComplete ? "YES" : "NO",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(stateMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendNewLine();
private void InitHttpHalfView(HttpHalfMessage half, MarkerSet markers, string title)
{
string padding = "";
 
// request info
owner.messagesBox.AppendText("Request Start: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestStartMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestStartTimestamp == DateTime.MinValue
? "<unknown>" : http.RequestStartTimestamp.ToString("HH:mm:ss.ffff"),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestStartMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Start: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.start = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(half.StartTimestamp == DateTime.MinValue
? "<unknown>" : half.StartTimestamp.ToString("HH:mm:ss.ffff"),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.start);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Method: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestMethodMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestMethod,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestMethodMarker);
owner.messagesBox.AppendNewLine();
if(half.IsRequest)
{
owner.messagesBox.AppendText(title + " Method: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.method = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText((half as HttpRequest).Method,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.method);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request URI: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestUriMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestUri,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestUriMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " URI: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.uri = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText((half as HttpRequest).Uri,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.uri);
owner.messagesBox.AppendNewLine();
}
else
{
owner.messagesBox.AppendText(title + " Status: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.status = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText((half as HttpResponse).StatusCode
+ " " + (half as HttpResponse).StatusMessage,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.status);
owner.messagesBox.AppendNewLine();
}
 
owner.messagesBox.AppendText("Request Version: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestVersionMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestVersion == HttpVersion.V0_9 ? "HTTP/0.9"
: http.RequestVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestVersionMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Version: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.version = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(VersionToString(half.Version),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.version);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Transfer Encoding: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestTransferEncodingMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(EncodingToString(http.RequestTransferEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestTransferEncodingMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Transfer Encoding: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.transferEncoding = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(EncodingToString(half.TransferEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.transferEncoding);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Content Length: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestLengthMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestLength < 0 ? "<unknown>" : http.RequestLength.ToString(),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestLengthMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Content Length: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.length = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(half.Length < 0 ? "<unknown>" : half.Length.ToString(),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.length);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Content Encoding: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestContentEncodingMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(EncodingToString(http.RequestContentEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestContentEncodingMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Content Encoding: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.contentEncoding = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(EncodingToString(half.ContentEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.contentEncoding);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Content Type: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestContentTypeMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestContentType == null ? "<unknown>"
: http.RequestContentType + "/" + http.RequestContentSubtype,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestContentTypeMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Content Type: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.contentType = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(half.ContentType == null ? "<unknown>"
: half.ContentType + "/" + half.ContentSubtype,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.contentType);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Content Charset: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
requestCharsetMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.RequestCharset == null ? "<unknown>" : http.RequestCharset,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(requestCharsetMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText(title + " Content Charset: " + padding,
Color.DarkRed, Color.Transparent, false, false, 0, 0);
markers.charset = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(half.Charset == null ? "<unknown>" : half.Charset,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(markers.charset);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Request Headers:",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
owner.messagesBox.AppendNewLine();
requestHeadersMarker = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(requestHeadersMarker);
owner.messagesBox.AppendText(title + " Headers:",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
owner.messagesBox.AppendNewLine();
markers.headers = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(markers.headers);
 
requestHeadersEnum = http.RequestHeaders.GetEnumerator();
ShowHeaders(requestHeadersEnum, requestHeadersMarker);
markers.headersEnum = half.Headers.GetEnumerator();
ShowHeaders(markers.headersEnum, markers.headers);
}
 
// response info
owner.messagesBox.AppendNewLine();
owner.messagesBox.AppendText("Response Start: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseStartMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.ResponseStartTimestamp == DateTime.MinValue
? "<unknown>" : http.ResponseStartTimestamp.ToString("HH:mm:ss.ffff"),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseStartMarker);
owner.messagesBox.AppendNewLine();
private void UpdateHttpHalfView(HttpHalfMessage half, MarkerSet markers)
{
if(half.IsRequest)
{
owner.messagesBox.ChangeText(markers.method, (half as HttpRequest).Method,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(markers.uri, (half as HttpRequest).Uri,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
}
else
{
owner.messagesBox.ChangeText(markers.status, (half as HttpResponse).StatusCode + " " + (half as HttpResponse).StatusMessage,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
}
 
owner.messagesBox.AppendText("Response Version: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseVersionMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.ResponseVersion == HttpVersion.V0_9
? "HTTP/0.9" : http.ResponseVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseVersionMarker);
owner.messagesBox.AppendNewLine();
owner.messagesBox.ChangeText(markers.version, VersionToString(half.Version),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(markers.transferEncoding, EncodingToString(half.TransferEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(markers.length, half.Length < 0
? "<unknown>" : half.Length.ToString(),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(markers.contentEncoding, EncodingToString(half.ContentEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(markers.contentType, half.ContentType == null ? "<unknown>"
: half.ContentType + "/" + half.ContentSubtype,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(markers.charset, half.Charset == null
? "<unknown>" : half.Charset,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
 
owner.messagesBox.AppendText("Response Status: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseStatusMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.ResponseStatusCode + " " + http.ResponseStatusMessage,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseStatusMarker);
owner.messagesBox.AppendNewLine();
ShowHeaders(markers.headersEnum, markers.headers);
}
 
owner.messagesBox.AppendText("Response Transfer Encoding: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseTransferEncodingMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(EncodingToString(http.ResponseTransferEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseTransferEncodingMarker);
owner.messagesBox.AppendNewLine();
protected override void InitView()
{
try
{
lock(http)
{
owner.messagesBox.Clear();
 
owner.messagesBox.AppendText("Response Content Length: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseLengthMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.ResponseLength < 0 ? "<unknown>" : http.ResponseLength.ToString(),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseLengthMarker);
// state
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Response Content Encoding: ",
owner.messagesBox.AppendText("Complete: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseContentEncodingMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(EncodingToString(http.ResponseContentEncoding),
stateMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.Request.Complete && http.Response.Complete ? "YES" : "NO",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseContentEncodingMarker);
owner.messagesBox.EndMark(stateMarker);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Response Content Type: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseContentTypeMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.ResponseContentType == null ? "<unknown>"
: http.ResponseContentType + "/" + http.ResponseContentSubtype,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseContentTypeMarker);
owner.messagesBox.AppendNewLine();
 
owner.messagesBox.AppendText("Response Content Charset: ",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
responseCharsetMarker = owner.messagesBox.BeginMark();
owner.messagesBox.AppendText(http.ResponseCharset == null ? "<unknown>" : http.ResponseCharset,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.EndMark(responseCharsetMarker);
owner.messagesBox.AppendNewLine();
// general info
InitHttpHalfView(http.Request, requestMarkers, "Request");
InitHttpHalfView(http.Response, responseMarkers, "Response");
 
owner.messagesBox.AppendText("Response Headers:",
Color.DarkRed, Color.Transparent, false, false, 0, 0);
// bodies
owner.messagesBox.AppendNewLine();
responseHeadersMarker = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(responseHeadersMarker);
requestMarkers.body = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(requestMarkers.body);
ShowBody(requestMarkers, http.Request, Color.Green);
 
responseHeadersEnum = http.ResponseHeaders.GetEnumerator();
ShowHeaders(responseHeadersEnum, responseHeadersMarker);
 
owner.messagesBox.AppendNewLine();
requestBodyMarker = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(requestBodyMarker);
ShowBody(requestBodyMarker, http.RequestBody, http.RequestLength, http.RequestText, Color.Green);
 
owner.messagesBox.AppendNewLine();
responseBodyMarker = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(responseBodyMarker);
ShowBody(responseBodyMarker, http.ResponseBody, http.ResponseLength, http.ResponseText, Color.Blue);
responseMarkers.body = owner.messagesBox.BeginMark();
owner.messagesBox.EndMark(responseMarkers.body);
ShowBody(responseMarkers, http.Response, Color.Blue);
}
}
finally
2042,56 → 2028,19
 
lock(http)
{
owner.messagesBox.ChangeText(stateMarker, http.RequestComplete && http.ResponseComplete ? "YES" : "NO",
// state
owner.messagesBox.ChangeText(stateMarker, http.Request.Complete && http.Response.Complete ? "YES" : "NO",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestMethodMarker, http.RequestMethod,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestUriMarker, http.RequestUri,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestVersionMarker, http.RequestVersion == HttpVersion.V0_9 ? "HTTP/0.9"
: http.RequestVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestTransferEncodingMarker, EncodingToString(http.RequestTransferEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestLengthMarker, http.RequestLength < 0
? "<unknown>" : http.RequestLength.ToString(),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestContentEncodingMarker, EncodingToString(http.RequestContentEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestContentTypeMarker, http.RequestContentType == null ? "<unknown>"
: http.RequestContentType + "/" + http.RequestContentSubtype,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(requestCharsetMarker, http.RequestCharset == null
? "<unknown>" : http.RequestCharset,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
 
ShowHeaders(requestHeadersEnum, requestHeadersMarker);
// general info
UpdateHttpHalfView(http.Request, requestMarkers);
UpdateHttpHalfView(http.Response, responseMarkers);
 
owner.messagesBox.ChangeText(responseVersionMarker, http.ResponseVersion == HttpVersion.V0_9
? "HTTP/0.9" : http.ResponseVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1",
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(responseStatusMarker, http.ResponseStatusCode + " " + http.ResponseStatusMessage,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(responseTransferEncodingMarker, EncodingToString(http.ResponseTransferEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(responseLengthMarker, http.ResponseLength < 0
? "<unknown>" : http.ResponseLength.ToString(),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(responseContentEncodingMarker, EncodingToString(http.ResponseContentEncoding),
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(responseContentTypeMarker, http.ResponseContentType == null ? "<unknown>"
: http.ResponseContentType + "/" + http.ResponseContentSubtype,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
owner.messagesBox.ChangeText(responseCharsetMarker, http.ResponseCharset == null
? "<unknown>" : http.ResponseCharset,
Color.DarkRed, Color.LightGray, false, false, 0, 27);
 
ShowHeaders(responseHeadersEnum, responseHeadersMarker);
 
owner.messagesBox.DeleteText(requestBodyMarker);
ShowBody(requestBodyMarker, http.RequestBody, http.RequestLength, http.RequestText, Color.Green);
owner.messagesBox.DeleteText(responseBodyMarker);
ShowBody(responseBodyMarker, http.ResponseBody, http.ResponseLength, http.ResponseText, Color.Blue);
// bodies
owner.messagesBox.DeleteText(requestMarkers.body);
ShowBody(requestMarkers, http.Request, Color.Green);
owner.messagesBox.DeleteText(responseMarkers.body);
ShowBody(responseMarkers, http.Response, Color.Blue);
}
}
finally
2129,24 → 2078,24
}
}
 
private void ShowBody(object marker, byte[] body, int len, string text, Color color)
private void ShowBody(MarkerSet markers, HttpHalfMessage half, Color color)
{
if(text != null)
if(half.Text != null)
{
ArrayList lines = Utils.SplitLine(text);
ArrayList lines = Utils.SplitLine(half.Text);
for(int i = 0; i < lines.Count; i++)
{
owner.messagesBox.InsertText(marker, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
owner.messagesBox.InsertNewLine(marker);
owner.messagesBox.InsertText(markers.body, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
owner.messagesBox.InsertNewLine(markers.body);
}
}
else if(body != null)
else if(half.Body != null)
{
ArrayList lines = Utils.SplitLine(Utils.BytesToString(body, len));
ArrayList lines = Utils.SplitLine(Utils.BytesToString(half.Body, half.Length));
for(int i = 0; i < lines.Count; i++)
{
owner.messagesBox.InsertText(marker, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
owner.messagesBox.InsertNewLine(marker);
owner.messagesBox.InsertText(markers.body, (string)lines[i], color, Color.LightGray, false, false, 0, 0);
owner.messagesBox.InsertNewLine(markers.body);
}
}
}
2155,20 → 2104,20
{
// request info
writer.WriteLine(
"Complete: " + (http.RequestComplete && http.ResponseComplete ? "YES" : "NO") + "\r\n"
+ "\r\nRequest Method: " + http.RequestMethod
+ "\r\nRequest URI: " + http.RequestUri
+ "\r\nRequest Version: " + (http.RequestVersion == HttpVersion.V0_9 ? "HTTP/0.9"
: http.RequestVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
+ "\r\nRequest Transfer Encoding: " + EncodingToString(http.RequestTransferEncoding)
+ "\r\nRequest Content Length: " + (http.RequestLength < 0 ? "<unknown>" : http.RequestLength.ToString())
+ "\r\nRequest Content Encoding: " + EncodingToString(http.RequestContentEncoding)
+ "\r\nRequest Content Type: " + (http.RequestContentType == null ? "<unknown>"
: http.RequestContentType + "/" + http.RequestContentSubtype)
+ "\r\nRequest Content Charset: " + (http.RequestCharset == null ? "<unknown>" : http.RequestCharset)
"Complete: " + (http.Request.Complete && http.Response.Complete ? "YES" : "NO") + "\r\n"
+ "\r\nRequest Method: " + http.Request.Method
+ "\r\nRequest URI: " + http.Request.Uri
+ "\r\nRequest Version: " + (http.Request.Version == HttpVersion.V0_9 ? "HTTP/0.9"
: http.Request.Version == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
+ "\r\nRequest Transfer Encoding: " + EncodingToString(http.Request.TransferEncoding)
+ "\r\nRequest Content Length: " + (http.Request.Length < 0 ? "<unknown>" : http.Request.Length.ToString())
+ "\r\nRequest Content Encoding: " + EncodingToString(http.Request.ContentEncoding)
+ "\r\nRequest Content Type: " + (http.Request.ContentType == null ? "<unknown>"
: http.Request.ContentType + "/" + http.Request.ContentSubtype)
+ "\r\nRequest Content Charset: " + (http.Request.Charset == null ? "<unknown>" : http.Request.Charset)
+ "\r\nRequest Headers:");
 
foreach(HttpHeader h in http.RequestHeaders)
foreach(HttpHeader h in http.Request.Headers)
{
int indent = 0;
foreach(string val in h.Values)
2187,19 → 2136,19
 
// response info
writer.WriteLine(
"\r\nResponse Version: " + (http.ResponseVersion == HttpVersion.V0_9
? "HTTP/0.9" : http.ResponseVersion == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
+ "\r\nResponse Status: " + http.ResponseStatusCode + " " + http.ResponseStatusMessage
+ "\r\nResponse Transfer Encoding: " + EncodingToString(http.ResponseTransferEncoding)
+ "\r\nResponse Content Length: " + (http.ResponseLength < 0
? "<unknown>" : http.ResponseLength.ToString())
+ "\r\nResponse Content Encoding: " + EncodingToString(http.ResponseContentEncoding)
+ "\r\nResponse Content Type: " + (http.ResponseContentType == null ? "<unknown>"
: http.ResponseContentType + "/" + http.ResponseContentSubtype)
+ "\r\nResponse Content Charset: " + (http.ResponseCharset == null ? "<unknown>" : http.ResponseCharset)
"\r\nResponse Version: " + (http.Response.Version == HttpVersion.V0_9
? "HTTP/0.9" : http.Response.Version == HttpVersion.V1_0 ? "HTTP/1.0" : "HTTP/1.1")
+ "\r\nResponse Status: " + http.Response.StatusCode + " " + http.Response.StatusMessage
+ "\r\nResponse Transfer Encoding: " + EncodingToString(http.Response.TransferEncoding)
+ "\r\nResponse Content Length: " + (http.Response.Length < 0
? "<unknown>" : http.Response.Length.ToString())
+ "\r\nResponse Content Encoding: " + EncodingToString(http.Response.ContentEncoding)
+ "\r\nResponse Content Type: " + (http.Response.ContentType == null ? "<unknown>"
: http.Response.ContentType + "/" + http.Response.ContentSubtype)
+ "\r\nResponse Content Charset: " + (http.Response.Charset == null ? "<unknown>" : http.Response.Charset)
+ "\r\nResponse Headers:");
 
foreach(HttpHeader h in http.ResponseHeaders)
foreach(HttpHeader h in http.Response.Headers)
{
int indent = 0;
foreach(string val in h.Values)
2218,23 → 2167,23
writer.WriteLine();
 
// request body
if(http.RequestText != null)
if(http.Request.Text != null)
{
writer.WriteLine(http.RequestText);
writer.WriteLine(http.Request.Text);
}
else if(http.RequestBody != null)
else if(http.Request.Body != null)
{
writer.WriteLine(Utils.BytesToString(http.RequestBody, http.RequestLength));
writer.WriteLine(Utils.BytesToString(http.Request.Body, http.Request.Length));
}
 
// response body
if(http.ResponseText != null)
if(http.Response.Text != null)
{
writer.WriteLine(http.ResponseText);
writer.WriteLine(http.Response.Text);
}
else if(http.ResponseBody != null)
else if(http.Response.Body != null)
{
writer.WriteLine(Utils.BytesToString(http.ResponseBody, http.ResponseLength));
writer.WriteLine(Utils.BytesToString(http.Response.Body, http.Response.Length));
}
 
writer.WriteLine("===============================================================");
/TCPproxy/trunk/Network.cs
8,14 → 8,13
using System.Text.RegularExpressions;
using System.Xml;
 
// FIXME deny write access to all public properties
// FIXME for text/xml get encoding from body if not specified in header
// FIXME option to not store parsed data, just raw packets and reparse on demand
// FIXME implement all others (not 'identity' and 'chunked') transfer-encodings
// FIXME benchmark one-by-one byte iterator vs. block read
// FIXME recongize "100 (Continue)" response, use next (real) response as part of same
// request-response interaction
// FIXME split HttpMessage class to request and response
// FIXME:
// - deny write access to all public properties
// - for text/xml get encoding from body if not specified in header
// - option to not store parsed data, just raw packets and reparse on demand
// - implement all others (not 'identity' and 'chunked') transfer- and content- encodings
// - benchmark one-by-one byte iterator vs. block read
// - locks for HttpMessage in parser
namespace TCPproxy
{
public enum BinLogTypes
289,18 → 288,19
 
public class TcpConnection
{
private string id;
private DateTime startTimestamp = DateTime.MinValue;
private DateTime localEndTimestamp = DateTime.MinValue;
private DateTime remoteEndTimestamp = DateTime.MinValue;
private IPEndPoint localPoint;
private IPEndPoint remotePoint;
private LinkedList messages = new LinkedList();
private SocketState localState = SocketState.None;
private SocketState remoteState = SocketState.None;
private SocketWorker worker;
private LinkedList https = new LinkedList();
private HttpParser httpParser;
private string id;
private DateTime startTimestamp = DateTime.MinValue;
private DateTime localEndTimestamp = DateTime.MinValue;
private DateTime remoteEndTimestamp = DateTime.MinValue;
private IPEndPoint localPoint;
private IPEndPoint remotePoint;
private LinkedList messages = new LinkedList();
private LinkedListReadOnly messagesReadOnly;
private SocketState localState = SocketState.None;
private SocketState remoteState = SocketState.None;
private SocketWorker worker;
private LinkedList https = new LinkedList();
private HttpParser httpParser;
 
public string Id
{
332,9 → 332,9
get { return remotePoint; }
}
 
public LinkedList Messages
public LinkedListReadOnly Messages
{
get { return messages; } // FIXME return read-only object
get { return new LinkedListReadOnly(messages); }
}
 
public SocketState LocalState
371,8 → 371,9
 
internal TcpConnection(string id)
{
this.id = id;
this.httpParser = HttpParser.Parse(this);
this.id = id;
this.httpParser = HttpParser.Parse(this);
this.messagesReadOnly = new LinkedListReadOnly(messages);
}
 
internal void Continue(IPAddress resendHost, int resendPort, Socket localSocket)
1511,23 → 1512,23
 
messages.AddHttpMessage(http);
SkipEmptyLines(requestPos);
http.RequestStartTimestamp = requestPos.CurrentMessage.Timestamp;
http.Request.StartTimestamp = requestPos.CurrentMessage.Timestamp;
 
ParseRequestLine(requestPos, http);
http.UpdateHttpMessage();
 
ParseHeaders(requestPos, http, true);
SetRequestProperties(http);
ParseHeaders(requestPos, http, http.Request);
SetRequestProperties(http, http.Request);
http.UpdateHttpMessage();
 
ParseBody(requestPos, http, true);
if("text" == http.RequestContentType && "xml" == http.RequestContentSubtype)
ParseBody(requestPos, http, http.Request);
if("text" == http.Request.ContentType && "xml" == http.Request.ContentSubtype)
{
http.RequestXml = new XmlMessage(http.RequestText);
http.Request.Xml = new XmlMessage(http.Request.Text);
}
http.UpdateHttpMessage();
 
http.RequestComplete = true;
http.Request.Complete = true;
http.UpdateHttpMessage();
 
SkipEmptyLines(requestPos);
1571,29 → 1572,23
lock(https)
{
if(!httpEnum.MoveNext())
throw new Exception("Tried to find response by no HTTP message available");
throw new Exception("Tried to find response but no HTTP message available");
}
}
 
HttpMessage http = (HttpMessage)httpEnum.Current;
 
ParseResponseLine(responsePos, http);
http.ResponseStartTimestamp = responsePos.CurrentMessage.Timestamp;
http.UpdateHttpMessage();
 
ParseHeaders(responsePos, http, false);
SetResponseProperties(http);
http.UpdateHttpMessage();
 
ParseBody(responsePos, http, false);
if("text" == http.ResponseContentType && "xml" == http.ResponseContentSubtype)
ParseResponse(responsePos, http);
if(http.Response.StatusCode == 100) // "100 (Continue)" response
{
http.ResponseXml = new XmlMessage(http.ResponseText);
http.GotContinueResponse();
ParseResponse(responsePos, http); // once again
}
http.UpdateHttpMessage();
 
http.ResponseComplete = true;
http.Response.Complete = true;
http.UpdateHttpMessage();
responsePos.NextOctetAndBack(); // go forward to see end of connection
}
}
catch(Exception ex)
1672,14 → 1667,14
private void ParseRequestLine(ParsePosition pos, HttpMessage http)
{
// method
http.RequestMethod = GetToken(pos, 1024);
if(http.RequestMethod == null || http.RequestMethod.Length == 0)
http.Request.Method = GetToken(pos, 1024);
if(http.Request.Method == null || http.Request.Method.Length == 0)
throw new HttpParseException("Request method name expected");
ExpectSpace(pos);
 
// URI
http.RequestUri = GetUntilSpace(pos, 1024);
if(http.RequestUri == null || http.RequestUri.Length == 0)
http.Request.Uri = GetUntilSpace(pos, 1024);
if(http.Request.Uri == null || http.Request.Uri.Length == 0)
throw new HttpParseException("Request URI expected");
 
if(pos.IsEnd)
1691,7 → 1686,7
{
pos.Back();
ExpectCRLF(pos);
http.RequestVersion = HttpVersion.V0_9;
http.Request.Version = HttpVersion.V0_9;
}
else if(b != 32)
{
1705,11 → 1700,11
 
if(versionStr == "HTTP/1.0")
{
http.RequestVersion = HttpVersion.V1_0;
http.Request.Version = HttpVersion.V1_0;
}
else if(versionStr == "HTTP/1.1")
{
http.RequestVersion = HttpVersion.V1_1;
http.Request.Version = HttpVersion.V1_1;
}
else
{
1719,7 → 1714,7
ExpectCRLF(pos);
}
 
private void ParseHeaders(ParsePosition pos, HttpMessage http, bool request)
private void ParseHeaders(ParsePosition pos, HttpMessage http, HttpHalfMessage half)
{
if(pos.IsEnd) return; // end of TCP messages
 
1737,19 → 1732,16
 
string name = GetToken(pos, 0);
if(name == null || name.Length == 0)
throw new HttpParseException("Request header name expected");
throw new HttpParseException("Header name expected");
 
if(pos.IsEnd || pos.NextOctet() != 58) // :
throw new HttpParseException("Request header value expected");
throw new HttpParseException("Header value expected");
 
string s = TrimHeaderValue(GetUntilEoL(pos, 0));
 
ExpectCRLF(pos);
 
if(request)
http.AddRequestHeader(name, s);
else
http.AddResponseHeader(name, s);
half.AddHeader(name, s);
}
}
 
1877,77 → 1869,89
return HttpContentEncoding.Unknown;
}
 
private void SetRequestProperties(HttpMessage http)
private void SetHttpProperties(HttpMessage http, HttpHalfMessage half)
{
// length
string contentLength = (string)http.RequestHeadersHash["content-length"];
HttpHeader contentLength = half.GetHeader("content-length");
if(contentLength != null)
{
http.RequestLength = int.Parse(contentLength);
half.Length = int.Parse(contentLength.Values[0]);
}
 
// transfer encoding
http.RequestTransferEncoding = ParseTransferEncoding((string)http.RequestHeadersHash["transfer-encoding"]);
HttpHeader transferEncoding = half.GetHeader("transfer-encoding");
half.TransferEncoding = ParseTransferEncoding((transferEncoding == null) ? null : transferEncoding.Values[0]);
if(HasBody(http, half) && half.TransferEncoding == HttpTransferEncoding.None)
half.TransferEncoding = HttpTransferEncoding.Identity;
 
// content encoding
http.RequestContentEncoding = ParseContentEncoding((string)http.RequestHeadersHash["content-encoding"]);
HttpHeader contentEncoding = half.GetHeader("content-encoding");
half.ContentEncoding = ParseContentEncoding((contentEncoding == null) ? null : contentEncoding.Values[0]);
if(HasBody(http, half) && half.ContentEncoding == HttpContentEncoding.None)
half.ContentEncoding = HttpContentEncoding.Identity;
 
// type & charset
string contentType = (string)http.RequestHeadersHash["content-type"];
HttpHeader contentType = half.GetHeader("content-type");
if(contentType != null)
{
Match match = Regex.Match(contentType, @"^\s*(\S+)/(\S+)\s*($|;\s*(charset=""?(\S+)""?)?)");
Match match = Regex.Match(contentType.Values[0], @"^\s*(\S+)/(\S+)\s*($|;\s*(charset=""?(\S+)""?)?)");
if(match.Success)
{
http.RequestContentType = match.Groups[1].Captures[0].Value;
http.RequestContentSubtype = match.Groups[2].Captures[0].Value;
if(match.Groups.Count >= 6) http.RequestCharset = match.Groups[5].Captures[0].Value.Trim('"');
half.ContentType = match.Groups[1].Captures[0].Value;
half.ContentSubtype = match.Groups[2].Captures[0].Value;
if(match.Groups.Count >= 6 && match.Groups[5].Captures.Count > 0)
half.Charset = match.Groups[5].Captures[0].Value.Trim('"');
}
}
}
 
private void SetRequestProperties(HttpMessage http, HttpRequest request)
{
SetHttpProperties(http, request);
 
// soap action
string soapAction = (string)http.RequestHeadersHash["soapaction"];
HttpHeader soapAction = request.GetHeader("soapaction");
if(soapAction != null)
{
http.SoapAction = soapAction.Trim('"');
request.SoapAction = soapAction.Values[0];
}
}
 
// RFC 2616: 4.3
private bool WaitForBody(HttpMessage http, bool isRequest)
private bool HasBody(HttpMessage http, HttpHalfMessage half)
{
if(isRequest)
if(half.IsRequest)
{
return (http.RequestLength > 0)
|| (http.RequestTransferEncoding != HttpTransferEncoding.None);
return (http.Request.Length > 0)
|| (http.Request.TransferEncoding != HttpTransferEncoding.None);
}
else
{
if(http.RequestMethod == "HEAD") return false;
if(http.ResponseStatusCode < 200) return false;
if(http.ResponseStatusCode == 204) return false;
if(http.ResponseStatusCode == 304) return false;
if(http.Request.Method == "HEAD") return false;
if(http.Response.StatusCode < 200) return false;
if(http.Response.StatusCode == 204) return false;
if(http.Response.StatusCode == 304) return false;
 
return true;
}
}
 
private void ParseBody(ParsePosition pos, HttpMessage http, bool isRequest)
private void ParseBody(ParsePosition pos, HttpMessage http, HttpHalfMessage half)
{
if(!WaitForBody(http, isRequest)) return;
if(!HasBody(http, half)) return;
 
// FIXME parse and save on-the-fly, dont wait util end of message
 
byte[] bin = new byte[8*1024];
int len = 0; // current bin biffer length
int limit = (isRequest ? http.RequestLength : http.ResponseLength);
int limit = half.Length;
int chunkLen = -1; // current length of current chunk
int chunkLimit = -1;
HttpTransferEncoding transferEncoding = (isRequest ? http.RequestTransferEncoding : http.ResponseTransferEncoding);
HttpContentEncoding contentEncoding = (isRequest ? http.RequestContentEncoding : http.ResponseContentEncoding);
string contentType = (isRequest ? http.RequestContentType : http.ResponseContentType);
string contentSubtype = (isRequest ? http.RequestContentSubtype : http.ResponseContentSubtype);
string charset = (isRequest ? http.RequestCharset : http.ResponseCharset);
HttpTransferEncoding transferEncoding = half.TransferEncoding;
HttpContentEncoding contentEncoding = half.ContentEncoding;
string contentType = half.ContentType;
string contentSubtype = half.ContentSubtype;
string charset = half.Charset;
 
for(byte b = pos.NextOctet(); !pos.IsEnd; b = pos.NextOctet())
{
2029,18 → 2033,27
}
}
 
if(isRequest)
half.Length = len;
half.Body = bin;
half.Text = text;
}
 
private void ParseResponse(ParsePosition pos, HttpMessage http)
{
ParseResponseLine(pos, http);
http.Response.StartTimestamp = pos.CurrentMessage.Timestamp;
http.UpdateHttpMessage();
 
ParseHeaders(pos, http, http.Response);
SetHttpProperties(http, http.Response);
http.UpdateHttpMessage();
 
ParseBody(pos, http, http.Response);
if("text" == http.Response.ContentType && "xml" == http.Response.ContentSubtype)
{
http.RequestLength = len;
http.RequestBody = bin;
http.RequestText = text;
http.Response.Xml = new XmlMessage(http.Response.Text);
}
else
{
http.ResponseLength = len;
http.ResponseBody = bin;
http.ResponseText = text;
}
http.UpdateHttpMessage();
}
 
private void ParseResponseLine(ParsePosition pos, HttpMessage http)
2052,11 → 2065,11
 
if(versionStr == "HTTP/1.0")
{
http.ResponseVersion = HttpVersion.V1_0;
http.Response.Version = HttpVersion.V1_0;
}
else if(versionStr == "HTTP/1.1")
{
http.ResponseVersion = HttpVersion.V1_1;
http.Response.Version = HttpVersion.V1_1;
}
else
{
2073,7 → 2086,7
{
int c = int.Parse(code);
if(c < 100 || c >= 1000) throw new HttpParseException("Status code expected");
http.ResponseStatusCode = c;
http.Response.StatusCode = c;
}
catch(FormatException)
{
2082,7 → 2095,7
ExpectSpace(pos);
 
// status message
http.ResponseStatusMessage = GetUntilEoL(pos, 0);
http.Response.StatusMessage = GetUntilEoL(pos, 0);
 
if(pos.IsEnd)
throw new HttpParseException("Unexpected end of message");
2089,38 → 2102,6
 
ExpectCRLF(pos);
}
 
private void SetResponseProperties(HttpMessage http)
{
// length
HttpHeader contentLength = (HttpHeader)http.ResponseHeadersHash["content-length"];
if(contentLength != null)
{
http.ResponseLength = int.Parse(contentLength.Values[0]);
}
 
// transfer encoding
HttpHeader transferEncoding = (HttpHeader)http.ResponseHeadersHash["transfer-encoding"];
http.ResponseTransferEncoding = ParseTransferEncoding((transferEncoding == null) ? null : transferEncoding.Values[0]);
 
// content encoding
HttpHeader contentEncoding = (HttpHeader)http.ResponseHeadersHash["content-encoding"];
http.ResponseContentEncoding = ParseContentEncoding((contentEncoding == null) ? null : contentEncoding.Values[0]);
 
// type & charset
HttpHeader contentType = (HttpHeader)http.ResponseHeadersHash["content-type"];
if(contentType != null)
{
Match match = Regex.Match(contentType.Values[0], @"^\s*(\S+)/(\S+)\s*($|;\s*(charset=""?(\S+)""?)?)");
if(match.Success)
{
http.ResponseContentType = match.Groups[1].Captures[0].Value;
http.ResponseContentSubtype = match.Groups[2].Captures[0].Value;
if(match.Groups.Count >= 6 && match.Groups[5].Captures.Count > 0)
http.ResponseCharset = match.Groups[5].Captures[0].Value.Trim('"');
}
}
}
}
 
public class HttpHeader
2165,258 → 2146,200
}
}
 
public class HttpMessage
public abstract class HttpHalfMessage
{
private bool requestComplete = false;
private HttpVersion requestVersion;
private string requestMethod;
private string requestUri;
private LinkedList requestHeaders = new LinkedList();
private Hashtable requestHeadersHash = new Hashtable();
private int requestLength = -1; // -1 == unknown
private HttpTransferEncoding requestTransferEncoding = HttpTransferEncoding.None;
private HttpContentEncoding requestContentEncoding = HttpContentEncoding.None;
private string requestContentType;
private string requestContentSubtype;
private string requestCharset;
private string soapAction;
private byte[] requestBody;
private string requestText;
private XmlMessage requestXml;
private DateTime requestStartTimestamp = DateTime.MinValue;
private bool complete = false;
private HttpVersion version;
protected LinkedList headers = new LinkedList();
protected Hashtable headersHash = new Hashtable();
private int length = -1; // -1 == unknown
private HttpTransferEncoding transferEncoding = HttpTransferEncoding.None;
private HttpContentEncoding contentEncoding = HttpContentEncoding.None;
private string contentType;
private string contentSubtype;
private string charset;
private byte[] body;
private string text;
private XmlMessage xml;
private DateTime startTimestamp = DateTime.MinValue;
 
private bool responseComplete = false;
private HttpVersion responseVersion;
private int responseStatusCode;
private string responseStatusMessage;
private LinkedList responseHeaders = new LinkedList();
private Hashtable responseHeadersHash = new Hashtable();
private int responseLength = -1; // -1 == unknown
private HttpTransferEncoding responseTransferEncoding = HttpTransferEncoding.None;
private HttpContentEncoding responseContentEncoding = HttpContentEncoding.None;
private string responseContentType;
private string responseContentSubtype;
private string responseCharset;
private byte[] responseBody;
private string responseText;
private XmlMessage responseXml;
private DateTime responseStartTimestamp = DateTime.MinValue;
 
public bool RequestComplete
public abstract bool IsRequest
{
get { return requestComplete; }
set { requestComplete = value; }
get;
}
 
public HttpVersion RequestVersion
public bool Complete
{
get { return requestVersion; }
set { requestVersion = value; }
get { return complete; }
set { complete = value; }
}
 
public string RequestMethod
public HttpVersion Version
{
get { return requestMethod; }
set { requestMethod = value; }
get { return version; }
set { version = value; }
}
 
public string RequestUri
public LinkedList Headers
{
get { return requestUri; }
set { requestUri = value; }
get { return headers; }
}
 
public LinkedList RequestHeaders
public int Length
{
get { return requestHeaders; }
get { return length; }
set { length = value; }
}
 
public IDictionary RequestHeadersHash
public HttpTransferEncoding TransferEncoding
{
get { return requestHeadersHash; }
get { return transferEncoding; }
set { transferEncoding = value; }
}
 
public int RequestLength
public HttpContentEncoding ContentEncoding
{
get { return requestLength; }
set { requestLength = value; }
get { return contentEncoding; }
set { contentEncoding = value; }
}
 
public HttpTransferEncoding RequestTransferEncoding
public string ContentType
{
get { return requestTransferEncoding; }
set { requestTransferEncoding = value; }
get { return contentType; }
set { contentType = value; }
}
 
public HttpContentEncoding RequestContentEncoding
public string ContentSubtype
{
get { return requestContentEncoding; }
set { requestContentEncoding = value; }
get { return contentSubtype; }
set { contentSubtype = value; }
}
 
public string RequestContentType
public string Charset
{
get { return requestContentType; }
set { requestContentType = value; }
get { return charset; }
set { charset = value; }
}
 
public string RequestContentSubtype
public byte[] Body
{
get { return requestContentSubtype; }
set { requestContentSubtype = value; }
get { return body; }
set { body = value; }
}
 
public string RequestCharset
public string Text
{
get { return requestCharset; }
set { requestCharset = value; }
get { return text; }
set { text = value; }
}
 
public string SoapAction
public XmlMessage Xml
{
get { return soapAction; }
set { soapAction = value; }
get { return xml; }
set { xml = value; }
}
 
public byte[] RequestBody
{
get { return requestBody; }
set { requestBody = value; }
}
 
public string RequestText
{
get { return requestText; }
set { requestText = value; }
}
 
public XmlMessage RequestXml
{
get { return requestXml; }
set { requestXml = value; }
}
 
public DateTime RequestStartTimestamp
public DateTime StartTimestamp
{
get { return requestStartTimestamp; }
set { requestStartTimestamp = value; }
get { return startTimestamp; }
set { startTimestamp = value; }
}
 
public bool ResponseComplete
public void AddHeader(string name, string headerValue)
{
get { return responseComplete; }
set { responseComplete = value; }
HttpHeader header = (HttpHeader)headersHash[name];
if(header == null)
{
header = new HttpHeader(name, headerValue);
headers.Add(header);
headersHash.Add(name.ToLower(), header);
}
else
{
header.AddValue(headerValue);
}
}
 
public HttpVersion ResponseVersion
public HttpHeader GetHeader(string name)
{
get { return responseVersion; }
set { responseVersion = value; }
return (HttpHeader)headersHash[name.ToLower()];
}
}
 
public int ResponseStatusCode
{
get { return responseStatusCode; }
set { responseStatusCode = value; }
}
public class HttpRequest : HttpHalfMessage
{
private string method;
private string uri;
private string soapAction;
 
public string ResponseStatusMessage
public override bool IsRequest
{
get { return responseStatusMessage; }
set { responseStatusMessage = value; }
get { return true; }
}
 
public LinkedList ResponseHeaders
public string Method
{
get { return responseHeaders; }
get { return method; }
set { method = value; }
}
 
public IDictionary ResponseHeadersHash
public string Uri
{
get { return responseHeadersHash; }
get { return uri; }
set { uri = value; }
}
 
public int ResponseLength
public string SoapAction
{
get { return responseLength; }
set { responseLength = value; }
get { return soapAction; }
set { soapAction = value; }
}
}
 
public HttpTransferEncoding ResponseTransferEncoding
{
get { return responseTransferEncoding; }
set { responseTransferEncoding = value; }
}
public class HttpResponse : HttpHalfMessage
{
private int statusCode;
private string statusMessage;
 
public HttpContentEncoding ResponseContentEncoding
public override bool IsRequest
{
get { return responseContentEncoding; }
set { responseContentEncoding = value; }
get { return false; }
}
 
public string ResponseContentType
public int StatusCode
{
get { return responseContentType; }
set { responseContentType = value; }
get { return statusCode; }
set { statusCode = value; }
}
 
public string ResponseContentSubtype
public string StatusMessage
{
get { return responseContentSubtype; }
set { responseContentSubtype = value; }
get { return statusMessage; }
set { statusMessage = value; }
}
}
 
public string ResponseCharset
{
get { return responseCharset; }
set { responseCharset = value; }
}
public class HttpMessage
{
private HttpRequest request = new HttpRequest();
private HttpResponse continueResponse = null;
private HttpResponse response = new HttpResponse();
 
public byte[] ResponseBody
public HttpRequest Request
{
get { return responseBody; }
set { responseBody = value; }
get { return request; }
}
 
public string ResponseText
public HttpResponse ContinueResponse
{
get { return responseText; }
set { responseText = value; }
get { return continueResponse; }
}
 
public XmlMessage ResponseXml
public HttpResponse Response
{
get { return responseXml; }
set { responseXml = value; }
get { return response; }
}
 
public DateTime ResponseStartTimestamp
{
get { return responseStartTimestamp; }
set { responseStartTimestamp = value; }
}
 
public void AddRequestHeader(string name, string headerValue)
{
requestHeaders.Add(new HttpHeader(name, headerValue));
requestHeadersHash.Add(name.ToLower(), headerValue);
}
 
public void AddResponseHeader(string name, string headerValue)
{
HttpHeader header = (HttpHeader)responseHeadersHash[name];
if(header == null)
{
header = new HttpHeader(name, headerValue);
responseHeaders.Add(header);
responseHeadersHash.Add(name.ToLower(), header);
}
else
{
header.AddValue(headerValue);
}
}
 
public event TcpEventHandler Update;
 
protected virtual void OnUpdate(TcpEventArgs e)
2431,6 → 2354,12
{
OnUpdate(new TcpEventArgs());
}
 
internal void GotContinueResponse()
{
continueResponse = response;
response = new HttpResponse();
}
}
 
internal class HttpParseException : Exception
/TCPproxy/trunk/LinkedList.cs
89,4 → 89,19
count++;
}
}
 
public class LinkedListReadOnly
{
private LinkedList origin;
 
public LinkedListReadOnly(LinkedList origin)
{
this.origin = origin;
}
 
public IEnumerator GetEnumerator()
{
return origin.GetEnumerator();
}
}
}