sdkcreationmw/sdkruntimes/msgsimulation/MsgRelay/Src/MsgRelayDll.cpp
changeset 0 b26acd06ea60
equal deleted inserted replaced
-1:000000000000 0:b26acd06ea60
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 //  Include Files  
       
    21 
       
    22 #include <e32std.h>         // GLDEF_C
       
    23 #include <s32mem.h>     // RDesReadStream
       
    24 #include <Gsmumsg.h>	// CSmsMessage
       
    25 #include <gsmubuf.h>	// CSmsBuffer
       
    26 #include <smut.h>		// KUidMsgTypeSMS
       
    27 #include <msvuids.h>	// KUidMsvMessageEntry
       
    28 #include <smsclnt.h>	// CSmsClientMtm
       
    29 #include <mtclreg.h>	// CClientMtmRegistry
       
    30 #include <mtmuibas.h>	// CBaseMtmUi
       
    31 #include <txtrich.h>	// CRichText
       
    32 #include <smutset.h>	// CSmsSettings
       
    33 #include <smuthdr.h>	// CSmsHeader
       
    34 #include <e32property.h> // RProperty 
       
    35 #include "MsgRelay.h"
       
    36 
       
    37 static const TInt KMaxSubjectLength = 30;
       
    38 
       
    39 const TUid KPSUidIdleInformation = {0x102071C0};
       
    40 const TUint32 KTelephonyIdleStatus = 0x00000001;
       
    41 enum TPSTelephonyIdleStatus { EPSTelephonyNotIdle, EPSTelephonyIdle };
       
    42 const TUid KPSUidAiInformation = {0x102750F0}; // ActiveIdle2 SID
       
    43 const TUint KActiveIdleState = 0x00000002; // Contains one value from following emuneration 
       
    44 enum EPSActiveIdleState { EPSAiBackground = 0,EPSAiForeground, EPSAiNumberEntry };
       
    45 
       
    46 TVersion MessageRelayVersion = TVersion(1, 0, 0);
       
    47 
       
    48 /****************************************************************************
       
    49 *   CRelaySession
       
    50 *****************************************************************************
       
    51 *
       
    52 *
       
    53 *
       
    54 ****************************************************************************/
       
    55 /* Implements actual functionality for clients. */
       
    56 class CRelaySession : public CSession2
       
    57 {
       
    58 	CMessageRelay *iOwner;
       
    59 	
       
    60 	/* Is the session listening for messages. */
       
    61 	TBool iListening;
       
    62 
       
    63 	/* The port that is listened, if iListening is ETrue.
       
    64 	   Port 0 means that port is not specified. */
       
    65 	TUint iListenPort;
       
    66 
       
    67 	/* The message type that is listened. */
       
    68 	TMessageType iListenType;
       
    69 
       
    70 	/* Notifies new messages to client...*/
       
    71 	TRequestStatus *iListenStatus;
       
    72 
       
    73 	/* Used for message passing. */
       
    74 	RMessage2 iRcvMessage;
       
    75 
       
    76 	void ConstructL();
       
    77 
       
    78 	CRelaySession(CMessageRelay *aOwner);
       
    79 public:
       
    80 	
       
    81 	static CRelaySession *NewL(CMessageRelay *aOwner);
       
    82 	static CRelaySession *NewLC(CMessageRelay *aOwner);
       
    83 
       
    84 	~CRelaySession();
       
    85 
       
    86 	void ServiceL(const RMessage2& aMessage);
       
    87 
       
    88 	/* If message is accepted ETrue is returned, otherwise EFalse. 
       
    89 	   An accepted message is relayed to the client listening for the
       
    90 	   messages or to the system Inbox(if no port specified). */
       
    91 	TBool AcceptL(TPtr8 &aMessage, TUint aPort, TMessageType aType);
       
    92 
       
    93 	/* Returns ETrue, is the port is already listened for. */
       
    94 	TBool IsListening(TUint aPort, TMessageType aType);
       
    95 
       
    96 };
       
    97 
       
    98 CRelaySession::CRelaySession(CMessageRelay *aOwner) : 
       
    99 CSession2(),
       
   100 iOwner(aOwner),
       
   101 iListening(EFalse)
       
   102 	{
       
   103 
       
   104 	}
       
   105 	
       
   106 void CRelaySession::ConstructL()
       
   107 	{
       
   108 	
       
   109 	}
       
   110 		
       
   111 CRelaySession *CRelaySession::NewL(CMessageRelay *aOwner)
       
   112 	{
       
   113 	CRelaySession *self = CRelaySession::NewLC(aOwner);
       
   114 	CleanupStack::Pop();
       
   115 	return self;
       
   116 	}
       
   117 
       
   118 CRelaySession *CRelaySession::NewLC(CMessageRelay *aOwner)
       
   119 	{
       
   120 	CRelaySession *self = new (ELeave) CRelaySession(aOwner);
       
   121 	CleanupStack::PushL(self);
       
   122 	self->ConstructL();
       
   123 	return self;
       
   124 	}
       
   125 
       
   126 CRelaySession::~CRelaySession()
       
   127 	{
       
   128 	for( int i = 0; i < iOwner->iSessions->Count(); i++)
       
   129 		{
       
   130 		if( iOwner->iSessions->At( i ) == this)
       
   131 			{
       
   132 			iOwner->iSessions->Delete( i );
       
   133 			break;
       
   134 			}
       
   135 		}
       
   136 	}
       
   137 
       
   138 /* Returns ETrue, is the port is already listened for. */
       
   139 TBool CRelaySession::IsListening(TUint aPort, TMessageType aType)
       
   140 	{
       
   141 	if (iListening == EFalse)
       
   142 		return EFalse;
       
   143 
       
   144 	if (aType != iListenType)
       
   145 		return EFalse;
       
   146 
       
   147 	if (aPort != iListenPort)
       
   148 		return EFalse;
       
   149 
       
   150 	return ETrue;
       
   151 	}
       
   152 
       
   153 void CRelaySession::ServiceL(const RMessage2& aMessage)
       
   154 	{
       
   155 	HBufC8 *newMessage = NULL;
       
   156 	TMessageType type;
       
   157 	TUint port;
       
   158 	
       
   159 	switch (aMessage.Function())
       
   160 		{
       
   161 		case KNewMessage:
       
   162 			{
       
   163 			if (iOwner == NULL)
       
   164 				User::Leave(KErrNotReady);
       
   165 
       
   166 			if (iOwner->iWriter == NULL)
       
   167 				User::Leave(KErrNotReady);
       
   168 
       
   169 			newMessage = HBufC8::NewL(aMessage.Int0());
       
   170 			TPtr8 ptr(newMessage->Des());
       
   171 			aMessage.ReadL( 1, ptr ); 
       
   172 
       
   173 			type = (TMessageType)aMessage.Int2();
       
   174 			iOwner->iWriter->WriteMessageL(ptr, type);
       
   175 			
       
   176 			aMessage.Complete(KErrNone);	
       
   177 
       
   178 			delete newMessage;
       
   179 
       
   180 			break;
       
   181 			}
       
   182     case KReceive:
       
   183       
       
   184       if (iListening) {
       
   185         if (!iRcvMessage.IsNull()) {
       
   186           iRcvMessage.Complete(KErrCancel);
       
   187         }
       
   188         iRcvMessage = aMessage;
       
   189 			  iOwner->TraverseInboxL();
       
   190       }
       
   191       else {
       
   192         aMessage.Complete(KErrNotReady);
       
   193       }
       
   194       break;
       
   195     case KCancelReceive:
       
   196       if (!iRcvMessage.IsNull()) {
       
   197         iRcvMessage.Complete(KErrCancel);
       
   198       }
       
   199       aMessage.Complete(KErrNone);
       
   200       break;
       
   201 		case KStartListening:
       
   202 
       
   203 			if (iOwner == NULL)
       
   204 				User::Leave(KErrNotReady);
       
   205 
       
   206 			type = (TMessageType)aMessage.Int1();
       
   207 			port = (TUint)aMessage.Int2();
       
   208 
       
   209 			if (iOwner->IsAnyBodyListening(port, type) != EFalse)
       
   210 				{
       
   211 				aMessage.Complete(KErrInUse);
       
   212 				return;
       
   213 				}
       
   214 
       
   215 			iListenType = type;
       
   216 			iListenPort = port;
       
   217 			iListening = ETrue;
       
   218       aMessage.Complete(KErrNone);	    	
       
   219 			break;
       
   220 
       
   221 		case KStopListening:
       
   222 			iListening = EFalse;
       
   223       if (!iRcvMessage.IsNull()) {
       
   224         iRcvMessage.Complete(KErrCancel);
       
   225       }
       
   226 			aMessage.Complete(KErrNone);	
       
   227 			break;
       
   228 
       
   229 		default:
       
   230 			User::Leave(KErrNotSupported);
       
   231 		}
       
   232 
       
   233 	}
       
   234 
       
   235 /* If message is accepted ETrue is returned, otherwise EFalse. 
       
   236    An accepted message is relayed to the client listening for the
       
   237    messages. */
       
   238 TBool CRelaySession::AcceptL(TPtr8 &aMessage, TUint aPort, TMessageType aType)
       
   239 	{
       
   240 	if (IsListening(aPort, aType) == EFalse)
       
   241 		return EFalse;
       
   242 
       
   243 	/* Write data to client */
       
   244   if (!iRcvMessage.IsNull()) {
       
   245     iRcvMessage.WriteL(0, aMessage);
       
   246     iRcvMessage.Complete(KErrNone);
       
   247   }
       
   248   
       
   249   return ETrue;
       
   250 	}
       
   251 
       
   252 /****************************************************************************
       
   253 *   CMessageRelay
       
   254 *****************************************************************************
       
   255 *
       
   256 *
       
   257 *
       
   258 ****************************************************************************/
       
   259 EXPORT_C CMessageRelay::CMessageRelay() : CServer2(EPriorityNormal)
       
   260 	{
       
   261 
       
   262 	}
       
   263 
       
   264 EXPORT_C void CMessageRelay::ConstructL(CMessageWriter *aWriter)
       
   265 	{
       
   266 	iSessions = new (ELeave) CArrayFixFlat<CRelaySession *>(1);
       
   267 
       
   268 	SetWriter(aWriter);
       
   269 
       
   270 	}
       
   271 
       
   272 EXPORT_C CMessageRelay *CMessageRelay::NewL(CMessageWriter *aWriter /*= NULL*/)
       
   273 	{
       
   274 	CMessageRelay *self = CMessageRelay::NewLC(aWriter);
       
   275 	CleanupStack::Pop();
       
   276 	return self;
       
   277 	}
       
   278 
       
   279 EXPORT_C CMessageRelay *CMessageRelay::NewLC(CMessageWriter *aWriter /*= NULL*/)
       
   280 	{
       
   281 	CMessageRelay *self = new (ELeave) CMessageRelay();
       
   282 	CleanupStack::PushL(self);
       
   283 	self->ConstructL(aWriter);
       
   284 	return self;
       
   285 	}
       
   286 
       
   287 EXPORT_C CMessageRelay::~CMessageRelay()
       
   288 	{
       
   289 	delete iSessions;
       
   290 	}
       
   291 
       
   292 /* Goes through all sessions and returns ETrue, is someone
       
   293    is listening the given port. */
       
   294 TBool CMessageRelay::IsAnyBodyListening(TUint aPort, TMessageType aType)
       
   295 	{
       
   296 	TInt i = 0;
       
   297 
       
   298 	for (i = 0; i < iSessions->Count(); i++)
       
   299 		{
       
   300 		if (iSessions->At(i)->IsListening(aPort, aType) != EFalse)
       
   301 			return ETrue;
       
   302 		}
       
   303 
       
   304 	return EFalse;
       
   305 	}
       
   306 
       
   307 CSession2* CMessageRelay::NewSessionL(const TVersion& aVersion) const
       
   308 	{
       
   309 	if (!User::QueryVersionSupported(MessageRelayVersion,
       
   310                                      aVersion))
       
   311         {
       
   312 		/* Wrong version. */
       
   313 		User::Leave(KErrNotSupported);
       
   314         }
       
   315 
       
   316 	CRelaySession *session = CRelaySession::NewL( (CMessageRelay *)this );
       
   317 
       
   318 	iSessions->AppendL(session);
       
   319 
       
   320 	return session;
       
   321 	}
       
   322 
       
   323 CSession2* CMessageRelay::NewSessionL(const TVersion& aVersion, const RMessage2&) const
       
   324 	{
       
   325 	return NewSessionL( aVersion );
       
   326 	}
       
   327 
       
   328 /* Starts the server. */
       
   329 void CMessageRelay::StartRelayL()
       
   330 	{
       
   331 	CServer2::StartL(KRelayServiceName);
       
   332 	} 
       
   333 
       
   334 /* Call this method when a new message is received to relay it
       
   335    to possible listeners. Returns ETrue, if the message was 
       
   336    accepted. If the message was not accepted, it must not be
       
   337    destroyed, but it must be offered again, as soon as there
       
   338    is a listener for it. */
       
   339 EXPORT_C TBool CMessageRelay::NewMessageL(TPtr8 &aMessage, TMessageType aType)
       
   340 	{
       
   341 	TInt i = 0;
       
   342 
       
   343 	if (aType != ESmsMessage)
       
   344 		User::Leave(KErrNotSupported);
       
   345     
       
   346 
       
   347 		/* Extract the port and check if it's listened to. */
       
   348 		RFs fs;
       
   349 		fs.Connect();
       
   350 
       
   351 		CSmsBuffer *smsBuf = CSmsBuffer::NewL();
       
   352 		CSmsMessage *smsMsg	= CSmsMessage::NewL(fs, CSmsPDU::ESmsSubmit, smsBuf);
       
   353 		
       
   354 		RDesReadStream rs(aMessage);
       
   355 		smsMsg->InternalizeL(rs);
       
   356 
       
   357 		rs.Close();
       
   358 		fs.Close();
       
   359 
       
   360 		CSmsPDU &pdu = smsMsg->SmsPDU(); 
       
   361 
       
   362 		TInt src, dst;
       
   363 
       
   364 		TBool isPorts = pdu.ApplicationPortAddressing(dst, src);
       
   365 
       
   366 		if (isPorts == EFalse)
       
   367 			{
       
   368 			/* Copy to inbox. */
       
   369 			CopyMessageToSmsInboxL(aMessage);
       
   370 			return ETrue;
       
   371            	}
       
   372 
       
   373 		for (i = 0; i < iSessions->Count(); i++)
       
   374 			{
       
   375 			if (iSessions->At(i)->AcceptL(aMessage, dst, aType) != EFalse)
       
   376 				return ETrue;
       
   377 			}
       
   378 
       
   379 		/* No listeners. Cache the message to Inbox. Inbox is traversed,
       
   380 		   when new listener are created. */
       
   381 		TPtr8 &aMessage2 = aMessage;   
       
   382 		CopyMessageToSmsInboxL(aMessage2);
       
   383 		return ETrue;
       
   384 		}
       
   385 
       
   386 /* Sets the message writer. Writers WriteMessageL(...) method
       
   387    is called when a client wants to send a message. */
       
   388 EXPORT_C void CMessageRelay::SetWriter(CMessageWriter *aWriter)
       
   389 	{
       
   390 	iWriter = aWriter;
       
   391 	}
       
   392 
       
   393 /* Copies the message to inbox. */
       
   394 void CMessageRelay::CopyMessageToSmsInboxL(TPtr8 &aMessage)
       
   395 	{
       
   396 	// Get the idle statuses from P&S
       
   397 	TInt aiStatus(0);    
       
   398     TInt aiGetErr = RProperty::Get( KPSUidAiInformation,
       
   399 									KActiveIdleState,
       
   400 									aiStatus );
       
   401 	TInt tiStatus(0);
       
   402 	TInt tiGetErr = RProperty::Get( KPSUidIdleInformation,
       
   403 									KTelephonyIdleStatus,
       
   404 									tiStatus );
       
   405 	
       
   406 	_LIT(KIdleStatus,"MSGRelay -- aiState:%d aiGetErr:%d tiState:%d tiGetErr:%d");
       
   407 	RDebug::Print(KIdleStatus, aiStatus, aiGetErr, tiStatus, tiGetErr);
       
   408 
       
   409 	// Update telephony idle status to idle and active idle status 
       
   410 	// to foreground if needed. Without these "New message" notifications
       
   411 	// might not be visible in some cases.
       
   412 	if( aiStatus != EPSAiForeground )
       
   413 		{
       
   414 		TInt setAiErr = RProperty::Set( KPSUidAiInformation, 
       
   415 											KActiveIdleState, 
       
   416 											EPSAiForeground );
       
   417 		_LIT( KAISetErr,"MSGRelay -- setAiErr:%d" );
       
   418 		RDebug::Print( KAISetErr, setAiErr );
       
   419 		}
       
   420 
       
   421 	if( tiStatus != EPSTelephonyIdle )
       
   422 		{
       
   423 		TInt setTiErr = RProperty::Set( KPSUidIdleInformation, 
       
   424 											KTelephonyIdleStatus, 
       
   425 											EPSTelephonyIdle );
       
   426 		_LIT( KTISetErr,"MSGRelay -- setTiErr:%d" );
       
   427 		RDebug::Print( KTISetErr, setTiErr );
       
   428 		}
       
   429 
       
   430 	RFs fs;
       
   431 
       
   432 	User::LeaveIfError(fs.Connect());
       
   433 
       
   434 	CSmsBuffer *smsBuf = CSmsBuffer::NewL();
       
   435 	CSmsMessage *smsMessage = CSmsMessage::NewL(fs, CSmsPDU::ESmsSubmit, smsBuf);
       
   436 	CMsvSession *iMsvSession = CMsvSession::OpenSyncL(*this);
       
   437 	CClientMtmRegistry *registry = CClientMtmRegistry::NewL(*iMsvSession);
       
   438 
       
   439 	RDesReadStream rs(aMessage);
       
   440 	rs >> *smsMessage;
       
   441 	rs.Close();
       
   442 
       
   443 	TMsvEntry index;
       
   444 
       
   445 	index.iMtm = KUidMsgTypeSMS;
       
   446 	index.iType = KUidMsvMessageEntry;
       
   447 	index.iServiceId = KMsvLocalServiceIndexEntryId;
       
   448 	index.iDate.HomeTime();
       
   449 	index.SetInPreparation(ETrue);
       
   450 
       
   451 	TMsvSelectionOrdering ordering;
       
   452 	CMsvEntry *entry = CMsvEntry::NewL(*iMsvSession, KMsvGlobalInBoxIndexEntryIdValue,
       
   453 									   ordering);
       
   454 
       
   455 	entry->CreateL(index);
       
   456 
       
   457 	entry->SetEntryL(index.Id());
       
   458 
       
   459 	CSmsClientMtm* mtm = (CSmsClientMtm*)registry->NewMtmL(KUidMsgTypeSMS);
       
   460 
       
   461 	mtm->SetCurrentEntryL(entry);
       
   462 
       
   463 	index = mtm->Entry().Entry();
       
   464 	
       
   465 	index.iDetails.Set(smsMessage->ToFromAddress());
       
   466 
       
   467 	index.SetInPreparation(EFalse);
       
   468 
       
   469 	index.SetSendingState(KMsvSendStateNotApplicable);
       
   470 	index.iDate = smsMessage->Time();
       
   471 
       
   472 	// Set the new and unread flags. Enables "New message" notifications.
       
   473 	index.SetNew( ETrue );
       
   474 	index.SetUnread( ETrue );
       
   475 
       
   476 	CRichText &mtmBody = mtm->Body();
       
   477 	mtmBody.Reset();
       
   478 
       
   479 	HBufC *data = HBufC::NewLC(smsBuf->Length());
       
   480 	TPtr ptr(data->Des());
       
   481 	
       
   482 	smsBuf->Extract(ptr, 0, smsBuf->Length());
       
   483 	
       
   484 	mtmBody.InsertL(0, ptr);
       
   485 
       
   486 	if (ptr.Length() > KMaxSubjectLength)
       
   487 		index.iDescription.Set(ptr.Left(KMaxSubjectLength));
       
   488 	else
       
   489 		index.iDescription.Set(ptr);
       
   490 
       
   491 	mtm->RestoreServiceAndSettingsL();
       
   492 
       
   493 	CSmsHeader &hdr = mtm->SmsHeader();
       
   494 
       
   495 	CSmsSettings *sendOpt = CSmsSettings::NewL();
       
   496 	CleanupStack::PushL(sendOpt);
       
   497 	
       
   498 	sendOpt->CopyL(mtm->ServiceSettings());
       
   499 	sendOpt->SetDelivery(ESmsDeliveryImmediately);
       
   500 	
       
   501 	hdr.SetSmsSettingsL(*sendOpt);
       
   502 	hdr.SetFromAddressL(smsMessage->ToFromAddress());
       
   503 
       
   504 	CleanupStack::PopAndDestroy(sendOpt);
       
   505 
       
   506 	CSmsMessage &newMsg = hdr.Message();
       
   507 
       
   508 	newMsg.SetServiceCenterAddressL(smsMessage->ServiceCenterAddress());
       
   509 
       
   510 	CSmsPDU &pdu = newMsg.SmsPDU();
       
   511 	CSmsPDU &oldPdu = smsMessage->SmsPDU();
       
   512 
       
   513 	pdu.SetAlphabet(oldPdu.Alphabet());
       
   514 
       
   515 	TSmsDataCodingScheme::TSmsClass coding;
       
   516 	TBool b = oldPdu.Class(coding);
       
   517 	pdu.SetClass(b, coding);
       
   518 
       
   519 	TInt dst = -1;
       
   520 	TInt src = -1; 
       
   521 	TBool is16;
       
   522 	
       
   523 	b = oldPdu.ApplicationPortAddressing(dst, src, &is16);
       
   524 
       
   525 	if(b != EFalse)
       
   526 		{
       
   527 		pdu.SetApplicationPortAddressingL(b, dst, src, is16);
       
   528 		}
       
   529 
       
   530 	mtm->AddAddresseeL(smsMessage->ToFromAddress(), index.iDetails);
       
   531 
       
   532     CMsvEntry &newEntry = mtm->Entry();    
       
   533     newEntry.ChangeL(index);                
       
   534 
       
   535 	mtm->SaveMessageL();                 
       
   536 
       
   537 	CleanupStack::PopAndDestroy(1);
       
   538 
       
   539 	}
       
   540 
       
   541 static CSmsMessage *ConvertEntryToMessageL(TMsvEntry &aIndex, CMsvSession *aSession)
       
   542 	{
       
   543 	CClientMtmRegistry *registry = CClientMtmRegistry::NewL(*aSession);
       
   544 	CleanupStack::PushL(registry);
       
   545 
       
   546 	CSmsClientMtm* mtm = (CSmsClientMtm*)registry->NewMtmL(aIndex.iMtm);
       
   547 	CleanupStack::PushL(mtm);
       
   548 
       
   549 	mtm->SwitchCurrentEntryL(aIndex.Id());
       
   550 	mtm->LoadMessageL();
       
   551 
       
   552 	CSmsHeader &hdr = mtm->SmsHeader();
       
   553 
       
   554 	CSmsMessage &msg = hdr.Message();
       
   555 
       
   556 	HBufC8 *buf = HBufC8::NewLC(KMaxSmsBufferSize);
       
   557 	TPtr8 ptr(buf->Des());
       
   558 	RDesWriteStream ws(ptr);
       
   559 
       
   560 	ws << msg;
       
   561 
       
   562 	ws.Close();
       
   563 
       
   564 	RFs fs;
       
   565 
       
   566 	User::LeaveIfError(fs.Connect());
       
   567 
       
   568 	CSmsBuffer *smsBuf = CSmsBuffer::NewL();
       
   569 	CSmsMessage *newMsg = CSmsMessage::NewL(fs, CSmsPDU::ESmsSubmit, smsBuf);
       
   570 
       
   571 	RDesReadStream rs(ptr);
       
   572 	rs >> *newMsg;
       
   573 
       
   574 	rs.Close();
       
   575 	fs.Close();
       
   576 
       
   577 	CleanupStack::PopAndDestroy(3);
       
   578 
       
   579 	return newMsg;
       
   580 	}
       
   581 
       
   582 static void DeleteEntryFromInboxL(CMsvEntry *aEntry, CMsvSession *aSession)
       
   583     {
       
   584 	TMsvEntry index = aEntry->Entry();
       
   585 	TMsvSelectionOrdering sort = aEntry->SortType();
       
   586 	sort.SetShowInvisibleEntries(ETrue);
       
   587 	CMsvEntry* parentEntry = CMsvEntry::NewL(*aSession, index.Parent(), sort);
       
   588 	CleanupStack::PushL(parentEntry);  
       
   589     
       
   590     TRAPD(err, parentEntry->DeleteL(index.Id()));
       
   591 
       
   592     if(err != KErrNone)
       
   593         {
       
   594         aSession->RemoveEntry(index.Id());
       
   595         }
       
   596 
       
   597 	CleanupStack::PopAndDestroy(parentEntry);
       
   598     }
       
   599 
       
   600 /* Traverses the inbox and sends messages to listeners. */
       
   601 void CMessageRelay::TraverseInboxL()
       
   602 	{
       
   603     TInt count = 0;
       
   604     CMsvEntrySelection* childrenEntrySelection;
       
   605     CMsvEntry* rootEntry;
       
   606     CMsvEntry* child;
       
   607 
       
   608 	CMsvSession *iMsvSession = CMsvSession::OpenSyncL(*this);
       
   609 	CleanupStack::PushL(iMsvSession);
       
   610 
       
   611     rootEntry = iMsvSession->GetEntryL(KMsvGlobalInBoxIndexEntryId);
       
   612     count = rootEntry->Count();
       
   613         
       
   614     childrenEntrySelection = rootEntry->ChildrenL();
       
   615 
       
   616     for(TInt i = 0; i < count; i++)
       
   617         {
       
   618         child = iMsvSession->GetEntryL((*childrenEntrySelection)[i]);
       
   619         TMsvEntry msvEntry = child->Entry();
       
   620         
       
   621 		if (msvEntry.iMtm != KUidMsgTypeSMS)
       
   622 			/* Not to us. */
       
   623 			continue;
       
   624 
       
   625 		CSmsMessage *smsMsg = ConvertEntryToMessageL(msvEntry, iMsvSession);
       
   626 		
       
   627 		HBufC8 *buf = HBufC8::NewLC(KMaxSmsBufferSize);
       
   628 		TPtr8 ptr(buf->Des());
       
   629 		RDesWriteStream ws(ptr);
       
   630 		
       
   631 		ws << *smsMsg;
       
   632 
       
   633 		ws.Close();
       
   634         
       
   635 		CSmsPDU &pdu = smsMsg->SmsPDU(); 
       
   636 
       
   637 		TInt src, dst;
       
   638 
       
   639 		TBool isPorts = pdu.ApplicationPortAddressing(dst, src);
       
   640 
       
   641 		if (isPorts == EFalse)
       
   642 			{
       
   643 			/* No ports, no listeners, leave to inbox. */
       
   644             CleanupStack::PopAndDestroy(1); //buf
       
   645 			continue;
       
   646 
       
   647 			}
       
   648 
       
   649 		for (i = 0; i < iSessions->Count(); i++)
       
   650 			{
       
   651 			if (iSessions->At(i)->AcceptL(ptr, dst, ESmsMessage) != EFalse)
       
   652 				{
       
   653 				/* Remove from inbox */
       
   654 				DeleteEntryFromInboxL(child, iMsvSession);
       
   655 				
       
   656 				/* Inbox has changed, start traversing again. */
       
   657 				rootEntry = iMsvSession->GetEntryL(KMsvGlobalInBoxIndexEntryId);
       
   658 				count = rootEntry->Count();
       
   659 				childrenEntrySelection = rootEntry->ChildrenL();
       
   660 				
       
   661 				i = -1; /* Will be incremented before testing... */
       
   662 				break;
       
   663 				}
       
   664 			}
       
   665 
       
   666 		CleanupStack::PopAndDestroy(1); //buf
       
   667 
       
   668         }
       
   669 	CleanupStack::PopAndDestroy(1); // iMsvSesssion
       
   670 	}
       
   671 
       
   672 void CMessageRelay::HandleSessionEventL(TMsvSessionEvent, TAny*, 
       
   673 										TAny*, TAny*)
       
   674 	{
       
   675 	}
       
   676 /****************************************************************************
       
   677 *   CMessageWriter
       
   678 *****************************************************************************
       
   679 *
       
   680 *
       
   681 *
       
   682 ****************************************************************************/
       
   683 EXPORT_C void CMessageWriter::ConstructL()
       
   684 	{
       
   685 
       
   686 	}
       
   687 
       
   688 EXPORT_C CMessageWriter *CMessageWriter::NewL()
       
   689 	{
       
   690 	CMessageWriter *self = CMessageWriter::NewLC();
       
   691 	CleanupStack::Pop();
       
   692 	return self;
       
   693 	}
       
   694 
       
   695 EXPORT_C CMessageWriter *CMessageWriter::NewLC()
       
   696 	{
       
   697 	CMessageWriter *self = new (ELeave) CMessageWriter;
       
   698 	CleanupStack::PushL(self);
       
   699 	self->ConstructL();
       
   700 	return self;
       
   701 	}
       
   702 
       
   703 EXPORT_C CMessageWriter::~CMessageWriter()
       
   704 	{
       
   705 
       
   706 	}
       
   707 
       
   708 /* Called when a message is received from client for sending. */
       
   709 EXPORT_C void CMessageWriter::WriteMessageL(TPtr8 & /*aMessage*/, TMessageType /*aType*/)
       
   710 	{
       
   711 	/* Nothing to do, inherited class will override. */
       
   712 	}
       
   713 
       
   714 // End of file