为朋友写的一个管理modem池的类,post到这儿顺便自己有机会才看,不知道n年后再看这段代码会不会痛心...
文件smssocket.h
#pragma once
#include "socketthread.h"
class CSmsSocket: public CSocketThread
{
public:
CSmsSocket(void);
~CSmsSocket(void);
long StartThread(void *pParam) ;
long StopThread() ;
long PushData2AgentOutBuf(AFFAIR_CONTEXT &affair_context);
long CloseTerminate(char *pSimNumber);
private:
#pragma pack(push,1)
typedef struct _SMS_HEAD
{
char chSMSC[2];//SMSC地址信息,在本程序中,默认为0
char TP_VFP[2];//基本参数(TP-MTI/VFP),默认为11
char TP_MR[2];//TP-MR,默认为00
char chTargetCnt[2];//目标地址数字个数,一般为0d
char chTargetNumber[16];//91 68 31 58 81 27 64 F8
char TP_PID[2];//协议标识(TP-PID)
char TP_DCS[2];//用户信息编码方式(TP-DCS
char TP_VP[2];//有效期(TP-VP) 5分钟
char TP_UD[2];//用户信息(TP-UD)
}SMS_HEAD,*LPSMS_HEAD;
typedef struct _SMS_CONTEXT
{
AFFAIR_CONTEXT stAffairContext;
SMS_HEAD stSmsHead;
char stSmsData[MAX_PACKAGE_CNT];
}SMS_CONTEXT,*PSMS_CONTEXT;
typedef struct _RECV_SMS_HEAD
{
char chSourceNumber[16];//91 68 31 58 81 27 64 F8
char TP_VFP[2];//基本参数(TP-MTI/VFP),默认为11
char chTargetCnt[2];//目标地址数字个数,一般为0d
char chTargetNumber[16];//91 68 31 58 81 27 64 F8
char TP_PID[2];//协议标识(TP-PID)
char TP_DCS[2];//用户信息编码方式(TP-DCS
char TP_SCTS[14];//时间戳(TP-SCTS)
char TP_UD[2];//用户信息长度(TP-UDL)
char stSmsData[MAX_PACKAGE_CNT];
}RECV_SMS_HEAD,*LPRECV_SMS_HEAD;
#pragma pack(pop)
void CloseSocket(PPER_SOCKET_CONTEXT,BOOL bNeedNegal = FALSE);
static void DealModemDataThread(void *pParam);
long DealTerminate2ServerInvoke(PPER_TERMINATE_CONTEXT,PAFFAIR_HEAD);
long DealTerminate2ServerRespond(PPER_TERMINATE_CONTEXT,PAFFAIR_HEAD);
long DealTerminate2ServerAbort(PPER_TERMINATE_CONTEXT,PAFFAIR_HEAD);
long DealServer2TerminateInvoke(PPER_TERMINATE_CONTEXT,PAFFAIR_HEAD);
long DealServer2TerminateRespond(PPER_TERMINATE_CONTEXT,PAFFAIR_HEAD);
long DealServer2TerminateAbort(PPER_TERMINATE_CONTEXT,PAFFAIR_HEAD);
long AdjustNeedSendData2Agent();
int OpenComInitModem(int iWhichCom,HANDLE &pComHandle);
int LetModemReRecvAgain(PPER_SOCKET_CONTEXT pPerIoContext);
int FindModemAnswerFromBackString(const char *pModemBackString,DWORD *pModemAnswer);
long SendInitAtCommand(PPER_SOCKET_CONTEXT pPerIoContext);
long SendData2Modem(PPER_SOCKET_CONTEXT pWhichModem,const unsigned char *pDataBuf,int iSendCnt);
long SendSmsRequest2Modem(PPER_SOCKET_CONTEXT pWhichModem,int iSmsCnt);
long DecodeRecvSms(PPER_SOCKET_CONTEXT pWhichModem);
long DecodeSmsIn2BinaryStream(const LPRECV_SMS_HEAD pRecvSmsHead,PAFFAIR_HEAD pAffairHead);
CMainThread *m_pMainThread;
THREAD_STATE m_iThreadState;
HANDLE m_hModemThread;
HANDLE m_hModemIocp;
CRITICAL_SECTION m_csVisitData;
CRITICAL_SECTION m_csVisitLocalModem;
typedef enum MODEM_ANSWER{AT_ERROR =1,AT_OK=2,AT_READY=4,AT_RING=8
,AT_WIND=16,AT_CLIP=32,AT_GOONSEND,AT_CMTI=64};
list<PER_SOCKET_CONTEXT> m_LocalModemQueue;
list<SMS_CONTEXT> m_SendOutSmsQueue;
};
#include "smssocket.h"
#include "mainthread.h"
#include "clientthread.h"
#include "function.h"
CSmsSocket::CSmsSocket()
:m_hModemIocp(INVALID_HANDLE_VALUE)
,m_hModemThread(INVALID_HANDLE_VALUE)
,m_iThreadState(NOT_RUN)
{
}
CSmsSocket::~CSmsSocket()
{
if (INVALID_HANDLE_VALUE != m_hModemThread)
{
CloseHandle(m_hModemThread);
m_hModemThread =INVALID_HANDLE_VALUE;
}
}
long CSmsSocket::StartThread(void *pParam)
{
TraceInfo(RGB(0,0,255),"终端监听线程初始化..../n");
m_iThreadState = STOPPED;
_ASSERT(NULL != pParam);
m_pMainThread = (CMainThread*)pParam;
_ASSERT(m_hModemThread ==INVALID_HANDLE_VALUE);
if (m_hModemThread != INVALID_HANDLE_VALUE)
{
StopThread();
}
m_hModemIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
_ASSERT(m_hModemIocp != NULL);
if (m_hModemIocp != NULL)
{
TraceInfo(RGB(0,0,255),"串口监听线程完成端口建立成功..../n");
InitializeCriticalSection(&m_csVisitLocalModem );
InitializeCriticalSection(&m_csVisitData);
int iComCnt = GetPrivateProfileInt ("SMS","comcnt",1,INIFILENAME);
int i =0;
int iComIndex = 0;
char csScoket[32] = {0};
HANDLE sScoket = INVALID_HANDLE_VALUE;
for (i=0;i<iComCnt;++i)
{
sprintf(csScoket,"comport%d",i+1);
iComIndex = GetPrivateProfileInt ("SMS",csScoket,1,INIFILENAME);
if (0 != OpenComInitModem(iComIndex,sScoket) && INVALID_HANDLE_VALUE != sScoket)
{
CloseHandle(sScoket);
sScoket = INVALID_HANDLE_VALUE;
}
}
m_hModemThread =(HANDLE) _beginthread(DealModemDataThread,0,this);
m_iThreadState = (m_hModemThread != INVALID_HANDLE_VALUE ? RUNNING :STOPPED);
}
return m_iThreadState;
}
long CSmsSocket::StopThread()
{
m_iThreadState = WANT_STOP;
return ::WaitForSingleObject (m_hModemThread,1000);
}
int CSmsSocket::OpenComInitModem(int iWhicsScoket,HANDLE &pComHandle)
{
if (iWhicsScoket <1 || iWhicsScoket > 33)
return 1;
if (pComHandle == NULL || IsBadWritePtr(&pComHandle,sizeof(HANDLE)))
return 2;
char csScoketName[32] = {0};
sprintf(csScoketName,".//COM%d",iWhicsScoket);
char chBand [256] = {0};
int iBand = GetPrivateProfileInt ("SMS","band",115200,INIFILENAME);
sprintf(chBand,"baud=%d parity=%c data=%d stop=%d", iBand, 'n', 8, 1);
pComHandle = CreateFile(csScoketName,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING
,FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL,0);
if (pComHandle == INVALID_HANDLE_VALUE)
return 3;
static COMMTIMEOUTS stCommTimeouts = {1790,10000,100000,100,1000};
if (!SetCommTimeouts(pComHandle, &stCommTimeouts))
{
CloseHandle(pComHandle);
pComHandle = INVALID_HANDLE_VALUE;
return 4;
}
DWORD dwCommEvents = 0;
if (! SetCommMask(pComHandle, dwCommEvents))
{
CloseHandle(pComHandle);
pComHandle = INVALID_HANDLE_VALUE;
return 5;
}
DCB dcb={0};
if (! GetCommState(pComHandle, &dcb))
{
CloseHandle(pComHandle);
pComHandle = INVALID_HANDLE_VALUE;
return 6;
}
dcb.fBinary = TRUE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
if (! BuildCommDCB(chBand, &dcb))
{
CloseHandle(pComHandle);
pComHandle = INVALID_HANDLE_VALUE;
return 7;
}
if (! SetCommState(pComHandle, &dcb))
{
CloseHandle(pComHandle);
pComHandle = INVALID_HANDLE_VALUE;
return 8;
}
list<PER_SOCKET_CONTEXT>::iterator iterAgent = NULL;
PER_SOCKET_CONTEXT perSocketContext = {0};
perSocketContext.modemStatus = S_NOT_INIT;
m_LocalModemQueue.push_back (perSocketContext);
iterAgent = m_LocalModemQueue.end ();
-- iterAgent;
if (iterAgent == m_LocalModemQueue.end ())
{
return 11;
}
PER_SOCKET_CONTEXT *lpModemContext = (PPER_SOCKET_CONTEXT)(&(iterAgent->Overlapped ));
lpModemContext->sScoket = (SOCKET)pComHandle;
lpModemContext->CurrentIoOperation = IO_RECV;
lpModemContext->SendBuffer.buf = lpModemContext->SendData ;
lpModemContext->SendBuffer.len = MAX_PACKAGE_CNT;
lpModemContext->RecvBuffer.buf = lpModemContext->RecvData ;
lpModemContext->RecvBuffer.len = MAX_PACKAGE_CNT;
sprintf(lpModemContext ->chSocketIp,"串口%02d",iWhicsScoket);
TraceInfo(RGB(0,0,255),"初始化%s成功!/n",lpModemContext ->chSocketIp);
m_hModemIocp = CreateIoCompletionPort(pComHandle, m_hModemIocp, (DWORD)lpModemContext, 0);
return SendInitAtCommand(lpModemContext);
}
int CSmsSocket::LetModemReRecvAgain(PPER_SOCKET_CONTEXT pPerIoContext)
{
//在每次发送前,把所有末完成的io操作全部取消掉
if (!HasOverlappedIoCompleted(&(pPerIoContext->Overlapped) ))
{
TraceInfo(RGB(0,0,255),"中止[%s]先前进行的IO操作!/n",pPerIoContext->chSocketIp );
CancelIo((HANDLE)pPerIoContext->sScoket );
}
pPerIoContext->CurrentIoOperation = IO_RECV;
DWORD dwRecvNumBytes = 0;
return ReadFile((HANDLE)pPerIoContext->sScoket , &(pPerIoContext->RecvData)
,MAX_PACKAGE_CNT,&dwRecvNumBytes,&(pPerIoContext->Overlapped));
}
int CSmsSocket::FindModemAnswerFromBackString(const char *pModemBackString,DWORD *pModemAnswer)
{
_ASSERT(!IsBadReadPtr(pModemBackString,4));
if (IsBadReadPtr(pModemBackString,4))
return 1;
_ASSERT(!IsBadWritePtr(pModemAnswer,sizeof(DWORD)));
if (IsBadWritePtr(pModemAnswer,sizeof(DWORD)))
return 2;
int iModemAnswer = 0;
int iSubStatus = 0;
*pModemAnswer = 0;
char *pFindModemAnswer = (char*)pModemBackString;
if (NULL != strstr(pFindModemAnswer,"RING"))
{
iModemAnswer |= AT_RING;
}
if (NULL != strstr(pFindModemAnswer,"ERROR"))
{
iModemAnswer |= AT_ERROR;
}
if (NULL != strstr(pFindModemAnswer,"WIND"))
{
iModemAnswer |= AT_WIND;
}
if (NULL != strstr(pFindModemAnswer,"CLIP"))
{
iModemAnswer |= AT_WIND;
}
if (NULL != strstr(pFindModemAnswer,"OK") || NULL != strstr(pFindModemAnswer,"READY"))
{
iModemAnswer |= AT_OK;
}
if (NULL != strstr(pFindModemAnswer,">"))
{
iModemAnswer |= AT_GOONSEND;
}
if (NULL != strstr(pFindModemAnswer,"+CMTI:"))
{
iModemAnswer |= AT_CMTI;
char *pFindSmsCnt = strstr(pFindModemAnswer,"+CMTI:");
char *pFindLastCMTI = strstr(pFindSmsCnt,"+CMTI:");
while (pFindLastCMTI != NULL)
{
pFindLastCMTI += lstrlen("+CMTI:");
pFindSmsCnt = pFindLastCMTI;
pFindLastCMTI = strstr(pFindSmsCnt,"+CMTI:");
}
pFindSmsCnt = strstr(pFindSmsCnt,",");
if (pFindSmsCnt != NULL)
{
pFindSmsCnt += 1;
iSubStatus = strtol(pFindSmsCnt,NULL,10);
}
}
*pModemAnswer = MAKELONG(iModemAnswer,iSubStatus);
return iModemAnswer >0 ? 0 : 3;
}
long CSmsSocket::SendInitAtCommand(PPER_SOCKET_CONTEXT pWhichModem)
{
const char *InitAtCommand[]={"AT/r","ATH/r","ATE0/r","AT+CMEE=1/r"
,"AT+CRC=1/r","AT+CLIP=1/r","AT+CMGF=0/r","AT+CPIN?/r","AT+CMGD=1,4/r"};
if (pWhichModem->modemStatus != S_NOT_INIT)
{
_ASSERT(0);
return 1;
}
if (pWhichModem->initAtCommand <S_END_INIT)
{
char *pSendAt = (char*)InitAtCommand[pWhichModem->initAtCommand ];
return SendData2Modem(pWhichModem,(const BYTE*)pSendAt,lstrlen(pSendAt));
}
else
{
pWhichModem->modemStatus =S_MODEM_IDLE;
return LetModemReRecvAgain(pWhichModem);
}
}
long CSmsSocket::SendSmsRequest2Modem(PPER_SOCKET_CONTEXT pWhichModem,int iSmsCnt)
{
pWhichModem->modemStatus =S_MODEM_ACQUIRE;
unsigned char chTemp[256] = {0};
sprintf((char*)chTemp,"AT+CMGS=%d/r",iSmsCnt );
return SendData2Modem(pWhichModem,chTemp,lstrlen((char*)chTemp));
}
long CSmsSocket::SendData2Modem(PPER_SOCKET_CONTEXT pWhichModem,const unsigned char *pDataBuf,int iSendCnt)
{
if (IsBadReadPtr(pWhichModem,sizeof(PPER_SOCKET_CONTEXT)))
return 1;
if (IsBadReadPtr(pDataBuf,iSendCnt))
return 2;
if (INVALID_HANDLE_VALUE == (HANDLE)pWhichModem ->sScoket )
return 3;
if (pWhichModem->modemStatus == S_MODEM_IDLE)
{
pWhichModem->modemStatus = S_MODEM_WAIT;
}
if (!HasOverlappedIoCompleted(&(pWhichModem->Overlapped) ))
{
TraceInfo(RGB(0,0,255),"中止[%s]先前进行的IO操作!/n",pWhichModem->chSocketIp );
CancelIo((HANDLE)pWhichModem->sScoket );
}
pWhichModem->CurrentIoOperation = IO_SEND;
memcpy(pWhichModem->SendData,pDataBuf,iSendCnt);
pWhichModem->SendBuffer.len = iSendCnt;
DWORD dwSendNumBytes =0;
TraceInfo(RGB(0,0,255),"%s发送数据%s",pWhichModem->chSocketIp,pWhichModem->SendData);
TraceData(pWhichModem->SendData,iSendCnt);
return WriteFile((HANDLE)pWhichModem ->sScoket,&(pWhichModem->SendData)
, iSendCnt, &dwSendNumBytes,&(pWhichModem->Overlapped ));
}
long CSmsSocket::CloseTerminate(char *pSimNumber)
{
return CFunction::SendTermLogin2AllClient (pSimNumber,FALSE);
}
void CSmsSocket::CloseSocket(PPER_SOCKET_CONTEXT lpModemContext,BOOL bNeedNegal )
{
EnterCriticalSection(&m_csVisitLocalModem);
__try
{
list<PER_SOCKET_CONTEXT>::iterator iterDelete = m_LocalModemQueue.begin ();
while (iterDelete != m_LocalModemQueue.end ())
{
if ((PPER_SOCKET_CONTEXT)(&(iterDelete->Overlapped)) == lpModemContext
&& iterDelete->sScoket == lpModemContext->sScoket)
{
CloseHandle((HANDLE)lpModemContext->sScoket);
TraceInfo(RGB(0,0,255),"删除代理[%s]相关信息成功!/n",iterDelete->chSocketIp );
m_LocalModemQueue.erase(iterDelete);
break;
}
++ iterDelete;
}
}
__finally
{
}
LeaveCriticalSection(&m_csVisitLocalModem);
}
long CSmsSocket::DealTerminate2ServerInvoke(PPER_TERMINATE_CONTEXT pper_modem_context,PAFFAIR_HEAD ppaffair_head)
{
//处理modem的invoke包,并必须发送相应的应答数据包到modem
long lResult = 1;
AFFAIR_CONTEXT stAffairContext = {0};
PAFFAIR_HEAD server2modem_head = (PAFFAIR_HEAD)&(stAffairContext.affair_head) ;
memcpy(server2modem_head,ppaffair_head,ppaffair_head->frame_length +2);
if (CLIENT_ADMIN == ppaffair_head->module_index &&ppaffair_head ->command ==TERM_LOGOUT)
{
//通知所有客户端该终端已经被关闭
char sim_card_number[32] = {0};
CFunction::Cast7ByteTo14SimStr((unsigned char*)ppaffair_head->lgsn ,sim_card_number );
sim_card_number[11] = '/0';
list<PER_TERMINATE_CONTEXT>::iterator iterDelete = m_pMainThread->m_TermniteQueue.begin ();
while (iterDelete != m_pMainThread->m_TermniteQueue.end ())
{
if (lstrlen(iterDelete->sim_card_number) >8 && strstr(sim_card_number,iterDelete->sim_card_number ))
{
m_pMainThread->CloseTerminate(iterDelete);
break;
}
++ iterDelete;
}
return 0;
}
else
lResult = CFunction::CheckModem2ServerPackageAndPutResult(ppaffair_head,server2modem_head,pper_modem_context);
if (NEED_SHUTDOWN == server2modem_head->msg_type )
{
//上层模块需要关闭与modem之前的连接
ppaffair_head ->module_index =CLIENT_ADMIN;
ppaffair_head ->msg_type=RESPOND;
ppaffair_head ->command=TERM_LOGOUT;
ppaffair_head->frame_length=sizeof(AFFAIR_HEAD)-2;
}
else if (0 != lResult)
{
//默认将server到modem的应答数据置为放弃本次事务ABORT
TraceInfo(RGB(255,0,0),"终端[%s]提交的INVOKE事务[%d],命令[%s]的处理失败,错误码为[%d]!/n",
pper_modem_context->sim_card_number ,ppaffair_head->sid
,KEYID(ppaffair_head->command) , lResult);
server2modem_head->msg_type = ABORT;
}
server2modem_head->crc = CFunction::CheckCrc16 (
(unsigned char*)&(server2modem_head->frame_length),server2modem_head->frame_length );
return PushData2AgentOutBuf(stAffairContext);
}
long CSmsSocket::DealTerminate2ServerRespond(PPER_TERMINATE_CONTEXT pper_modem_context,PAFFAIR_HEAD ppaffair_head)
{
//该函数处理modem到server的先前的invoke事务的respond
//查找modem的server_2_modem_queue,找到对应的invoke数据包,
list<AFFAIR_CONTEXT>::iterator affair_context_iter = pper_modem_context->server_2_modem_queue ->begin ();
while (affair_context_iter != pper_modem_context->server_2_modem_queue->end ())
{
if (affair_context_iter->affair_head.sid == ppaffair_head->sid &&
affair_context_iter->affair_head.command == (ppaffair_head->command+0x60) )
{
//found that affair
break;
}
++ affair_context_iter;
}
if (affair_context_iter == pper_modem_context->server_2_modem_queue->end ())
{
//如果没有找到,也不需要回复数据包,直接扔掉
TraceInfo(RGB(255,0,0),"终端[%s]Respond数据包[%s]末找到SID[%d]!/n",
pper_modem_context->sim_card_number,KEYID(ppaffair_head->command ),ppaffair_head->sid );
return 1;
}
//找到了,则从server_2_modem_queue删除相应invoke包,并判断是否需要回显给client
PPER_SOCKET_CONTEXT pper_socket_context=(PPER_SOCKET_CONTEXT)affair_context_iter->sender_client;
DWORD dwPackageSize = ppaffair_head->frame_length +sizeof(unsigned short);
DWORD dwRecvNumBytes= 0;
DWORD dwFlags = 0;
int nRet = 0;
//调用crc16检验是否正确,如不是,则继续发送上一包数据
if (ppaffair_head->crc != CFunction::CheckCrc16 (
(unsigned char*)&(ppaffair_head->frame_length ),ppaffair_head->frame_length ))
{
return 2;
}
//发过来的lgsn为modem的ccid,需要将其转化为modem的sim卡号,再发送到客户端
CFunction::Cast14SimStrTo7Byte(pper_modem_context->sim_card_number ,(unsigned char*)ppaffair_head->lgsn );
//调用相应处理模块的处理modem的respond信息函数
CFunction::CheckModemRespondPackage (pper_modem_context,ppaffair_head,pper_socket_context,affair_context_iter);
BOOL bFindAllUserInfoSendIn = affair_context_iter->affair_status ==SENDED_IN ? TRUE : FALSE;
switch ((DWORD)pper_socket_context)
{
case -1:
{
//发送到所有客户端
CClientThread *pClientThread = (CClientThread*)m_pMainThread->m_pClientThread ;
_ASSERT(NULL == pClientThread);
if (NULL != pClientThread)
{
list<PER_SOCKET_CONTEXT>::iterator client_socket_iter =pClientThread->listClientQueue.begin ();
while (client_socket_iter != pClientThread->listClientQueue.end ())
{
pper_socket_context =(PPER_SOCKET_CONTEXT)&(client_socket_iter->Overlapped);
if (pper_socket_context)
{
//只有在modem返回应答后才对有可能client发送数据,所以在这儿不用保护
memcpy(pper_socket_context->SendData ,ppaffair_head,dwPackageSize);
pper_socket_context->SendBuffer.len = dwPackageSize;
nRet = send(pper_socket_context->sScoket ,pper_socket_context->SendData,dwPackageSize,0);
if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) )
{
TraceInfo(RGB(255,0,0),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]失败,错误码为[%d]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),
pper_socket_context->chSocketIp,WSAGetLastError() );
}
else
{
TraceInfo(RGB(0,0,255),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),pper_socket_context->chSocketIp );
}
}
++ client_socket_iter;
}
}
}
break;
case 0:
{
//不需要发送到客户端,是server到modem的invoke
}
break;
default:
{
if (pper_socket_context>0)
{
//只有在modem返回应答后才对有可能client发送数据,所以在这儿不用保护
nRet = send(pper_socket_context->sScoket ,(char*)ppaffair_head,dwPackageSize,0);
if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) )
{
TraceInfo(RGB(255,0,0),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]失败,错误码为[%d]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),
pper_socket_context->chSocketIp,WSAGetLastError() );
}
else
{
TraceInfo(RGB(0,0,255),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),
pper_socket_context->chSocketIp );
}
}
else
{
//不属于上述三种情况就肯定有错了
_ASSERT(0);
}
}
break;
}
//删除该次由client或server到modem的保存在modem中server_2_modem_queue的事务
EnterCriticalSection (&(pper_modem_context->visit_modem_privi ));
TraceInfo(RGB(0,0,255),"终端[%s]的事务[%d]命令[%s]操作完成,剩余事务次数为[%d]!/n",
pper_modem_context->sim_card_number,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),pper_modem_context->server_2_modem_queue->size()-1);
//只是简单的把affair_status置为POPED,在schedulethread中删除相应结构
if (ppaffair_head->command == SACP_USER_ALL_USER_INFO )
{
if (TRUE == bFindAllUserInfoSendIn)
affair_context_iter->affair_status =POPED;
}
else
affair_context_iter->affair_status =POPED;
//开始下一次事务操作吧
pper_modem_context->current_affair = NULL;
LeaveCriticalSection (&(pper_modem_context->visit_modem_privi ));
return 0;
}
long CSmsSocket::DealTerminate2ServerAbort(PPER_TERMINATE_CONTEXT pper_modem_context,PAFFAIR_HEAD ppaffair_head)
{
//该函数处理modem到server的先前的invoke事务的respond
//查找modem的server_2_modem_queue,找到对应的invoke数据包,
list<AFFAIR_CONTEXT>::iterator affair_context_iter = pper_modem_context->server_2_modem_queue ->begin ();
while (affair_context_iter != pper_modem_context->server_2_modem_queue->end ())
{
if (affair_context_iter->affair_head.sid == ppaffair_head->sid &&
affair_context_iter->affair_head.command == (ppaffair_head->command+0x60) )
{
//found that affair
break;
}
++ affair_context_iter;
}
if (affair_context_iter == pper_modem_context->server_2_modem_queue->end ())
{
//如果没有找到,也不需要回复数据包,直接扔掉
return 1;
}
//找到了,则从server_2_modem_queue删除相应invoke包,并判断是否需要回显给client
PPER_SOCKET_CONTEXT pper_socket_context=(PPER_SOCKET_CONTEXT)affair_context_iter->sender_client;
DWORD dwPackageSize = ppaffair_head->frame_length +sizeof(unsigned short);
DWORD dwRecvNumBytes= 0;
DWORD dwFlags = 0;
int nRet = 0;
//调用crc16检验是否正确,如不是,则继续发送上一包数据
if (ppaffair_head->crc != CFunction::CheckCrc16 (
(unsigned char*)&(ppaffair_head->frame_length ),ppaffair_head->frame_length ))
{
return 2;
}
//发过来的lgsn为modem的ccid,需要将其转化为modem的sim卡号,再发送到客户端
CFunction::Cast14SimStrTo7Byte(pper_modem_context->sim_card_number ,(unsigned char*)ppaffair_head->lgsn );
//调用相应处理模块的处理modem的respond信息函数
CFunction::CheckModemAbortPackage (pper_modem_context,ppaffair_head,pper_socket_context,affair_context_iter);
switch ((DWORD)pper_socket_context)
{
case -1:
{
//发送到所有客户端
CClientThread *pClientThread = (CClientThread*)m_pMainThread->m_pClientThread ;
_ASSERT(NULL == pClientThread);
if (NULL != pClientThread)
{
list<PER_SOCKET_CONTEXT>::iterator client_socket_iter =pClientThread->listClientQueue.begin ();
while (client_socket_iter != pClientThread->listClientQueue.end ())
{
pper_socket_context =(PPER_SOCKET_CONTEXT)&(client_socket_iter->Overlapped);
if (pper_socket_context)
{
//只有在modem返回应答后才对有可能client发送数据,所以在这儿不用保护
memcpy(pper_socket_context->SendData ,ppaffair_head,dwPackageSize);
pper_socket_context->SendBuffer.len = dwPackageSize;
nRet = send(pper_socket_context->sScoket ,pper_socket_context->SendData,dwPackageSize,0);
if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) )
{
TraceInfo(RGB(255,0,0),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]失败,错误码为[%d]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),
pper_socket_context->chSocketIp,WSAGetLastError() );
}
else
{
TraceInfo(RGB(0,0,255),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),pper_socket_context->chSocketIp );
}
}
++ client_socket_iter;
}
}
}
break;
case 0:
{
//不需要发送到客户端,是server到modem的invoke
}
break;
default:
{
if (pper_socket_context>0)
{
//只有在modem返回应答后才对有可能client发送数据,所以在这儿不用保护
memcpy(pper_socket_context->SendData ,ppaffair_head,dwPackageSize);
pper_socket_context->SendBuffer.len = dwPackageSize;
nRet = send(pper_socket_context->sScoket ,pper_socket_context->SendData,dwPackageSize,0);
if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) )
{
TraceInfo(RGB(255,0,0),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]失败,错误码为[%d]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),
pper_socket_context->chSocketIp,WSAGetLastError() );
}
else
{
TraceInfo(RGB(0,0,255),"终端接收线程将终端[%s]的事务[%d]命令[%s]的应答数据包发送到客户端[%s]!/n",
pper_modem_context->sim_card_number ,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),
pper_socket_context->chSocketIp );
}
}
else
{
//不属于上述三种情况就肯定有错了
_ASSERT(0);
}
}
break;
}
//删除该次由client或server到modem的保存在modem中server_2_modem_queue的事务
EnterCriticalSection (&(pper_modem_context->visit_modem_privi ));
TraceInfo(RGB(0,0,255),"终端[%s]的事务[%d]命令[%s]操作完成,剩余事务次数为[%d]!/n",
pper_modem_context->sim_card_number,affair_context_iter->affair_head.sid,
KEYID(affair_context_iter->affair_head.command),pper_modem_context->server_2_modem_queue->size()-1);
//只是简单的把affair_status置为POPED,在schedulethread中删除相应结构
affair_context_iter->affair_status =POPED;
//pper_modem_context->server_2_modem_queue ->erase (affair_context_iter);
//开始下一次事务操作吧
pper_modem_context->current_affair = NULL;
LeaveCriticalSection (&(pper_modem_context->visit_modem_privi ));
return 0;
}
long CSmsSocket::DealServer2TerminateInvoke(PPER_TERMINATE_CONTEXT pper_modem_context,PAFFAIR_HEAD ppaffair_head)
{
//该函数处理modem到server的先前的invoke事务的respond
//查找modem的server_2_modem_queue,找到对应的invoke数据包,
list<AFFAIR_CONTEXT>::iterator affair_context_iter = pper_modem_context->server_2_modem_queue ->begin ();
while (affair_context_iter != pper_modem_context->server_2_modem_queue->end ())
{
if (affair_context_iter->affair_head.sid == ppaffair_head->sid &&
affair_context_iter->affair_head.command == ppaffair_head->command )
{
//found that affair
break;
}
++ affair_context_iter;
}
if (affair_context_iter == pper_modem_context->server_2_modem_queue->end ())
{
//如果没有找到,
return 1;
}
char chClientIP[32] = {0};
PPER_SOCKET_CONTEXT per_socket_context=(PPER_SOCKET_CONTEXT)affair_context_iter->sender_client;
if (per_socket_context&&!IsBadWritePtr(per_socket_context,sizeof(PER_SOCKET_CONTEXT)))
sprintf(chClientIP,"客户端%s",per_socket_context->chSocketIp);
else
lstrcpy(chClientIP,"服务器");
//找到了,把该事务的相关信息置位
TraceInfo(RGB(0,0,255),"终端接收线程第[%d]次[%s]到终端[%s]的事务[%d]命令[%s]成功!/n",
affair_context_iter->retry_send_cnt,chClientIP,
pper_modem_context->sim_card_number ,ppaffair_head->sid ,KEYID(ppaffair_head->command) );
affair_context_iter->affair_status =SENDED_OUT;
return 0;
}
long CSmsSocket::DealServer2TerminateRespond(PPER_TERMINATE_CONTEXT pper_modem_context,PAFFAIR_HEAD ppaffair_head)
{
TraceInfo(RGB(0,0,255),"终端[%s]的Respond数据事务[%d]命令[%s]发送成功!/n",
pper_modem_context->sim_card_number ,ppaffair_head->sid ,KEYID(ppaffair_head->command) );
return 0;
}
long CSmsSocket::DealServer2TerminateAbort(PPER_TERMINATE_CONTEXT pper_modem_context,PAFFAIR_HEAD ppaffair_head)
{
TraceInfo(RGB(0,0,255),"终端[%s]的Abort数据事务[%d]命令[%s]发送成功!/n",
pper_modem_context->sim_card_number ,ppaffair_head->sid ,KEYID(ppaffair_head->command) );
return 0;
}
long CSmsSocket::PushData2AgentOutBuf(AFFAIR_CONTEXT &affair_context)
{
EnterCriticalSection(&m_csVisitLocalModem);
__try
{
SMS_CONTEXT stSmsContext = {0};
memcpy(&stSmsContext,&affair_context,sizeof(AFFAIR_CONTEXT));
LPSMS_HEAD pSmsHead = (LPSMS_HEAD)&(stSmsContext.stSmsHead);
memset(pSmsHead,'0',sizeof(SMS_HEAD));
pSmsHead->TP_VFP[0] = '1';
pSmsHead->TP_VFP[1] = '1';
pSmsHead->chTargetCnt[0] = '0';
pSmsHead->chTargetCnt[1] = 'd';
PAFFAIR_HEAD pAffairHead = (PAFFAIR_HEAD)&(affair_context.affair_kind);
char chSimString[32] = {0};
CFunction::Cast7ByteTo14SimStr ((BYTE*)pAffairHead->lgsn,chSimString);
char *pTarget = pSmsHead->chTargetNumber;
lstrcpy(pTarget,"9168");
pTarget += 4;
char *pCast = (char*)chSimString;
if (chSimString[0] == '8' && chSimString[1] =='6')
pCast += 2;
int i=0;
for (;i<6;++i)
{
*pTarget =pCast[i+1];
++ pTarget;
*pTarget=pCast[i];
++ pTarget;
}
pSmsHead->chTargetNumber[14] ='F';
pSmsHead->TP_DCS[1] ='5';
sprintf(pSmsHead->TP_UD,"%02d",pAffairHead->frame_length+2);
if (pAffairHead->frame_length+2 < (MAX_PACKAGE_CNT >> 1) )
{
pTarget = (char*)&(stSmsContext.stSmsData );
pCast = (char*)pAffairHead;
for (i=0;i<pAffairHead->frame_length+2;++i)
{
sprintf(pTarget,"%02X",*pCast);
++ pCast;
pTarget += 2;
}
*pTarget ++= 0x1a;
*pTarget = '/0';
m_SendOutSmsQueue.push_back (stSmsContext);
}
}
__finally
{
}
LeaveCriticalSection(&m_csVisitLocalModem);
return 0;
}
long CSmsSocket::AdjustNeedSendData2Agent()
{
EnterCriticalSection(&m_csVisitLocalModem);
list<SMS_CONTEXT>::iterator pDataOut = m_SendOutSmsQueue.begin ();
list<SMS_CONTEXT>::iterator pSend = NULL;
list<PER_SOCKET_CONTEXT>::iterator pIdelModem = NULL;
PAFFAIR_HEAD pAffairHead = NULL;
PPER_SOCKET_CONTEXT pWhichModem = NULL;
DWORD dwIoSize = 0;
__try
{
while (pDataOut != m_SendOutSmsQueue.end ())
{
pSend = pDataOut;
++ pDataOut;
pAffairHead = (PAFFAIR_HEAD)&(pSend->stAffairContext.affair_head) ;
dwIoSize = pAffairHead->frame_length+15;
if (dwIoSize >MAX_PACKAGE_CNT || PUSHED != pSend->stAffairContext.affair_status)
continue;
pIdelModem = m_LocalModemQueue.begin();
while (pIdelModem != m_LocalModemQueue.end())
{
if (pIdelModem ->modemStatus == S_MODEM_IDLE && pIdelModem->has_sms_cnt ==0)
break;
++ pIdelModem;
}
if (pIdelModem != m_LocalModemQueue.end())
{
pWhichModem = (PPER_SOCKET_CONTEXT)&(pIdelModem->Overlapped);
pWhichModem->modemStatus = S_MODEM_SEND_SMS_ACQUIRE;
SendSmsRequest2Modem(pWhichModem,dwIoSize);
pSend->stAffairContext.affair_status = SENDING_OUT;
pSend->stAffairContext.affair_mdoem_context=pWhichModem;
pWhichModem->pCurrentAffair=(void*)&(pSend->stAffairContext.affair_mdoem_context);
break;
}
}
}
__finally
{
}
LeaveCriticalSection(&m_csVisitLocalModem);
return 0;
}
long CSmsSocket::DecodeSmsIn2BinaryStream(const LPRECV_SMS_HEAD pRecvSmsHead,PAFFAIR_HEAD pAffairHead)
{
if (IsBadReadPtr(pRecvSmsHead,sizeof(RECV_SMS_HEAD)) || IsBadWritePtr(pAffairHead,sizeof(AFFAIR_HEAD)))
return 1;
char chTemp[32] = {0};
int i = atoi(pRecvSmsHead->TP_UD);
pAffairHead->frame_length = i -2;
char *pData = pRecvSmsHead->stSmsData ;
char *pDest = (char*)pAffairHead;
while (i -- >0)
{
strncpy(chTemp,pData,2);
chTemp[2] ='/0';
sscanf(chTemp,"%02X",pDest);
pData += 2;
++ pDest;
}
for (i= 0;i<6;++i)
{
chTemp[2*i+1] =pRecvSmsHead->chTargetNumber[4+2*i];
chTemp[2*i] =pRecvSmsHead->chTargetNumber[4+2*i+1];
}
chTemp[11] = '/0';
CFunction::Cast14SimStrTo7Byte(chTemp,(unsigned char*)pAffairHead->lgsn );
TraceData((char*)pAffairHead,pAffairHead->frame_length+2);
return pAffairHead->frame_length;
}
long CSmsSocket::DecodeRecvSms(PPER_SOCKET_CONTEXT pWhichModem)
{
DWORD dwIoSize = 0;
char chMsgHead[MAX_PACKAGE_CNT] = {0};
char *pFindCmgr = strstr(pWhichModem->RecvData,"+CMGR:");
if (NULL == pFindCmgr)
return 1;
pFindCmgr += 6;
pFindCmgr = strstr(pFindCmgr,"/r/n");
if (NULL == pFindCmgr)
return 2;
pFindCmgr += 2;
LPRECV_SMS_HEAD pRecvSmsHead = (LPRECV_SMS_HEAD)pFindCmgr;
PAFFAIR_HEAD pAffairHead = (PAFFAIR_HEAD)chMsgHead;
dwIoSize = DecodeSmsIn2BinaryStream(pRecvSmsHead,pAffairHead);
if (dwIoSize <= 0 )
return 3;
PER_TERMINATE_CONTEXT stTerminalContext = {0};
PPER_TERMINATE_CONTEXT pPerTerminateContext = NULL;
char sim_card_number[32] = {0};
CFunction::Cast7ByteTo14SimStr((unsigned char*)pAffairHead->lgsn ,sim_card_number );
sim_card_number[11] = '/0';
CFunction::GetModemByHisSimNo(sim_card_number,&pPerTerminateContext);
if (NULL == pPerTerminateContext)
{
TraceInfo(RGB(255,0,0),"末能找到终端[%s]的相关数据结构/n",sim_card_number);
return 4;
}
if (pAffairHead->frame_length +2 == dwIoSize)
{
//判断是事务发到modem后modem的respond数据包,还是modem的invoke数据包
switch (pAffairHead->msg_type)
{
case INVOKE:
//modem到server的invoke数据包
DealTerminate2ServerInvoke(pPerTerminateContext,pAffairHead);
break;
case RESPOND:
//modem到server的先前事务的应答包
DealTerminate2ServerRespond(pPerTerminateContext,pAffairHead);
break;
case ABORT:
//modem到server的先前事务的应答包,但先前事务的数据不正确
DealTerminate2ServerAbort(pPerTerminateContext,pAffairHead);
break;
default:
_ASSERT(0);
break;
}
}
else
{
TraceInfo(RGB(255,0,0),"处理线程接收到的数据包位数[Need:%d Real:%d]不正确!/n",
pAffairHead->frame_length +2,dwIoSize);
pAffairHead->msg_type = ABORT;
}
return 0;
}
void CSmsSocket::DealModemDataThread(void *pParam)
{
CSmsSocket *pModemThread = (CSmsSocket*)pParam;
_ASSERT(NULL != pModemThread);
_ASSERT(! IsBadReadPtr(pModemThread,sizeof(CSmsSocket)));
if (NULL == pModemThread || IsBadReadPtr(pModemThread,sizeof(CSmsSocket)))
return ;
DWORD dwThreadId = GetCurrentThreadId();
HANDLE hIOCP = (HANDLE)pModemThread->m_hModemIocp ;
BOOL bNeedRecv = TRUE;
DWORD dwIoSize = 0;
DWORD dwRecvNumBytes = 0;
DWORD dwLastError = 0;
DWORD dwFlags = 0;
DWORD dwModemAnswerStatus = 0;
int iModemAnswer = 0;
int iModemSubAnswer = 0;
char chReadSmsIndex[32] = {0};
PSMS_CONTEXT pSendSms = NULL;
PPER_SOCKET_CONTEXT lpModemContext = NULL;
LPWSAOVERLAPPED lpOverlapped = NULL;
while (RUNNING == pModemThread->m_iThreadState )
{
try
{
bNeedRecv = GetQueuedCompletionStatus(hIOCP,&dwIoSize,(PDWORD_PTR)&lpModemContext,
(LPOVERLAPPED *)&lpOverlapped,1700);
dwLastError = GetLastError();
if( !bNeedRecv )
{
switch (dwLastError)
{
case WAIT_TIMEOUT:
{
pModemThread->AdjustNeedSendData2Agent();
}
break;
case ERROR_OPERATION_ABORTED:
{
//线程主动调用中止所有末完成的io操作
TraceInfo(RGB(0,0,255),"代理线程[%d]主动调用中止所有末完成的io操作!/n",dwThreadId);
}
break;
default:
{
TraceInfo(RGB(255,0,0),"完成端口检测到事件[%d]/r",dwLastError);
SetLastError(0);
}
break;
}
continue;
}
if( lpModemContext == NULL )
{
//要求本线程退出执行,父线程调用PostQueuedCompletionStatus(hIOCP, 0, 0, NULL);
TraceInfo(RGB(255,0,0),"终端处理线程[%d]退出循环!/n",dwThreadId);
return ;
}
bNeedRecv = TRUE;
switch(lpModemContext->CurrentIoOperation )
{
case IO_RECV:
{
pModemThread->FindModemAnswerFromBackString(lpModemContext->RecvData,&dwModemAnswerStatus);
iModemAnswer = LOWORD(dwModemAnswerStatus);
iModemSubAnswer = HIWORD(dwModemAnswerStatus);
TraceInfo(RGB(0,0,255),"%s接收到数据为%s",lpModemContext->chSocketIp,lpModemContext->RecvData);
if ( iModemAnswer &AT_CMTI)
{
lpModemContext->has_sms_cnt+=iModemSubAnswer;
}
switch (lpModemContext->modemStatus)
{
case S_NOT_INIT:
{
if (iModemAnswer &AT_OK)
++ lpModemContext->initAtCommand;
if (iModemAnswer &AT_OK || iModemAnswer & AT_ERROR)
{
pModemThread->SendInitAtCommand(lpModemContext);
bNeedRecv = FALSE;
}
}
break;
case S_MODEM_SEND_SMS_ACQUIRE:
{
pSendSms = (PSMS_CONTEXT)lpModemContext->pCurrentAffair;
if (iModemAnswer &AT_GOONSEND)
{
lpModemContext->modemStatus=S_MODEM_SMS_SENDING;
TraceData((char*)pSendSms->stSmsData,lstrlen(pSendSms->stSmsData));
pModemThread->SendData2Modem(lpModemContext
,(BYTE*)pSendSms->stSmsData,lstrlen(pSendSms->stSmsData));
bNeedRecv = FALSE;
}
else if (iModemAnswer &AT_ERROR)
{
Sleep(100);
pModemThread->SendData2Modem(lpModemContext
,(BYTE*)lpModemContext->SendData,lpModemContext->SendBuffer.len);
bNeedRecv = FALSE;
}
}
break;
case S_MODEM_SMS_SENDING:
{
if (iModemAnswer &AT_OK || iModemAnswer &AT_ERROR)
{
pSendSms = (PSMS_CONTEXT)lpModemContext->pCurrentAffair;
EnterCriticalSection(&(pModemThread->m_csVisitLocalModem));
list<SMS_CONTEXT>::iterator pFindSms= pModemThread->m_SendOutSmsQueue.begin ();
PSMS_CONTEXT pFindSmsContext = NULL;
while (pFindSms != pModemThread->m_SendOutSmsQueue.end ())
{
pFindSmsContext = (PSMS_CONTEXT)&(pFindSms->stAffairContext) ;
if (0 == memcmp(&(pFindSmsContext->stSmsData)
,&(pSendSms->stSmsData),MAX_PACKAGE_CNT))
{
pModemThread->m_SendOutSmsQueue.erase(pFindSms);
break;
}
++ pFindSms;
}
LeaveCriticalSection(&(pModemThread->m_csVisitLocalModem));
lpModemContext->modemStatus=S_MODEM_IDLE;
}
}
case S_MODEM_IDLE:
case S_MODEM_DELSMS:
case S_MODEM_WAIT:
{
if (lpModemContext->has_sms_cnt >0)
{
sprintf(chReadSmsIndex,"AT+CMGR=%d/r",lpModemContext->has_sms_cnt);
lpModemContext->modemStatus = S_MODEM_WAIT_SMS;
pModemThread->SendData2Modem(lpModemContext
,(BYTE*)chReadSmsIndex,lstrlen(chReadSmsIndex));
bNeedRecv = FALSE;
}
}
break;
case S_MODEM_WAIT_SMS:
{
if (iModemAnswer & AT_OK )
{
-- lpModemContext->has_sms_cnt;
//分析接受到的短消息
pModemThread->DecodeRecvSms(lpModemContext);
}
if (lpModemContext->has_sms_cnt <= 0)
{
sprintf(chReadSmsIndex,"AT+CMGD=1,1/r");
lpModemContext->modemStatus = S_MODEM_DELSMS;
pModemThread->SendData2Modem(lpModemContext
,(BYTE*)chReadSmsIndex,lstrlen(chReadSmsIndex));
bNeedRecv = FALSE;
}
else
{
sprintf(chReadSmsIndex,"AT+CMGR=%d/r",lpModemContext->has_sms_cnt);
lpModemContext->modemStatus = S_MODEM_WAIT_SMS;
pModemThread->SendData2Modem(lpModemContext
,(BYTE*)chReadSmsIndex,lstrlen(chReadSmsIndex));
bNeedRecv = FALSE;
}
}
break;
}
}
break;
case IO_SEND:
if (0 ==FlushFileBuffers((HANDLE)lpModemContext->sScoket))
{
Sleep(100);
}
break;
default:
_ASSERT(0);
}
if (TRUE == bNeedRecv)
{
pModemThread->LetModemReRecvAgain(lpModemContext);
}
}
catch(...)
{
}
}
}