tcpiputils/dhcp/src/MsgSender.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the Message sender that just
       
    15 // resends messages until  max retry or max count has been reached
       
    16 // max retry and max count are constants
       
    17 // 
       
    18 //
       
    19 
       
    20 /**
       
    21  @file MsgSender.cpp
       
    22  @internalTechnology
       
    23 */
       
    24 
       
    25 #include "DHCP_Std.h"
       
    26 #include "DHCPServer.h"
       
    27 #include "MsgSender.h"
       
    28 #include <in_sock.h>
       
    29 #include <es_sock.h>
       
    30 #include "DHCPAuthentication.h"
       
    31 #include "DHCPIP4StateMachine.h"
       
    32 CMessageSender::~CMessageSender()
       
    33 /**
       
    34   * Destructor for message sender
       
    35   *
       
    36   * @internalTechnology
       
    37   */
       
    38 	{
       
    39 	Cancel();
       
    40 	delete iMsg;
       
    41 	delete iExpireTimer;
       
    42 	}
       
    43 
       
    44 void CMessageSender::DoCancel()
       
    45 /**
       
    46   * Specific cancel implementation for message sender
       
    47   *
       
    48   * @internalTechnology
       
    49   */
       
    50 	{
       
    51 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::DoCancel")));
       
    52 	iSocket.CancelSend();
       
    53 	}
       
    54 
       
    55 void CMessageSender::Cancel()
       
    56 /**
       
    57   * Specific cancel implementation overriding CActive's implemention
       
    58   *
       
    59   * @internalTechnology
       
    60   */
       
    61 	{
       
    62 	if (iExpireTimer)
       
    63 		{
       
    64 		iExpireTimer->Cancel();
       
    65 		}
       
    66 	CActive::Cancel();
       
    67 	if (IsAdded())
       
    68 		{
       
    69 		Deque();
       
    70 		}
       
    71 	}
       
    72 
       
    73 void CMessageSender::TimerExpired()
       
    74 /**
       
    75   * Ticking timer expired so resend the message
       
    76   *
       
    77   * @internalTechnology
       
    78   */
       
    79 	{
       
    80     iRetryCount++;
       
    81     iRetryDuration += iMicroSecs.Int();
       
    82 	
       
    83 	TTime now;
       
    84 	TTimeIntervalSeconds tempSecs;
       
    85 	now.HomeTime(); 
       
    86 	(void)now.SecondsFrom(iTaskStartedAtCopy, tempSecs);
       
    87 	TUint16 time =static_cast<TUint16>(tempSecs.Int());
       
    88 
       
    89 	if(CMessageSender::GetFamilyType() == KAfInet)
       
    90 		{
       
    91 		TUint8* elapsedOptionBody = const_cast<TUint8*>(iMsg->Des().Ptr()) + DHCPv4::KLengthUptoSecs;
       
    92 		TBigEndian::SetValue( elapsedOptionBody, DHCPv4::KSecsElapsedLength, time );
       
    93 		}
       
    94 		
       
    95     if ( SendingContinues() )
       
    96         {
       
    97 		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::TimerExpired - SendTo")));
       
    98     	iSocket.SendTo(*iMsg, iAddr, 0, iStatus);
       
    99 	    SetActive();
       
   100         }
       
   101     else
       
   102         {
       
   103 		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::TimerExpired - RunError")));
       
   104         RunError(KErrTimedOut);
       
   105         }
       
   106 	}
       
   107 
       
   108 void CMessageSender::SendL(TInetAddr& aAddr, const TDesC8& aMsg, TTimeIntervalMicroSeconds aSecs, TInt aRetryCount)
       
   109 /**
       
   110   * Copy message and send the first time
       
   111   *
       
   112   * @internalTechnology
       
   113   */
       
   114 	{
       
   115 	iMaxRetryCount = aRetryCount;
       
   116    iRetryCount = -1; //the very first send doesn't count as a retry
       
   117    iRetryDuration = 0;
       
   118 	iAddr = aAddr;
       
   119 	if (!iMsg || iMsg->Des().MaxLength() < aMsg.Length())
       
   120 		{
       
   121 		delete iMsg;
       
   122 		iMsg = NULL;
       
   123 		iMsg = HBufC8::NewL(aMsg.Length());
       
   124 		}
       
   125 	iMsg->Des().Copy(aMsg);
       
   126 	ASSERT(!IsAdded());
       
   127 	CActiveScheduler::Add(this);
       
   128 
       
   129    	iMicroSecs = aSecs.Int64();
       
   130    if ( CalculateDelay() )
       
   131       {
       
   132       StartTimerL();
       
   133       }
       
   134    else
       
   135       {
       
   136       TimerExpired();
       
   137       }
       
   138 	}
       
   139 
       
   140 void CMessageSender::StartTimerL()
       
   141    {
       
   142 	if (!iExpireTimer)
       
   143 		{
       
   144 		iExpireTimer = CExpireTimer::NewL();
       
   145 		}
       
   146 	iExpireTimer->After(iMicroSecs, *this);
       
   147    }
       
   148 
       
   149 TBool CMessageSender::SendingContinues() const
       
   150    {
       
   151    
       
   152    if(iRetryCount == iMaxRetryCount /*DHCPv4::KReqMaxRetry*/)
       
   153    	{
       
   154    	return EFalse;
       
   155    	}
       
   156 #ifdef _DEBUG
       
   157    TTimeIntervalMicroSeconds32 msec = KWaitForResponseTime * KMicrosecondsInSecs;
       
   158    if (CDHCPServer::DebugFlags() & KDHCP_SetShortRetryTimeOut)
       
   159       {
       
   160       msec = KDHCP_ShortRetryTimeOut * KMicrosecondsInSecs;
       
   161       }
       
   162 
       
   163    return iMicroSecs.Int()<=msec.Int();
       
   164 #else
       
   165    return iMicroSecs.Int()<=static_cast<TInt>(KWaitForResponseTime * KMicrosecondsInSecs);
       
   166 #endif
       
   167    }
       
   168 
       
   169 TBool CMessageSender::CalculateDelay()
       
   170    {
       
   171    if ( iRetryCount > -1 )
       
   172       {// exponential backoff algorithm
       
   173 	   //iMicroSecs = iMicroSecs.Int()*2;	
       
   174 	   	iMicroSecs = iMicroSecs.Int() * 2;
       
   175       }
       
   176     return iRetryCount > -1;
       
   177    }
       
   178 
       
   179 void CMessageSender::RunL()
       
   180 /**
       
   181   * RunL called when the message has been sent. It checks the retransmition conditions
       
   182   * and either ends with timeout or re-sets the timer accordingly.
       
   183   *
       
   184   * @internalTechnology
       
   185   */
       
   186 	{
       
   187 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CMessageSender::RunL - %d"), iStatus.Int()));
       
   188 	if ( !iMMSListener || iStatus.Int() == KErrNone 
       
   189 			|| iMMSListener->MSReportError(iStatus.Int()) == KErrNone )
       
   190 		{
       
   191         CalculateDelay();
       
   192         StartTimerL();
       
   193 		}
       
   194 	else
       
   195 	    {
       
   196 	    User::Leave(iStatus.Int());    
       
   197 	    }
       
   198 	}
       
   199 
       
   200 TInt CMessageSender::RunError(TInt aError)
       
   201 /**
       
   202   * RunError performs some cleanup after RunL leaves
       
   203   *
       
   204   * @internalTechnology
       
   205   */
       
   206 	{
       
   207 	if (iMMSListener)
       
   208 		{
       
   209 		if ( (aError = iMMSListener->MSReportError(aError)) == KErrNone )
       
   210          {//continue, no check for max values we assume that the listener knows what
       
   211          //it's doing
       
   212          ASSERT( iExpireTimer );
       
   213          ++iRetryCount;
       
   214          CalculateDelay();
       
   215 			iExpireTimer->After(iMicroSecs, *this);
       
   216          }
       
   217 		}
       
   218 	return KErrNone;
       
   219 	}
       
   220