📄 pppoefsm.cpp
字号:
USHORT usServiceNameLastSend;
// only one service
RetrieveTag(PPPOE_TAG_SERVICE,pLastSendPacket,&pServiceNameLastSend,&usServiceNameLastSend,FALSE);
// should not be null
if(!pServiceNameLastSend)
__leave;
PUCHAR pCurrentOffset = pRecvedPacket->m_pucDataBuffer;
USHORT usTotalLen = ntohs(pRecvedPacket->m_pFrame->m_pppFrame.m_usLen);
PUCHAR pServiceNameRecved = NULL;
USHORT usServiceNameRecved = 0;
// check service match
for(;;)
{
RetrieveServiceName(pRecvedPacket,&pServiceNameRecved,&usServiceNameRecved,pCurrentOffset,usTotalLen);
if(!pServiceNameRecved)
break;
if( !usServiceNameLastSend ||
(usServiceNameLastSend == usServiceNameRecved &&
RtlCompareMemory(pServiceNameRecved,pServiceNameLastSend,usServiceNameRecved) == usServiceNameRecved))
{
bFoundService = TRUE;
break;
}
pCurrentOffset += usServiceNameRecved + sizeof(PPP_TAG);
usTotalLen -= (usServiceNameRecved + sizeof(PPP_TAG));
}
if(!bFoundService)
__leave;
// copy service name
pChannel->m_usServiceLen = usServiceNameLastSend;
if(pChannel->m_usServiceLen > sizeof(pChannel->m_ucService))
pChannel->m_usServiceLen = sizeof(pChannel->m_ucService);
NdisMoveMemory(pChannel->m_ucService,pServiceNameLastSend,pChannel->m_usServiceLen);
// copy mac address
NdisMoveMemory(pChannel->m_macPeer,pRecvedPacket->m_pFrame->m_srcMac,6);
pChannel->m_pLastPacket = NULL;
// set fsm state
pChannel->m_ulFsmState = FSM_CLIENT_SEND_PADR;
// deref original packet
DereferencePacket(pLastSendPacket);
NdisReleaseSpinLock(&pChannel->m_lockSelf);
bNeedReleaseLock = FALSE;
// cancel timer
CancelTimerItem(&pChannel->m_timerItemDiscovery,(PVOID)1);
// add call to bind list
AddChannel2Bind(pChannel,pBind);
NdisAcquireSpinLock(&pChannel->m_lockSelf);
bNeedReleaseLock = TRUE;
// check fsm state
if(pChannel->m_ulFsmState != FSM_CLIENT_SEND_PADR)
__leave;
LARGE_INTEGER llHostUnique;
USHORT usLen;
// create unique host value
CreateUniqueValue(pChannel,&llHostUnique,&usLen);
// create packet
pSendPacket = InitializePADRToSend(pRecvedPacket,pChannel->m_ucService,pChannel->m_usServiceLen,
reinterpret_cast<PUCHAR>(&llHostUnique),usLen);
ReferencePacket(pSendPacket);
// save the pointer
pChannel->m_pLastPacket = pSendPacket;
ReferenceBind(pBind,TRUE);
InitializeTimerItem(&pChannel->m_timerItemDiscovery);
// schedule timer
pChannel->m_usRetryCounts = 0;
ScheduleTimerItem(&pChannel->m_timerItemDiscovery,FsmSendPADRTimeOut,g_pAdapter->m_ulSendTimeOut,pChannel);
pChannel->m_ulFsmState = FSM_CLIENT_WAIT_FOR_PADS;
NdisReleaseSpinLock(&pChannel->m_lockSelf);
bNeedReleaseLock = FALSE;
// send it
NDIS_STATUS status = SendPacket(pBind,pSendPacket);
if(status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
{
bNeedDropCall = TRUE;
}
DebugInfo(("got an enough satisfied PADO so send a PADR...\n"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pChannel->m_lockSelf);
if(bNeedDropCall)
{
NdisMCmMakeCallComplete(NDIS_STATUS_FAILURE,pChannel->m_hNdisVcHandle,NULL,NULL,pChannel->m_pOutParam);
}
}
// client wait for PADS,check recved packet,get session id,complete the make call request
VOID ClientWaitForPADS(PCHANNEL pChannel,PBIND_CONTEXT pBind,PPACKET pRecvedPacket)
{
BOOLEAN bNeedDropCall = FALSE;
BOOLEAN bNeedReleaseLock = TRUE;
PPACKET pSendPacket = NULL;
__try
{
// check pointer
if( !pRecvedPacket ||
pRecvedPacket->m_pFrame->m_pppFrame.m_ucCode != PPPOE_CODE_PADS ||
pRecvedPacket->m_ulFlags & PPPOE_PACKET_ERROR_TAG_RECV)
{
DebugInfo(("recv packet is not a PADS or a PADS with error tag,ignore this packet...\n"));
__leave;
}
// last send packet
PPACKET pLastSendPacket = pChannel->m_pLastPacket;
if(!pLastSendPacket)
{
bNeedDropCall = TRUE;
__leave;
}
// check host unique
if( pLastSendPacket->m_usHostUnique != pRecvedPacket->m_usHostUnique ||
RtlCompareMemory(pLastSendPacket->m_pHostUnique,pRecvedPacket->m_pHostUnique,pRecvedPacket->m_usHostUnique) != pRecvedPacket->m_usHostUnique)
{
DebugInfo(("recved PADS's host unique not match ignore it...\n"));
__leave;
}
// get service name
PUCHAR pServiceNameRecved;
USHORT usServiceNameRecved;
RetrieveTag(PPPOE_TAG_SERVICE,pRecvedPacket,&pServiceNameRecved,&usServiceNameRecved,FALSE);
if(!pServiceNameRecved)
__leave;
PUCHAR pServiceNameLastSend;
USHORT usServiceNameLastSend;
// check service match
RetrieveTag(PPPOE_TAG_SERVICE,pLastSendPacket,&pServiceNameLastSend,&usServiceNameLastSend,FALSE);
if(!pServiceNameLastSend)
__leave;
if( usServiceNameLastSend!= usServiceNameRecved ||
RtlCompareMemory(pServiceNameRecved,pServiceNameLastSend,usServiceNameRecved) != usServiceNameRecved)
{
__leave;
}
// save session id
pChannel->m_usSessionId = ntohs(pRecvedPacket->m_pFrame->m_pppFrame.m_usSession);
pChannel->m_pLastPacket = NULL;
pChannel->m_ulFsmState = FSM_SESSION;
DereferencePacket(pLastSendPacket);
NdisReleaseSpinLock(&pChannel->m_lockSelf);
bNeedReleaseLock = FALSE;
// cancel timer
CancelTimerItem(&pChannel->m_timerItemDiscovery,(PVOID)1);
NDIS_STATUS status = NdisMCmActivateVc(pChannel->m_hNdisVcHandle,pChannel->m_pOutParam);
if(status != NDIS_STATUS_PENDING)
mcmActivateVcComplete(status,pChannel,pChannel->m_pOutParam);
NdisMCmMakeCallComplete(NDIS_STATUS_SUCCESS,pChannel->m_hNdisVcHandle,NULL,NULL,pChannel->m_pOutParam);
DebugInfo(("the PADS is ok,so go to session stage...\n"));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pChannel->m_lockSelf);
if(bNeedDropCall)
{
NdisMCmMakeCallComplete(NDIS_STATUS_FAILURE,pChannel->m_hNdisVcHandle,NULL,NULL,pChannel->m_pOutParam);
}
}
// send PADI time out
VOID FsmSendPADITimeOut(PTIMER_ITEM pItem,PVOID pContext,PVOID pCancelContext)
{
PCHANNEL pChannel = static_cast<PCHANNEL>(pContext);
NdisDprAcquireSpinLock(&pChannel->m_lockSelf);
BOOLEAN bDropCall = FALSE;
BOOLEAN bNeedReleaseLock = TRUE;
if(pCancelContext)
{
pChannel->m_usRetryCounts = 0;
}
else
{
DebugInfo(("client sending PADI timeout %d...\n",pChannel->m_usRetryCounts + 1));
__try
{
if(pChannel->m_ulFsmState != FSM_CLIENT_WAIT_FOR_PADO)
__leave;
if(pChannel->m_usRetryCounts >= g_pAdapter->m_ulMaxRetryTimes)
{
bDropCall = TRUE;
__leave;
}
if(!pChannel->m_pLastPacket)
__leave;
ReferencePacket(pChannel->m_pLastPacket);
InitializeTimerItem(&pChannel->m_timerItemDiscovery);
ScheduleTimerItem(&pChannel->m_timerItemDiscovery,FsmSendPADITimeOut,g_pAdapter->m_ulSendTimeOut,pChannel);
++pChannel->m_usRetryCounts;
NdisDprReleaseSpinLock(&pChannel->m_lockSelf);
bNeedReleaseLock = FALSE;
bDropCall = !BroadcastPacket(pChannel->m_pLastPacket);
DereferencePacket(pChannel->m_pLastPacket);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
if(bNeedReleaseLock)
NdisDprReleaseSpinLock(&pChannel->m_lockSelf);
if(bDropCall)
{
NdisMCmMakeCallComplete(NDIS_STATUS_FAILURE,pChannel->m_hNdisVcHandle,NULL,NULL,pChannel->m_pOutParam);
}
}
// send PADR time out DISPATCH_LEVEL
VOID FsmSendPADRTimeOut(PTIMER_ITEM pItem,PVOID pContext,PVOID pCancelContext)
{
PCHANNEL pChannel = static_cast<PCHANNEL>(pContext);
NdisDprAcquireSpinLock(&pChannel->m_lockSelf);
BOOLEAN bDropCall = FALSE;
BOOLEAN bNeedReleaseLock = TRUE;
if(pCancelContext)
{
pChannel->m_usRetryCounts = 0;
}
else
{
DebugInfo(("client sending PADR timeout %d...\n",pChannel->m_usRetryCounts + 1));
__try
{
if(pChannel->m_ulFsmState != FSM_CLIENT_WAIT_FOR_PADS)
__leave;
if(pChannel->m_usRetryCounts >= g_pAdapter->m_ulMaxRetryTimes)
{
bDropCall = TRUE;
__leave;
}
if(!pChannel->m_pBindContext)
{
bDropCall = TRUE;
__leave;
}
if(!pChannel->m_pLastPacket)
__leave;
ReferenceBind(pChannel->m_pBindContext,TRUE);
ReferencePacket(pChannel->m_pLastPacket);
InitializeTimerItem(&pChannel->m_timerItemDiscovery);
ScheduleTimerItem(&pChannel->m_timerItemDiscovery,FsmSendPADRTimeOut,g_pAdapter->m_ulSendTimeOut,pChannel);
++pChannel->m_usRetryCounts;
NdisDprReleaseSpinLock(&pChannel->m_lockSelf);
bNeedReleaseLock = FALSE;
NDIS_STATUS status = SendPacket(pChannel->m_pBindContext,pChannel->m_pLastPacket);
if(status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
{
bDropCall = TRUE;
__leave;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
if(bNeedReleaseLock)
NdisDprReleaseSpinLock(&pChannel->m_lockSelf);
if(bDropCall)
{
NdisMCmMakeCallComplete(NDIS_STATUS_FAILURE,pChannel->m_hNdisVcHandle,NULL,NULL,pChannel->m_pOutParam);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -