private void OnReceive(IAsyncResult ar)
{
try
{
int bytesRead = _stream.EndRead(ar);
if (bytesRead == 0)
{
Disconnect(SocketError.ConnectionReset);
return;
}
_bytesLeft += bytesRead;
if (_bytesLeft > _buffer.Length)
{
#if DEBUG
throw new BadRequestException("Too large HTTP header: " + Encoding.UTF8.GetString(_buffer, 0, bytesRead));
#else
throw new BadRequestException("Too large HTTP header: " + _bytesLeft);
#endif
}
#if DEBUG
#pragma warning disable 219
string temp = Encoding.ASCII.GetString(_buffer, 0, _bytesLeft);
_log.Write(this, LogPrio.Trace, "Received: " + temp);
#pragma warning restore 219
#endif
int offset = _parser.ParseMessage(_buffer, 0, _bytesLeft);
Check100Continue();
// try again to see if we can parse another message (check parser to see if it is looking for a new message)
int oldOffset = offset;
while (_parser.CurrentState == HttpRequestParser.State.FirstLine && offset != 0 && _bytesLeft - offset > 0)
{
#if DEBUG
temp = Encoding.ASCII.GetString(_buffer, offset, _bytesLeft - offset);
_log.Write(this, LogPrio.Trace, "Processing: " + temp);
#endif
offset = _parser.ParseMessage(_buffer, offset, _bytesLeft - offset);
Check100Continue();
}
// need to be able to move prev bytes, so restore offset.
if (offset == 0)
offset = oldOffset;
// copy unused bytes to the beginning of the array
if (offset > 0 && _bytesLeft != offset)
{
int bytesToMove = _bytesLeft - offset;
for (int i = 0; i < bytesToMove; ++i)
_buffer[i] = _buffer[i + offset];
}
_bytesLeft -= offset;
if (_stream.CanRead)
_stream.BeginRead(_buffer, _bytesLeft, _buffer.Length - _bytesLeft, OnReceive, null);
}
catch (BadRequestException err)
{
_log.Write(this, LogPrio.Warning, "Bad request, responding with it. Error: " + err);
try
{
Respond(HttpHelper.HTTP10, HttpStatusCode.BadRequest, err.Message);
}
catch(Exception err2)
{
_log.Write(this, LogPrio.Fatal, "Failed to reply to a bad request. " + err2);
}
Disconnect(SocketError.NoRecovery);
}
catch (IOException err)
{
_log.Write(this, LogPrio.Debug, "Failed to end receive: " + err.Message);
if (err.InnerException is SocketException)
Disconnect((SocketError) ((SocketException) err.InnerException).ErrorCode);
else
Disconnect(SocketError.ConnectionReset);
}
catch (ObjectDisposedException err)
{
_log.Write(this, LogPrio.Debug, "Failed to end receive : " + err.Message);
Disconnect(SocketError.NotSocket);
}
}