--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/zeroconf/server/src/csendmessagequeue.cpp Thu Jun 24 19:09:47 2010 +0530
@@ -0,0 +1,338 @@
+// Copyright (c) 2008-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:
+// csendmessagequeue.cpp
+//
+//
+/**
+@file
+@internalTechnology
+*/
+
+#include "f32file.h"
+
+#include "cmessagehandler.h"
+#include "csendmessagequeue.h"
+__FLOG_STMT(_LIT8(KComponent,"MDNSServer");)
+/**
+Two phase constructor
+@param aDnsMessage Dns message to be sent
+@param aUnicast True if it is a unicast response
+@param aAddr address to which the packet to be send
+@return CSendMessageData object
+*/
+CSendMessageData* CSendMessageData::NewL(CDnsMessage* aDnsMessage, TBool aUnicast,TSockAddr aAddr,MMessageHandler& aCallback)
+ {
+ CSendMessageData* self = new(ELeave)CSendMessageData(aDnsMessage,aUnicast,aAddr,aCallback);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+Constant function which returns the reference to the Dns message object it wraps
+@return constant reference to dnsmessage object
+*/
+const CDnsMessage& CSendMessageData::GetDnsMessage()const
+ {
+ __FLOG(_L8("CSendMessageData::GetDnsMessage - Exit"));
+ return const_cast<CDnsMessage&> (*iMessage);
+ }
+
+/**
+Constant function which returns the address of the data to be sent
+@return Constant reference to the address
+*/
+const TSockAddr& CSendMessageData::GetSockAddress()const
+ {
+ __FLOG(_L8("CSendMessageData::GetSockAddress - Exit"));
+ return iSockAddr;
+ }
+
+/**
+Constant function which returns true if the message is unicast
+@return True if message is unicast
+*/
+const TBool& CSendMessageData::IsUnicast()const
+ {
+ __FLOG(_L8("CSendMessageData::IsUnicast - Exit"));
+ return iUnicast;
+ }
+/**
+Destructor
+*/
+CSendMessageData::~CSendMessageData()
+ {
+ __FLOG(_L8("CSendMessageData::~CSendMessageData - Entry"));
+ delete iMessage;
+ __FLOG(_L8("CSendMessageData::~CSendMessageData - Exit"));
+ __FLOG_CLOSE;
+ }
+
+/**
+Two phase constructor
+@param aDnsMessage DnsMessage to be send
+*/
+void CSendMessageData::ConstructL()
+ {
+ __FLOG_OPEN(KMDNSSubsystem, KComponent);
+ }
+
+/**
+Constructor
+@param aUnicast True if it is a unicast response
+@param aAddr Address to which the data to be sent
+*/
+CSendMessageData::CSendMessageData(CDnsMessage* aDnsMessage,TBool aUnicast,TSockAddr aAddr,MMessageHandler& aCallback):iMessage(aDnsMessage),iUnicast(aUnicast),iSockAddr(aAddr),iCallback(aCallback)
+ {
+
+ }
+
+MMessageHandler& CSendMessageData::Callback()
+ {
+ __FLOG(_L8("CSendMessageData::Callback - Exit"));
+ return iCallback;
+ }
+/**
+Two phase Constructor
+@param aSocket reference to the RSocket
+*/
+CSendMessageQueue* CSendMessageQueue::NewL(RSocket& aSocket)
+ {
+ CSendMessageQueue* self = new (ELeave)CSendMessageQueue();
+ CleanupStack::PushL(self);
+ self->ConstructL(aSocket);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+Constructor
+*/
+CSendMessageQueue::CSendMessageQueue():CTimer(EPriorityStandard)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+/**
+Function derived from MSocketHandler Observer.
+This method will be called on succesfull sending of the packet.
+*/
+void CSendMessageQueue::OnCompletionL(TDesC8& /*aData*/, const TSockAddr& /*aAddr*/, TInt /*aLength*/)
+ {
+ __FLOG(_L8("CSendMessageQueue::OnCompletionL - Entry"));
+ if(iSendMessageData)
+ {
+ iIsSocketActive = EFalse;
+ iSendMessageData->Callback().OnPacketSendL(KErrNone);
+ }
+ delete iSendMessageData;
+ iSendMessageData = NULL;
+ if(iMessageQueue.Count() > 0 && !IsActive() )
+ {
+ StartTransmit();
+ }
+ __FLOG(_L8("CSendMessageQueue::OnCompletionL - Exit"));
+ }
+
+/*
+Function derived from MSocketHandler Observer.
+This method will be called on error in sending the packet.
+*/
+void CSendMessageQueue::OnError(TInt aError)
+ {
+ __FLOG(_L8("CSendMessageQueue::OnError - Entry"));
+ if(iSendMessageData)
+ {
+ iSendMessageData->Callback().OnPacketSendL(aError);
+ }
+ __FLOG(_L8("CSendMessageQueue::OnError - Exit"));
+ }
+
+/**
+Destructor
+*/
+CSendMessageQueue::~CSendMessageQueue()
+ {
+ __FLOG(_L8("CSendMessageQueue::~CSendMessageQueue - Entry"));
+ delete iSendSocket;
+ delete iSendMessageData;
+ iMessageQueue.ResetAndDestroy();
+ iMessageQueue.Close();
+ iOutput.Close();
+ __FLOG(_L8("CSendMessageQueue::~CSendMessageQueue - Exit"));
+ __FLOG_CLOSE;
+ }
+
+/**
+Two phase constructor
+@param refernce to RSocket
+*/
+void CSendMessageQueue::ConstructL(RSocket& aSocket)
+ {
+ __FLOG(_L8("CSendMessageQueue::ConstructL - Entry"));
+ iSendSocket = CSocketHandler::NewL(aSocket, *this, ESocketSend);
+ CTimer::ConstructL();
+ iIsSocketActive = EFalse;
+ __FLOG(_L8("CSendMessageQueue::ConstructL - Exit"));
+ }
+
+/**
+Derived from CActive
+*/
+void CSendMessageQueue::RunL()
+ {
+ __FLOG(_L8("CSendMessageQueue::RunL - Entry"));
+ if (MessageReady())
+ {
+ iSendMessageData = NextDnsMessageL();
+ CleanupStack::PushL(iSendMessageData);
+ const CDnsMessage& dnsMessage = iSendMessageData->GetDnsMessage();
+ // close the previously allocated memory.
+ iOutput.Close();
+ //composes the message from the Dnsmessage object .
+ CDnsMessageComposerParser* comPos = CDnsMessageComposerParser::NewL();
+ CleanupStack::PushL(comPos);
+ comPos->CreateMessageL(iOutput, iSendMessageData->GetDnsMessage());
+ TSocketHandlerParams param(ESocketSendTo,&iOutput,&(iSendMessageData->GetSockAddress()));
+ iSendSocket->Activate(param);
+ iIsSocketActive = ETrue;
+ CleanupStack::PopAndDestroy();//comPos
+ CleanupStack::Pop();
+ }
+ __FLOG(_L8("CSendMessageQueue::RunL - Exit"));
+ }
+/*
+ * Nothing to do.
+ */
+void CSendMessageQueue::DoCancel()
+ {
+ __FLOG(_L8("CSendMessageQueue::DoCancel - Exit"));
+ }
+
+void CSendMessageQueue::QueueDnsMessageL(const CSendMessageData& aMessageData)
+ {
+ __FLOG(_L8("CSendMessageQueue::QueueDnsMessageL - Entry"));
+ if (aMessageData.IsUnicast())
+ {
+ // Unicast replies are to be given higher priority .
+ // Insert the unicast response in the queue.
+ TInt count(iMessageQueue.Count());
+ TInt index(0);
+ for (; index < count; ++index)
+ {
+ if (!iMessageQueue[index]->IsUnicast())
+ {
+ break;
+ }
+ }
+ iMessageQueue.InsertL(&aMessageData, index);
+
+ iNextTransmit.HomeTime();
+ Cancel();
+ }
+ else
+ {
+ // Queue the packet
+ iMessageQueue.AppendL(&aMessageData);
+ }
+
+ // kick the transmit limiter, so we're sure the message will be sent
+ if(!iIsSocketActive)
+ {
+ NextTransmitTime(iNextTransmit);
+ }
+ __FLOG(_L8("CSendMessageQueue::QueueDnsMessageL - Exit"));
+ }
+
+void CSendMessageQueue::NextTransmitTime(TTime aTime)
+ {
+ __FLOG(_L8("CSendMessageQueue::NextTransmitTime - Entry"));
+ // if we aren't already active, set the next TX time
+ if (!IsActive())
+ {
+ TTime now;
+ now.HomeTime();
+
+ if (aTime > now)
+ {
+ At(aTime);
+ }
+ else
+ {
+ StartTransmit();
+ }
+ }
+ __FLOG(_L8("CSendMessageQueue::NextTransmitTime - Exit"));
+ }
+
+void CSendMessageQueue::StartTransmit()
+ {
+ __FLOG(_L8("CSendMessageQueue::StartTransmit - Entry"));
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status,KErrNone);
+ __FLOG(_L8("CSendMessageQueue::StartTransmit - Exit"));
+ }
+
+CSendMessageData* CSendMessageQueue::NextDnsMessageL()
+ {
+ __FLOG(_L8("CSendMessageQueue::NextDnsMessageL - Entry"));
+ if (0 == iMessageQueue.Count())
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ CSendMessageData* ret = iMessageQueue[0];
+ iMessageQueue.Remove(0);
+ // calculate the next possible transmit time.
+ iNextTransmit.HomeTime();
+ TInt delay = 20 + (Math::Rand(iRandomSeed) % 100);
+ iNextTransmit += TTimeIntervalMicroSeconds(delay * 1000);
+ __FLOG(_L8("CSendMessageQueue::NextDnsMessageL - Exit"));
+ return ret;
+ }
+
+TBool CSendMessageQueue::MessageReady()
+ {
+ __FLOG(_L8("CSendMessageQueue::MessageReady - Entry"));
+ TBool ready = EFalse;
+ if (0 != iMessageQueue.Count())
+ {
+ if (iMessageQueue[0]->IsUnicast())
+ {
+ // unicast messages go out straight away.
+ ready = ETrue;
+ }
+ else
+ {
+ TTime now;
+ now.HomeTime();
+ if (!IsActive())
+ {
+ if (now >= iNextTransmit)
+ {
+ ready = ETrue;
+ }
+ else
+ {
+ NextTransmitTime(iNextTransmit);
+ }
+ }
+ }
+ }
+ __FLOG(_L8("CSendMessageQueue::MessageReady - Exit"));
+ return ready;
+ }
+