// EsmeTransceiverCom.cpp : Implementation of CEsmeTransceiverCom
#include "stdafx.h"
#include "EsmeTransceiverCom.h"
// CEsmeTransceiverCom
STDMETHODIMP CEsmeTransceiverCom::bind(BSTR sysid, BSTR passwd, BSTR systype, ISmppAddressCom* iaddr, VARIANT_BOOL* pret)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
USES_CONVERSION;
LPSTR sid, pwd, stype;
sid = OLE2A(sysid);
pwd = OLE2A(passwd);
stype = OLE2A(systype);
SHORT npi;
SHORT ton;
BSTR addr;
iaddr->get_NPI(&npi);
iaddr->get_TON(&ton);
iaddr->get_Address(&addr);
LPSTR paddr = OLE2A(addr);
CSmppAddress srange(ton, npi, paddr);
SysFreeString(addr);
//setting finished, going to bind to SMSC
EnterCriticalSection(&m_cs); //enter m_cs
ResetEvent(m_response_event);
CEsmeTransceiver::bind(sid, pwd, stype, srange);
HANDLE hwait[] = {m_response_event, m_hDisconnectEvent, m_hKillEvent};
DWORD ret = WaitForMultipleObjects(3, hwait, FALSE, 30000);
if (ret == WAIT_OBJECT_0)
{
if (m_last_error)
*pret = VARIANT_FALSE;
else
*pret = VARIANT_TRUE;
}
else
*pret = VARIANT_FALSE;
ResetEvent(m_response_event);
LeaveCriticalSection(&m_cs); //leave m_cs
return S_OK;
}
STDMETHODIMP CEsmeTransceiverCom::unbind(VARIANT_BOOL* pret)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
EnterCriticalSection(&m_cs); //enter m_cs
ResetEvent(m_response_event);
CEsmeTransceiver::unbind();
HANDLE hwait[] = {m_response_event, m_hDisconnectEvent, m_hKillEvent};
DWORD ret = WaitForMultipleObjects(3, hwait, FALSE, 30000);
if (ret == WAIT_OBJECT_0)
{
if (m_last_error)
*pret = VARIANT_FALSE;
else
*pret = VARIANT_TRUE;
}
else
*pret = VARIANT_FALSE;
ResetEvent(m_response_event);
LeaveCriticalSection(&m_cs); //leave m_cs
return S_OK;
}
STDMETHODIMP CEsmeTransceiverCom::enquireLink(VARIANT_BOOL* pret)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
EnterCriticalSection(&m_cs); //enter m_cs
ResetEvent(m_response_event);
CEsmeTransceiver::enquireLink();
HANDLE hwait[] = {m_response_event, m_hDisconnectEvent, m_hKillEvent};
DWORD ret = WaitForMultipleObjects(3, hwait, FALSE, 30000);
if (ret == WAIT_OBJECT_0)
{
if (m_last_error)
*pret = VARIANT_FALSE;
else
*pret = VARIANT_TRUE;
}
else
*pret = VARIANT_FALSE;
ResetEvent(m_response_event);
LeaveCriticalSection(&m_cs); //leave m_cs
return S_OK;
}
STDMETHODIMP CEsmeTransceiverCom::init(BSTR svrip, LONG port)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
USES_CONVERSION;
LPSTR sip = OLE2A(svrip);
CEsmeTransceiver::init(sip, port);
return S_OK;
}
STDMETHODIMP CEsmeTransceiverCom::close(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
CEsmeTransceiver::close();
return S_OK;
}
STDMETHODIMP CEsmeTransceiverCom::get_Connected(VARIANT_BOOL* pVal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
if (CEsmeTransceiver::isConnected())
{
*pVal = VARIANT_TRUE;
}
else
{
*pVal = VARIANT_FALSE;
}
return S_OK;
}
STDMETHODIMP CEsmeTransceiverCom::submitMessage(ISubmitSMCom* isubmit, BSTR* pMsgid, VARIANT_BOOL* pret)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: Add your implementation code here
CSubmitSM sm;
USES_CONVERSION;
BSTR svrtype;
isubmit->get_ServiceType(&svrtype);
LPSTR stype = OLE2A(svrtype);
sm.setServiceType(stype);
SHORT dc, esm, repif, priflag, proid, defmsg, regdel;
isubmit->get_dataCoding(&dc);
isubmit->get_esmClass(&esm);
isubmit->get_replaceIfPresent(&repif);
isubmit->get_priorityFlag(&priflag);
isubmit->get_protocolID(&proid);
isubmit->get_smDefaultMsgId(&defmsg);
isubmit->get_registeredDelivery(®del);
sm.setDataCoding(dc);
sm.setEsmClass(esm);
sm.setReplaceIfPresent(repif);
sm.setPriorityFlag(priflag);
sm.setProtocolId(proid);
sm.setSmDefaultMsgId(defmsg);
sm.setRegisteredDelivery(regdel);
SHORT ton, npi;
BSTR addr;
ISmppAddressCom *iaddr;
//getting source
isubmit->get_Source(&iaddr);
iaddr->get_TON(&ton);
iaddr->get_NPI(&npi);
iaddr->get_Address(&addr);
iaddr->Release();
LPSTR paddr = OLE2A(addr);
SysFreeString(addr);
CSmppAddress src(ton, npi, paddr);
//getting destination
isubmit->get_Destination(&iaddr);
iaddr->get_TON(&ton);
iaddr->get_NPI(&npi);
iaddr->get_Address(&addr);
iaddr->Release();
paddr = OLE2A(addr);
SysFreeString(addr);
CSmppAddress dst(ton, npi, paddr);
//assing source and destination
sm.setSource(src);
sm.setDestination(dst);
ISmppDateCom *idate;
BSTR strdate;
//getting ScheduledDelivery
isubmit->get_scheduledDelivery(&idate);
idate->toString(&strdate);
LPSTR sdt = OLE2A(strdate);
idate->Release();
CSmppDate schdel;
schdel.setDate(sdt);
//getting ValidityPeriod
isubmit->get_validityPeriod(&idate);
idate->toString(&strdate);
sdt = OLE2A(strdate);
idate->Release();
CSmppDate valprd;
valprd.setDate(sdt);
//assign scheduledDelivery and validityPeriod to sm
sm.setScheduledDelivery(schdel);
sm.setValidityPeriod(valprd);
VARIANT var;
isubmit->getMessage(&var);
SAFEARRAY *psa = var.parray;
BYTE *padata;
int nsize = psa->rgsabound->cElements;
SafeArrayAccessData(psa, (void **) &padata);
sm.setMessage(padata, nsize);
SafeArrayUnaccessData(psa);
//
//okay, we've setting up the SubmitSM, send it
//
EnterCriticalSection(&m_cs); //enter m_cs
ResetEvent(m_response_event);
CEsmeTransceiver::submitMessage(sm);
HANDLE hwait[] = {m_response_event, m_hDisconnectEvent, m_hKillEvent};
DWORD ret = WaitForMultipleObjects(3, hwait, FALSE, 30000);
if (ret == WAIT_OBJECT_0)
{
if (m_last_error)
*pret = VARIANT_FALSE;
else
{
*pret = VARIANT_TRUE;
*pMsgid = m_last_msg_id.AllocSysString();
}
}
else
*pret = VARIANT_FALSE;
ResetEvent(m_response_event);
LeaveCriticalSection(&m_cs); //leave m_cs
return S_OK;
}
//registered callback to handle SMPP packets sent from SMSC
//(must be static class method or global procedure)
void __stdcall CEsmeTransceiverCom::processPacketProc(CPacketBase *pak, LPVOID param)
{
CEsmeTransceiverCom *pTrans = (CEsmeTransceiverCom *) param;
//route to instance method, so it can access instance attributes
pTrans->processPacket(pak);
}
//actuallly SMPP packets are in turns handled here
void CEsmeTransceiverCom::processPacket(CPacketBase *pak)
{
switch (pak->getCommandId())
{
case SMPP_ENQUIRE_LINK:
{
//SMSC requested us to send querylink response
CEnquireLink *pPak;
pPak = static_cast<CEnquireLink *>(pak);
//automatic reponse for enquery link
CEnquireLinkResp elresp(*pPak);
sendPacket(elresp);
}
break;
case SMPP_DELIVER_SM:
{
//got a deliver SM
CDeliverSM *pPak;
pPak = static_cast<CDeliverSM *>(pak);
//automatic response deliversm reponse
CDeliverSMResp dresp (*pPak);
sendPacket(dresp);
//notify client for the deliver SM
NotifyClientDeliverSM(pPak);
}
break;
case SMPP_BIND_TRANSCEIVER_RESP:
{
//bind transceiver response
CBindTransceiverResp *pPak;
pPak = static_cast<CBindTransceiverResp *>(pak);
if (pPak->getCommandStatus() == 0)
{
m_last_error = false;
}
else
{
m_last_error = true;
}
SetEvent(m_response_event);
}
break;
case SMPP_UNBIND_RESP:
{
//unbind response
CUnbindResp *pPak;
pPak = static_cast<CUnbindResp *>(pak);
if (pPak->getCommandStatus() == 0)
{
m_last_error = false;
}
else
{
m_last_error = true;
}
SetEvent(m_response_event);
}
break;
case SMPP_SUBMIT_SM_RESP:
{
//Submit Short Message Response
CSubmitSMResp *pPak;
pPak = static_cast<CSubmitSMResp *>(pak);
if (pPak->getCommandStatus() == 0)
{
m_last_msg_id = pPak->getMessageId();
m_last_error = false;
}
else
{
m_last_error = true;
}
SetEvent(m_response_event);
}
break;
case SMPP_ENQUIRE_LINK_RESP:
{
//Previous EnquireLink is responsed
CEnquireLinkResp *pPak;
pPak = static_cast<CEnquireLinkResp *>(pak);
if (pPak->getCommandStatus() == 0)
{
m_last_error = false;
SetEvent(m_response_event);
}
else
{
m_last_error = true;
}
SetEvent(m_response_event);
}
break;
default:
break;
}
}
void CEsmeTransceiverCom::NotifyClientDeliverSM(CDeliverSM *pak)
{
IDeliverSMCom *pVal;
//create an CDeliverSMCom instance to return
CoCreateInstance( CLSID_DeliverSMCom,
NULL,
CLSCTX_ALL,
IID_IDeliverSMCom,
(void **) &pVal);
USES_CONVERSION;
pVal->put_dataCoding(pak->getDataCoding());
pVal->put_esmClass(pak->getEsmClass());
pVal->put_replaceIfPresent(pak->getReplaceIfPresent());
pVal->put_priorityFlag(pak->getPriorityFlag());
pVal->put_protocolID(pak->getProtocolId());
pVal->put_smDefaultMsgId(pak->getSmDefaultMsgId());
pVal->put_registeredDelivery(pak->getRegisteredDelivery());
//create an CSmppAddressCom for setting addresses
ISmppAddressCom *iaddr;
CoCreateInstance( CLSID_SmppAddressCom,
NULL,
CLSCTX_ALL,
IID_ISmppAddressCom,
(void **) &iaddr);
BSTR addrstr;
//Setting source
CSmppAddress source = pak->getSource();
iaddr->put_TON(source.m_addr_ton);
iaddr->put_NPI(source.m_addr_npi);
addrstr = source.m_addr.AllocSysString();
iaddr->put_Address(addrstr);
SysFreeString(addrstr);
pVal->put_Source(iaddr);
//Setting Destination
CSmppAddress destination = pak->getDestination();
iaddr->put_TON(destination.m_addr_ton);
iaddr->put_NPI(destination.m_addr_npi);
addrstr = destination.m_addr.AllocSysString();
iaddr->put_Address(addrstr);
SysFreeString(addrstr);
pVal->put_Destination(iaddr);
iaddr->Release();
//create an CSmppDate for setting dates
ISmppDateCom *idate;
CoCreateInstance( CLSID_SmppDateCom,
NULL,
CLSCTX_ALL,
IID_ISmppDateCom,
(void **) &idate);
BSTR strdate;
//setting scheduleddelivery
CSmppDate schdate = pak->getScheduledDelivery();
strdate = schdate.toString().AllocSysString();
idate->setDate(strdate);
pVal->put_scheduledDelivery(idate);
SysFreeString(strdate);
//setting validityperiod
CSmppDate vldprd = pak->getValidityPeriod();
strdate = vldprd.toString().AllocSysString();
idate->setDate(strdate);
pVal->put_validityPeriod(idate);
SysFreeString(strdate);
idate->Release();
//setting message
PBYTE pdata;
uint32 nsize;
pak->getMessage(pdata, nsize);
VARIANT var;
VariantInit(&var);
var.vt = VT_ARRAY | VT_UI1;
SAFEARRAY *psa;
SAFEARRAYBOUND bounds = {nsize, 0};
psa = SafeArrayCreate(VT_UI1, 1, &bounds);
BYTE *padata;
SafeArrayAccessData(psa, (void **) &padata);
memcpy(padata, pdata, nsize);
SafeArrayUnaccessData(psa);
var.parray = psa;
pVal->setMessage(var);
//fire notification event
Fire_OnDeliverSM(pVal);
}