/// <summary> /// Tries to parse a chunk size line for the message /// </summary> /// <returns></returns> private bool TryAndParseChunkSizeLine(ref HttpMessage message, EventHandler <HttpMessageProgressEventArgs> onProgress, object stateObject) { // try and parse a token from the data HttpByteParserToken token = _parser.GetNextToken(); if (token == null) { return(false); } // the first line of any message is never empty if (token.IsEmpty) { return(false); } // success! this line is a header string line = token.ToString(HttpUtils.Encoding); // parse the size line HttpChunkSizeLine chunkSizeLine = HttpChunkSizeLine.Parse(line); // create a new chunk _chunk = new HttpChunk(chunkSizeLine, null); // change state to processing chunk data _state = Processing.ChunkData; return(true); }
/// <summary> /// Destroys the internal variables used to read the message /// </summary> private void CleanupVars() { // reset our internal vars _chunk = null; _chunkedBody = null; _parser = null; _receivedBytes = null; _headerOffsetStart = -1; _headerOffsetEnd = -1; }
/// <summary> /// Initializes internal variables used to read the message /// </summary> private void InitVars() { // reset our internal vars _state = Processing.FirstLine; _chunk = null; _chunkedBody = null; _parser = new HttpByteParser(); _receivedBytes = null; _headerOffsetStart = -1; _headerOffsetEnd = -1; }
/// <summary> /// Tries to parse some chunk data for the message /// </summary> /// <returns></returns> private bool TryAndParseChunkData(ref HttpMessage message, EventHandler <HttpMessageProgressEventArgs> onProgress, object stateObject) { // get bytes, and update the index... int waitingOn = _chunk.Size; int received = _receivedBytes.Length - 2 - _parser.Index; // if we received enough data to pull in a chunk, do that now if (received >= waitingOn) { // copy the end of the data out as chunk data byte[] data = HttpUtils.Clone(_receivedBytes, _parser.Index, _chunk.Size); // bump the parser past the end of the next \r\n _parser.Index += _chunk.Size + 2; // create a new chunked body if (_chunkedBody == null) { _chunkedBody = new HttpChunkedBody(); } // assign the data to the chunk _chunk.Data = data; // todo: // add the chunk to the body _chunkedBody.Chunks.Add(_chunk); // if the chunk is empty, it's the last chunk bool empty = _chunk.IsEmpty; // destroy the chunk _chunk = null; if (empty) { // change state to processing chunk data _state = Processing.ChunkTrailerHeaderLine; } else { // go back to processing a chunk size line _state = Processing.ChunkSizeLine; } return(true); } return(false); }
/// <summary> /// Tries to parse some chunk data for the message /// </summary> /// <returns></returns> private bool TryAndParseChunkData(ref HttpMessage message, EventHandler<HttpMessageProgressEventArgs> onProgress, object stateObject) { // get bytes, and update the index... int waitingOn = _chunk.Size; int received = _receivedBytes.Length - 2 - _parser.Index; // if we received enough data to pull in a chunk, do that now if (received >= waitingOn) { // copy the end of the data out as chunk data byte[] data = HttpUtils.Clone(_receivedBytes, _parser.Index, _chunk.Size); // bump the parser past the end of the next \r\n _parser.Index += _chunk.Size + 2; // create a new chunked body if (_chunkedBody == null) _chunkedBody = new HttpChunkedBody(); // assign the data to the chunk _chunk.Data = data; // todo: // add the chunk to the body _chunkedBody.Chunks.Add(_chunk); // if the chunk is empty, it's the last chunk bool empty = _chunk.IsEmpty; // destroy the chunk _chunk = null; if (empty) { // change state to processing chunk data _state = Processing.ChunkTrailerHeaderLine; } else { // go back to processing a chunk size line _state = Processing.ChunkSizeLine; } return true; } return false; }
/// <summary> /// Initializes internal variables used to read the message /// </summary> private void InitVars() { // reset our internal vars _state = Processing.FirstLine; _chunk = null; _chunkedBody = null; _parser = new HttpByteParser(); _receivedBytes = null; _headerOffsetStart = -1; _headerOffsetEnd = -1; }
/// <summary> /// Destroys the internal variables used to read the message /// </summary> private void CleanupVars() { // reset our internal vars _chunk = null; _chunkedBody = null; _parser = null; _receivedBytes = null; _headerOffsetStart = -1; _headerOffsetEnd = -1; }
/// <summary> /// Tries to parse a chunk size line for the message /// </summary> /// <returns></returns> private bool TryAndParseChunkSizeLine(ref HttpMessage message, EventHandler<HttpMessageProgressEventArgs> onProgress, object stateObject) { // try and parse a token from the data HttpByteParserToken token = _parser.GetNextToken(); if (token == null) return false; // the first line of any message is never empty if (token.IsEmpty) return false; // success! this line is a header string line = token.ToString(HttpUtils.Encoding); // parse the size line HttpChunkSizeLine chunkSizeLine = HttpChunkSizeLine.Parse(line); // create a new chunk _chunk = new HttpChunk(chunkSizeLine, null); // change state to processing chunk data _state = Processing.ChunkData; return true; }
/// <summary> /// Adds a chunk to the list /// </summary> /// <param name="chunk"></param> public void Add(HttpChunk chunk) { base.InnerList.Add(chunk); }
/// <summary> /// Removes a chunk from the list /// </summary> /// <param name="chunk"></param> public void Remove(HttpChunk chunk) { }
/// <summary> /// Removes a chunk from the list /// </summary> /// <param name="chunk"></param> public void Remove(HttpChunk chunk) { }
/// <summary> /// Adds an array of chunks to the list /// </summary> /// <param name="chunks"></param> public void AddRange(HttpChunk[] chunks) { foreach(HttpChunk chunk in chunks) this.Add(chunk); }
/// <summary> /// Adds a chunk to the list /// </summary> /// <param name="chunk"></param> public void Add(HttpChunk chunk) { base.InnerList.Add(chunk); }
/// <summary> /// Sends the body of a chunked transfer-encoded message /// </summary> /// <param name="socket"></param> /// <param name="abortEvent"></param> /// <param name="message"></param> internal protected void SendBodyChunked(Socket socket, ManualResetEvent abortEvent, HttpMessage message, EventHandler <HttpMessageProgressEventArgs> onProgress, object stateObject) { int segmentNumber = 0; int totalBytesSent = 0; byte[] body = message.ToByteArray(false /* no headers */, true /* just the body */); while (true) { // if we have sent the entire message then we can abortEvent if (totalBytesSent > body.Length) { break; } // start out with a full segment size (this is just the buffer size by which we will send - 8k seems to be really common although i have no idea why other than that it's a power of 2...) int chunkSize = MAX_SEGMENT_SIZE_CHUNKED; // adjust how much we need to send to complete the message if (chunkSize > (body.Length - totalBytesSent)) { chunkSize = (body.Length - totalBytesSent); } // bump up the segment number segmentNumber++; // create a chunk of data to send byte[] bytes = new byte[chunkSize]; Buffer.BlockCopy(body, totalBytesSent, bytes, 0, chunkSize); // create a chunk around the data HttpChunk chunk = new HttpChunk(bytes); // send the data int bytesSent = HttpUtils.SendBytes(socket, chunk.ToByteArray()); // if any data was sent if (bytesSent > 0) { // figure out how much as data, minus the chunks control chars int actualBytesSent = bytesSent - chunk.GetNonDataByteCount(); // if the chunksize is zero or less then we'll return what was sent if (chunkSize > 0) { // all other times it'll not count the non data byte count in the chunk bytesSent = actualBytesSent; } } // tally the number of bytes we have sent totalBytesSent += bytesSent; // notify the callback of our progress this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, false, bytes, totalBytesSent, stateObject)); // clear that buffer immediately bytes = null; // see if we have been instructed to abortEvent reading if (abortEvent != null) { if (abortEvent.WaitOne(1, false)) { throw new HttpMessageWriterAbortedException(message); } } } }
/// <summary> /// Sends the body of a chunked transfer-encoded message /// </summary> /// <param name="socket"></param> /// <param name="abortEvent"></param> /// <param name="message"></param> internal protected void SendBodyChunked(Socket socket, ManualResetEvent abortEvent, HttpMessage message, EventHandler<HttpMessageProgressEventArgs> onProgress, object stateObject) { int segmentNumber = 0; int totalBytesSent = 0; byte[] body = message.ToByteArray(false /* no headers */, true /* just the body */); while(true) { // if we have sent the entire message then we can abortEvent if (totalBytesSent > body.Length) break; // start out with a full segment size (this is just the buffer size by which we will send - 8k seems to be really common although i have no idea why other than that it's a power of 2...) int chunkSize = MAX_SEGMENT_SIZE_CHUNKED; // adjust how much we need to send to complete the message if (chunkSize > (body.Length - totalBytesSent)) chunkSize = (body.Length - totalBytesSent); // bump up the segment number segmentNumber++; // create a chunk of data to send byte[] bytes = new byte[chunkSize]; Buffer.BlockCopy(body, totalBytesSent, bytes, 0, chunkSize); // create a chunk around the data HttpChunk chunk = new HttpChunk(bytes); // send the data int bytesSent = HttpUtils.SendBytes(socket, chunk.ToByteArray()); // if any data was sent if (bytesSent > 0) { // figure out how much as data, minus the chunks control chars int actualBytesSent = bytesSent - chunk.GetNonDataByteCount(); // if the chunksize is zero or less then we'll return what was sent if (chunkSize > 0) // all other times it'll not count the non data byte count in the chunk bytesSent = actualBytesSent; } // tally the number of bytes we have sent totalBytesSent += bytesSent; // notify the callback of our progress this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, false, bytes, totalBytesSent, stateObject)); // clear that buffer immediately bytes = null; // see if we have been instructed to abortEvent reading if (abortEvent != null) if (abortEvent.WaitOne(1, false)) throw new HttpMessageWriterAbortedException(message); } }