]> git.mxchange.org Git - simgear.git/blob - simgear/io/DNSClient.cxx
Introduce SGBinaryFile
[simgear.git] / simgear / io / DNSClient.cxx
1 /**
2  * \file DNSClient.cxx - simple DNS resolver client engine for SimGear
3  */
4
5 // Written by James Turner
6 //
7 // Copyright (C) 2016 Torsten Dreyer - torsten (at) t3r (dot) de
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 // Library General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23
24 #include "DNSClient.hxx"
25 #include "udns.h"
26 #include <time.h>
27 #include <simgear/debug/logstream.hxx>
28
29 namespace simgear {
30
31 namespace DNS {
32
33 class Client::ClientPrivate {
34 public:
35     ClientPrivate() {
36         if (dns_init(NULL, 0) < 0)
37             SG_LOG(SG_IO, SG_ALERT, "Can't init udns library" );
38
39         if( dns_open(NULL) < 0 )
40             SG_LOG(SG_IO, SG_ALERT, "Can't open udns context" );
41     }
42
43     ~ClientPrivate() {
44         dns_close(NULL);
45     }
46 };
47
48 Request::Request( const std::string & dn ) :
49         _dn(dn),
50         _type(DNS_T_ANY),
51         _complete(false),
52         _timeout_secs(5),
53         _start(0)
54 {
55 }
56
57 Request::~Request()
58 {
59 }
60
61 bool Request::isTimeout() const
62 {
63     return (time(NULL) - _start) > _timeout_secs;
64 }
65
66 NAPTRRequest::NAPTRRequest( const std::string & dn ) :
67         Request(dn)
68 {
69     _type = DNS_T_NAPTR;
70 }
71
72 static bool sortNAPTR( const NAPTRRequest::NAPTR_ptr a, const NAPTRRequest::NAPTR_ptr b )
73 {
74     if( a->order > b->order ) return false;
75     if( a->order < b->order ) return true;
76     return a->preference < b->preference;
77 }
78
79 static void dnscbNAPTR(struct dns_ctx *ctx, struct dns_rr_naptr *result, void *data)
80 {
81     NAPTRRequest * r = static_cast<NAPTRRequest*>(data);
82     if (result) {
83         r->cname = result->dnsnaptr_cname;
84         r->qname = result->dnsnaptr_qname;
85         r->ttl = result->dnsnaptr_ttl;
86         for (int i = 0; i < result->dnsnaptr_nrr; i++) {
87             if( !r->qservice.empty() && r->qservice != result->dnsnaptr_naptr[i].service )
88                 return;
89
90             //TODO: case ignore and result flags may have more than one flag
91             if( !r->qflags.empty() && r->qflags != result->dnsnaptr_naptr[i].flags )
92                 return;
93
94             NAPTRRequest::NAPTR_ptr naptr(new NAPTRRequest::NAPTR);
95             r->entries.push_back(naptr);
96             naptr->order = result->dnsnaptr_naptr[i].order;
97             naptr->preference = result->dnsnaptr_naptr[i].preference;
98             naptr->flags = result->dnsnaptr_naptr[i].flags;
99             naptr->service = result->dnsnaptr_naptr[i].service;
100             naptr->regexp = result->dnsnaptr_naptr[i].regexp;
101             naptr->replacement = result->dnsnaptr_naptr[i].replacement;
102         }
103         std::sort( r->entries.begin(), r->entries.end(), sortNAPTR );
104         free(result);
105     }
106     r->setComplete();
107 }
108
109 void NAPTRRequest::submit()
110 {
111     if (!dns_submit_naptr(NULL, getDn().c_str(), 0, dnscbNAPTR, this )) {
112         SG_LOG(SG_IO, SG_ALERT, "Can't submit dns request for " << getDn());
113         return;
114     }
115     _start = time(NULL);
116 }
117
118
119 Client::~Client()
120 {
121 }
122
123 Client::Client() :
124     d(new ClientPrivate)
125 {
126 }
127
128 void Client::makeRequest(const Request_ptr& r)
129 {
130     r->submit();
131 }
132
133
134 void Client::update(int waitTimeout)
135 {
136     time_t now = time(NULL);
137     if( dns_timeouts( NULL, waitTimeout, now ) < 0 )
138         return;
139     dns_ioevent(NULL, now);
140 }
141
142 } // of namespace DNS
143
144 } // of namespace simgear