Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1198 → Rev 1199

/TCPproxy/trunk/Network.cs
1,5 → 1,6
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
12,6 → 13,12
// FIXME option to not store parsed data, just raw packets and reparse on demand
namespace TCPproxy
{
public enum BinLogTypes
{
None = 1,
TcpConnection
}
 
public enum LogLevel
{
Critical,
34,6 → 41,7
 
public enum TcpMessageDirection
{
None,
Local,
Remote
}
251,6 → 259,15
TcpLogEventArgs e = new TcpLogEventArgs(level, null, ex);
OnLog(e);
}
 
public void ReadBinLog(BinaryReader reader)
{
// tcp connections
TcpConnection tcp;
while((tcp = TcpConnection.ReadBinLog(reader)) != null) {
OnNewTcp(new TcpConnectionEventArgs(tcp));
}
}
}
 
public class TcpConnection
350,7 → 367,8
 
public void Cancel()
{
worker.Cancel();
if(worker != null)
worker.Cancel();
}
 
protected TcpMessage Append(TcpMessageDirection direction, byte[] newBytes)
388,13 → 406,11
}
}
 
 
public override string ToString() // FIXME delete the method
{
return id + " " + startTimestamp.ToString("HH:mm:ss.ffff");
}
 
 
protected void SetLocalPoint(IPEndPoint localPoint)
{
this.localPoint = localPoint;
575,6 → 591,113
OnLog(e);
}
 
private void WriteEndPoint(BinaryWriter writer, IPEndPoint endPoint)
{
// end point as (family as int, ip length, ip as bytes, port)
byte[] ipBuf = endPoint.Address.GetAddressBytes();
writer.Write((UInt32)endPoint.AddressFamily);
writer.Write((UInt32)ipBuf.Length);
writer.Write(ipBuf);
writer.Write((UInt32)endPoint.Port);
}
 
public void WriteBinLog(BinaryWriter writer)
{
// header
writer.Write((byte)BinLogTypes.TcpConnection);
 
// id as (length, UTF-8)
byte[] idBuf = Encoding.UTF8.GetBytes(id);
writer.Write((UInt32)idBuf.Length);
writer.Write(idBuf);
 
// timestamps as ticks
writer.Write((UInt64)startTimestamp.Ticks);
writer.Write((UInt64)localEndTimestamp.Ticks);
writer.Write((UInt64)remoteEndTimestamp.Ticks);
 
// end points as (family as int, ip length, ip as bytes, port)
WriteEndPoint(writer, localPoint);
WriteEndPoint(writer, remotePoint);
 
// states as byte
writer.Write((byte)localState);
writer.Write((byte)remoteState);
 
// each tcp message as (direction as byte, timestamp in ticks, length, content)
foreach(TcpMessage message in messages) {
writer.Write((byte)message.Direction);
writer.Write((UInt64)message.Timestamp.Ticks);
writer.Write((UInt32)message.Length);
writer.Write(message.Bytes, 0, message.Length);
}
 
// end of stream marker
writer.Write((byte)TcpMessageDirection.None);
}
 
private static IPEndPoint ReadEndPoint(BinaryReader reader)
{
// end point as (family as int, ip length, ip as bytes, port)
AddressFamily fam = (AddressFamily)reader.ReadInt32();
int addressLength = reader.ReadInt32();
byte[] addressBytes = reader.ReadBytes(addressLength);
int port = reader.ReadInt32();
IPAddress address = new IPAddress(addressBytes);
 
return new IPEndPoint(address, port);
}
 
internal static TcpConnection ReadBinLog(BinaryReader reader)
{
// header
BinLogTypes recordType = (BinLogTypes)reader.ReadByte();
 
if(recordType == BinLogTypes.None)
return null;
else if(recordType == BinLogTypes.TcpConnection) {
}
else
throw new Exception("Wrong data type");
 
// id as (length, UTF-8)
int idLength = (int)reader.ReadUInt32();
string id = Encoding.UTF8.GetString(reader.ReadBytes(idLength));
 
TcpConnection tcp = new TcpConnection(id);
 
// timestamps as ticks
tcp.startTimestamp = new DateTime((long)reader.ReadUInt64());
tcp.localEndTimestamp = new DateTime((long)reader.ReadUInt64());
tcp.remoteEndTimestamp = new DateTime((long)reader.ReadUInt64());
 
// end points as (family as int, ip length, ip as bytes, port)
tcp.localPoint = ReadEndPoint(reader);
tcp.remotePoint = ReadEndPoint(reader);
 
// states as byte - read but ignore
reader.ReadByte();
reader.ReadByte();
 
// each tcp message as (direction as byte, timestamp in ticks, length, content)
tcp.localState = SocketState.Closed;
tcp.remoteState = SocketState.Closed;
for(;;) {
TcpMessageDirection direction = (TcpMessageDirection)reader.ReadByte();
if(direction == TcpMessageDirection.None) break; // end of stream marker
 
DateTime timestamp = new DateTime((long)reader.ReadUInt64());
int bufLength = (int)reader.ReadUInt32();
byte[] buf = reader.ReadBytes(bufLength);
 
TcpMessage msg = tcp.Append(direction, buf);
msg.SetTimestamp(timestamp);
}
tcp.OnUpdate(new TcpEventArgs());
 
return tcp;
}
 
protected class SocketWorker
{
private enum SendCommandType
1208,6 → 1331,9
{
newMessageEvent.Reset();
moved = messagesEnum.MoveNext();
 
if(!moved && messages.LocalState == SocketState.Closed && messages.RemoteState == SocketState.Closed)
return false;
}
 
if(moved) break;
1293,20 → 1419,19
}
}
 
private TcpConnection messages;
private AutoResetEvent requestEvent = new AutoResetEvent(false); // new request found
private AutoResetEvent nextMessageEvent = new AutoResetEvent(false); // request goes to next TCP message
private LinkedList https = new LinkedList();
private ParsePosition requestPos;
private ParsePosition responsePos;
private AutoResetEvent newMessageEvent = new AutoResetEvent(false); // new TCP message available
private Thread runThread;
private TcpConnection messages;
private AutoResetEvent requestEvent = new AutoResetEvent(false); // new request found
private AutoResetEvent nextMessageEvent = new AutoResetEvent(false); // request goes to next TCP message
private LinkedList https = new LinkedList();
private ParsePosition requestPos;
private ParsePosition responsePos;
private Thread runThread;
 
public static HttpParser Parse(TcpConnection messages)
{
HttpParser parser = new HttpParser(messages);
parser.runThread = new Thread(new ThreadStart(parser.Run));
parser.RunThread.Name = "HttpParser.Run";
parser.runThread.Name = "HttpParser.Run";
parser.runThread.Start();
 
return parser;
1325,7 → 1450,9
 
private HttpParser(TcpConnection messages)
{
this.messages = messages;
this.messages = messages;
this.requestPos = new ParsePosition(messages, nextMessageEvent);
this.responsePos = new ParsePosition(messages, null);
InitTables();
}
 
1338,9 → 1465,6
 
try
{
requestPos = new ParsePosition(messages, nextMessageEvent);
responsePos = new ParsePosition(messages, null);
 
responseThread = new Thread(new ThreadStart(MatchResponses));
responseThread.Name = "HttpParser.MatchResponses";
responseThread.Start();
2240,7 → 2364,7
 
public class TcpMessage
{
private TcpMessageDirection direction;
private TcpMessageDirection direction = TcpMessageDirection.None;
private byte[] bytes;
private int length = 0;
private DateTime timestamp;
2274,6 → 2398,11
get { return timestamp; }
}
 
internal void SetTimestamp(DateTime timestamp)
{
this.timestamp = timestamp;
}
 
internal TcpMessage()
{
this.timestamp = DateTime.Now;