Example #1
0
        /// <summary>
        /// Tries to parse the first line for the message
        /// </summary>
        /// <returns></returns>
        private bool TryAndParseFirstLine(ref HttpMessage message, HttpMessageProgressEventHandler 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! store the first line of the message
            message._firstLine = token.ToString(HttpUtils.Encoding);

            // save the offset into the data where the headers start
            _headerOffsetStart = _parser.Index;

            // change state to processing headers!
            _state = Processing.HeaderLine;

            return(true);
        }
Example #2
0
        /// <summary>
        /// Connects to the server specified by the address and port, sends the request and waits for a response.
        /// </summary>
        /// <param name="address">The address of the server, either an IPv4 address or Dns hostname</param>
        /// <param name="port">The port of the server</param>
        /// <param name="request">The request to send</param>
        /// <param name="exception">Any exception that is throw or encountered during the request/response session with the server</param>
        /// <param name="verbose">A flag that indicates the connection's verbosity level, true for more messages</param>
        /// <returns></returns>
        public static HttpResponse GetResponse(
            string address,
            int port,
            HttpRequest request,
            out Exception exception,
            bool verbose,
            AddressResolutionEventHandler onResolvingAddress,
            HttpMessageProgressEventHandler onSendProgress,
            HttpMessageProgressEventHandler onRecvProgress,
            object stateObject)
        {
            try
            {
                // parse the address using either IPv4 or Dns for hostnames into an end point with the port specified
                IPEndPoint ep = HttpUtils.Resolve(address, port, null, onResolvingAddress, stateObject);

                // return a response from the server
                return(HttpRequest.GetResponse(ep, request, out exception, verbose, onSendProgress, onRecvProgress, stateObject));
            }
            catch (ThreadAbortException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                exception = ex;
            }
            return(null);
        }
Example #3
0
 /// <summary>
 /// Notifies the callback method of our progress while reading in the message
 /// </summary>
 /// <param name="onProgress"></param>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 protected virtual void OnProgress(HttpMessageProgressEventHandler onProgress, object sender, HttpMessageProgressEventArgs e)
 {
     if (onProgress != null)
     {
         onProgress(sender, e);
     }
 }
Example #4
0
        /// <summary>
        /// Tries to parse a chunk size line for the message
        /// </summary>
        /// <returns></returns>
        private bool TryAndParseChunkSizeLine(ref HttpMessage message, HttpMessageProgressEventHandler 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);
        }
Example #5
0
        /// <summary>
        /// Tries to parse a trailer header for the message
        /// </summary>
        /// <returns></returns>
        private bool TryAndParseTrailerHeaderLine(ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            // try and parse a token from the data
            HttpByteParserToken token = _parser.GetNextToken();

            if (token == null)
            {
                // change state to processing the body
                _state = Processing.Finished;

                // we're done with the headers
                return(true);
            }

            // the first line of any message is never empty
            if (token.IsEmpty)
            {
                // change state to processing the body
                _state = Processing.Finished;

                // we're done with the headers
                return(true);
            }

            // success! this line is a header
            string line = token.ToString(HttpUtils.Encoding);

            // parse the line into a new header
            HttpHeader header = HttpHeader.Parse(line);

            // save the header in the chunked body trailers
            _chunkedBody.TrailerHeaders.Add(header);

            return(true);
        }
		/// <summary>
		/// Writes the message to the socket
		/// </summary>
		/// <param name="socket"></param>
		/// <param name="abortEvent"></param>
		/// <param name="message"></param>
		public void Write(Socket socket, ManualResetEvent abortEvent, HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{			
			// send the headers of the message
			this.SendHeaders(socket, message, onProgress, stateObject);

			// send the body of the message
			this.SendBody(socket, abortEvent, message, onProgress, stateObject);
		}
Example #7
0
        /// <summary>
        /// Connects to the server specified by the endpoint, sends the request and waits for a response.
        /// </summary>
        /// <param name="ep">The address:port of the server</param>
        /// <param name="request">The request to send</param>
        /// <param name="exception">Any exception that is throw or encountered during the request/response session with the server</param>
        /// <param name="verbose">A flag that indicates the connection's verbosity level, true for more messages</param>
        /// <returns></returns>
        public static HttpResponse GetResponse(
            IPEndPoint ep,
            HttpRequest request,
            out Exception exception,
            bool verbose,
            HttpMessageProgressEventHandler onSendProgress,
            HttpMessageProgressEventHandler onRecvProgress,
            object stateObject)
        {
            #region Params Validation

            if (ep == null)
            {
                throw new ArgumentNullException("ep");
            }

            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            exception = null;

            #endregion

            // define a connection for this request/response session
            HttpConnection connection = null;

            try
            {
                // create a connection to the remote end point
                connection = new HttpConnection(ep, false, verbose, HttpOptions.SendTimeout, HttpOptions.RecvTimeout);

                // return a response from the server
                return(HttpRequest.GetResponse(connection, request, out exception, onSendProgress, onRecvProgress, stateObject));
            }
            catch (ThreadAbortException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                exception = ex;
            }
            finally
            {
                // always try and close the connect up afterwards
                if (connection != null)
                {
                    connection.Close();
                }
            }
            return(null);
        }
Example #8
0
        /// <summary>
        /// Tries to parse some chunk data for the message
        /// </summary>
        /// <returns></returns>
        private bool TryAndParseChunkData(ref HttpMessage message, HttpMessageProgressEventHandler 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);
        }
Example #9
0
        /// <summary>
        /// Sends the specified request using the connection's socket
        /// </summary>
        /// <param name="request"></param>
        public virtual void SendRequest(
            HttpRequest request,
            HttpMessageProgressEventHandler onProgress,
            object stateObject)
        {
            Debug.WriteLineIf(_verbose, "Sending request...", MY_TRACE_CATEGORY);
            Debug.WriteIf(_verbose, request.ToString(false));

            // lock the writer
            lock (_messageWriter)
            {
                // send the message
                _messageWriter.Write(_socket, null, request, onProgress, stateObject);
            }
        }
Example #10
0
        /// <summary>
        /// Tries to parse a header line for the message
        /// </summary>
        /// <returns></returns>
        private bool TryAndParseHeaderLine(ref HttpMessage message, HttpMessageProgressEventHandler 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)
            {
                // save the offset into the data where the headers end
                _headerOffsetEnd = _parser.Index;

                // determine if the body is chunked, as we have all the headers now we can determine how the message is going to come in
                if (message.IsChunked)
                {
                    // change state to processing a chunk size line
                    _state = Processing.ChunkSizeLine;
                }
                else
                {
                    // change state to processing the body
                    _state = Processing.Body;
                }

                // notify the callback that we have received the headers
                this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, true, new byte[] {}, _receivedBytes.Length, stateObject));

                // we're done with the headers
                return(true);
            }

            // success! this line is a header
            string line = token.ToString(HttpUtils.Encoding);

            // parse the line into a new header
            HttpHeader header = HttpHeader.Parse(line);

            // save the header
            message.Headers.Add(header);

            return(true);
        }
Example #11
0
        /// <summary>
        /// Sends the specified request and waits for a response using the specified connection.
        /// </summary>
        /// <param name="connection">The connection to use for communication</param>
        /// <param name="request">The request to send</param>
        /// <param name="exception">Any exception that is throw or encountered during the request/response session with the server</param>
        /// <returns></returns>
        public static HttpResponse GetResponse(
            HttpConnection connection,
            HttpRequest request,
            out Exception exception,
            HttpMessageProgressEventHandler onSendProgress,
            HttpMessageProgressEventHandler onRecvProgress,
            object stateObject)
        {
            #region Params Validation

            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            exception = null;

            #endregion

            // use the connection to get a response
            HttpResponse response = connection.GetResponse(request, onSendProgress, onRecvProgress, stateObject);

            // if there is no response, then obviously something went wrong, retrieve the last exception from the connection
            if (response == null)
            {
                exception = connection.GetLastException();

                if (exception != null)
                {
                    if (exception.GetType() == typeof(ThreadAbortException))
                    {
                        throw exception;
                    }
                }
            }

            // return the response
            return(response);
        }
Example #12
0
        /// <summary>
        /// Tries to parse the body for the message
        /// </summary>
        /// <returns></returns>
        private bool TryAndParseBody(ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            // determine the content length of the message's entity
            int contentLength = message.ContentLength;

            // the number of bytes we have received thus far would be determined by looking at the different between what we have and where the header's stopped
            int postedBytesLength = _receivedBytes.Length - _headerOffsetEnd;

            // we could have potentially received more than just one message so the extra data would be denoted by the difference between the content length and the body which we received
            int extraBytesReceived = postedBytesLength - contentLength;

            // if we received extra bytes that do not belong to this message
            if (extraBytesReceived > 0)
            {
                // create a new buffer to hold the exra
                _previouslyReceivedBytes = new byte[extraBytesReceived];

                // copy the tail of the message off as extra bytes
                Buffer.BlockCopy(_receivedBytes, _headerOffsetEnd + contentLength, _previouslyReceivedBytes, 0, extraBytesReceived);

                // now shrink the bytes received to be exactly what comprises the bytes that make up this message
                byte[] tempBuffer = new byte[_headerOffsetEnd + contentLength];
                Buffer.BlockCopy(_receivedBytes, 0, tempBuffer, 0, tempBuffer.Length);
                _receivedBytes = tempBuffer;
            }

            // if we've read in enough data to get the body, or there's no body coming
            if ((postedBytesLength >= contentLength && contentLength > 0) || (contentLength == 0))
            {
                // change state to finished
                _state = Processing.Finished;

                // we want to kick out of the processing loop
                return(false);
            }

            // otherwise we simply need to wait on the socket to receive more data
            return(false);
        }
Example #13
0
        /// <summary>
        /// Sends the request and waits for a response
        /// </summary>
        /// <param name="request">The request to be processed by the server and for which we want a response.</param>
        /// <returns></returns>
        public virtual HttpResponse GetResponse(
            HttpRequest request,
            HttpMessageProgressEventHandler onSendProgress,
            HttpMessageProgressEventHandler onRecvProgress,
            object stateObject)
        {
            try
            {
                // send the request
                this.SendRequest(request, onSendProgress, stateObject);

                // lock the reader
                HttpResponse response = null;
                lock (_messageReader)
                {
                    // receive the response
                    HttpMessage message = _messageReader.Read(_socket, null, onRecvProgress, stateObject);
                    if (message.Type == HttpMessageTypes.HttpResponse)
                    {
                        response = new HttpResponse(message);
                    }
                }

                if (response != null)
                {
                    Debug.WriteLineIf(_verbose, "Logging response...", MY_TRACE_CATEGORY);
                    Debug.WriteIf(_verbose, response.ToString(false));
                }

                return(response);
            }
            catch (Exception ex)
            {
                // notify that this connection has encountered an exception
                this.OnException(this, new ExceptionEventArgs(ex));
                this.Close();
            }
            return(null);
        }
Example #14
0
        /// <summary>
        /// Writes the message's headers to the socket
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="message"></param>
        internal protected int SendHeaders(Socket socket, HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            // check the headers of the message
            this.CheckHeaders(socket, message);

            /*
             * The only thing we can reliably send at the start of every message are the headers
             * Technically we should be carefull how many bytes the headers are, but at this point
             * until i see it fail, i'm gonna take it easy on the paranoia factor, sometimes i can only defend so much before i'm wasting time... :P
             *
             * So send the headers
             * */
            byte[] bytes = message.ToByteArray(true /* get just the headers */, false /* do not include the body */);

            // send the header bytes
            int bytesSent = HttpUtils.SendBytes(socket, bytes);

            // notify the callback that we have sent the headers
            this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, true, bytes, bytesSent, stateObject));

            return(bytesSent);
        }
Example #15
0
        /// <summary>
        /// Reads an HttpMessage from the specified socket
        /// </summary>
        /// <param name="socket">The socket to read</param>
        /// <param name="abortEvent">An event to watch in case of an abort</param>
        /// <returns></returns>
        public virtual HttpMessage Read(Socket socket, ManualResetEvent abortEvent, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            if (socket == null)
            {
                throw new ArgumentNullException("socket");
            }

            // setup our vars
            this.InitVars();

            // create a new message
            HttpMessage message = new HttpMessage();

            try
            {
                // while we've not finished reading the message
                while (!this.IsFinished(abortEvent))
                {
                    // keep receiving
                    this.ReceiveData(socket, abortEvent, ref message, onProgress, stateObject);

                    // keep processing
                    this.ProcessData(abortEvent, ref message, onProgress, stateObject);
                }
            }
            catch (OperationAbortedException)
            {
                throw new HttpMessageReaderAbortedException(message);
            }

            // set the message body
            message._body = this.ReconstructChunkedBodyIfNecessary(ref message);

            // clean up our vars
            this.CleanupVars();

            return(message);
        }
		/// <summary>
		/// Tries to parse the first line for the message
		/// </summary>
		/// <returns></returns>
		private bool TryAndParseFirstLine(ref HttpMessage message, HttpMessageProgressEventHandler 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! store the first line of the message
			message._firstLine = token.ToString(HttpUtils.Encoding);

			// save the offset into the data where the headers start
			_headerOffsetStart = _parser.Index;

			// change state to processing headers!
			_state = Processing.HeaderLine;
			
			return true;
		}
		/// <summary>
		/// Sends the specified request and waits for a response using the specified connection.
		/// </summary>
		/// <param name="connection">The connection to use for communication</param>
		/// <param name="request">The request to send</param>
		/// <param name="exception">Any exception that is throw or encountered during the request/response session with the server</param>
		/// <returns></returns>
		public static HttpResponse GetResponse(
			HttpConnection connection, 
			HttpRequest request, 
			out Exception exception,
			HttpMessageProgressEventHandler onSendProgress,
			HttpMessageProgressEventHandler onRecvProgress,
			object stateObject)
		{
			#region Params Validation

			if (connection == null)
				throw new ArgumentNullException("connection");

			if (request == null)
				throw new ArgumentNullException("request");

			exception = null;

			#endregion

			// use the connection to get a response
			HttpResponse response = connection.GetResponse(request, onSendProgress, onRecvProgress, stateObject);
			
			// if there is no response, then obviously something went wrong, retrieve the last exception from the connection
			if (response == null)
			{
				exception = connection.GetLastException();

				if (exception != null)
					if (exception.GetType() == typeof(ThreadAbortException))
						throw exception;
			}
			
			// return the response
			return response;
		}
		/// <summary>
		/// Tries to parse a chunk size line for the message
		/// </summary>
		/// <returns></returns>
		private bool TryAndParseChunkSizeLine(ref HttpMessage message, HttpMessageProgressEventHandler 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>
		/// Tries to parse a header line for the message
		/// </summary>
		/// <returns></returns>
		private bool TryAndParseHeaderLine(ref HttpMessage message, HttpMessageProgressEventHandler 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)
			{
				// save the offset into the data where the headers end
				_headerOffsetEnd = _parser.Index;

				// determine if the body is chunked, as we have all the headers now we can determine how the message is going to come in
				if (message.IsChunked)
					// change state to processing a chunk size line
					_state = Processing.ChunkSizeLine;
				else
					// change state to processing the body
					_state = Processing.Body;

				// notify the callback that we have received the headers
				this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, true, new byte[] {}, _receivedBytes.Length, stateObject));							
				
				// we're done with the headers
				return true; 
			}

			// success! this line is a header
			string line = token.ToString(HttpUtils.Encoding);

			// parse the line into a new header
			HttpHeader header = HttpHeader.Parse(line);

			// save the header
			message.Headers.Add(header);

			return true;
		}
		/// <summary>
		/// Processes the raw data, either reading headers or chunked body data
		/// </summary>
		private void ProcessData(ManualResetEvent abortEvent, ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			// at each pass in the processing phase set the buffer to be parsed by the parser to the buffer into which we received bytes
			// the previous parsing phase may have failed simply because we did not have enough data yet to fullfill the current state's needs
			// so we'll update what we have received and carry on from the last spot, just hopefully with more data... :P
			_parser.SetBuffer(_receivedBytes);
						
			bool stillParsing = true;

			// enter a processing loop and keep trying to parse data based on our current state until the phase fails
			while(stillParsing)
			{
				// look at our current state to determine what data we should be trying to process and parse
				switch(_state)
				{					
					case Processing.FirstLine:
						stillParsing = this.TryAndParseFirstLine(ref message, onProgress, stateObject);	
						break;
					
					case Processing.HeaderLine:
						stillParsing = this.TryAndParseHeaderLine(ref message, onProgress, stateObject);	
						break;
						
					case Processing.ChunkSizeLine:
						stillParsing = this.TryAndParseChunkSizeLine(ref message, onProgress, stateObject);	
						break;

					case Processing.ChunkData:
						stillParsing = this.TryAndParseChunkData(ref message, onProgress, stateObject);	
						break;

					case Processing.ChunkTrailerHeaderLine:
						stillParsing = this.TryAndParseTrailerHeaderLine(ref message, onProgress, stateObject);	
						break;

					case Processing.Body:
						stillParsing = this.TryAndParseBody(ref message, onProgress, stateObject);	
						break;

					case Processing.Finished:
						Debug.Assert(false, "We should be out of the processing loop if our state is 'Finished'.");
						break;
				};

				// and in case any of the methods change the state to finished, but think they are still processing
				if (stillParsing)
					// jump in and check so we don't get stuck in an endless loop of parsing
					stillParsing = !this.IsFinished(abortEvent);
			}
		}
		/// <summary>
		/// Notifies the callback method of our progress while reading in the message
		/// </summary>
		/// <param name="onProgress"></param>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected virtual void OnProgress(HttpMessageProgressEventHandler onProgress, object sender, HttpMessageProgressEventArgs e)
		{			
			if (onProgress != null)
				onProgress(sender, e);			
		}
		/// <summary>
		/// Writes the message's headers to the socket
		/// </summary>
		/// <param name="socket"></param>
		/// <param name="message"></param>
		internal protected int SendHeaders(Socket socket, HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			// check the headers of the message
			this.CheckHeaders(socket, message);

			/*
			 * The only thing we can reliably send at the start of every message are the headers
			 * Technically we should be carefull how many bytes the headers are, but at this point
			 * until i see it fail, i'm gonna take it easy on the paranoia factor, sometimes i can only defend so much before i'm wasting time... :P
			 * 
			 * So send the headers
			 * */
			byte[] bytes = message.ToByteArray(true /* get just the headers */, false /* do not include the body */);

			// send the header bytes
			int bytesSent = HttpUtils.SendBytes(socket, bytes);

			// notify the callback that we have sent the headers
			this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, true, bytes, bytesSent, stateObject));

			return bytesSent;
		}
		/// <summary>
		/// Sends the specified request using the connection's socket
		/// </summary>
		/// <param name="request"></param>
		public virtual void SendRequest(
			HttpRequest request,			
			HttpMessageProgressEventHandler onProgress,
			object stateObject)
		{
			Debug.WriteLineIf(_verbose, "Sending request...", MY_TRACE_CATEGORY);			
			Debug.WriteIf(_verbose, request.ToString(false));

			// lock the writer
			lock(_messageWriter)
			{
				// send the message
				_messageWriter.Write(_socket, null, request, onProgress, stateObject);
			}
		}
		/// <summary>
		/// Waits for data to become available for reading on the socket, then reads it into the main buffer for processing
		/// </summary>
		private void ReceiveData(Socket socket, ManualResetEvent abortEvent, ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			/*
			 * Data Receiving Phase
			 * This will receive data from the socket until we have enough data to process.
			 * */

			// wait for some bytes to become available
			int bytesAvailable = 0;
			byte[] bytesReceived = new byte[0];

			// if we don't have data left over from last time try and go with just that first
			if (_previouslyReceivedBytes == null)
			{
				// ok there was nothing left over, so we're back to receiving again
				bytesAvailable = HttpUtils.WaitForAvailableBytes(socket, abortEvent);
					
				// receive as many bytes as we can (a chunk as it were)
				bytesReceived = HttpUtils.ReceiveBytes(socket, bytesAvailable, MAX_BUFFER_LENGTH);
			}
						
			// if there was anything left over from last time
			if (_previouslyReceivedBytes != null)
			{				
				// combine the previous with this chunk
				bytesReceived = HttpUtils.Combine(_previouslyReceivedBytes, bytesReceived);					
			
				Debug.WriteLine(string.Format("Retaining '{0}' bytes from last message.", bytesReceived.Length));

				// reset the previous buffer
				_previouslyReceivedBytes = null;
			}

			// if we have a previous message buffer
			if (_receivedBytes != null)
			{
				// combine what we had, with what we just received
				byte[] buffer = HttpUtils.Combine(_receivedBytes, bytesReceived);
				_receivedBytes = buffer;			
			}
			else
				/*
				 * this is the first part of a new message
				 * */
				// otherwise just start with the chunk
				_receivedBytes = bytesReceived;				

			// if we have received the headers
			if (this.IsPastHeaders())
				// notify the callback that data has been received
				this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, false, bytesReceived, _receivedBytes.Length, stateObject));							
		}
		/// <summary>
		/// Writes the message's body to the socket
		/// </summary>
		/// <param name="socket"></param>
		/// <param name="message"></param>
		internal protected void SendBody(Socket socket, ManualResetEvent abortEvent, HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			// bail if there is no message body
			if (message.Body == null)
				return;

			// bail if there is a message body, with no length
			if (message.Body.Length == 0)
				return;

			/*
			 * In order to properly send the body, we must first determine if the transfer-encoding is chunked or not
			 * */
			if (HttpUtils.Contains(message.TransferEncoding, HttpTransferEncodings.Chunked))
			{
				// chunked
				this.SendBodyChunked(socket, abortEvent, message, onProgress, stateObject);
			}
			else
			{
				// non-chunked
				this.SendBodyNonChunked(socket, abortEvent, message, onProgress, stateObject);
			}
		}
Example #26
0
        /// <summary>
        /// Writes the message to the socket
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="abortEvent"></param>
        /// <param name="message"></param>
        public void Write(Socket socket, ManualResetEvent abortEvent, HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            // send the headers of the message
            this.SendHeaders(socket, message, onProgress, stateObject);

            // send the body of the message
            this.SendBody(socket, abortEvent, message, onProgress, stateObject);
        }
Example #27
0
        /// <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, HttpMessageProgressEventHandler 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, HttpMessageProgressEventHandler 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>
		/// Connects to the server specified by the endpoint, sends the request and waits for a response.
		/// </summary>
		/// <param name="ep">The address:port of the server</param>
		/// <param name="request">The request to send</param>
		/// <param name="exception">Any exception that is throw or encountered during the request/response session with the server</param>
		/// <param name="verbose">A flag that indicates the connection's verbosity level, true for more messages</param>
		/// <returns></returns>
		public static HttpResponse GetResponse(
			IPEndPoint ep,
			HttpRequest request, 
			out Exception exception, 
			bool verbose,
			HttpMessageProgressEventHandler onSendProgress,
			HttpMessageProgressEventHandler onRecvProgress,
			object stateObject)
		{
			#region Params Validation

			if (ep == null)
				throw new ArgumentNullException("ep");

			if (request == null)
				throw new ArgumentNullException("request");

			exception = null;

			#endregion

			// define a connection for this request/response session
			HttpConnection connection = null;

			try
			{
				// create a connection to the remote end point
				connection = new HttpConnection(ep, false, verbose, HttpOptions.SendTimeout, HttpOptions.RecvTimeout);
				
				// return a response from the server
				return HttpRequest.GetResponse(connection, request, out exception, onSendProgress, onRecvProgress, stateObject);
			}
			catch(ThreadAbortException ex)
			{
				throw ex;
			}
			catch(Exception ex)
			{
				exception = ex;
			}
			finally
			{
				// always try and close the connect up afterwards
				if (connection != null)
					connection.Close();
			}
			return null;
		}
		/// <summary>
		/// Tries to parse the body for the message
		/// </summary>
		/// <returns></returns>
		private bool TryAndParseBody(ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			// determine the content length of the message's entity
			int contentLength = message.ContentLength;

			// the number of bytes we have received thus far would be determined by looking at the different between what we have and where the header's stopped
			int postedBytesLength = _receivedBytes.Length - _headerOffsetEnd;

			// we could have potentially received more than just one message so the extra data would be denoted by the difference between the content length and the body which we received
			int extraBytesReceived = postedBytesLength - contentLength;

			// if we received extra bytes that do not belong to this message
			if (extraBytesReceived > 0)
			{				
				// create a new buffer to hold the exra
				_previouslyReceivedBytes = new byte[extraBytesReceived];

				// copy the tail of the message off as extra bytes
				Buffer.BlockCopy(_receivedBytes, _headerOffsetEnd + contentLength, _previouslyReceivedBytes, 0, extraBytesReceived);

				// now shrink the bytes received to be exactly what comprises the bytes that make up this message
				byte[] tempBuffer = new byte[_headerOffsetEnd + contentLength];
				Buffer.BlockCopy(_receivedBytes, 0, tempBuffer, 0, tempBuffer.Length);				
				_receivedBytes = tempBuffer;
			}

			// if we've read in enough data to get the body, or there's no body coming
			if ( (postedBytesLength >= contentLength && contentLength > 0) || (contentLength == 0))
			{				
				// change state to finished
				_state = Processing.Finished;		

				// we want to kick out of the processing loop
				return false;
			}

			// otherwise we simply need to wait on the socket to receive more data
			return false;
		}
		/// <summary>
		/// Connects to the server specified by the address and port, sends the request and waits for a response.
		/// </summary>
		/// <param name="address">The address of the server, either an IPv4 address or Dns hostname</param>
		/// <param name="port">The port of the server</param>
		/// <param name="request">The request to send</param>
		/// <param name="exception">Any exception that is throw or encountered during the request/response session with the server</param>
		/// <param name="verbose">A flag that indicates the connection's verbosity level, true for more messages</param>
		/// <returns></returns>
		public static HttpResponse GetResponse(
			string address, 
			int port, 
			HttpRequest request, 
			out Exception exception, 
			bool verbose,
			AddressResolutionEventHandler onResolvingAddress,
			HttpMessageProgressEventHandler onSendProgress,
			HttpMessageProgressEventHandler onRecvProgress,
			object stateObject)
		{
			try
			{
				// parse the address using either IPv4 or Dns for hostnames into an end point with the port specified
				IPEndPoint ep = HttpUtils.Resolve(address, port, null, onResolvingAddress, stateObject);
				
				// return a response from the server
				return HttpRequest.GetResponse(ep, request, out exception, verbose, onSendProgress, onRecvProgress, stateObject);
			}
			catch(ThreadAbortException ex)
			{
				throw ex;
			}
			catch(Exception ex)
			{
				exception = ex;
			}
			return null;
		}
		/// <summary>
		/// Tries to parse a trailer header for the message
		/// </summary>
		/// <returns></returns>
		private bool TryAndParseTrailerHeaderLine(ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			// try and parse a token from the data
			HttpByteParserToken token = _parser.GetNextToken();						
			if (token == null)
			{
				// change state to processing the body
				_state = Processing.Finished;

				// we're done with the headers
				return true; 
			}
			
			// the first line of any message is never empty
			if (token.IsEmpty)
			{
				// change state to processing the body
				_state = Processing.Finished;

				// we're done with the headers
				return true; 
			}

			// success! this line is a header
			string line = token.ToString(HttpUtils.Encoding);

			// parse the line into a new header
			HttpHeader header = HttpHeader.Parse(line);

			// save the header in the chunked body trailers
			_chunkedBody.TrailerHeaders.Add(header);

			return true;
		}
		/// <summary>
		/// Sends the request and waits for a response
		/// </summary>
		/// <param name="request">The request to be processed by the server and for which we want a response.</param>
		/// <returns></returns>
		public virtual HttpResponse GetResponse(
			HttpRequest request,
			HttpMessageProgressEventHandler onSendProgress,
			HttpMessageProgressEventHandler onRecvProgress,
			object stateObject)
		{
			try
			{
				// send the request
				this.SendRequest(request, onSendProgress, stateObject);			

				// lock the reader
				HttpResponse response = null;
				lock(_messageReader)
				{
					// receive the response
					HttpMessage message = _messageReader.Read(_socket, null, onRecvProgress, stateObject);
					if (message.Type == HttpMessageTypes.HttpResponse)
						response = new HttpResponse(message);
				}

				if (response != null)
				{
					Debug.WriteLineIf(_verbose, "Logging response...", MY_TRACE_CATEGORY);
					Debug.WriteIf(_verbose, response.ToString(false));
				}

				return response;
			}
			catch(Exception ex) 
			{
				// notify that this connection has encountered an exception				
				this.OnException(this, new ExceptionEventArgs(ex));
				this.Close();
			}
			return null;
		}
		/// <summary>
		/// Tries to parse some chunk data for the message
		/// </summary>
		/// <returns></returns>
		private bool TryAndParseChunkData(ref HttpMessage message, HttpMessageProgressEventHandler 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;
		}
Example #35
0
        /// <summary>
        /// Writes the message's body to the socket
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="message"></param>
        internal protected void SendBody(Socket socket, ManualResetEvent abortEvent, HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            // bail if there is no message body
            if (message.Body == null)
            {
                return;
            }

            // bail if there is a message body, with no length
            if (message.Body.Length == 0)
            {
                return;
            }

            /*
             * In order to properly send the body, we must first determine if the transfer-encoding is chunked or not
             * */
            if (HttpUtils.Contains(message.TransferEncoding, HttpTransferEncodings.Chunked))
            {
                // chunked
                this.SendBodyChunked(socket, abortEvent, message, onProgress, stateObject);
            }
            else
            {
                // non-chunked
                this.SendBodyNonChunked(socket, abortEvent, message, onProgress, stateObject);
            }
        }
		/// <summary>
		/// Sends the body of a non-chunked transfer-encoded message
		/// </summary>
		/// <param name="socket"></param>
		/// <param name="abortEvent"></param>
		/// <param name="message"></param>
		internal protected void SendBodyNonChunked(Socket socket, ManualResetEvent abortEvent, HttpMessage message, HttpMessageProgressEventHandler 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_NONCHUNKED;

				// 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 the chunk to send
				byte[] bytes = new byte[chunkSize];
				Buffer.BlockCopy(body, totalBytesSent /* offset */, bytes, 0, chunkSize);

				// try and send the segment
				int bytesSent = HttpUtils.SendBytes(socket, bytes);

				// update the stream position which is the total number of bytes received
				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);					
			} // while (true)
		}
Example #37
0
        /// <summary>
        /// Sends the body of a non-chunked transfer-encoded message
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="abortEvent"></param>
        /// <param name="message"></param>
        internal protected void SendBodyNonChunked(Socket socket, ManualResetEvent abortEvent, HttpMessage message, HttpMessageProgressEventHandler 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_NONCHUNKED;

                // 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 the chunk to send
                byte[] bytes = new byte[chunkSize];
                Buffer.BlockCopy(body, totalBytesSent /* offset */, bytes, 0, chunkSize);

                // try and send the segment
                int bytesSent = HttpUtils.SendBytes(socket, bytes);

                // update the stream position which is the total number of bytes received
                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);
                    }
                }
            }             // while (true)
        }
Example #38
0
        /// <summary>
        /// Waits for data to become available for reading on the socket, then reads it into the main buffer for processing
        /// </summary>
        private void ReceiveData(Socket socket, ManualResetEvent abortEvent, ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            /*
             * Data Receiving Phase
             * This will receive data from the socket until we have enough data to process.
             * */

            // wait for some bytes to become available
            int bytesAvailable = 0;

            byte[] bytesReceived = new byte[0];

            // if we don't have data left over from last time try and go with just that first
            if (_previouslyReceivedBytes == null)
            {
                // ok there was nothing left over, so we're back to receiving again
                bytesAvailable = HttpUtils.WaitForAvailableBytes(socket, abortEvent);

                // receive as many bytes as we can (a chunk as it were)
                bytesReceived = HttpUtils.ReceiveBytes(socket, bytesAvailable, MAX_BUFFER_LENGTH);
            }

            // if there was anything left over from last time
            if (_previouslyReceivedBytes != null)
            {
                // combine the previous with this chunk
                bytesReceived = HttpUtils.Combine(_previouslyReceivedBytes, bytesReceived);

                Debug.WriteLine(string.Format("Retaining '{0}' bytes from last message.", bytesReceived.Length));

                // reset the previous buffer
                _previouslyReceivedBytes = null;
            }

            // if we have a previous message buffer
            if (_receivedBytes != null)
            {
                // combine what we had, with what we just received
                byte[] buffer = HttpUtils.Combine(_receivedBytes, bytesReceived);
                _receivedBytes = buffer;
            }
            else
            {
                /*
                 * this is the first part of a new message
                 * */
                // otherwise just start with the chunk
                _receivedBytes = bytesReceived;
            }

            // if we have received the headers
            if (this.IsPastHeaders())
            {
                // notify the callback that data has been received
                this.OnProgress(onProgress, this, new HttpMessageProgressEventArgs(message, false, bytesReceived, _receivedBytes.Length, stateObject));
            }
        }
Example #39
0
        /// <summary>
        /// Processes the raw data, either reading headers or chunked body data
        /// </summary>
        private void ProcessData(ManualResetEvent abortEvent, ref HttpMessage message, HttpMessageProgressEventHandler onProgress, object stateObject)
        {
            // at each pass in the processing phase set the buffer to be parsed by the parser to the buffer into which we received bytes
            // the previous parsing phase may have failed simply because we did not have enough data yet to fullfill the current state's needs
            // so we'll update what we have received and carry on from the last spot, just hopefully with more data... :P
            _parser.SetBuffer(_receivedBytes);

            bool stillParsing = true;

            // enter a processing loop and keep trying to parse data based on our current state until the phase fails
            while (stillParsing)
            {
                // look at our current state to determine what data we should be trying to process and parse
                switch (_state)
                {
                case Processing.FirstLine:
                    stillParsing = this.TryAndParseFirstLine(ref message, onProgress, stateObject);
                    break;

                case Processing.HeaderLine:
                    stillParsing = this.TryAndParseHeaderLine(ref message, onProgress, stateObject);
                    break;

                case Processing.ChunkSizeLine:
                    stillParsing = this.TryAndParseChunkSizeLine(ref message, onProgress, stateObject);
                    break;

                case Processing.ChunkData:
                    stillParsing = this.TryAndParseChunkData(ref message, onProgress, stateObject);
                    break;

                case Processing.ChunkTrailerHeaderLine:
                    stillParsing = this.TryAndParseTrailerHeaderLine(ref message, onProgress, stateObject);
                    break;

                case Processing.Body:
                    stillParsing = this.TryAndParseBody(ref message, onProgress, stateObject);
                    break;

                case Processing.Finished:
                    Debug.Assert(false, "We should be out of the processing loop if our state is 'Finished'.");
                    break;
                }
                ;

                // and in case any of the methods change the state to finished, but think they are still processing
                if (stillParsing)
                {
                    // jump in and check so we don't get stuck in an endless loop of parsing
                    stillParsing = !this.IsFinished(abortEvent);
                }
            }
        }
		/// <summary>
		/// Reads an HttpMessage from the specified socket
		/// </summary>
		/// <param name="socket">The socket to read</param>
		/// <param name="abortEvent">An event to watch in case of an abort</param>
		/// <returns></returns>
		public virtual HttpMessage Read(Socket socket, ManualResetEvent abortEvent, HttpMessageProgressEventHandler onProgress, object stateObject)
		{
			if (socket == null)
				throw new ArgumentNullException("socket");
			
			// setup our vars
			this.InitVars();			

			// create a new message
			HttpMessage message = new HttpMessage();

			try
			{
				// while we've not finished reading the message
				while(!this.IsFinished(abortEvent))
				{
					// keep receiving
					this.ReceiveData(socket, abortEvent, ref message, onProgress, stateObject);

					// keep processing
					this.ProcessData(abortEvent, ref message, onProgress, stateObject);				
				}
			}
			catch(OperationAbortedException)
			{
				throw new HttpMessageReaderAbortedException(message);
			}
			
			// set the message body
			message._body = this.ReconstructChunkedBodyIfNecessary(ref message);

			// clean up our vars
			this.CleanupVars();

			return message;
		}