📄 mobilecontrol.cpp
字号:
// 发送短信前做分条处理
wzSMSContent_Wide = NULL;
ASSERT ( lpszSMSContent_Byte && strlen(lpszSMSContent_Byte) > 0 );
CStringArray *pAryStr = PartMessengerOrSMSText ( lpszSMSContent_Byte, ENUM_MsgPeerType_Mobile,
ENUM_MsgType_Private, NULL, NULL );
if ( !pAryStr ) return ENUM_ERROR_TYPE_PARAMETER;
for ( int i=0; i<pAryStr->GetSize(); i++ )
{
CString csTextOne = pAryStr->GetAt ( i );
csTextOne.TrimLeft(); csTextOne.TrimRight();
ENUM_ERROR_TYPE eErrorTypeTemp = SendOnePartSMS ( eMobileSMSType, csReceiverMobileNO, bInternationalMobileNO,
csTextOne, wzSMSContent_Wide, dwPMAccount_Sender, Proc_SendSMSEnd, wParam, lParam );
if ( eErrorTypeTemp != ENUM_ERROR_TYPE_SUCCESS )
{
eErrorType = eErrorTypeTemp;
}
}
pAryStr->RemoveAll();
delete pAryStr;
return eErrorType;
}
ENUM_ERROR_TYPE CMobileControl::InfillSMParam (
OUT SM_PARAM &SmParam,
IN CString csReceiverMobileNO // 接收者手机号
)
{
memset ( &SmParam, 0, sizeof(SM_PARAM) );
if ( !m_nInitOK ) return ENUM_ERROR_TYPE_NoneMobile;
GetSMSCNO ();
if ( m_csSMSC.GetLength() <= MIN_MOBILENO_LENGTH )
{
LogML ( L_ERROR, "SMSC Error, Cancel send SMS to(#4) [%s]", csReceiverMobileNO );
return ENUM_ERROR_TYPE_ConfigNotRight;
}
CString csSMSC = m_csSMSC;
// 填充短消息结构
StandardMobileNOHead ( csSMSC );
STRNCPY_CS(SmParam.SCA, csSMSC);
STRNCPY_CS(SmParam.TPA, csReceiverMobileNO);
SmParam.TP_PID = 0;
return ENUM_ERROR_TYPE_SUCCESS;
}
//
// 发送短信,过长的短信,这个模块不会处理,请在调用前先处理
//
ENUM_ERROR_TYPE CMobileControl::SendOnePartSMS (
ENUM_MOBILESMSTYPE eMobileSMSType,
LPCTSTR lpszReceiverMobileNO, // 接收者手机号
BOOL bInternationalMobileNO,
LPCTSTR lpszSMSContent_Byte, // 单字节短信内容
WCHAR *wzSMSContent_Wide/*=NULL*/, // 宽字符短信内容
DWORD dwPMAccount_Sender/*=INVALID_PMACCOUNT*/, // 发送者的 PM 号码
FUNC_SendSMSEnd Proc_SendSMSEnd/*=NULL*/, // 发送完成时通过该回调函数来通知请求者
WPARAM wParam/*=NULL*/,
LPARAM lParam/*=NULL*/
)
{
if ( !lpszSMSContent_Byte || strlen(lpszSMSContent_Byte) <= 0 )
return ENUM_ERROR_TYPE_IllegalData;
// 完全相同(短信内容和接收者手机号相同)的短信在 SAME_SMS_INTERVAL_TIMELONG 秒内不允许发送
// 防止短信炸弹,也防止 UDP 通信时收到重发的短信包
#ifdef _PUBLISH
static CString csReceiverMobileNO_Last, csSMSContent_Last;
static time_t tTimeLast = 0;
if ( csReceiverMobileNO_Last == lpszReceiverMobileNO &&
csSMSContent_Last == lpszSMSContent_Byte )
{
if ( difftime ( time(NULL), tTimeLast ) < SAME_SMS_INTERVAL_TIMELONG )
{
return ENUM_ERROR_TYPE_RequestHandling;
}
}
csReceiverMobileNO_Last = GET_SAFE_STRING ( lpszReceiverMobileNO );
csSMSContent_Last = GET_SAFE_STRING ( lpszSMSContent_Byte );
tTimeLast = time(NULL);
#endif
// 队列是否满了?
m_CSFor_SMSSendQueue.Lock ();
if ( m_Ary_SMS_SendQueue.GetSize() > MAX_SMSQUEUE_NUM )
{
m_CSFor_SMSSendQueue.Unlock ();
return ENUM_ERROR_TYPE_BufferQueueFill;
}
m_CSFor_SMSSendQueue.Unlock ();
// 创建一个队列节点
t_SMS_SendQueue SMS_SendQueue;
memset ( &SMS_SendQueue, 0, sizeof(t_SMS_SendQueue) );
SMS_SendQueue.dwPMAccount_Sender = dwPMAccount_Sender;
SMS_SendQueue.Proc_SendSMSEnd = Proc_SendSMSEnd;
SMS_SendQueue.wParam = wParam;
SMS_SendQueue.lParam = lParam;
SMS_SendQueue.eMobileSMSType = eMobileSMSType;
ENUM_ERROR_TYPE eErrorType = InfillSMParam ( SMS_SendQueue.sm, GET_SAFE_STRING(lpszReceiverMobileNO) );
STRNCPY_SZ ( SMS_SendQueue.sm.TP_UD_Byte, lpszSMSContent_Byte );
if ( wzSMSContent_Wide )
{
wcsncpy ( SMS_SendQueue.sm.TP_UD_Wide, wzSMSContent_Wide, LENGTH(SMS_SendQueue.sm.TP_UD_Wide) );
}
SMS_SendQueue.sm.bInternationalMobileNO = bInternationalMobileNO;
if ( eErrorType != ENUM_ERROR_TYPE_SUCCESS )
return eErrorType;
// 做服务器运行时,将要发送的短信包添加到队列中
BOOL bRes = TRUE;
if ( m_bRunAsServer )
{
m_CSFor_SMSSendQueue.Lock ();
m_Ary_SMS_SendQueue.Add ( SMS_SendQueue );
m_CSFor_SMSSendQueue.Unlock ();
// 然后通知手机工作线程
ASSERT ( m_hEvt_SMSSendQueue && m_hEvt_SMSSendQueue != INVALID_HANDLE_VALUE );
::SetEvent ( m_hEvt_SMSSendQueue );
}
// 单机版时直接发送短信
else
{
bRes = SendOneSMSQueue ( SMS_SendQueue );
}
return ( bRes ? ENUM_ERROR_TYPE_SUCCESS : ENUM_ERROR_TYPE_SendSMSFailed );
}
//
// 发送短信队列里的短信
//
BOOL CMobileControl::SendSMSQueue ()
{
ASSERT ( m_bRunAsServer );
// 发送队列里的一条短消息
m_CSFor_SMSSendQueue.Lock ();
if ( m_Ary_SMS_SendQueue.GetSize() <= 0 )
{
m_CSFor_SMSSendQueue.Unlock ();
return TRUE;
}
t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 );
t_SMS_SendQueue SMS_SendQueue;
memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) );
m_Ary_SMS_SendQueue.RemoveAt ( 0 );
m_CSFor_SMSSendQueue.Unlock ();
BOOL bRes = SendOneSMSQueue ( SMS_SendQueue );
// 系统要退出了
if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
return TRUE;
else
{
m_CSFor_SMSSendQueue.Lock ();
// 还有短信需要发送
if ( m_Ary_SMS_SendQueue.GetSize() > 0 )
{
::SetEvent ( m_hEvt_SMSSendQueue );
}
m_CSFor_SMSSendQueue.Unlock ();
}
return TRUE;
}
BOOL CMobileControl::SendOneSMSQueue ( t_SMS_SendQueue &SMS_SendQueue )
{
ASSERT ( m_nInitOK );
ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE );
// 系统要退出了
if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
{
if ( SMS_SendQueue.Proc_SendSMSEnd )
{
SMS_SendQueue.Proc_SendSMSEnd ( ENUM_ERROR_TYPE_SySTerminate,
SMS_SendQueue.wParam, SMS_SendQueue.lParam );
}
return FALSE;
}
int nTotalCharNum = 0, nFreeCharNum = 0, nTP_DCS = 0;
int nOneSMSByteCount = ParseSMSContentAttr ( SMS_SendQueue.sm.TP_UD_Byte,
&nTotalCharNum, &nFreeCharNum, &nTP_DCS );
SMS_SendQueue.sm.TP_DCS = nTP_DCS;
ASSERT ( nFreeCharNum >= 0 );
// 附加短信“ PM:111 send by 'callgle' ”
CString csAppText;
if ( IS_CallgleClient_PMACCOUNT ( SMS_SendQueue.dwPMAccount_Sender ) )
csAppText.Format ( "\nPM:%u\nSend by \"%s\"", SMS_SendQueue.dwPMAccount_Sender, CALLGLE_ENGLISH_NAME );
else
csAppText.Format ( "\nSend by \"%s\"", CALLGLE_ENGLISH_NAME );
int nAppTextTotalCharNum = 0;
ParseSMSContentAttr ( csAppText.GetBuffer(0), &nAppTextTotalCharNum );
if ( nAppTextTotalCharNum < nFreeCharNum )
{
int nLen = strlen ( SMS_SendQueue.sm.TP_UD_Byte );
hwSnprintf ( SMS_SendQueue.sm.TP_UD_Byte+nLen, LENGTH(SMS_SendQueue.sm.TP_UD_Byte)-nLen,
"%s", csAppText );
WCHAR wzAppText[256] = {0};
::MultiByteToWideChar(CP_ACP, 0, csAppText, csAppText.GetLength(),
wzAppText, sizeof(wzAppText) );
nLen = wcslen ( SMS_SendQueue.sm.TP_UD_Wide );
if ( nLen > 0 )
{
_snwprintf ( SMS_SendQueue.sm.TP_UD_Wide+nLen, LENGTH(SMS_SendQueue.sm.TP_UD_Wide)-nLen,
L"%s", wzAppText );
}
}
BOOL bRet = SendOneSMSPkt ( &(SMS_SendQueue.sm) );
if ( SMS_SendQueue.Proc_SendSMSEnd )
{
SMS_SendQueue.Proc_SendSMSEnd ( bRet?ENUM_ERROR_TYPE_SUCCESS:ENUM_ERROR_TYPE_SendSMSFailed, SMS_SendQueue.wParam, SMS_SendQueue.lParam );
}
if ( bRet && m_pdwSentSMSCount )
{
(*m_pdwSentSMSCount) ++;
}
// 将发送完的短信保存到数据库
if ( m_pHwMysql_PMMsg )
{
CString csSMSContent = SMS_SendQueue.sm.TP_UD_Byte;
int nFindPos = csSMSContent.Find ( "\nPM:", 0 );
if ( nFindPos >= 0 )
csSMSContent = csSMSContent.Left ( nFindPos );
else
{
nFindPos = csSMSContent.Find ( "\nSend by", 0 );
if ( nFindPos >= 0 )
csSMSContent = csSMSContent.Left ( nFindPos );
}
m_pHwMysql_PMMsg->SaveSMSToHistoryRecord (
SMS_SendQueue.dwPMAccount_Sender,
SimplifyMobileNO(SMS_SendQueue.sm.TPA),
SMS_SendQueue.eMobileSMSType,
ENUM_SMSOrientation_Send,
(bRet?ENUM_BOOL_TRUE:ENUM_BOOL_FALSE),
NULL,
csSMSContent );
}
return bRet;
}
void CMobileControl::ClearSendQueue ()
{
// 还有短信需要发送
while ( TRUE )
{
m_CSFor_SMSSendQueue.Lock ();
if ( m_Ary_SMS_SendQueue.GetSize() <= 0 )
{
m_CSFor_SMSSendQueue.Unlock ();
break;
}
t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 );
t_SMS_SendQueue SMS_SendQueue;
memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) );
m_Ary_SMS_SendQueue.RemoveAt ( 0 );
m_CSFor_SMSSendQueue.Unlock ();
SendOneSMSQueue ( SMS_SendQueue );
}
}
BOOL CMobileControl::HandleRecvSMS(SM_PARAM *pSMRecv)
{
ASSERT ( pSMRecv );
if ( GetMobileStatus() == ENUM_ERROR_TYPE_MobileDisable )
{
LogML ( L_WARNING, "Discard recevied SMS $[%s : %s]$, because Mobile mobule %s",
pSMRecv->TPA, pSMRecv->TP_UD_Byte, g_pErrorTypeDesc[ENUM_ERROR_TYPE_MobileDisable] );
return FALSE;
}
if ( !CHwMobile::HandleRecvSMS ( pSMRecv ) )
return FALSE;
CString csTemp = SimplifyMobileNO ( pSMRecv->TPA );
STRNCPY_CS ( pSMRecv->TPA, csTemp );
ASSERT ( m_Proc_ReceivedSMS );
return m_Proc_ReceivedSMS ( pSMRecv, m_wParam, m_lParam );
}
//
// 读手机里的短信最新收到的短信
//
BOOL CMobileControl::ReadNewSMS ()
{
if ( !m_bRecvSMSEnable ) return TRUE;
ASSERT ( m_nInitOK );
ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE );
// 系统要退出了
if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
return TRUE;
if ( !QueryDeviceExist () )
{
return FALSE;
}
// 收短信通知
return gsmReadMessageContent ( "+CMT:" );
}
//
// 读取手机中已经存在的所有短信
//
BOOL CMobileControl::ReadExistSMSInMobile()
{
if ( !m_bRecvSMSEnable ) return TRUE;
if ( Write ( "AT+CMGL=4\r" ) < 1 )
return FALSE;
if ( !WaitForDataToRead ( 2, 5*WAIT_DATA_TIMEOUT ) )
return FALSE;
return gsmReadMessageContent ( "+CMGL:" );
}
//
// 读取手机所有电话本。
// 注意:及时删除返回的指针
//
t_Ary_PhoneBook* CMobileControl::ReadPhoneBook()
{
t_Ary_PhoneBook *pAry_PhoneBook = new t_Ary_PhoneBook;
if ( !pAry_PhoneBook )
{
::AfxThrowMemoryException ();
return NULL;
}
pAry_PhoneBook->SetSize ( 0, 10*sizeof(t_PhoneBook) );
if ( !gsmReadPhoneBook ( "SM", pAry_PhoneBook ) )
return pAry_PhoneBook;
if ( !gsmReadPhoneBook ( "ME", pAry_PhoneBook ) )
return pAry_PhoneBook;
return pAry_PhoneBook;
}
LPCTSTR CMobileControl::GetObjectName()
{
return "Mobile control module";
}
//
// 检测字符串 lpszStr 的是否以字符串 lpszHead1 或 lpszHead2 或 lpszHead3 开头
//
LPCTSTR CMobileControl::CheckHeadStr ( LPCTSTR lpszStr, LPCTSTR lpszHead1, LPCTSTR lpszHead2, LPCTSTR lpszHead3 )
{
if ( !lpszStr || !lpszHead1 || strlen(lpszStr) <= 0 )
return NULL;
if ( strstr ( lpszStr, lpszHead1 ) == lpszStr )
return lpszHead1;
if ( lpszHead2 && strstr ( lpszStr, lpszHead2 ) == lpszStr )
return lpszHead2;
if ( lpszHead3 && strstr ( lpszStr, lpszHead3 ) == lpszStr )
return lpszHead3;
return NULL;
}
//
// 标准化短信内容,把全角的数字和符号变为半角的
//
// 全角简体中文
char* f_szSBCSimp[] =
{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "#", "%", "?", "!",
""
};
// 半角
char* f_szDBCEng[] =
{
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "#", "%", "?", "!",
""
};
// 全角繁体中文
char* f_SBCTrad[] =
{
"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -