--- a/cbs/CbsServer/ServerSrc/Ccbsreccollector.cpp Mon Aug 23 15:50:31 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,584 +0,0 @@
-/*
-* Copyright (c) 2003 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: This module contains the implementation of CCbsRecDecoder class
-* member functions.
-*
-* This class represents a collector, which stores pages of multipaged
-* messages. Complete messages are assembled and returned back to
-* the caller of CollectL() method.
-*
-* CCbsRecCollector stores message pages in a number of dynamic arrays.
-* If all but one page of a message are present in collector, and
-* the remaining page is received, the pages will be assembled and
-* the corresponding message chain deleted.
-*
-* The maximum number of incomplete messages stored in collector at once
-* is fixed and determined by KMaxCollectorMessages in CCbsRecCollector.cpp.
-*
-* CCbsRecCollector implements a circular list to contain message.
-* Each incomplete message occupies a slot in this list. If the list already
-* contains KMaxCollectorMessages messages, the next received multipaged
-* message will delete all received pages of the oldest message in list.
-*
-* On receival of a message page, the collector compares network information
-* (PLMN, LAC, CellId) of both messages to decide whether pages are of
-* the same message. In short, for pages to be of the same message
-* their network information have to meet the requirements set by the
-* geographical scope of the already collected page.
-* See ETSI GSM 03.41 for a detailed description.
-*
-*/
-
-
-// INCLUDE FILES
-#include "CbsServerPanic.h"
-#include "CCbsRecCollector.h"
-#include "CCbsRecMessage.h"
-#include "CCbsMessageFactory.h"
-#include "CCbsMessageCleanUpTimer.h"
-#include "CbsLogger.h"
-
-// CONSTANTS
-
-// Maximum number of pages in a single CB message.
-const TInt KMaxMessagePages = 15;
-
-// Maximum number of partial messages contained in the collector list.
-const TInt KMaxCollectorMessages = 10;
-
-// ================= MEMBER FUNCTIONS =======================
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::CCbsRecCollector
-// C++ default constructor can NOT contain any code, that
-// might leave.
-// -----------------------------------------------------------------------------
-//
-CCbsRecCollector::CCbsRecCollector( CCbsMessageFactory& aFactory )
- : iRootNodeIterator( 0 ),
- iFactory( aFactory )
- {
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::ConstructL
-// Symbian 2nd phase constructor can leave.
-// -----------------------------------------------------------------------------
-//
-void CCbsRecCollector::ConstructL()
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::ConstructL()");
-
- // initialize the root node array
- iRootNodeArray = new ( ELeave ) CArrayPtrFlat< CMessageBuffer >
- ( KMaxCollectorMessages );
- iRootNodeArray->SetReserveL( KMaxCollectorMessages );
- iMessageCleanupTimerArray = new ( ELeave ) CArrayPtrFlat< CCbsMessageCleanupTimer >
- ( KMaxCollectorMessages );
-
- for ( TInt i( 0 ); i < KMaxCollectorMessages; i++)
- {
- CMessageBuffer* array = new ( ELeave )
- CMessageBuffer( KMaxMessagePages );
- CleanupStack::PushL( array );
- iRootNodeArray->AppendL( array );
-
- CCbsMessageCleanupTimer* messageCleanUpTimer = CCbsMessageCleanupTimer::NewL( *this, *array );
- iMessageCleanupTimerArray->AppendL( messageCleanUpTimer );
-
- CleanupStack::Pop(); // array
- }
- CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::ConstructL()");
- }
-
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::NewL
-// Two-phased constructor.
-// -----------------------------------------------------------------------------
-//
- CCbsRecCollector* CCbsRecCollector::NewL( CCbsMessageFactory& aFactory )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::NewL()");
-
- CCbsRecCollector* self = new ( ELeave ) CCbsRecCollector( aFactory );
- CleanupStack::PushL( self );
- self->ConstructL();
- CleanupStack::Pop();
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::NewL()");
- return self;
- }
-
-// Destructor
-CCbsRecCollector::~CCbsRecCollector()
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::~CCbsRecCollector()");
-
- if ( iRootNodeArray )
- {
- TInt rootArrayLength( iRootNodeArray->Count() );
- for ( TInt i( 0 ); i < rootArrayLength; i++ )
- {
- iRootNodeArray->At( i )->ResetAndDestroy();
- }
- iRootNodeArray->ResetAndDestroy();
- delete iRootNodeArray;
- }
-
- if ( iMessageCleanupTimerArray )
- {
- iMessageCleanupTimerArray->ResetAndDestroy();
- delete iMessageCleanupTimerArray;
- }
-
- CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::~CCbsRecCollector()");
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::CollectL
-// Adds a message to the location pointed by iRootNodeIterator.
-//
-// Checks if all pages of message are present. If all pages
-// are present, sets aCompleted to ECbsMessageComplete,
-// combines message pages into a single message, destroys
-// pages from the list and returns the complete message
-// to caller in aMessage.
-
-// Algorithm:
-// 1. Check if other pages of this message exist in list.
-// (serial number and message identifier match)
-// 2. True: Check if the other messages in chain need
-// to be deleted. This is based on geographical scope
-// and network information.
-// Add this message to the correct message chain.
-// False: Add this message to the chain pointed
-// by the iRootNodeIterator.
-// 3. Seek out the position in the chosed message chain so that
-// the page number sequence remains ordered (1, 2, .., n)
-// 4. Add the page to the correct position in chain.
-// 5. Check if all pages of this message exist (number count).
-// 6. True: Combine message pages into a single message
-// and return this page to the caller. Set aCompleted
-// to ECbsMessageComplete.
-// False: Set aCompleted to ECbsMessageIncomplete.
-//
-// Note: Ownership of aMessage assumed. aMessage assumed to be
-// on cleanup stack.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CCbsMessage* CCbsRecCollector::CollectL(
- CCbsMessage* aMessage, TInt aMessageType )
- {
- CBSLOGSTRING("CBSSERVER: >>> CCbsRecCollector::CollectL()");
-
- // 1.
- CMessageBuffer* array = FindChainContainingPage( *aMessage );
- CCbsMessage* mergedMessage = NULL;
-
- if ( array )
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): array != NULL");
-
- // 2. (True), 3.
- __ASSERT_DEBUG( array->Count() > 0,
- CbsServerPanic( ECbsCollectorArrayEmpty ) );
-
- // Check geographical scope and network info to decide whether
- // existing pages in this chain should be deleted.
- TBool preserveExistingPages(
- CheckPageAreaInfoMatch( *aMessage, *array->At( 0 ) ) );
-
- CBSLOGSTRING2("CBSSERVER: CCbsRecCollector::CollectL(): preserveExistingPages: %d", preserveExistingPages );
-
- if ( preserveExistingPages )
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Adding msg to chain...");
- // aMessage is deleted, if it is a duplicate.
- AddMessageToChainL( aMessage, *array );
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Adding msg to chain OK.");
- }
- else
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain...");
- DeleteChainL( *array );
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain OK.");
- array->InsertL( 0, aMessage );
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Msg added to array.");
- }
- // aMessage, ownership transferred to msg chain or
- // aMessage has been deleted by AddMessageToChainL
- CleanupStack::Pop();
-
- // 5. Check if this chain contains all pages of the message.
- if ( AllPagesPresent( *array ) )
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): All pages present, merging...");
-
- // 6. merge creates a new copy of this message
- // leaves a pointer to msg to cleanup stack
- mergedMessage = MergePagesLC( *array ); // on CS
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Merging OK.");
-
- // we stop timer if its livecast message
- if ( aMessageType == ECbsMessageLivecast )
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Msg type == ECbsMessageLivecast, stopping timer.");
-
- TKeyArrayFix key(0, ECmpTUint16);
- TInt index;
- iRootNodeArray->Find( array, key, index);
- iMessageCleanupTimerArray->At( index )->StopTimer();
-
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Timer stopped.");
- }
-
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain...");
- DeleteChainL( *array );
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Deleting chain OK.");
-
- CleanupStack::Pop(); // mergedMessage
- }
- }
- else
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): array == NULL");
-
- // if message pagenumber does not start from 1, its not inserted to chain.
- if ( aMessage->ThisPage () == 1 )
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): aMessage->ThisPage () == 1");
-
- // 2. (False)
- // add this page as the first node in chain pointed by
- // iRootNodeIterator. Delete any pages contained in the chain
- // occuping this location first.
- array = iRootNodeArray->At( iRootNodeIterator );
- DeleteChainL( *array );
- array->InsertL( 0, aMessage );
- CleanupStack::Pop(); // aMessage, ownership transferred to msg chain.
- iRootNodeIterator++;
- // Return to the first message, if passed the
- // maximum messages.
- iRootNodeIterator %= KMaxCollectorMessages;
-
- if ( aMessageType == ECbsMessageLivecast )
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): aMessageType == ECbsMessageLivecast");
-
- // start timeout timer for livecast message
- TKeyArrayFix key(0, ECmpTUint16);
- TInt index;
- iRootNodeArray->Find( array, key, index);
- iMessageCleanupTimerArray->At( index )->StartTimer();
-
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): Timer started.");
- }
- }
- else
- {
- CBSLOGSTRING("CBSSERVER: CCbsRecCollector::CollectL(): CleanupStack::Pop()");
- CleanupStack::Pop();
- }
- }
- // mergedMessage == NULL if msg not completed,
- // otherwise return the complete message
- CBSLOGSTRING("CBSSERVER: <<< CCbsRecCollector::CollectL(), returning mergedMessage.");
-
- return mergedMessage;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::DeleteChainL
-// Deletes all message pages contained in aArray.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsRecCollector::DeleteChainL(
- CMessageBuffer& aArray ) const
- {
- aArray.ResetAndDestroy();
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::AllPagesPresent
-// Returns ETrue if all pages of the message of aArray are present.
-// Counts pages in message chain aArray and compares the result
-// against the total number of pages in the message.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TBool CCbsRecCollector::AllPagesPresent(
- const CMessageBuffer& aArray ) const
- {
- TBool result( ETrue );
- if ( TUint( aArray.Count() ) < aArray.At( 0 )->TotalPages() )
- {
- result = EFalse;
- }
-
- return result;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::MergePagesLC
-// Returns a complete message in aMessage.
-// Merges all pages in message chain aArray and returns
-// a pointer to the resulting assembled message. The pointer
-// is also left on the cleanup stack.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CCbsMessage* CCbsRecCollector::MergePagesLC(
- CMessageBuffer& aArray ) const
- {
- if ( aArray.Count() <= 0 )
- {
- User::Leave( KErrNotFound );
- }
- // Create a new message based on first message page in the chain.
- CCbsMessage* message = iFactory.CreateMessageL( *aArray.At( 0 ) );
-
- CleanupStack::PushL( message ); // left on cleanup stack
-
- // Traverse through the chain and merge contents.
- TInt length( 0 );
- TInt count( aArray.Count() );
-
- // If this is a Livecast message, use the 8-bit representation
- // (message not decoded).
- if ( message->IsLivecastMessage() )
- {
- for ( TInt j( 0 ); j < count; j++ )
- {
- length += aArray.At( j )->Contents8().Length();
- }
-
- __ASSERT_DEBUG( length >= 0, CbsServerPanic( ECbsCollectorMergeFailed ) );
-
- message->ReserveContentSize8L( length );
- count = aArray.Count();
-
- for ( TInt i( 1 ); i < count; i++ )
- {
- message->AppendContent8( aArray.At( i )->Contents8() );
- }
- }
- // Else use the 16-bit representation (message already decoded)
- else
- {
- for ( TInt j( 0 ); j < count; j++ )
- {
- length += aArray.At( j )->Contents().Length();
- }
-
- __ASSERT_DEBUG( length >= 0, CbsServerPanic( ECbsCollectorMergeFailed ) );
-
- message->ReserveContentSizeL( length );
- count = aArray.Count();
-
- // Append the rest of the pages (first page handled earlier)
- for ( TInt i( 1 ); i < count; i++ )
- {
- message->AppendContent( aArray.At( i )->Contents() );
- }
- }
- return message;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::FindChainContainingPage
-// Returns the buffer containing pages of same message.
-// Finds and returns a message chain which already contains pages
-// of aMessage's message. If none is found, NULL is returned.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-CMessageBuffer* CCbsRecCollector::FindChainContainingPage(
- const CCbsMessage& aMessage ) const
- {
- TBool quitSeek( EFalse );
- TInt seekIterator( 0 );
- TCbsDbMessageKey key( aMessage.Key() );
- TCbsDbTopicNumber topicNumber( aMessage.TopicNumber() );
- CMessageBuffer* array = NULL;
-
- // find out if the root array contains pages of this message
- while ( ( seekIterator < KMaxCollectorMessages ) && !quitSeek )
- {
- array = iRootNodeArray->At( seekIterator );
- if ( array->Count() > 0 )
- {
- CCbsMessage* msg = array->At( 0 );
- if ( key == msg->Key() && topicNumber == msg->TopicNumber() )
- {
- quitSeek = ETrue;
- }
- }
- seekIterator++;
- }
-
- if ( !quitSeek )
- {
- array = NULL;
- }
-
- return array;
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::AddMessageToChainL
-// Adds message page aMessage to the correct position in message chain aArray
-//
-// Message chains are ordered in ascending page number order.
-// Duplicate pages are not accepted.
-//
-// Ownership of aMessage is transferred to aArray, if the given page
-// hasn't been already collected. The given page will be deleted,
-// if it already exists in the chain.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-void CCbsRecCollector::AddMessageToChainL(
- CCbsMessage* aMessage,
- CMessageBuffer& aArray ) const
- {
- // Find out a position for this page in the chain.
- TInt chainLength( aArray.Count() );
- TInt insertPosition( -1 );
- TBool duplicate( EFalse );
-
- for ( TInt i( 0 ); ( i < chainLength ) && !duplicate; i++ )
- {
- CCbsMessage* msg = aArray.At( i );
- if ( insertPosition == -1 && msg->ThisPage() > aMessage->ThisPage() )
- {
- insertPosition = i;
- }
- else if ( msg->ThisPage() == aMessage->ThisPage() )
- {
- duplicate = ETrue; // This page has been already collected
- delete aMessage;
- }
- }
-
- // If this message was not a duplicate, add it to the chain
- if ( !duplicate )
- {
- if ( insertPosition == -1 )
- {
- aArray.AppendL( aMessage );
- }
- else
- {
- aArray.InsertL( insertPosition, aMessage );
- }
- }
- }
-
-// -----------------------------------------------------------------------------
-// CCbsRecCollector::CheckPageAreaInfoMatch
-// Checks if these pages can be merged. Returns ETrue, if merging is acceptable.
-//
-// Decision is based network information and geographical scope of
-// pages. Network information consists of cell id, location area code
-// and operator id.
-//
-// Assumption: aPage1 and aPage have identical message
-// identifiers and serial numbers.
-// Returns ETrue if the pages are of same message.
-// On EFalse previous pages should be deleted.
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TBool CCbsRecCollector::CheckPageAreaInfoMatch(
- const CCbsMessage& aPage1,
- const CCbsMessage& aPage2 ) const
- {
- RMobilePhone::TMobilePhoneNetworkInfoV1 info1;
- RMobilePhone::TMobilePhoneNetworkInfoV1 info2;
-
- aPage1.GetPLMN( info1 );
- aPage2.GetPLMN( info2 );
-
- TBool result( EFalse );
-
- if ( info1.iCountryCode == KRecMessageNoNetworkInfo ||
- info2.iCountryCode == KRecMessageNoNetworkInfo )
- {
- // Network info is unavailable; we must assume that the aPage1
- // is of the same page area as aPage2, so we return ETrue
- // unconditionally.
- result = ETrue;
- }
-
- if ( info1.iCountryCode == info2.iCountryCode &&
- info1.iNetworkId == info2.iNetworkId )
- // PLMN match
- {
- if ( aPage1.LAC() == aPage2.LAC() )
- // LAC match
- {
- if ( aPage1.CellId() == aPage2.CellId() )
- // Cell match
- {
- // Full network information match
- result = ETrue;
- }
- else
- {
- // Cell mismatch
- if ( aPage1.GeographicalScope() ==
- ECbsRecGeographicalScopeCell )
- // Cell id mismatch and scoped cell wide.
- {
- result = EFalse;
- }
- else
- // Cell id mismatch, not scoped cell wide.
- {
- result = ETrue;
- }
- }
- }
- else
- // LAC mismatch
- {
- if ( aPage1.GeographicalScope() ==
- ECbsRecGeographicalScopePLMN )
- {
- // LAC mismatch but scoped operator-wide
- result = ETrue;
- }
- else
- {
- // LAC mismatch and not scoped operator-wide
- result = EFalse;
- }
- }
- }
- else
- // PLMN mismatch
- {
- result = EFalse; // operator mismatch
- }
-
- return result;
- }
-
-
-// ================= OTHER EXPORTED FUNCTIONS ==============
-
-// End of File