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; |