⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 messagetransport.cpp

📁 Symbian OS C++ for Mobile Phones Volume 3 源码
💻 CPP
字号:
// Copyright (c) 2004 - 2007, Symbian Software Ltd. All rights reserved.

#include "messagetransport.h"


// -------- (de)allocation --------

CMessageTransport::CMessageTransport(MTransportObserver& aObserver)
/**
	This c'tor is defined to pass the supplied observer to the superclass.

	@param	aObserver		Observer to notify about transport events.
							This is managed by the CTransport superclass.
 */
:	CTransport(aObserver)
	{
	// empty.
	}

void CMessageTransport::ConstructL(const TDesC& aAddress, TBool aInitListen, TBool aObserverSession)
/**
	Second-phase constructor allocates resources required by this transport.
	Specifically, opens a session with the message server to listen for incoming
	messages.
	
	@param	aAddress		Remote device's address.  The format depends
							on the type of MTM.  E.g., it could be an email
							address or a string containing a telephone number.
	@param	aInitListen		If true, this object should start by listening
							for an incoming payload.  Otherwise, it should
							wait for its owner to send a payload to the remote
							device.
	@param	aObserverSession If true this transport should open a read-only session
							with the message server because it does not need to modify
							message entries directly.  Transports which use the sendas
							server can open a read-only session, whereas those which
							modify the message store directly should not.
 */
	{
	CTransport::ConstructL(aInitListen);

	iRemoteAddress = aAddress.AllocL();
	
	if (aObserverSession)
		iMsvSession = CMsvSession::OpenAsObserverL(*this);
	else
		iMsvSession = CMsvSession::OpenSyncL(*this);
	}

CMessageTransport::~CMessageTransport()
/**
	Closes session with message server and deletes own
	copy of remote device's address.
 */
	{
	delete iMsvSession;
	delete iRemoteAddress;
	}


// -------- implement CTransport --------

void CMessageTransport::DoSendPayloadL()
/**
	Implement CTransport by sending the payload in iPayload.
	The actual sending is delegated to a subclass.  This layer
	inserts a prefix so the payload can be identified by
	the receiving device.  This is required because transports
	can add content to the payload.  E.g., an ISP may append
	an advertisement or a disclaimer to an email.
*/
	{
	TRAN_LOG0(">CMessageTransport::DoSendPayloadL");
	TBuf<KMtPylPrefixLen + KPayloadLen> nativeBuf(KMtPylPrefix);
	nativeBuf.Append(iPayload);
	
	BuildAndSendMessageL(nativeBuf);
	TRAN_LOG0("<CMessageTransport::DoSendPayloadL");
	}

void CMessageTransport::DoLaunchRead()
/**
	Implement CTransport by waiting for an incoming message.
 */
	{
	// If iListening is set then HandleSessionEventL wil accept
	// incoming messages and complete this AO if the payload is found.

	iStatus = KRequestPending;
	// CTransport calls CActive::SetActive
	}


// -------- implement MMsvSessionObserver --------

void CMessageTransport::HandleSessionEventL(
	MMsvSessionObserver::TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3)
/**
	Implement MMsvSessionObserver by interpreting an incoming message as
	a move from the remote device.

	@param	aEvent			Type of messaging event.  This implementation is
							only interested in messages which are created (EMsvEntriesCreated)
							and changed (EMsvEntriesChanged).
	@param	aArg1			In this context, points to a CMsvEntrySelection object
							that describes the added or changed entries.
	@param	aArg2			In this contents, points to a TMsvId value that identifies
							the parent entry.
	@param	aArg3			Not used.
 */
	{
	(void) aArg3;
	TRAN_LOG2(">CMessageTransport::HandleSessionEventL,evt=%d,lst=%d", aEvent, iListening);
	
	// if not listening for response, then ignore this message
	if (! iListening)
		return;
	
	// ignore messages which are being sent or created
	TMsvId parentEntry = *reinterpret_cast<TMsvId*>(aArg2);
	if (parentEntry == KMsvGlobalOutBoxIndexEntryId || parentEntry == KMsvSentEntryId || parentEntry == KMsvDraftEntryId)
		return;
	
	// the messaging server issues a created event when it finds out about
	// an incoming message, and change events as it constructs it.
	if (!(aEvent == EMsvEntriesCreated || aEvent == EMsvEntriesChanged))
		return;

	const CMsvEntrySelection& entries = *reinterpret_cast<const CMsvEntrySelection*>(aArg1);
	TRAPD(r, HandleReceivedMessageL(entries));
	TRAN_LOG1("<CMessageTransport::HandleSessionEventL,hmr=%d", r);
	CompleteSelfIfError(r);
	}

void CMessageTransport::HandleReceivedMessageL(const CMsvEntrySelection& aEntries)
/**
	Helper function for HandleSessionEventL processes messages which has
	arrived in the inbox, looking for a response to the previous move.

	@param	aEntries		Entries which have been created or changed.
 */ 
	{
	TInt entryCount = aEntries.Count();
	for (TInt i = 0; i < entryCount; ++i)
		{
		TMsvId id = aEntries[i];

		TRAPD(r, HandleReceivedMessage2L(id));

		// if the current message is not the response then skip it
		if (r == KErrOandXMessageNotFound || r == KErrNotFound)
			continue;

		// leave if a real error such as OOM occured
		User::LeaveIfError(r);

		// found message so return immediately
		return;
		}

	// could not find message in selection.  This is not actually an error,
	// it just means the message has not been received yet.  Just wait for
	// HandleSessionEventL to be called again.
	}

void CMessageTransport::HandleReceivedMessage2L(TMsvId aEntryId)
/**
	Helper function for HandleReceivedMessageL.
	
	This function can "fail" if it detects an incorrect type of
	message, e.g. an email was received when looking for an SMS,
	or if there is a system-level failure, such as OOM.
	
	If the former case, this leaves with KErrOandXMessageNotFound
	which tells HandleReceivedMessageL to continue iterating through
	the messages.

	If the message is the right type but does not contain the payload
	this function leaves with KErrOandXMessageNotFound.

	If this function does find the payload then it completes this AO
	with KErrNone.

	@param	aEntryId		Identifier of created or changed message.
	@leave	KErrOandXMessageNotFound The supplied message was not
							the expected reply.
 */
	{
	TRAN_LOG1(">CMessageTransport::HandleReceivedMessage2L,entry=0x%x", aEntryId);
	CMsvEntry* msve = iMsvSession->GetEntryL(aEntryId);
	CleanupStack::PushL(msve);

	// the message must have an associated store which contains the
	// body text (SMS and email) or attachment (MMS.)
	const TMsvEntry& e = msve->Entry();
	if (!(e.Complete() && ShouldUseReceivedMtmUid(e.iMtm) && msve->HasStoreL()))
		User::Leave(KErrOandXMessageNotFound);
	
	CMsvStore* msvs = msve->ReadStoreL();
	CleanupStack::PushL(msvs);
	
	// extract the payload from body text or an attachment
	TRAN_LOG0("-CMessageTransport::HandleReceivedMessage2L,extracting");
	HBufC* plainText = ExtractPlainTextLC(*msvs);
	
	// search the body text for the payload prefix
	TInt prefixPos = plainText->Find(KMtPylPrefix);
	TRAN_LOG3("-CMessageTransport::HandleReceivedMessage2L,pfx=%d,plaintext=\"%S\"(%d)", prefixPos, plainText, plainText->Length());
	if ((prefixPos == KErrNotFound) || (prefixPos + KMtPylPrefixLen + KPayloadLen > plainText->Length()))
		User::Leave(KErrOandXMessageNotFound);
	
	// found the payload, so extract it into iPayload
	iPayload.Copy(plainText->Mid(prefixPos + KMtPylPrefixLen, KPayloadLen));
	CleanupStack::PopAndDestroy(3, msve);
	
	// complete this AO to notify the observer from CTransport::RunL
	CompleteSelf(KErrNone);
	}


// -------- partially implement CActive --------

void CMessageTransport::DoCancel()
/**
	Cancel any outstanding read.  Outstanding writes are queued from
	the subclass and so they have to be cancelled there.
 */
	{
	__MT_ASSERT(iListening, EMtDcNotListening);
	iListening = EFalse;
	
	CompleteSelf(KErrCancel);
	}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -