Committing ZeroConf for 10.1 to the FCL.
/*
* Copyright (c) 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:
*
*/
#include "cdnsmessagecomposerparser.h"
#include "cdnsmsgbuf.h"
#include "cdnspacket.h"
__FLOG_STMT(_LIT8(KSubsys,"Dns Message Composer Parser");)
__FLOG_STMT(_LIT8(KComponent,"DnsMessage");)
CDnsMessageComposerParser::CDnsMessageComposerParser()
{
}
EXPORT_C CDnsMessageComposerParser* CDnsMessageComposerParser::NewL()
{
CDnsMessageComposerParser* self= new(ELeave)CDnsMessageComposerParser;
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
CDnsMessageComposerParser::~CDnsMessageComposerParser()
{
iBuf.Close();
delete iPacket;
delete iMsgBuf;
__FLOG(_L8("-> Composer Parser destroyed"));
__FLOG_CLOSE;
}
void CDnsMessageComposerParser::ConstructL()
{
__FLOG_OPEN(KSubsys, KComponent);
__FLOG(_L8("-> Composer parser created"));
}
/**
Composes mdns message
@param aMessage
@param aType RR type
@param aUnicast
@return iBuf composed dns buffer
*/
EXPORT_C void CDnsMessageComposerParser::CreateMessageL(RBuf8& aMessageBuffer, const CDnsMessage& aMessage )
{
__FLOG(_L8("-> Composing Dns Message"));
aMessageBuffer.CreateL(GetLength(aMessage));
iMsgBuf = CDnsMsgBuf::NewL(aMessageBuffer);
const TDnsHeader& header = aMessage.Header();
iMsgBuf->SetInt16(header.Id());
iMsgBuf->SetInt16(header.Flags());
const RPointerArray<CDnsQuestion>& quesList = aMessage.Queries();
const RPointerArray<CDnsResourceData>& ansList = aMessage.Answers();
const RPointerArray<CDnsResourceData>& authList= aMessage.Authorities();
const RPointerArray<CDnsResourceData>& additionalList = aMessage.Additional();
iMsgBuf->SetInt16(quesList.Count());
iMsgBuf->SetInt16(ansList.Count());
iMsgBuf->SetInt16(authList.Count());
iMsgBuf->SetInt16(additionalList.Count());
TInt i;
for(i=0; i<quesList.Count(); i++ )
{
CDnsQuestion* ques = quesList[i];
iMsgBuf->SetDomainNameL(ques->Name());
iMsgBuf->SetInt16(ques->Type());
iMsgBuf->SetInt16(ques->Class());
}
// add answer section
for(i=0; i<ansList.Count(); i++ )
{
AppendResourceRecordsL(ansList[i]);
}
// add authority section
for(i=0; i<authList.Count(); i++ )
{
AppendResourceRecordsL(authList[i]);
}
// add additional section
for(i=0; i<additionalList.Count(); i++ )
{
AppendResourceRecordsL(additionalList[i]);
}
aMessageBuffer.SetLength(GetLength(aMessage));
}
/**
Parses the raw dns packet
@param aBuf
@return dnsMessage Dns Message Structure
*/
EXPORT_C CDnsMessage* CDnsMessageComposerParser::ParseMessageL(const TDesC8& aBuf)
{
__FLOG(_L8("-> Parsing Dns Raw Buffer"));
iBuf.CreateL(aBuf);
iPacket = CDnsPacket::NewL(iBuf.LeftTPtr(iBuf.Length()));
const TDnsHeader& header = iPacket->GetHeaderL();
CDnsMessage* dnsMessage = CDnsMessage::NewL(header.Id(),header.IsQuery());
CleanupStack::PushL(dnsMessage);
dnsMessage->SetHeader(header);
TInt i;
// extract the query section;
for(i=0; i<header.QueryCount(); i++)
{
__FLOG(_L8("-> Retrieving Query Section"));
RBuf8 domainName;
domainName.CreateL(KMaxDNSNameLength);
iPacket->GetDomainNameL(domainName);
CDnsQuestion* question = CDnsQuestion::NewL();
CleanupStack::PushL(question);
question->SetNameL(domainName);
question->SetType(iPacket->GetInt16L());
question->SetClass(iPacket->GetInt16L());
domainName.Close();
dnsMessage->AppendQueryL(question);
CleanupStack::Pop(question);
}
// extract the answer section
for(i=0; i<header.AnswerCount(); i++)
{
__FLOG(_L8("-> Retrieving Answer Section"));
CDnsResourceData* resourceRecord = GetResourceRecordsL();
CleanupStack::PushL(resourceRecord);
dnsMessage->AppendAnswerL(resourceRecord);
CleanupStack::Pop(resourceRecord);
}
// extract the authority section
for(i=0; i<header.AuthorityNSCount(); i++)
{
__FLOG(_L8("-> Retrieving Authority NS Section"));
CDnsResourceData* resourceRecord = GetResourceRecordsL();
CleanupStack::PushL(resourceRecord);
dnsMessage->AppendAuthorityL(resourceRecord);
CleanupStack::Pop(resourceRecord);
}
// extract the additional section
for(i=0; i<header.AdditionalRCount(); i++)
{
__FLOG(_L8("-> Retrieving Additional Record Section"));
CDnsResourceData* resourceRecord = GetResourceRecordsL();
CleanupStack::PushL(resourceRecord);
dnsMessage->AppendAdditionalL(resourceRecord);
CleanupStack::Pop(resourceRecord);
}
CleanupStack::Pop(dnsMessage);
return dnsMessage;
}
CDnsResourceData* CDnsMessageComposerParser::GetResourceRecordsL()
{
__FLOG(_L8("-> Retrieving Resource Records"));
RBuf8 name;
name.CreateL(KMaxDNSNameLength);
iPacket->GetDomainNameL(name);
TUint16 type = iPacket->GetInt16L();
TUint16 classType = iPacket->GetInt16L();
TUint32 ttl = iPacket->GetInt32L();
TUint16 rdLength = iPacket->GetInt16L();
CDnsResourceData* resourceData = NULL;
switch(type)
{
case EDnsType_A : // A record
{
TInetAddr addr;
addr.SetAddress(iPacket->GetInt32L());
CRdTypeA* addrRecord = CRdTypeA::NewL();
CleanupStack::PushL(addrRecord);
addrRecord->SetNameL(name);
addrRecord->SetType(type);
addrRecord->SetClass(classType);
addrRecord->SetTtl(ttl);
addrRecord->SetRdLength(rdLength);
addrRecord->SetAddr(addr);
CleanupStack::Pop(addrRecord);
resourceData = addrRecord;
}
break;
case EDnsType_PTR: // PTR record
{
RBuf8 ptrDomainName;
ptrDomainName.CreateL(KMaxDNSNameLength);
iPacket->GetRdDomainNameL(ptrDomainName,rdLength);
CRdTypePtr* ptrRecord = CRdTypePtr::NewL();
CleanupStack::PushL(ptrRecord);
ptrRecord->SetNameL(name);
ptrRecord->SetType(type);
ptrRecord->SetClass(classType);
ptrRecord->SetTtl(ttl);
ptrRecord->SetRdLength(rdLength);
ptrRecord->SetDomainNameL(ptrDomainName);
ptrDomainName.Close();
CleanupStack::Pop(ptrRecord);
resourceData = ptrRecord;
}
break;
case EDnsType_SRV: // SRC record
{
TUint16 priority = iPacket->GetInt16L();
TUint16 weight = iPacket->GetInt16L();
TUint16 port = iPacket->GetInt16L();
RBuf8 srvDomainName;
srvDomainName.CreateL(KMaxDNSNameLength);
TInt length1 = sizeof(priority);
TInt length2 = sizeof(weight);
TInt length3 = sizeof(port);
TInt length = length1+length2+length3; // 6 = sizeof( prio + weight + port )
iPacket->GetRdDomainNameL(srvDomainName,rdLength - length);
CRdTypeSrv* srvRecord = CRdTypeSrv::NewL();
CleanupStack::PushL(srvRecord);
srvRecord->SetNameL(name);
srvRecord->SetType(type);
srvRecord->SetClass(classType);
srvRecord->SetTtl(ttl);
srvRecord->SetRdLength(rdLength);
srvRecord->SetPriority(priority);
srvRecord->SetWeight(weight);
srvRecord->SetPort(port);
srvRecord->SetTargetL(srvDomainName);
srvDomainName.Close();
CleanupStack::Pop(srvRecord);
resourceData = srvRecord;
}
break;
case EDnsType_TXT: // TXT record
{
TInt strLength = 0;
CRdTypeTxt* txtRecord = CRdTypeTxt::NewL();
CleanupStack::PushL(txtRecord);
txtRecord->SetNameL(name);
txtRecord->SetType(type);
txtRecord->SetClass(classType);
txtRecord->SetTtl(ttl);
txtRecord->SetRdLength(rdLength);
while(rdLength)
{
RBuf8 txtString;
strLength = iPacket->GetCharL();
rdLength--;
txtString.CreateL(strLength);
iPacket->GetStringL(txtString,strLength);
rdLength -= strLength;
txtRecord->AppendTextDataL(txtString);
}
CleanupStack::Pop(txtRecord);
resourceData = txtRecord;
}
break;
default:
//User::Leave(KErrCorrupt);
break;
}
name.Close();
return resourceData;
}
void CDnsMessageComposerParser::AppendResourceRecordsL( CDnsResourceData* aResourceRecord )
{
__FLOG(_L8("-> Adding Resource Records to buffer"));
iMsgBuf->SetDomainNameL(aResourceRecord->Name());
iMsgBuf->SetInt16(aResourceRecord->Type());
iMsgBuf->SetInt16(aResourceRecord->Class());
iMsgBuf->SetInt32(aResourceRecord->Ttl());
switch( aResourceRecord->Type())
{
case EDnsType_A: // A record
{
CRdTypeA* addrRecord = static_cast<CRdTypeA*>(aResourceRecord);
const TInetAddr& addr = addrRecord->Address();
iMsgBuf->SetInt16(4);
iMsgBuf->SetInt32(addr.Address());
}
break;
case EDnsType_PTR: // PTR record
{
CRdTypePtr* ptrRecord = static_cast<CRdTypePtr*>(aResourceRecord);
iMsgBuf->SetPtrRdLengthL(ptrRecord->DomainName());
iMsgBuf->SetDomainNameL(ptrRecord->DomainName());
}
break;
case EDnsType_SRV: // SRV record
{
CRdTypeSrv* srvRecord = static_cast<CRdTypeSrv*>(aResourceRecord);
iMsgBuf->SetSrvRdLengthL(srvRecord->Target());
iMsgBuf->SetInt16(srvRecord->Priority());
iMsgBuf->SetInt16( srvRecord->Weight());
iMsgBuf->SetInt16( srvRecord->Port());
iMsgBuf->SetDomainNameL(srvRecord->Target());
}
break;
case EDnsType_TXT: // TXT record
{
CRdTypeTxt* txtRecord = static_cast<CRdTypeTxt*>(aResourceRecord);
const RArray<RBuf8>& txtList = txtRecord->Text();
iMsgBuf->SetTxtRdLength(txtList);
for(TInt j=0; j<txtList.Count(); j++)
{
RBuf8 txt;
txt.CreateL(txtList[j]);
iMsgBuf->SetText(txt);
txt.Close();
}
}
break;
}
}
//Returns the size of the dns message
TUint16 CDnsMessageComposerParser::GetLength(const CDnsMessage& aMessage)const
{
return (aMessage.Size());
}