/****************************************************************************
*
* Copyright (C) 2000-2001 RealNetworks, Inc. All rights reserved.
*
* This program is free software. It may be distributed under the terms
* in the file LICENSE, found in the top level of the source distribution.
*
*/
#ifndef _RESOLVER_H
#define _RESOLVER_H
#include "types.h"
#include "ttree.h"
#include "str.h"
#include "sock.h"
#include "timer.h"
#include <string.h>
/*
* Locations found in the WinNT registry:
* \\HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\
* DhcpDomain
* DhcpNameServer
* Domain
* Nameserver
* Hostname
* SearchList
* (Win2000: also in Interfaces\*\ for each interface)
*/
class CResolverResponse
{
public:
virtual void GetHostDone( int err, const CString& strQuery, in_addr addrResult ) = 0;
virtual void GetHostDone( int err, in_addr addrQuery, const CString& strResult ) = 0;
};
class CResolver : public CTimerResponse,
public CStreamResponse
{
private: // Unimplemented
CResolver( const CResolver& );
CResolver& operator=( const CResolver& );
CResolver( void );
public:
virtual ~CResolver( void );
static CResolver* GetResolver( void );
bool GetHost( CResolverResponse* pResponse, const CString& strHost );
bool GetHost( CResolverResponse* pResponse, struct in_addr addr );
protected:
virtual void OnTimer( void );
virtual void OnConnectDone( int err );
virtual void OnReadReady( void );
virtual void OnWriteReady( void );
virtual void OnExceptReady( void );
virtual void OnClosed( void );
struct dns_hdr
{
UINT16 id;
UINT16 flags; // QR:1, OPCODE:4, AA:1, TC:1, RD:1, RA:1, Z:3, RCODE:4
UINT16 qdcnt;
UINT16 ancnt;
UINT16 nscnt;
UINT16 arcnt;
};
struct dns_qr_hdr
{
CString strHost;
UINT16 qtype;
UINT16 qclass;
};
struct dns_rr_hdr
{
UINT16 rtype;
UINT16 rclass;
UINT32 ttl;
UINT16 rdlen;
};
void SendQuery( const CSockAddr& addr, const CString& strHost, UINT16 qtype );
void AddHostEntry( time_t tExpire, const CString& strHost, struct in_addr addr );
void ReadConfig( void );
bool EncodeName( CPCHAR szName, PBYTE& rpbuf, size_t& rlen );
bool ParseQuestionHeader( dns_qr_hdr* phdr, const CBuffer& rbuf, size_t& rpos );
bool ParseAnswerHeader( dns_rr_hdr* phdr, const CBuffer& rbuf, size_t& rpos );
bool DecodeName( PCHAR pname, const CBuffer& rbuf, size_t& rpos );
protected:
typedef TSingleList<CResolverResponse*> CResolverResponseList;
typedef TSingleList<CSockAddr> CNameserverList;
typedef TSingleList<CString> CDomainList;
class CHostInfo
{
public:
CHostInfo( const CString& strName ) :
m_tExpire(0), m_strName(strName) { m_addr.s_addr = INADDR_NONE; }
CHostInfo( time_t tExpire, const CString& strName, struct in_addr addr ) :
m_tExpire(tExpire), m_strName(strName), m_addr(addr) {}
CHostInfo& operator=( const CHostInfo& other )
{
m_tExpire = other.m_tExpire;
m_strName = other.m_strName;
m_addr = other.m_addr;
return *this;
}
int operator==( const CHostInfo& other ) const { return ( strcasecmp( m_strName, other.m_strName ) == 0 ); }
int operator<( const CHostInfo& other ) const { return ( strcasecmp( m_strName, other.m_strName ) < 0 ); }
int operator>( const CHostInfo& other ) const { return ( strcasecmp( m_strName, other.m_strName ) > 0 ); }
time_t m_tExpire;
CString m_strName;
struct in_addr m_addr;
};
typedef AvlTree<CHostInfo> CHostInfoTree;
class CAddrInfo
{
public:
CAddrInfo( struct in_addr addr ) :
m_tExpire(0), m_addr(addr) {}
CAddrInfo( time_t tExpire, struct in_addr addr, const CString& strName ) :
m_tExpire(tExpire), m_addr(addr), m_strName(strName) {}
CAddrInfo& operator=( const CAddrInfo& other )
{
m_tExpire = other.m_tExpire;
m_addr = other.m_addr;
m_strName = other.m_strName;
return *this;
}
int operator==( const CAddrInfo& other ) const { return ( m_addr.s_addr == other.m_addr.s_addr ); }
int operator<( const CAddrInfo& other ) const { return ( m_addr.s_addr < other.m_addr.s_addr ); }
int operator>( const CAddrInfo& other ) const { return ( m_addr.s_addr > other.m_addr.s_addr ); }
time_t m_tExpire;
struct in_addr m_addr;
CString m_strName;
};
typedef AvlTree<CAddrInfo> CAddrInfoTree;
class CHostQuery
{
public:
CHostQuery(const CString& strHost) :
m_tExpire(0), m_tDelta(4), m_strHost(strHost), m_strFQDN(strHost) {}
void AddResponse( CResolverResponse* pResponse )
{ m_listResponses.InsertTail( pResponse ); }
//XXX: this is soooooo lame
CHostQuery( const CHostQuery& other )
{
m_tExpire = other.m_tExpire;
m_tDelta = other.m_tDelta;
m_strHost = other.m_strHost;
m_strFQDN = other.m_strFQDN;
m_itrDomain = other.m_itrDomain;
m_itrServer = other.m_itrServer;
CResolverResponseList::ConstIterator itr( other.m_listResponses.Begin() );
while( itr )
{
m_listResponses.InsertTail( *itr );
itr++;
}
}
CHostQuery& operator=( const CHostQuery& other )
{
while( ! m_listResponses.IsEmpty() ) m_listResponses.RemoveHead();
m_tExpire = other.m_tExpire;
m_tDelta = other.m_tDelta;
m_strHost = other.m_strHost;
m_strFQDN = other.m_strFQDN;
m_itrDomain = other.m_itrDomain;
m_itrServer = other.m_itrServer;
CResolverResponseList::ConstIterator itr( other.m_listResponses.Begin() );
while( itr )
{
m_listResponses.InsertTail( *itr );
itr++;
}
return *this;
}
int operator==( const CHostQuery& other ) const { return ( strcasecmp( m_strHost, other.m_strHost ) == 0 ); }
int operator<( const CHostQuery& other ) const { return ( strcasecmp( m_strHost, other.m_strHost ) < 0 ); }
int operator>( const CHostQuery& other ) const { return ( strcasecmp( m_strHost, other.m_strHost ) > 0 ); }
time_t m_tExpire;
time_t m_tDelta;
CString m_strHost;
CString m_strFQDN;
CDomainList::Iterator m_itrDomain;
CNameserverList::Iterator m_itrServer;
CResolverResponseList m_listResponses;
};
typedef AvlTree<CHostQuery> CHostQueryTree;
class CAddrQuery
{
public:
CAddrQuery( struct in_addr addr ) :
m_tExpire(0), m_tDelta(4), m_addr(addr) {}
void AddResponse( CResolverResponse* pResponse )
{ m_listResponses.InsertTail( pResponse ); }
//XXX: this is soooooo lame
CAddrQuery( const CAddrQuery& other )
{
m_tExpire = other.m_tExpire;
m_tDelta = other.m_tDelta;
m_addr = other.m_addr;
m_itrServer = other.m_itrServer;
CResolverResponseList::ConstIterator itr( other.m_listResponses.Begin() );
while( itr )
{
m_listResponses.InsertTail( *itr );
itr++;
}
m_addr = other.m_addr;
}
CAddrQuery& operator=( const CAddrQuery& other )
{
while( ! m_listResponses.IsEmpty() ) m_listResponses.RemoveHead();
m_tExpire = other.m_tExpire;
m_tDelta = other.m_tDelta;
m_addr = other.m_addr;
m_itrServer = other.m_itrServer;
CResolverResponseList::ConstIterator itr( other.m_listResponses.Begin() );
while( itr )
{
m_listResponses.InsertTail( *itr );
itr++;
}
return *this;
}
int operator==( const CAddrQuery& other ) const { return ( m_addr.s_addr == other.m_addr.s_addr ); }
int operator<( const CAddrQuery& other ) const { return ( m_addr.s_addr < other.m_addr.s_addr ); }
int operator>( const CAddrQuery& other ) const { return ( m_addr.s_addr > other.m_addr.s_addr ); }
time_t m_tExpire;
time_t m_tDelta;
struct in_addr m_addr;
CNameserverList::Iterator m_itrServer;
CResolverResponseList m_listResponses;
};
typedef AvlTree<CAddrQuery> CAddrQueryTree;
void WalkHostTree( AvlNode<CHostQuery>* pNode );
void WalkAddrTree( AvlNode<CAddrQuery>* pNode );
protected:
CUdpSocket m_sock;
CTimer m_timer;
UINT16 m_usQueryID;
CNameserverList m_listServers;
CDomainList m_listDomains;
CHostInfoTree m_treeHostInfo;
CAddrInfoTree m_treeAddrInfo;
CHostQueryTree m_treeHostQueries;
CAddrQueryTree m_treeAddrQueries;
static CResolver * m_pResolver;
};
#endif //ndef _RESOLVER_H
syntax highlighted by Code2HTML, v. 0.9.1