?? gdpsms.cpp
字號:
// gdpsms.cpp
//
// Copyright (c) 2002 Symbian Ltd. All rights reserved.
//
#include "gdpsms.h"
#include <ImplementationProxy.h>
#include <ecom.h>
CGdpSmsComms::CGdpSmsComms()
{
}
CGdpSmsComms::~CGdpSmsComms()
{
REComSession::DestroyedImplementation(iDtor_ID_Key);
delete iSender;
delete iReceiver;
delete iResMan;
}
CGdpSession* CGdpSmsComms::NewL()
{
return new (ELeave) CGdpSmsComms();
}
void CGdpSmsComms::OpenL(MGdpPacketHandler* aHandler)
{
RDebug::Print(_L("CGdpSmsComms::OpenL() Called"));
iResMan = new(ELeave) CGdpSmsResourceManager();
iResMan->OpenL();
iSender = new(ELeave) CGdpSmsSender(*iResMan);
iSender->OpenL(*aHandler); // Inform handler of successful send
iReceiver = new(ELeave) CGdpSmsReceiver(*iResMan);
iReceiver->OpenL(*aHandler); // route packets up to the handler passed to us
}
void CGdpSmsComms::SendL(const TDesC8& aAddress, const TDesC8& aData)
{
RDebug::Print(_L("CGdpSmsComms::SendL() Called."));
__ASSERT_ALWAYS(iSender != NULL, GdpUtil::Fault(GdpUtil::EProtocolNotOpen));
iSender->SendL(aAddress, aData);
}
TInt CGdpSmsComms::ReceiveAll()
{
RDebug::Print(_L("CGdpSmsComms::ReceiveAllL() Called"));
__ASSERT_ALWAYS(iReceiver != NULL, GdpUtil::Fault(GdpUtil::EProtocolNotOpen));
iReceiver->ReceiveAllL();
return KErrNone;
}
TInt CGdpSmsComms::GetMaxPacketLength() const
{
RDebug::Print(_L("CGdpSmsComms::GetMaxPacketLength() Called"));
return KGdpSmsSduMaxSize;
}
TBool CGdpSmsComms::IsNetworked() const
{
return ETrue;
}
CGdpSmsStateMachine::CGdpSmsStateMachine(CGdpSmsResourceManager& aResMan)
: CGdpStateMachine(EPriorityStandard), iResMan(aResMan)
{
}
#pragma warning(disable:4355) // Disable "C4355: 'this' used in member initialization".
CGdpSmsSender::CGdpSmsSender(CGdpSmsResourceManager& aResMan)
: CGdpSmsStateMachine(aResMan),
iSendMsgState(*this)
{
RDebug::Print(_L("CGdpSmsSender::CGdpSmsSender"));
}
#pragma warning(default:4355) // Turn it back on.
CGdpSmsSender::~CGdpSmsSender()
{
Close();
}
void CGdpSmsSender::OpenL(MGdpPacketHandler& aHandler)
{
iHandler = &aHandler;
Reset();
}
void CGdpSmsSender::Close()
{
Cancel();
}
void CGdpSmsSender::SendL(const TDesC8& aAddress, const TDesC8& aData)
{
RDebug::Print(_L("CGdpSmsSender::SendL() Called."));
if (IsActive())
return; // Don't leave -- just quietly drop the overflow packet
// Create the SMS message
CSmsBuffer* smsBuffer = CSmsBuffer::NewL();
iSmsMsg = CSmsMessage::NewL(iResMan.iFs, CSmsPDU::ESmsSubmit, smsBuffer);
TSmsUserDataSettings smsSettings;
smsSettings.SetAlphabet(TSmsDataCodingScheme::ESmsAlphabet8Bit);
smsSettings.SetTextCompressed(EFalse);
// Convert address to unicode string required by CSmsMessage
__ASSERT_ALWAYS(aAddress.Length() <= KGdpMaxAddressLen, GdpUtil::Fault(GdpUtil::EBadSendAddress));
TBuf<KGdpMaxAddressLen> bufAddress;
bufAddress.Copy(aAddress);
iSmsMsg->SetUserDataSettingsL(smsSettings);
iSmsMsg->SetToFromAddressL(bufAddress);
iSmsMsg->SmsPDU().SetServiceCenterAddressL(KServiceCenterNumber);
// Insert our SMS pattern header so that our receiver is able to detect
// the incoming message, and then append the data.
smsBuffer->InsertL(0, KGdpSmsHeaderTag);
CSmsPDU& pdu = iSmsMsg->SmsPDU();
CSmsUserData& userData = pdu.UserData();
userData.AddInformationElementL(CSmsInformationElement::ESmsIEIReserved, aData);
iRetries = KGdpSmsSendRetries;
Reset();
ReEnterCurrentState(); // Kick us off again.
}
void CGdpSmsSender::Reset()
{
SetNextState(static_cast<TState*>(&iSendMsgState));
}
CGdpStateMachine::TState* CGdpSmsSender::ErrorOnStateEntry(TInt /*aError*/)
{
return NULL; // Give up!
}
CGdpStateMachine::TState* CGdpSmsSender::ErrorOnStateExit(TInt /*aError*/)
{
Reset();
if (--iRetries < 0)
return NULL;
return CurrentState(); // Force re-entry to initial state
}
CGdpSmsSender::TSenderState::TSenderState(CGdpSmsSender& aSmsSender)
: iSender(aSmsSender)
{
}
CGdpSmsSender::TSendMsgState::TSendMsgState(CGdpSmsSender& aSmsSender)
: TSenderState(aSmsSender)
{
}
void CGdpSmsSender::TSendMsgState::EnterL()
{
// Close the socket as it may already be open.
iSender.iSocket.Close();
// Open a socket
User::LeaveIfError(iSender.iSocket.Open(iSender.iResMan.iSocketServer, KSMSAddrFamily, KSockDatagram, KSMSDatagramProtocol));
// Bind to SMS port
TSmsAddr smsAddr;
smsAddr.SetSmsAddrFamily(ESmsAddrSendOnly);
iSender.iSocket.Bind(smsAddr);
// Open a write stream on the socket and stream our message.
RSmsSocketWriteStream writeStream(iSender.iSocket);
writeStream << *(iSender.iSmsMsg);
// message has not been sent at this point
writeStream.CommitL();
// Send the message
iSender.iSocket.Ioctl(KIoctlSendSmsMessage, iSender.iStatus, &iSender.iOctlResult, KSolSmsProv);
iSender.SetActive();
}
CGdpStateMachine::TState* CGdpSmsSender::TSendMsgState::CompleteL()
{
RDebug::Print(_L("Message sent!!"));
iSender.iHandler->SendComplete(KErrNone);
delete iSender.iSmsMsg;
iSender.iSocket.Close();
return NULL; // Last state so return NULL
}
CGdpStateMachine::TState* CGdpSmsSender::TSendMsgState::ErrorL(TInt aCode)
{
User::Leave(aCode);
return NULL;
}
void CGdpSmsSender::TSendMsgState::Cancel()
{
if (iSender.iSocket.SubSessionHandle())
iSender.iSocket.CancelIoctl();
}
/************** Receiver ***************/
#pragma warning(disable:4355) // Disable "C4355: 'this' used in member initialization".
CGdpSmsReceiver::CGdpSmsReceiver(CGdpSmsResourceManager& aResMan)
: CGdpSmsStateMachine(aResMan),
iWaitState(*this),
iReadMsgState(*this)
{
}
#pragma warning(default:4355) // Turn it back on.
CGdpSmsReceiver::~CGdpSmsReceiver()
{
Close();
}
void CGdpSmsReceiver::OpenL(MGdpPacketHandler& aHandler)
{
iHandler = &aHandler;
Reset();
}
void CGdpSmsReceiver::Close()
{
Cancel();
}
void CGdpSmsReceiver::ReceiveAllL()
{
__ASSERT_ALWAYS(iHandler != NULL, GdpUtil::Fault(GdpUtil::EProtocolNotOpen));
if (IsActive())
return;
iRetries = KGdpSmsReceiveRetries;
ReEnterCurrentState();
}
void CGdpSmsReceiver::Reset()
{// Called on start-up and if an error occurs
SetNextState(&iWaitState);
}
CGdpStateMachine::TState* CGdpSmsReceiver::ErrorOnStateEntry(TInt /*aError*/)
{
return NULL;
}
CGdpStateMachine::TState* CGdpSmsReceiver::ErrorOnStateExit(TInt /*aError*/)
{
Reset();
if (--iRetries<0)
return NULL;
return CurrentState();
}
CGdpSmsReceiver::TReceiverState::TReceiverState(CGdpSmsReceiver& aSmsReceiver)
: iReceiver(aSmsReceiver)
{
}
/* ---------- Receiver States ------------ */
CGdpSmsReceiver::TWaitState::TWaitState(CGdpSmsReceiver& aSmsReceiver)
: TReceiverState(aSmsReceiver)
{
}
CGdpSmsReceiver::TReadMsgState::TReadMsgState(CGdpSmsReceiver& aSmsReceiver)
: TReceiverState(aSmsReceiver)
{
}
void CGdpSmsReceiver::TWaitState::EnterL()
{
// Close the socket as it may already be open.
iReceiver.iSocket.Close();
// Open a socket
User::LeaveIfError(iReceiver.iSocket.Open(iReceiver.iResMan.iSocketServer, KSMSAddrFamily, KSockDatagram, KSMSDatagramProtocol));
// Set the pattern to search for in incoming SMS messages. Messages which do not have our
// signature will be consumed by the Messaging Application.
TSmsAddr smsAddr;
smsAddr.SetSmsAddrFamily(ESmsAddrMatchText);
smsAddr.SetTextMatch(KGdpSmsHeaderTag8());
User::LeaveIfError(iReceiver.iSocket.Bind(smsAddr));
// Wait for incoming messages
iReceiver.iOctlResult()= KSockSelectRead;
iReceiver.iSocket.Ioctl(KIOctlSelect, iReceiver.iStatus, &(iReceiver.iOctlResult), KSOLSocket);
iReceiver.SetActive();
}
CGdpStateMachine::TState* CGdpSmsReceiver::TWaitState::CompleteL()
{
// Received a message so move to read state.
return static_cast<TState*> (&iReceiver.iReadMsgState);
}
CGdpStateMachine::TState* CGdpSmsReceiver::TWaitState::ErrorL(TInt aCode)
{
User::Leave(aCode);
return NULL;
}
void CGdpSmsReceiver::TWaitState::Cancel()
{
iReceiver.iSocket.CancelIoctl();
}
void CGdpSmsReceiver::TReadMsgState::EnterL()
{
// Create an empty message and buffer for our incoming message.
CSmsBuffer* buffer=NULL;
buffer=CSmsBuffer::NewL();
iReceiver.iSmsMsg = CSmsMessage::NewL(iReceiver.iResMan.iFs, CSmsPDU::ESmsSubmit, buffer);
// Read the message.
RSmsSocketReadStream readstream(iReceiver.iSocket);
readstream >> *(iReceiver.iSmsMsg);
// Let the socket know that we have read the message and it can be removed from the message
// store.
iReceiver.iSocket.Ioctl(KIoctlReadMessageSucceeded, iReceiver.iStatus, NULL, KSolSmsProv);
iReceiver.SetActive();
}
CGdpStateMachine::TState* CGdpSmsReceiver::TReadMsgState::CompleteL()
{
// Extract the message contents
CSmsPDU& pdu = iReceiver.iSmsMsg->SmsPDU();
CSmsUserData& userData = pdu.UserData();
CSmsInformationElement& recvElement = userData.InformationElement(0);
// Convert from address from uncode and send to handler
TPtrC ptrFrom = iReceiver.iSmsMsg->ToFromAddress();
HBufC8* hFromAddress = HBufC8::NewLC(ptrFrom.Length());
TPtr8 p = hFromAddress->Des();
p.Copy(ptrFrom);
iReceiver.iHandler->GdpHandleL(*hFromAddress, recvElement.Data());
// Cleanup
CleanupStack::PopAndDestroy(); // hbuf, hFromAddress;
delete iReceiver.iSmsMsg;
iReceiver.iSocket.Close();
// Return to wait state for next message.
return static_cast<TState*> (&iReceiver.iWaitState);
}
CGdpStateMachine::TState* CGdpSmsReceiver::TReadMsgState::ErrorL(TInt aCode)
{
User::Leave(aCode);
return NULL;
}
void CGdpSmsReceiver::TReadMsgState::Cancel()
{
iReceiver.iSocket.CancelIoctl();
}
CGdpSmsResourceManager::~CGdpSmsResourceManager()
{
Close();
}
void CGdpSmsResourceManager::OpenL()
{
User::LeaveIfError(iSocketServer.Connect());
User::LeaveIfError(iFs.Connect());
}
void CGdpSmsResourceManager::Close()
{
iFs.Close();
iSocketServer.Close();
}
// Define the interface UIDs
const TImplementationProxy ImplementationTable[] =
{
{{0x101f8b5e}, CGdpSmsComms::NewL},
};
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
{
aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
return ImplementationTable;
}
TInt E32Dll(TDllReason)
{
return KErrNone;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -