vpnengine/ikev2lib/src/ikev2messagesendqueue.cpp
changeset 0 33413c0669b9
child 3 2df28d7a2299
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/ikev2messagesendqueue.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,236 @@
+/*
+* Copyright (c) 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:  IKEv2 IKE message send que.
+*
+*/
+
+#include "ikev2messagesendqueue.h"
+#include "ikemsgheader.h"
+#include "ikedebug.h"
+
+_LIT8(KKeepaliveData, 0xff);
+
+CIkev2MessageSendQueue* CIkev2MessageSendQueue::NewL(MIkeDataInterface& aDataInterface,
+                                                     const TInetAddr& aDestinationAddress,
+                                                     TUint8 aDscp,
+                                                     TUint aNatKeepAliveInterval,
+                                                     MIkeDebug& aDebug)
+    {
+    CIkev2MessageSendQueue* self = new (ELeave) CIkev2MessageSendQueue(aDataInterface,
+                                                                       aDestinationAddress,
+                                                                       aDscp,
+                                                                       aNatKeepAliveInterval,
+                                                                       aDebug);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    
+    return self;
+    }
+
+
+CIkev2MessageSendQueue::CIkev2MessageSendQueue(MIkeDataInterface& aDataInterface,
+                                               const TInetAddr& aDestinationAddress,
+                                               TUint8 aDscp,
+                                               TUint aNatKeepAliveInterval,
+                                               MIkeDebug& aDebug)
+:CActive(EPriorityStandard), 
+ iDataInterface(aDataInterface), 
+ iNatKeepAliveInterval(aNatKeepAliveInterval),
+ iDestinationAddress(aDestinationAddress),
+ iDscp(aDscp),
+ iDebug(aDebug)
+    {
+    CActiveScheduler::Add(this);
+    
+    if (iNatKeepAliveInterval == 0)
+        {
+        iNatKeepAliveInterval = 120;
+        }
+    }
+
+
+void CIkev2MessageSendQueue::ConstructL()
+    {
+    iSender = CIkev2Sender::NewL( iDataInterface,
+                                  *this);        
+    User::LeaveIfError(iNatKeepaliveTimer.CreateLocal());
+    }
+
+
+CIkev2MessageSendQueue::~CIkev2MessageSendQueue()
+    {
+    Cancel();
+    iNatKeepaliveTimer.Close();
+    iSasBehindNat.Close();
+    delete iSender;
+    iIkeMsgSendBuffer.Reset();
+    iIkeMsgSendBuffer.Close();
+    }
+
+void CIkev2MessageSendQueue::SendIkeMessageL(const TPtrC8 aIkeMsg, 
+                                             TBool aFloatedPort)
+    {        
+    Cancel();
+    if (!iSender->IsActive())
+        {        
+        iIkeMsgInSending.Set(aIkeMsg);
+        TUint port = (aFloatedPort) ? FLOATED_IKE_PORT : IKE_PORT;
+
+#ifdef _DEBUG
+        TBuf<80> destAddr;
+        iDestinationAddress.Output(destAddr);
+        DEBUG_LOG3(_L("No sending active. Message sent immediately to %S:%d DSCP=%d."), &destAddr, port, iDscp);
+#endif //_DEBUG        
+        iDestinationAddress.SetPort(port);
+        iSender->SendIkeMsg(port, iDestinationAddress, iDscp, iIkeMsgInSending);        
+        }
+    else
+        {
+        DEBUG_LOG(_L("Sending in progress, message added to send queue."));
+        TIkeMsgWaitQueueObject waitObject = { aIkeMsg, aFloatedPort };
+        User::LeaveIfError(iIkeMsgSendBuffer.Append(waitObject));
+        }
+    }
+
+
+void CIkev2MessageSendQueue::CancelSend(const TPtrC8& aIkeMsg)
+    {
+    DEBUG_LOG(_L("Sending of one datagram canceled."));
+    if (aIkeMsg.Ptr() == iIkeMsgInSending.Ptr())
+        {
+        __ASSERT_DEBUG(iSender->IsActive(), User::Invariant());
+        //The NAT keepalive timer should not be active, because sending
+        //is in progress.
+        __ASSERT_DEBUG(!IsActive(), User::Invariant()); 
+        iSender->Cancel();
+        iIkeMsgInSending.Set(NULL, 0);
+        // Send next message from queue.    
+        SendIkeMsgCompleted( KErrCancel );
+        }
+    else
+        {        
+        for (TUint i = 0; i < iIkeMsgSendBuffer.Count(); ++i)
+            {
+            if (iIkeMsgSendBuffer[i].iIkeMsg.Ptr() == aIkeMsg.Ptr())
+                {
+                iIkeMsgSendBuffer.Remove(i);
+                break;
+                }            
+            }        
+        }              
+    }
+
+void CIkev2MessageSendQueue::SendIkeMsgCompleted( TInt /*aStatus*/ )
+    {
+    DEBUG_LOG(_L("Ike message send complete."));
+    iIkeMsgInSending.Set(NULL, 0);
+    
+    if (iIkeMsgSendBuffer.Count() > 0)
+        {
+        TIkeMsgWaitQueueObject& waitObject = iIkeMsgSendBuffer[0];
+        TUint port = (waitObject.iFloatedPort) ? FLOATED_IKE_PORT : 500;
+        iSender->SendIkeMsg(port, iDestinationAddress, iDscp, waitObject.iIkeMsg);
+        iIkeMsgSendBuffer.Remove(0);
+        iIkeMsgInSending.Set(waitObject.iIkeMsg);
+        }
+    else if (iSasBehindNat.Count() > 0 && iNatKeepAliveInterval > 0)
+        {
+        ArmKeepaliveTimer();
+        }
+    }
+
+
+void CIkev2MessageSendQueue::CancelAll()
+    {
+    iSender->Cancel();
+    iIkeMsgSendBuffer.Reset();
+    }
+
+
+void CIkev2MessageSendQueue::NewSaBehindNatL(TUint aSaId)
+    {
+    DEBUG_LOG1(_L("CIkev2MessageSendQueue::NewSaBehindNatL: SaId=%d"), aSaId);
+    __ASSERT_DEBUG(iSasBehindNat.Find(aSaId) == KErrNotFound, User::Invariant());
+    User::LeaveIfError(iSasBehindNat.Append(aSaId));    
+    if (!iSender->IsActive() && iNatKeepAliveInterval > 0)
+        {
+        //No sending acticve arm the nat keepalive timer.
+        ArmKeepaliveTimer();
+        }
+    }
+
+
+void CIkev2MessageSendQueue::SaBehindNatDeleted(TUint aSaId)
+    {
+    DEBUG_LOG1(_L("CIkev2MessageSendQueue::SaBehindNatDeleted: SaId=%d"), aSaId);
+    TInt index = iSasBehindNat.Find(aSaId);
+    __ASSERT_DEBUG(index >= 0, User::Invariant());
+    iSasBehindNat.Remove(index);   
+    if (iSasBehindNat.Count() == 0)
+        {
+        //Cancel keepalive timer
+        Cancel();
+        }
+    }
+
+void CIkev2MessageSendQueue::RunL()
+    {
+    //Send the NAT keepalive
+    
+    __ASSERT_DEBUG(!iSender->IsActive(), User::Invariant());
+    __ASSERT_DEBUG(iSasBehindNat.Count() > 0 && iNatKeepAliveInterval > 0, User::Invariant());
+    
+    if (iRemainingTime == 0)
+        {
+        DEBUG_LOG(_L("Sending NAT keepalive"));
+        iSender->SendIkeMsg(FLOATED_IKE_PORT, iDestinationAddress, iDscp, KKeepaliveData);
+        }
+    else if (iRemainingTime > KMaxTInt/1000000)
+        {
+        iRemainingTime -= KMaxTInt/1000000;
+        iNatKeepaliveTimer.After(iStatus, KMaxTInt);
+        SetActive();
+        }
+    else
+        {        
+        iNatKeepaliveTimer.After(iStatus, iRemainingTime*1000000);
+        iRemainingTime = 0;
+        SetActive();
+        }
+    }
+
+void CIkev2MessageSendQueue::DoCancel()
+    {    
+    iNatKeepaliveTimer.Cancel();
+    iRemainingTime = 0;
+    DEBUG_LOG(_L("Keepalive timer canceled"));
+    }
+
+void CIkev2MessageSendQueue::ArmKeepaliveTimer()
+    {
+    DEBUG_LOG(_L("CIkev2MessageSendQueue::ArmKeepaliveTimer"));    
+    //Arm NAT keepalive timer.
+    if (iNatKeepAliveInterval > KMaxTInt/1000000 ) 
+        {
+        iRemainingTime = iNatKeepAliveInterval - KMaxTInt/1000000;
+        iNatKeepaliveTimer.After(iStatus, KMaxTInt);
+        }
+    else
+        {
+        iRemainingTime = 0;
+        iNatKeepaliveTimer.After(iStatus, iNatKeepAliveInterval * 1000000);
+        }        
+    SetActive();    
+    }