tcpiputils/dhcp/src/MsgSender.cpp
changeset 0 af10295192d8
--- /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;
+	}
+