diff -r 000000000000 -r af10295192d8 tcpiputils/dhcp/src/MsgSender.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tcpiputils/dhcp/src/MsgSender.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,220 @@ +// Copyright (c) 2003-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: +// Implements the Message sender that just +// resends messages until max retry or max count has been reached +// max retry and max count are constants +// +// + +/** + @file MsgSender.cpp + @internalTechnology +*/ + +#include "DHCP_Std.h" +#include "DHCPServer.h" +#include "MsgSender.h" +#include +#include +#include "DHCPAuthentication.h" +#include "DHCPIP4StateMachine.h" +CMessageSender::~CMessageSender() +/** + * Destructor for message sender + * + * @internalTechnology + */ + { + Cancel(); + delete iMsg; + delete iExpireTimer; + } + +void CMessageSender::DoCancel() +/** + * Specific cancel implementation for message sender + * + * @internalTechnology + */ + { + __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::DoCancel"))); + iSocket.CancelSend(); + } + +void CMessageSender::Cancel() +/** + * Specific cancel implementation overriding CActive's implemention + * + * @internalTechnology + */ + { + if (iExpireTimer) + { + iExpireTimer->Cancel(); + } + CActive::Cancel(); + if (IsAdded()) + { + Deque(); + } + } + +void CMessageSender::TimerExpired() +/** + * Ticking timer expired so resend the message + * + * @internalTechnology + */ + { + iRetryCount++; + iRetryDuration += iMicroSecs.Int(); + + TTime now; + TTimeIntervalSeconds tempSecs; + now.HomeTime(); + (void)now.SecondsFrom(iTaskStartedAtCopy, tempSecs); + TUint16 time =static_cast(tempSecs.Int()); + + if(CMessageSender::GetFamilyType() == KAfInet) + { + TUint8* elapsedOptionBody = const_cast(iMsg->Des().Ptr()) + DHCPv4::KLengthUptoSecs; + TBigEndian::SetValue( elapsedOptionBody, DHCPv4::KSecsElapsedLength, time ); + } + + if ( SendingContinues() ) + { + __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::TimerExpired - SendTo"))); + iSocket.SendTo(*iMsg, iAddr, 0, iStatus); + SetActive(); + } + else + { + __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::TimerExpired - RunError"))); + RunError(KErrTimedOut); + } + } + +void CMessageSender::SendL(TInetAddr& aAddr, const TDesC8& aMsg, TTimeIntervalMicroSeconds aSecs, TInt aRetryCount) +/** + * Copy message and send the first time + * + * @internalTechnology + */ + { + iMaxRetryCount = aRetryCount; + iRetryCount = -1; //the very first send doesn't count as a retry + iRetryDuration = 0; + iAddr = aAddr; + if (!iMsg || iMsg->Des().MaxLength() < aMsg.Length()) + { + delete iMsg; + iMsg = NULL; + iMsg = HBufC8::NewL(aMsg.Length()); + } + iMsg->Des().Copy(aMsg); + ASSERT(!IsAdded()); + CActiveScheduler::Add(this); + + iMicroSecs = aSecs.Int64(); + if ( CalculateDelay() ) + { + StartTimerL(); + } + else + { + TimerExpired(); + } + } + +void CMessageSender::StartTimerL() + { + if (!iExpireTimer) + { + iExpireTimer = CExpireTimer::NewL(); + } + iExpireTimer->After(iMicroSecs, *this); + } + +TBool CMessageSender::SendingContinues() const + { + + if(iRetryCount == iMaxRetryCount /*DHCPv4::KReqMaxRetry*/) + { + return EFalse; + } +#ifdef _DEBUG + TTimeIntervalMicroSeconds32 msec = KWaitForResponseTime * KMicrosecondsInSecs; + if (CDHCPServer::DebugFlags() & KDHCP_SetShortRetryTimeOut) + { + msec = KDHCP_ShortRetryTimeOut * KMicrosecondsInSecs; + } + + return iMicroSecs.Int()<=msec.Int(); +#else + return iMicroSecs.Int()<=static_cast(KWaitForResponseTime * KMicrosecondsInSecs); +#endif + } + +TBool CMessageSender::CalculateDelay() + { + if ( iRetryCount > -1 ) + {// exponential backoff algorithm + //iMicroSecs = iMicroSecs.Int()*2; + iMicroSecs = iMicroSecs.Int() * 2; + } + return iRetryCount > -1; + } + +void CMessageSender::RunL() +/** + * RunL called when the message has been sent. It checks the retransmition conditions + * and either ends with timeout or re-sets the timer accordingly. + * + * @internalTechnology + */ + { + __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::RunL - %d"), iStatus.Int())); + if ( !iMMSListener || iStatus.Int() == KErrNone + || iMMSListener->MSReportError(iStatus.Int()) == KErrNone ) + { + CalculateDelay(); + StartTimerL(); + } + else + { + User::Leave(iStatus.Int()); + } + } + +TInt CMessageSender::RunError(TInt aError) +/** + * RunError performs some cleanup after RunL leaves + * + * @internalTechnology + */ + { + if (iMMSListener) + { + if ( (aError = iMMSListener->MSReportError(aError)) == KErrNone ) + {//continue, no check for max values we assume that the listener knows what + //it's doing + ASSERT( iExpireTimer ); + ++iRetryCount; + CalculateDelay(); + iExpireTimer->After(iMicroSecs, *this); + } + } + return KErrNone; + } +