/// <summary> /// Sets up the socket reader to read the Content of the HTTP request /// </summary> private void SetUpReadingContent() { ContentLength = long.Parse(WebConnection.Headers["CONTENT-LENGTH"]); if (ContentLength <= WebServer.MaxInMemoryContentSize) Content = new WebConnectionContent.InMemory(ContentLength); else if (ContentLength <= WebServer.MaxContentSize) Content = new WebConnectionContent.OnDisk(); else { Close(WebResults.From(Status._413_Request_Entity_Too_Large, "Too much data, max size: " + WebServer.MaxContentSize.ToString())); return; } if (BufferBytesRead >= ContentLength) { byte[] toCopy = new byte[ContentLength]; Array.Copy(Buffer, 0, toCopy, 0, toCopy.Length); Content.TakeBytes(toCopy); if (BufferBytesRead == ContentLength) BufferBytesRead = 0; else { byte[] oldBuffer = Buffer; Buffer = new byte[oldBuffer.Length]; Array.Copy(oldBuffer, ContentLength, Buffer, 0, BufferBytesRead - ContentLength); //System.Buffer.BlockCopy(Buffer, Convert.ToInt32(ContentLength), Buffer, 0, Convert.ToInt32(BufferBytesRead - ContentLength)); BufferBytesRead = Convert.ToInt32(Convert.ToInt64(BufferBytesRead) - ContentLength); } WebConnectionIOState = WebConnectionIOState.PerformingRequest; PerformRequest(); return; } else if (0 == BufferBytesRead) { ReadStartTime = DateTime.UtcNow; WebConnectionIOState = WebConnectionIOState.ReadingContent; } else // Buffer has less bytes then what's needed { byte[] toCopy = new byte[BufferBytesRead]; Array.Copy(Buffer, 0, toCopy, 0, BufferBytesRead); Content.TakeBytes(toCopy); BufferBytesRead = 0; ReadStartTime = DateTime.UtcNow; WebConnectionIOState = WebConnectionIOState.ReadingContent; } ReadContent(); }
/// <summary> /// Sends the stream to the browser. This should be called on the same thread that owns this web connection /// </summary> /// <param name="stream"></param> private void SendToBrowserInt(Stream stream) { byte[] buffer = new byte[60000]; DateTime sendEnd = DateTime.UtcNow.AddMinutes(5); using (stream) try { if (Socket.Connected) { int bytesRead; do { bytesRead = stream.Read(buffer, 0, buffer.Length); int bytesSent = 0; if (bytesRead > 0) do { if (DateTime.UtcNow > sendEnd) { log.Warn("Sending timed out"); Close(); return; } bytesSent += Socket.Send(buffer, bytesSent, bytesRead - bytesSent, SocketFlags.None); } while (bytesSent < bytesRead); } while (bytesRead > 0); } else { log.Debug("Connection Dropped...."); return; } if (KeepAlive) { ReadStartTime = DateTime.UtcNow; //WebConnectionIOState = WebConnectionIOState.ReadingHeader; //Start(); // I currently syspect that going into Async mode between requests is causing weird delays and slowness // If data is available, immediately start reading the header, else, end the thread and use a callback to restart it if (Socket.Available > 0 || BufferBytesRead > 0) { WebConnectionIOState = WebConnectionIOState.ReadingHeader; // Another thread is used because this method needs to be non-blocking Start(); } else { WebConnectionIOState = WebConnectionIOState.Idle; // Set the timeout to the total header timeout Socket.ReceiveTimeout = Convert.ToInt32(WebServer.HeaderTimeout.TotalMilliseconds); try { Socket.BeginReceive( Buffer, 0, Buffer.Length, SocketFlags.None, StartNewConnection, null); } // If there's an exception, it means the socket is disconnected. catch { WebConnectionIOState = WebConnectionIOState.Disconnected; } } } else Close(); } catch (Exception e) { log.Error("Error Occurred", e); Close(); } finally { stream.Close(); if (null != Content) { Content.Dispose(); Content = null; } } }