VirtualBox

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

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

Main/HostDnsServiceDarwin: Add and remove the stop source object in the thread function for consistentcy. Also should fix the startup crashes.

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