diff -r 000000000000 -r af10295192d8 networkprotocols/dnsproxy/dnsproxyserver/src/dnsproxyqryhandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkprotocols/dnsproxy/dnsproxyserver/src/dnsproxyqryhandler.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,573 @@ +// 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: +// @internalTechnology +// + + + +#include "dnsproxyengine.h" +#include "dnsproxyqryhandler.h" +#include "dnsproxyservconf.h" +#include "dnsproxylistener.h" +#include "dnsproxymsgproc.h" +#include "dnsproxylog.h" +#include + +// Creates an instance of query handlers +CDnsProxyQueryHandler* CDnsProxyQueryHandler::NewL(CDnsProxyEngine& aEngine, CDnsProxyListener& aListener) +/** + * This is the method to create an instance of CDnsProxyQueryHandler + * @param aEngine + * + * @internalTechnology +*/ + { + CDnsProxyQueryHandler* gResolver = new(ELeave)CDnsProxyQueryHandler(aEngine, aListener); + gResolver->ResetServerCount(); + gResolver->iCurrentUplink = 0; + return gResolver; + } + +CDnsProxyQueryHandler::CDnsProxyQueryHandler(CDnsProxyEngine& aEngine, CDnsProxyListener& aListener):CActive(EPriorityStandard),iTimeout(TQueryTimeoutLinkage::TimeoutL),iProxyEngine(aEngine),iListener(aListener) +/** + * Constructor and adds active object into active scheduler + * @param aEngine - reference to CDnsProxyEngine + * + * @internalTechnology + **/ + { + CActiveScheduler::Add(this); + } + +/* + * destructor and releases all the resources + * */ +CDnsProxyQueryHandler::~CDnsProxyQueryHandler() +/** + * Destructor method cancel any pending operations and closes socket. + * + * @internalTechnology + **/ + { + Cancel(); + DeActivateSocket(); + } + + +//Invoked when request completes +/* + * This function RunL will be invoked whenever request completes + * + * */ +void CDnsProxyQueryHandler::RunL() +/** + * RunL of this active object is invoked when any pending read/write finishes. + * + * @internalTechnology + **/ + { + __LOG3("CDnsProxyQueryHandler(%x)::RunL() Status(%d) and State(%d)", this, iStatus.Int(), GetActiveObjectState()) + if(iStatus.Int() == KErrNone) + { + if(GetActiveObjectState() == EInit) + { + SetTimer(iProxyEngine.GetConfig().iTimerVal); + RunReader(); + } + else if(GetActiveObjectState() == EComplete) + { + SetActiveObjectState(EInit); + CancelTimer(); + SetQHandlerState(EFalse); + iQueryContext->SetQueryState(EResolved); + iQueryContext->SetDnsReplyMessage(iReply); + iProxyEngine.GetProxyListener()->SendTo(iQueryContext); + //Query Finished from Handler Perspective + QueryDone(); + //Process Next Query + ProcessNextQueryL(); + } + } + else + { + //Delete the Query context under processing + iListener.DeleteQCtxFromListL(iQueryContext); + //Complete the query + QueryDone(); + //Process Next Query + ProcessNextQueryL(); + } + } + +void CDnsProxyQueryHandler::ProcessQueryL() +/** + * This function gets called from the listener to start processing the query once + * it is assigned to the query handler. + * The function builds the dns server list, if there is not existing one.In case there + * are no DNS servers available/configured on the interfaces it sends DNS server failure + * as there is no uplink available. + * In case server count is zero or we are finished with all the configured servers + * reset the server count and send dns server failure message. + * Also check if there is anything else pending in the queue for processing. + * + * @internalTechnology + **/ + { + /** + * Build the server list here. This gives available DNS server addresses on the + * already up interfaces. + */ + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL Entry") + + if(iListener.GetConfiguredUplinkIap() != KErrNone) + { + //No Uplink available, hence send Dns server failure message + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL :No Uplink Available") + SendDnsFailureL(); + return; + } + + TInt count = iProxyEngine.iProxyServer->GetServerCount(); + if((count == 0) || (iListener.GetUplinkIap() != iCurrentUplink)) + { + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL Server Count is Zero") + iCurrentUplink = iListener.GetUplinkIap(); + iProxyEngine.iProxyServer->BuildGlobalDnsServerListL(iCurrentUplink); + count = iProxyEngine.iProxyServer->GetServerCount(); + __LOG1("\n CDnsProxyQueryHandler::ProcessQueryL Server Count is :%d", count) + } + //In case count is greater than zero do further processing else send dns failure message + if (count > 0) + { + TDnsServerInfo* info = NULL; + do + { + //Get DNS server information from the list + info = iProxyEngine.iProxyServer->GetDnsServerInfo(iCurServer); + + //coverity[new_values] + if(info) + { + //Set Uplink connection information in context + iListener.SetUplinkConnectionInfo(info->iConnInfo); + //Attach to given Uplink information + TInt err = iListener.ActivateUplink(); + if(err == KErrNone) + { + //Activate the socket function + ActivateSocketL(); + //Send Query to Dns server address + SendQuery(info->iAddr); + } + else + { + //In case uplink is down, send Dns failure + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL Unable to activate uplink") + SendDnsFailureL(); + } + break; + } + else + { + //Loop through the available list + iCurServer++; + if(iCurServer == count) + { + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL Invalid Uplinks") + ResetServerCount(); + SendDnsFailureL(); + } + + } + } + //coverity[dead_error_line] + //coverity[dead_error_condition] + while(info != NULL && iCurServer < count); + } + else + { + //No Uplink available, hence send Dns server failure message + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL :No Uplink Available") + SendDnsFailureL(); + } + __LOG("\n CDnsProxyQueryHandler::ProcessQueryL Exit") + } + +//Method to cancel outstanding request of the active object +void CDnsProxyQueryHandler::DoCancel() +/** + * This method is an implementation of DoCancel method of an active object + * Cancels pending read/ write operations and cancel the timer if active. + * + * @internalTechnology + **/ + { + if (GetQHandlerState() != EFalse) + { + if(GetActiveObjectState() == EInit) + { + iSocket.CancelSend(); + } + else + { + CancelTimer(); + iSocket.CancelRecv(); + } + } + } + + +void CDnsProxyQueryHandler::CancelTimer() +/** + * This method cancels the timer if already active and gets called from DoCancel method. + * Also it resets the timer count. + * + * @internalTechnology + **/ + { + if(iTimeout.IsActive()) + { + iTimeout.Cancel(); + } + iTimerCount = 0; //ReInitialize the Timer Count + + } + +void CDnsProxyQueryHandler::SetQueryContext(TQueryContext* aQueryContext) +/** + * This method sets the query context to be processes for this query handler. + * + * @internalTechnology + **/ + { + iQueryContext = aQueryContext; + } + +void CDnsProxyQueryHandler::SetTimer(TUint aTime) +/** + * This method sets the timer for the query whose response is pending. + * @param aTime - the value of timer + * + * @internalTechnology + **/ + { + + iTimeout.Set(iProxyEngine.GetProxyListener()->iTimer,aTime); + + } + +TBool CDnsProxyQueryHandler::GetQHandlerState() +/** + * This method gets the current state of query handler. + * + * @internalTechnology + **/ + { + return iQueryHandlerStatus; + } + + +void CDnsProxyQueryHandler::SetQHandlerState(TBool aQueryHandlerStatus) +/** + * This method sets the current state of query handler. + * @param aQueryHandlerStatus - New state + * + * @internalTechnology + **/ + { + iQueryHandlerStatus = aQueryHandlerStatus; + } + +/* + * Sets the time out value to specified object + * @param aNow - time out value + * */ +void CDnsProxyQueryHandler::TimeoutL(const TTime& /*aNow*/) +/** + * Sets the time out value to specified object + * @param aNow - time out value + * + * @internalTechnology + **/ + { + __LOG1("CDnsProxyQueryHandler(%x)::TimeoutL:Query Timed Out", this) + + // If already active cancel any pending request. + Cancel(); + + //Compare the timer count with the configured retry count + if(iTimerCount < iProxyEngine.GetConfig().iRetryCount) + { + //Set active object state to Init + SetActiveObjectState(EInit); + // increment timer(retry count) count + iTimerCount++; + // Move to next server in the list + iCurServer++; + //Process the query again. + ProcessQueryL(); + } + else + { + //See if next query available in the queue to handle and deletes + // the query handler + QueryDone(); + //Delete the Query context under processing + iListener.DeleteQCtxFromListL(iQueryContext); + //Process Next Unassigned query in the list if any + ProcessNextQueryL(); + } + } + +void CDnsProxyQueryHandler::ProcessNextQueryL() +/** + * The method fetches next available query context in the list for processing. + * and starts processing the same. + * @param None + * + * @internalTechnology + **/ + { + __LOG1("CDnsProxyQueryHandler(%x)::ProcessNextQueryL() Entry", this) + TQueryContext *qCtx = iListener.GetQCtxFromList(EUnAssigned); + + if((qCtx != NULL) && (qCtx->GetGlobalScope() == 1)) + { + //Set the query state to assigned from unassigned. + qCtx->SetQueryState(EAssigned); + //Set query context for the Qhandler + SetQueryContext(qCtx); + //Process Query Context + ProcessQueryL(); + } + __LOG1("CDnsProxyQueryHandler(%x)::ProcessNextQueryL() Exit", this) + + } + +void CDnsProxyQueryHandler::ActivateSocketL() +/** + * The method closes the socket if already open. It then opens the socket and binds + * the same to new random port. The query handler status is ETRUE which means it's + * processing the query. + * + * + * @internalTechnology + **/ + { + __LOG1("CDnsProxyQueryHandler(%x)::ActivateSocketL() Entry", this) + if(iActiveStatus == EFalse) + { + iActiveStatus = ETrue; + SetQHandlerState(ETrue); + User::LeaveIfError(iSocket.Open(iProxyEngine.GetSocketServer(), KAfInet, KSockDatagram, KProtocolInetUdp,iListener.GetUplinkConnHandle())); + BindRandomPort(); + } + __LOG1("CDnsProxyQueryHandler(%x)::ActivateSocketL() Exit", this) + } + +void CDnsProxyQueryHandler::DeActivateSocket() +/** + * The method closes the socket if already open. + * + * @internalTechnology + **/ + { + __LOG2("CDnsProxyQueryHandler(%x)::DeActivateSocketL() Entry, Active Status(%d)", this, iActiveStatus) + if(iActiveStatus) + { + iSocket.CancelSend(); + iSocket.CancelRecv(); + iSocket.Close(); + iActiveStatus = EFalse; + } + __LOG2("CDnsProxyQueryHandler(%x)::DeActivateSocketL() Exit, Active Status(%d)", this, iActiveStatus) + } + +void CDnsProxyQueryHandler::SendQuery(TInetAddr& aServerAddress) +/** + * The method sends the query under processing to the external DNS server. + * @param aServerAddress -Address of the DNS server to which query needs to be send + * + * @internalTechnology + **/ + { + __LOG1("CDnsProxyQueryHandler(%x)::SendQuery() Entry", this) + if(IsActive()) + { + __LOG1("CDnsProxyQueryHandler(%x)::SendQuery() is already active", this) + return; + } + + SetActiveObjectState(EInit); + TPtrC8 msg = iQueryContext->GetDnsQueryMessage(); + iSocket.SendTo(msg,aServerAddress,0,iStatus); + SetActive(); + __LOG1("CDnsProxyQueryHandler(%x)::SendQuery() Exit", this) + } + +void CDnsProxyQueryHandler::SendDnsFailureL() +/** + * The method sends the DNS server failure to the querying host. + * @param none + * + * @internalTechnology + **/ + { + __LOG1("CDnsProxyQueryHandler(%x)::SendDnsFailureL() Entry", this) + TBuf8 buf = iQueryContext->GetDnsQueryMessage(); + TMsgBuf &msgbuf = TMsgBuf::Cast(buf); + + iListener.GetMessageProc().GetDnsFailureMessage(msgbuf); + + SetQHandlerState(EFalse); + iQueryContext->SetQueryState(EResolved); + iQueryContext->SetDnsReplyMessage(msgbuf); + + iProxyEngine.GetProxyListener()->SendTo(iQueryContext); + //Query Finished from Handler Perspective + QueryDone(); + //Process Next Query + ProcessNextQueryL(); + __LOG1("CDnsProxyQueryHandler(%x)::SendDnsFailureL() Exit", this) + } + +void CDnsProxyQueryHandler::QueryDone() +/** + * The method resets the Queryhandler. + * + * @internalTechnology + **/ + + { + __LOG1("CDnsProxyQueryHandler(%x)::QueryDone() Entry", this) + Cancel(); + + //Cancels timer if active + CancelTimer(); + //Deactivates socket + DeActivateSocket(); + iListener.DeActivateUplink(); + ResetSockActiveStatus(); + ResetServerCount(); + ResetTimerCount(); + SetQueryContext(NULL); + SetActiveObjectState(EInit); + //Set QHandler state to False which means it is available for processing next + SetQHandlerState(EFalse); + __LOG1("CDnsProxyQueryHandler(%x)::QueryDone() Exit", this) + + } + +void CDnsProxyQueryHandler::RunReader() +/** + * The method initiates receive request for reading DNS response. + * + * @internalTechnology + **/ + { + __LOG1("CDnsProxyQueryHandler(%x)::RunReader() Entry", this) + // If already active then return + TBool is_active = IsActive(); + if(is_active) + { + return; + } + + // Set socket status to Ecomplete. + SetActiveObjectState(EComplete); + + iSocket.RecvFrom(iReply,iFrom,0,iStatus); + SetActive(); // Set the active object to active. + __LOG1("CDnsProxyQueryHandler(%x)::RunReader() Exit", this) + } + +void CDnsProxyQueryHandler::BindRandomPort() +/** + * This method generates the random port number and binds the socket to it. + * This function will be removed as it can be left to TCP/IP stack itself. + * + * @internalTechnology + * */ + { + TInt64 seed =0; + TInt err = 0; + TInt min_num = 1100; //because standard port number range is:1 to 1024 + TInt max_min = 65500; + TTime time; + TInt64 iRandom_port; + + do + { + time.UniversalTime(); + seed = time.Int64(); + + TInt port_num = Math::Rand(seed); + TInt res = max_min - min_num; + TInt val = port_num % res; //if it fails then use min_num instead res + iRandom_port = val+min_num; + + TInetAddr inetaddr2; + inetaddr2.SetPort(iRandom_port); + + err = iSocket.Bind(inetaddr2); + }while(err!=KErrNone); + } + +TInt CDnsProxyQueryHandler::RunError(TInt aErr) +/** + * This method implements RunError method of an active object. This helps in debugging. + * + * @internalTechnology + * */ + { + __LOG2("CDnsProxyQueryHandler(%x)::RunError %d", this, aErr) + if(iQueryContext) + { + //Delete the Query context under processing + TRAPD(err,iListener.DeleteQCtxFromListL(iQueryContext)); + __LOG1("DeleteQCtxFromListL::RunError %d",err) + } + //Complete the query + QueryDone(); + //Flush all the queries in queue + iListener.DeleteAllQCtxFromList(); + + return KErrNone; + } + +TStatus CDnsProxyQueryHandler::GetActiveObjectState() +/** + * This method returns the state of the object + * @param None + * @return None + * + * @internalTechnology + * */ + { + return iSocketStatus; + + } + +void CDnsProxyQueryHandler::SetActiveObjectState(TStatus aState) +/** + * This method returns the state of the object + * @param None + * @return None + * + * @internalTechnology + * */ + { + iSocketStatus = aState; + + }