diff -r 000000000000 -r b16258d2340f applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspCORxData.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerpluginsandutils/httpprotocolplugins/WspProtocolHandler/CWspCORxData.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,310 @@ +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +// System includes +#include +#include +#include +#include + +// User includes +#include "mwspcorxdatacallback.h" +#include "cwspcotransaction.h" +#include "cwspheaderutils.h" +#include "wsppanic.h" + +// Class signature +#include "cwspcorxdata.h" + + + +CWspCORxData* CWspCORxData::NewL( + CProtTransaction& aTransaction, + MRxDataObserver& aObserver, + MWspCORxDataCallback& aMethodCallback + ) + { + return new (ELeave) CWspCORxData(aTransaction, aObserver, aMethodCallback); + } + +CWspCORxData::CWspCORxData( + CProtTransaction& aTransaction, + MRxDataObserver& aObserver, + MWspCORxDataCallback& aMethodCallback + ) +: CRxData(aTransaction, aObserver), iMethodCallback(aMethodCallback), iOverallDataSize(KErrNotFound) + { + } + +CWspCORxData::~CWspCORxData() + { + } + +void CWspCORxData::SetResponseDataL(const TDesC8& aResponseHeaders, MHTTPDataSupplier& aResponseBody, TBool aMoreResponseData) + { + // Store the more data flag + iMoreData = aMoreResponseData; + + // Set the header data + SetHeaderDataL(aResponseHeaders); + + // Set the body data + SetBodyDataL(aResponseBody); + + // Is the response complete? Is there any data to be passed to the client? + if( !iMoreData && iBodyData.Length() == 0 ) + { + // Have received the entire response - inform the client. + ResponseCompleteL(); + } + } + +void CWspCORxData::UpdateResponseDataL(const TDesC8& aTrailerHeaders, TBool aMoreResponseData) + { + __ASSERT_DEBUG( iMoreData, Panic(KWspPanicNotExpectingMoreResponseData) ); + + // Store the more data flag + iMoreData = aMoreResponseData; + + // Is there trailer headers? + if( aTrailerHeaders.Length() > 0 ) + { + // Is this the last primitive + if( iMoreData ) + { + // This is not the last primitive so no trailer headers allowed. + User::Leave(KWspErrTrailerHeadersNotExpected); + } + // Update the header data + UpdateHeaderDataL(aTrailerHeaders); + } + // Update the body data + UpdateBodyDataL(); + + // Is the response complete? Is there any data to be passed to the client? + if( !iMoreData && iBodyData.Length() == 0 ) + { + // Have received the entire response - inform the client. + ResponseCompleteL(); + } + } + +void CWspCORxData::SetHeaderDataL(const TDesC8& aResponseHeaders) + { + // Was any header data received in this primitive. + if( aResponseHeaders.Length() > 0 ) + { + // Segment the header data into the separate header fields in the response + // object's headers. + RHTTPTransaction trans = iProtTrans->Transaction(); + RHTTPHeaders headers = trans.Response().GetHeaderCollection(); + STATIC_CAST(CWspCOTransaction*, + iProtTrans)->GetWspHeaderUtils().DecodeReplyHeadersL( + trans.Session().StringPool(), + aResponseHeaders, + headers + ); + } + // Inform the client that all the response headers have been received + RHTTPTransaction tr = iProtTrans->Transaction(); + tr.SendEventL( + THTTPEvent::EGotResponseHeaders, + THTTPEvent::EIncoming, + THTTPFilterHandle(THTTPFilterHandle::EProtocolHandler) + ); + } + +void CWspCORxData::SetBodyDataL(MHTTPDataSupplier& aResponseBody) + { + __ASSERT_DEBUG( !iGotBodyData, Panic(KWspPanicRxDataObjectNotReset) ); + + // Store the body data supplier + iBodyDataSupplier = &aResponseBody; + + // Update the overall data size + iOverallDataSize = iBodyDataSupplier->OverallDataSize(); + + // Add the body data supplier to the response object + iProtTrans->Transaction().Response().SetBody(*this); + + // Get the data... + UpdateBodyDataL(); + } + +void CWspCORxData::UpdateHeaderDataL(const TDesC8& aTrailerHeaders) + { + // This is the last S-MethodResultData primitive and there is header data - + // these are probably Trailer Headers. + + // Segment the header data into the separate header fields in the response + // object's headers. + RHTTPTransaction trans = iProtTrans->Transaction(); + RHTTPHeaders headers = trans.Response().GetHeaderCollection(); + STATIC_CAST(CWspCOTransaction*, + iProtTrans)->GetWspHeaderUtils().DecodeHeadersL( + trans.Session().StringPool(), + aTrailerHeaders, + headers + ); + iHasTrailer = ETrue; + } + +void CWspCORxData::UpdateBodyDataL() + { + __ASSERT_DEBUG( !iGotBodyData, Panic(KWspPanicResponseDataNotReleased) ); + __ASSERT_DEBUG( iBodyDataSupplier, Panic(KWspPanicNoResponseDataReceived) ); + + // Is there more data for this SDU? + iLastChunk = iBodyDataSupplier->GetNextDataPart(iBodyData); + + // Check to see there is some data + if( iBodyData.Length() == 0 ) + { + // Are there more chunks? Keep trying to there is some data.. + while( !iLastChunk && iBodyData.Length() == 0 ) + { + // Release the data in the body data supplier + iBodyDataSupplier->ReleaseData(); + + // Get the next chunk + iLastChunk = iBodyDataSupplier->GetNextDataPart(iBodyData); + } + // Was some data received? + if( iBodyData.Length() == 0 ) + { + // Release the data in the body data supplier + iBodyDataSupplier->ReleaseData(); + + // No body data received - is this the last primitive? It is possible + // to have no body data if the last primitive had the trailer headers + // only. + if( iMoreData ) + { + // Something has gone wrong - more data expected, but none sent in + // this SDU. Response must be corrupt. + User::Leave(KWspErrExpectingBodyData); + } + // Inform method callback to send the response to the primitive + iMethodCallback.SendResponsePrimitive(); + + // Nothing more to do + return; + } + } + // Set the flag to indicate that there is some response body data + iGotBodyData = ETrue; + + // Inform the client that there is some (more) response data. + RHTTPTransaction tr = iProtTrans->Transaction(); + tr.SendEventL( + THTTPEvent::EGotResponseBodyData, + THTTPEvent::EIncoming, + THTTPFilterHandle(THTTPFilterHandle::EProtocolHandler) + ); + } + +void CWspCORxData::ResponseCompleteL() + { + if( iHasTrailer ) + { + // Inform the client that there are trailer headers + RHTTPTransaction tr = iProtTrans->Transaction(); + tr.SendEventL( + THTTPEvent::EGotResponseTrailerHeaders, + THTTPEvent::EIncoming, + THTTPFilterHandle(THTTPFilterHandle::EProtocolHandler) + ); + iHasTrailer = EFalse; + } + // Tell the observer that the response is complete - this object will + // be deleted by this call, so is the last thing to be done. + iObserver->SetStatusL(*this, THTTPEvent::EResponseComplete); + } + +/* + * Methods from CRxData + */ + +void CWspCORxData::ResetRxData() + { + User::Panic(KWspPanicCategory, KErrNotSupported); + } + +/* + * Methods from MHTTPDataSupplier + */ + +TBool CWspCORxData::GetNextDataPart(TPtrC8& aDataPart) + { + __ASSERT_DEBUG( iGotBodyData, Panic(KWspPanicNoResponseDataReceived) ); + + // Set the data part to the given chunk. + aDataPart.Set(iBodyData); + + // Set the return value + return (iLastChunk && !iMoreData); + } + +void CWspCORxData::ReleaseData() + { + __ASSERT_DEBUG( iGotBodyData, Panic(KWspPanicNoResponseDataReceived) ); + + // Release the data in the body data supplier + iBodyDataSupplier->ReleaseData(); + + // Clear flag that indicates that there is a current data part. + iGotBodyData = EFalse; + + // Has all the data for this SDU been passed to the client? + TInt error = KErrNone; + if( iLastChunk ) + { + // Ok, all the response data has been received and the client has been + // passed all of it - it has just released the last batch. Inform method + // callback to send the response to the primitive + iMethodCallback.SendResponsePrimitive(); + + // Are there subsequent S-MethodResultData primitives to follow? + if( !iMoreData ) + { + // No, have received all data from server - inform observer that the + // response is complete. + TRAP(error, ResponseCompleteL()); + } + } + else + { + // No, data supplier still has got more - go get it. + TRAP(error, UpdateBodyDataL()); + } + // Any problems...? + if( error != KErrNone ) + { + // Could not send event - need to abort the method + iMethodCallback.AbortResponse(); + } + } + +TInt CWspCORxData::OverallDataSize() + { + return iOverallDataSize; + } + +TInt CWspCORxData::Reset() + { + __ASSERT_DEBUG( iBodyDataSupplier, Panic(KWspPanicNoResponseDataReceived) ); + + return iBodyDataSupplier->Reset(); + }