VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp@ 49235

Last change on this file since 49235 was 49235, checked in by vboxsync, 12 years ago

Main/HostDnsService: splits HostDnsService on "singleton" HostDnsMonitor
which monitors host changes and share DnsInformation to per HostImpl/VirtualBoxImpl objects
HostDnsMonitorProxy.

TODO: Win/Darwin parts might burn (not tested)
TODO: find good place to call HostDnsMonitor::shutdown() to stop
monitoring thread. (ref counting could be used on
HostDnsMonitor::addMonitorProxy and HostDnsMonitor::releaseMonitorProxy,
but it better to pausing monitoring on no --auto-shutdown launches of VBoxSVC).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.5 KB
Line 
1/* $Id: HostDnsServiceLinux.cpp 49235 2013-10-22 18:56:03Z vboxsync $ */
2/** @file
3 * Linux specific DNS information fetching.
4 */
5
6/*
7 * Copyright (C) 2013 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 <iprt/assert.h>
19#include <iprt/err.h>
20#include <iprt/initterm.h>
21#include <iprt/file.h>
22#include <iprt/log.h>
23#include <iprt/stream.h>
24#include <iprt/string.h>
25#include <iprt/semaphore.h>
26#include <iprt/thread.h>
27
28#include <errno.h>
29#include <poll.h>
30#include <string.h>
31#include <unistd.h>
32
33#include <fcntl.h>
34
35#include <sys/inotify.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38
39#include <string>
40#include <vector>
41#include "../HostDnsService.h"
42
43
44static RTTHREAD g_DnsMonitoringThread;
45static RTSEMEVENT g_DnsInitEvent;
46static int g_DnsMonitorStop[2];
47
48class FileDescriptor
49{
50 public:
51 FileDescriptor(int d = -1):fd(d){}
52
53 virtual ~FileDescriptor() {
54 if (fd != -1)
55 close(fd);
56 }
57
58 int fileDescriptor() const {return fd;}
59
60 protected:
61 int fd;
62};
63
64
65class AutoNotify:public FileDescriptor
66{
67 public:
68 AutoNotify()
69 {
70 FileDescriptor::fd = inotify_init();
71 AssertReturnVoid(FileDescriptor::fd != -1);
72 }
73
74};
75
76
77class AutoWatcher:public FileDescriptor
78{
79 public:
80 AutoWatcher(const AutoNotify& notifier, const std::string& filename, uint32_t mask = IN_CLOSE_WRITE)
81 :name(filename)
82 {
83 nfd = notifier.fileDescriptor();
84 fd = inotify_add_watch(nfd, name.c_str(), mask);
85 AssertMsgReturnVoid(fd != -1, ("failed to add watcher %s\n", name.c_str()));
86
87 int opt = fcntl(fd, F_GETFL);
88 opt |= O_NONBLOCK;
89 fcntl(fd, F_SETFL, opt);
90 }
91
92 ~AutoWatcher()
93 {
94 int rc = inotify_rm_watch(nfd, fd);
95 AssertMsgReturnVoid(rc != -1, ("Can't detach watcher %d from %d (%d: %s)\n", nfd, fd,
96 errno, strerror(errno)));
97 }
98
99 private:
100 std::string name;
101 int nfd;
102};
103
104
105HostDnsServiceLinux::~HostDnsServiceLinux()
106{
107 send(g_DnsMonitorStop[0], "", 1, 0);
108}
109
110
111int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
112{
113 AutoNotify a;
114 HostDnsServiceLinux *dns = static_cast<HostDnsServiceLinux *>(pvUser);
115 AutoWatcher w(a, std::string(dns->resolvConf().c_str()));
116
117 int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop);
118 AssertMsgReturn(rc == 0, ("socketpair: failed (%d: %s)\n", errno, strerror(errno)), E_FAIL);
119
120 FileDescriptor stopper0(g_DnsMonitorStop[0]);
121 FileDescriptor stopper1(g_DnsMonitorStop[1]);
122
123 pollfd polls[2];
124 RT_ZERO(polls);
125
126 polls[0].fd = a.fileDescriptor();
127 polls[0].events = POLLIN;
128
129 polls[1].fd = g_DnsMonitorStop[1];
130 polls[1].events = POLLIN;
131
132 RTSemEventSignal(g_DnsInitEvent);
133
134 while(true)
135 {
136 rc = poll(polls, 2, -1);
137 if (rc == -1)
138 continue;
139
140 AssertMsgReturn( ((polls[0].revents & (POLLERR|POLLNVAL)) == 0)
141 && ((polls[1].revents & (POLLERR|POLLNVAL)) == 0),
142 ("Debug Me"), VERR_INTERNAL_ERROR);
143
144 if (polls[1].revents & POLLIN)
145 return VINF_SUCCESS; /* time to shutdown */
146
147 if (polls[0].revents & POLLIN)
148 {
149 dns->readResolvConf();
150 /* notifyAll() takes required locks */
151 dns->notifyAll();
152
153 polls[0].revents = 0;
154
155 inotify_event ev;
156 rc = read(a.fileDescriptor(), static_cast<void *>(&ev), sizeof(ev));
157 AssertMsg(rc == sizeof(ev) && ev.wd == w.fileDescriptor(), ("Hmm, debug me"));
158 }
159 }
160}
161
162
163HRESULT HostDnsServiceLinux::init(const char *aResolvConfFileName)
164{
165 HRESULT hrc = HostDnsServiceResolvConf::init(aResolvConfFileName);
166 AssertComRCReturnRC(hrc);
167
168 int rc = RTThreadCreate(&g_DnsMonitoringThread, HostDnsServiceLinux::hostMonitoringRoutine,
169 this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
170 AssertRCReturn(rc, E_FAIL);
171
172 rc = RTSemEventCreate(&g_DnsInitEvent);
173 AssertRCReturn(rc, E_FAIL);
174
175 RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
176
177 return S_OK;
178}
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