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

📄 layerfsm.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		pFsm->idTxCR++;
		dwResult = PppFsmActionSCR(pFsm);
		if (dwResult == NO_ERROR)
			newState = PFS_Request_Sent;
		break;

	case PFS_Closing:
		newState = PFS_Stopping;
		break;
	}

	PppFsmNewState(pFsm, newState);

	return dwResult;
}

DWORD
PppFsmClose(
	PPppFsm	pFsm)
//
//	Called to request that the finite state machine
//	take steps to enter the closed state.
//
{
	DWORD	    dwResult = NO_ERROR;
	PppFsmState newState = pFsm->state;

	DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmClose %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));

	switch(pFsm->state)
	{
	case PFS_Initial:
		break;

	case PFS_Starting:
		newState = PFS_Initial;
		break;

	case PFS_Closed:
	case PFS_Closing:
		break;

	case PFS_Stopped:
		newState = PFS_Closed;
		break;

	case PFS_Stopping:
		newState = PFS_Closing;
		break;

	case PFS_Opened:
		PppFsmActionTLD(pFsm);
		// FALLTHROUGH
	case PFS_Request_Sent:
	case PFS_Ack_Received:
	case PFS_Ack_Sent:
		PppFsmActionIRC(pFsm, pFsm->dwMaxTerminate);
		PppFsmActionSTR(pFsm);
		newState = PFS_Closing;
		break;
	}

	PppFsmNewState(pFsm, newState);

	return dwResult;
}

DWORD
PppFsmRenegotiate(
	PPppFsm	pFsm)
//
//  Called to request that the FSM renegotiate options with the peer.
//  This takes the layer down if it is currently Opened, then proceeds
//  through the whole negotiation process to get it back to the Opened state.
//
{
	DWORD	dwResult = NO_ERROR;
	PppFsmState newState = pFsm->state;

	DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmRenegotiate %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));

	switch(pFsm->state)
	{
	case PFS_Initial:
	case PFS_Closed:
	case PFS_Closing:
	case PFS_Starting:
		break;

	case PFS_Opened:
		PppFsmActionTLD(pFsm);
		// FALLTHROUGH
	case PFS_Stopped:
	case PFS_Stopping:
	case PFS_Request_Sent:
	case PFS_Ack_Received:
	case PFS_Ack_Sent:
		PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
		OptionResetNegotiation(&pFsm->optionContext);
		pFsm->idTxCR++;
		dwResult = PppFsmActionSCR(pFsm);
		if (dwResult == NO_ERROR)
			newState = PFS_Request_Sent;
		break;
	}

	PppFsmNewState(pFsm, newState);

	return dwResult;
}

DWORD
PppFsmLowerLayerUp(
	PPppFsm	pFsm)
//
//	Called to indicate that the layer below this one has
//	come up, we are able to send/receive frames.
//
{
	DWORD	    dwResult = NO_ERROR;
	PppFsmState newState = pFsm->state;

	DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmLowerLayerUp %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));

	switch(pFsm->state)
	{
	case PFS_Initial:
		newState = PFS_Closed;
		break;

	case PFS_Starting:
		OptionResetNegotiation(&pFsm->optionContext);
		PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
		pFsm->idTxCR++;
		dwResult = PppFsmActionSCR(pFsm);
		if (dwResult == NO_ERROR)
			newState = PFS_Request_Sent;
		else
			newState = PFS_Stopped;
		break;
	}

	PppFsmNewState(pFsm, newState);

	return dwResult;
}

DWORD
PppFsmLowerLayerDown(
	PPppFsm	pFsm)
//
//	Called to indicate that the layer below this one has
//	gone down, we are unable to send/receive frames any more.
//
{
	DWORD	dwResult = NO_ERROR;

	DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmLowerLayerDown %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));

	switch(pFsm->state)
	{
	case PFS_Initial:
	case PFS_Starting:
		break;

	case PFS_Closing:
	case PFS_Closed:
		PppFsmNewState(pFsm, PFS_Initial);
		break;

	case PFS_Opened:
		PppFsmActionTLD(pFsm);
		// FALLTHROUGH
	case PFS_Stopped:
	case PFS_Stopping:
	case PFS_Request_Sent:
	case PFS_Ack_Received:
	case PFS_Ack_Sent:
		PppFsmNewState(pFsm, PFS_Starting);
		break;

	default:
		ASSERT(FALSE);
		break;
	}

	return dwResult;
}

DWORD
PppFsmProtocolRejected(
	PPppFsm	pFsm)
//
//	Called to handle the rejection of our protocol
//  by the peer.
//
{
	DWORD	dwResult = NO_ERROR;

	DEBUGMSG(ZONE_TRACE, (L"PPP: PppFsmProtocolRejected %hs State=%hs\n", pFsm->pDescriptor->szProtocolName, g_szStateName[pFsm->state]));

	switch(pFsm->state)
	{
	case PFS_Initial:
	case PFS_Starting:
		break;

	case PFS_Closed:
	case PFS_Closing:
		PppFsmNewState(pFsm, PFS_Closed);
		break;

	case PFS_Stopped:
	case PFS_Stopping:
	case PFS_Request_Sent:
	case PFS_Ack_Received:
	case PFS_Ack_Sent:
		PppFsmNewState(pFsm, PFS_Stopped);
		break;

	case PFS_Opened:
		PppFsmActionTLD(pFsm);
		PppFsmActionIRC(pFsm, pFsm->dwMaxTerminate);
		PppFsmActionSTR(pFsm);
		PppFsmNewState(pFsm, PFS_Stopping);
		break;
	}

	return dwResult;
}

void
PppFsmActionSendCodeReject(
	IN	OUT	PPppFsm	     pFsm,
	IN		PBYTE	     pPacket,
	IN		DWORD		 cbPacket)
//
//  Send a code-reject packet containing the packet
//  received from the peer with an unrecognized code.
//
{
	//
	// Per RFC1661 5.6
	//	"The Rejected-Packet MUST be truncated to comply with
	//   the peer's established MRU."
	//
	// Currently, for simplicity, assume default MRU of 1500.
	//
	if (cbPacket > (PPP_DEFAULT_MTU - PPP_PACKET_HEADER_SIZE))
	{
	    // Truncate the rejected packet
		cbPacket = PPP_DEFAULT_MTU - PPP_PACKET_HEADER_SIZE;
	}

	pFsm->cbResponsePacket = PPP_PACKET_HEADER_SIZE + cbPacket;
	ASSERT(pFsm->cbResponsePacket <= PPP_DEFAULT_MTU);

	PPP_SET_PACKET_HEADER(pFsm->abResponsePacket, PPP_CODE_REJECT, pFsm->idNextCodeReject, pFsm->cbResponsePacket);
	pFsm->idNextCodeReject++;
	memcpy(&pFsm->abResponsePacket[PPP_PACKET_HEADER_SIZE], pPacket, cbPacket);

	pFsm->bmActions |= ACTION_SEND_RESPONSE;
}

#define MAX_RESPONSE_PACKET_SIZE PPP_DEFAULT_MTU

DWORD
PppFsmProcessRxConfigureRequest(
	IN	OUT	PPppFsm	     pFsm,
	IN		PBYTE	     pPacket,
	IN		DWORD		 cbPacket,
	    OUT PBYTE        pResponsePacket,
    IN  OUT PDWORD       pcbResponsePacket)
{
	DWORD dwResult;

	//
	// Construct a response (ACK/NAK/REJ) to the configure-request
	//
	dwResult = OptionProcessRxMessage(
					&pFsm->optionContext,
					pPacket,
					cbPacket,
					pResponsePacket,
					pcbResponsePacket);

	ASSERT ((dwResult != NO_ERROR) 
		 || (*pcbResponsePacket >= PPP_PACKET_HEADER_SIZE && PPP_CONFIGURE_ACK <= *pResponsePacket && *pResponsePacket <= PPP_CONFIGURE_REJ));

	return dwResult;
}

DWORD
PppFsmProcessRxConfigureResponse(
	IN	OUT	PPppFsm	     pFsm,
	IN		PBYTE	     pPacket,
	IN		DWORD		 cbPacket)
{
	DWORD dwResult;

	dwResult = OptionProcessRxMessage(
					&pFsm->optionContext,
					pPacket,
					cbPacket,
					NULL,
					NULL);

	return dwResult;
}

void
PppFsmProcessRxPacket(
	IN	OUT	PPppFsm	pFsm,
	IN		PBYTE	pPacket,
	IN		DWORD	cbPacket)
//
//	Process a received packet for the protocol managed by this Fsm.
//	The protocol type field must have been stripped from the packet already.
//
//	For state machine table, see RFC 1661 section 4.1
//
{
	PppFsmState	curState,
				newState;
	BYTE		code,
				id;
	DWORD		dwResult;
	DWORD       length;
	PPppFsmExtensionMessageDescriptor pMsgDescriptor;

	do
	{
		//
		//	All packets have the form:
		//		<Code> <Id> <Length:2 octets> <Data: Length-4 octets>
		//
		if (cbPacket < PPP_PACKET_HEADER_SIZE)
		{
			DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING RX %hs short packet, %u bytes\n"), 
				pFsm->pDescriptor->szProtocolName, cbPacket));
			break;
		}

		code = pPacket[0];
		id = pPacket[1];
		length = (pPacket[2] << 8) | pPacket[3];
		if (length < PPP_PACKET_HEADER_SIZE || cbPacket < length)
		{
			DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING RX %hs length %u invalid for cbPacket %u\n"), 
				pFsm->pDescriptor->szProtocolName, length, cbPacket));
			break;
		}

		curState = pFsm->state;
		newState = curState;

#ifdef DEBUG
		if (ZONE_TRACE)
			PppFsmDebugShowPacket(pFsm, "RX", pPacket, cbPacket);
#endif
		switch(code)
		{
		case PPP_CONFIGURE_REQUEST:
			switch(curState)
			{
			case PFS_Closed:
				PppFsmActionSTA(pFsm, id);
				break;

			case PFS_Stopped:
			case PFS_Request_Sent:
			case PFS_Ack_Sent:
			case PFS_Ack_Received:
			case PFS_Opened:
				pFsm->cbResponsePacket = sizeof(pFsm->abResponsePacket);
				dwResult = PppFsmProcessRxConfigureRequest(pFsm, pPacket, cbPacket, &pFsm->abResponsePacket[0], &pFsm->cbResponsePacket);
				if (dwResult == NO_ERROR)
				{
					newState = pFsm->abResponsePacket[0] == PPP_CONFIGURE_ACK ? PFS_Ack_Sent : PFS_Request_Sent;

					if (curState == PFS_Stopped || curState == PFS_Opened)
					{
						if (curState == PFS_Opened)
							PppFsmActionTLD(pFsm);

						OptionResetNegotiation(&pFsm->optionContext);
						PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
						pFsm->idTxCR++;
						if (PppFsmActionSCR(pFsm) != NO_ERROR)
							newState = PFS_Stopped;
					}
					else if (curState == PFS_Ack_Received)
					{
						newState = newState == PFS_Ack_Sent ? PFS_Opened : PFS_Ack_Received;
					}

					//
					// Note that the response must be sent AFTER the config-request sent above
					// in order to prevent infinite renegotiations from occuring.
					//
					pFsm->bmActions |= ACTION_SEND_RESPONSE;
				}
				else if (dwResult == ERROR_PPP_NOT_CONVERGING)
				{
					// Further negotiation is probably futile, give up and shut down the link
					newState = PFS_Stopped;
				}
				break;
			}
			break;

		case PPP_CONFIGURE_ACK:
		case PPP_CONFIGURE_NAK:
		case PPP_CONFIGURE_REJ:
			//
			// Ignore the response if its ID does not match the most
			// recent config-request we sent.
			//
			if (id != pFsm->idTxCR)
			{
				// Stale response, ignore it
				DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - RX Stale response id=%u, expecting %u\n"), id, pFsm->idTxCR));
				break;
			}

			switch(curState)
			{
			case PFS_Closed:
			case PFS_Stopped:
				PppFsmActionSTA(pFsm, id);
				break;

			case PFS_Opened:
			    PppFsmActionTLD(pFsm);
				// FALLTHROUGH
			case PFS_Ack_Received:
				//
				// We are in a state in which we are not expecting a response.
				//
				DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - Unexpected response received\n")));
				pFsm->idTxCR++;
				if (PppFsmActionSCR(pFsm) == NO_ERROR)
					newState = PFS_Request_Sent;
				else
				{
					PppFsmActionSTR(pFsm);
					newState = PFS_Stopping;
				}
				break;

			case PFS_Request_Sent:
			case PFS_Ack_Sent:
				//
				// All improperly formed responses must be ignored, and not
				// result in a state transition.
				//
				if (code == PPP_CONFIGURE_ACK)
				{
					//
					//	An ACK packet must be identical to the CR we issued,
					//  except for the 1st byte (which is ACK(2) instead of CR(1)
					//
					DWORD len = (pPacket[2] << 8) | pPacket[3];

					if (pFsm->cbRequestBuffer != len ||
						memcmp(pFsm->pRequestBuffer + 1, pPacket + 1, len - 1))
					{
						// Invalid ACK - ignore
						DEBUGMSG(ZONE_WARN, (TEXT("PPP: WARNING - ACK received with nonmatching option list\n")));
						dwResult = ERROR_INVALID_MESSAGE;
						break;
					}
				}
				dwResult = PppFsmProcessRxConfigureResponse(pFsm, pPacket, cbPacket);
				if (dwResult == ERROR_UNRECOGNIZED_RESPONSE && code == PPP_CONFIGURE_ACK)
				{
					//
					// Treat the malformed ACK packet as a NAK.
					// This is specifically designed to deal with a misbehaving peer
					// that sends a MPPE ACK with more than 1 encryption type enabled.
					// The CCP code will adjust the next CR sent.
					//
					dwResult = NO_ERROR;
					code = PPP_CONFIGURE_NAK;
				}
				if (dwResult == NO_ERROR)
				{
					// Valid response
					PppFsmActionIRC(pFsm, pFsm->dwMaxConfigure);
					if (code == PPP_CONFIGURE_ACK)
						newState = curState == PFS_Request_Sent ? PFS_Ack_Received : PFS_Opened;
					else
					{
						pFsm->idTxCR++;
						if (PppFsmActionSCR(pFsm) != NO_ERROR)
						    newState = PFS_Stopped;
					}
				}
				break;
			}
			break;

		case PPP_TERMINATE_REQUEST:
			switch(curState)
			{
			case PFS_Closed:
			case PFS_Closing:
			case PFS_Stopped:
			case PFS_Stopping:
			case PFS_Request_Sent:
				PppFsmActionSTA(pFsm, id);
				break;

			case PFS_Ack_Received:
			case PFS_Ack_Sent:
				PppFsmActionSTA(pFsm, id);
				newState = PFS_Request_Sent;
				break;

			case PFS_Opened:
			    PppFsmActionTLD(pFsm);
				PppFsmActionZRC(pFsm);
				PppFsmActionSTA(pFsm, id);
				newState = PFS_Stopping;
				break;
			}
			break;

		case PPP_TERMINATE_ACK:
			switch (pFsm->state)
			{
			case PFS_Closing:
				newState = PFS_Closed;
				break;

			case PFS_Stopping:
				newState = PFS_Stopped;
				break;

			case PFS_Ack_Received:
				// This is per RFC1661, but seems wierd that
				// we enter the Request_Sent state without
				// sending a new request...
				newState = PFS_Request_Sent;
				break;

			case PFS_Opened:
			    PppFsmActionTLD(pFsm);
				pFsm->idTxCR++;
				if (PppFsmActionSCR(pFsm) == NO_ERROR)
					newState = PFS_Request_Sent;
				else
					newState = PFS_Stopped;
				break;
			}
			break;

		case PPP_CODE_REJECT:
			//
			// We must be running a newer version of the protocol,
			// such that the peer does not understand the code.
			//
			// If the rejected code is for a required message type
			// like PPP_CONFIGURE_REQUEST, this is catastrophic
			// and we need to take down the link.
			//
			// Regardless, log the bad message the peer doesn't like,
			// stop sending that message type.
			//

			break;

		default:
			//
			// Search the list of protocol specific code handlers
			//
			pMsgDescriptor = pFsm->pDescriptor->pExtensionMessageDescriptors;
			if (pMsgDescriptor)
			{
				while (TRUE)
				{
					if (pMsgDescriptor->MessageRxCb == NULL)
					{
						// Didn't find a matching handler
						pMsgDescriptor = NULL;
						break;
					}
					if (pMsgDescriptor->code == code)
					{
						break;
					}
					pMsgDescriptor++;
				}
			}

			if (pMsgDescriptor)
			{
				//
				// Invoke the extension message handler
				//
				pMsgDescriptor->MessageRxCb(pFsm->CbContext, code, id, pPacket + 4, length - 4);
			}
			else
			{
				//
				// Unrecognized code - RUC
				PppFsmActionSendCodeReject(pFsm, pPacket, cbPacket);
			}
			break;
		}

		PppFsmNewState(pFsm, newState);

	} while (FALSE); // end do
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -