--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/zeroconf/server/src/cresponsehandler.cpp Thu Jun 24 19:09:47 2010 +0530
@@ -0,0 +1,423 @@
+// 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:
+// cresponsehandler.cpp
+//
+//
+/**
+@file
+@internalTechnology
+*/
+
+//System include
+#include <mdns/ccacheentry.h>
+
+//User include
+#include "cresponsehandler.h"
+__FLOG_STMT(_LIT8(KComponent,"MDNSServer");)
+/**
+Two phase constructor
+@param aMessageHandler a reference to messagehandler
+*/
+CResponseHandler* CResponseHandler::NewL(CMessageHandler& aMessageHandler)
+ {
+ CResponseHandler* self = new(ELeave) CResponseHandler(aMessageHandler);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+Destructor
+*/
+CResponseHandler::~CResponseHandler()
+ {
+ __FLOG(_L8("CResponseHandler::~CResponseHandler - Entry"));
+ iNotifyPtrName.Close();
+ __FLOG(_L8("CResponseHandler::~CResponseHandler - Exit"));
+ __FLOG_CLOSE;
+ }
+
+/**
+Handles any resopnse packet recieved from the mdns port
+@param response packet
+@return void
+*/
+void CResponseHandler::HandleIncomingPacketL(CDnsMessage& aMessage, const TSockAddr& /*aAddr*/)
+ {
+ __FLOG(_L8("CResponseHandler::HandleIncomingPacketL - Entry"));
+ iNotifyPtrName.Close();
+ // process the answer section, and add to the host and service caches
+ TInt aCount(aMessage.Header().AnswerCount());
+ const RPointerArray<CDnsResourceData>& answers = aMessage.Answers();
+ for (TInt i = 0; i < aCount; ++i)
+ {
+ HandlePacketAnswersL(answers[i]);
+ }
+ aCount = aMessage.Header().AdditionalRCount();
+ const RPointerArray<CDnsResourceData>& additional = aMessage.Additional();
+ for (TInt i = 0; i < aCount; ++i)
+ {
+ if(additional[i]!=NULL)
+ HandlePacketAnswersL(additional[i]);
+ }
+ aCount = aMessage.Header().AuthorityNSCount();
+ const RPointerArray<CDnsResourceData>& authoritative = aMessage.Authorities();
+ for (TInt i = 0; i < aCount; ++i)
+ {
+ if(authoritative[i]!=NULL)
+ HandlePacketAnswersL(authoritative[i]);
+ }
+
+ if(iNotifyPtrName.Count() > 0 )
+ {
+ MessageHandler().NotifyNewServiceL(iNotifyPtrName);
+ for(TInt i=0 ; i<iNotifyPtrName.Count() ; i++)
+ {
+ iNotifyPtrName[i].Close();
+ }
+ iNotifyPtrName.Close();
+ }
+ __FLOG(_L8("CResponseHandler::HandleIncomingPacketL - Exit"));
+ }
+
+/*
+Constructor
+*/
+CResponseHandler::CResponseHandler(CMessageHandler& aMessageHandler):CBaseHandler(aMessageHandler)
+ {
+
+ }
+
+/**
+Two phasae constructor
+*/
+void CResponseHandler::ConstructL()
+ {
+ __FLOG_OPEN(KMDNSSubsystem, KComponent);
+ __FLOG(_L8("CResponseHandler::ConstructL - Entry Exit"));
+ }
+/*
+ * Based on the type of query response recieved from the network.
+ * it will route the record to particular interface.
+ * @param aResourceData record recieved from the network.
+ */
+void CResponseHandler::HandlePacketAnswersL(CDnsResourceData* aResourceData)
+ {
+ __FLOG(_L8("CResponseHandler::HandlePacketAnswersL - Entry"));
+ switch(aResourceData->Type())
+ {
+ case EDnsType_A:
+ {
+ HandleAddrAnswersL(aResourceData);
+ break;
+ }
+
+ case EDnsType_PTR:
+ {
+ HandlePTRAnswersL(aResourceData);
+ break;
+ }
+
+ case EDnsType_TXT:
+ {
+ HandleTXTAnswersL(aResourceData);
+ break;
+ }
+
+ case EDnsType_AAAA:
+ {
+ HandleAAAAAnswersL(aResourceData);
+ //MessageHandler().DnsCache().Insert();
+ break;
+ }
+
+ case EDnsType_SRV:
+ {
+ HandleSRVAnswersL(aResourceData);
+ break;
+ }
+ }
+ __FLOG(_L8("CResponseHandler::HandlePacketAnswersL - Exit"));
+ }
+
+/**
+This handles any address content in the answer section .
+If the cache already contains a address entry with the same name .This will notify the server to change the name.
+If the cache doesnt contain the entry it will just add this entry in to it.
+@param aResourceData Contains the answers and nspackets recieved from the mdns port
+@param aEntry Reference to entry to which record should be added so as to add the same to cache later.
+@return void
+*/
+void CResponseHandler::HandleAddrAnswersL(CDnsResourceData* aResourceData)
+ {
+ __FLOG(_L8("CResponseHandler::HandleAddrAnswersL - Entry"));
+ CRdTypeA* addrRecord = static_cast<CRdTypeA*>(aResourceData);
+ CleanupStack::PushL(addrRecord);
+ TBufC8<100> domainName(addrRecord->Name());
+ RPointerArray<CCacheEntry> aCacheArray;
+ TBool isUpdated = EFalse;
+ TRAPD(error,MessageHandler().DnsCache().FindServiceL(aCacheArray,domainName,EDnsType_A));
+ if(error == KErrNone && 0 != aCacheArray.Count())
+ {
+ const CRdTypeA* addrRecordCEntry = (aCacheArray[0])->AddressRecord();
+ if(addrRecordCEntry != NULL && addrRecordCEntry->Name().Compare(domainName) == 0)
+ {
+ if(aCacheArray[0]->IsAuthoritative())
+ {
+ if(addrRecordCEntry->Address() != addrRecord->Address() && addrRecord->IsFlushBitSet())
+ {
+ MessageHandler().DnsCache().UpdateCacheL(*addrRecord,EFalse,0);
+ isUpdated = ETrue;
+ }
+ }
+ else
+ {
+ isUpdated = ETrue;
+ MessageHandler().DnsCache().UpdateCacheL(*addrRecord,EFalse,0);
+ }
+
+ }
+
+ }
+
+ if (! isUpdated&& 0 != aResourceData->Ttl())
+ {
+ // we didn't find it, add a new entry.
+ MessageHandler().DnsCache().UpdateCacheL(*addrRecord,EFalse,0);
+ }
+ aCacheArray.ResetAndDestroy();
+ aCacheArray.Close();
+ CleanupStack::Pop();//addrRecord
+ __FLOG(_L8("CResponseHandler::HandleAddrAnswersL - Exit"));
+ }
+
+/*
+ * Handles any PTR records in the answer section.
+ * 1.Updates the cache if not present .
+ * 2.Notitfies the client about the new service availability if registered for it.
+ * @param aResourceData ptr record recieved from the network.
+ */
+
+void CResponseHandler::HandlePTRAnswersL(CDnsResourceData* aResourceData)
+ {
+ __FLOG(_L8("CResponseHandler::HandlePTRAnswersL - Entry"));
+ CRdTypePtr* ptrEntry = static_cast<CRdTypePtr*>(aResourceData);
+ CleanupStack::PushL(ptrEntry);
+ TBufC8<100> name(ptrEntry->Name());
+ RPointerArray<CCacheEntry> aCacheArray;
+ MessageHandler().DnsCache().FindServiceL(aCacheArray,name,EDnsType_PTR);
+ TBool isUpdated = EFalse;
+ for (TInt i =0 ; i< aCacheArray.Count(); i++)
+ {
+ if(NULL != aCacheArray[i])
+ {
+ const CRdTypePtr* ptrRecord = aCacheArray[i]->PtrRecord();
+ if(ptrRecord->DomainName().CompareF(ptrEntry->DomainName()) == 0)
+ {
+ MessageHandler().DnsCache().UpdateCacheL(*ptrEntry,EFalse,0);
+ isUpdated = ETrue;
+ if(aResourceData->Ttl() == 0)
+ {
+ if(ptrEntry->DomainName().Find(ptrEntry->Name()) != KErrNotFound)
+ {
+ RBuf8 temp;
+ temp.CreateL(ptrEntry->DomainName());
+ if(iNotifyPtrName.Find(temp) == KErrNotFound)
+ {
+ iNotifyPtrName.AppendL(temp);
+ }
+ else
+ {
+ temp.Close();
+ }
+ }
+ CRdTypeSrv* srvRecord = static_cast <CRdTypeSrv*>( aCacheArray[i]->ServiceRecord());
+ if(srvRecord != NULL)
+ {
+ srvRecord->SetTtl(0);
+ MessageHandler().DnsCache().UpdateCacheL(*srvRecord,EFalse,0);
+ }
+ CRdTypeTxt* txtRecord = static_cast <CRdTypeTxt*> (aCacheArray[i]->TxtRecord());
+ if(txtRecord != NULL)
+ {
+ txtRecord->SetTtl(0);
+ MessageHandler().DnsCache().UpdateCacheL(*txtRecord,EFalse,0);
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ if(!isUpdated && 0 != aResourceData->Ttl())
+ {
+ MessageHandler().DnsCache().UpdateCacheL(*ptrEntry,EFalse,0);
+ //Notify the client about new service
+ if(ptrEntry->DomainName().Find(ptrEntry->Name()) != KErrNotFound)
+ {
+ RBuf8 temp;
+ temp.CreateL(ptrEntry->DomainName());
+ if(iNotifyPtrName.Find(temp) == KErrNotFound)
+ {
+ iNotifyPtrName.AppendL(temp);
+ }
+ else
+ {
+ temp.Close();
+ }
+ }
+ }
+ aCacheArray.ResetAndDestroy();
+ aCacheArray.Close();
+ CleanupStack::Pop(ptrEntry);
+ __FLOG(_L8("CResponseHandler::HandlePTRAnswersL - Exit"));
+ }
+
+/*
+ * Handles any TXT records in the answer section.
+ * 1.Updates the cache if not present .
+ * @param aResourceData ptr record recieved from the network.
+ */
+void CResponseHandler::HandleTXTAnswersL(CDnsResourceData* aResourceData)
+ {
+ __FLOG(_L8("CResponseHandler::HandleTXTAnswersL - Entry"));
+ CRdTypeTxt* txtEntry = static_cast<CRdTypeTxt*>(aResourceData);
+ CleanupStack::PushL(txtEntry);
+ RPointerArray<CCacheEntry> aCacheArray;
+ TBool isUpdated = EFalse;
+ TRAPD(error,MessageHandler().DnsCache().FindServiceL(aCacheArray,txtEntry->Name(),EDnsType_TXT));
+ if(error == KErrNone && 0 != aCacheArray.Count() && NULL != aCacheArray[0]->TxtRecord())
+ {
+ const CRdTypeTxt* txtRecord = aCacheArray[0]->TxtRecord();
+ if(NULL != txtRecord && txtRecord->Name().CompareF(txtEntry->Name()) == 0)
+ {
+ if(aCacheArray[0]->IsAuthoritative())
+ {
+ isUpdated = ETrue;
+ MessageHandler().DnsCache().UpdateCacheL(*txtEntry,ETrue,0);
+ }
+ else
+ {
+ isUpdated = ETrue;
+ MessageHandler().DnsCache().UpdateCacheL(*txtEntry,EFalse,0);
+ }
+
+ }
+ }
+ if(!isUpdated && aResourceData->Ttl() != 0 )
+ {
+ MessageHandler().DnsCache().UpdateCacheL(*txtEntry,EFalse,0);
+ }
+ RBuf8 temp;
+ temp.CreateL(txtEntry->Name());
+ if(iNotifyPtrName.Find(temp) == KErrNotFound)
+ {
+ iNotifyPtrName.AppendL(temp);
+ }
+ else
+ {
+ temp.Close();
+ }
+ aCacheArray.ResetAndDestroy();
+ aCacheArray.Close();
+ CleanupStack::Pop();//txtEntry*/
+ __FLOG(_L8("CResponseHandler::HandleTXTAnswersL - Exit"));
+ }
+
+void CResponseHandler::HandleAAAAAnswersL(CDnsResourceData* /*aResourceData*/)
+ {
+
+ }
+
+/*
+ * Handles any SRV records in the answer section.
+ * 1.Updates the cache if not present .
+ * @param aResourceData ptr record recieved from the network.
+ */
+void CResponseHandler::HandleSRVAnswersL(CDnsResourceData* aResourceData)
+ {
+ __FLOG(_L8("CResponseHandler::HandleSRVAnswersL - Entry"));
+ CRdTypeSrv* srvEntry = static_cast<CRdTypeSrv*>(aResourceData);
+ CleanupStack::PushL(srvEntry);
+ RPointerArray<CCacheEntry> cacheArray;
+ TBool isUpdated = EFalse;
+ TRAPD(error,MessageHandler().DnsCache().FindServiceL(cacheArray,srvEntry->Name(),EDnsType_SRV));
+ if(KErrNone == error && cacheArray.Count() != 0 && NULL != cacheArray[0]->ServiceRecord())
+ {
+ const CRdTypeSrv* srvRecord = cacheArray[0]->ServiceRecord();
+ /*if(aResourceData->Ttl() == 0)
+ {
+ if(srvEntry->Name().Find(srvEntry->Target()) != KErrNotFound)
+ {
+ RBuf8 temp;
+ temp.CreateL(srvEntry->Name());
+ if(iNotifyPtrName.Find(temp) == KErrNotFound)
+ {
+ iNotifyPtrName.AppendL(temp);
+ }
+ else
+ {
+ temp.Close();
+ }
+ }
+ CRdTypeSrv* srvRecord = static_cast <CRdTypeSrv*>( cacheArray[i]->ServiceRecord());
+ if(srvRecord != NULL)
+ {
+ srvRecord->SetTtl(0);
+ MessageHandler().DnsCache().UpdateCacheL(*srvRecord,EFalse,0);
+ }
+ CRdTypeTxt* txtRecord = static_cast <CRdTypeTxt*> (aCacheArray[i]->TxtRecord());
+ if(txtRecord != NULL)
+ {
+ txtRecord->SetTtl(0);
+ MessageHandler().DnsCache().UpdateCacheL(*txtRecord,EFalse,0);
+ }
+ }*/
+
+ if(srvRecord->Name().CompareF(srvEntry->Name()) == 0 && srvEntry->IsFlushBitSet())
+ {
+ if(cacheArray[0]->IsAuthoritative())
+ {
+ isUpdated = ETrue;
+ MessageHandler().DnsCache().UpdateCacheL(*srvEntry,ETrue,0);
+ }
+ else
+ {
+ isUpdated = ETrue;
+ MessageHandler().DnsCache().UpdateCacheL(*srvEntry,EFalse,0);
+ }
+ }
+
+ }
+ RBuf8 temp;
+ temp.CreateL(srvEntry->Name());
+ if(iNotifyPtrName.Find(temp) == KErrNotFound)
+ {
+ iNotifyPtrName.AppendL(temp);
+ }
+ else
+ {
+ temp.Close();
+ }
+ if(!isUpdated && srvEntry->Ttl() != 0)
+ {
+ MessageHandler().DnsCache().UpdateCacheL(*srvEntry,EFalse,0);
+ }
+ cacheArray.ResetAndDestroy();
+ cacheArray.Close();
+ CleanupStack::Pop();//srvEntry
+ __FLOG(_L8("CResponseHandler::HandleSRVAnswersL - Exit"));
+ }
+