more changes on http server low level

This commit is contained in:
UbitUmarov
2020-04-08 14:35:31 +01:00
parent f0f067d05c
commit f976d10de2
6 changed files with 175 additions and 126 deletions

View File

@@ -20,7 +20,7 @@ namespace OSHttpServer
/// </remarks>
public class HttpClientContext : IHttpClientContext, IDisposable
{
const int MAXPIPEREQUESTS = 5;
const int MAXREQUESTS = 20;
const int MAXKEEPALIVE = 60000;
static private int basecontextID;
@@ -36,22 +36,20 @@ namespace OSHttpServer
public bool Available = true;
public bool StreamPassedOff = false;
public int MonitorStartMS = 0;
public int MonitorKeepaliveMS = 0;
public int LastActivityTimeMS = 0;
public int MonitorKeepaliveStartMS = 0;
public bool TriggerKeepalive = false;
public int TimeoutFirstLine = 70000; // 70 seconds
public int TimeoutRequestReceived = 180000; // 180 seconds
public int TimeoutFirstLine = 10000; // 10 seconds
public int TimeoutRequestReceived = 30000; // 30 seconds
// The difference between this and request received is on POST more time is needed before we get the full request.
public int TimeoutFullRequestProcessed = 600000; // 10 minutes
public int TimeoutMaxIdle = 180000; // 3 minutes
public int m_TimeoutKeepAlive = MAXKEEPALIVE; // 400 seconds before keepalive timeout
// public int TimeoutKeepAlive = 120000; // 400 seconds before keepalive timeout
public int m_maxPipeRequests = MAXPIPEREQUESTS;
public int m_maxRequests = MAXREQUESTS;
public bool FirstRequestLineReceived;
public bool FullRequestReceived;
public bool FullRequestProcessed;
private bool isSendingResponse = false;
@@ -68,15 +66,15 @@ namespace OSHttpServer
}
}
public int MaxPipeRequests
public int MaxRequests
{
get { return m_maxPipeRequests; }
get { return m_maxRequests; }
set
{
if(value <= 1)
m_maxPipeRequests = 1;
m_maxRequests = 1;
else
m_maxPipeRequests = value > MAXPIPEREQUESTS ? MAXPIPEREQUESTS : value;
m_maxRequests = value > MAXREQUESTS ? MAXREQUESTS : value;
}
}
@@ -118,7 +116,7 @@ namespace OSHttpServer
m_parser.BodyBytesReceived += OnBodyBytesReceived;
m_currentRequest = new HttpRequest(this);
IsSecured = secured;
_stream = stream;
m_stream = stream;
m_sock = sock;
m_bufferSize = 8196;
@@ -128,7 +126,7 @@ namespace OSHttpServer
SSLCommonName = "";
if (secured)
{
SslStream _ssl = (SslStream)_stream;
SslStream _ssl = (SslStream)m_stream;
X509Certificate _cert1 = _ssl.RemoteCertificate;
if (_cert1 != null)
{
@@ -150,7 +148,7 @@ namespace OSHttpServer
if (contextID < 0)
return false;
if (Stream == null || m_sock == null || !m_sock.Connected)
if (m_stream == null || m_sock == null || !m_sock.Connected)
return false;
return true;
@@ -191,9 +189,11 @@ namespace OSHttpServer
m_currentRequest.UriPath = e.UriPath;
m_currentRequest.AddHeader("remote_addr", RemoteAddress);
m_currentRequest.AddHeader("remote_port", RemotePort);
FirstRequestLineReceived = true;
TriggerKeepalive = false;
MonitorKeepaliveMS = 0;
MonitorKeepaliveStartMS = 0;
LastActivityTimeMS = ContextTimeoutManager.EnvironmentTickCount();
}
/// <summary>
@@ -218,10 +218,10 @@ namespace OSHttpServer
if (StreamPassedOff)
return;
if (Stream != null)
if (m_stream != null)
{
Stream.Close();
Stream = null;
m_stream.Close();
m_stream = null;
m_sock = null;
}
@@ -233,10 +233,9 @@ namespace OSHttpServer
FirstRequestLineReceived = false;
FullRequestReceived = false;
FullRequestProcessed = false;
MonitorStartMS = 0;
LastActivityTimeMS = 0;
StopMonitoring = true;
MonitorKeepaliveMS = 0;
MonitorKeepaliveStartMS = 0;
TriggerKeepalive = false;
isSendingResponse = false;
@@ -283,15 +282,15 @@ namespace OSHttpServer
}
}
private Stream _stream;
private Stream m_stream;
/// <summary>
/// Gets or sets the network stream.
/// </summary>
internal Stream Stream
{
get { return _stream; }
set { _stream = value; }
get { return m_stream; }
set { m_stream = value; }
}
/// <summary>
@@ -315,12 +314,12 @@ namespace OSHttpServer
{
try
{
if (Stream != null)
if (m_stream != null)
{
if (error == SocketError.Success)
Stream.Flush();
Stream.Close();
Stream = null;
m_stream.Flush();
m_stream.Close();
m_stream = null;
}
m_sock = null;
}
@@ -339,11 +338,11 @@ namespace OSHttpServer
try
{
int bytesRead = 0;
if (Stream == null)
if (m_stream == null)
return;
try
{
bytesRead = Stream.EndRead(ar);
bytesRead = m_stream.EndRead(ar);
}
catch (NullReferenceException)
{
@@ -357,7 +356,7 @@ namespace OSHttpServer
return;
}
if(m_maxPipeRequests <= 0)
if(m_maxRequests <= 0)
return;
m_ReceiveBytesLeft += bytesRead;
@@ -367,7 +366,7 @@ namespace OSHttpServer
}
int offset = m_parser.Parse(m_ReceiveBuffer, 0, m_ReceiveBytesLeft);
if (Stream == null)
if (m_stream == null)
return; // "Connection: Close" in effect.
// try again to see if we can parse another message (check parser to see if it is looking for a new message)
@@ -378,7 +377,7 @@ namespace OSHttpServer
{
nextOffset = m_parser.Parse(m_ReceiveBuffer, offset, nextBytesleft);
if (Stream == null)
if (m_stream == null)
return; // "Connection: Close" in effect.
if (nextOffset == 0)
@@ -393,7 +392,7 @@ namespace OSHttpServer
Buffer.BlockCopy(m_ReceiveBuffer, offset, m_ReceiveBuffer, 0, m_ReceiveBytesLeft - offset);
m_ReceiveBytesLeft -= offset;
if (Stream != null && Stream.CanRead)
if (m_stream != null && m_stream.CanRead)
{
if (!StreamPassedOff)
Stream.BeginRead(m_ReceiveBuffer, m_ReceiveBytesLeft, m_ReceiveBuffer.Length - m_ReceiveBytesLeft, OnReceive, null);
@@ -449,10 +448,10 @@ namespace OSHttpServer
{
while(true)
{
if (_stream == null || !_stream.CanRead)
if (m_stream == null || !m_stream.CanRead)
return;
int bytesRead = await _stream.ReadAsync(m_ReceiveBuffer, m_ReceiveBytesLeft, m_ReceiveBuffer.Length - m_ReceiveBytesLeft).ConfigureAwait(false);
int bytesRead = await m_stream.ReadAsync(m_ReceiveBuffer, m_ReceiveBytesLeft, m_ReceiveBuffer.Length - m_ReceiveBytesLeft).ConfigureAwait(false);
if (bytesRead == 0)
{
@@ -465,7 +464,7 @@ namespace OSHttpServer
throw new BadRequestException("HTTP header Too large: " + m_ReceiveBytesLeft);
int offset = m_parser.Parse(m_ReceiveBuffer, 0, m_ReceiveBytesLeft);
if (Stream == null)
if (m_stream == null)
return; // "Connection: Close" in effect.
// try again to see if we can parse another message (check parser to see if it is looking for a new message)
@@ -476,7 +475,7 @@ namespace OSHttpServer
{
nextOffset = m_parser.Parse(m_ReceiveBuffer, offset, nextBytesleft);
if (Stream == null)
if (m_stream == null)
return; // "Connection: Close" in effect.
if (nextOffset == 0)
@@ -536,13 +535,14 @@ namespace OSHttpServer
private void OnRequestCompleted(object source, EventArgs args)
{
TriggerKeepalive = false;
MonitorKeepaliveMS = 0;
MonitorKeepaliveStartMS = 0;
FullRequestReceived = true;
LastActivityTimeMS = ContextTimeoutManager.EnvironmentTickCount();
if (m_maxPipeRequests == 0)
if (m_maxRequests == 0)
return;
if(--m_maxPipeRequests == 0)
if(--m_maxRequests == 0)
m_currentRequest.Connection = ConnectionType.Close;
// load cookies if they exist
@@ -574,13 +574,9 @@ namespace OSHttpServer
}
}
public void ReqResponseAboutToSend(uint requestID)
{
isSendingResponse = true;
}
public void StartSendResponse(HttpResponse response)
{
LastActivityTimeMS = ContextTimeoutManager.EnvironmentTickCount();
isSendingResponse = true;
m_currentResponse = response;
ContextTimeoutManager.EnqueueSend(this, response.Priority);
@@ -595,19 +591,19 @@ namespace OSHttpServer
if(!CanSend())
return false;
m_currentResponse?.SendNextAsync(bytesLimit);
return false;
}
public void ContinueSendResponse()
public void ContinueSendResponse(bool notThrottled)
{
if(m_currentResponse == null)
return;
ContextTimeoutManager.EnqueueSend(this, m_currentResponse.Priority);
ContextTimeoutManager.EnqueueSend(this, m_currentResponse.Priority, notThrottled);
}
public void ReqResponseSent(uint requestID, ConnectionType ctype)
public void EndSendResponse(uint requestID, ConnectionType ctype)
{
isSendingResponse = false;
m_currentResponse?.Clear();
@@ -626,6 +622,7 @@ namespace OSHttpServer
Disconnect(SocketError.Success);
else
{
LastActivityTimeMS = ContextTimeoutManager.EnvironmentTickCount();
lock (requestsInServiceIDs)
{
if (requestsInServiceIDs.Count == 0)
@@ -645,22 +642,23 @@ namespace OSHttpServer
/// <exception cref="ArgumentException">If <paramref name="httpVersion"/> is invalid.</exception>
public void Respond(string httpVersion, HttpStatusCode statusCode, string reason, string body, string contentType)
{
LastActivityTimeMS = ContextTimeoutManager.EnvironmentTickCount();
if (string.IsNullOrEmpty(contentType))
contentType = "text/html";
if (string.IsNullOrEmpty(reason))
reason = statusCode.ToString();
string response = string.IsNullOrEmpty(body)
? httpVersion + " " + (int)statusCode + " " + reason + "\r\n\r\n"
: string.Format("{0} {1} {2}\r\nContent-Type: {5}\r\nContent-Length: {3}\r\n\r\n{4}",
byte[] buffer;
if(string.IsNullOrEmpty(body))
buffer = Encoding.ASCII.GetBytes(httpVersion + " " + (int)statusCode + " " + reason ?? statusCode.ToString() + "\r\n\r\n");
else
buffer = Encoding.UTF8.GetBytes(
string.Format("{0} {1} {2}\r\nContent-Type: {5}\r\nContent-Length: {3}\r\n\r\n{4}",
httpVersion, (int)statusCode, reason ?? statusCode.ToString(),
body.Length, body, contentType);
byte[] buffer = Encoding.ASCII.GetBytes(response);
body.Length, body, contentType));
Send(buffer);
if (m_currentRequest.Connection == ConnectionType.Close)
FullRequestProcessed = true;
}
/// <summary>
@@ -671,6 +669,7 @@ namespace OSHttpServer
/// <param name="reason">reason for the status code.</param>
public void Respond(string httpVersion, HttpStatusCode statusCode, string reason)
{
Respond(httpVersion, statusCode, reason, null, null);
}
@@ -699,7 +698,7 @@ namespace OSHttpServer
public bool Send(byte[] buffer, int offset, int size)
{
if (Stream == null || m_sock == null || !m_sock.Connected)
if (m_stream == null || m_sock == null || !m_sock.Connected)
return false;
if (offset + size > buffer.Length)
@@ -710,14 +709,14 @@ namespace OSHttpServer
{
try
{
Stream.Write(buffer, offset, size);
m_stream.Write(buffer, offset, size);
}
catch
{
ok = false;
}
if (!ok && Stream != null)
if (!ok && m_stream != null)
Disconnect(SocketError.NoRecovery);
return ok;
}
@@ -725,7 +724,7 @@ namespace OSHttpServer
public async Task<bool> SendAsync(byte[] buffer, int offset, int size)
{
if (Stream == null || m_sock == null || !m_sock.Connected)
if (m_stream == null || m_sock == null || !m_sock.Connected)
return false;
if (offset + size > buffer.Length)
@@ -735,7 +734,7 @@ namespace OSHttpServer
ContextTimeoutManager.ContextEnterActiveSend();
try
{
await Stream.WriteAsync(buffer, offset, size).ConfigureAwait(false);
await m_stream.WriteAsync(buffer, offset, size).ConfigureAwait(false);
}
catch
{
@@ -744,7 +743,7 @@ namespace OSHttpServer
ContextTimeoutManager.ContextLeaveActiveSend();
if (!ok && Stream != null)
if (!ok && m_stream != null)
Disconnect(SocketError.NoRecovery);
return ok;
}
@@ -770,7 +769,7 @@ namespace OSHttpServer
m_parser.BodyBytesReceived -= OnBodyBytesReceived;
m_parser.Clear();
return new HTTPNetworkContext() { Socket = m_sock, Stream = _stream as NetworkStream };
return new HTTPNetworkContext() { Socket = m_sock, Stream = m_stream as NetworkStream };
}
public void Dispose()