Implemented CTelObject::SetSessionOwnerByTsyHandleAndIpc() and CPhoneBase::FindByIpcAndSecureId()
// Copyright (c) 1999-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:
// Implements CWapSmsProvider and CWapSmsProviderWrite
//
//
/**
@file
*/
#include <e32std.h>
#include <wap_sock.h>
#include "ws_main.h"
#include "es_wsms.h"
#include "WAPDGRM.H"
#include "ws_obsvr.h"
#include "smsprot.h"
#include <es_mbuf.h>
//
// implementation of CWapSmsProvider
//
// CWapSmsProvider policies
static _LIT_SECURITY_POLICY_C1(wapSmsProviderSetLocalNamePolicy, ECapabilityNetworkServices );
static _LIT_SECURITY_POLICY_C1(wapSmsProviderSetOptionPolicy, ECapability_None);
static _LIT_SECURITY_POLICY_C1(wapSmsProviderGetLengthIoctlPolicy,ECapability_None);
static _LIT_SECURITY_POLICY_C1(wapSmsProviderGetMessageParamLengthIoctlPolicy,ECapability_None);
static _LIT_SECURITY_POLICY_C1(wapSmsProviderGetMessageParametersIoctlPolicy,ECapabilityReadDeviceData);
static _LIT_SECURITY_POLICY_C1(wapSmsProviderWritePolicy,ECapabilityNetworkServices);
/**
* Factory
*/
CWapSmsProvider* CWapSmsProvider::NewL(CWapSmsProtocol* aProtocol)
{
LOGWAPPROT1("CWapSmsProvider::NewL()");
CWapSmsProvider* provider=new(ELeave) CWapSmsProvider(aProtocol);
CleanupStack::PushL(provider);
provider->iWapSmsProviderWrite = CWapSmsProviderWrite::NewL(*provider);
CleanupStack::Pop();
return provider;
} // CWapSmsProvider::NewL
/**
* Constructor
*/
CWapSmsProvider::CWapSmsProvider(CWapSmsProtocol* aProtocol)
:iMessageType(ESmartMessage)
,iProtocol(aProtocol)
,iSendPending(EFalse)
,iIoctlOutstanding(EFalse)
,iIsNewStyleClient(EFalse)
,iStatusReportScheme(EWapSmsDefault)
{
iRecvdMsgQueue.SetOffset(CWapDatagram::LinkOffset());
} // CWapSmsProvider::CWapSmsProvider
/**
* Destructor
*/
CWapSmsProvider::~CWapSmsProvider()
{
iSAPLink.Deque();
while(!iRecvdMsgQueue.IsEmpty())
{
CWapDatagram* msg = iRecvdMsgQueue.First();
iRecvdMsgQueue.Remove(*msg);
delete msg;
}
delete iWapSmsProviderWrite;
} // CWapSmsProvider::~CWapSmsProvider
/**
* Return WAPSMS options
*/
TInt CWapSmsProvider::GetOption(TUint aLevel,TUint aName, TDes8& aOption)const
{
LOGWAPPROT1("CWapSmsProvider::GetOption");
TInt ret=KErrNone;
if (TInt(aLevel)==KWapSmsOptionLevel && TInt(aName)==KWapSmsOptionNameDCS)
aOption = TPtrC8((TText8*)&iDataCodingScheme,sizeof(TWapSmsDataCodingScheme));
else
ret=iProtocol->GetOption(aLevel,aName,aOption,NULL);
return ret;
} // CWapSmsProvider::GetOption
/**
* Set WAPSMS options
*
* @capability None
*
*/
TInt CWapSmsProvider::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption)
{
LOGWAPPROT1("CWapSmsProvider::SetOption");
if(!iSecurityChecker || (iSecurityChecker->CheckPolicy(wapSmsProviderSetOptionPolicy,"CWapSmsProvider SetOption policy check") != KErrNone))
{
return KErrPermissionDenied;
}
TInt ret=KErrNone;
if (TInt(aLevel)==KWapSmsOptionLevel)
{
switch(TInt(aName))
{
case KWapSmsOptionNameDCS:
{
iDataCodingScheme = static_cast<TWapSmsDataCodingScheme>(*aOption.Ptr());
break;
}
case KWapSmsOptionWapDatagram:
{
iMessageType=EWapDatagram;
break;
}
case KWapSmsStatusReportScheme:
{
iStatusReportScheme = static_cast<TWapSmsStatusReportScheme>(*aOption.Ptr());
break;
}
case KWapSmsOptionNewStyleClient:
{
iIsNewStyleClient = ETrue;
break;
}
case KWapSmsOptionOKToDeleteMessage:
{
//Get the first message from the queue
CWapDatagram* msg = iRecvdMsgQueue.First();
//Find and delete from SAR
TBool found=iProtocol->FindAndDeleteMsg(*msg);
if(!found)
{
LOGWAPPROT1("CWapSmsProvider::SetOption: Error. Couldn't find the message in the SAR for deletion");
break;
}
//Remove from the queue
iRecvdMsgQueue.Remove(*msg);
delete msg;
break;
}
default:
ret=KErrNotSupported;
}
}
else
{
ret=iProtocol->SetOption(aLevel,aName,aOption,NULL);
}
return ret;
} // CWapSmsProvider::SetOption
/**
* Shutdown the SAP
*/
void CWapSmsProvider::Shutdown(TCloseType aType)
{
LOGWAPPROT1("CWapSmsProvider::Shutdown");
if (aType!=CServProviderBase::EImmediate)
iSocket->CanClose();
} // CWapSmsProvider::Shutdown
/**
* Setup datagram with socket specific options and forward to protocol
* Return zero to block the send - will be completed by CWapSapMessageSender
*
* @capability NetworkServices
*/
TInt CWapSmsProvider::Write(RMBufChain& aBufChain, TUint /*options*/, TSockAddr* aAddr)
{
LOGWAPPROT1("CWapSmsProvider::Write()");
if(!iSecurityChecker || (iSecurityChecker->CheckPolicy(wapSmsProviderWritePolicy,"CWapSmsProvider Write policy check") != KErrNone))
{
return KErrPermissionDenied;
}
// @note: LOGIFH2A2 macro for logging esock write
#ifdef SMSLOGGERIF
TInt length = aBufChain.Length();
LOGWAPPROT2("CWapSmsProvider::Write [%d bytes]", length);
TBuf8<0x100> dumpBuf;
if(length > 0x100)
{
TInt parts=0;
TInt offset = 0;
while (offset < length)
{
aBufChain.CopyOut(dumpBuf, offset);
offset += length;
LOGIF2(_L8("ESock WAP concantonated part: %d"),parts++);
LOGIF2(_L8("ESOCK WRITE: %S"),&dumpBuf);
LOGIFH2A2(_L8("ESOCK WRITE: "),dumpBuf);
}
}
else
{
aBufChain.CopyOut(dumpBuf, 0);
LOGIF2(_L8("ESOCK WRITE: %S"),&dumpBuf);
LOGIFH2A2(_L8("ESOCK WRITE: "),dumpBuf);
}
#endif
// Note that if this fails somehow it still frees the buf chain and sets itself active - it's
// not clear to me whether this is good behaviour but it's the pre-mbuf behaviour too
iWapSmsProviderWrite->Start(aBufChain, *aAddr);
return KErrNone;
} // CWapSmsProvider::Write
/**
* Read a datagram off the queue
*/
TInt CWapSmsProvider::GetData(RMBufChain& aBufChain, TUint aLength, TUint /*options*/,TSockAddr* aAddr)
{
LOGWAPPROT1("CWapSmsProvider::GetData()");
CWapDatagram* msg = iRecvdMsgQueue.First();
if(!iIsNewStyleClient)
{
iRecvdMsgQueue.Remove(*msg);
}
TInt err = msg->WapDatagram(aBufChain, aLength);
//@note: LOGIFH2A2 macro for logging esock getdata
LOGWAPPROT1("CWapSmsProvider::GetData");
// Logging migrated to WapDatagram() for ease of descriptor ref
if (err > 0 && aAddr)
{
TWapAddr* wapAddr = reinterpret_cast<TWapAddr*>(aAddr);
TInt toPort,fromPort;
msg->Ports(fromPort,toPort);
wapAddr->SetWapPort(static_cast<TWapPortNumber>(fromPort));
TBuf8<KMaxSockAddrSize> addrBuf;
addrBuf.Copy(msg->FromAddress());
wapAddr->SetWapAddress(addrBuf);
}
if(!iIsNewStyleClient)
{
delete msg;
}
return err > 0? 1: err; // datagrams are atoms not byte counts
} // CWapSmsProvider::GetData
/**
* New data has arrived notify ESOCK.
*/
void CWapSmsProvider::NewData(CWapDatagram* aMsg)
{
TBool notifyEsock = EFalse;
LOGWAPPROT1("CWapSmsProvider::NewData");
if(iIoctlOutstanding && iName==KSOGetLength && iIsNewStyleClient)
{
TPckgBuf<TInt> buf= aMsg->WapDatagramLength();
iSocket->IoctlComplete(&buf);
iIoctlOutstanding= EFalse;
iName= NULL;
notifyEsock = ETrue;
}
else if(iIoctlOutstanding && iName==KSOGetMessageParametersLength && iIsNewStyleClient)
{
CBufFlat* buffer = aMsg->SmsExternalisedStream();
TPckgBuf<TInt> buf = buffer->Size();
iSocket->IoctlComplete(&buf);
iIoctlOutstanding= EFalse;
iName= NULL;
notifyEsock = ETrue;
}
else if(iIoctlOutstanding && iName==KSOGetMessageParameters && iIsNewStyleClient)
{
CBufFlat* buffer = aMsg->SmsExternalisedStream();
TPtr8 buf = buffer->Ptr(0);
iSocket->IoctlComplete(&buf);
iIoctlOutstanding= EFalse;
iName= NULL;
notifyEsock = ETrue;
}
else if(iName!=KSOGetLength && iName!=KSOGetMessageParametersLength && iName!=KSOGetMessageParameters && iIsNewStyleClient)
{
notifyEsock= EFalse;
}
if(!iIsNewStyleClient || notifyEsock)
iSocket->NewData(1);
//else we notify ESock in IOCTL for new client
} // CWapSmsProvider::NewData
/**
* Error happened, notify ESOCK
*/
void CWapSmsProvider::Error(TInt aError, TUint aOperationMask)
{
LOGWAPPROT3("CWapSmsProvider::Error [aError=%d, mask=%d] ", aError, aOperationMask);
iSocket->Error(aError, aOperationMask);
} // CWapSmsProvider::Error
/**
* Return the offset to the dblquelink
*/
TInt CWapSmsProvider::LinkOffset()
{
LOGWAPPROT1("CWapSmsProvider::LinkOffset");
return _FOFF(CWapSmsProvider,iSAPLink);
} // CWapSmsProvider::LinkOffset
/**
* Return the address associated with the sap
*/
void CWapSmsProvider::LocalName(TSockAddr& aAddr) const
{
LOGWAPPROT1("CWapSmsProvider::LocalName");
Mem::Copy(&aAddr,&iLocalAddress,sizeof(TSockAddr));
} // CWapSmsProvider::LocalName
/**
* Set the local address of the sap - called by RSocket::Bind
*
* @capability NetworkServices
*/
TInt CWapSmsProvider::SetLocalName(TSockAddr& aAddr)
{
LOGWAPPROT1("CWapSmsProvider::SetLocalName()");
if(!iSecurityChecker || (iSecurityChecker->CheckPolicy(wapSmsProviderSetLocalNamePolicy,"CWapSmsProvider SetLocalName policy check") != KErrNone))
{
return KErrPermissionDenied;
}
TWapAddr* wapAddr = reinterpret_cast<TWapAddr*>(&aAddr);
LOGWAPPROT2("CWapSmsProvider::SetLocalName %d",wapAddr->WapPort());
// Due ESOCK interface port EWapPortUnspecified value (-1) can be transferred as a maximum unsigned 16 int
if (wapAddr->WapPort()==EWapPortUnspecified || wapAddr->WapPort()==static_cast<TUint16>(EWapPortUnspecified))
{
if(!iProtocol->AllocateLocalAddress(iLocalAddress))
return KErrInUse;
else return KErrNone;
}
TInt ret=iProtocol->AddrAlreadyUsedByWAP(*wapAddr,this);
if(ret == KErrInUse) return ret;
else if(ret == KErrAlreadyExists) return KErrNone;
TSmsAddr addr;
if(wapAddr->Port() <=255)
addr.SetSmsAddrFamily(ESmsAddrApplication8BitPort);
else
addr.SetSmsAddrFamily(ESmsAddrApplication16BitPort);
addr.SetPort(wapAddr->Port());
if((iProtocol->SmsProtocol()->SmsAddrIsAlreadyUsed(NULL,addr)))
return KErrInUse;
Mem::Copy(&iLocalAddress,&aAddr,sizeof(TSockAddr));
TInt err;
TRAP(err,ret = iProtocol->CheckSarL(*wapAddr,this));
if(err!=KErrNone)
return err;
if(ret!=KErrNone)
{
Error(ret,MSocketNotify::EErrorAllOperations);
}
return KErrNone;
} // RSocket::Bind
/**
* Returns true if aAddr matches the local address of the sap
*/
TBool CWapSmsProvider::MatchesLocalAddress(const TWapAddr& aAddr)
{
LOGWAPPROT1("CWapSmsProvider::MatchesLocalAddress");
return (iLocalAddress == aAddr);
} // CWapSmsProvider::MatchesLocalAddress
//
/**
* Called to perform specific IO control by the client (i.e. Wap Messaging API).The client is able
* to get the size of the datagram once it has been received or confirm the receipt
* of the message.
*
* Only one ioctl request may be outstanding at any one time.
*
* Implementation of pure virtual CServProviderBase::Ioctl().
*
* @param aLevel the IOCTL level. // Can be only KSolWapProv
* @param aName the IOCTL name.
* @param aOption the IOCTL option.
*
*/
void CWapSmsProvider::Ioctl(TUint aLevel,TUint aName,TDes8 * /*aOption*/)
{
LOGWAPPROT3("CWapSmsProvider::Ioctl [aLevel=%d, aName=%d]", aLevel, aName);
LOGWAPPROT2("CWapSmsProtocol::Ioctl [provider=0x%08x]",this);
iName=aName;
switch (aLevel)
{
case KSolWapProv:
{
if(iIoctlOutstanding || !iIsNewStyleClient)
{
Error(KErrInUse,MSocketNotify::EErrorIoctl);
break;
}
switch (iName)
{
case KSOGetLength:
//
// Get the length
//
{
if(!iSecurityChecker || (iSecurityChecker->CheckPolicy(wapSmsProviderGetLengthIoctlPolicy,"CWapSmsProvider GetLength Ioctl policy check") != KErrNone))
{
Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
return;
}
iIoctlOutstanding = ETrue;
//check the queue for any other message for this client and call new data if any exist
if(!iRecvdMsgQueue.IsEmpty())
{
CWapDatagram* msg = iRecvdMsgQueue.First();
//check the datagram.
if(msg->IsComplete())
{
NewData(msg);
}
else
{
// else notify the client with error.
// Note:this can happen if client uses 8-Bit port number for 7-Bit datagram
Error(KErrGeneral,MSocketNotify::EErrorIoctl);
iIoctlOutstanding = EFalse;
}
}
break;
}
case KSOGetMessageParametersLength:
//
// Get the Message Parameters Length
//
{
if(!iSecurityChecker || (iSecurityChecker->CheckPolicy(wapSmsProviderGetMessageParamLengthIoctlPolicy,"CWapSmsProvider KSOGetMessageParametersLength Ioctl policy check") != KErrNone))
{
Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
return;
}
iIoctlOutstanding = ETrue;
//check the queue for any other message for this client and call new data if any exist
if(!iRecvdMsgQueue.IsEmpty())
{
CWapDatagram* msg = iRecvdMsgQueue.First();
//check the datagram.
if(msg->IsComplete())
{
NewData(msg);
}
else
{
// else notify the client with error.
// Note:this can happen if client uses 8-Bit port number for 7-Bit datagram
Error(KErrGeneral,MSocketNotify::EErrorIoctl);
iIoctlOutstanding = EFalse;
}
}
break;
}
case KSOGetMessageParameters:
//
// Get the Message Parameters
//
{
if(!iSecurityChecker || (iSecurityChecker->CheckPolicy(wapSmsProviderGetMessageParametersIoctlPolicy,"CWapSmsProvider GetMessageParameters Ioctl policy check") != KErrNone))
{
Error(KErrPermissionDenied,MSocketNotify::EErrorIoctl);
return;
}
iIoctlOutstanding = ETrue;
//check the queue for any other message for this client and call new data if any exist
if(!iRecvdMsgQueue.IsEmpty())
{
CWapDatagram* msg = iRecvdMsgQueue.First();
//check the datagram.
if(msg->IsComplete())
{
NewData(msg);
}
else
{
// else notify the client with error.
// Note:this can happen if client uses 8-Bit port number for 7-Bit datagram
Error(KErrGeneral,MSocketNotify::EErrorIoctl);
iIoctlOutstanding = EFalse;
}
}
break;
}
default:
//
// Unsupported ioctl name
//
{
// Error gracefully
Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
}
}
break;
}
default:
// Gracefully error in release build
Error(KErrNotSupported,MSocketNotify::EErrorIoctl);
}
} // CServProviderBase::Ioctl
/**
* Cancel IOCTL- can only have one outstanding IOCTL at a time
*/
void CWapSmsProvider::CancelIoctl(TUint aLevel,TUint aName)
{
LOGWAPPROT1("CWapSmsProvider::CancelIoctl()");
if(!iIoctlOutstanding || (aName!=iName) || (aLevel!=KSolWapProv))
{
Error(KErrNotFound,MSocketNotify::EErrorIoctl);
}
else
{
iIoctlOutstanding=EFalse;
}
} // CWapSmsProvider::CancelIoctl
/**
* Start the provider- does nothing
*/
void CWapSmsProvider::Start()
{
LOGWAPPROT1("CWapSmsProvider::Start()");
} // CWapSmsProvider::Start
void CWapSmsProvider::AddToQueue(CWapDatagram* aMsg)
/**
* Adding the datagram to received messages queue
*/
{
LOGWAPPROT1("CWapSmsProvider::AddToQueue...");
iRecvdMsgQueue.AddLast(*aMsg);
NewData(aMsg);
} // CWapSmsProvider::AddToQueue
TInt CWapSmsProvider::SecurityCheck(MProvdSecurityChecker* aSecurityChecker)
{
LOGWAPPROT1("CWapSmsProvider::SecurityCheck()");
iSecurityChecker=aSecurityChecker;
return KErrNone;
} // CWapSmsProvider::SecurityCheck
TWapSmsStatusReportScheme CWapSmsProvider::GetStatusReportScheme()
{
return iStatusReportScheme;
}
TWapSmsDataCodingScheme CWapSmsProvider::GetDataCodingScheme()
{
return iDataCodingScheme;
}
//
// implementation of CWapSmsProviderWrite
//
/**
* 2 phase constructor
*/
CWapSmsProviderWrite* CWapSmsProviderWrite::NewL(CWapSmsProvider& aWapSmsProvider)
{
LOGWAPPROT1("CWapSmsProviderWrite::NewL");
CWapSmsProviderWrite* self = new (ELeave) CWapSmsProviderWrite(aWapSmsProvider);
CleanupStack::PushL(self);
self->iMsgSender = CWapSapMessageSender::NewL(aWapSmsProvider.iProtocol->SmsProtocol(), &aWapSmsProvider);
CleanupStack::Pop(self);
return self;
} // CWapSmsProviderWrite::NewL
/**
* Constructor
*/
CWapSmsProviderWrite::CWapSmsProviderWrite(CWapSmsProvider& aWapSmsProvider)
:CActive(EPriorityStandard)
,iWapSmsProvider(aWapSmsProvider)
{
LOGWAPPROT1("CWapSmsProviderWrite::CWapSmsProviderWrite()");
CActiveScheduler::Add(this);
} // CWapSmsProviderWrite::CWapSmsProviderWrite
/**
* Destructor
*/
CWapSmsProviderWrite::~CWapSmsProviderWrite()
{
Cancel();
delete iMsgSender;
delete iDes;
} // CWapSmsProviderWrite::~CWapSmsProviderWrite
void CWapSmsProviderWrite::Start(RMBufChain& aBufChain, TSockAddr& aAddr)
{
LOGWAPPROT1("CWapSmsProviderWrite::Start");
iWapAddr = reinterpret_cast<TWapAddr&>(aAddr);
delete iDes;
iDes = NULL;
TRAPD(err, (iDes = HBufC8::NewL(aBufChain.Length())) );
if(err == KErrNone)
{
TPtr8 desBuf(iDes->Des());
desBuf.SetLength(aBufChain.Length());
aBufChain.CopyOut(desBuf, 0);
// Logging migrated from CWapSmsProvider::GetData
LOGSMSIF2("ESOCK READ: \"%S\"", iDes);
LOGSMSIFHEXBUF(_L8("ESOCK READ"), *iDes);
LOGSMSIFTIMESTAMP();
}
aBufChain.Free();
TRequestStatus* status = &iStatus;
User::RequestComplete(status, err);
SetActive();
} // CWapSmsProviderWrite::Start
void CWapSmsProviderWrite::RunL()
{
LOGWAPPROT1("CWapSmsProviderWrite::RunL");
User::LeaveIfError(iStatus.Int());
//no need to use cleanup stack
CWapDatagram* datagram = CWapDatagram::NewL(*iDes);
if (iWapSmsProvider.iDataCodingScheme == EWapSms7BitDCS)
datagram->SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet7Bit);
else
datagram->SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
if (iWapSmsProvider.iStatusReportScheme == EWapSmsTPSRR)
{
datagram->SetStatusReportScheme(ETPSRRScheme);
}
else
{
datagram->SetStatusReportScheme(EDefaultScheme);
}
TBuf<KMaxSockAddrSize> addrBuf;
addrBuf.Copy(iWapAddr.WapAddress());
datagram->SetToAddress(addrBuf);
TInt fromPort = iWapSmsProvider.iLocalAddress.WapPort();
datagram->SetPorts(fromPort, iWapAddr.WapPort());
iMsgSender->SendDatagramL(datagram); // takes ownership of datagram
} // CWapSmsProviderWrite::RunL
TInt CWapSmsProviderWrite::RunError(TInt aError)
{
LOGWAPPROT1("CWapSmsProviderWrite::RunError");
iWapSmsProvider.Error(aError, MSocketNotify::EErrorSend);
return KErrNone;
} // CWapSmsProviderWrite::RunError
void CWapSmsProviderWrite::DoCancel()
{
LOGWAPPROT1("CWapSmsProviderWrite::DoCancel");
TRequestStatus* status = &iStatus;
User::RequestComplete(status, KErrCancel);
} // CWapSmsProviderWrite::DoCancel
// EOF - WS_PRVDR.CPP