applayerprotocols/httptransportfw/httpmessage/chttpmessagecomposer.h
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #ifndef __CHTTPMESSAGECOMPOSER_H__
       
    17 #define __CHTTPMESSAGECOMPOSER_H__
       
    18 
       
    19 #include <e32base.h>
       
    20 #include <http/mhttpdatasupplier.h>
       
    21 
       
    22 #include "timerlogger.h"
       
    23 #include "mhttpbuffersupplier.h"
       
    24 #include "thttpdatacomposer.h"
       
    25 
       
    26 
       
    27 class MHttpMessageComposerObserver;
       
    28 
       
    29 class CHttpMessageComposer : public CActive,
       
    30 							 public MHttpBufferSupplier
       
    31 /**	
       
    32 	The CHttpMessageComposer class provides functionality for creating HTTP/1.1 
       
    33 	messages as defined in RFC2616. The HTTP/1.1 protocol specifies that the CR
       
    34 	LF sequence is the end of line (eol) marker for all protocol elements except
       
    35 	the entity-body.
       
    36 
       
    37 	The composer does not process any header fields or start-line tokens. 
       
    38 	Therefore it needs to be told if headers and/or an entity body is expected. 
       
    39 	If the message does contain an entity body and the size of the body data is
       
    40 	not known then the composer will apply the chunked transfer encoding to the
       
    41 	entity body. 
       
    42 
       
    43 	The composer needs an observer (MHttpMessageComposerObserver). The observer 
       
    44 	supplies the message info such as the start-line tokens, header field tokens
       
    45 	and other message info. An MHTTPDataSupplier object is used to supply the 
       
    46 	entity body data if there is one. The observer must ensure that the 
       
    47 	descriptors containing the tokens it supplies remain valid until the composer
       
    48 	notifies it that the message is complete.
       
    49 
       
    50 	The composer is initially in the Idle state waiting to be notified of 
       
    51 	available message info. When it is notified, the composer moves into the 
       
    52 	CreatingStartLine state.
       
    53 
       
    54 	In the CreatingStartLine state the composer obtains the start-line tokens 
       
    55 	from the observer. These are added to the current data buffer. The composer
       
    56 	moves to the CreatingHeaders state.
       
    57 
       
    58 	In the CreatingHeaders state the composer adds header fields to the current
       
    59 	data buffer. The observer provides the header field tokens for the field 
       
    60 	name and field value. The composer will not fold header field values onto 
       
    61 	multiple lines unless the provided field token already contains folded field
       
    62 	values. The observer also informs the composer if there is no more header 
       
    63 	field data. The composer remains in the CreatingHeaders state until there 
       
    64 	are no more header field values. 
       
    65 	
       
    66 	In this case the composer adds an empty line to the current data buffer to 
       
    67 	mark the end of the header fields section. The current data buffer is ready
       
    68 	to be sent and the composer informs its observer of this. The composer moves
       
    69 	into the PendingEntityBody and waits for the observer to notify it that it 
       
    70 	has finished with the current data buffer.
       
    71 	
       
    72 	In the PendingEntityBody state the composer releases the current data buffer.
       
    73 	It then asks its observer if the message has an entity body. If there is no
       
    74 	entity body or if it is zero length then the composer moves to PendingIdle 
       
    75 	state. If there is an entity body and the size is known the composer moves 
       
    76 	to the SendEntityData state. If the entity body size is unknown the composer
       
    77 	moves to the CreatingChunkSize state.
       
    78 
       
    79 	In the SendEntityBody state the composer gets the next entity body data part
       
    80 	from the data supplier for the entity body. It sets this data as the current
       
    81 	send buffer and notifies the observer that message data is ready. A check is
       
    82 	made to see that if the data supplier claims that this is the last data part 
       
    83 	that all the specified amount of entity body data has been sent. If this is 
       
    84 	not true the observer will receive an error code of KErrCorrupt. The composer
       
    85 	moves to PendingReleaseData state and waits for the observer to notify it 
       
    86 	that it has finished with the current data buffer.
       
    87 
       
    88 	In the PendingReleaseData state the composer notifies the entity body data
       
    89 	supplier that it has finished with the current data part. If all the 
       
    90 	specified entity body data has been sent the composer moves to the 
       
    91 	PendingIdle state. If there is more entity body data to send the composer
       
    92 	moves to the SendEntityData and waits for the observer to notify it that 
       
    93 	there is more message info available.
       
    94 
       
    95 	In the CreatingChunkSize state the composer adds the size of the following
       
    96 	chunk-data component to the current send buffer as defined in RFC2616 
       
    97 	section 3.6.1. The send buffer wil contain the empty line delimiting the 
       
    98 	previous chunk-data component if this is not the first chunk-size component
       
    99 	to be sent. The composer notifies its observer that message data is ready. 
       
   100 	The composer moves into the SendChunkData state and waits for the observer 
       
   101 	to notify it that it has finished with the current data buffer.
       
   102 
       
   103 	If the chunk-data is zero-length then the chunk-size component is not added
       
   104 	to the send buffer.	
       
   105 
       
   106 	In the SendChunkData state the composer releases the current data buffer. It
       
   107 	then gets the chunk-data from the data supplier for the entity body. It sets
       
   108 	this data as the current buffer. The observer is only notified that message 
       
   109 	data is ready if the chunk-data is not zer-length. The composer moves into 
       
   110 	the PendingReleaseChunk state and waits for the observer to notify it that 
       
   111 	it has finished with the current data buffer.
       
   112 
       
   113 	In the PendingReleaseChunk state the composer notifies the entity body data
       
   114 	supplier that it has finished with the current data part. If that was the 
       
   115 	last part of the entity body data the composer adds the last-chunk component
       
   116 	to the current data buffer. It then asks the observer if the message has any 
       
   117 	trailer headers. If there are trailer headers then the composer moves to the 
       
   118 	CreatingTrailers state. Otherwise the composer moves to the 
       
   119 	CreatingEndOfTrailers state. 
       
   120 	
       
   121 	If there is more entity body data to follow the composer moves to the 
       
   122 	CreatingChunkSize state and waits for the observer to notify it that there is 
       
   123 	more message info available.
       
   124 
       
   125 	In the CreatingTrailers state the composer adds trailer header fields to the 
       
   126 	current data buffer. The observer provides the trailer header field tokens 
       
   127 	for the field name and field value. The composer will not fold header field 
       
   128 	values onto multiple lines unless the provided field token already contains 
       
   129 	folded field values. The observer also informs the composer if the provided 
       
   130 	field info is for the last trailer header field. The composer remains in the
       
   131 	CreatingTrailers state until there are no more trailer header field values. 
       
   132 	
       
   133 	In this case the composer adds an empty line to the current data buffer to 
       
   134 	mark the end of the trailer header fields section. The current data buffer 
       
   135 	is ready to be sent and the composer informs its observer of this. The
       
   136 	composer moves into the PendingEndOfChunkedBody and waits for the observer 
       
   137 	to notify it that it has finished with the current data buffer.
       
   138 
       
   139 	In the PendingEndOfChunkedBody the composer releases the current data buffer
       
   140 	and moves into the PendingIdle state. 
       
   141 
       
   142 	In the PendingIdle state the composer informs its observer that the message
       
   143 	is complete. The composer moves to the Idle state.
       
   144 	@internalComponent
       
   145 	@see		MHttpMessageComposerObserver
       
   146 */
       
   147 	{
       
   148 public:	// methods
       
   149 
       
   150 	static CHttpMessageComposer* NewL(MHttpMessageComposerObserver& aObserver);
       
   151 	virtual ~CHttpMessageComposer();
       
   152 	
       
   153 	void MessageInfoAvailable();
       
   154 	void GetMessageData(TPtrC8& aData);
       
   155 	void ReleaseMessageData();
       
   156 	void Reset();
       
   157 	TBool CheckMessagePendingComplete();
       
   158 
       
   159 private:	// enums
       
   160 
       
   161 	enum TComposerState
       
   162 /**	
       
   163 	The TComposerState enumeration defines the state machine for the http message
       
   164 	state machine.
       
   165 */
       
   166 		{
       
   167 		/** The composer is idle.
       
   168 		*/
       
   169 		EIdle						= 0,
       
   170 
       
   171 		/** The start-line is being created. The next state depends on whether 
       
   172 			there are headers or not.
       
   173 		*/
       
   174 		ECreatingStartLine,
       
   175 
       
   176 		/** The message has header fields. The next header field is added to the
       
   177 			http message. The composer remains in this state until all the header
       
   178 			fields have been added. If there is no more header field info an 
       
   179 			empty line is added. The composer has prepared the first part of the
       
   180 			http message and can notify its observer that message data is ready.
       
   181 		*/
       
   182 		ECreatingHeaders,
       
   183 
       
   184 		/** The composer needs to decide whether there is entity body and if so
       
   185 			does it need to be chunk encoded or not.
       
   186 		*/
       
   187 		EPendingEntityBody,
       
   188 
       
   189 		/** The message has a non-encoded entity body. It notifies its observer
       
   190 			that message data is ready.
       
   191 		*/
       
   192 		ESendEntityData,
       
   193 
       
   194 		/** The composer releases the current entity body data. If all the body
       
   195 			data has been sent then the message is complete. Otherwise the 
       
   196 			composer waits to be notified that more entity body data is available.
       
   197 		*/
       
   198 		EPendingReleaseData,
       
   199 
       
   200 		/** There is entity body to sent as in chunk-encoded format. The chunk-
       
   201 			size component specifying the size of the subsequent chunk-data is
       
   202 			added to the send buffer. The composer notifies its observer that it
       
   203 			has message ready. Note the send buffer will contain the empty line
       
   204 			marking the end of the previous chunk-data if this is not the first
       
   205 			chunk-size.
       
   206 		*/
       
   207 		ECreatingChunkSize,
       
   208 
       
   209 		/** The chunk-data is ready to be sent. The observer is notified that 
       
   210 			there is message data ready.
       
   211 		*/
       
   212 		ESendChunkData,
       
   213 
       
   214 		/** The composer releases the current chunk-data. If this was the last
       
   215 			chunk-data then the composer checks for trailer headers. If there 
       
   216 			are no trailer then the message is complete, otherwise the trailers
       
   217 			are added.
       
   218 		*/
       
   219 		EPendingReleaseChunk,
       
   220 
       
   221 		/** The message has trailer header fields. The next trailer header field
       
   222 			is added to the http message. The composer remains in this state 
       
   223 			until all the trailer header fields have been added. If there is no 
       
   224 			more trailer header field info an empty line is added. The composer 
       
   225 			has prepared the final part of the http message and can notify its 
       
   226 			observer that message data is ready.
       
   227 		*/
       
   228 		ECreatingTrailers,
       
   229 
       
   230 		/** The composer releases the current data buffer. The observer needs
       
   231 			to be informed that message is complete.
       
   232 		*/
       
   233 		EPendingEndOfChunkedBody,
       
   234 
       
   235 		/** The message is complete and the composer is waiting to go idle. The
       
   236 			observer is notified.
       
   237 		*/
       
   238 		EPendingIdle
       
   239 		};
       
   240 
       
   241 	enum TDataState
       
   242 /**	
       
   243 	The TDataState enumeration defines the state of the message parser as 
       
   244 	regards to the current data packet.
       
   245 */
       
   246 		{
       
   247 		/**	The composer is waiting for more message info to be available to be
       
   248 			able to continue composing.
       
   249 		*/
       
   250 		EWaitingForInfo			= 0,
       
   251 
       
   252 		/**	The composer is creating the message from the available info.
       
   253 		*/
       
   254 		EGotInfo,
       
   255 
       
   256 		/** The composer is waiting for the observer to release the current data
       
   257 			buffer before continuing to compose the message.
       
   258 		*/
       
   259 		EWaitingForRelease,
       
   260 
       
   261 		/**	The composer has been reset.
       
   262 		*/
       
   263 		EReset
       
   264 		};
       
   265 
       
   266 	enum TComposingStatus
       
   267 /**	
       
   268 	The TComposingStatus enumeration defines the status of composing for the 
       
   269 	current state of the composer.
       
   270 */
       
   271 		{
       
   272 		/**	The current state has been completed.
       
   273 		*/
       
   274 		ESectionDone		= 0,
       
   275 
       
   276 		/** The current state has not been completed.
       
   277 		*/
       
   278 		ESectionNotDone,
       
   279 
       
   280 		/** The current data packet should be sent.
       
   281 		*/
       
   282 		ESendData,
       
   283 
       
   284 		/** The composer should not continue. Either the message is complete or
       
   285 			more message info is required to continue.
       
   286 		*/
       
   287 		EStop
       
   288 		};
       
   289 
       
   290 private:	// methods from CActive
       
   291 
       
   292 	virtual void RunL();
       
   293 	virtual void DoCancel();
       
   294 	virtual TInt RunError(TInt aError);
       
   295 
       
   296 private:	// methods from MHttpBufferSupplier
       
   297 
       
   298 	virtual void ReAllocBufferL(TInt aRequiredSize, TPtr8& aBuffer);
       
   299 	virtual void DeleteBuffer();
       
   300 
       
   301 private:	// methods
       
   302 
       
   303 	CHttpMessageComposer(MHttpMessageComposerObserver& aObserver);
       
   304 
       
   305 	TComposingStatus ComposeStartLineL();
       
   306 	TComposingStatus ComposeHeadersL();
       
   307 	TComposingStatus ComposeSingleHeaderL();
       
   308 	TComposingStatus ComposeChunkSizeL();
       
   309 	TComposingStatus ComposeLastChunkL();
       
   310 	TComposingStatus ComposeTrailerL();
       
   311 
       
   312 	void CompleteSelf();
       
   313 	void DoReset();
       
   314 
       
   315 private:	// attributes
       
   316 
       
   317 	MHttpMessageComposerObserver&	iObserver;
       
   318 	THttpDataComposer				iDataComposer;
       
   319 	TComposerState					iState;
       
   320 	TDataState						iDataState;
       
   321 	HBufC8*							iDataBuffer;
       
   322 	TPtrC8							iSendBuffer;
       
   323 	MHTTPDataSupplier*				iBodyData;
       
   324 	TInt							iDataSizeLeft;
       
   325 	TBool							iLastChunk;
       
   326 	__DECLARE_PERFORMANCE_LOG
       
   327 	};
       
   328 
       
   329 #endif	// __CHTTPMESSAGECOMPOSER_H__