VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostDnsService.cpp@ 55457

Last change on this file since 55457 was 55278, checked in by vboxsync, 10 years ago

Main/HostDnsService: Poll for VBoxInternal2/HostDNSOrderIgnore global extradata change, at most every 30 seconds, and only if there is new DNS information. This helps greatly with enabling/disabling this feature, as previously one had to ensure that VBoxSVC was terminated/re-started.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/* $Id: HostDnsService.cpp 55278 2015-04-15 11:27:50Z vboxsync $ */
2/** @file
3 * Base class for Host DNS & Co services.
4 */
5
6/*
7 * Copyright (C) 2013-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <VBox/com/array.h>
19#include <VBox/com/ptr.h>
20#include <VBox/com/string.h>
21
22#include <iprt/cpp/utils.h>
23
24#include "Logging.h"
25#include "VirtualBoxImpl.h"
26#include <iprt/time.h>
27#include <iprt/thread.h>
28#include <iprt/semaphore.h>
29#include <iprt/critsect.h>
30
31#include <algorithm>
32#include <set>
33#include <string>
34#include "HostDnsService.h"
35
36
37static HostDnsMonitor *g_monitor;
38
39static void dumpHostDnsInformation(const HostDnsInformation&);
40static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&);
41
42
43bool HostDnsInformation::equals(const HostDnsInformation &info, bool fDNSOrderIgnore) const
44{
45 if (fDNSOrderIgnore)
46 {
47 std::set<std::string> l(servers.begin(), servers.end());
48 std::set<std::string> r(info.servers.begin(), info.servers.end());
49
50 return (l == r)
51 && (domain == info.domain)
52 && (searchList == info.searchList); // XXX: also ignore order?
53 }
54 else
55 {
56 return (servers == info.servers)
57 && (domain == info.domain)
58 && (searchList == info.searchList);
59 }
60}
61
62inline static void detachVectorOfString(const std::vector<std::string>& v,
63 std::vector<com::Utf8Str> &aArray)
64{
65 aArray.resize(v.size());
66 size_t i = 0;
67 for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it, ++i)
68 aArray[i] = Utf8Str(it->c_str());
69}
70
71struct HostDnsMonitor::Data
72{
73 Data(bool aThreaded)
74 : uLastExtraDataPoll(0),
75 fDNSOrderIgnore(false),
76 fThreaded(aThreaded),
77 virtualbox(NULL)
78 {}
79
80 std::vector<PCHostDnsMonitorProxy> proxies;
81 HostDnsInformation info;
82 uint64_t uLastExtraDataPoll;
83 bool fDNSOrderIgnore;
84 const bool fThreaded;
85 RTTHREAD hMonitoringThread;
86 RTSEMEVENT hDnsInitEvent;
87 VirtualBox *virtualbox;
88};
89
90struct HostDnsMonitorProxy::Data
91{
92 Data(const HostDnsMonitor *aMonitor, VirtualBox *aParent)
93 : info(NULL)
94 , virtualbox(aParent)
95 , monitor(aMonitor)
96 , fModified(true)
97 {}
98
99 virtual ~Data()
100 {
101 if (info)
102 {
103 delete info;
104 info = NULL;
105 }
106 }
107
108 HostDnsInformation *info;
109 VirtualBox *virtualbox;
110 const HostDnsMonitor *monitor;
111 bool fModified;
112};
113
114
115HostDnsMonitor::HostDnsMonitor(bool fThreaded)
116 : m(NULL)
117{
118 m = new HostDnsMonitor::Data(fThreaded);
119}
120
121HostDnsMonitor::~HostDnsMonitor()
122{
123 if (m)
124 {
125 delete m;
126 m = NULL;
127 }
128}
129
130const HostDnsMonitor *HostDnsMonitor::getHostDnsMonitor(VirtualBox *aParent)
131{
132 /* XXX: Moved initialization from HostImpl.cpp */
133 if (!g_monitor)
134 {
135# if defined (RT_OS_DARWIN)
136 g_monitor = new HostDnsServiceDarwin();
137# elif defined(RT_OS_WINDOWS)
138 g_monitor = new HostDnsServiceWin();
139# elif defined(RT_OS_LINUX)
140 g_monitor = new HostDnsServiceLinux();
141# elif defined(RT_OS_SOLARIS)
142 g_monitor = new HostDnsServiceSolaris();
143# elif defined(RT_OS_FREEBSD)
144 g_monitor = new HostDnsServiceFreebsd();
145# elif defined(RT_OS_OS2)
146 g_monitor = new HostDnsServiceOs2();
147# else
148 g_monitor = new HostDnsService();
149# endif
150 g_monitor->init(aParent);
151 }
152
153 return g_monitor;
154}
155
156void HostDnsMonitor::addMonitorProxy(PCHostDnsMonitorProxy proxy) const
157{
158 RTCLock grab(m_LockMtx);
159 m->proxies.push_back(proxy);
160 proxy->notify();
161}
162
163void HostDnsMonitor::releaseMonitorProxy(PCHostDnsMonitorProxy proxy) const
164{
165 RTCLock grab(m_LockMtx);
166 std::vector<PCHostDnsMonitorProxy>::iterator it;
167 it = std::find(m->proxies.begin(), m->proxies.end(), proxy);
168
169 if (it == m->proxies.end())
170 return;
171
172 m->proxies.erase(it);
173}
174
175void HostDnsMonitor::shutdown()
176{
177 if (g_monitor)
178 {
179 delete g_monitor;
180 g_monitor = NULL;
181 }
182}
183
184const HostDnsInformation &HostDnsMonitor::getInfo() const
185{
186 return m->info;
187}
188
189void HostDnsMonitor::setInfo(const HostDnsInformation &info)
190{
191 RTCLock grab(m_LockMtx);
192
193 pollGlobalExtraData();
194
195 if (info.equals(m->info))
196 return;
197
198 LogRel(("HostDnsMonitor: old information\n"));
199 dumpHostDnsInformation(m->info);
200 LogRel(("HostDnsMonitor: new information\n"));
201 dumpHostDnsInformation(info);
202
203 bool fIgnore = m->fDNSOrderIgnore && info.equals(m->info, m->fDNSOrderIgnore);
204 m->info = info;
205
206 if (fIgnore)
207 {
208 LogRel(("HostDnsMonitor: order change only, not notifying\n"));
209 return;
210 }
211
212 std::vector<PCHostDnsMonitorProxy>::const_iterator it;
213 for (it = m->proxies.begin(); it != m->proxies.end(); ++it)
214 (*it)->notify();
215}
216
217HRESULT HostDnsMonitor::init(VirtualBox *virtualbox)
218{
219 m->virtualbox = virtualbox;
220
221 pollGlobalExtraData();
222
223 if (m->fThreaded)
224 {
225 int rc = RTSemEventCreate(&m->hDnsInitEvent);
226 AssertRCReturn(rc, E_FAIL);
227
228 rc = RTThreadCreate(&m->hMonitoringThread,
229 HostDnsMonitor::threadMonitoringRoutine,
230 this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
231 AssertRCReturn(rc, E_FAIL);
232
233 RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
234 }
235 return S_OK;
236}
237
238
239void HostDnsMonitor::pollGlobalExtraData()
240{
241 uint64_t uNow = RTTimeNanoTS();
242 if (m->virtualbox && (uNow - m->uLastExtraDataPoll >= RT_NS_30SEC || m->uLastExtraDataPoll == 0))
243 {
244 m->uLastExtraDataPoll = uNow;
245
246 const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
247 com::Bstr bstrHostDNSOrderIgnore;
248 m->virtualbox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(),
249 bstrHostDNSOrderIgnore.asOutParam());
250 bool fDNSOrderIgnore = false;
251 if (bstrHostDNSOrderIgnore.isNotEmpty())
252 {
253 if (bstrHostDNSOrderIgnore != "0")
254 fDNSOrderIgnore = true;
255 }
256
257 if (fDNSOrderIgnore != m->fDNSOrderIgnore)
258 {
259 m->fDNSOrderIgnore = fDNSOrderIgnore;
260 LogRel(("HostDnsMonitor: %ls=%ls\n",
261 bstrHostDNSOrderIgnoreKey.raw(),
262 bstrHostDNSOrderIgnore.raw()));
263 }
264 }
265}
266
267void HostDnsMonitor::monitorThreadInitializationDone()
268{
269 RTSemEventSignal(m->hDnsInitEvent);
270}
271
272
273int HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
274{
275 HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
276 return pThis->monitorWorker();
277}
278
279/* HostDnsMonitorProxy */
280HostDnsMonitorProxy::HostDnsMonitorProxy()
281 : m(NULL)
282{
283}
284
285HostDnsMonitorProxy::~HostDnsMonitorProxy()
286{
287 if (m)
288 {
289 if (m->monitor)
290 m->monitor->releaseMonitorProxy(this);
291 delete m;
292 m = NULL;
293 }
294}
295
296void HostDnsMonitorProxy::init(const HostDnsMonitor *mon, VirtualBox* aParent)
297{
298 m = new HostDnsMonitorProxy::Data(mon, aParent);
299 m->monitor->addMonitorProxy(this);
300 updateInfo();
301}
302
303void HostDnsMonitorProxy::notify() const
304{
305 LogRel(("HostDnsMonitorProxy::notify\n"));
306 m->fModified = true;
307 m->virtualbox->i_onHostNameResolutionConfigurationChange();
308}
309
310HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
311{
312 AssertReturn(m && m->info, E_FAIL);
313 RTCLock grab(m_LockMtx);
314
315 if (m->fModified)
316 updateInfo();
317
318 LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
319 dumpHostDnsStrVector("name server", m->info->servers);
320
321 detachVectorOfString(m->info->servers, aNameServers);
322
323 return S_OK;
324}
325
326HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
327{
328 AssertReturn(m && m->info, E_FAIL);
329 RTCLock grab(m_LockMtx);
330
331 if (m->fModified)
332 updateInfo();
333
334 LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n",
335 m->info->domain.empty() ? "no domain set" : m->info->domain.c_str()));
336
337 *pDomainName = m->info->domain.c_str();
338
339 return S_OK;
340}
341
342HRESULT HostDnsMonitorProxy::GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
343{
344 AssertReturn(m && m->info, E_FAIL);
345 RTCLock grab(m_LockMtx);
346
347 if (m->fModified)
348 updateInfo();
349
350 LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
351 dumpHostDnsStrVector("search string", m->info->searchList);
352
353 detachVectorOfString(m->info->searchList, aSearchStrings);
354
355 return S_OK;
356}
357
358bool HostDnsMonitorProxy::operator==(PCHostDnsMonitorProxy& rhs)
359{
360 if (!m || !rhs->m)
361 return false;
362
363 /**
364 * we've assigned to the same instance of VirtualBox.
365 */
366 return m->virtualbox == rhs->m->virtualbox;
367}
368
369void HostDnsMonitorProxy::updateInfo()
370{
371 HostDnsInformation *info = new HostDnsInformation(m->monitor->getInfo());
372 HostDnsInformation *old = m->info;
373
374 m->info = info;
375 if (old)
376 {
377 delete old;
378 }
379
380 m->fModified = false;
381}
382
383
384static void dumpHostDnsInformation(const HostDnsInformation& info)
385{
386 dumpHostDnsStrVector("server", info.servers);
387 dumpHostDnsStrVector("search string", info.searchList);
388
389 if (!info.domain.empty())
390 LogRel((" domain: %s\n", info.domain.c_str()));
391 else
392 LogRel((" no domain set\n"));
393}
394
395
396static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
397{
398 int i = 1;
399 for (std::vector<std::string>::const_iterator it = v.begin();
400 it != v.end();
401 ++it, ++i)
402 LogRel((" %s %d: %s\n", prefix.c_str(), i, it->c_str()));
403 if (v.empty())
404 LogRel((" no %s entries\n", prefix.c_str()));
405}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette