public bool Parse(Socket socket, out RouteMatch? match, out RouteHandler route)
{
positionInTmp = 0;
Pipeline = false;
var methodEnd = ReadUntil(socket, Space, 0);
if (methodEnd == -1)
{
match = null;
route = null;
if (!socket.Connected)
{
offsetInOutput = 0;
return false;
}
else if (positionInTmp == 0)
{
if (offsetInOutput != 0)
{
socket.Send(OutputTemp, offsetInOutput, SocketFlags.None);
offsetInOutput = 0;
socket.Close();
return false;
}
else return ReturnError(socket, 408);
}
else return ReturnError(socket, 505);
}
HttpMethod = ReadMethod(methodEnd, InputTemp);
var rowEnd = ReadUntil(socket, LF, methodEnd + 1);
if (rowEnd == -1 || rowEnd < 12)
{
match = null;
route = null;
return ReturnError(socket, 505);
}
RequestHeadersLength = 0;
ResponseHeadersLength = 0;
HttpProtocolVersion = ReadProtocol(rowEnd - 2);
if (HttpProtocolVersion == null)
{
match = null;
route = null;
ReturnError(socket, 505, "Only HTTP/1.1 and HTTP/1.0 supported (partially)", false);
return false;
}
match = ReadUrl(rowEnd, out route);
if (route == null)
{
var unknownRoute = "Unknown route " + RawUrl + " on method " + HttpMethod;
ReturnError(socket, 404, unknownRoute, false);
return false;
}
ResponseStatus = HttpStatusCode.OK;
ResponseLength = null;
ResponseContentType = null;
TemplateMatch = null;
ResponseIsJson = false;
ContentTypeResponseIndex = -1;
do
{
var start = rowEnd + 1;
rowEnd = ReadUntil(socket, CR, start);
if (rowEnd == start) break;
else if (rowEnd == -1) return ReturnError(socket, 414);
else
{
int i = start;
for (; i < rowEnd; i++)
if (InputTemp[i] == ':')
break;
if (i == rowEnd) return ReturnError(socket, 414);
var nameBuf = TmpCharBuf;
for (int x = start; x < i; x++)
nameBuf[x - start] = Lower[InputTemp[x]];
var name = KeyCache.Get(nameBuf, i - start);
if (InputTemp[i + 1] == 32) i++;
for (int x = i + 1; x < rowEnd; x++)
nameBuf[x - i - 1] = (char)InputTemp[x];
var value = ValueCache.Get(nameBuf, rowEnd - i - 1);
if (RequestHeadersLength == RequestHeaders.Length)
{
var newHeaders = new HeaderPair[RequestHeaders.Length * 2];
Array.Copy(RequestHeaders, newHeaders, RequestHeaders.Length);
RequestHeaders = newHeaders;
}
RequestHeaders[RequestHeadersLength++] = new HeaderPair(name, value);
}
rowEnd++;
} while (positionInTmp <= InputTemp.Length);
rowEnd += 2;
if (HttpMethod == "POST" || HttpMethod == "PUT")
{
int len = 0;
var ct = GetRequestHeader("content-length");
if (ct != null)
{
if (!int.TryParse(ct, out len)) return ReturnError(socket, 411);
if (len > Limit) return ReturnError(socket, 413);
}
else return ReturnError(socket, 411);
InputStream.Reset();
var size = totalBytes - rowEnd;
InputStream.Write(InputTemp, rowEnd, size);
len -= size;
var oldTimeout = socket.ReceiveTimeout;
socket.ReceiveTimeout = 10000;
while (len > 0)
{
size = socket.Receive(InputTemp, Math.Min(len, InputTemp.Length), SocketFlags.None);
if (size < 1) return ReturnError(socket, 408);
InputStream.Write(InputTemp, 0, size);
len -= size;
}
socket.ReceiveTimeout = oldTimeout;
InputStream.Position = 0;
rowEnd = totalBytes;
totalBytes = 0;
}
else
{
Pipeline = rowEnd < totalBytes;
if (Pipeline)
{
Buffer.BlockCopy(InputTemp, rowEnd, InputTemp, 0, totalBytes - rowEnd);
totalBytes -= rowEnd;
}
else
{
totalBytes = 0;
}
}
return true;
}