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

📄 lcp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
lcpIdleDisconnectTimerStart(
	IN  PLCPContext	    pContext,
	IN  DWORD           DurationMs)
{
	if (DurationMs && pContext->pFsm->state == PFS_Opened)
	{
		CTEStartTimer(&pContext->IdleDisconnectTimer, DurationMs, lcpIdleDisconnectTimerCb, (PVOID)pContext);
	}
}

void
lcpIdleDisconnectTimerCb(
	CTETimer *timer,
	PVOID     context)
//
//  This function is called periodically to check to see if we are receiving traffic from the
//  peer. We take action based upon how much time has elapsed since the last traffic received:
//
//  Elapsed Time                            Action
//  ------------                            ------
//  0 to dwIdleDisconnectMs/2               Restart timer for dwIdleDisconnectMs/2
//  dwIdleDisconnect/2 to dwIdleDisconnect  Send Echo Request, start timer for dwEchoRequestIntervalMs
//  > dwIdleDisconnect                     Terminate link
//
{
	PLCPContext	    pContext = (PLCPContext)context;
	BOOL            bTerminateConnection = FALSE;
	DWORD           CurrentTime = GetTickCount();
	DWORD           TimeSinceLastRxData;

	pppLock(pContext->session);

	if (pContext->session->bRxData)
	{
		pContext->session->bRxData = FALSE;
		pContext->LastRxDataTime = CurrentTime;

		// Line is receiving, restart timer
		lcpIdleDisconnectTimerStart(pContext, pContext->dwIdleDisconnectMs / 2);
	}
	else
	{
		// Didn't receive anything lately
		
		TimeSinceLastRxData = CurrentTime - pContext->LastRxDataTime;

		if (TimeSinceLastRxData <= pContext->dwIdleDisconnectMs)
		{
			// We haven't been idle for too long, send echo request
			lcpEchoRequestSend(pContext);
			lcpIdleDisconnectTimerStart(pContext, pContext->dwEchoRequestIntervalMs);
		}
		else
		{
			// Idle for too long, disconnect
		    DEBUGMSG(ZONE_WARN, (L"PPP: WARNING - No RX data from peer for %u ms, terminating connection\n", pContext->dwIdleDisconnectMs));
			pContext->session->bDisconnectDueToUnresponsivePeer = TRUE;
			pppLcp_Close(pContext, NULL, NULL);
		}
	}

	pppUnLock(pContext->session);

}

void
lcpSetIdleDisconnectMs(
	IN	PVOID	context,
	IN  DWORD   dwIdleDisconnectMs)
{
	PLCPContext	    pContext = (PLCPContext)context;

	lcpIdleDisconnectTimerStop(pContext);

	pContext->dwIdleDisconnectMs = dwIdleDisconnectMs;

	pContext->LastRxDataTime = GetTickCount();
	lcpIdleDisconnectTimerStart(pContext, pContext->dwIdleDisconnectMs / 2);
}

void
lcpRxDiscardRequest(
	IN	PVOID	context,
	IN	BYTE	code,
	IN  BYTE    id,
	IN	PBYTE	pData,
	IN	DWORD	cbData)
{
}

PppFsmExtensionMessageDescriptor lcpExtensionMessageDescriptor[] =
{
	{LCP_PROTOCOL_REJECT, "Protocol-Reject", lcpRxProtocolReject},
	{LCP_ECHO_REQUEST,    "Echo-Request",    lcpRxEchoRequest},
	{LCP_ECHO_REPLY,      "Echo-Reply",      lcpRxEchoReply},
	{LCP_DISCARD_REQUEST, "Discard-Request", lcpRxDiscardRequest},
	{0,                    NULL,             NULL}
};

//
//	cbMaxTxPacket derivation for LCP:
//		6 bytes standard PPP packet header
//		4 bytes MRU option
//		6 bytes ACCM option
//		5 bytes auth option
//		6 bytes magic number option
//		2 bytes pfc option
//		2 bytes acfc option
//
static PppFsmDescriptor lcpFsmData =
{
	"LCP",             // szProtocolName
	PPP_PROTOCOL_LCP,  // ProtocolWord
	64,					// cbMaxTxPacket
	lcpUp,
	lcpDown,
	lcpStarted,
	lcpFinished,
	lcpSendPacket,
	lcpSessionLock,
	lcpSessionUnlock,
	&lcpExtensionMessageDescriptor[0]	// Extension message handlers for LCP
};

void
pppLcp_Open(
	IN	PLCPContext	pContext)
//
//  Get the LCP FSM into the opened state, ready to establish connections when the
//  MAC layer is up.
//
{
	PppFsmOpen(pContext->pFsm);
}

void
pppLcp_Close(
	IN	PLCPContext	pContext,
	IN	void	    (*pLcpCloseCompleteCallback)(PVOID),
	IN	PVOID	    pCallbackData)
//
//	Get LCP into the initial state, i.e. closed and MAC layer down.
//  When PFS_Initial is achieved, invoke the pLcpCloseCompleteCallback function.
//
{
	DWORD dwResult;

    DEBUGMSG(ZONE_FUNCTION, (TEXT( "PPP: +pppLcp_Close\n" )));

	// Signal the state machine to
	// get to the initial state.  The state machine will
	// call pppLcpCloseCompleteCallback when that state
	// is achieved, and that function will call the
	// pLcpCloseCompleteCallback handler.
	//

	DEBUGMSG(ZONE_LCP, (TEXT( "PPP: PppFsmClose LCP\n" )));
	PppFsmClose(pContext->pFsm);

	if( pContext->pFsm->state == PFS_Initial )
	{
		// All done
		if (pLcpCloseCompleteCallback)
			pLcpCloseCompleteCallback(pCallbackData);
	}
	else 
	{	
		// Can be in one of the following states:
		//   PFS_Closed  (MAC layer is still up)
		//   PFS_Closing (MAC layer is up, waiting for terminate-ack)
		//
		// Allocate and add the close request to the queue of
		// pending close requests.
		//
		dwResult = pppInsertCompleteCallbackRequest(&pContext->pPendingCloseCompleteList, pLcpCloseCompleteCallback, pCallbackData);
		if (ERROR_SUCCESS != dwResult)
		{
			// Unable to allocate callback structure. Perform callback immediately as if LCP was down (no graceful LCP shutdown).
			if (pLcpCloseCompleteCallback)
				pLcpCloseCompleteCallback(pCallbackData);
		}
		else
		{
			if (pContext->pFsm->state == PFS_Closed)
			{
				// Need to terminate MAC layer to get to Initial state
				pppMac_CallClose(pContext->session->macCntxt, NULL, NULL);

				// When lcpLowerLayerDown is called, we will enter the PFS_Initial state and
				// process pPendingCloseCompleteList
			}
			else // PFS_Closing state
			{
				// lcpFinished will be called when the state machine transitions from:
				//    PFS_Closing to PFS_Initial (on a Down indication) or
				//    PFS_Closing to PFS_Closed (on receive-terminate-ack)
			}
		}
	}
    DEBUGMSG(ZONE_FUNCTION, (TEXT( "PPP: -pppLcp_Close\n" )));
}

void
pppLcp_Rejected(
	IN	PVOID	context )
//
//	Called when the peer rejects the LCP protocol.
//  The link will be terminated.
//
{
	PLCPContext	pContext = (PLCPContext)context;
			
	PppFsmProtocolRejected(pContext->pFsm);
}

static BOOLEAN
StringIsInMultiSz(
	IN	PWSTR	sz,
	IN	PWSTR	multisz)
//
//	Return TRUE if sz is one of the strings in multisz.
//
{
	BOOLEAN	bFound = FALSE;

	while (*multisz != L'\0')
	{
		if (wcsicmp(sz, multisz) == 0)
		{
			bFound = TRUE;
			break;
		}
		multisz += wcslen(multisz) + 1;
	}
	return bFound;
}

DWORD
LcpOpen(
	IN	PVOID	context)
//
//  Called when RasIoControl is invoked to cause us to open LCP.
//
{
	PLCPContext	    pContext = (PLCPContext)context;

	DEBUGMSG(ZONE_LCP, (TEXT("PPP: Open LCP\n")));
	return PppFsmOpen(pContext->pFsm);
}

DWORD
LcpClose(
	IN	PVOID	context)
//
//  Called when RasIoControl is invoked to cause us to open LCP.
//
{
	PLCPContext	    pContext = (PLCPContext)context;

	DEBUGMSG(ZONE_LCP, (TEXT("PPP: Close LCP\n")));
	return PppFsmClose(pContext->pFsm);
}

DWORD
LcpRenegotiate(
	IN	PVOID	context)
//
//  Called when RasIoControl is invoked to cause us to renegotiate
//  our LCP parameters, typically after we have modified one of
//  the settings.
//
{
	PLCPContext	    pContext = (PLCPContext)context;

	DEBUGMSG(ZONE_LCP, (TEXT("PPP: Renegotiate LCP\n")));
	return PppFsmRenegotiate(pContext->pFsm);
}

DWORD
LcpGetParameter(
	IN	    PVOID	                  context,
	IN  OUT PRASCNTL_LAYER_PARAMETER  pParm,
	IN  OUT PDWORD                    pcbParm)
//
// Called by RasIoControl to get a particular LCP parameter.
//
{
	PLCPContext	    pContext = (PLCPContext)context;
	DWORD           dwResult = ERROR_SUCCESS;
	lcpOptValue_t  *pValues = &pContext->local;

	pParm->dwValueType = RASCNTL_LAYER_PARAMETER_TYPE_DWORD;
	pParm->dwValueSize = sizeof(DWORD);
	switch (pParm->dwParameterId)
	{
	case LCP_OPT_MRU:
		pParm->dwValue = pValues->MRU;
		break;

	case LCP_OPT_ACCM:
		pParm->dwValue = pValues->ACCM;
		break;

	case LCP_OPT_AUTH_PROTOCOL:
		pParm->dwValue = pValues->Auth.Protocol;
		break;

	case LCP_OPT_MAGIC_NUMBER:
		pParm->dwValue = pValues->MagicNumber;
		break;

	case LCP_OPT_PFC:
		pParm->dwValue = pValues->bPFC;
		break;

	case LCP_OPT_ACFC:
		pParm->dwValue = pValues->bACFC;
		break;

	default:
		dwResult = ERROR_INVALID_PARAMETER;
		break;
	}

	return dwResult;
}

DWORD
LcpSetParameter(
	IN	    PVOID	                  context,
	IN      PRASCNTL_LAYER_PARAMETER  pParm,
	IN      DWORD                     cbParm)
//
// Called by RasIoControl to set a particular LCP parameter.
//
{
	PLCPContext	    pContext = (PLCPContext)context;
	DWORD           dwResult = ERROR_SUCCESS;
	lcpOptValue_t  *pValues = &pContext->local;

	switch (pParm->dwParameterId)
	{
	case LCP_OPT_MRU:
		pValues->MRU = (USHORT)pParm->dwValue;;
		break;

	case LCP_OPT_ACCM:
		pContext->DesiredACCM = pParm->dwValue;
		break;

	case LCP_OPT_AUTH_PROTOCOL:
		pValues->Auth.Protocol = (USHORT)pParm->dwValue;
		break;

	case LCP_OPT_MAGIC_NUMBER:
		pValues->MagicNumber = pParm->dwValue;
		break;

	case LCP_OPT_PFC:
		pValues->bPFC = pParm->dwValue;
		break;

	case LCP_OPT_ACFC:
		pValues->bACFC = pParm->dwValue;
		break;

	default:
		dwResult = ERROR_INVALID_PARAMETER;
		break;
	}

	return dwResult;
}

PROTOCOL_DESCRIPTOR pppLcpProtocolDescriptor =
{
	pppLcpRcvData,
	LcpProtocolRejected,
	LcpOpen,
	LcpClose,
	LcpRenegotiate,
	LcpGetParameter,
	LcpSetParameter
};

DWORD
pppLcp_InstanceCreate(
	IN	PVOID session,
	OUT	PVOID *ReturnedContext)
//
//	Called during session creation to allocate and initialize the IPCP protocol
//	context.
//
{
	pppSession_t    *pSession = (pppSession_t *)session;
	RASPENTRY		*pRasEntry = &pSession->rasEntry;
	PLCPContext     pContext;
	DWORD			dwResult = NO_ERROR;
	WCHAR           wmszIdleDeviceTypes[MAX_PATH];
	
    DEBUGMSG( ZONE_LCP | ZONE_FUNCTION, (TEXT( "pppLcp_InstanceCreate\r\n" )));
    ASSERT( session );

	do
	{
		pContext = (PLCPContext)pppAlloc(pSession,  sizeof(*pContext), TEXT( "IPCP CONTEXT" ) );
		if( pContext == NULL )
		{
			DEBUGMSG( ZONE_LCP, (TEXT( "PPP: ERROR: NO MEMORY for IPCP context\r\n" )) );
			dwResult = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Register LCP context and protocol decriptor with session

		dwResult = PPPSessionRegisterProtocol(pSession, PPP_PROTOCOL_LCP, &pppLcpProtocolDescriptor, pContext);
		if (dwResult != NO_ERROR)
			break;

		// Initialize context

		pContext->session = session;

		pContext->pPendingCloseCompleteList = NULL;

		CTEInitTimer(&pContext->IdleDisconnectTimer);
		pContext->dwIdleDisconnectMs = DEFAULT_IDLE_DISCONNECT_MS;
		pContext->dwEchoRequestIntervalMs = DEFAULT_ECHO_REQUEST_INTERVAL_MS;
		memset(wmszIdleDeviceTypes, 0, sizeof(wmszIdleDeviceTypes));
		wcscpy(wmszIdleDeviceTypes, RASDT_PPPoE);

		(void)ReadRegistryValues(HKEY_LOCAL_MACHINE, TEXT("Comm\\ppp\\Parms"),
										RAS_VALUENAME_LCP_IDLE_DISCONNECT_MS, REG_DWORD, 0,  &pContext->dwIdleDisconnectMs, sizeof(DWORD),
										RAS_VALUENAME_LCP_ECHO_REQUEST_INTERVAL_MS, REG_DWORD, 0,  &pContext->dwEchoRequestIntervalMs, sizeof(DWORD),
										RAS_VALUENAME_LCP_IDLE_DEVICE_TYPES, REG_MULTI_SZ, 0, &wmszIdleDeviceTypes[0], sizeof(wmszIdleDeviceTypes),
										NULL);

		if (!StringIsInMultiSz(pRasEntry->szDeviceType, wmszIdleDeviceTypes))
		{
			// Disable Idle Disconnect detection for this connection
			pContext->dwIdleDisconnectMs = 0;
		}

		// Create Fsm

		pContext->pFsm = PppFsmNew(&lcpFsmData, lcpResetPeerOptionValuesCb, pContext);
		if (pContext->pFsm == NULL)
		{
			dwResult = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Configure option values

		lcpOptionInit(pContext);

		// Put the FSM into the opened state, ready to go when the lower layer comes up

		PppFsmOpen(pContext->pFsm);
	} while (FALSE);

	if (dwResult != NO_ERROR)
	{
		pppFree(pSession, pContext, TEXT( "LCP CONTEXT" ));
		pContext = NULL;
	}

	*ReturnedContext = pContext;
    return dwResult;
}

void
pppLcp_InstanceDelete(
	IN	PVOID	context )
//
//	Called during session deletion to free the IPCP protocol context
//	created by pppLcp_InstanceCreate.
//
{
	PLCPContext	pContext = (PLCPContext)context;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+pppLcp_InstanceDelete\r\n" )));

	if (context)
	{
		DEBUGMSG(ZONE_LCP, (TEXT( "PPP: Close LCP\n" )));

		lcpIdleDisconnectTimerStop(pContext);
		PppFsmClose(pContext->pFsm);
		PppFsmDelete(pContext->pFsm);
		pppFree( pContext->session, pContext, TEXT( "LCP CONTEXT" ) );
	}
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-pppLcp_InstanceDelete\r\n" )));
}

DWORD
pppLcp_QueryParameter(
	IN	    PVOID	context,
	IN      BOOL    bLocal,
	IN      DWORD   type,
	    OUT PVOID   pValue,
	IN  OUT PDWORD  pcbValue)
//
//  Query the value of a parameter negotiated by LCP
//
{
	PLCPContext	   pContext = (PLCPContext)context;
	DWORD          dwResult = NO_ERROR;
	lcpOptValue_t *pValues = bLocal ? &pContext->local : &pContext->peer;
    PVOID          pCurValue;
	DWORD          dwSize;

	switch(type)
	{
	case LCP_OPT_MRU:
		dwSize = sizeof(pValues->MRU);
		pCurValue = &pValues->MRU;
		break;

	case LCP_OPT_AUTH_PROTOCOL:
		dwSize = sizeof(lcpAuthValue_t);
		pCurValue = &pValues->Auth;
		break;

	default:
		dwResult = ERROR_INVALID_PARAMETER;
		break;
	}

	if (dwResult == NO_ERROR)
	{
		if (*pcbValue < dwSize)
			dwResult = ERROR_INSUFFICIENT_BUFFER;
		else
			memcpy(pValue, pCurValue, dwSize);

		*pcbValue = dwSize;
	}

	return dwResult;
}

⌨️ 快捷键说明

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