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

//System include
#include <mdns/cdnsmessagecomposerparser.h>
#include <mdns/cdnsmessage.h>
#include <e32base.h>

//user include
#include "cmessagehandler.h"
#include "cqueryhandler.h"
#include "ccacheentry.h"
#include "cresponsehandler.h"
#include "cadvertizehandler.h"
#include <mdns/mdnscachemgr.h>

__FLOG_STMT(_LIT8(KComponent,"MDNSServer");)
//
/**
Two phase constructor 
@param aServer reference to CBonjourServer
@return pointer to CMessageHandler
*/
CMessageHandler* CMessageHandler::NewL(CMdnsServer& aServer)
	{
	CMessageHandler* self = new (ELeave) CMessageHandler(aServer);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop();
	return self;
	}
/**
Implementation of MSocketHandlerObserver 
@param aData packet recieved from the mdns port
@param aAddr address from which packet is recieved
@param aLength length of the packet reieved
@return void
*/		
void CMessageHandler::OnCompletionL(TDesC8& aData, const TSockAddr& aAddr, TInt aLength ) 
	{
	__FLOG(_L8("CMessageHandler::OnCompletionL - Entry"));
	HandleIncomingPacketL(aData ,aAddr ,aLength );
	iRecieveSocket->Activate(TSocketHandlerParams(ESocketRecieve));	
	__FLOG(_L8("CMessageHandler::OnCompletionL - Exit"));
	}
/**
Any error in the socket will be notified here
@paran aError error with which socket leaves
@return void
*/	
void CMessageHandler::OnError(TInt /*aError*/)
	{
	__FLOG(_L8("CMessageHandler::OnError -Entry Exit"));
	}
	
/**
Constructor
*/
CMessageHandler::CMessageHandler(CMdnsServer& aServer):iServer(aServer)
	{
	
	}
	
/**
Two phase constructor
*/	
void CMessageHandler::ConstructL()
	{
	__FLOG_OPEN(KMDNSSubsystem, KComponent);
	__FLOG(_L8("CMessageHandler::ConstructL - Entry"));
	iQueryHandler = CQueryHandler::NewL(*this);
	iResponseHandler = CResponseHandler::NewL(*this);
	iAdvertizeHandler = CAdvertizeHandler::NewL(*this);
	iRecieveSocket = CSocketHandler::NewL(iServer.Socket(),*this,ESocketRecieve);
	iSendMessageQueue = CSendMessageQueue::NewL(iServer.Socket());
	iRecieveSocket->Activate(TSocketHandlerParams(ESocketRecieve));	
	iDnsCache = CMDNSCacheManager::NewL(200);
	iDummyhandler = CBaseHandler::NewL(*this);
	__FLOG(_L8("CMessageHandler::ConstructL - Exit"));
	}

/*
Destructor
*/	
CMessageHandler::~CMessageHandler()
	{
	__FLOG(_L8("CMessageHandler::~CMessageHandler - Entry"));
	delete iQueryHandler;
	delete iResponseHandler;
	delete iAdvertizeHandler;
	delete iRecieveSocket;
	TRAPD(err,iDnsCache->DumpCacheL());
	delete iDnsCache;
	delete iPacket;
	delete iSendMessageQueue;
	delete iDummyhandler;
	__FLOG(_L8("CMessageHandler::~CMessageHandler - Exit"));
	__FLOG_CLOSE;
	}
/**
This method parse the packet and dispatch the packet for handling it based on the operation requested.
from the header
@param aData packet read from the mdns port
@param aAddr address from which the packet is recieved
@param length lenght of the data recieved
@return void
*/	
void CMessageHandler::HandleIncomingPacketL(TDesC8& aData, const TSockAddr& aAddr, TInt /*length*/)
	{
	__FLOG(_L8("CMessageHandler::HandleIncomingPacketL - Entry"));    
	CDnsMessageComposerParser* comPos = CDnsMessageComposerParser::NewL();	
	CleanupStack::PushL(comPos);
	CDnsMessage* message = comPos->ParseMessageL(aData);
	CleanupStack::PushL(message);
	CBaseHandler& iOperationHandler = GetHandlerL(*message);
	iOperationHandler.HandleIncomingPacketL(*message ,aAddr);	
	CleanupStack::PopAndDestroy(message);//comPos and message
	CleanupStack::PopAndDestroy(comPos);
	__FLOG(_L8("CMessageHandler::HandleIncomingPacketL - Exit"));
	}

/**
This is a factory method which reads the packet and returns the handle to either
response or query handler
@param aMessage Dnspacket to read the header and to constructthe appropriate handler.
@return Poointer to CBaseHandler --base class to both response and query handler.
*/ 
CBaseHandler& CMessageHandler::GetHandlerL(CDnsMessage& aMessage)
	{
	__FLOG(_L8("CMessageHandler::GetHandlerL - Entry"));
	TDnsHeader header = aMessage.Header();
	//
	if(header.IsQuery() && !header.IsAuthoritative())
		{
		return 	*iQueryHandler;
		}
	else if(header.IsAuthoritative())
		{
		return *iResponseHandler;
		}
	else 
		{
		return *iDummyhandler;	
		}	
	__FLOG(_L8("CMessageHandler::GetHandlerL - Exit"));		
	}
/**
@return return a reference to CacheManager
*/
MDNSCacheMgr& CMessageHandler::DnsCache() const
	{
	__FLOG(_L8("CMessageHandler::DnsCache -Entry Exit"));
     return *iDnsCache;		
	}

/*
 * Routes the query sent by the client to query handler to handle it.
 * @param aMessage Pointer to a message object ;contains the query.
 * @param aHandle session id which generated the query.
 */
void CMessageHandler::ServiceClientQueryL(CDnsMessage* aMessage,TInt aHandle)
	{
	__FLOG(_L8("CMessageHandler::ServiceClientQueryL - Entry"));
	iQueryHandler->ServiceClientQueryL(aMessage, aHandle);
	__FLOG(_L8("CMessageHandler::ServiceClientQueryL - Exit"));
	}
	
/*
 * returns the pointer to the messagequeue.
 */
CSendMessageQueue& CMessageHandler::MessageQueue()const
	{
	__FLOG(_L8("CMessageHandler::MessageQueue -Entry Exit"));
	return *iSendMessageQueue;	
	}

/*
 * Notify the server after the query has been handled.
 * @param aClientHandle SessionId which had sent the query.
 */
void CMessageHandler::NotifyClientQuery(TInt aClientHandle)
	{
	__FLOG(_L8("CMessageHandler::NotifyClientQuery - Entry"));
	iServer.NotifyClientQuery(aClientHandle);	
	__FLOG(_L8("CMessageHandler::NotifyClientQuery - Exit"));
	}
	
/*
 * Route an internal query to the query handler
 * @param aMessage pointer to the dnsmeesage containg the query.
 * @param Observer to which successfull delivery of packet to be notified.
 */
void CMessageHandler::SendQueryL(CDnsMessage* aMessage, MMessageHandler& aObserver)
	{
	__FLOG(_L8("CMessageHandler::SendQueryL - Entry"));
	iQueryHandler->SendQueryL(aMessage, aObserver);	
	__FLOG(_L8("CMessageHandler::SendQueryL - Exit"));
	}
/*
 * Route the packet to be advertised to the adveritser.
 * @param aData array of CDnsresourceData to be advertised.
 * @param aSessionId session which adveritised the packet.
 */			
void CMessageHandler::AdvertizePacketL(const RPointerArray<CDnsResourceData> aData, TInt aSessionId,TBool aIsUpdate)
    {
    __FLOG(_L8("CMessageHandler::AdvertizePacketL - Entry"));
    iAdvertizeHandler->AdvertizePacketL(aData, aSessionId,aIsUpdate);
    __FLOG(_L8("CMessageHandler::AdvertizePacketL - Exit"));
    }

/*
 * Notify the server when a new service is published
 * @param aName name of the service published
 * inacase of autoresolve name will be the new published name.
 * @param aError will be the result of publish.ESuccess if successfull and E*Conflict.
 * @param aSessionId session which initaiated publish.
 * 
 */
void CMessageHandler::NotifyServicePublishL(const RBuf8& aName,TInt aError, TInt aSessionId)
    {
    __FLOG(_L8("CMessageHandler::NotifyServicePublishL - Entry"));
    iServer.NotifyServicePublishL(aName,aError, aSessionId);
    __FLOG(_L8("CMessageHandler::NotifyServicePublishL - Exit"));
    }
    
/*
 * @param aProbing ETrue if hostprobing in progress.
 */
void CMessageHandler::SetStateHostProbing(TBool aProbing)
    {
    __FLOG(_L8("CMessageHandler::SetStateHostProbing - Entry"));
    iServer.SetStateHostProbing(aProbing);
    __FLOG(_L8("CMessageHandler::SetStateHostProbing - Exit"));
    }

/* 
 * notify the server when a new service has been published in the network
 * @param aName array of new service published , for the servcetype client has requested.
 */
void CMessageHandler::NotifyNewServiceL(const RArray<RBuf8>& aName)
    {
    __FLOG(_L8("CMessageHandler::NotifyNewServiceL - Entry"));
    iServer.NotifyNewServiceL(aName);
    __FLOG(_L8("CMessageHandler::NotifyNewServiceL - Exit"));
    }

CMdnsServer& CMessageHandler::Server()
    {
    return iServer; 
    }
