diff -r 78fbd574edf4 -r da856f45b798 zeroconf/server/src/cadvertizehandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zeroconf/server/src/cadvertizehandler.cpp Thu Jun 24 19:09:47 2010 +0530 @@ -0,0 +1,470 @@ +// 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: +// cadvertizehandler.cpp +// +// +/** +@file +@internalTechnology +*/ +//System include +#include + +//UserInclude +#include "cadvertizehandler.h" +__FLOG_STMT(_LIT8(KComponent,"MDNSServer");) + +/* + * Two phase constructor + * @param aMessagHandler areference to messagehandler object. + * @param aAutoResolveEnabled If true sercice name conflict will be handled. + * aAutoResolveEnabled is True by default + */ +CAdvertizeHandler* CAdvertizeHandler::NewL(CMessageHandler& aMessageHandler,TBool aAutoResolveEnabled) + { + CAdvertizeHandler* self = new (ELeave) CAdvertizeHandler(aMessageHandler,aAutoResolveEnabled); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +/* + * Destructor + */ +CAdvertizeHandler::~CAdvertizeHandler() + { + __FLOG(_L8("CAdvertizeHandler::~CAdvertizeHandler- Entry")); + iData.ResetAndDestroy(); + iData.Close(); + iName.Close(); + iProbeName.Close(); + iProbeType.Close(); + __FLOG(_L8("CAdvertizeHandler::~CAdvertizeHandler- Exit")); + __FLOG_CLOSE; + } +/* + * No incoming packet for this so no need to handle + */ +void CAdvertizeHandler::HandleIncomingPacketL(CDnsMessage& /*aMessage*/) + { + __FLOG(_L8("CAdvertizeHandler::HandleIncomingPacketL- Entry")); + //Nothing To Do ............ + __FLOG(_L8("CAdvertizeHandler::HandleIncomingPacketL- Exit")); + } + +static void CleanUpCache(TAny* aAny) + { + + //RPointerArray records = static_cast < RPointerArray > (*aAny); + RPointerArray * records = static_cast < RPointerArray *> (aAny); + records->ResetAndDestroy(); + records->Close(); + } +/* + * Constructor + * @param aMessageHandler reference to messagehandler + * @param aAutoResolveEnabled will be true by default ,if true servicename conflict + * will be handled by default + */ +CAdvertizeHandler::CAdvertizeHandler(CMessageHandler& aMessageHandler,TBool aAutoResolveEnabled):CBaseHandler(aMessageHandler) + { + __FLOG(_L8("CAdvertizeHandler::CAdvertizeHandler- Entry")); + iAutoResolveEnabled = aAutoResolveEnabled; + iCurrentProbeState = EIdle; + iProbeCounter = 0 ; + __FLOG(_L8("CAdvertizeHandler::CAdvertizeHandler- Exit")); + } + +/* + * Twophase constructor + */ +void CAdvertizeHandler::ConstructL() + { + __FLOG_OPEN(KMDNSSubsystem, KComponent); + __FLOG(_L8("CAdvertizeHandler::ConstructL- Entry")); + CBaseHandler::ConstructL(); + //Nothing + __FLOG(_L8("CAdvertizeHandler::ConstructL- Exit")); + } +/* + * Keeps a copy of the records to be published and starts the active object. + * @param aData an array of records to be published. + * @param aSessionId session id initiating the advertizement. + */ +void CAdvertizeHandler::AdvertizePacketL(const RPointerArray aData, TInt aSessionId,TBool aIsUpdate) + { + __FLOG(_L8("CAdvertizeHandler::AdvertizePacketL- Entry")); + iName.Close(); + iName.Create(aData[0]->Name()); + iProbeName.Close(); + iProbeName.CreateL(KMaxLength); + iProbeName.Append(iName); + iCurrentProbeState = EStart; + iData.ResetAndDestroy(); + for(TInt i =0 ; i= KMaxFailures) + { + //If Probe Failure rate is greater then 15 per second, wait for + //5 seconds before probing again + iProbeCounter = 0; + After(5*1000*1000); + } + } + else // to intimate server of failure + { + MessageHandler().NotifyServicePublishL(iName,EConflictWithoutAutoResolve,iSessionId); + } + + } + } + + switch(iCurrentProbeState) + { + case EIdle: + break;//Do Nothing + + case EStart: + { + currentTime.UniversalTime(); + TInt64 randseed = currentTime.Int64(); + + //Random time between 0 & 250 ms + TInt delay = Math::Rand(randseed) % 250; + iCurrentProbeState = EProbeFirstUnicast; + //Convert to microsecond + + After(delay*1000); + } + break; + + case EProbeFirstUnicast: + { + SendProbeL(ETrue); + iCurrentProbeState = EProbeSecondUnicast; + } + break; + + case EProbeSecondUnicast: + { + SendProbeL(ETrue); + iCurrentProbeState = EProbeMulticast; + } + break; + + case EProbeMulticast: + { + SendProbeL(EFalse); + iCurrentProbeState = EProbeComplete; + } + break; + + case EProbeComplete: + { + iCurrentProbeState = EFirstAnnouncement; + //Probe succeeded ,insert in cache + InsertInCache(); + After(KProbeDelay*1000); + //Some Delay ?? Required or defensive response HAS TO come within 750ms? + } + break; + + case EFirstAnnouncement: + { + SendAnnouncementL(); + iCurrentProbeState = ESecondAnnouncement; + //After(1000);// A Millisecond delay: Required?? + } + break; + + case ESecondAnnouncement: + { + SendAnnouncementL(); + iCurrentProbeState = EIdle; + } + break; + } + __FLOG(_L8("CAdvertizeHandler::RunL- Exit")); + } +/* + * Handles any leave in RunL + * @param aError error with which runL leaves. + */ +TInt CAdvertizeHandler::RunError(TInt aError) + { + __FLOG(_L8("CAdvertizeHandler::RunError- Entry")); + return aError; + } + +/* + * Self completes the request. + */ +void CAdvertizeHandler::Schedule() + { + __FLOG(_L8("CAdvertizeHandler::Schedule- Entry")); + TRequestStatus* status(&iStatus); + *status = KRequestPending; + SetActive(); + User::RequestComplete(status, KErrNone); + __FLOG(_L8("CAdvertizeHandler::Schedule- Exit")); + } + +/* + * Function will be called when there is a conflict. + * this will change the publishing name by appending a + * number at the end of it. + * @return iProbeCounter returns probecounter value. + */ +TInt CAdvertizeHandler::GenerateNonConflictingName() + { + __FLOG(_L8("CAdvertizeHandler::GenerateNonConflictingName- Entry")); + _LIT8(KDot,"."); + + RBuf8 oldName; + oldName.CreateL(iName); + + ++iProbeCounter; + TBuf8 newName; + iName.Close(); + iName.Create(KMaxLength); + iName.Append(iProbeName); + + TInt pos = iName.Locate('.'); + _LIT8(KOpenBrace,"("); + newName.Append(KOpenBrace); + newName.AppendNum(iProbeCounter); + _LIT8(KCloseBrace,")"); + newName.Append(KCloseBrace); + iName.Insert(pos,newName); + ChangeDomainL(oldName); + oldName.Close(); + __FLOG(_L8("CAdvertizeHandler::GenerateNonConflictingName- Exit")); + return iProbeCounter; + } + +/* + * Finds whether the service already exists in the network . + * If service is in the network ,same will be present in the cache. + * @return probFailed returns true if probe has failed. + */ +TBool CAdvertizeHandler::DefensiveResponseL() + { + __FLOG(_L8("CAdvertizeHandler::DefensiveResponseL- Entry")); + TBool probeFailed(EFalse); + RPointerArray entries; + CleanupStack::PushL(TCleanupItem(TCleanupOperation(&CleanUpCache),&entries)); + + _LIT8(KDot,"."); + TBuf8 buffer; + + buffer.Copy(iName); + buffer.Append(KDot); + MessageHandler().DnsCache().FindServiceL(entries,buffer,EDnsQType_Any); + if(entries.Count()>0) + { + probeFailed = ETrue; + } + CleanupStack::PopAndDestroy(); + //entries.ResetAndDestroy(); + //entries.Close(); + __FLOG(_L8("CAdvertizeHandler::DefensiveResponseL- Exit")); + return probeFailed; + } + +/* + * creates a DnsMessage object and send it to the messagehandler to handle it. + * @param aUnicast true if the packet to be sent is an unicast one;false for multicast. + * + */ +void CAdvertizeHandler::SendProbeL(TBool aUnicast) + { + __FLOG(_L8("CAdvertizeHandler::SendProbeL- Entry")); + //Construct DNS Message + CDnsMessage* message = CDnsMessage::NewL(0,ETrue); + CleanupStack::PushL(message); + + //Form the Query/Question part of the message + CDnsQuestion* question = CDnsQuestion::NewL(); + CleanupStack::PushL(question); + question->SetNameL(iName); + question->SetClass(EDnsClass_IN); + question->SetType(EDnsQType_Any); + if(aUnicast) + { + question->SetUnicast(ETrue); + } + + //Append the Query to the Message + message->AppendQueryL(question); + //Append to the Authoritative Section + for(TInt i =0 ; i < iData.Count();i++) + { + message->AppendAuthorityL(iData[i]->CloneL()); + } + + //Send the query + MessageHandler().SendQueryL(message,*this); + + CleanupStack::Pop();//question + CleanupStack::Pop();//message + __FLOG(_L8("CAdvertizeHandler::SendProbeL- Exit")); + } + +/* + * If probing is successfull ,new service record will + * be added to the cache using this. + */ +void CAdvertizeHandler::InsertInCache() + { + __FLOG(_L8("CAdvertizeHandler::InsertInCache- Entry")); + TBuf8 name; + _LIT8(KDot,"."); + //TODO name should be appended with dot + + for(TInt i =0 ; iName()); + name.Append(KDot); + iData[i]->SetNameL(name); + MessageHandler().DnsCache().UpdateCacheL(*(iData[i]),ETrue,iSessionId); + } + __FLOG(_L8("CAdvertizeHandler::InsertInCache- Exit")); + } + +/* + * Announces the new service. + */ +void CAdvertizeHandler::SendAnnouncementL() + { + __FLOG(_L8("CAdvertizeHandler::SendAnnouncementL- Entry")); + RPointerArray entries; + //An API in Cache Interface that returns a list of all Authoritative records + MessageHandler().DnsCache().AuthoritativeEntriesL(entries); + CDnsMessage* message = CDnsMessage::NewL(0,EFalse); + CleanupStack::PushL(message); + + TDnsHeader header(message->Header()); + header.SetAuthoritative(ETrue); + message->SetHeader(header); + + //Append to the Authoritative Section + for(TInt i =0 ; i < iData.Count();i++) + { + message->AppendAuthorityL(iData[i]->CloneL()); + } + +/* + for(TInt index =0; indexAddressRecord()) + message->AppendAnswerL(entry->AddressRecord()->CloneL()); + if(entry->ServiceRecord()) + message->AppendAnswerL(entry->ServiceRecord()->CloneL()); + if(entry->PtrRecord()) + message->AppendAnswerL(entry->PtrRecord()->CloneL()); + if(entry->TxtRecord()) + message->AppendAnswerL(entry->TxtRecord()->CloneL()); + + //should've been a new API sendresponse + + } +*/ + MessageHandler().SendQueryL(message,*this); + CleanupStack::Pop();//message + entries.ResetAndDestroy(); + entries.Close(); + __FLOG(_L8("CAdvertizeHandler::SendAnnouncementL- Exit")); + } +void CAdvertizeHandler::ChangeDomainL(TDesC8& aName) + { + for(TInt i =0 ; iName().Compare(aName) == 0) + { + iData[i]->SetNameL(iName); + } + if(iData[i]->Type()==EDnsType_PTR) + { + CRdTypePtr* ptr = static_cast(iData[i]); + if(ptr->DomainName().Compare(aName) == 0) + { + ptr->SetDomainNameL(iName); + } + + } + + } + }