/**************************************************************************** * * 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 /* * 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 CResolverResponseList; typedef TSingleList CNameserverList; typedef TSingleList 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 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 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 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 CAddrQueryTree; void WalkHostTree( AvlNode* pNode ); void WalkAddrTree( AvlNode* 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