public void Work()
{
var handler = server.RequestHandler;
//using (var stream = new NetworkStream(client, false))
//using (var reader = new StreamReader(stream))
{
var httpRequest = new HttpRequestHeader(this, client);
while (IsClientConnected)
{
try
{
var httpString = httpRequest.Read();
if (string.IsNullOrEmpty(httpString)) break;
NameValueCollection headers = null;
string method = null;
string path = null;
string protocol = null;
string version = null;
bool? hasPostData = null;
using (var reader = new StringReader(httpString))
{
var firstLine = reader.ReadLine();
if (string.IsNullOrEmpty(firstLine))
{
server.LogMessage("HTTP ERROR: Empty request");
SendInvalidRequest(null);
//continue;
break;
}
var m = Regex.Match(firstLine, @"^([a-zA-Z]+)\s+(\S+)\s+([A-Z]+)/(\d.\d)$");
if (!m.Success)
{
server.LogMessage("HTTP FIXME: {0}", firstLine);
SendInvalidRequest(null);
break;
}
method = m.Groups[1].Value.ToUpperInvariant();
path = m.Groups[2].Value;
protocol = m.Groups[3].Value;
version = m.Groups[4].Value;
hasPostData = server.HasPostData(method);
if (hasPostData == null)
{
server.LogMessage("HTTP ERROR: Unknown method {0}", method);
SendInvalidRequest("Unknown HTTP method", protocol, version);
break;
}
if (!server.IsValidProtocol(protocol, version))
{
SendInvalidRequest("Unknown HTTP version", protocol, version);
break;
}
headers = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
string header;
while (!string.IsNullOrEmpty(header = reader.ReadLine()))
{
var parts = header.Split(new[] { ':' }, 2);
if (parts.Length != 2) continue;
var headerName = parts[0].Trim();
var headerValue = parts[1].TrimStart();
if (string.IsNullOrEmpty(headerName) || string.IsNullOrEmpty(headerValue)) continue;
headers.Add(headerName, HttpUtility.UrlDecode(headerValue));
}
}
byte[] postData = null;
var contentLengthHdr = headers["Content-Length"];
int contentLength = 0;
if (!string.IsNullOrEmpty(contentLengthHdr) && int.TryParse(contentLengthHdr, NumberStyles.None, null, out contentLength) && contentLength > 0)
{
if (!hasPostData.Value)
{
server.LogMessage("{0} request cannot contain data", method);
SendInvalidRequest(method + " request cannot contain data", protocol, version);
break;
}
postData = new byte[contentLength];
//stream.Read(postData, 0, contentLength);
var offset = 0;
while (offset < contentLength)
{
var read = client.Receive(postData, offset, contentLength - offset, SocketFlags.None);
offset += read;
}
}
var request = new HttpRequest((IPEndPoint)client.RemoteEndPoint, method, path, protocol, version, headers, postData, this);
HttpResponse response;
try
{
response = handler(request);
}
catch (Exception ex)
{
server.LogError(ex);
response = new ServerErrorResponse(ex);
}
SendResponse(response);
if (response.Code >= 500) break;
if (string.Equals(headers["Connection"], "close", StringComparison.OrdinalIgnoreCase)) break;
if (server.IsStopping) break;
}
catch (Exception ex)
{
server.LogMessage("HTTP ERROR: {0}", ex.ToString());
break;
}
}
//Server.Player.Logger.LogMessage("=== Connection {0} to be terminated ===", Thread.CurrentThread.ManagedThreadId);
Close();
}
}