summaryrefslogtreecommitdiff
path: root/src/VBox/Main/src-server/HostDnsService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Main/src-server/HostDnsService.cpp')
-rw-r--r--src/VBox/Main/src-server/HostDnsService.cpp363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/HostDnsService.cpp b/src/VBox/Main/src-server/HostDnsService.cpp
new file mode 100644
index 00000000..011528fb
--- /dev/null
+++ b/src/VBox/Main/src-server/HostDnsService.cpp
@@ -0,0 +1,363 @@
+/* $Id: HostDnsService.cpp $ */
+/** @file
+ * Base class fo Host DNS & Co services.
+ */
+
+/*
+ * Copyright (C) 2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <VBox/com/array.h>
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+
+#include <iprt/cpp/utils.h>
+
+#include "Logging.h"
+#include "VirtualBoxImpl.h"
+#include <iprt/thread.h>
+#include <iprt/semaphore.h>
+#include <iprt/critsect.h>
+
+#include <algorithm>
+#include <string>
+#include "HostDnsService.h"
+
+
+static HostDnsMonitor *g_monitor;
+
+static void dumpHostDnsInformation(const HostDnsInformation&);
+static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&);
+
+/* Lockee */
+Lockee::Lockee()
+{
+ RTCritSectInit(&mLock);
+}
+
+Lockee::~Lockee()
+{
+ RTCritSectDelete(&mLock);
+}
+
+const RTCRITSECT* Lockee::lock() const
+{
+ return &mLock;
+}
+
+/* ALock */
+ALock::ALock(const Lockee *aLockee)
+ : lockee(aLockee)
+{
+ RTCritSectEnter(const_cast<PRTCRITSECT>(lockee->lock()));
+}
+
+ALock::~ALock()
+{
+ RTCritSectLeave(const_cast<PRTCRITSECT>(lockee->lock()));
+}
+
+inline static void detachVectorOfString(const std::vector<std::string>& v,
+ ComSafeArrayOut(BSTR, aBstrArray))
+{
+ com::SafeArray<BSTR> aBstr(v.size());
+
+ std::vector<std::string>::const_iterator it;
+
+ int i = 0;
+ it = v.begin();
+ for (; it != v.end(); ++it, ++i)
+ Utf8Str(it->c_str()).cloneTo(&aBstr[i]);
+
+ aBstr.detachTo(ComSafeArrayOutArg(aBstrArray));
+}
+
+struct HostDnsMonitor::Data
+{
+ Data(bool aThreaded):fThreaded(aThreaded){}
+
+ std::vector<PCHostDnsMonitorProxy> proxies;
+ HostDnsInformation info;
+ const bool fThreaded;
+ RTTHREAD hMonitoringThread;
+ RTSEMEVENT hDnsInitEvent;
+};
+
+struct HostDnsMonitorProxy::Data
+{
+ Data(const HostDnsMonitor *aMonitor, const VirtualBox *aParent)
+ : info(NULL)
+ , virtualbox(aParent)
+ , monitor(aMonitor)
+ , fModified(true)
+ {}
+
+ virtual ~Data()
+ {
+ if (info)
+ {
+ delete info;
+ info = NULL;
+ }
+ }
+
+ HostDnsInformation *info;
+ const VirtualBox *virtualbox;
+ const HostDnsMonitor *monitor;
+ bool fModified;
+};
+
+
+HostDnsMonitor::HostDnsMonitor(bool fThreaded)
+ : m(NULL)
+{
+ m = new HostDnsMonitor::Data(fThreaded);
+}
+
+HostDnsMonitor::~HostDnsMonitor()
+{
+ if (m)
+ {
+ delete m;
+ m = NULL;
+ }
+}
+
+const HostDnsMonitor *HostDnsMonitor::getHostDnsMonitor()
+{
+ /* XXX: Moved initialization from HostImpl.cpp */
+ if (!g_monitor)
+ {
+# if defined (RT_OS_DARWIN)
+ g_monitor = new HostDnsServiceDarwin();
+# elif defined(RT_OS_WINDOWS)
+ g_monitor = new HostDnsServiceWin();
+# elif defined(RT_OS_LINUX)
+ g_monitor = new HostDnsServiceLinux();
+# elif defined(RT_OS_SOLARIS)
+ g_monitor = new HostDnsServiceSolaris();
+# elif defined(RT_OS_FREEBSD)
+ g_monitor = new HostDnsServiceFreebsd();
+# elif defined(RT_OS_OS2)
+ g_monitor = new HostDnsServiceOs2();
+# else
+ g_monitor = new HostDnsService();
+# endif
+ g_monitor->init();
+ }
+
+ return g_monitor;
+}
+
+void HostDnsMonitor::addMonitorProxy(PCHostDnsMonitorProxy proxy) const
+{
+ ALock l(this);
+ m->proxies.push_back(proxy);
+ proxy->notify();
+}
+
+void HostDnsMonitor::releaseMonitorProxy(PCHostDnsMonitorProxy proxy) const
+{
+ ALock l(this);
+ std::vector<PCHostDnsMonitorProxy>::iterator it;
+ it = std::find(m->proxies.begin(), m->proxies.end(), proxy);
+
+ if (it == m->proxies.end())
+ return;
+
+ m->proxies.erase(it);
+}
+
+void HostDnsMonitor::shutdown()
+{
+ if (g_monitor)
+ {
+ delete g_monitor;
+ g_monitor = NULL;
+ }
+}
+
+const HostDnsInformation &HostDnsMonitor::getInfo() const
+{
+ return m->info;
+}
+
+void HostDnsMonitor::notifyAll() const
+{
+ ALock l(this);
+ std::vector<PCHostDnsMonitorProxy>::const_iterator it;
+ for (it = m->proxies.begin(); it != m->proxies.end(); ++it)
+ (*it)->notify();
+}
+
+void HostDnsMonitor::setInfo(const HostDnsInformation &info)
+{
+ ALock l(this);
+ m->info = info;
+}
+
+HRESULT HostDnsMonitor::init()
+{
+ if (m->fThreaded)
+ {
+ int rc = RTSemEventCreate(&m->hDnsInitEvent);
+ AssertRCReturn(rc, E_FAIL);
+
+ rc = RTThreadCreate(&m->hMonitoringThread,
+ HostDnsMonitor::threadMonitoringRoutine,
+ this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
+ AssertRCReturn(rc, E_FAIL);
+
+ RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
+ }
+ return S_OK;
+}
+
+
+void HostDnsMonitor::monitorThreadInitializationDone()
+{
+ RTSemEventSignal(m->hDnsInitEvent);
+}
+
+
+int HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
+{
+ HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
+ return pThis->monitorWorker();
+}
+
+/* HostDnsMonitorProxy */
+HostDnsMonitorProxy::HostDnsMonitorProxy()
+ : m(NULL)
+{
+}
+
+HostDnsMonitorProxy::~HostDnsMonitorProxy()
+{
+ if (m)
+ {
+ if (m->monitor)
+ m->monitor->releaseMonitorProxy(this);
+ delete m;
+ m = NULL;
+ }
+}
+
+void HostDnsMonitorProxy::init(const HostDnsMonitor *mon, const VirtualBox* aParent)
+{
+ m = new HostDnsMonitorProxy::Data(mon, aParent);
+ m->monitor->addMonitorProxy(this);
+ updateInfo();
+}
+
+void HostDnsMonitorProxy::notify() const
+{
+ m->fModified = true;
+ const_cast<VirtualBox *>(m->virtualbox)->onHostNameResolutionConfigurationChange();
+}
+
+HRESULT HostDnsMonitorProxy::GetNameServers(ComSafeArrayOut(BSTR, aNameServers))
+{
+ AssertReturn(m && m->info, E_FAIL);
+ ALock l(this);
+
+ if (m->fModified)
+ updateInfo();
+
+ LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
+ dumpHostDnsStrVector("Name Server", m->info->servers);
+
+ detachVectorOfString(m->info->servers, ComSafeArrayOutArg(aNameServers));
+
+ return S_OK;
+}
+
+HRESULT HostDnsMonitorProxy::GetDomainName(BSTR *aDomainName)
+{
+ AssertReturn(m && m->info, E_FAIL);
+ ALock l(this);
+
+ if (m->fModified)
+ updateInfo();
+
+ LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n", m->info->domain.c_str()));
+
+ Utf8Str(m->info->domain.c_str()).cloneTo(aDomainName);
+
+ return S_OK;
+}
+
+HRESULT HostDnsMonitorProxy::GetSearchStrings(ComSafeArrayOut(BSTR, aSearchStrings))
+{
+ AssertReturn(m && m->info, E_FAIL);
+ ALock l(this);
+
+ if (m->fModified)
+ updateInfo();
+
+ LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
+ dumpHostDnsStrVector("Search String", m->info->searchList);
+
+ detachVectorOfString(m->info->searchList, ComSafeArrayOutArg(aSearchStrings));
+
+ return S_OK;
+}
+
+bool HostDnsMonitorProxy::operator==(PCHostDnsMonitorProxy& rhs)
+{
+ if (!m || !rhs->m)
+ return false;
+
+ /**
+ * we've assigned to the same instance of VirtualBox.
+ */
+ return m->virtualbox == rhs->m->virtualbox;
+}
+
+void HostDnsMonitorProxy::updateInfo()
+{
+ HostDnsInformation *info = new HostDnsInformation(m->monitor->getInfo());
+ HostDnsInformation *old = m->info;
+
+ LogRel(("HostDnsMonitorProxy: Host's DNS information updated:\n"));
+ dumpHostDnsInformation(*info);
+
+ m->info = info;
+ if (old)
+ {
+ LogRel(("HostDnsMonitorProxy: Old host information:\n"));
+ dumpHostDnsInformation(*old);
+
+ delete old;
+ }
+
+ m->fModified = false;
+}
+
+
+static void dumpHostDnsInformation(const HostDnsInformation& info)
+{
+ dumpHostDnsStrVector("DNS server", info.servers);
+ dumpHostDnsStrVector("SearchString", info.searchList);
+
+ if (!info.domain.empty())
+ LogRel(("DNS domain: %s\n", info.domain.c_str()));
+}
+
+
+static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
+{
+ int i = 1;
+ for (std::vector<std::string>::const_iterator it = v.begin();
+ it != v.end();
+ ++it, ++i)
+ LogRel(("%s %d: %s\n", prefix.c_str(), i, it->c_str()));
+}