VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp@ 77666

Last change on this file since 77666 was 77666, checked in by vboxsync, 6 years ago

Main/HostDnsServiceDarwin: Fixed shutting down procedure by making sure fStop is initialized. Also added a couple of checks / assertions.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1/* $Id: HostDnsServiceDarwin.cpp 77666 2019-03-12 15:41:14Z vboxsync $ */
2/** @file
3 * Darwin specific DNS information fetching.
4 */
5
6/*
7 * Copyright (C) 2004-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. 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/string.h>
19#include <VBox/com/ptr.h>
20
21
22#include <iprt/errcore.h>
23#include <iprt/thread.h>
24#include <iprt/semaphore.h>
25
26#include <CoreFoundation/CoreFoundation.h>
27#include <SystemConfiguration/SCDynamicStore.h>
28
29#include <string>
30#include <vector>
31#include "../HostDnsService.h"
32
33
34struct HostDnsServiceDarwin::Data
35{
36 Data()
37 : m_fStop(false) { }
38
39 SCDynamicStoreRef m_store;
40 CFRunLoopSourceRef m_DnsWatcher;
41 CFRunLoopRef m_RunLoopRef;
42 CFRunLoopSourceRef m_Stopper;
43 bool m_fStop;
44 RTSEMEVENT m_evtStop;
45 static void performShutdownCallback(void *);
46};
47
48
49static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
50
51
52HostDnsServiceDarwin::HostDnsServiceDarwin():HostDnsMonitor(true),m(NULL)
53{
54 m = new HostDnsServiceDarwin::Data();
55}
56
57
58HostDnsServiceDarwin::~HostDnsServiceDarwin()
59{
60 if (!m)
61 return;
62
63 monitorThreadShutdown();
64
65 CFRelease(m->m_RunLoopRef);
66
67 CFRelease(m->m_DnsWatcher);
68
69 CFRelease(m->m_store);
70
71 RTSemEventDestroy(m->m_evtStop);
72
73 delete m;
74 m = NULL;
75}
76
77
78void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *, void *, void *info)
79{
80 HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
81
82 RTCLock grab(pThis->m_LockMtx);
83 pThis->updateInfo();
84}
85
86
87HRESULT HostDnsServiceDarwin::init(HostDnsMonitorProxy *proxy)
88{
89 SCDynamicStoreContext ctx;
90 RT_ZERO(ctx);
91
92 ctx.info = this;
93
94 m->m_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
95 (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
96 &ctx);
97 AssertReturn(m->m_store, E_FAIL);
98
99 m->m_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, m->m_store, 0);
100 if (!m->m_DnsWatcher)
101 return E_OUTOFMEMORY;
102
103 int rc = RTSemEventCreate(&m->m_evtStop);
104 AssertRCReturn(rc, E_FAIL);
105
106 CFRunLoopSourceContext sctx;
107 RT_ZERO(sctx);
108 sctx.perform = HostDnsServiceDarwin::Data::performShutdownCallback;
109 m->m_Stopper = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sctx);
110 AssertReturn(m->m_Stopper, E_FAIL);
111
112 HRESULT hrc = HostDnsMonitor::init(proxy);
113 AssertComRCReturn(hrc, hrc);
114
115 return updateInfo();
116}
117
118
119void HostDnsServiceDarwin::monitorThreadShutdown()
120{
121 RTCLock grab(m_LockMtx);
122 if (!m->m_fStop)
123 {
124 CFRunLoopSourceSignal(m->m_Stopper);
125 CFRunLoopWakeUp(m->m_RunLoopRef);
126
127 RTSemEventWait(m->m_evtStop, RT_INDEFINITE_WAIT);
128 }
129}
130
131
132int HostDnsServiceDarwin::monitorWorker()
133{
134 m->m_RunLoopRef = CFRunLoopGetCurrent();
135 AssertReturn(m->m_RunLoopRef, VERR_INTERNAL_ERROR);
136
137 CFRetain(m->m_RunLoopRef);
138
139 CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
140 (const void **)&kStateNetworkGlobalDNSKey,
141 1, &kCFTypeArrayCallBacks);
142 if (!watchingArrayRef)
143 {
144 CFRelease(m->m_DnsWatcher);
145 return E_OUTOFMEMORY;
146 }
147
148 if(SCDynamicStoreSetNotificationKeys(m->m_store, watchingArrayRef, NULL))
149 CFRunLoopAddSource(CFRunLoopGetCurrent(), m->m_DnsWatcher, kCFRunLoopCommonModes);
150
151 CFRelease(watchingArrayRef);
152
153 monitorThreadInitializationDone();
154
155 while (!m->m_fStop)
156 {
157 CFRunLoopRun();
158 }
159
160 CFRelease(m->m_RunLoopRef);
161
162 /* We're notifying stopper thread. */
163 RTSemEventSignal(m->m_evtStop);
164
165 return VINF_SUCCESS;
166}
167
168
169HRESULT HostDnsServiceDarwin::updateInfo()
170{
171 CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(m->m_store,
172 kStateNetworkGlobalDNSKey);
173 /**
174 * # scutil
175 * \> get State:/Network/Global/DNS
176 * \> d.show
177 * \<dictionary\> {
178 * DomainName : vvl-domain
179 * SearchDomains : \<array\> {
180 * 0 : vvl-domain
181 * 1 : de.vvl-domain.com
182 * }
183 * ServerAddresses : \<array\> {
184 * 0 : 192.168.1.4
185 * 1 : 192.168.1.1
186 * 2 : 8.8.4.4
187 * }
188 * }
189 */
190
191 if (!propertyRef)
192 return S_OK;
193
194 HostDnsInformation info;
195 CFStringRef domainNameRef = (CFStringRef)CFDictionaryGetValue(
196 static_cast<CFDictionaryRef>(propertyRef), CFSTR("DomainName"));
197 if (domainNameRef)
198 {
199 const char *pszDomainName = CFStringGetCStringPtr(domainNameRef,
200 CFStringGetSystemEncoding());
201 if (pszDomainName)
202 info.domain = pszDomainName;
203 }
204
205 int i, arrayCount;
206 CFArrayRef serverArrayRef = (CFArrayRef)CFDictionaryGetValue(
207 static_cast<CFDictionaryRef>(propertyRef), CFSTR("ServerAddresses"));
208 if (serverArrayRef)
209 {
210 arrayCount = CFArrayGetCount(serverArrayRef);
211 for (i = 0; i < arrayCount; ++i)
212 {
213 CFStringRef serverAddressRef = (CFStringRef)CFArrayGetValueAtIndex(serverArrayRef, i);
214 if (!serverArrayRef)
215 continue;
216
217 const char *pszServerAddress = CFStringGetCStringPtr(serverAddressRef,
218 CFStringGetSystemEncoding());
219 if (!pszServerAddress)
220 continue;
221
222 info.servers.push_back(std::string(pszServerAddress));
223 }
224 }
225
226 CFArrayRef searchArrayRef = (CFArrayRef)CFDictionaryGetValue(
227 static_cast<CFDictionaryRef>(propertyRef), CFSTR("SearchDomains"));
228 if (searchArrayRef)
229 {
230 arrayCount = CFArrayGetCount(searchArrayRef);
231
232 for (i = 0; i < arrayCount; ++i)
233 {
234 CFStringRef searchStringRef = (CFStringRef)CFArrayGetValueAtIndex(searchArrayRef, i);
235 if (!searchArrayRef)
236 continue;
237
238 const char *pszSearchString = CFStringGetCStringPtr(searchStringRef,
239 CFStringGetSystemEncoding());
240 if (!pszSearchString)
241 continue;
242
243 info.searchList.push_back(std::string(pszSearchString));
244 }
245 }
246
247 CFRelease(propertyRef);
248
249 setInfo(info);
250
251 return S_OK;
252}
253
254void HostDnsServiceDarwin::Data::performShutdownCallback(void *info)
255{
256 HostDnsServiceDarwin::Data *pThis = static_cast<HostDnsServiceDarwin::Data *>(info);
257 AssertPtrReturnVoid(pThis);
258 pThis->m_fStop = true;
259}
Note: See TracBrowser for help on using the repository browser.

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