zeroconf/server/src/cresponsehandler.cpp
changeset 14 da856f45b798
--- /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"));
+	}	
+