Subversion Repositories general

Compare Revisions

Ignore whitespace Rev 1092 → Rev 1122

/TCPproxy/trunk/Network.cs
28,7 → 28,7
Connecting,
Connected,
ShutdownSend,
ShutdownReceive,
ShutdownReceived,
Closed
}
 
152,10 → 152,10
socket.BeginAccept(new AsyncCallback(OnClientConnect), null);
SendLog(null, LogLevel.Important, "Listen on " + socket.LocalEndPoint);
}
 
public void StopListening()
{
try
try
{
if(socket != null)
{
164,10 → 164,10
}
}
catch(ObjectDisposedException) // socket is already closed
{
}
catch(Exception ex)
{
}
catch(Exception ex)
{
Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
}
}
189,7 → 189,7
 
protected virtual void OnClientConnect(IAsyncResult asyn)
{
try
try
{
Socket worker = socket.EndAccept(asyn);
socket.BeginAccept(new AsyncCallback(OnClientConnect), null); // wait for next client
198,7 → 198,7
tcp.Close += new TcpEventHandler(TcpConnectionClosed);
OnNewTcp(new TcpConnectionEventArgs(tcp));
 
lock(tcpConnections)
lock(tcpConnections)
{
tcpConnections.Add(tcp);
}
206,7 → 206,7
tcp.Continue(resendHost, resendPort, worker);
}
catch(ObjectDisposedException) {} // socket is closed
catch(Exception ex)
catch(Exception ex)
{
Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
}
224,9 → 224,9
 
protected virtual void OnNewTcp(TcpConnectionEventArgs e)
{
if(NewTcp != null)
if(NewTcp != null)
{
NewTcp(this, e);
NewTcp(this, e);
}
}
 
234,9 → 234,9
 
protected virtual void OnLog(TcpLogEventArgs e)
{
if(Log != null)
if(Log != null)
{
Log(this, e);
Log(this, e);
}
}
 
364,7 → 364,7
 
TcpMessage message;
 
lock(this)
lock(this)
{
message = new TcpMessage();
message.Direction = direction;
397,71 → 397,71
 
protected void SetLocalPoint(IPEndPoint localPoint)
{
this.localPoint = localPoint;
this.localPoint = localPoint;
OnUpdate(new TcpEventArgs());
}
 
protected void SetRemotePoint(IPEndPoint remotePoint)
{
this.remotePoint = remotePoint;
this.remotePoint = remotePoint;
OnUpdate(new TcpEventArgs());
}
 
protected void SetLocalState(SocketState localState)
{
if(this.localState == SocketState.None && localState == SocketState.Connecting)
if(this.localState == SocketState.None && localState == SocketState.Connecting)
{
startTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.None && localState == SocketState.Connected)
else if(this.localState == SocketState.None && localState == SocketState.Connected)
{
startTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.None && localState == SocketState.Closed)
else if(this.localState == SocketState.None && localState == SocketState.Closed)
{
}
else if(this.localState == SocketState.Connecting && localState == SocketState.Connected)
else if(this.localState == SocketState.Connecting && localState == SocketState.Connected)
{
}
else if(this.localState == SocketState.Connecting && localState == SocketState.Closed)
else if(this.localState == SocketState.Connecting && localState == SocketState.Closed)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.Connected && localState == SocketState.ShutdownSend)
else if(this.localState == SocketState.Connected && localState == SocketState.ShutdownSend)
{
}
else if(this.localState == SocketState.Connected && localState == SocketState.ShutdownReceive)
else if(this.localState == SocketState.Connected && localState == SocketState.ShutdownReceived)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.Connected && localState == SocketState.Closed)
else if(this.localState == SocketState.Connected && localState == SocketState.Closed)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.ShutdownSend && localState == SocketState.Closed)
else if(this.localState == SocketState.ShutdownSend && localState == SocketState.Closed)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.ShutdownSend && localState == SocketState.ShutdownReceive)
else if(this.localState == SocketState.ShutdownSend && localState == SocketState.ShutdownReceived)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.ShutdownReceive && localState == SocketState.ShutdownSend)
else if(this.localState == SocketState.ShutdownReceived && localState == SocketState.ShutdownSend)
{
}
else if(this.localState == SocketState.ShutdownReceive && localState == SocketState.Closed)
else if(this.localState == SocketState.ShutdownReceived && localState == SocketState.Closed)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else if(this.localState == SocketState.Closed && localState == SocketState.Closed)
else if(this.localState == SocketState.Closed && localState == SocketState.Closed)
{
if(localEndTimestamp == DateTime.MinValue) localEndTimestamp = DateTime.Now;
}
else
else
{
throw new Exception("Wrong local socket state change: from " + this.localState + " to " + localState);
}
this.localState = localState;
this.localState = localState;
if(this.localState == SocketState.Closed) httpParser.NewMessageArived();
OnUpdate(new TcpEventArgs());
}
468,57 → 468,57
 
protected void SetRemoteState(SocketState remoteState)
{
if(this.remoteState == SocketState.None && remoteState == SocketState.Connecting)
if(this.remoteState == SocketState.None && remoteState == SocketState.Connecting)
{
}
else if(this.remoteState == SocketState.None && remoteState == SocketState.Connected)
else if(this.remoteState == SocketState.None && remoteState == SocketState.Connected)
{
}
else if(this.remoteState == SocketState.None && remoteState == SocketState.Closed)
else if(this.remoteState == SocketState.None && remoteState == SocketState.Closed)
{
}
else if(this.remoteState == SocketState.Connecting && remoteState == SocketState.Connected)
else if(this.remoteState == SocketState.Connecting && remoteState == SocketState.Connected)
{
}
else if(this.remoteState == SocketState.Connecting && remoteState == SocketState.Closed)
else if(this.remoteState == SocketState.Connecting && remoteState == SocketState.Closed)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else if(this.remoteState == SocketState.Connected && remoteState == SocketState.ShutdownSend)
else if(this.remoteState == SocketState.Connected && remoteState == SocketState.ShutdownSend)
{
}
else if(this.remoteState == SocketState.Connected && remoteState == SocketState.ShutdownReceive)
else if(this.remoteState == SocketState.Connected && remoteState == SocketState.ShutdownReceived)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else if(this.remoteState == SocketState.Connected && remoteState == SocketState.Closed)
else if(this.remoteState == SocketState.Connected && remoteState == SocketState.Closed)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else if(this.remoteState == SocketState.ShutdownSend && remoteState == SocketState.Closed)
else if(this.remoteState == SocketState.ShutdownSend && remoteState == SocketState.Closed)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else if(this.remoteState == SocketState.ShutdownSend && remoteState == SocketState.ShutdownReceive)
else if(this.remoteState == SocketState.ShutdownSend && remoteState == SocketState.ShutdownReceived)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else if(this.remoteState == SocketState.ShutdownReceive && remoteState == SocketState.ShutdownSend)
else if(this.remoteState == SocketState.ShutdownReceived && remoteState == SocketState.ShutdownSend)
{
}
else if(this.remoteState == SocketState.ShutdownReceive && remoteState == SocketState.Closed)
else if(this.remoteState == SocketState.ShutdownReceived && remoteState == SocketState.Closed)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else if(this.remoteState == SocketState.Closed && remoteState == SocketState.Closed)
else if(this.remoteState == SocketState.Closed && remoteState == SocketState.Closed)
{
if(remoteEndTimestamp == DateTime.MinValue) remoteEndTimestamp = DateTime.Now;
}
else
else
{
throw new Exception("Wrong remote socket state change: from " + this.remoteState + " to " + remoteState);
}
this.remoteState = remoteState;
this.remoteState = remoteState;
if(this.remoteState == SocketState.Closed) httpParser.NewMessageArived();
OnUpdate(new TcpEventArgs());
}
527,9 → 527,9
 
protected virtual void OnUpdate(TcpEventArgs e)
{
if(Update != null)
if(Update != null)
{
Update(this, e);
Update(this, e);
}
}
 
537,9 → 537,9
 
protected virtual void OnNewHttp(TcpHttpEventArgs e)
{
if(NewHttp != null)
if(NewHttp != null)
{
NewHttp(this, e);
NewHttp(this, e);
}
}
 
547,9 → 547,9
 
protected virtual void OnClose(TcpEventArgs e)
{
if(Close != null)
if(Close != null)
{
Close(this, e);
Close(this, e);
}
}
 
557,9 → 557,9
 
protected virtual void OnLog(TcpLogEventArgs e)
{
if(Log != null)
if(Log != null)
{
Log(this, e);
Log(this, e);
}
}
 
588,7 → 588,7
{
public byte[] buffer = null;
public int length = 0;
public SendCommandType cmdType = SendCommandType.Send;
public SendCommandType cmdType = SendCommandType.Send;
}
 
private static int BUF_SIZE = 2048;
614,12 → 614,12
 
public SocketWorker(IPAddress resendHost, int resendPort, Socket localSocket, TcpConnection tcp)
{
try
try
{
tcp.SendLog(LogLevel.Debug, string.Format("Local socket: {0}:{1} <-> {2}:{3}",
((IPEndPoint)localSocket.LocalEndPoint).Address,
tcp.SendLog(LogLevel.Debug, string.Format("Local socket: {0}:{1} <-> {2}:{3}",
((IPEndPoint)localSocket.LocalEndPoint).Address,
((IPEndPoint)localSocket.LocalEndPoint).Port,
((IPEndPoint)localSocket.RemoteEndPoint).Address,
((IPEndPoint)localSocket.RemoteEndPoint).Address,
((IPEndPoint)localSocket.RemoteEndPoint).Port));
 
this.localSocket = localSocket;
629,13 → 629,13
 
tcp.SetLocalPoint((IPEndPoint)localSocket.RemoteEndPoint);
this.localSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
 
localSendThread = new Thread(new ThreadStart(LocalSendProc));
localSendThread.Name = "SocketWorker.LocalSendProc";
localSendThread.Start();
 
ContinueLocalReceive();
 
if(resendHost == null)
{
remoteSocket = null;
659,10 → 659,10
remoteSocketEvent.Set(); // remote socket ready to send data
tcp.SendLog(LogLevel.Info, "Connected to server " + tcp.RemotePoint.ToString());
 
tcp.SendLog(LogLevel.Debug, string.Format("Remote socket: {0}:{1} <-> {2}:{3}",
((IPEndPoint)remoteSocket.LocalEndPoint).Address,
tcp.SendLog(LogLevel.Debug, string.Format("Remote socket: {0}:{1} <-> {2}:{3}",
((IPEndPoint)remoteSocket.LocalEndPoint).Address,
((IPEndPoint)remoteSocket.LocalEndPoint).Port,
((IPEndPoint)remoteSocket.RemoteEndPoint).Address,
((IPEndPoint)remoteSocket.RemoteEndPoint).Address,
((IPEndPoint)remoteSocket.RemoteEndPoint).Port));
}
}
675,7 → 675,7
 
private void ContinueLocalReceive()
{
try
try
{
localDataBuffer = new byte[BUF_SIZE];
localSocket.BeginReceive(localDataBuffer, 0, BUF_SIZE, SocketFlags.None, receiveLocalMethod, this);
694,7 → 694,7
 
private void ContinueRemoteReceive()
{
try
try
{
remoteDataBuffer = new byte[BUF_SIZE];
remoteSocket.BeginReceive(remoteDataBuffer, 0, BUF_SIZE, SocketFlags.None, receiveRemoteMethod, this);
713,9 → 713,9
 
private void CheckLocalSocket()
{
lock(localSocket)
lock(localSocket)
{
try
try
{
if(localSocketReceiveShutdown && localSocketSendShutdown)
{
732,11 → 732,11
 
private void CheckRemoteSocket()
{
lock(remoteSocket)
lock(remoteSocket)
{
try
try
{
if(remoteSocketReceiveShutdown && remoteSocketSendShutdown)
if(remoteSocketReceiveShutdown && remoteSocketSendShutdown)
{
if(remoteSocket.Connected) remoteSocket.Close();
tcp.SetRemoteState(SocketState.Closed);
751,7 → 751,7
 
private void OnLocalReceived(IAsyncResult asyn)
{
try
try
{
int bytesReceived = 0;
bool reset = false;
766,9 → 766,9
}
catch(SocketException ex)
{
if(ex.ErrorCode == 10054)
if(ex.ErrorCode == 10054)
reset = true;
else
else
throw ex;
}
 
795,7 → 795,7
tcp.SendLog(LogLevel.Info, "Got showdown from local end");
 
localSocket.Shutdown(SocketShutdown.Receive);
tcp.SetLocalState(SocketState.ShutdownReceive);
tcp.SetLocalState(SocketState.ShutdownReceived);
localSocketReceiveShutdown = true;
CheckLocalSocket();
 
833,16 → 833,16
{
try
{
while(true)
while(true)
{
SendCommand cmd;
 
if(localSendQueue.Count == 0)
if(localSendQueue.Count == 0)
{
localSendEvent.WaitOne();
}
 
lock(localSendQueue)
lock(localSendQueue)
{
localSendEvent.Reset();
cmd = (SendCommand)localSendQueue.Dequeue();
895,7 → 895,7
 
private void OnRemoteReceived(IAsyncResult asyn)
{
try
try
{
int bytesReceived = 0;
bool reset = false;
910,9 → 910,9
}
catch(SocketException ex)
{
if(ex.ErrorCode == 10054)
if(ex.ErrorCode == 10054)
reset = true;
else
else
throw ex;
}
 
939,7 → 939,7
tcp.SendLog(LogLevel.Info, "Got showdown from remote end");
 
remoteSocket.Shutdown(SocketShutdown.Receive);
tcp.SetRemoteState(SocketState.ShutdownReceive);
tcp.SetRemoteState(SocketState.ShutdownReceived);
remoteSocketReceiveShutdown = true;
CheckRemoteSocket();
 
975,18 → 975,18
 
private void RemoteSendProc()
{
try
try
{
while(true)
while(true)
{
SendCommand cmd;
 
if(remoteSendQueue.Count == 0)
if(remoteSendQueue.Count == 0)
{
remoteSendEvent.WaitOne();
}
 
lock(remoteSendQueue)
lock(remoteSendQueue)
{
remoteSendEvent.Reset();
cmd = (SendCommand)remoteSendQueue.Dequeue();
1038,15 → 1038,15
{
tcp.SendLog(LogLevel.Important, "Connection canceled");
 
try
try
{
if(localSendThread != null && localSendThread.IsAlive) localSendThread.Abort();
if(remoteSendThread != null && remoteSendThread.IsAlive) remoteSendThread.Abort();
 
// close sockets
try
try
{
if(localSocket != null)
if(localSocket != null)
{
lock(localSocket)
{
1060,7 → 1060,7
}
tcp.SetLocalState(SocketState.Closed);
 
try
try
{
if(remoteSocket != null)
{
1103,14 → 1103,14
 
private static HttpCharType[] charTypes = null;
private static bool[] tokenChars = null;
private static char[] charValues = {
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
private static char[] charValues = {
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\0'
};
 
1158,9 → 1158,9
 
// token table
tokenChars = new bool[256];
for(int i = 0; i < tokenChars.Length; i++)
for(int i = 0; i < tokenChars.Length; i++)
{
tokenChars[i] = !(charTypes[i] == HttpCharType.NonChar
tokenChars[i] = !(charTypes[i] == HttpCharType.NonChar
|| charTypes[i] == HttpCharType.Control || charTypes[i] == HttpCharType.Separator
|| charTypes[i] == HttpCharType.CrLf);
}
1202,7 → 1202,7
 
private bool MoveNext()
{
for(bool moved = false; !moved; )
for(bool moved = false; !moved; )
{
lock(messages)
{
1212,7 → 1212,7
 
if(moved) break;
 
if(!newMessageEvent.WaitOne())
if(!newMessageEvent.WaitOne())
throw new Exception("Cannot get next TCP message");
 
lock(messages)
1233,7 → 1233,7
 
TcpMessage newTcp = null;
 
do
do
{
if(!MoveNext())
{
1273,7 → 1273,7
 
public void SetDirection(TcpMessageDirection direction)
{
do
do
{
if(!MoveNext())
{
1336,7 → 1336,7
{
Thread responseThread = null;
 
try
try
{
requestPos = new ParsePosition(messages, nextMessageEvent);
responsePos = new ParsePosition(messages, null);
1346,10 → 1346,10
responseThread.Start();
 
// find requests
while(!requestPos.IsEnd)
while(!requestPos.IsEnd)
{
HttpMessage http = new HttpMessage();
lock(https)
lock(https)
{
https.Add(http);
requestEvent.Set(); // new request available
1364,7 → 1364,7
ParseHeaders(requestPos, http, true);
SetRequestProperties(http);
http.UpdateHttpMessage();
 
bool fullLength = ParseBody(requestPos, http, true);
if("text" == http.RequestContentType && "xml" == http.RequestContentSubtype)
{
1381,7 → 1381,7
 
responseThread.Join();
}
catch(Exception ex)
catch(Exception ex)
{
Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
if(responseThread != null) responseThread.Abort();
1390,16 → 1390,16
 
private void MatchResponses()
{
try
try
{
IEnumerator httpEnum = https.GetEnumerator();
 
if(!nextMessageEvent.WaitOne()) throw new Exception("Cannot get first message of request");
 
responsePos.SetDirection(requestPos.CurrentMessage.Direction == TcpMessageDirection.Local
responsePos.SetDirection(requestPos.CurrentMessage.Direction == TcpMessageDirection.Local
? TcpMessageDirection.Remote : TcpMessageDirection.Local);
while(!responsePos.IsEnd)
 
while(!responsePos.IsEnd)
{
bool moved;
 
1409,14 → 1409,14
moved = httpEnum.MoveNext();
}
 
if(!moved)
if(!moved)
{
if(!requestEvent.WaitOne())
if(!requestEvent.WaitOne())
throw new Exception("Cannot get next request");
 
lock(https)
{
if(!httpEnum.MoveNext())
if(!httpEnum.MoveNext())
throw new Exception("Tried to find response by no HTTP message available");
}
}
1442,7 → 1442,7
http.UpdateHttpMessage();
}
}
catch(Exception ex)
catch(Exception ex)
{
Console.WriteLine(ex.Message + " (" + ex.GetType().Name + ")\n" + ex.StackTrace);
}
1473,7 → 1473,7
if(limit > 0 && limit < ++len) return null; // length limit
}
 
return res.ToString();
return res.ToString();
}
 
private string GetUntilEoL(ParsePosition pos, int limit)
1487,7 → 1487,7
if(limit > 0 && limit < ++len) return null; // length limit
}
 
return res.ToString();
return res.ToString();
}
 
private void ExpectSpace(ParsePosition pos)
1510,7 → 1510,7
 
private void SkipEmptyLines(ParsePosition pos)
{
while(pos.CurrentOctet() == 13)
while(pos.CurrentOctet() == 13)
ExpectCRLF(pos);
}
 
1532,13 → 1532,13
 
// EoL or version
byte b = pos.CurrentOctet();
if(b == 13)
if(b == 13)
{
if(pos.IsEnd || pos.NextOctet() != 10)
if(pos.IsEnd || pos.NextOctet() != 10)
{
throw new HttpParseException("Linefeed expected");
}
else
else
{
if(!pos.IsEnd) ExpectCRLF(pos);
http.RequestVersion = HttpVersion.V0_9;
1545,7 → 1545,7
return;
}
}
else if(b != 32)
else if(b != 32)
{
throw new HttpParseException("HTTP version expected");
}
1556,15 → 1556,15
if(pos.IsEnd || versionStr == null || versionStr.Length == 0)
throw new HttpParseException("HTTP version expected");
 
if(versionStr == "HTTP/1.0")
if(versionStr == "HTTP/1.0")
{
http.RequestVersion = HttpVersion.V1_0;
}
else if(versionStr == "HTTP/1.1")
else if(versionStr == "HTTP/1.1")
{
http.RequestVersion = HttpVersion.V1_1;
}
else
else
{
throw new HttpParseException("Unknown HTTP version: " + versionStr);
}
1576,18 → 1576,18
{
if(pos.IsEnd) return; // end of TCP messages
 
while(true)
while(true)
{
if(pos.IsEnd)
throw new HttpParseException("Unexpected end of message");
 
if(pos.CurrentOctet() == 13)
if(pos.CurrentOctet() == 13)
{
if(pos.IsEnd || pos.NextOctet() != 10)
if(pos.IsEnd || pos.NextOctet() != 10)
{
throw new HttpParseException("Linefeed expected");
}
else
else
{
pos.NextOctet(); // end of header, move to body
return;
1628,21 → 1628,21
HeaderValueState state = HeaderValueState.Space;
StringBuilder buf = new StringBuilder();
 
for(int i = 0, l = s.Length; i < l; i++)
for(int i = 0, l = s.Length; i < l; i++)
{
char c = s[i];
switch(state)
switch(state)
{
case HeaderValueState.Space:
if(c != ' ' && c != '\t')
{
if(c == '"')
if(c == '"')
{
if(buf.Length > 0) buf.Append(' ');
buf.Append(c);
state = HeaderValueState.Quoted;
}
else
else
{
if(buf.Length > 0) buf.Append(' ');
buf.Append(c);
1652,16 → 1652,16
break;
 
case HeaderValueState.Token:
if(c == ' ' || c == '\t')
if(c == ' ' || c == '\t')
{
state = HeaderValueState.Space;
}
else if(c == '"')
else if(c == '"')
{
buf.Append(c);
state = HeaderValueState.Quoted;
}
else
else
{
buf.Append(c);
}
1668,18 → 1668,18
break;
 
case HeaderValueState.Quoted:
if(c == '"')
if(c == '"')
{
buf.Append(c);
i++;
if(i < l)
{
{
c = s[i];
if(c == ' ' || c == '\t')
if(c == ' ' || c == '\t')
{
state = HeaderValueState.Space;
}
else if(c == '"')
else if(c == '"')
{
buf.Append(c);
state = HeaderValueState.Quoted;
1691,7 → 1691,7
}
}
}
else
else
{
buf.Append(c);
}
1704,15 → 1704,15
 
private HttpEncoding ParseEncoding(string encoding)
{
if(encoding == null || encoding == "identity")
if(encoding == null || encoding == "identity")
return HttpEncoding.Identify;
else if(encoding == "gzip")
else if(encoding == "gzip")
return HttpEncoding.Gzip;
else if(encoding == "compress")
else if(encoding == "compress")
return HttpEncoding.Compress;
else if(encoding == "deflate")
else if(encoding == "deflate")
return HttpEncoding.Deflate;
else
else
return HttpEncoding.Unknown;
}
 
1720,7 → 1720,7
{
// length
string contentLength = (string)http.RequestHeadersHash["Content-Length"];
if(contentLength != null)
if(contentLength != null)
{
http.RequestLength = int.Parse(contentLength);
}
1730,10 → 1730,10
 
// type & charset
string contentType = (string)http.RequestHeadersHash["Content-Type"];
if(contentType != null)
if(contentType != null)
{
Match match = Regex.Match(contentType, @"^\s*(\S+)/(\S+)\s*($|;\s*(charset=""?(\S+)""?)?)");
if(match.Success)
if(match.Success)
{
http.RequestContentType = match.Groups[1].Captures[0].Value;
http.RequestContentSubtype = match.Groups[2].Captures[0].Value;
1743,7 → 1743,7
 
// soap action
string soapAction = (string)http.RequestHeadersHash["soapaction"];
if(soapAction != null)
if(soapAction != null)
{
http.SoapAction = soapAction.Trim('"');
}
1765,7 → 1765,7
 
for(byte b = pos.CurrentOctet(); !pos.IsEnd; b = pos.NextOctet())
{
if(len >= bin.Length)
if(len >= bin.Length)
{
byte[] newBin = new byte[bin.Length*2];
Array.Copy(bin, newBin, len);
1780,26 → 1780,26
}
 
string text = null;
if(encoding == HttpEncoding.Identify && contentType == "text")
if(encoding == HttpEncoding.Identify && contentType == "text")
{
try
try
{
Encoding enc = Encoding.GetEncoding(charset == null ? (contentSubtype == "xml" ? "UTF-8" : "ASCII") : charset);
text = enc.GetString(bin, 0, len);
}
catch(NotSupportedException)
catch(NotSupportedException)
{
Console.WriteLine("Unsupported encoding: " + charset);
}
}
 
if(request)
if(request)
{
http.RequestLength = len;
http.RequestBody = bin;
http.RequestText = text;
}
else
else
{
http.ResponseLength = len;
http.ResponseBody = bin;
1816,15 → 1816,15
if(pos.IsEnd || versionStr == null || versionStr.Length == 0)
throw new HttpParseException("HTTP version expected");
 
if(versionStr == "HTTP/1.0")
if(versionStr == "HTTP/1.0")
{
http.ResponseVersion = HttpVersion.V1_0;
}
else if(versionStr == "HTTP/1.1")
else if(versionStr == "HTTP/1.1")
{
http.ResponseVersion = HttpVersion.V1_1;
}
else
else
{
throw new HttpParseException("Unknown HTTP version: " + versionStr);
}
1835,13 → 1835,13
if(code == null || code.Length != 3)
throw new HttpParseException("Status code expected");
 
try
try
{
int c = int.Parse(code);
if(c < 100 || c >= 1000) throw new HttpParseException("Status code expected");
http.ResponseStatusCode = c;
}
catch(FormatException)
catch(FormatException)
{
throw new HttpParseException("Status code expected");
}
1849,7 → 1849,7
 
// status message
http.ResponseStatusMessage = GetUntilEoL(pos, 0);
 
if(pos.IsEnd)
throw new HttpParseException("Unexpected end of message");
 
1860,7 → 1860,7
{
// length
HttpHeader contentLength = (HttpHeader)http.ResponseHeadersHash["Content-Length"];
if(contentLength != null)
if(contentLength != null)
{
http.ResponseLength = int.Parse(contentLength.Values[0]);
}
1871,14 → 1871,14
 
// type & charset
HttpHeader contentType = (HttpHeader)http.ResponseHeadersHash["Content-Type"];
if(contentType != null)
if(contentType != null)
{
Match match = Regex.Match(contentType.Values[0], @"^\s*(\S+)/(\S+)\s*($|;\s*(charset=""?(\S+)""?)?)");
if(match.Success)
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)
if(match.Groups.Count >= 6 && match.Groups[5].Captures.Count > 0)
http.ResponseCharset = match.Groups[5].Captures[0].Value.Trim('"');
}
}
1916,7 → 1916,7
{
headerValues = new string[1];
}
else
else
{
string[] newValues = new string[headerValues.Length + 1];
Array.Copy(headerValues, 0, newValues, 0, headerValues.Length);
2153,7 → 2153,7
 
public override string ToString() // FIXME delete the method
{
return (soapAction != null ? soapAction
return (soapAction != null ? soapAction
: (requestMethod == null ? "" : requestMethod) + " " + (requestUri == null ? "" : requestUri));
}
 
2161,9 → 2161,9
 
protected virtual void OnUpdate(TcpEventArgs e)
{
if(Update != null)
if(Update != null)
{
Update(this, e);
Update(this, e);
}
}
 
2210,7 → 2210,7
 
internal XmlMessage(string text)
{
try
try
{
this.xml = new XmlDocument();
this.xml.LoadXml(text);
2242,7 → 2242,7
 
public byte[] Bytes
{
get
get
{
return bytes;
}
2283,10 → 2283,10
{
if(newBytes == null) return this;
 
lock(this)
lock(this)
{
// grow array
if(this.length + length > bytes.Length)
if(this.length + length > bytes.Length)
{
int newLength = bytes.Length;
while(this.length + length > newLength) newLength *= 2;