?? messagetransport.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 + -