⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pppoefsm.cpp

📁 pppoe client
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -