applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspCORxData.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 <http/framework/mrxdataobserver.h>
       
    18 #include <http/mhttpdatasupplier.h>
       
    19 #include <http/rhttptransaction.h>
       
    20 #include <wsperror.h>
       
    21 
       
    22 // User includes
       
    23 #include "mwspcorxdatacallback.h"
       
    24 #include "cwspcotransaction.h"
       
    25 #include "cwspheaderutils.h"
       
    26 #include "wsppanic.h"
       
    27 
       
    28 // Class signature
       
    29 #include "cwspcorxdata.h"
       
    30 
       
    31 
       
    32 
       
    33 CWspCORxData* CWspCORxData::NewL(
       
    34 								CProtTransaction&		aTransaction, 
       
    35 								MRxDataObserver&		aObserver, 
       
    36 								MWspCORxDataCallback&	aMethodCallback
       
    37 								)
       
    38 	{
       
    39 	return new (ELeave) CWspCORxData(aTransaction, aObserver, aMethodCallback);
       
    40 	}
       
    41 
       
    42 CWspCORxData::CWspCORxData(
       
    43 						  CProtTransaction&			aTransaction, 
       
    44 						  MRxDataObserver&			aObserver, 
       
    45 						  MWspCORxDataCallback&		aMethodCallback
       
    46 						  )
       
    47 : CRxData(aTransaction, aObserver), iMethodCallback(aMethodCallback), iOverallDataSize(KErrNotFound)
       
    48 	{
       
    49 	}
       
    50 
       
    51 CWspCORxData::~CWspCORxData()
       
    52 	{
       
    53 	}
       
    54 
       
    55 void CWspCORxData::SetResponseDataL(const TDesC8& aResponseHeaders, MHTTPDataSupplier& aResponseBody, TBool aMoreResponseData)
       
    56 	{
       
    57 	// Store the more data flag
       
    58 	iMoreData = aMoreResponseData;
       
    59 
       
    60 	// Set the header data
       
    61 	SetHeaderDataL(aResponseHeaders);
       
    62 
       
    63 	// Set the body data
       
    64 	SetBodyDataL(aResponseBody);
       
    65 	
       
    66 	// Is the response complete? Is there any data to be passed to the client?
       
    67 	if( !iMoreData && iBodyData.Length() == 0 )
       
    68 		{
       
    69 		// Have received the entire response - inform the client.
       
    70 		ResponseCompleteL();
       
    71 		}
       
    72 	}
       
    73 
       
    74 void CWspCORxData::UpdateResponseDataL(const TDesC8& aTrailerHeaders, TBool aMoreResponseData)
       
    75 	{
       
    76 	__ASSERT_DEBUG( iMoreData, Panic(KWspPanicNotExpectingMoreResponseData) );
       
    77 
       
    78 	// Store the more data flag
       
    79 	iMoreData = aMoreResponseData;
       
    80 
       
    81 	// Is there trailer headers?
       
    82 	if( aTrailerHeaders.Length() > 0 )
       
    83 		{
       
    84 		// Is this the last primitive
       
    85 		if( iMoreData )
       
    86 			{
       
    87 			// This is not the last primitive so no trailer headers allowed.
       
    88 			User::Leave(KWspErrTrailerHeadersNotExpected);
       
    89 			}
       
    90 		// Update the header data
       
    91 		UpdateHeaderDataL(aTrailerHeaders);
       
    92 		}
       
    93 	// Update the body data
       
    94 	UpdateBodyDataL();
       
    95 
       
    96 	// Is the response complete? Is there any data to be passed to the client?
       
    97 	if( !iMoreData && iBodyData.Length() == 0 )
       
    98 		{
       
    99 		// Have received the entire response - inform the client.
       
   100 		ResponseCompleteL();
       
   101 		}
       
   102 	}
       
   103 
       
   104 void CWspCORxData::SetHeaderDataL(const TDesC8& aResponseHeaders)
       
   105 	{
       
   106 	// Was any header data received in this primitive.
       
   107 	if( aResponseHeaders.Length() > 0 )
       
   108 		{
       
   109 		// Segment the header data into the separate header fields in the response
       
   110 		// object's headers.
       
   111 		RHTTPTransaction trans	= iProtTrans->Transaction();
       
   112 		RHTTPHeaders headers	= trans.Response().GetHeaderCollection();
       
   113 		STATIC_CAST(CWspCOTransaction*, 
       
   114 					iProtTrans)->GetWspHeaderUtils().DecodeReplyHeadersL(
       
   115 																		trans.Session().StringPool(),
       
   116 																		aResponseHeaders,
       
   117 																		headers
       
   118 																		);
       
   119 		}
       
   120 	// Inform the client that all the response headers have been received
       
   121 	RHTTPTransaction tr = iProtTrans->Transaction();
       
   122 	tr.SendEventL(
       
   123 				 THTTPEvent::EGotResponseHeaders,
       
   124 				 THTTPEvent::EIncoming, 
       
   125 				 THTTPFilterHandle(THTTPFilterHandle::EProtocolHandler)
       
   126 				 );
       
   127 	}
       
   128 
       
   129 void CWspCORxData::SetBodyDataL(MHTTPDataSupplier& aResponseBody)
       
   130 	{
       
   131 	__ASSERT_DEBUG( !iGotBodyData, Panic(KWspPanicRxDataObjectNotReset) );
       
   132 
       
   133 	// Store the body data supplier
       
   134 	iBodyDataSupplier = &aResponseBody;
       
   135 
       
   136 	// Update the overall data size
       
   137 	iOverallDataSize = iBodyDataSupplier->OverallDataSize();
       
   138 
       
   139    	// Add the body data supplier to the response object
       
   140    	iProtTrans->Transaction().Response().SetBody(*this);
       
   141 
       
   142 	// Get the data...
       
   143 	UpdateBodyDataL();
       
   144 	}
       
   145 
       
   146 void CWspCORxData::UpdateHeaderDataL(const TDesC8& aTrailerHeaders)
       
   147 	{
       
   148 	// This is the last S-MethodResultData primitive and there is header data -
       
   149 	// these are probably Trailer Headers.
       
   150 
       
   151 	// Segment the header data into the separate header fields in the response
       
   152 	// object's headers.
       
   153 	RHTTPTransaction trans	= iProtTrans->Transaction();
       
   154 	RHTTPHeaders headers	= trans.Response().GetHeaderCollection();
       
   155 	STATIC_CAST(CWspCOTransaction*, 
       
   156 				iProtTrans)->GetWspHeaderUtils().DecodeHeadersL(
       
   157 															   trans.Session().StringPool(),
       
   158 															   aTrailerHeaders,
       
   159 															   headers
       
   160 															   );
       
   161 	iHasTrailer = ETrue;
       
   162 	}
       
   163 
       
   164 void CWspCORxData::UpdateBodyDataL()
       
   165 	{
       
   166 	__ASSERT_DEBUG( !iGotBodyData, Panic(KWspPanicResponseDataNotReleased) );
       
   167 	__ASSERT_DEBUG( iBodyDataSupplier, Panic(KWspPanicNoResponseDataReceived) );
       
   168 
       
   169 	// Is there more data for this SDU?
       
   170 	iLastChunk = iBodyDataSupplier->GetNextDataPart(iBodyData);
       
   171 
       
   172 	// Check to see there is some data
       
   173 	if( iBodyData.Length() == 0 )
       
   174 		{
       
   175 		// Are there more chunks? Keep trying to there is some data..
       
   176 		while( !iLastChunk && iBodyData.Length() == 0 )
       
   177 			{
       
   178 			// Release the data in the body data supplier
       
   179 			iBodyDataSupplier->ReleaseData();
       
   180 
       
   181 			// Get the next chunk
       
   182 			iLastChunk = iBodyDataSupplier->GetNextDataPart(iBodyData);
       
   183 			}
       
   184 		// Was some data received?
       
   185 		if( iBodyData.Length() == 0 )
       
   186 			{
       
   187 			// Release the data in the body data supplier
       
   188 			iBodyDataSupplier->ReleaseData();
       
   189 
       
   190 			// No body data received - is this the last primitive? It is possible
       
   191 			// to have no body data if the last primitive had the trailer headers
       
   192 			// only.
       
   193 			if( iMoreData )
       
   194 				{
       
   195 				// Something has gone wrong - more data expected, but none sent in 
       
   196 				// this SDU. Response must be corrupt.
       
   197 				User::Leave(KWspErrExpectingBodyData);
       
   198 				}
       
   199 			// Inform method callback to send the response to the primitive
       
   200 			iMethodCallback.SendResponsePrimitive();
       
   201 
       
   202 			// Nothing more to do
       
   203 			return;
       
   204 			}
       
   205 		}
       
   206 	// Set the flag to indicate that there is some response body data
       
   207 	iGotBodyData = ETrue;
       
   208 
       
   209 	// Inform the client that there is some (more) response data.
       
   210 	RHTTPTransaction tr = iProtTrans->Transaction();
       
   211 	tr.SendEventL(
       
   212 				 THTTPEvent::EGotResponseBodyData,
       
   213 				 THTTPEvent::EIncoming, 
       
   214 				 THTTPFilterHandle(THTTPFilterHandle::EProtocolHandler)
       
   215 				 );
       
   216 	}
       
   217 
       
   218 void CWspCORxData::ResponseCompleteL()
       
   219 	{
       
   220 	if( iHasTrailer )
       
   221 		{
       
   222 		// Inform the client that there are trailer headers
       
   223 		RHTTPTransaction tr = iProtTrans->Transaction();
       
   224 		tr.SendEventL(
       
   225 					 THTTPEvent::EGotResponseTrailerHeaders,
       
   226 					 THTTPEvent::EIncoming, 
       
   227 					 THTTPFilterHandle(THTTPFilterHandle::EProtocolHandler)
       
   228 					 );
       
   229 		iHasTrailer = EFalse;
       
   230 		}
       
   231 	// Tell the observer that the response is complete - this object will
       
   232 	// be deleted by this call, so is the last thing to be done.
       
   233 	iObserver->SetStatusL(*this, THTTPEvent::EResponseComplete);
       
   234 	}
       
   235 
       
   236 /*
       
   237  * Methods from CRxData
       
   238  */
       
   239 
       
   240 void CWspCORxData::ResetRxData()
       
   241 	{
       
   242 	User::Panic(KWspPanicCategory, KErrNotSupported);	
       
   243 	}
       
   244 
       
   245 /*
       
   246  * Methods from MHTTPDataSupplier
       
   247  */
       
   248 
       
   249 TBool CWspCORxData::GetNextDataPart(TPtrC8& aDataPart)
       
   250 	{
       
   251 	__ASSERT_DEBUG( iGotBodyData, Panic(KWspPanicNoResponseDataReceived) );
       
   252 
       
   253 	// Set the data part to the given chunk.
       
   254 	aDataPart.Set(iBodyData);
       
   255 
       
   256 	// Set the return value
       
   257 	return (iLastChunk && !iMoreData);
       
   258 	}
       
   259 
       
   260 void CWspCORxData::ReleaseData()
       
   261 	{
       
   262 	__ASSERT_DEBUG( iGotBodyData, Panic(KWspPanicNoResponseDataReceived) );
       
   263 
       
   264 	// Release the data in the body data supplier
       
   265 	iBodyDataSupplier->ReleaseData();
       
   266 
       
   267 	// Clear flag that indicates that there is a current data part.
       
   268 	iGotBodyData = EFalse;
       
   269 
       
   270 	// Has all the data for this SDU been passed to the client?
       
   271 	TInt error = KErrNone;
       
   272 	if( iLastChunk )
       
   273 		{
       
   274 		// Ok, all the response data has been received and the client has been 
       
   275 		// passed all of it - it has just released the last batch. Inform method
       
   276 		// callback to send the response to the primitive
       
   277 		iMethodCallback.SendResponsePrimitive();
       
   278 
       
   279 		// Are there subsequent S-MethodResultData primitives to follow?
       
   280 		if( !iMoreData )
       
   281 			{
       
   282 			// No, have received all data from server - inform observer that the 
       
   283 			// response is complete.
       
   284 			TRAP(error, ResponseCompleteL());
       
   285 			}
       
   286 		}
       
   287 	else
       
   288 		{
       
   289 		// No, data supplier still has got more - go get it.
       
   290 		TRAP(error, UpdateBodyDataL());
       
   291 		}
       
   292 	// Any problems...?
       
   293 	if( error != KErrNone )
       
   294 		{
       
   295 		// Could not send event - need to abort the method
       
   296 		iMethodCallback.AbortResponse();
       
   297 		}
       
   298 	}
       
   299 	
       
   300 TInt CWspCORxData::OverallDataSize()
       
   301 	{
       
   302 	return iOverallDataSize;
       
   303 	}
       
   304 
       
   305 TInt CWspCORxData::Reset()
       
   306 	{
       
   307 	__ASSERT_DEBUG( iBodyDataSupplier, Panic(KWspPanicNoResponseDataReceived) );
       
   308 
       
   309 	return iBodyDataSupplier->Reset();
       
   310 	}