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

📄 pppoe.cpp

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