// 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:
// mdnsserversession.cpp
// 
//
/**
@file
@internalTechnology
*/

#include "mdnsserversession.h"
#include <s32mem.h>
#include <utf.h>
#include "mdnsserver.h"
#include <mdns/cmdnsserverconstants.h>
#include <f32file.h>
__FLOG_STMT(_LIT8(KComponent,"MDNSServer");)
/*
 * Two phase constructor.
 */
CMdnsServerSession* CMdnsServerSession::NewL(const CMdnsServer& aServer)
	{
	CMdnsServerSession* self = CMdnsServerSession::NewLC(aServer);
	CleanupStack::Pop(self);
	return self;
	}


/*
 * Two phase constructor
 * @param aServer reference to the server.
 */
CMdnsServerSession* CMdnsServerSession::NewLC(const CMdnsServer& aServer)
	{
	CMdnsServerSession* self = new (ELeave) CMdnsServerSession(aServer);
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

/*
 * @param aMessage RMessage object.
 */
void CMdnsServerSession::ServiceL(const RMessage2& aMessage)
	{
	__FLOG(_L8("CMdnsServerSession::ServiceL - Entry"));
	switch (aMessage.Function())
		{
	case EZeroconfServerMessageVersion:
		break;
		
	case EMdnsServerQueryMessages:
		{
		if(NULL != iClientQuery.Handle())
			{
			aMessage.Complete(KErrInUse);	
			}
		else if (iServer.IsHostProbing() )
            {
            iServer.MessageQueue()->AppendMessageL(EQueryMessage,aMessage,SessionId());
            }
		else	
			{
			ServiceQueryL(aMessage);
			}	
		}
		break;
		
	case EMdnsServerRecieveMessages:
		{
		HBufC8* buffer = HBufC8::NewLC(KDnsBufferlength);
		TPtr8 bufferPointer(buffer->Des());
		iResponseBundle.Store(bufferPointer);	
		aMessage.Write(0,bufferPointer);	
		CleanupStack::PopAndDestroy();//delete buffer
		aMessage.Complete(KErrNone);
		iResponseBundle.Close();
		}	
		break;
	
	case EMndsServerPublishMessages:
	    {
	    if( iServer.IsHostProbing() || iServer.IsPublishingService())
	        {
	        iServer.MessageQueue()->AppendMessageL(EPublishMessage,aMessage,SessionId());
	        }
	    else
	        {
	        iServer.SetPublishingService(ETrue);
	        PublishL(aMessage);
	        }
	    break;
	    }
	case EMdnsServerStartNotifyMessages:
	    {
	    RegisterNotifyL(aMessage);
	    aMessage.Complete(KErrNone);
	    break;
	    }
	    
	case EMdnsServerStopNotifyMessages:
	    {
	    StopNotifyL(aMessage);
	    aMessage.Complete(KErrNone);
	    break;
	    }
	    
	case EMdnsServerRecieveNotifyMessages:
	    {
	    iNotifyMessageRequest = aMessage;
	    break;
	    }
	default:
		User::Leave(KErrUnknown);
		break;
		}
	
	__FLOG(_L8("CMdnsServerSession::ServiceL - Exit"));
	}
	
void CMdnsServerSession::ServiceError(const RMessage2& aMessage, TInt aError)
	{
	__FLOG(_L8("CMdnsServerSession::ServiceError - Entry Exit"));
	aMessage.Complete(aError);
	}



void CMdnsServerSession::CleanUp()
    {
    __FLOG(_L8("CMdnsServerSession::CleanUp - Entry"));
    // First thing is to send bye-bye packets to the services that we have published.
    
    RPointerArray <CCacheEntry> cacheEntries;
    iServer.MessageHandler().DnsCache().AuthoritativeEntriesL(cacheEntries);
    
    for(TInt index =0; index < cacheEntries.Count();index++)
        {               
        CCacheEntry* entry = cacheEntries[index];
        if(entry->SessionId()==iSessionId)
            {
            // To filter out address records.
            if(entry->ServiceRecord())
                {
                
                // found the entry to be deleted
                if(entry->ServiceRecord())
                    entry->ServiceRecord()->SetTtl(0);
                if(entry->TxtRecord())
                    entry->TxtRecord()->SetTtl(0);
                if(entry->PtrRecord())
                    entry->PtrRecord()->SetTtl(0);
                
                // delete the entry in the cache
                
                // !!!!!! Assuming that the entry will always contain a srv record.
                iServer.MessageHandler().DnsCache().DeleteEntryL(entry->ServiceRecord()->Name());
                
                CDnsMessage* message = CDnsMessage::NewL(0,EFalse);
                CleanupStack::PushL(message);    
                
                TDnsHeader header(message->Header());
                header.SetAuthoritative(ETrue);
                message->SetHeader(header);
                
                if(entry->ServiceRecord())
                message->AppendAnswerL(entry->ServiceRecord()->CloneL());
                if(entry->PtrRecord())
                message->AppendAnswerL(entry->PtrRecord()->CloneL());
                if(entry->TxtRecord())
                message->AppendAnswerL(entry->TxtRecord()->CloneL());
    
                // bye-bye packet on the way to the network !!!
                iServer.MessageHandler().SendQueryL(message,iServer);
                CleanupStack::Pop(); //message   
                }
            
            }
        }       
    
    
    cacheEntries.ResetAndDestroy();
    cacheEntries.Close();   
    __FLOG(_L8("CMdnsServerSession::CleanUp - Exit"));
    }
/*
 * Destructor
 */
CMdnsServerSession::~CMdnsServerSession()
	{
	__FLOG(_L8("CMdnsServerSession::~CMdnsServerSession - Entry"));
	CleanUp();
	iQueryBundle.Close();
	iResponseBundle.Close();
	iServer.DropSession();
	for(TInt i =0 ; i<iRegisterNotifyArray.Count();i++ )
	    {
	    iRegisterNotifyArray[i].Close();
	    }
	iRegisterNotifyArray.Close();
	__FLOG(_L8("CMdnsServerSession::~CMdnsServerSession - Exit"));
	__FLOG_CLOSE;
	}
/*
 * Constructor
 */
CMdnsServerSession::CMdnsServerSession(const CMdnsServer& aServer)
	: iServer(const_cast<CMdnsServer&>(aServer))
	{
	iSessionId = iServer.NewSession();
	}
	
/*
 * Two phase constructor
 */
void CMdnsServerSession::ConstructL()
	{
	__FLOG_OPEN(KMDNSSubsystem, KComponent);
	}

//TODO
TInt CMdnsServerSession::CountResources()
	{
	return 3;
	}

void CMdnsServerSession::ServerVersionL(const RMessage2& aMessage)
	{
	__FLOG(_L8("CMdnsServerSession::ServerVersionL - Entry"));
	TVersion mdnsServerVersion(0, 8, 0);
	TPckgC<TVersion> pkg(mdnsServerVersion);
	aMessage.WriteL(0, pkg);
	aMessage.Complete(KErrNone);
	__FLOG(_L8("CMdnsServerSession::ServerVersionL - Exit"));

	}
/*
 * Service any query rom the client
 */
void CMdnsServerSession::ServiceQueryL(const RMessage2& aMessage)
	{
	__FLOG(_L8("CMdnsServerSession::ServiceQueryL - Entry"));
	iQueryBundle.Close();
	iClientQuery = aMessage;
	TInt len = aMessage.GetDesLengthL(0);
	HBufC8* query = HBufC8::NewLC(aMessage.GetDesLengthL(0));
	TPtr8 loadPtr = query->Des();
	aMessage.ReadL(0,loadPtr);
	iQueryBundle.CreateL();
	TInt retOnLoad = iQueryBundle.Load(loadPtr);
	User::LeaveIfError(retOnLoad);
	RParameterFamily pnpFamily = iQueryBundle.GetFamilyAtIndex(0);
	TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
	CDnsMessage* message = CDnsMessage::NewL(0,ETrue );
	CleanupStack::PushL(message);
	for ( TInt paramIndex = count - 1; paramIndex >= 0; paramIndex-- )
		{ 
		CMDnsQueryRequestParamSet* queryParam = static_cast<CMDnsQueryRequestParamSet*> (pnpFamily.GetParameterSetAtIndex ( paramIndex, RParameterFamily::ERequested ));
		HBufC8* name = HBufC8::NewL(256);
		CleanupStack::PushL(name);
		TPtr8 ptrName(name->Des());
		ptrName.Append(queryParam->InstanceName());
		if(queryParam->InstanceName().Length() > 0)
			{
			ptrName.Append(_L8("."));	
			}
		ptrName.Append(queryParam->ServiceType());
		if(queryParam->QueryType() != EDnsType_A)
			{
			ptrName.Append(1 == queryParam->Protocol() ? KTcpProtocolType : KUdpProtocolType);	
			}
		ptrName.Append(KLocalTld);
		ptrName.Append(_L8("."));
		CDnsQuestion* question = CDnsQuestion::NewL();
		CleanupStack::PushL(question);
		question->SetNameL(ptrName);
		question->SetClass(EDnsClass_IN);
		question->SetType(queryParam->QueryType());
		question->SetUnicast(EFalse);
		message->AppendQueryL(question);
		CleanupStack::Pop();
		CleanupStack::PopAndDestroy();//name
		}
	iServer.MessageHandler().ServiceClientQueryL(message,aMessage.Handle());	
	CleanupStack::Pop();//message
	CleanupStack::PopAndDestroy();//query
	__FLOG(_L8("CMdnsServerSession::ServiceQueryL - Exit"));
	}

TInt CMdnsServerSession::OutStandQueryClientHandle()const
	{
	return iClientQuery.Handle();	
	}
	
void CMdnsServerSession::SendResponseL()
	{
	__FLOG(_L8("CMdnsServerSession::SendResponseL - Entry"));
	RParameterFamily pnpFamily = iQueryBundle.GetFamilyAtIndex(0);
	TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
	//Open a new reference to ResponseBundle 
	iResponseBundle.Open ();
	CleanupClosePushL( iResponseBundle );
	for(TInt index =0 ;index <count ; index++)
		{
		CMDnsQueryRequestParamSet* queryParam = static_cast<CMDnsQueryRequestParamSet*> (pnpFamily.GetParameterSetAtIndex ( index, RParameterFamily::ERequested ));
		HBufC8* name = HBufC8::NewL(KDnsBufferlength);
		CleanupStack::PushL(name);
		TPtr8 ptrName(name->Des());
		ptrName.Append(queryParam->InstanceName());
		if(queryParam->InstanceName().Size()>0)
		    ptrName.Append(_L8("."));
		ptrName.Append(queryParam->ServiceType());
		if(queryParam->QueryType() != EDnsType_A)
			{
			ptrName.Append(1 == queryParam->Protocol() ? KTcpProtocolType : KUdpProtocolType);	
			}
		ptrName.Append(KLocalTld);
		ptrName.Append(_L8("."));	
		RPointerArray<CCacheEntry> records;
		iServer.MessageHandler().DnsCache().FindServiceL(records,ptrName,(TDnsType)queryParam->QueryType());
		TInt count = records.Count();
		switch((TDnsType)queryParam->QueryType())	
			{
				case EDnsType_PTR:
					{
					RParameterFamily pnpFamily = iResponseBundle.CreateFamilyL (EMdnsPtrParamset);
					while(count -- > 0 )
						{
						iResponseBundle.SetPnPObserver((MPnPObserver*)NULL);
						CMDnsPtrParamSet* responseParam = CMDnsPtrParamSet::NewL(pnpFamily);
						responseParam->SetInstanceNameL(records[count]->PtrRecord()->Name());
						responseParam->SetDomainNameL(records[count]->PtrRecord()->DomainName());
						//responseParam->SetTtlL(records[count]->PtrRecord()->Ttl());
						}
					break;
					}
				case EDnsType_SRV:
					{
					RParameterFamily pnpFamily = iResponseBundle.CreateFamilyL (EMdnsSrvParamset);
					while(count -- > 0 )
						{
						iResponseBundle.SetPnPObserver((MPnPObserver*)NULL);
						CMDnsSrvParamSet* responseParam = CMDnsSrvParamSet::NewL(pnpFamily);
						responseParam->SetDomainNameL(records[count]->ServiceRecord()->Name());
						responseParam->SetTargetL(records[count]->ServiceRecord()->Target());
						responseParam->SetPriority(records[count]->ServiceRecord()->Priority());
						responseParam->SetWeight(records[count]->ServiceRecord()->Weight());
						responseParam->SetPort(records[count]->ServiceRecord()->Port());	
						}
					break;	
					}
				case EDnsType_TXT:
					{
					RParameterFamily pnpFamily = iResponseBundle.CreateFamilyL (EMdnsTxtParamset);
					while(count -- > 0 )
						{
						iResponseBundle.SetPnPObserver((MPnPObserver*)NULL);
						CMDnsTxtParamSet* responseParam = CMDnsTxtParamSet::NewL(pnpFamily);
						responseParam->SetDomainNameL(records[count]->TxtRecord()->Name());
						RArray<RBuf8> txtData = records[count]->TxtRecord()->Text();
						
						for(TInt j=0;j<txtData.Count();j++)
						    {
						    responseParam->AppendTxtData(txtData[j]);
						    }
						}
					break;
					}
				case EDnsType_A:
					{
					RParameterFamily pnpFamily = iResponseBundle.CreateFamilyL (EMdnsAddrParamset);
					while(count -- > 0 )
						{
						iResponseBundle.SetPnPObserver((MPnPObserver*)NULL);
						CMDnsAddrParamSet* responseParam = CMDnsAddrParamSet::NewL(pnpFamily);
						responseParam->SetDomainNameL(records[count]->AddressRecord()->Name());	
						responseParam->SetAddress(records[count]->AddressRecord()->Address());
						}
					break;
					}
				case EDnsQType_Any:
				    {
				    iResponseBundle.SetPnPObserver((MPnPObserver*)NULL);
                    while(count -- > 0 )
                         {
                         CreateAnyQueryResponseL(*records[count]);
                         }
				    break;
				    }
					
			}
		records.ResetAndDestroy();
		records.Close();	
		CleanupStack::PopAndDestroy();//name	
		}//end of for loop
		
		HBufC8* buffer = HBufC8::NewLC(KDnsBufferlength);	
		TPtr8 bufferPointer(buffer->Des());
		iResponseBundle.Store(bufferPointer);
		TInt len = bufferPointer.Length();
		TPckgC<TInt> lenbuf(len); 
		iClientQuery.Write(1,lenbuf);
		CleanupStack::PopAndDestroy();//buffer
		iClientQuery.Complete(KErrNone);
		CleanupStack::Pop();//iResponseBundle
		__FLOG(_L8("CMdnsServerSession::SendResponseL - Exit"));	
	}

void CMdnsServerSession::PublishL(const RMessage2& aMessage)
    {
    __FLOG(_L8("CMdnsServerSession::PublishL - Entry"));
    TBool isUpdate = aMessage.Int2();
    iPublishRequest = aMessage;
    TInt len = aMessage.GetDesLengthL(0);
    HBufC8* query = HBufC8::NewLC(aMessage.GetDesLengthL(0));
    TPtr8 loadPtr = query->Des();
    aMessage.ReadL(0,loadPtr);
    iPublishBundle.CreateL();
    TInt retOnLoad = iPublishBundle.Load(loadPtr);
    TInt familyCount = iPublishBundle.CountParameterFamilies();
    RPointerArray<CDnsResourceData> publishRecordArray;
    for(TInt i =0 ; i< familyCount; i++)
        {
        RParameterFamily pnpFamily = iPublishBundle.GetFamilyAtIndex(i);
        switch (pnpFamily.Id())
            {
            case EMdnsSrvParamset:
                {
                TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
                for (TInt index= 0; index < count ; index++ )
                    {
                    CMDnsSrvParamSet* srvParamSet = static_cast<CMDnsSrvParamSet*> (pnpFamily.GetParameterSetAtIndex ( index, RParameterFamily::ERequested ));
                    CRdTypeSrv* srvRecord = CRdTypeSrv::NewL();
                    CleanupStack::PushL(srvRecord);
                    srvRecord->SetNameL(srvParamSet->DomainName());
                    srvRecord->SetClass(EDnsClass_IN);
                    srvRecord->SetFlushBit(EFalse);
                    srvRecord->SetPort(srvParamSet->Port()); 
                    srvRecord->SetPriority(srvParamSet->Priority() );
                    srvRecord->SetTargetL(iServer.HostName());
                    srvRecord->SetTtl(120);
                    srvRecord->SetType(EDnsType_SRV);
                    srvRecord->SetWeight(srvParamSet->Weight());
                    publishRecordArray.AppendL(srvRecord);
                    CleanupStack::Pop();//CRdtypeSrv
                    //Ptr Record
                    /*
                    CRdTypePtr* ptrRecord = CRdTypePtr::NewL();
                    CleanupStack::PushL(ptrRecord);
                    TInt pos = srvParamSet->DomainName().Locate('.');
                    ptrRecord->SetNameL(srvParamSet->DomainName().Mid(pos+1));
                    ptrRecord->SetClass(EDnsClass_IN);
                    ptrRecord->SetFlushBit(EFalse);
                    ptrRecord->SetTtl(120);
                    ptrRecord->SetType(EDnsType_PTR);
                    ptrRecord->SetDomainNameL(srvParamSet->DomainName());
                    publishRecordArray.AppendL(ptrRecord);
                    CleanupStack::Pop();
                    */
                    }
                break;
                }
            case EMdnsPtrParamset:
                {
                //do nothing
                TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
                for (TInt index= 0; index < count ; index++ )
                     {
                     CMDnsPtrParamSet* ptrParamSet = static_cast<CMDnsPtrParamSet*>(pnpFamily.GetParameterSetAtIndex( index, RParameterFamily::ERequested ));
                     CRdTypePtr* ptrRecord = CRdTypePtr::NewL();
                     CleanupStack::PushL(ptrRecord);
                     ptrRecord->SetNameL(ptrParamSet->InstanceName());
                     ptrRecord->SetClass(EDnsClass_IN);
                     ptrRecord->SetFlushBit(EFalse);
                     ptrRecord->SetTtl(120);
                     ptrRecord->SetType(EDnsType_PTR);
                     ptrRecord->SetDomainNameL(ptrParamSet->DomainName());
                     publishRecordArray.AppendL(ptrRecord);
                     CleanupStack::Pop();//Remove Ptr Record from the queue..
                     }
                break;
                }
            case EMdnsAddrParamset:
                {
                TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
                for (TInt index= 0; index < count ; index++ )
                     {
                     CMDnsAddrParamSet* addrParamSet = static_cast<CMDnsAddrParamSet*>(pnpFamily.GetParameterSetAtIndex( index, RParameterFamily::ERequested ));
                     CRdTypeA* addrRecord = CRdTypeA::NewL();
                     CleanupStack::PushL(addrRecord);
                     addrRecord->SetAddr(addrParamSet->Address());
                     addrRecord->SetNameL(addrParamSet->DomainName());
                     addrRecord->SetClass(EDnsClass_IN);
                     addrRecord->SetFlushBit(EFalse);
                     addrRecord->SetTtl(120);
                     addrRecord->SetType(EDnsType_A);
                     publishRecordArray.AppendL(addrRecord);
                     CleanupStack::Pop();//remove addrecord from the queue
                     }
                break;
                }
            case EMdnsTxtParamset:
                {
                TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
                for (TInt index= 0; index < count ; index++ )
                     {
                     CMDnsTxtParamSet* txtParamSet = static_cast<CMDnsTxtParamSet*>(pnpFamily.GetParameterSetAtIndex( index, RParameterFamily::ERequested ));
                     CRdTypeTxt* txtRecord = CRdTypeTxt::NewL();
                     CleanupStack::PushL(txtRecord);
                     txtRecord->SetNameL(txtParamSet->DomainName());
                     txtRecord->SetClass(EDnsClass_IN);
                     txtRecord->SetFlushBit(EFalse);
                     txtRecord->SetTtl(120);
                     txtRecord->SetType(EDnsType_TXT);
                     RArray<RBuf8> txtArray ;
                     txtParamSet->TxtDataL(txtArray);
                     TInt txtCnt = txtArray.Count();
                     for(TInt count = 0; count < txtCnt ; count ++ )
                         {
                         txtRecord->AppendTextDataL(txtArray[count]);
                         }
                     txtArray.Close();
                     publishRecordArray.AppendL(txtRecord);
                     CleanupStack::Pop();//remove txtRecord from the queue..
                     }
                break;
                }
            }
        
        }
    TRAPD(publishError ,iServer.MessageHandler().AdvertizePacketL(publishRecordArray,iSessionId , isUpdate));
    if(publishError == KErrNotFound)
        {
        aMessage.Complete(KErrNotFound);
        }
    publishRecordArray.Close();
    iPublishBundle.Close();
    CleanupStack::PopAndDestroy(query);
    __FLOG(_L8("CMdnsServerSession::PublishL - Exit"));
    }
    
void CMdnsServerSession::HandleServiceNameConflictL(const RBuf8& aName,TInt aError)
    {
    __FLOG(_L8("CMdnsServerSession::HandleServiceNameConflictL - Entry"));
    iResponseBundle.Open ();
    CleanupClosePushL( iResponseBundle );
    
    RParameterFamily pnpFamily = iResponseBundle.CreateFamilyL (EMdnsPublishResponseParamset);
    iResponseBundle.SetPnPObserver((MPnPObserver*)NULL);
    
    CMDnsPublishResponseParamSet* responseParam = CMDnsPublishResponseParamSet::NewL(pnpFamily);
    responseParam->SetDomainNameL(aName);
    responseParam->SetError(aError);

    
    TInt len = iResponseBundle.Length();
    TPckgC<TInt> lenbuf(len); 
    iPublishRequest.Write(1,lenbuf);
    
    iPublishRequest.Complete(KErrNone);
    CleanupStack::Pop();//iResponseBundle
    __FLOG(_L8("CMdnsServerSession::HandleServiceNameConflictL - Exit"));
    }
   
void CMdnsServerSession::RegisterNotifyL(const RMessage2& aMessage)
    {
    __FLOG(_L8("CMdnsServerSession::RegisterNotifyL - Entry"));
    iIsNotifyRequested = ETrue;
    RPnPParameterBundle registerBundle;
    TInt size = aMessage.GetDesLength(0);
    HBufC8* registerbuf = HBufC8::NewLC(aMessage.GetDesLengthL(0));
    TPtr8 loadPtr = registerbuf->Des();
    aMessage.ReadL(0,loadPtr);
    registerBundle.CreateL();
    registerBundle.Load(loadPtr);
    RParameterFamily pnpFamily = registerBundle.GetFamilyAtIndex(0);
    TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
    for(TInt index =0 ; index<count ; index++)
        {
        CMDnsRegisterNotifyParamSet* registerParamSet = static_cast<CMDnsRegisterNotifyParamSet*>(pnpFamily.GetParameterSetAtIndex( index, RParameterFamily::ERequested ));
        RBuf8 instanceName;
        instanceName.CreateL(registerParamSet->InstanceName());
        iRegisterNotifyArray.AppendL(instanceName);
        }
    registerBundle.Close();
    CleanupStack::PopAndDestroy();//registerbuffer
    __FLOG(_L8("CMdnsServerSession::RegisterNotifyL - Exit"));
    }

void CMdnsServerSession::StopNotifyL(const RMessage2& aMessage)
    {
    __FLOG(_L8("CMdnsServerSession::StopNotifyL - Entry"));
    RPnPParameterBundle registerBundle;
    TInt size = aMessage.GetDesLength(0);
    HBufC8* registerbuf = HBufC8::NewLC(aMessage.GetDesLengthL(0));
    TPtr8 loadPtr = registerbuf->Des();
    aMessage.ReadL(0,loadPtr);
    registerBundle.CreateL();
    registerBundle.Load(loadPtr);
    RParameterFamily pnpFamily = registerBundle.GetFamilyAtIndex(0);
    TUint count = pnpFamily.CountParameterSets ( RParameterFamily::ERequested ) ;
    for(TInt index =0 ; index< count; index++)
        {
        CMDnsRegisterNotifyParamSet* registerParamSet = static_cast<CMDnsRegisterNotifyParamSet*>(pnpFamily.GetParameterSetAtIndex( index, RParameterFamily::ERequested ));
        RBuf8 instanceName;
        instanceName.CreateL(registerParamSet->InstanceName());
        for(TInt i =0 ; i< iRegisterNotifyArray.Count();i++)
                {
                if(instanceName.Compare(iRegisterNotifyArray[i]) == 0)
                    {
                    RBuf8& temp = iRegisterNotifyArray[i];
                    iRegisterNotifyArray.Remove(i);
                    temp.Close();
                    }
                }
        instanceName.Close();
        }
    if(iRegisterNotifyArray.Count() == 0 )
        {
        iIsNotifyRequested =EFalse;
        }
    registerBundle.Close();
    CleanupStack::PopAndDestroy();//registerbuffer
    __FLOG(_L8("CMdnsServerSession::StopNotifyL - Exit"));
    }

TInt CMdnsServerSession::SessionId()
    {
    __FLOG(_L8("CMdnsServerSession::SessionId - Exit"));
    return iSessionId;
    }
void CMdnsServerSession::NewServiceL(const RArray<RBuf8>& aName)
    {
    __FLOG(_L8("CMdnsServerSession::NewServiceL - Entry"));
    if(iIsNotifyRequested && iNotifyMessageRequest.Handle())
        {
        RPnPParameterBundle publishBundle;
        publishBundle.CreateL();
        RParameterFamily pnpFamily = publishBundle.CreateFamilyL (EMdnsPtrParamset);
        publishBundle.SetPnPObserver((MPnPObserver*)NULL);
        for(TInt i =0 ; i < aName.Count();i++)
            {
            for(TInt j= 0 ; j< iRegisterNotifyArray.Count(); j++)
                {
                TInt pos = aName[i].Find(iRegisterNotifyArray[j]);
                if(pos != KErrNotFound)
                    {
                    CMDnsPtrParamSet* responseParam = CMDnsPtrParamSet::NewL(pnpFamily);
                    responseParam->SetInstanceNameL(iRegisterNotifyArray[j]);
                    responseParam->SetDomainNameL(aName[i]); 
                    // have to fill up the ttl field, query the cache
                    RPointerArray <CCacheEntry>  aEntries;
                    iServer.MessageHandler().DnsCache().FindServiceL(aEntries,aName[i],EDnsType_SRV);
                    responseParam->SetTtlL(0);
                    if(aEntries.Count()==0)
                        {
                        // already deleted from cache
                        responseParam->SetTtlL(0);
                        }
                    else if(aEntries[0]->PtrRecord()!=NULL)
                        {
                        responseParam->SetTtlL(aEntries[0]->PtrRecord()->Ttl());
                        }
                    aEntries.ResetAndDestroy();
                    aEntries.Close();    
                    break;
                    }
                }
            }
        HBufC8* buffer = HBufC8::NewLC(KDnsBufferlength);   
        TPtr8 bufferPointer(buffer->Des());
        publishBundle.Store(bufferPointer);
        iNotifyMessageRequest.Write(0,bufferPointer);
        iNotifyMessageRequest.Complete(KErrNone);
        CleanupStack::PopAndDestroy(buffer);//buffer
        publishBundle.Close();
        }
    __FLOG(_L8("CMdnsServerSession::NewServiceL - Exit"));
    }


void CMdnsServerSession::CreateAnyQueryResponseL(CCacheEntry& aEntry)
    {
    RParameterFamily ptrFamily = iResponseBundle.CreateFamilyL (EMdnsPtrParamset);
    RParameterFamily srvFamily = iResponseBundle.CreateFamilyL (EMdnsSrvParamset);
    RParameterFamily txtFamily = iResponseBundle.CreateFamilyL (EMdnsTxtParamset);
    RParameterFamily AFamily = iResponseBundle.CreateFamilyL (EMdnsAddrParamset);
    if(aEntry.AddressRecord()!= NULL)
        {
        CMDnsAddrParamSet* responseParam = CMDnsAddrParamSet::NewL(AFamily);
        responseParam->SetDomainNameL(aEntry.AddressRecord()->Name()); 
        responseParam->SetAddress(aEntry.AddressRecord()->Address());
        }
    if(aEntry.ServiceRecord()!= NULL)
        {
        CMDnsSrvParamSet* responseParam = CMDnsSrvParamSet::NewL(srvFamily);
        responseParam->SetDomainNameL(aEntry.ServiceRecord()->Name());
        responseParam->SetTargetL(aEntry.ServiceRecord()->Target());
        responseParam->SetPriority(aEntry.ServiceRecord()->Priority());
        responseParam->SetWeight(aEntry.ServiceRecord()->Weight());
        responseParam->SetPort(aEntry.ServiceRecord()->Port());
        }
    if(aEntry.PtrRecord()!= NULL)
        {
        CMDnsPtrParamSet* responseParam = CMDnsPtrParamSet::NewL(ptrFamily);
        responseParam->SetInstanceNameL(aEntry.PtrRecord()->Name());
        responseParam->SetDomainNameL(aEntry.PtrRecord()->DomainName());
        //responseParam->SetTtlL(aEntry.PtrRecord()->Ttl());
        }
    if(aEntry.TxtRecord()!= NULL)
        {
        CMDnsTxtParamSet* responseParam = CMDnsTxtParamSet::NewL(txtFamily);
        responseParam->SetDomainNameL(aEntry.TxtRecord()->Name());
        RArray<RBuf8> txtData = aEntry.TxtRecord()->Text();
        for(TInt txtCount = 0 ;txtCount < txtData.Count();txtCount++)
            {
            responseParam->AppendTxtData(txtData[txtCount]);
            }
        }
    
    }
