--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linklayerprotocols/pppnif/SPPP/PPPFSM.CPP Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1826 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+#include "PPPLCP.H"
+#include "PPPBASE.H"
+#include "PPPLOG.H"
+#include "ncpip.h"
+#include "PPPCCP.H" // for KPppIdCcp
+#include <es_ini.h>
+
+//
+// PPP State machine
+//
+
+MPppFsm::MPppFsm(CPppLcp* aPppLcp, TPppPhase aPhase, TUint aPppId)
+ : MPppRecvr(aPppLcp, aPhase, aPppId),
+ // Values may be initialized via .ini file, but unless specified otherwise:
+ iTerminateRequestEnabled(ETrue), // RFC-compliant termination phase (TerminateRequest) is enabled
+ iTerminateAckEnabled(ETrue), // RFC-compliant termination phase (TerminateAck) is enabled
+ iFsmTerminationCauseError(KErrNone),
+ iMaxTerminateRequest(KPppFsmTerminateRequestRetries), // Wait after Sending TerminateRequest
+ iTerminateRequestTimeout(KPppFsmTerminateRequestTimeout), // Wait for TerminateAck after sending TerminateRequest
+ iTerminateAckTimeout(KPppFsmTerminateAckTimeout), // Wait after sending TerminateAck
+ iFsmTermination(EFalse),
+ iNoEvidenceOfPeer(EFalse),
+ iWaitTimeNoIncrease(EFalse)
+ {
+ }
+
+MPppFsm::~MPppFsm()
+ {
+ TimerDelete();
+ if (!iRequestList.IsEmpty())
+ iRequestList.Free();
+ }
+
+void MPppFsm::FsmConstructL()
+/**
+Construct the state machine object
+*/
+ {
+ ReadIniFileL();
+ // Dump the configuration resulting from the .ini file:
+
+ LOG(iPppLcp->iLogger->Printf(_L("%s FSM: TerminateRequestEnabled[%d], MaxTerminateRequest[%d], TerminateRequestTimeout[%d]"),\
+ __iFsmName,
+ iTerminateRequestEnabled,
+ iMaxTerminateRequest,
+ iTerminateRequestTimeout);)
+
+ LOG(iPppLcp->iLogger->Printf(_L("%s FSM: TerminateAckEnabled[%d], TerminateAckTimeout[%d]"),\
+ __iFsmName,
+ iTerminateAckEnabled,
+ iTerminateAckTimeout);)
+
+ TimerConstructL(KPppFsmTimerPriority);
+ }
+
+void MPppFsm::TerminateLink()
+/**
+Tear down the protocol, regardless of the state of the FSM.
+*/
+ {
+ // Support for Termination Phase.
+ // This is not according to the RFC, but it is done to avoid
+ // any regressions in the existing PPP.
+ switch(iState)
+ {
+ case EPppFsmStopping: // We have received TerminateRequest, sent TerminateAck and
+ // are waiting for one timeout to expire.
+ break; // Stay in EPppFsmStopping state
+ default:
+ SendInitialTerminateRequest();
+ SetState(EPppFsmClosing);
+ }
+ }
+
+//
+// Open/Close calls from higher level protocols
+//
+
+TInt MPppFsm::FsmOpen()
+/**
+Begin the state machine and protocol.
+Called by the derived class during initialization.
+
+@return KErrNone if successful, otherwise one of the system-wide error codes
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Open Request"), __iFsmName); )
+ TInt err = KErrNone;
+
+ InitMaxFailure();
+
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ err = FsmLayerStarted();
+ SetState(EPppFsmStarting);
+ break;
+ case EPppFsmStarting:
+ break;
+ case EPppFsmClosed:
+ err = FsmLayerStarted();
+ SendInitialConfigRequest();
+ SetState(EPppFsmReqSent);
+ break;
+ case EPppFsmStopped:
+ case EPppFsmClosing:
+ case EPppFsmStopping:
+ case EPppFsmOpened:
+ // Check that we *really* want to do this!
+ LowerLayerDown();
+ LowerLayerUp();
+ break;
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ break;
+ }
+ iPppAbortCode = KErrNone;
+ return err;
+ }
+
+void MPppFsm::FsmClose(TInt aReason)
+/**
+Close the state machine and protocol.
+Called by the derived class on closing.
+
+@param aReason Reason for closing
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Close Request, error[%d]"), __iFsmName, aReason); )
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmClosed:
+ case EPppFsmClosing:
+ break;
+ case EPppFsmStarting:
+ FsmLayerFinished();
+ SetState(EPppFsmInitial);
+ break;
+ case EPppFsmStopped:
+ SetState(EPppFsmClosed);
+ break;
+ case EPppFsmStopping:
+ SetState(EPppFsmClosing);
+ break;
+ case EPppFsmOpened:
+ FsmLayerDown(aReason);
+ // continue into next statement
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ SendInitialTerminateRequest();
+ SetState(EPppFsmClosing);
+ break;
+ }
+ }
+
+void MPppFsm::FsmAbort(TInt aReason)
+/**
+Abort the protocol.
+
+@param aReason Reason for aborting
+*/
+// 29.11.00. Changed slightly so that this does the same as RXJ-
+// in the PPP RFC for all states.
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Abort Request, error[%d]"), __iFsmName, aReason); )
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ // bad event
+ break;
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ FsmLayerFinished();
+ break;
+ case EPppFsmClosing:
+ FsmLayerFinished();
+ SetState(EPppFsmClosed);
+ break;
+ case EPppFsmStopping:
+ FsmLayerFinished();
+ SetState(EPppFsmStopped);
+ break;
+ case EPppFsmOpened:
+ FsmLayerDown();
+ SendInitialTerminateRequest();
+ SetState(EPppFsmStopping);
+ break;
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ FsmLayerFinished(aReason);
+ SetState(EPppFsmStopped);
+ break;
+ }
+ iPppAbortCode = aReason;
+ }
+
+
+
+//
+// Upcall from Timer
+//
+
+EXPORT_C void MPppFsm::TimerComplete(TInt /*aStatus*/)
+/**
+Called by MTimer on timer expiry.
+
+@param aStatus Aynchronous request completion status (ignored)
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Timer Expired %d "), __iFsmName, iRestartCount); )
+
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ case EPppFsmOpened:
+ // Bad Event
+ return;
+ default:
+ break;
+ }
+
+ if (iRestartCount>0)
+ {
+ switch (iState)
+ {
+ case EPppFsmClosing:
+ case EPppFsmStopping:
+ SendTerminateRequest();
+ break;
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ //PG RFC 1661 4.6 double timeout period
+ // Allow for configuration of non-doubling of timeout period (initially for
+ // conformance testing) - default behaviour is for doubling to occur.
+ if (!iWaitTimeNoIncrease && iWaitTime*2 < KPppFsmRequestMaxTimeout)
+ {
+ iWaitTime = iWaitTime * 2;
+ }
+ SendConfigRequest();
+ if(iState == EPppFsmAckRecvd)
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch(iState)
+ {
+ case EPppFsmClosing: // We sent out TerminateRequests, no TerminateAcks received.
+ FsmLayerFinished(iFsmTerminationCauseError); // Authoritative Close of the Link --> KErrCancel
+ break;
+ case EPppFsmStopping: // We've sent TerminateAck and waited one restart period
+ FsmLayerFinished(iFsmTerminationCauseError); // Peer initiated disconnection.
+ break;
+ default:
+ // Don't abort if we're configured to persist.
+ if(!iPersist)
+ {
+ iFsmTermination = ETrue; // Used later to bring down the FSM as opposed to restarting it.
+ FsmLayerFinished(KErrTimedOut);
+ }
+ else
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM going idle"), __iFsmName); )
+ }
+ break;
+ }
+
+ switch (iState)
+ {
+ case EPppFsmClosing:
+ SetState(EPppFsmClosed);
+ break;
+ case EPppFsmStopping:
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ SetState(EPppFsmStopped);
+ break;
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ case EPppFsmOpened:
+ default:
+ break;
+ }
+ }
+ }
+
+//
+// Upcalls from Recvr
+//
+
+EXPORT_C void MPppFsm::LowerLayerUp()
+/**
+Called when the lower layer protocol has come up.
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Up Event"), __iFsmName); )
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ SetState(EPppFsmOpened);
+ break;
+ case EPppFsmStarting:
+ SendInitialConfigRequest();
+ SetState(EPppFsmReqSent);
+ break;
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ case EPppFsmClosing:
+ case EPppFsmStopping:
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ case EPppFsmOpened:
+ // Bad Event
+ break;
+ }
+ }
+
+
+EXPORT_C void MPppFsm::LowerLayerDown(TInt aStatus)
+/**
+Signals the Down event.
+Called when the lower layer protocol has gone down.
+This means that our layer can no longer receive or transmit anything.
+
+In case of LCP, this means that the physical link is closed (e.g. Peer dropped DTR)
+If we are LCP, this may mean that PPP is finished, because the link is no longer available.
+
+@param aStatus Error code indicating the reason the layer is going down
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Down Event, error[%d]"), __iFsmName, aStatus); )
+
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ // Bad Event
+ break;
+ case EPppFsmStarting:
+ FsmLayerDown(aStatus);
+ break;
+ case EPppFsmClosed:
+ SetState(EPppFsmInitial);
+ break;
+ case EPppFsmClosing: // We are waiting for Terminate Ack (or TerminateRequest retransmission)
+ SetState(EPppFsmInitial);
+ break;
+ case EPppFsmStopped:
+ if(!iFsmTermination) // We are not terminating, so we restart the FSM.
+ {
+ FsmLayerStarted();
+ SetState(EPppFsmStarting);
+ return; // The alternative is calling FsmTerminationPhaseComplete from every case.
+ }
+ // If we are terminating, we terminate the FSM and notify Nifman that the NIF is finished.
+ SetState(EPppFsmStarting);
+ break;
+ case EPppFsmStopping: // We are waiting 1 restart period after transmitting Terminate Ack
+ SetState(EPppFsmStarting);
+ break;
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ FsmLayerDown(aStatus);
+ SetState(EPppFsmStarting);
+ break;
+ case EPppFsmOpened:
+ FsmLayerDown(aStatus);
+ SetState(EPppFsmStarting);
+ break;
+ }
+ // This call is critical to make sure PPP reports its demise correctly. Otherwise, Nifman remains unaware, and
+ // ESock / Nifman / PPP hangs.
+ FsmTerminationPhaseComplete(); // ASSUMPTION: LCP signals to Nifman. Others do nothing.
+ // Note: early return from EPppFsmStopped.
+ }
+
+EXPORT_C void MPppFsm::FrameError()
+/**
+Called when a bad frame is received.
+No action is currently taken.
+
+@see RecvFrame() is called instead when a good frame is received
+*/
+ {
+ return;
+ }
+
+EXPORT_C void MPppFsm::KillProtocol()
+/**
+Called when the lower level protocol is killed.
+*/
+ {
+ //
+ // This came to light as a result of the CCP work
+ // This happens if a protocol is told to shut down,
+ // I'm not sure how to handle it?? Do we just Stop it???
+ //
+ return;
+ }
+
+EXPORT_C TBool MPppFsm::RecvFrame(RMBufChain& aPacket)
+/**
+Receives and processes a PPP frame.
+Called by CPppLcp.
+
+@see FrameError() is called instead when a bad frame is received
+
+@param aPacket MBuf chain containing packet
+
+@return EFalse
+*/
+ {
+ RMBufPacket pkt;
+ pkt.Assign(aPacket);
+ pkt.Unpack();
+ RMBufPktInfo* info = pkt.Info();
+
+ TUint8 op;
+ TUint8 id;
+ TInt len;
+
+ // Extract and drop LCP header
+ pkt.Align(4);
+ TUint8* ptr = pkt.First()->Ptr();
+ op = *ptr++;
+ id = *ptr++;
+ len = BigEndian::Get16(ptr);
+
+ // Check packet length is OK
+ if (info->iLength<len || info->iLength<4 )
+ {
+ // Too short!
+ pkt.Free();
+ return EFalse;
+ }
+ else if (info->iLength > len)
+ pkt.TrimEnd(len);
+
+ // Received a potentially valid packet; probably we have a meaningful relationship with peer
+ iNoEvidenceOfPeer = EFalse;
+ // If op is unknown
+ switch (op)
+ {
+ case KPppLcpConfigAck:
+ case KPppLcpConfigNak:
+ case KPppLcpConfigReject:
+ // Filter out bad acks
+ if (iState>=EPppFsmReqSent && id!=iRequestId)
+ break;
+ else
+ iRequestId |= KPppRequestIdAnswered;
+ // fall through ...
+ case KPppLcpConfigRequest:
+ // Option negotiation ops
+ // Split the MBuf chain in separate options
+
+ //if(len<=4)
+ if(len<4)
+ break;
+
+ //
+ // Hmmm sometimes we receive a Config request of Length 4
+ // i.e. no options Send a Config ACK
+ //
+ if ( (len == 4) && (op == KPppLcpConfigRequest))
+ {
+ if (ProcessEmptyConfigReq())
+ {
+ if (iPppId == KPppIdCcp)
+ {
+ // For empty CCP Config Requests send a Protocol Reject,
+ // otherwise we can end up continually exchanging empty
+ // Config Requests and Config ACK's. KPppIdLcp is passed to
+ // CPppHdlcLink::Send() via FsmRejectPacket() to ensure
+ // transmission of an *LCP* Protocol Reject of CCP rather than
+ // a *CCP* Protocol Reject of CCP (subtle difference).
+ pkt.Pack();
+ FsmRejectPacket(pkt, KPppLcpProtocolReject, KPppIdLcp);
+ }
+ else
+ {
+ // Send an acknowledgement
+ ptr = pkt.First()->Ptr();
+ *ptr = KPppLcpConfigAck;
+ pkt.Pack();
+ SendFrame(pkt);
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (len == 4 && (op != KPppLcpConfigAck && iPppLcp->QueryExternalIPConfiguration()))
+ {
+ // With Mobile IP, there is the possibility of having no options to negotiate, in which
+ // case an empty ConfigReq would be sent out. This would be acknowledged by an empty
+ // ConfigAck, so ensure that we process the latter.
+ break;
+ }
+ else
+ {
+ pkt.TrimStart(4);
+ ProcessConfig(op, id, len-4, pkt);
+ }
+
+ break;
+ case KPppLcpTerminateAck:
+ // Filter out bad acks
+ if ((iState==EPppFsmClosing || iState==EPppFsmStopping) && id!=iTerminateId)
+ break;
+ else
+ iTerminateId |= KPppRequestIdAnswered;
+ // fall through ...
+ case KPppLcpTerminateRequest:
+ if(len<4)
+ break;
+
+ pkt.TrimStart(4);
+ ProcessTerminate(op, id, len-4, pkt);
+ break;
+ case KPppLcpCodeReject:
+ case KPppLcpProtocolReject:
+ if(len<=4)
+ break;
+ pkt.TrimStart(4);
+ ProcessReject(op, id, len-4, pkt);
+ break;
+ default:
+ if (!FsmRecvUnknownCode(op, id, len, pkt))
+ {
+ pkt.Pack();
+ FsmRejectPacket(pkt);
+ }
+ break;
+ }
+ pkt.Free();
+ return EFalse;
+ }
+
+//
+// Rest of PPP
+//
+
+TBool MPppFsm::FsmRecvUnknownCode(TUint8 /*aCode*/, TUint8 /*aId*/, TInt /*aLength*/, RMBufChain& /*aPacket*/)
+/**
+Handle a received packet with an unknown code.
+
+@param aCode Packet code (ignored)
+@param aId Packet identifier (ignored)
+@param aLength Length of packet (ignored)
+@param aPacket MBuf chain containing packet (ignored)
+
+@return EFalse
+*/
+ {
+ return EFalse;
+ }
+
+void MPppFsm::ProcessReject(TUint8 aCode, TUint8 /*aId*/, TInt /* aLength */, RMBufChain& aPacket)
+/**
+Handle a Code Reject or Protocol Reject.
+If the reject rejects a code (or protocol) that should
+be known terminate layer.
+(Note, As the behaviour of protocol reject is the same
+as code reject, this function handles protocol reject for LCP)
+
+@param aCode Packet code
+@param aId Packet identifier (ignored)
+@param aLength Length of packet (ignored)
+@param aPacket MBuf chain containing packet.
+*/
+ {
+ TBool isCatastrophic = EFalse;
+
+ // Valid reject packets should have a len >=4
+ if(aPacket.Length()<4)
+ return;
+
+ // Determine if the reject is acceptable
+ if (aCode==KPppLcpProtocolReject)
+ {
+
+ aPacket.Align(2);
+ TUint prot = BigEndian::Get16(aPacket.First()->Ptr());
+ aPacket.TrimStart(2);
+ switch (prot)
+ {
+ case KPppIdLcp:
+ isCatastrophic = ETrue;
+ break;
+
+ case KPppIdCompressedData:
+ // Shut down and unload the current compressor
+ LOG( iPppLcp->iLogger->Printf(_L("Compressed Packet rejected: Unloading compressor.")); )
+ iPppLcp->PppUnloadCompressor() ;
+ break ;
+
+ default:
+ {
+ /*
+ * Tut tut the existing code only handled Protocol rejects for the
+ * LCP protocol. What about all the others?
+ */
+ iFsmTermination = ETrue; // Used later to bring down the FSM as opposed to restarting it.
+ iPppLcp->StopProtocol(prot);
+ break;
+ }
+ }
+ }
+ else
+ {
+ TUint8 code = aPacket.First()->Get(0);
+ switch (code)
+ {
+ case KPppLcpConfigRequest:
+ case KPppLcpConfigAck:
+ case KPppLcpConfigNak:
+ case KPppLcpConfigReject:
+ case KPppLcpTerminateRequest:
+ case KPppLcpTerminateAck:
+ isCatastrophic = ETrue;
+ break;
+ case KPppLcpCodeReject:
+ case KPppLcpProtocolReject:
+ iFsmTermination = ETrue;
+ isCatastrophic = ETrue;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!isCatastrophic)
+ {
+ if (iState==EPppFsmAckRecvd)
+ SetState(EPppFsmReqSent);
+ return;
+ }
+
+ LOG( iPppLcp->iLogger->Printf(_L("%s Catastrophic Reject, packet code[%d]"), __iFsmName, aCode); )
+
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ // bad event
+ break;
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ FsmLayerFinished();
+ break;
+ case EPppFsmClosing:
+ FsmLayerFinished();
+ SetState(EPppFsmClosed);
+ break;
+ case EPppFsmStopping:
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ FsmLayerFinished();
+ SetState(EPppFsmStopped);
+ break;
+ case EPppFsmOpened:
+ FsmLayerDown();
+ SendInitialTerminateRequest();
+ SetState(EPppFsmStopped);
+ break;
+ }
+ }
+
+void MPppFsm::ProcessTerminate(TUint8 aCode, TUint8 aId, TInt /*aLength*/, RMBufChain& /*aPacket*/)
+/**
+Handle a Terminate Request packet and cleanly terminate the connection.
+
+@param aCode Packet code
+@param aId Packet identifier
+@param aLength Length of packet (ignored)
+@param aPacket MBuf chain containing packet (ignored)
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s Terminate Request, packet code[%d]"), __iFsmName, aCode); )
+
+ if (aCode==KPppLcpTerminateRequest)
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("Rx: TerminateRequest Id[%d]"), aId); )
+ iFsmTermination = ETrue; // Used later to bring down the FSM as opposed to restarting it.
+ iFsmTerminationCauseError = KErrDisconnected;
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ // bad event
+ break;
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ case EPppFsmClosing:
+ case EPppFsmStopping:
+ SendTerminateAck(aId);
+ break;
+ case EPppFsmReqSent:
+ case EPppFsmAckRecvd:
+ case EPppFsmAckSent:
+ SendTerminateAck(aId);
+ FsmLayerFinished(KErrCouldNotConnect);
+ SetState(EPppFsmReqSent);
+ break;
+ case EPppFsmOpened:
+ ZeroRestartCount();
+ if(iTerminateAckEnabled) // Fully RFC compliant shutdown sequence, as opposed to "Legacy" shutdown.
+ // Once "Legacy" shutdown is removed, a check for TerminateAckEnabled may
+ // be safely removed as well.
+ {
+ SendTerminateAck(aId);
+
+ // RFC1661 3.7: wait at least one restart period
+ TimerCancel();
+ TimerAfter(iTerminateAckTimeout * 1000);
+ // If iTerminateAckTimeout is zero, we proceed to terminate the FSM and close the link almost
+ // immediately. This may result in TerminateAck send being cancelled when we close the actual link.
+
+ FsmLayerDown(KErrDisconnected);
+ }
+ else // "Legacy" shutdown sequence
+ // Once "legacy" behaviour is not required any more, this section of code may be safely removed.
+ {
+ // We do not send terminate Ack.
+ FsmLayerDown();
+ FsmLayerFinished(KErrCommsLineFail);
+ // Note:
+ // KErrCommsLineFail is given a special interpreation by the NCP, which may inform Nifman to
+ // renegotiate the link, rather than terminate.
+ }
+
+ SetState(EPppFsmStopping);
+ break;
+ default:
+ break;
+ }
+ } // KPppLcpterminateRequest
+ else // KPppLcpTerminateAck
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("Rx: TerminateAck Id[%d]"), aId); )
+
+ if (iPppAbortCode!=KErrNone)
+ {
+ iPppLcp->PhaseAborted(iPppAbortCode);
+ }
+ else
+ {
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ // bad event
+ break;
+ case EPppFsmClosed:
+ case EPppFsmStopped:
+ break;
+ case EPppFsmClosing: // Terminate Request Sent
+ FsmLayerFinished(iFsmTerminationCauseError);
+ SetState(EPppFsmClosed);
+ break;
+ case EPppFsmStopping: // Terminate Ack sent
+ FsmLayerFinished(iFsmTerminationCauseError);
+ SetState(EPppFsmStopped);
+ break;
+ case EPppFsmReqSent:
+ case EPppFsmAckSent:
+ KillProtocol();
+ break;
+ case EPppFsmAckRecvd:
+ SetState(EPppFsmReqSent);
+ break;
+ case EPppFsmOpened:
+ FsmLayerDown();
+ SendConfigRequest();
+ SetState(EPppFsmReqSent);
+ break;
+ }
+ }
+ }
+ }
+
+TBool MPppFsm::ProcessEmptyConfigReq()
+/**
+Handle Config Request with no options.
+
+@return ETrue on a valid state change
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s Empty Config Request"), __iFsmName); )
+
+
+ TBool retCode = EFalse;
+
+
+ // About to drop out of opened state to need to reset things
+ // BEFORE the new request is processed.
+ if (iState==EPppFsmOpened)
+ {
+ FsmLayerDown();
+ InitialiseConfigRequest();
+ }
+
+
+ // State processing
+
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ // Bad event
+ case EPppFsmClosing:
+ case EPppFsmStopping:
+ break;
+
+ case EPppFsmClosed:
+ //SendTerminateAck(aId);
+ break;
+ case EPppFsmStopped:
+ {
+ SendInitialConfigRequest();
+ SetState(EPppFsmAckSent);
+ retCode = ETrue;
+ break;
+ }
+ case EPppFsmReqSent:
+ {
+ retCode = ETrue;
+ SetState(EPppFsmAckSent);
+ break;
+ }
+ case EPppFsmAckRecvd:
+ {
+ retCode = ETrue;
+ SetState(EPppFsmOpened);
+ FsmLayerUp();
+ break;
+ }
+ case EPppFsmAckSent:
+ {
+ retCode = ETrue;
+ break;
+ }
+ case EPppFsmOpened:
+ {
+ // This will cause empty config request to restart config negotiation
+ SendInitialConfigRequest();
+ SetState(EPppFsmAckSent);
+ retCode=ETrue;
+ break;
+ }
+ }
+ return retCode;
+ }
+
+void MPppFsm::ProcessConfig(TUint8 aCode, TUint8 aId, TInt /* aLength */, RMBufChain& aPacket)
+/**
+Handle ConfigRequest, ConfigAck, ConfigNak and ConfigReject
+
+@param aCode Packet code
+@param aId Packet identifier
+@param aLength Length of packet (ignored)
+@param aPacket MBuf chain containing packet.
+*/
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s Process Config, packet code[%d]"), __iFsmName, aCode); )
+
+ // Split the recvd packet into separate options
+ // placing each option in a queue where it can be
+ // easily parsed and manipulated in the upcall handlers.
+ RPppOptionList rcvlist; // Recvd list of options
+
+ TRAPD(err, rcvlist.SetL(aPacket));
+ if (err!=KErrNone)
+ return;
+
+ enum TCheckResult { ENop, EAck, ENak, ERej } reply = ENop;
+
+ RPppOptionList acklist; // List of Ack'd options - only valid of the following are empty
+ RPppOptionList naklist; // List of Nak'd options - only valid of the following is empty
+ RPppOptionList rejlist; // List of Rejected options
+
+ if (aCode==KPppLcpConfigRequest)
+ {
+ // About to drop out of opened state to need to reset things
+ // BEFORE the new request is processed.
+ if (iState==EPppFsmOpened)
+ {
+ FsmLayerDown();
+ InitialiseConfigRequest();
+ }
+
+ // If any duplicated RFC1661 options, then discard the packet
+ if (!FsmConfigRequestOptionsValid(rcvlist))
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM - ConfigRequest discarded due to duplicate RFC1661 options"), __iFsmName); )
+ rcvlist.Free();
+ return;
+ }
+
+ // Check options, and split into list of OK, Bad and Unknown
+ // Note - the naklist options will have been updated to
+ // contain acceptable values.
+
+ FsmCheckConfigRequest(rcvlist, acklist, naklist, rejlist);
+
+ if (!rejlist.IsEmpty())
+ {
+ reply = ERej;
+ naklist.Free();
+ acklist.Free();
+ }
+ else if (!naklist.IsEmpty())
+ {
+ reply = ENak;
+ acklist.Free();
+ }
+ else if (!acklist.IsEmpty())
+ {
+ reply = EAck;
+ FsmApplyConfigRequest(acklist);
+ }
+ else
+ {
+ // Panic - options lost by derived class!
+ }
+ }
+
+ // State processing
+
+ switch (iState)
+ {
+ case EPppFsmInitial:
+ case EPppFsmStarting:
+ // Bad event
+ case EPppFsmClosing:
+ case EPppFsmStopping:
+ break;
+
+ case EPppFsmClosed:
+ SendTerminateAck(aId);
+ break;
+
+ case EPppFsmStopped:
+ switch (aCode)
+ {
+ case KPppLcpConfigRequest:
+ SendInitialConfigRequest();
+ switch (reply)
+ {
+ case EAck:
+ SendConfigReply(acklist, KPppLcpConfigAck, aId);
+ SetState(EPppFsmAckSent);
+ break;
+ case ENak:
+ SendConfigReply(naklist, KPppLcpConfigNak, aId);
+ SetState(EPppFsmReqSent);
+ break;
+ case ERej:
+ SendConfigReply(rejlist, KPppLcpConfigReject, aId);
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ break;
+ case KPppLcpConfigAck:
+ case KPppLcpConfigNak:
+ case KPppLcpConfigReject:
+ SendTerminateAck(aId);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case EPppFsmReqSent:
+ switch (aCode)
+ {
+ case KPppLcpConfigRequest:
+ switch (reply)
+ {
+ case EAck:
+ SendConfigReply(acklist, KPppLcpConfigAck, aId);
+ SetState(EPppFsmAckSent);
+ break;
+ case ENak:
+ // RFC 1661 4.6
+ if(MaxFailureExceeded())
+ SendConfigReply(naklist, KPppLcpConfigReject, aId);
+ else
+ {
+ DecrementMaxFailure();
+ SendConfigReply(naklist, KPppLcpConfigNak, aId);
+ }
+ SetState(EPppFsmReqSent);
+ break;
+ case ERej:
+ SendConfigReply(rejlist, KPppLcpConfigReject, aId);
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ break;
+ case KPppLcpConfigAck:
+ if (FsmAckOptionsValid(rcvlist, iRequestList))
+ {
+ InitRestartCountForConfig();
+ FsmRecvConfigAck(rcvlist);
+ SetState(EPppFsmAckRecvd);
+ }
+ else
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM - ConfigAck discarded due to option mismatch with original ConfigRequest"), __iFsmName); )
+ }
+ break;
+ case KPppLcpConfigNak:
+ InitRestartCountForConfig();
+ FsmRecvConfigNak(rcvlist, iRequestList);
+ SendConfigRequestAfterNak(rcvlist);
+ break;
+ case KPppLcpConfigReject:
+ InitRestartCountForConfig();
+ FsmRecvConfigReject(rcvlist, iRequestList);
+ SendConfigRequestAfterReject(rcvlist);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case EPppFsmAckRecvd:
+ switch (aCode)
+ {
+ case KPppLcpConfigRequest:
+ switch (reply)
+ {
+ case EAck:
+ SendConfigReply(acklist, KPppLcpConfigAck, aId);
+ SetState(EPppFsmOpened);
+ FsmLayerUp();
+ break;
+ case ENak:
+ // RFC 1661 4.6
+ if(MaxFailureExceeded())
+ SendConfigReply(naklist, KPppLcpConfigReject, aId);
+ else
+ {
+ DecrementMaxFailure();
+ SendConfigReply(naklist, KPppLcpConfigNak, aId);
+ }
+ break;
+ case ERej:
+ SendConfigReply(rejlist, KPppLcpConfigReject, aId);
+ break;
+ default:
+ break;
+ }
+ break;
+ case KPppLcpConfigAck:
+ case KPppLcpConfigNak:
+ case KPppLcpConfigReject:
+ SendConfigRequest();
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case EPppFsmAckSent:
+ switch (aCode)
+ {
+ case KPppLcpConfigRequest:
+ switch (reply)
+ {
+ case EAck:
+ SendConfigReply(acklist, KPppLcpConfigAck, aId);
+ break;
+ case ENak:
+ // RFC 1661 4.6
+ if(MaxFailureExceeded())
+ SendConfigReply(naklist, KPppLcpConfigReject, aId);
+ else
+ {
+ DecrementMaxFailure();
+ SendConfigReply(naklist, KPppLcpConfigNak, aId);
+ }
+ SetState(EPppFsmReqSent);
+ break;
+ case ERej:
+ SendConfigReply(rejlist, KPppLcpConfigReject, aId);
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ break;
+ case KPppLcpConfigAck:
+ if (FsmAckOptionsValid(rcvlist, iRequestList))
+ {
+ InitRestartCountForConfig();
+ FsmRecvConfigAck(rcvlist);
+ SetState(EPppFsmOpened);
+ FsmLayerUp();
+ }
+ else
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM - ConfigAck discarded due to option mismatch with original ConfigRequest"), __iFsmName); )
+ }
+ break;
+ case KPppLcpConfigNak:
+ InitRestartCountForConfig();
+ FsmRecvConfigNak(rcvlist, iRequestList);
+ SendConfigRequestAfterNak(rcvlist);
+ break;
+ case KPppLcpConfigReject:
+ if (FsmRejectOptionsValid(rcvlist, iRequestList))
+ {
+ InitRestartCountForConfig();
+ FsmRecvConfigReject(rcvlist, iRequestList);
+ SendConfigRequestAfterReject(rcvlist);
+ }
+ else
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM - ConfigReject discarded due to option mismatch with original ConfigRequest"), __iFsmName); )
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case EPppFsmOpened:
+ // Config Reset done above
+ switch (aCode)
+ {
+ case KPppLcpConfigRequest:
+ SendConfigRequest();
+ switch (reply)
+ {
+ case EAck:
+ SendConfigReply(acklist, KPppLcpConfigAck, aId);
+ SetState(EPppFsmAckSent);
+ break;
+ case ENak:
+ SendConfigReply(naklist, KPppLcpConfigNak, aId);
+ SetState(EPppFsmReqSent);
+ break;
+ case ERej:
+ SendConfigReply(rejlist, KPppLcpConfigReject, aId);
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ break;
+ case KPppLcpConfigAck:
+ SendConfigRequest();
+ FsmRecvConfigAck(rcvlist);
+ SetState(EPppFsmReqSent);
+ break;
+ case KPppLcpConfigNak:
+ FsmRecvConfigNak(rcvlist, iRequestList);
+ SendConfigRequestAfterNak(rcvlist);
+ SetState(EPppFsmReqSent);
+ break;
+ case KPppLcpConfigReject:
+ FsmRecvConfigReject(rcvlist, iRequestList);
+ SendConfigRequestAfterReject(rcvlist);
+ SetState(EPppFsmReqSent);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ // Invalid state
+ LOG( iPppLcp->iLogger->Printf(_L("%s Invalid state %d"), __iFsmName, iState); )
+ break;
+ }
+ rcvlist.Free();
+ acklist.Free();
+ naklist.Free();
+ rejlist.Free();
+ }
+
+void MPppFsm::SendConfigRequest()
+/**
+Send the config request in iRequestList
+*/
+ {
+ if (iPppAbortCode!=KErrNone)
+ return;
+
+
+ // With Mobile IP, there is the possibility of having no options to negotiate, in which case
+ // we would send an empty ConfigRequest rather than nothing.
+
+ TBool emptyList = iRequestList.IsEmpty();
+ if (emptyList && !iPppLcp->QueryExternalIPConfiguration())
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("%s FSM Request list empty"), __iFsmName); )
+ return;
+ }
+
+ RMBufPacket pkt;
+ iRequestId &= 0xff;
+ TRAPD(err, iRequestList.CreatePacketL(pkt, iPppId, KPppLcpConfigRequest, (TUint8)iRequestId, emptyList));
+ if (err!=KErrNone)
+ {
+ //__DEBUGGER();
+ return;
+ }
+ SendFrame(pkt);
+ --iRestartCount;
+ TimerCancel();
+ TInt temp=iWaitTime;
+ if (iPppId==KPppIdIpcp && iLengthenTimers)
+ temp=KPppFsmLengthenedRequestTimeout;
+ TimerAfter(temp*1000);
+ }
+
+
+TInt MPppFsm::InitialiseConfigRequest()
+/**
+Delete any existing request list, then create a new one.
+Initialise counters for sending config requests.
+
+@return Error code
+
+@post iRequestList is initialized
+*/
+ {
+ iLastCfgReqFcs = 0;
+ iConsecCfgReq = 0;
+ iRequestId = FsmNewId();
+ InitRestartCountForConfig();
+ if (!iRequestList.IsEmpty())
+ iRequestList.Free();
+ TRAPD(err, FsmFillinConfigRequestL(iRequestList));
+ return err;
+ }
+
+void MPppFsm::SendInitialConfigRequest()
+/**
+Initialise request list and send a request if successful.
+*/
+ {
+ if (InitialiseConfigRequest()==KErrNone)
+ SendConfigRequest();
+ }
+
+void MPppFsm::SendConfigRequestAfterNak(RPppOptionList& /*aOptsList*/)
+/**
+Update the options list and send a new config request after a Nak.
+
+@param aOptList Options list (ignored)
+*/
+ {
+ iRequestId = FsmNewId();
+
+ // Calc a 32bit CRC of the request list data
+ // and compare with last recorded RequestAfterNAK CRC.
+ // If the same, then it is more likely that negotiation
+ // is not converging.
+ TPppFcs32 fcs;
+ iRequestList.Crc32(fcs);
+
+ if (fcs.Fcs()==iLastCfgReqFcs)
+ {
+ if (++iConsecCfgReq>KPppFsmNonConvergeLimit)
+ {
+ LOG( iPppLcp->iLogger->Printf(_L("NonConvergence limit reached")); )
+ FsmAbort(KErrTimedOut);
+ return;
+ }
+ }
+ else
+ {
+ iLastCfgReqFcs = fcs.Fcs();
+ iConsecCfgReq = 0;
+ }
+
+ SendConfigRequest();
+ }
+
+void MPppFsm::SendConfigRequestAfterReject(RPppOptionList& /*aOptsList*/)
+/**
+Update the options list and send a new config request after a Reject.
+
+@param aOptList Options list (ignored)
+*/
+ {
+ iRequestId = FsmNewId();
+ SendConfigRequest();
+ }
+
+void MPppFsm::SendConfigReply(RPppOptionList& aOptList, TUint8 aType, TUint8 aId)
+/**
+Reply to a config request with a set of options.
+
+@param aOptList Options list
+@param aType Packet type (Ack, Nak, Rej)
+@param aId Packet identifier
+*/
+ {
+ if (iPppAbortCode!=KErrNone)
+ return;
+
+ RMBufPacket pkt;
+ TRAPD(err, aOptList.CreatePacketL(pkt, iPppId, aType, aId, EFalse));
+ if (err!=KErrNone)
+ {
+ //__DEBUGGER();
+ return;
+ }
+ SendFrame(pkt);
+// TimerCancel();
+// TimerAfter(iWaitTime*1000);
+ }
+
+void MPppFsm::SendInitialTerminateRequest()
+/**
+Send the first Terminate Request packet to begin connection teardown.
+*/
+ {
+ iTerminateId = FsmNewId();
+ InitRestartCountForTerminate();
+ if(iRestartCount > 0)
+ {
+ SendTerminateRequest();
+ }
+ else // We are configured to send zero Terminate Requests.
+ {
+ TimerCancel();
+ TimerAfter(0); // As if we finished transmitting Terminate Requests.
+ }
+ }
+
+void MPppFsm::SendTerminateRequest()
+/**
+Send a Terminate Request packet.
+
+@pre SendInitialTerminateRequest() must have previously been called
+*/
+ {
+ RMBufPacket pkt;
+ const TUint pktLen = 4;
+ TUint8* ptr = NewPacket(pkt, pktLen);
+ if (ptr == NULL)
+ {
+ __ASSERT_DEBUG(EFalse,PppPanic(EPppPanic_PPPNoMemory));
+ return;
+ }
+ *ptr++ = KPppLcpTerminateRequest;
+ iTerminateId &= 0xff;
+ *ptr++ = (TUint8)iTerminateId;
+ BigEndian::Put16(ptr, (TUint16)pktLen);
+ pkt.Pack();
+ SendFrame(pkt);
+
+ --iRestartCount;
+ TimerCancel();
+ TInt temp=iWaitTime;
+ if (iLengthenTimers)
+ temp=KPppFsmLengthenedTerminateTimeout;
+ TimerAfter(temp*1000);
+ LOG( iPppLcp->iLogger->Printf(_L("Tx: TerminateRequest Id[%d]. Restart Count[%d]"), iTerminateId, iRestartCount); )
+ }
+
+void MPppFsm::SendTerminateAck(TUint8 aId)
+/**
+Send a Terminate Ack packet.
+
+@param aId Packet identifier
+*/
+ {
+ RMBufPacket pkt;
+ const TUint pktLen = 4;
+ TUint8* ptr = NewPacket(pkt, pktLen);
+ if (ptr == NULL)
+ {
+ __ASSERT_DEBUG(EFalse,PppPanic(EPppPanic_PPPNoMemory));
+ return;
+ }
+ *ptr++ = KPppLcpTerminateAck;
+ *ptr++ = aId;
+ BigEndian::Put16(ptr, (TUint16)pktLen);
+ pkt.Pack();
+ SendFrame(pkt);
+
+ LOG(iPppLcp->iLogger->Printf(_L("Tx: TerminateAck Id[%d]."),aId);)
+ }
+
+void MPppFsm::InitRestartCountForConfig()
+/**
+Initialize the restart count and wait time
+with values appropriate for the config phase.
+*/
+ {
+
+ // RFC 1661 4.6 Max-Configure
+ iWaitTime = iWaitTimeConfig;
+ iRestartCount = iMaxRestartConfig;
+ }
+
+void MPppFsm::InitRestartCountForTerminate()
+/**
+Initialize the restart count and wait time for
+with values appropriate for the termination phase.
+*/
+ {
+ if(iNoEvidenceOfPeer)
+ {
+ // If we've been told to terminate by our control and haven't yet heard anything from the peer then we
+ // don't attempt to send it a disconnect. This is a little unpleasant because if we've sent it a config
+ // packet it may be left waiting for us until it times out, however the more likely state is that we
+ // haven't yet completed sending the packet to it because the BCA is still waiting on its bearer to
+ // set up. Unfortunately we don't seem to have a palatable way to abort this BCA write from here.
+ LOG(iPppLcp->iLogger->Printf(_L("InitRestartCountForTerminate: no evidence of peer contact so terminating without notice"));)
+ ZeroRestartCount();
+ }
+ else
+ {
+ iWaitTime = iTerminateRequestTimeout;
+ iRestartCount = iMaxTerminateRequest;
+ }
+ }
+
+void MPppFsm::ZeroRestartCount()
+/**
+Clear the restart count.
+*/
+ {
+ iRestartCount = 0;
+ }
+
+TUint8 MPppFsm::FsmNewId()
+/**
+Generate a new nonzero packet identifier.
+
+@return Packet identifier
+*/
+ {
+ if (++iCurrentId==0)
+ ++iCurrentId;
+ return iCurrentId;
+ }
+
+void MPppFsm::SetState(TPppFsmState aState)
+/**
+Set the next state in the FSM.
+Cancels the timer when appropriate.
+
+@param aState Next state
+*/
+ {
+ LOG( iPppLcp->iLogger->DumpState(__iFsmName, iState, aState); )
+ iState = aState;
+ if (iState<EPppFsmClosing || iState==EPppFsmOpened)
+ {
+ if(iState == EPppFsmStarting)
+ {
+ iNoEvidenceOfPeer = ETrue;
+ }
+ TimerCancel();
+ }
+ }
+
+
+void MPppFsm::FsmRejectPacket(RMBufChain& aPacket, TUint aReason, TUint aPppId)
+/**
+Send a Code Reject or Protocol Reject packet.
+
+@param aPacket MBuf chain containing packet; it will be used to send the reject message.
+@param aReason Reason for rejecting (KPppLcpCodeReject or KPppLcpProtocolReject)
+@param aPppId PPP protocol ID
+*/
+ {
+ RMBufPacket pkt;
+ pkt.Assign(aPacket);
+ pkt.Unpack();
+ RMBufPktInfo* info = pkt.Info();
+
+ // This function reuses the rejected packet chain to send the reject message,
+ // so reserve some space at the beginning for the reject header.
+ TInt prep = 0;
+ if (aReason==KPppLcpCodeReject)
+ prep = 4;
+ else if (aReason==KPppLcpProtocolReject)
+ prep = 6;
+ else
+ {
+ // Unknown reject reason
+ pkt.Free();
+ return;
+ }
+
+ TRAPD(err, pkt.PrependL(prep));
+ if (err!=KErrNone)
+ {
+ pkt.Free();
+ return;
+ }
+ info->iLength += prep;
+
+ // If the frame to be sent is too large, lop off the end to make it fit.
+ __ASSERT_DEBUG(iPppLcp->MaxTransferSize() > 0, PppPanic(EPppPanic_InvalidData));
+ if (info->iLength > iPppLcp->MaxTransferSize())
+ {
+ pkt.TrimEnd(iPppLcp->MaxTransferSize());
+ info->iLength = iPppLcp->MaxTransferSize();
+ }
+
+ TUint8* ptr = pkt.First()->Ptr();
+
+ *ptr++ = TUint8(aReason); // xxx
+ *ptr++ = FsmNewId();
+ BigEndian::Put16(ptr, (TUint16)info->iLength);
+ ptr += 2;
+ if (aReason==KPppLcpProtocolReject)
+ {
+ BigEndian::Put16(ptr, (TUint16)TPppAddr::Cast((info->iDstAddr)).GetProtocol());
+ TPppAddr::Cast((info->iDstAddr)).SetProtocol(KPppIdLcp);
+ }
+
+ pkt.Pack();
+ if (aPppId == KPppIdAsIs)
+ SendFrame(pkt);
+ else
+ iPppLcp->PppLink()->Send(pkt, aPppId);
+ }
+
+void MPppFsm::ReadIniFileL()
+/**
+Reads the contents of the ppp.ini file.
+
+@leave Error code if file cannot be read
+*/
+ // Added September 1999
+ // Currently can read from ini file :-
+ // Max-Configure
+ // Max-Failure
+ // Restart Timer
+ // Enable TerminateRequest / TerminateAck
+ // Max TerminateRequest
+ // TerminateRequest timeout
+ // TerminateAck timeout
+ {
+ // Check the ini file exists and can be opened
+ CESockIniData* ini = NULL;
+ TRAPD(res,
+ if (iPppLcp->PppLinkMode() == CPppLcpConfig::EPppLinkIsServer)
+ {
+ ini = CESockIniData::NewL(PPP_SERVER_INI_FILE);
+ }
+ else
+ {
+ ini = CESockIniData::NewL(PPP_INI_FILE);
+ }
+ )
+ if(res!=KErrNone)
+ {
+ if(res==KErrNotFound)
+ {
+ // No .ini file; use default values
+ iMaxFailureConfig = KPppMaxFailureDefault;
+ iMaxRestartConfig = KPppFsmRequestRetries;
+ iWaitTimeConfig = KPppFsmRequestTimeout;
+
+
+ // Termination Phase Support.
+ // If the .ini file is missing, full support is enabled.
+
+ iTerminateRequestEnabled = ETrue;
+ iMaxTerminateRequest = KPppFsmTerminateRequestRetries;
+ iTerminateRequestTimeout = KPppFsmTerminateRequestTimeout;
+
+ iTerminateAckEnabled = ETrue;
+ iTerminateAckTimeout = KPppFsmTerminateAckTimeout;
+
+ return;
+ }
+ User::Leave(res);
+ }
+ CleanupStack::PushL(ini);
+ TInt entry;
+//
+// Max-Failure
+ // Read enable switch
+ if (ini->FindVar(LCPSECTIONNAME,PPPMAXFAILUREENTRYNAME_ENABLE, entry))
+ {
+ if (entry == 0)
+ iMaxFailureConfig = KPppMaxFailureDefault;
+ else
+ {
+ if (ini->FindVar(LCPSECTIONNAME,PPPMAXFAILUREENTRYNAME_COUNT, entry))
+ iMaxFailureConfig = entry;
+ else
+ iMaxFailureConfig = KPppMaxFailureDefault;
+ }
+ }
+ else
+ iMaxFailureConfig = KPppMaxFailureDefault;
+
+//
+// Max-Configure
+ // Read enable switch
+ if (ini->FindVar(LCPSECTIONNAME,PPPMAXRESTARTENTRYNAME_ENABLE, entry))
+ {
+ if (entry == 0)
+ iMaxRestartConfig = KPppFsmRequestRetries;
+ else
+ {
+ if (ini->FindVar(LCPSECTIONNAME,PPPMAXRESTARTENTRYNAME_COUNT, entry))
+ iMaxRestartConfig = entry;
+ else
+ iMaxRestartConfig = KPppFsmRequestRetries;
+ }
+ }
+ else
+ iMaxRestartConfig = KPppFsmRequestRetries;
+//
+// Restart Timer
+ // Read enable switch
+ if (ini->FindVar(LCPSECTIONNAME,PPPRESTARTTIMERENTRYNAME_ENABLE, entry))
+ {
+ if (entry == 0)
+ iWaitTimeConfig = KPppFsmRequestTimeout;
+ else
+ {
+ if (ini->FindVar(LCPSECTIONNAME,PPPRESTARTTIMERENTRYNAME_PERIOD, entry))
+ iWaitTimeConfig = entry;
+ else
+ iWaitTimeConfig = KPppFsmRequestTimeout;
+ }
+ }
+ else
+ iWaitTimeConfig = KPppFsmRequestTimeout;
+
+
+ //
+ // Support PPP Termination Sequence Configurability, required for
+ // CDMA support.
+ //
+ if(ini->FindVar(LCPSECTIONNAME, TERMINATE_REQUEST_ENABLE, entry))
+ {
+ if(0 == entry)
+ {
+ iTerminateRequestEnabled = EFalse;
+ }
+ }
+
+ // Max Terminate Requests to be sent.
+ if(iTerminateRequestEnabled)
+ {
+ if(ini->FindVar(LCPSECTIONNAME, MAX_TERMINATE_REQUEST_ENABLE, entry))
+ {
+ if(0 != entry)
+ {
+ if (ini->FindVar(LCPSECTIONNAME, MAX_TERMINATE_REQUEST_COUNT, entry))
+ {
+ iMaxTerminateRequest = entry;
+ }
+ }
+ }
+
+ // Normal Terminate Request timeout
+ if(ini->FindVar(LCPSECTIONNAME, TERMINATE_REQUEST_TIMER_ENABLE, entry))
+ {
+ if(0 != entry)
+ {
+ if (ini->FindVar(LCPSECTIONNAME, TERMINATE_REQUEST_TIMER_PERIOD, entry))
+ {
+ iTerminateRequestTimeout = entry;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Special Case: Support legacy shutdown behaviour: send only one Terminate Request.
+ // To disable sending TerminatRequest entirely, Enable TerminateRequest, and set MaxTerminateRequest to 0.
+ // When support for legacy shutdown is not necessary, this code can be safely removed.
+ iMaxTerminateRequest = 1;
+ }
+
+ //
+ // Terminate ACK configurability
+ //
+ // Is sending a configure ACK enabled?
+ if(ini->FindVar(LCPSECTIONNAME, TERMINATE_ACK_ENABLE, entry))
+ {
+ if(0 == entry)
+ {
+ iTerminateAckEnabled = EFalse;
+ }
+ }
+
+ // Read Terminate ACK settings only if it is enabled
+ if(iTerminateAckEnabled)
+ {
+ if(ini->FindVar(LCPSECTIONNAME, TERMINATE_ACK_TIMER_ENABLE, entry))
+ {
+ if(0 != entry)
+ {
+ if(ini->FindVar(LCPSECTIONNAME, TERMINATE_ACK_TIMER_PERIOD, entry))
+ {
+ iTerminateAckTimeout = entry;
+ }
+ }
+ }
+ }
+
+ // Setting that controls doubling of timeout value on restart timer
+ if (ini->FindVar(LCPSECTIONNAME, PPP_RESTARTTIMER_ENTRYNAME_MODE, entry))
+ {
+ if (entry == 1)
+ {
+ iWaitTimeNoIncrease = ETrue;
+ }
+ }
+
+
+ CleanupStack::PopAndDestroy();
+ }
+
+TUint8* MPppFsm::NewPacket(RMBufPacket& aPkt, TUint aLength)
+/**
+Allocate a new packet buffer and info header. The caller must fill in the
+the packet and call its Pack() method before sending.
+
+@param aPkt reference to a packet
+@param aLength length of the buffer
+@return pointer to the beginning of the first packet in the chain or NULL on error
+
+@see RPppOptionList::CreatePacketL
+*/
+ {
+ TRAPD(err, aPkt.AllocL(aLength));
+ if (err != KErrNone)
+ {
+ return NULL;
+ }
+ RMBufPktInfo* info=NULL;
+ TRAP(err,info = aPkt.NewInfoL());
+ if (err != KErrNone)
+ {
+ aPkt.Free();
+ return NULL;
+ }
+ info->iLength = aLength;
+ TPppAddr::Cast((info->iDstAddr)).SetProtocol(iPppId);
+ return aPkt.First()->Ptr();
+ }
+
+
+TBool MPppFsm::FsmAckOptionsValid(RPppOptionList& /*aList*/, RPppOptionList& /*aRequestList*/)
+/**
+Perform validation checking on the option list of a ConfigAck or ConfigReject.
+
+@param aList option list of incoming ConfigAck or ConfigReject
+@return ETrue if options valid, else EFalse. EFalse return causes packet to be discarded.
+*/
+ {
+ return ETrue;
+ }
+
+TBool MPppFsm::FsmRejectOptionsValid(RPppOptionList& /*aList*/, RPppOptionList& /*aRequestList*/)
+/**
+Perform validation checking on the option list of a ConfigAck or ConfigReject.
+
+@param aList option list of incoming ConfigAck or ConfigReject
+@return ETrue if options valid, else EFalse. EFalse return causes packet to be discarded.
+*/
+ {
+ return ETrue;
+ }
+TBool MPppFsm::FsmConfigRequestOptionsValid(RPppOptionList& /*aList*/)
+/**
+Perform validation checking on the option list of a ConfigRequest.
+
+@param aList option list of incoming ConfigRequest
+@return ETrue if options valid, else EFalse. EFalse return causes packet to be discarded.
+*/
+ {
+ return ETrue;
+ }
+