📄 pppoe.cpp
字号:
// set fsm state
pCall->m_ulFsmState = FSM_CLIENT_SEND_PADR;
// deref original packet
DereferencePacket(pLastSendPacket);
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
// cancel timer
CancelTimerItem(&g_timer,&pCall->m_timerPPPOEItem,(PVOID)1);
// add call to bind list
AddCall2Bind(pCall,pBind);
// tell upper call state change
TspiCallStateChange(pCall,LINECALLSTATE_PROCEEDING,0);
NdisAcquireSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = TRUE;
// check fsm state
if(pCall->m_ulFsmState != FSM_CLIENT_SEND_PADR)
__leave;
LARGE_INTEGER llHostUnique;
USHORT usLen;
// create unique host value
CreateUniqueValue(pCall->m_hdCall,&llHostUnique,&usLen);
// create packet
pSendPacket = InitializePADRToSend(pRecvedPacket,pCall->m_ucServiceName,pCall->m_usServiceNameLen,
(PUCHAR)&llHostUnique,usLen);
ReferencePacket(pSendPacket);
// save the pointer
pCall->m_pLastSendDiscoveryPacket = pSendPacket;
ReferenceBind(pBind,TRUE);
NdisInitializeListHead(&pCall->m_timerPPPOEItem.m_ltItem);
// schedule timer
pCall->m_usRetryCount = 0;
ScheduleTimerItem(&g_timer,&pCall->m_timerPPPOEItem,g_pAdapter->m_ulSendTimeOut,FsmSendPADRTimeOut,pCall);
ReferenceCall(pCall,FALSE);
pCall->m_ulFsmState = FSM_CLIENT_WAIT_FOR_PADS;
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
// send it
NDIS_STATUS status = SendPPPOEPacket(g_pAdapter,pBind,pSendPacket);
if(status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
{
bNeedDropCall = TRUE;
ulReportCallStateParam = LINEDISCONNECTMODE_UNREACHABLE;
}
drvDbgPrint("got an enough satisfied PADO so send a PADR...\n");
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bNeedDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
}
// wait for PADS
VOID ClientWaitForPADS(PCALL_INFO pCall,PBIND_CONTEXT pBind,PPPPOE_PACKET pRecvedPacket)
{
BOOLEAN bNeedDropCall = FALSE;
ULONG ulReportCallStateParam = 0;
BOOLEAN bNeedReleaseLock = TRUE;
PPPPOE_PACKET pSendPacket = NULL;
__try
{
// check pointer
if( !pRecvedPacket ||
pRecvedPacket->m_pFrame->m_pppFrame.m_ucCode != PPPOE_CODE_PADS)
{
drvDbgPrint("recv PADS packet error ignore this packet...\n");
__leave;
}
// check error status
if(pRecvedPacket->m_ulFlags & PPPOE_PACKET_ERROR_TAG_RECV)
{
bNeedDropCall = TRUE;
switch(pRecvedPacket->m_ulErrorTag)
{
case PPPOE_TAG_SERVICE_NAME_ERROR:
ulReportCallStateParam = LINEDISCONNECTMODE_BADADDRESS;
break;
case PPPOE_TAG_AC_SYSTEM_ERROR:
ulReportCallStateParam = LINEDISCONNECTMODE_INCOMPATIBLE;
break;
case PPPOE_TAG_AC_COOKIE_ERROR:
ulReportCallStateParam = LINEDISCONNECTMODE_REJECT;
break;
default:
ulReportCallStateParam = LINEDISCONNECTMODE_UNKNOWN;
break;
}
__leave;
}
// last send packet
PPPPOE_PACKET pLastSendPacket = pCall->m_pLastSendDiscoveryPacket;
if(!pLastSendPacket)
{
bNeedDropCall = TRUE;
ulReportCallStateParam = LINEDISCONNECTMODE_UNKNOWN;
__leave;
}
// check host unique
if( pLastSendPacket->m_usHostUnique != pRecvedPacket->m_usHostUnique ||
RtlCompareMemory(pLastSendPacket->m_pHostUnique,pRecvedPacket->m_pHostUnique,pRecvedPacket->m_usHostUnique) != pRecvedPacket->m_usHostUnique)
{
drvDbgPrint("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
pCall->m_usSessionId = ntohs(pRecvedPacket->m_pFrame->m_pppFrame.m_usSession);
pCall->m_pLastSendDiscoveryPacket = NULL;
DereferencePacket(pLastSendPacket);
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
// cancel timer
CancelTimerItem(&g_timer,&pCall->m_timerPPPOEItem,(PVOID)1);
TspiCallStateChange(pCall,LINECALLSTATE_CONNECTED,0);
drvDbgPrint("the PADS is ok,so go to session stage...\n");
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bNeedDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
}
// send PADI time out
VOID FsmSendPADITimeOut(PPPPOE_TIMER_ITEM pItem,PVOID pContext,PVOID pCancelContext)
{
PCALL_INFO pCall = static_cast<PCALL_INFO>(pContext);
NdisAcquireSpinLock(&pCall->m_lockSelf);
BOOLEAN bDropCall = FALSE;
ULONG ulReportCallStateParam = 0;
BOOLEAN bNeedReleaseLock = TRUE;
if(pCancelContext)
{
pCall->m_usRetryCount = 0;
}
else
{
drvDbgPrint("client sending PADI timeout %d...\n",pCall->m_usRetryCount + 1);
__try
{
if(pCall->m_ulFsmState != FSM_CLIENT_WAIT_FOR_PADO)
__leave;
if(pCall->m_usRetryCount >= g_pAdapter->m_ulMaxRetryTimes)
{
bDropCall = TRUE;
ulReportCallStateParam = LINEDISCONNECTMODE_NOANSWER;
__leave;
}
if(!pCall->m_pLastSendDiscoveryPacket)
__leave;
ReferencePacket(pCall->m_pLastSendDiscoveryPacket);
NdisInitializeListHead(&pCall->m_timerPPPOEItem.m_ltItem);
ScheduleTimerItem(&g_timer,&pCall->m_timerPPPOEItem,g_pAdapter->m_ulSendTimeOut,FsmSendPADITimeOut,pCall);
ReferenceCall(pCall,FALSE);
++pCall->m_usRetryCount;
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
ulReportCallStateParam = LINEDISCONNECTMODE_UNREACHABLE;
bDropCall = !BroadcastPacket(pCall->m_pLastSendDiscoveryPacket);
DereferencePacket(pCall->m_pLastSendDiscoveryPacket);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
DereferenceCall(pCall);
}
// send PADR time out
VOID FsmSendPADRTimeOut(PPPPOE_TIMER_ITEM pItem,PVOID pContext,PVOID pCancelContext)
{
PCALL_INFO pCall = static_cast<PCALL_INFO>(pContext);
NdisAcquireSpinLock(&pCall->m_lockSelf);
BOOLEAN bDropCall = FALSE;
ULONG ulReportCallStateParam = 0;
BOOLEAN bNeedReleaseLock = TRUE;
if(pCancelContext)
{
pCall->m_usRetryCount = 0;
}
else
{
drvDbgPrint("client sending PADR timeout %d...\n",pCall->m_usRetryCount + 1);
__try
{
if(pCall->m_ulFsmState != FSM_CLIENT_WAIT_FOR_PADS)
__leave;
if(pCall->m_usRetryCount >= g_pAdapter->m_ulMaxRetryTimes)
{
bDropCall = TRUE;
ulReportCallStateParam = LINEDISCONNECTMODE_BUSY;
__leave;
}
if(!pCall->m_pBindContext)
{
bDropCall = TRUE;
ulReportCallStateParam = LINEDISCONNECTMODE_UNREACHABLE;
__leave;
}
if(!pCall->m_pLastSendDiscoveryPacket)
__leave;
ReferenceBind(pCall->m_pBindContext,TRUE);
ReferencePacket(pCall->m_pLastSendDiscoveryPacket);
NdisInitializeListHead(&pCall->m_timerPPPOEItem.m_ltItem);
ScheduleTimerItem(&g_timer,&pCall->m_timerPPPOEItem,g_pAdapter->m_ulSendTimeOut,FsmSendPADRTimeOut,pCall);
ReferenceCall(pCall,FALSE);
++pCall->m_usRetryCount;
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
NDIS_STATUS status = SendPPPOEPacket(g_pAdapter,pCall->m_pBindContext,pCall->m_pLastSendDiscoveryPacket);
if(status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
{
bDropCall = TRUE;
ulReportCallStateParam = LINEDISCONNECTMODE_UNREACHABLE;
__leave;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
DereferenceCall(pCall);
}
// offering timeout
VOID ServerOfferingTimeOut(PPPPOE_TIMER_ITEM pItem,PVOID pContext,PVOID pCancelContext)
{
PCALL_INFO pCall = static_cast<PCALL_INFO>(pContext);
NdisAcquireSpinLock(&pCall->m_lockSelf);
BOOLEAN bDropCall = FALSE;
ULONG ulReportCallStateParam = 0;
if(pCancelContext)
{
pCall->m_usRetryCount = 0;
}
else
{
drvDbgPrint("server wait for some app answer incoming call time out %d.\n",pCall->m_usRetryCount);
__try
{
if(pCall->m_ulFsmState != FSM_SERVER_WAIT_FOR_ANSWER)
__leave;
if(pCall->m_usRetryCount >= g_pAdapter->m_ulMaxRetryTimes)
{
bDropCall = TRUE;
__leave;
}
NdisInitializeListHead(&pCall->m_timerPPPOEItem.m_ltItem);
ScheduleTimerItem(&g_timer,&pCall->m_timerPPPOEItem,g_pAdapter->m_ulRecvTimeOut,ServerOfferingTimeOut,pCall);
ReferenceCall(pCall,FALSE);
++pCall->m_usRetryCount;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
}
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
DereferenceCall(pCall);
}
// server send PADS
VOID ServerReceiveNewCall(PCALL_INFO pCall,PBIND_CONTEXT pBind,PPPPOE_PACKET pRecvedPacket)
{
BOOLEAN bDropCall = FALSE;
BOOLEAN bCloseCall = FALSE;
ULONG ulReportCallStateParam = 0;
BOOLEAN bNeedReleaseLock = TRUE;
__try
{
if(!pRecvedPacket || pRecvedPacket->m_pFrame->m_pppFrame.m_ucCode != PPPOE_CODE_PADR)
__leave;
NdisMoveMemory(pCall->m_macPeer,pRecvedPacket->m_pFrame->m_srcMac,6);
PUCHAR pService = NULL;
USHORT usService = 0;
RetrieveTag(PPPOE_TAG_SERVICE,pRecvedPacket,&pService,&usService,FALSE);
if(usService > 256)
usService = 256;
NdisMoveMemory(pCall->m_ucServiceName,pService,usService);
// host order!!!!
USHORT usSession = GetSessionIdFromCallHandle(pCall->m_hdCall);
// build a PADS and save it
PPPPOE_PACKET pSendPacket = InitializePADSToSend(pRecvedPacket,usSession);
if(!pSendPacket)
{
bCloseCall = TRUE;
__leave;
}
pCall->m_pLastSendDiscoveryPacket = pSendPacket;
pCall->m_ulFsmState = FSM_SERVER_WAIT_FOR_ANSWER;
pCall->m_usRetryCount = 0;
NdisInitializeListHead(&pCall->m_timerPPPOEItem.m_ltItem);
ScheduleTimerItem(&g_timer,&pCall->m_timerPPPOEItem,g_pAdapter->m_ulRecvTimeOut,ServerOfferingTimeOut,pCall);
ReferenceCall(pCall,FALSE);
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
TspiIndicateNewCall(pCall);
AddCall2Bind(pCall,pBind);
TspiCallStateChange(pCall,LINECALLSTATE_OFFERING,0);
drvDbgPrint("server detected a new call,wait for some app answer this call.\n");
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bCloseCall)
{
NDIS_TAPI_CLOSE_CALL close;
close.hdCall = pCall->m_hdCall;
TspiCloseCall(g_pAdapter,&close,FALSE);
}
if(bDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
}
// server answer call
NDIS_STATUS ServerAnswerCall(PCALL_INFO pCall,PBIND_CONTEXT pBind,PPPPOE_PACKET pRecvedPacket)
{
BOOLEAN bDropCall = FALSE;
ULONG ulReportCallStateParam = 0;
BOOLEAN bNeedReleaseLock = TRUE;
NDIS_STATUS status = NDIS_STATUS_FAILURE;
__try
{
if(pRecvedPacket)
__leave;
if(!pCall->m_pLastSendDiscoveryPacket || !pCall->m_pBindContext)
{
bDropCall = TRUE;
__leave;
}
ReferencePacket(pCall->m_pLastSendDiscoveryPacket);
ReferenceBind(pCall->m_pBindContext,TRUE);
// host order!!!
pCall->m_usSessionId = GetSessionIdFromCallHandle(pCall->m_hdCall);
NdisReleaseSpinLock(&pCall->m_lockSelf);
bNeedReleaseLock = FALSE;
CancelTimerItem(&g_timer,&pCall->m_timerPPPOEItem,(PVOID)1);
NDIS_STATUS status = SendPPPOEPacket(g_pAdapter,pCall->m_pBindContext,pCall->m_pLastSendDiscoveryPacket);
drvDbgPrint("server wait for some app answer incoming call finished.send PADS.\n");
if(status != NDIS_STATUS_SUCCESS && status != NDIS_STATUS_PENDING)
{
bDropCall = TRUE;
}
else
{
TspiCallStateChange(pCall,LINECALLSTATE_CONNECTED,0);
status = NDIS_STATUS_SUCCESS;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
if(bNeedReleaseLock)
NdisReleaseSpinLock(&pCall->m_lockSelf);
if(bDropCall)
{
NDIS_TAPI_DROP drop;
drop.hdCall = pCall->m_hdCall;
TspiDrop(g_pAdapter,&drop,ulReportCallStateParam);
}
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -