--- /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 <in_sock.h>
+#include <es_sock.h>
+#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<TUint16>(tempSecs.Int());
+
+ if(CMessageSender::GetFamilyType() == KAfInet)
+ {
+ TUint8* elapsedOptionBody = const_cast<TUint8*>(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<TInt>(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;
+ }
+