applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspCOTxData.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2001-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 // System includes
       
    17 #include <uri8.h>
       
    18 #include <wspstringconstants.h>
       
    19 #include <httpstringconstants.h>
       
    20 #include <wsp/mwspcapabilityviewer.h>
       
    21 #include <wsp/wsptypes.h>
       
    22 #include <wsperror.h>
       
    23 
       
    24 // User includes
       
    25 #include <http/rhttpheaders.h>
       
    26 #include <http/thttphdrval.h>
       
    27 #include "cwspcotransaction.h"
       
    28 #include "cwspheaderutils.h"
       
    29 #include "mwspcotxdatacallback.h"
       
    30 #include "wsppanic.h"
       
    31 
       
    32 // Class signature
       
    33 #include "cwspcotxdata.h"
       
    34 
       
    35 // Constants used in this module
       
    36 const TInt KPDUTypeFieldSize			= 1;	// Size in bytes
       
    37 const TInt KUIntVarOctetShift			= 7;
       
    38 const TInt KWspTxDataDefaultBufferSize	= 2048;
       
    39 
       
    40 CWspCOTxData* CWspCOTxData::NewL(CProtTransaction& aTransaction, MWspCOTxDataCallback& aObserver, MWspCapabilityViewer& aNegotiatedCapInfo)
       
    41 	{
       
    42 	return new (ELeave) CWspCOTxData(aTransaction, aObserver, aNegotiatedCapInfo);
       
    43 	}
       
    44 
       
    45 CWspCOTxData::~CWspCOTxData()
       
    46 	{
       
    47 	Cleanup();
       
    48 	}
       
    49 
       
    50 CWspCOTxData::CWspCOTxData(CProtTransaction& aTransaction, MWspCOTxDataCallback& aObserver, MWspCapabilityViewer& aNegotiatedCapInfo)
       
    51 : CTxData(aTransaction), iObserver(aObserver), iNegotiatedCapInfo(aNegotiatedCapInfo)
       
    52 	{
       
    53 	}
       
    54 
       
    55 const TDesC8& CWspCOTxData::RequestHeadersData()
       
    56 	{
       
    57 	return *iHeaderData;
       
    58 	}
       
    59 
       
    60 MHTTPDataSupplier& CWspCOTxData::RequestBodyData()
       
    61 	{
       
    62 	return *this;
       
    63 	}
       
    64 
       
    65 void CWspCOTxData::SetRequestDataL()
       
    66 	{
       
    67 	// Set the required session properties. Note - assume that the server 
       
    68 	// message size is at least the size of the server SDU size.
       
    69 	iRemainingSDUSpace		= iNegotiatedCapInfo.GetServerSDUSize();
       
    70 	if( iRemainingSDUSpace == 0 )
       
    71 		{
       
    72 		// SDU size is unlimited - set to highest value
       
    73 		iRemainingSDUSpace = KMaxTUint32;
       
    74 		}
       
    75 	iRemainingMessageSpace	= iNegotiatedCapInfo.GetServerMessageSize();
       
    76 	if( iRemainingMessageSpace != 0 )
       
    77 		{
       
    78 		// Message is not unlimited
       
    79 		iLimitedMessageSize = ETrue;
       
    80 		}
       
    81 	iSupportLDT				= iNegotiatedCapInfo.GetProtocolOptions() & ELargeDataTransfer;
       
    82 
       
    83 	// Get the request object from the transaction
       
    84 	RHTTPTransaction trans	= ProtTrans().Transaction();
       
    85 	RHTTPRequest request	= trans.Request();
       
    86 
       
    87 	// Encode the headers - this checks for trailer headers. Trailer header are 
       
    88 	// only allowed if LDT is supported in the session.
       
    89 	SetHeaderDataL(request);
       
    90 
       
    91 	// Headers encoded ok? Check for a request body.
       
    92 	if( request.HasBody() )
       
    93 		{
       
    94 		// Set the remaining server SDU space property
       
    95 		THTTPHdrVal remainingSDUProperty = iRemainingSDUSpace;
       
    96 		SetSessionPropertyL(HTTP::EWspRemainingSDUSize, remainingSDUProperty);
       
    97 
       
    98 		// Set the body data - this will set the iRequestComplete flag
       
    99 		SetBodyDataL(*request.Body());
       
   100 		}
       
   101 	else
       
   102 		{
       
   103 		// If there is no body request then the function OverallDataSize will 
       
   104 		// return zero. The transport handler should not try to access the data.
       
   105 		iRequestComplete = ETrue;
       
   106 
       
   107 		// Reset the body data
       
   108 		iBodyData = KNullDesC8().AllocL();
       
   109 
       
   110 		// Flag that there is some body data, although of zero length
       
   111 		iGotBodyData = ETrue;
       
   112 
       
   113 		// Set state so that primitive is sent
       
   114 		iState = EDone;
       
   115 		}
       
   116 	// Tell oberver what to do.
       
   117 	DecideObserverAction();
       
   118 
       
   119 	// Set the remaining message size session property
       
   120 	THTTPHdrVal remainingMessageSizeProperty = iRemainingMessageSpace;
       
   121 	SetSessionPropertyL(HTTP::EWspRemainingMessageSize, remainingMessageSizeProperty);
       
   122 	}
       
   123 
       
   124 void CWspCOTxData::NotifyMoreRequestData()
       
   125 	{
       
   126 	__ASSERT_DEBUG( iState == EWaitForMoreData, Panic(KWspPanicTxDataInInvalidState) );
       
   127 
       
   128 	// Get the next data part from the client.
       
   129 	iRequestComplete = iBodyDataSupplier->GetNextDataPart(iDataPart);
       
   130 
       
   131 	// Was the overall data size known?
       
   132 	if( iOverallDataSize == -1 )
       
   133 		{
       
   134 		TInt dataSize = iDataPart.Length();
       
   135 
       
   136 		// Is the message size limited?
       
   137 		if( iLimitedMessageSize )
       
   138 			{
       
   139 			// Check to see if this new load of data has blown the message size. 
       
   140 			// Need to include trailer info too.
       
   141 			// NOTE - if LDT is not supported, this will be reflected in the message
       
   142 			// size being the same as the SDU size.
       
   143 			if( dataSize + iTrailerInfoLength > iRemainingMessageSpace )
       
   144 				{
       
   145 				// Too much data - abort the request.
       
   146 				// NOTE - this could delete this object, so ensure that accessing data
       
   147 				// members is not done after this call.
       
   148 				iObserver.AbortInvoke();
       
   149 				return;
       
   150 				}
       
   151 			}
       
   152 		// Need to check to see if the SDU size is unlimited
       
   153 		if( iNegotiatedCapInfo.GetServerSDUSize() == 0 )
       
   154 			{
       
   155 			// It is so calculate a sensible buffer size
       
   156 			TPtr8 buf = iBodyData->Des();
       
   157 			TInt totalDataSize = dataSize + buf.Length();
       
   158 			if( totalDataSize > buf.MaxLength() )
       
   159 				{
       
   160 				TInt bufferSize = ((totalDataSize / KWspTxDataDefaultBufferSize) + 1) * KWspTxDataDefaultBufferSize;
       
   161 
       
   162 				// Reallocate to a larger buffer
       
   163 				iBodyData = iBodyData->ReAlloc(bufferSize);
       
   164 				
       
   165 				// Was there enough memory?
       
   166 				if( iBodyData == NULL )
       
   167 					{
       
   168 					// Too much data - abort the request.
       
   169 					// NOTE - this could delete this object, so ensure that accessing data
       
   170 					// members is not done after this call.
       
   171 					iObserver.AbortInvoke();
       
   172 					return;
       
   173 					}
       
   174 				}
       
   175 			}
       
   176 		}
       
   177 	// Update the body data
       
   178 	UpdateBodyData();
       
   179 
       
   180 	// Send trailer headers?
       
   181 	if( iState == EDone && iHasTrailer )
       
   182 		{
       
   183 		// Cannot send trailer in the first SDU - has the header data been 
       
   184 		// cleared? This implies that at least one SDU has been sent.
       
   185 		if( iHeaderData->Des().Length() == 0 )
       
   186 			{
       
   187 			// Ensure that they fit in either this SDU or the message as a whole.
       
   188 			CheckTrailer();
       
   189 			}
       
   190 		else
       
   191 			{
       
   192 			// This is the first SDU - send trailers in the next one, if they fit.
       
   193 			if( iLimitedMessageSize && iRemainingMessageSpace - iRemainingSDUSpace < iTrailerInfoLength )
       
   194 				{
       
   195 				// Not enough space for the trailers - abort the method.
       
   196 				iState = EAbortMethod;
       
   197 				}
       
   198 			}
       
   199 		}
       
   200 	// Tell oberver what to do.
       
   201 	DecideObserverAction();
       
   202 	}
       
   203 
       
   204 void CWspCOTxData::ReceivedCnf()
       
   205 	{
       
   206 	__ASSERT_DEBUG( iState == EDone || iState == EGotMoreData, Panic(KWspPanicTxDataInInvalidState) );
       
   207 
       
   208 	// Zero the encoded headers buffer
       
   209 	iHeaderData->Des().Zero();
       
   210 
       
   211 	// Check to see if the request is done.
       
   212 	if( iState == EDone && !iHasTrailer )
       
   213 		{
       
   214 		// Client has sent all the request data and this has all been sent in 
       
   215 		// the SDUs - done!
       
   216 		iState = EIdle;
       
   217 
       
   218 		// Was this a POST-type SDU?
       
   219 		if( iBodyDataSupplier )
       
   220 			{
       
   221 			// Tell client to release the last data chunk.
       
   222 			iBodyDataSupplier->ReleaseData();
       
   223 			}
       
   224 
       
   225 		// Release resources here
       
   226 		Cleanup();
       
   227 		}
       
   228 	else
       
   229 		{
       
   230 		// Set the remaining SDU space
       
   231 		iRemainingSDUSpace = iNegotiatedCapInfo.GetServerSDUSize();
       
   232 		if( iRemainingSDUSpace == 0 )
       
   233 			{
       
   234 			// SDU size is unlimited - set to highest value
       
   235 			iRemainingSDUSpace = KMaxTUint32;
       
   236 			}
       
   237 		if( iLimitedMessageSize && iRemainingSDUSpace > iRemainingMessageSpace )
       
   238 			{
       
   239 			// The remaining message space is less than the SDU size - adjust the 
       
   240 			// remaining SDU space.
       
   241 			iRemainingSDUSpace = iRemainingMessageSpace;
       
   242 			}
       
   243 
       
   244 		// Update the body data
       
   245 		UpdateBodyData();
       
   246 
       
   247 		// Send trailer headers?
       
   248 		if( iState == EDone && iHasTrailer )
       
   249 			{
       
   250 			// Ensure that they fit in either this SDU or the message as a whole.
       
   251 			CheckTrailer();
       
   252 			}
       
   253 
       
   254 		// Tell oberver what to do.
       
   255 		DecideObserverAction();
       
   256 		}
       
   257 	}
       
   258 
       
   259 void CWspCOTxData::SetHeaderDataL(RHTTPRequest aRequest)
       
   260 	{
       
   261 	// See how much space is required for URI and header info - initialise with
       
   262 	// type field length.
       
   263 	TUint32 infoLength = KPDUTypeFieldSize;
       
   264 
       
   265 	// Calculate length of uri info
       
   266 	TUint32 uriLength = aRequest.URI().UriDes().Length();
       
   267 	TUint32 uriInfoLength = CalculateUIntVarLength(uriLength) + uriLength;
       
   268 
       
   269 	// Check that the uri fits in the SDU
       
   270 	infoLength += uriInfoLength;
       
   271 	if( infoLength > iRemainingSDUSpace )
       
   272 		{
       
   273 		// Abort the method - SDU blown with just uri info!
       
   274 		User::Leave(KWspErrRequestTooBig);
       
   275 		}
       
   276 
       
   277 	// Get the encoded headers...
       
   278 	EncodeHeadersL(aRequest.GetHeaderCollection());
       
   279 
       
   280 	// Calculate the header info size - this depends on the method
       
   281 	TUint32 headersLength = iHeaderData->Des().Length();
       
   282 
       
   283 	switch( aRequest.Method().Index(RHTTPSession::GetTable()) )
       
   284    		{
       
   285 	case HTTP::EOPTIONS: case HTTP::EHEAD: case HTTP::EDELETE: case HTTP::ETRACE:
       
   286    	case HTTP::EGET:
       
   287    		{
       
   288 		// Nothing more to do for get-type PDU.
       
   289    		} break;
       
   290 	case HTTP::EPUT:
       
   291    	case HTTP::EPOST:
       
   292    		{
       
   293 		// Need to add the UIntVar representation of the headers length
       
   294 		TUint32 headerInfoLength = CalculateUIntVarLength(headersLength);
       
   295 		infoLength += headerInfoLength;
       
   296 		if( infoLength > iRemainingSDUSpace )
       
   297 			{
       
   298 			// Abort the method - SDU blown by the header length info!
       
   299 			User::Leave(KWspErrRequestTooBig);
       
   300 			}
       
   301    		} break;
       
   302    	default:
       
   303    		__ASSERT_DEBUG(0, Panic(KWspPanicBadMethodType));
       
   304    		break;
       
   305    		}
       
   306 	// Check to see if the headers fit into the SDU
       
   307 	infoLength += headersLength;
       
   308 	if( infoLength > iRemainingSDUSpace )
       
   309 		{
       
   310 		// Abort the method - SDU blown
       
   311 		User::Leave(KWspErrRequestTooBig);
       
   312 		}
       
   313 	// Update the remaining SDU and message space
       
   314 	iRemainingSDUSpace		-= infoLength;
       
   315 	if( iLimitedMessageSize )
       
   316 		iRemainingMessageSpace	-= infoLength;
       
   317 
       
   318 	// Are there trailer headers?
       
   319 	if( iHasTrailer )
       
   320 		{
       
   321 		// Only allowed if LDT supported
       
   322 		if( iSupportLDT )
       
   323 			{
       
   324 			if( iLimitedMessageSize )
       
   325 				{
       
   326 				// Trailers allowed - update message space
       
   327 				TUint32 trailerLength = iTrailerData->Des().Length();
       
   328 				iTrailerInfoLength = CalculateUIntVarLength(trailerLength) + trailerLength;
       
   329 
       
   330 				if( iLimitedMessageSize && iTrailerInfoLength > iRemainingMessageSpace )
       
   331 					{
       
   332 					// Abort the method - Message size is blown by the trailer 
       
   333 					// headers info!
       
   334 					User::Leave(KWspErrRequestTooBig);
       
   335 					}
       
   336 				}
       
   337 			}
       
   338 		else
       
   339 			{
       
   340 			// Leave - cannot do trailer headers if LDT not supported.
       
   341 			User::Leave(KWspErrTrailerHeadersNotExpected);
       
   342 			}
       
   343 		}
       
   344 	}
       
   345 
       
   346 void CWspCOTxData::EncodeHeadersL(RHTTPHeaders aHeaders)
       
   347 	{
       
   348 	// Is there a trailer header?
       
   349 	RStringPool stringPool = ProtTrans().Transaction().Session().StringPool();
       
   350 	THTTPHdrVal trailer;
       
   351 	TInt err = aHeaders.GetField(
       
   352 								stringPool.StringF(WSP::ETrailer, WSP::Table),
       
   353 								0,		// Zero index -> first part
       
   354 								trailer
       
   355 								);
       
   356 	iHasTrailer = (err == KErrNone);
       
   357 	CWspCOTransaction& wspTrans = STATIC_CAST(CWspCOTransaction&, ProtTrans());
       
   358 	if( iHasTrailer )
       
   359 		{
       
   360 		// Encode the header and trailer data
       
   361 		iHeaderData = wspTrans.GetWspHeaderUtils().EncodeNoTrailerHeadersL(stringPool, aHeaders, iTrailerData);
       
   362 		}
       
   363 	else
       
   364 		{
       
   365 		// Encode the header data
       
   366 		iHeaderData = wspTrans.GetWspHeaderUtils().EncodeHeadersL(stringPool, aHeaders);
       
   367 		}
       
   368 	}
       
   369 
       
   370 void CWspCOTxData::SetBodyDataL(MHTTPDataSupplier& aRequestBody)
       
   371 	{
       
   372 	__ASSERT_DEBUG( iBodyData == NULL, Panic(KWspPanicTxDataInInvalidState) );
       
   373 
       
   374 	// Store the body data supplier
       
   375 	iBodyDataSupplier = &aRequestBody;
       
   376 
       
   377 	// Set the overall data size
       
   378 	iOverallDataSize = iBodyDataSupplier->OverallDataSize();
       
   379 
       
   380 	// Is the data sized known?
       
   381 	if( iLimitedMessageSize && iOverallDataSize != -1 )
       
   382 		{
       
   383 		// Check to see if it will fit in the message, including trailer info.
       
   384 		// NOTE - if LDT is not supported, this will be reflected in the message
       
   385 		// size being the same as the SDU size.
       
   386 		if( iOverallDataSize + iTrailerInfoLength > iRemainingMessageSpace )
       
   387 			{
       
   388 			// Abort the method - Message size is blown by the request data.
       
   389 			User::Leave(KWspErrRequestTooBig);
       
   390 			}
       
   391 		}
       
   392 	// Get the data...
       
   393 	iRequestComplete = iBodyDataSupplier->GetNextDataPart(iDataPart);
       
   394 
       
   395 	if( iLimitedMessageSize && iOverallDataSize == -1 )
       
   396 		{
       
   397 		// Check to see if this data part exceeds the message space.
       
   398 		// NOTE - if LDT is not supported, this will be reflected in the message
       
   399 		// size being the same as the SDU size.
       
   400 		TInt dataSize = iDataPart.Length();
       
   401 		if( dataSize + iTrailerInfoLength > iRemainingMessageSpace )
       
   402 			{
       
   403 			// Abort the method - Message size is blown by the request data.
       
   404 			User::Leave(KWspErrRequestTooBig);
       
   405 			}
       
   406 		// Check to see if there are any more chunks
       
   407 		if( iRequestComplete )
       
   408 			{
       
   409 			// The overall data size is known
       
   410 			iOverallDataSize = dataSize;
       
   411 			}
       
   412 		}
       
   413 
       
   414 	// Create the buffer
       
   415 	TInt bufferSize = iNegotiatedCapInfo.GetServerSDUSize();
       
   416 
       
   417 	// Is the SDU size unlimited?
       
   418 	if( bufferSize == 0 )
       
   419 		{
       
   420 		// Is the overall data size known?
       
   421 		if( iOverallDataSize != -1 )
       
   422 			{
       
   423 			// Set buffer size to be the data size
       
   424 			bufferSize = iOverallDataSize;
       
   425 			}
       
   426 		else
       
   427 			{
       
   428 			// Get just enough for this chunk...
       
   429 			bufferSize = ((iDataPart.Length() / KWspTxDataDefaultBufferSize) + 1) * KWspTxDataDefaultBufferSize;
       
   430 			}
       
   431 		}
       
   432 	// Allocate space for the request data.
       
   433 	iBodyData = HBufC8::NewL(bufferSize);
       
   434 
       
   435 	// Update the body data
       
   436 	UpdateBodyData();
       
   437 	}
       
   438 
       
   439 void CWspCOTxData::UpdateBodyData()
       
   440 	{
       
   441 	__ASSERT_DEBUG( !iGotBodyData, Panic(KWspPanicTxDataInInvalidState) );
       
   442 
       
   443 	// The data buffer iBodyData has (at least) a max size of the SDU size. Need
       
   444 	// to copy enough data so that the SDU (and therefore the buffer) is not 
       
   445 	// exceeded. 
       
   446 	
       
   447 	// Does the given data part exceed the SDU?
       
   448 	TInt dataLength = iDataPart.Length();
       
   449 	TInt copyLength = dataLength;
       
   450 	if( STATIC_CAST(TUint32, dataLength) > iRemainingSDUSpace )
       
   451 		{
       
   452 		// Set the copy length to the remaining SDU space.
       
   453 		copyLength = iRemainingSDUSpace;
       
   454 		}
       
   455 
       
   456 	// Copy the required amount of data.
       
   457 	iBodyData->Des().Append(iDataPart.Left(copyLength));
       
   458 
       
   459 	// Save remaining data part for later.
       
   460 	iDataPart.Set(iDataPart.Right(dataLength - copyLength));
       
   461 
       
   462 	// Update the remaining SDU and message space.
       
   463 	iRemainingSDUSpace		-= copyLength;
       
   464 	if( iLimitedMessageSize )
       
   465 		iRemainingMessageSpace	-= copyLength;
       
   466 
       
   467 	// Update the state according to the request data state.
       
   468 	UpdateState();
       
   469 
       
   470 	// Check the state...
       
   471 	if( iState == EWaitForMoreData )
       
   472 		{
       
   473 		// Release the data from the client - need to get next batch.
       
   474 		iBodyDataSupplier->ReleaseData();
       
   475 		}
       
   476 	else
       
   477 		{
       
   478 		// Flag the fact that there is body data
       
   479 		iGotBodyData = ETrue;
       
   480 		}
       
   481 	}
       
   482 
       
   483 void CWspCOTxData::UpdateState()
       
   484 	{
       
   485 	// Possible scenarios;
       
   486 	// 1) The request is complete and the received data fits into a single SDU.
       
   487 	// ACTION - MoreData flag is False. State is EDone.
       
   488 	//
       
   489 	// 2) The request is complete and the received data requires subsequent SDUs.
       
   490 	// ACTION - MoreData flag is True. State is EGotMoreData.
       
   491 	//
       
   492 	// 3) The request is not complete and the received data does not fill the SDU.
       
   493 	// ACTION - Need to wait for the next bit of data. State is EWaitForMoreData.
       
   494 	//
       
   495 	// 4) The request is not complete and the received fills the SDU.
       
   496 	// ACTION - MoreData flag is True. Ensure request data given fits in the SDU. 
       
   497 	//			State is EGotMoreData.
       
   498 	
       
   499 	if( iRequestComplete )
       
   500 		{
       
   501 		// Possible scenarios 1, 2, 5, 6 and NOTE.
       
   502 		if( iDataPart.Length() == 0 )
       
   503 			{
       
   504 			// No more data to send - scenario 1.
       
   505 			iState = EDone;
       
   506 			}
       
   507 		else
       
   508 			{
       
   509 			// Need to send remaining request data later - scenario 2.
       
   510 			iState = EGotMoreData;
       
   511 			}
       
   512 		}
       
   513 	else
       
   514 		{
       
   515 		// Possible scenarios here are 3 and 4.
       
   516 		if( iRemainingSDUSpace == 0 )
       
   517 			{
       
   518 			// No space left in the SDU and need to send it - scenario 4.
       
   519 			iState = EGotMoreData;
       
   520 			}
       
   521 		else
       
   522 			{
       
   523 			// There is still space in the SDU. Need to wait for more data from
       
   524 			// the client - scenario 3.
       
   525 			iState = EWaitForMoreData;
       
   526 			}
       
   527 		}
       
   528 	}
       
   529 
       
   530 void CWspCOTxData::CheckTrailer()
       
   531 	{
       
   532 	// Do they fit in this SDU?
       
   533 	if( iLimitedMessageSize && iTrailerInfoLength > iRemainingSDUSpace )
       
   534 		{
       
   535 		// Trailers either do not fit in this SDU. Is there enough space 
       
   536 		// to send them?
       
   537 		if( iRemainingMessageSpace - iRemainingSDUSpace < iTrailerInfoLength )
       
   538 			{
       
   539 			// Not enough space for the trailers - abort the method.
       
   540 			iState = EAbortMethod;
       
   541 			}
       
   542 		}
       
   543 	else
       
   544 		{
       
   545 		// The trailer info fits into this SDU - update the header data.
       
   546 		delete iHeaderData;
       
   547 		iHeaderData		= iTrailerData;
       
   548 		iTrailerData	= NULL;
       
   549 
       
   550 		// Clear flag indicating that the trailers have yet to be sent.
       
   551 		iHasTrailer = EFalse;
       
   552 		}
       
   553 	}
       
   554 
       
   555 void CWspCOTxData::DecideObserverAction()
       
   556 	{
       
   557 	// Posible actions for the observer - 
       
   558 	// 1)	If the state is either EDone or EGotMoreData, then the observer 
       
   559 	//		needs to send a method primitive.
       
   560 	// 2)	If the state is EAbortMethod, then the observer needs to abort the
       
   561 	//		method.
       
   562 	// 3)	If the state is EWaitForMoreData, then the observe does nothing.
       
   563 
       
   564 	if( iState == EAbortMethod )
       
   565 		{
       
   566 		// Something has gone wrong - need to tell observer to abort the
       
   567 		// method.
       
   568 		// NOTE - this could delete this object, so ensure that accessing data
       
   569 		// members is not done after this call.
       
   570 		iObserver.AbortInvoke();
       
   571 		}
       
   572 	else if( iState != EWaitForMoreData )
       
   573 		{
       
   574 		// Update the remaining message space - remove the remaining space in
       
   575 		// this SDU.
       
   576 		if( iLimitedMessageSize )
       
   577 			iRemainingMessageSpace -= iRemainingSDUSpace;
       
   578 
       
   579 		// Tell observer to send a primitive
       
   580 		iObserver.SendInvokePrimitive();
       
   581 		}
       
   582 	}
       
   583 
       
   584 void CWspCOTxData::Cleanup()
       
   585 	{
       
   586 	delete iHeaderData;
       
   587 	iHeaderData		= NULL;
       
   588 	delete iBodyData;
       
   589 	iBodyData		= NULL;
       
   590 	delete iTrailerData;
       
   591 	iTrailerData	= NULL;
       
   592 	}
       
   593 
       
   594 void CWspCOTxData::SetSessionPropertyL(TInt aProperty, THTTPHdrVal aFieldValue)
       
   595 	{
       
   596 	RHTTPSession session			= ProtTrans().Transaction().Session();
       
   597 	RHTTPConnectionInfo	connInfo	= session.ConnectionInfo();
       
   598 	RStringPool stringPool			= session.StringPool();
       
   599 
       
   600 	connInfo.SetPropertyL(
       
   601 						 stringPool.StringF(aProperty, RHTTPSession::GetTable()), 
       
   602 						 aFieldValue
       
   603 						 );
       
   604 	}
       
   605 
       
   606 TInt CWspCOTxData::CalculateUIntVarLength(TUint32 aUint)
       
   607 	{
       
   608 	TUint8 size = 0; // maximum value is 5 with a 32 bit integer
       
   609 	TUint32 value = aUint;
       
   610 	do {
       
   611 		++size;
       
   612 		value >>= KUIntVarOctetShift; ; // shift by 7 bits.
       
   613 		} while (value>0);
       
   614 
       
   615 	return size;
       
   616 	}
       
   617 
       
   618 /*
       
   619  * Methods from MHTTPDataSupplier
       
   620  */
       
   621 
       
   622 TBool CWspCOTxData::GetNextDataPart(TPtrC8& aDataPart)
       
   623 	{
       
   624 	__ASSERT_DEBUG( iGotBodyData, Panic(KWspPanicNoRequestDataReceived) );
       
   625 
       
   626 	// Set the data part
       
   627 	aDataPart.Set(iBodyData->Des());
       
   628 
       
   629 	// Set the return value
       
   630 	TBool lastChunk = ETrue;
       
   631 	if( iState != EDone || iHasTrailer )
       
   632 		{
       
   633 		// All the current data has not been sent  - this is not the last chunk.
       
   634 		lastChunk = EFalse;
       
   635 		}
       
   636 	return lastChunk;
       
   637 	}
       
   638 
       
   639 void CWspCOTxData::ReleaseData()
       
   640 	{
       
   641 	__ASSERT_DEBUG( iGotBodyData, Panic(KWspPanicNoRequestDataReceived) );
       
   642 
       
   643 	// Clear the flag indicating that there is request data
       
   644 	iGotBodyData = EFalse;
       
   645 
       
   646 	// Zero the old body data.
       
   647 	TPtr8 buf = iBodyData->Des();
       
   648 	buf.Zero();
       
   649 	}
       
   650 	
       
   651 TInt CWspCOTxData::OverallDataSize()
       
   652 	{
       
   653 	return iOverallDataSize;
       
   654 	}
       
   655 
       
   656 TInt CWspCOTxData::Reset()
       
   657 	{
       
   658 	// This does nothing
       
   659 	return KErrNotFound;
       
   660 	}