VirtualBox

Changeset 50263 in vbox for trunk


Ignore:
Timestamp:
Jan 28, 2014 7:29:52 PM (11 years ago)
Author:
vboxsync
Message:

Main/HostDnsService:

  • Generic part could be used with threading on or off: OS which can monitor changes on DNS structures might need this (e.g. Windows, Darwin, Linux)
  • ResolvConf based (Linux, Solaris, FreeBSD ans Os/2) doesn't use scanf based resovl.conf parsing new Slirp's parser used instead. It's configured to provide strings instead of addresses. (to resolve xtracker/7034c2)
  • Darwin monitoring code has been refactored.
  • linux changed to handle cases described in xtracker/7034c3
  • Windows monitors changes on register changes.
Location:
trunk/src/VBox/Main
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile.kmk

    r50202 r50263  
    389389        $(if $(VBOX_WITH_XPCOM),src-server/xpcom/server.cpp,)
    390390
     391ifn1of ($(KBUILD_TARGET), win darwin)
     392        VBoxSVC_SOURCES += $(PATH_ROOT)/src/VBox/Devices/Network/slirp/resolv_conf_parser.c
     393endif
     394
    391395VBoxSVC_SOURCES.darwin = \
    392396        src-server/darwin/iokit.cpp \
  • trunk/src/VBox/Main/src-server/HostDnsService.cpp

    r49818 r50263  
    8383struct HostDnsMonitor::Data
    8484{
     85    Data(bool aThreaded):fThreaded(aThreaded){}
     86
    8587    std::vector<PCHostDnsMonitorProxy> proxies;
    8688    HostDnsInformation info;
     89    const bool fThreaded;
     90    RTTHREAD hMonitoringThread;
     91    RTSEMEVENT hDnsInitEvent;
    8792};
    8893
     
    112117
    113118
    114 HostDnsMonitor::HostDnsMonitor()
     119HostDnsMonitor::HostDnsMonitor(bool fThreaded)
    115120  : m(NULL)
    116121{
     122   m = new HostDnsMonitor::Data(fThreaded);
    117123}
    118124
     
    201207HRESULT HostDnsMonitor::init()
    202208{
    203     m = new HostDnsMonitor::Data();
     209    if (m->fThreaded)
     210    {
     211        int rc = RTSemEventCreate(&m->hDnsInitEvent);
     212        AssertRCReturn(rc, E_FAIL);
     213
     214        rc = RTThreadCreate(&m->hMonitoringThread,
     215                            HostDnsMonitor::threadMonitoringRoutine,
     216                            this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
     217        AssertRCReturn(rc, E_FAIL);
     218
     219        RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
     220    }
    204221    return S_OK;
    205222}
    206223
     224
     225void HostDnsMonitor::monitorThreadInitializationDone()
     226{
     227    RTSemEventSignal(m->hDnsInitEvent);
     228}
     229
     230
     231int HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
     232{
     233    HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
     234    return pThis->monitorWorker();
     235}
    207236
    208237/* HostDnsMonitorProxy */
  • trunk/src/VBox/Main/src-server/HostDnsService.h

    r49718 r50263  
    4747{
    4848  public:
    49     ALock(const Lockee *l);
     49    explicit ALock(const Lockee *l);
    5050    ~ALock();
    5151
     
    7575    void releaseMonitorProxy(PCHostDnsMonitorProxy) const;
    7676    const HostDnsInformation &getInfo() const;
     77    /* @note: method will wait till client call
     78       HostDnsService::monitorThreadInitializationDone() */
    7779    virtual HRESULT init();
    7880
    7981  protected:
     82    explicit HostDnsMonitor(bool fThreaded = false);
     83    virtual ~HostDnsMonitor();
     84
    8085    void notifyAll() const;
    8186    void setInfo(const HostDnsInformation &);
    82     HostDnsMonitor();
    83     virtual ~HostDnsMonitor();
     87
     88    /* this function used only if HostDnsMonitor::HostDnsMonitor(true) */
     89    void monitorThreadInitializationDone();
     90    virtual void monitorThreadShutdown() = 0;
     91    virtual int monitorWorker() = 0;
    8492
    8593  private:
    8694    HostDnsMonitor(const HostDnsMonitor &);
    8795    HostDnsMonitor& operator= (const HostDnsMonitor &);
     96    static int threadMonitoringRoutine(RTTHREAD, void *);
    8897
    8998  public:
     
    97106class HostDnsMonitorProxy : public Lockee
    98107{
    99   public:
     108    public:
    100109    HostDnsMonitorProxy();
    101110    ~HostDnsMonitorProxy();
     
    109118    bool operator==(PCHostDnsMonitorProxy&);
    110119
    111   private:
     120    private:
    112121    void updateInfo();
    113122
    114   private:
     123    private:
    115124    struct Data;
    116125    Data *m;
     
    125134    HRESULT init();
    126135
    127   private:
     136    protected:
     137    virtual void monitorThreadShutdown();
     138    virtual int monitorWorker();
     139
     140    private:
    128141    HRESULT updateInfo();
    129142    static void hostDnsServiceStoreCallback(void *store, void *arrayRef, void *info);
     143    struct Data;
     144    Data *m;
    130145};
    131146# endif
     
    133148class HostDnsServiceWin : public HostDnsMonitor
    134149{
    135   public:
     150    public:
    136151    HostDnsServiceWin();
    137152    ~HostDnsServiceWin();
    138153    HRESULT init();
    139154
    140   private:
     155    protected:
     156    virtual void monitorThreadShutdown();
     157    virtual int monitorWorker();
     158
     159    private:
    141160    void strList2List(std::vector<std::string>& lst, char *strLst);
    142161    HRESULT updateInfo();
     162
     163    private:
     164    struct Data;
     165    Data *m;
    143166};
    144167# endif
     
    147170{
    148171  public:
    149     HostDnsServiceResolvConf() : m(NULL) {}
     172    explicit HostDnsServiceResolvConf(bool fThreaded = false) : HostDnsMonitor(fThreaded), m(NULL) {}
    150173    virtual ~HostDnsServiceResolvConf();
    151174    virtual HRESULT init(const char *aResolvConfFileName);
    152     const std::string& resolvConf();
     175    const std::string& resolvConf() const;
    153176
    154177  protected:
    155178    HRESULT readResolvConf();
     179    /* While not all hosts supports Hosts DNS change notifiaction
     180     * default implementation offers return VERR_IGNORE.
     181     */
     182    virtual void monitorThreadShutdown() {}
     183    virtual int monitorWorker() {return VERR_IGNORED;}
    156184
    157185  protected:
     
    175203{
    176204  public:
    177     HostDnsServiceLinux(){}
    178     ~HostDnsServiceLinux();
    179     HRESULT init() {return init("/etc/resolv.conf");}
    180     HRESULT init(const char *aResolvConfFileName);
    181 
    182     static int hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser);
     205    HostDnsServiceLinux():HostDnsServiceResolvConf(true){}
     206    virtual ~HostDnsServiceLinux();
     207    virtual HRESULT init(){ return HostDnsServiceResolvConf::init("/etc/resolv.conf");}
     208
     209  protected:
     210    virtual void monitorThreadShutdown();
     211    virtual int monitorWorker();
    183212};
    184213
  • trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp

    r50213 r50263  
    2525
    2626#include "HostDnsService.h"
     27#include "../../Devices/Network/slirp/resolv_conf_parser.h"
    2728
    2829
     
    3435};
    3536
    36 const std::string &HostDnsServiceResolvConf::resolvConf()
     37const std::string& HostDnsServiceResolvConf::resolvConf() const
    3738{
    3839    return m->resolvConfFilename;
    3940}
    4041
    41 static int fileGets(RTFILE File, void *pvBuf, size_t cbBufSize, size_t *pcbRead)
    42 {
    43     size_t cbRead;
    44     char bTest;
    45     int rc = VERR_NO_MEMORY;
    46     char *pu8Buf = (char *)pvBuf;
    47     *pcbRead = 0;
    48 
    49     while (   RT_SUCCESS(rc = RTFileRead(File, &bTest, 1, &cbRead))
    50            && (pu8Buf - (char *)pvBuf) >= 0
    51            && (size_t)(pu8Buf - (char *)pvBuf) < cbBufSize)
    52     {
    53         if (cbRead == 0)
    54             return VERR_EOF;
    55 
    56         if (bTest == '\r' || bTest == '\n')
    57         {
    58             *pu8Buf = 0;
    59             return VINF_SUCCESS;
    60         }
    61         *pu8Buf = bTest;
    62          pu8Buf++;
    63         (*pcbRead)++;
    64     }
    65     return rc;
    66 }
    6742
    6843HostDnsServiceResolvConf::~HostDnsServiceResolvConf()
     
    7752HRESULT HostDnsServiceResolvConf::init(const char *aResolvConfFileName)
    7853{
     54    m = new Data(aResolvConfFileName);
     55
    7956    HostDnsMonitor::init();
    8057
    81     m = new Data(aResolvConfFileName);
    8258    readResolvConf();
    8359
     
    8561}
    8662
     63
    8764HRESULT HostDnsServiceResolvConf::readResolvConf()
    8865{
    89     char buff[256];
    90     char buff2[256];
    91     int cNameserversFound = 0;
    92     bool fWarnTooManyDnsServers = false;
    93     struct in_addr tmp_addr;
    94     size_t bytes;
     66    struct rcp_state st;
     67   
     68    st.rcps_flags = RCPSF_NO_STR2IPCONV;
     69    int rc = rcp_parse(&st, m->resolvConfFilename.c_str());
     70    if (rc == -1)
     71        return S_OK;
     72
    9573    HostDnsInformation info;
    96     RTFILE resolvConfFile;
     74    for (unsigned i = 0; i != st.rcps_num_nameserver; ++i)
     75    {
     76        AssertBreak(st.rcps_str_nameserver[i]);
     77        info.servers.push_back(st.rcps_str_nameserver[i]);
     78    }
     79   
     80    if (st.rcps_domain)
     81        info.domain = st.rcps_domain;
    9782
    98     int rc = RTFileOpen(&resolvConfFile, m->resolvConfFilename.c_str(),
    99                         RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    100     AssertRCReturn(rc, E_FAIL);
    101 
    102     while (    RT_SUCCESS(rc = fileGets(resolvConfFile, buff, sizeof(buff), &bytes))
    103             && rc != VERR_EOF)
     83    for (unsigned i = 0; i != st.rcps_num_searchlist; ++i)
    10484    {
    105         if (   cNameserversFound == 4
    106             && !fWarnTooManyDnsServers
    107             && sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1)
    108         {
    109             fWarnTooManyDnsServers = true;
    110             LogRel(("NAT: too many nameservers registered.\n"));
    111         }
    112         if (   sscanf(buff, "nameserver%*[ \t]%255s", buff2) == 1
    113             && cNameserversFound < 4) /* Unix doesn't accept more than 4 name servers*/
    114         {
    115             if (!inet_aton(buff2, &tmp_addr))
    116                 continue;
    117 
    118             info.servers.push_back(std::string(buff2));
    119 
    120             cNameserversFound++;
    121         }
    122         if (   !strncmp(buff, "domain", 6)
    123             || !strncmp(buff, "search", 6))
    124         {
    125             char *tok;
    126             char *saveptr;
    127 
    128             tok = strtok_r(&buff[6], " \t\n", &saveptr);
    129 
    130             if (tok != NULL)
    131                 info.domain = std::string(tok);
    132         }
     85        AssertBreak(st.rcps_searchlist[i]);
     86        info.searchList.push_back(st.rcps_searchlist[i]);
    13387    }
    134 
    135     RTFileClose(resolvConfFile);
    136 
    13788    setInfo(info);
    13889
  • trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp

    r50213 r50263  
    3232
    3333
    34 
    35 SCDynamicStoreRef g_store;
    36 CFRunLoopSourceRef g_DnsWatcher;
    37 CFRunLoopRef g_RunLoopRef;
    38 RTTHREAD g_DnsMonitoringThread;
    39 RTSEMEVENT g_DnsInitEvent;
     34struct HostDnsServiceDarwin::Data
     35{
     36    SCDynamicStoreRef m_store;
     37    CFRunLoopSourceRef m_DnsWatcher;
     38    CFRunLoopRef m_RunLoopRef;
     39    CFRunLoopSourceRef m_Stopper;
     40    bool m_fStop;
     41    RTSEMEVENT m_evtStop;
     42    static void performShutdownCallback(void *);
     43};
     44
    4045
    4146static const CFStringRef kStateNetworkGlobalDNSKey = CFSTR("State:/Network/Global/DNS");
    4247
    43 static int hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
    44 {
    45     NOREF(ThreadSelf);
    46     NOREF(pvUser);
    47     g_RunLoopRef = CFRunLoopGetCurrent();
    48     AssertReturn(g_RunLoopRef, VERR_INTERNAL_ERROR);
    49 
    50     CFRetain(g_RunLoopRef);
     48
     49HostDnsServiceDarwin::HostDnsServiceDarwin():HostDnsMonitor(true),m(NULL)
     50{
     51    m = new HostDnsServiceDarwin::Data();
     52}
     53
     54
     55HostDnsServiceDarwin::~HostDnsServiceDarwin()
     56{
     57    if (!m)
     58        return;
     59
     60    monitorThreadShutdown();
     61
     62    CFRelease(m->m_RunLoopRef);
     63   
     64    CFRelease(m->m_DnsWatcher);
     65
     66    CFRelease(m->m_store);
     67
     68    RTSemEventDestroy(m->m_evtStop);
     69
     70    delete m;
     71    m = NULL;
     72}
     73
     74
     75void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *, void *, void *info)
     76{
     77    HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
     78
     79    ALock l(pThis);
     80    pThis->updateInfo();
     81    pThis->notifyAll();
     82}
     83
     84
     85HRESULT HostDnsServiceDarwin::init()
     86{
     87    SCDynamicStoreContext ctx;
     88    RT_ZERO(ctx);
     89
     90    ctx.info = this;
     91
     92    m->m_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
     93                                   (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
     94                                   &ctx);
     95    AssertReturn(m->m_store, E_FAIL);
     96
     97    m->m_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, m->m_store, 0);
     98    if (!m->m_DnsWatcher)
     99        return E_OUTOFMEMORY;
     100
     101    int rc = RTSemEventCreate(&m->m_evtStop);
     102    AssertRCReturn(rc, E_FAIL);
     103
     104    CFRunLoopSourceContext sctx;
     105    RT_ZERO(sctx);
     106    sctx.perform = HostDnsServiceDarwin::Data::performShutdownCallback;
     107    m->m_Stopper = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &sctx);
     108    AssertReturn(m->m_Stopper, E_FAIL);
     109
     110    HRESULT hrc = HostDnsMonitor::init();
     111    AssertComRCReturn(hrc, hrc);
     112
     113    return updateInfo();
     114}
     115
     116
     117void HostDnsServiceDarwin::monitorThreadShutdown()
     118{
     119    ALock l(this);
     120    if (!m->m_fStop)
     121    {
     122        CFRunLoopSourceSignal(m->m_Stopper);
     123        CFRunLoopWakeUp(m->m_RunLoopRef);
     124       
     125        RTSemEventWait(m->m_evtStop, RT_INDEFINITE_WAIT);
     126    }
     127}
     128
     129
     130int HostDnsServiceDarwin::monitorWorker()
     131{
     132    m->m_RunLoopRef = CFRunLoopGetCurrent();
     133    AssertReturn(m->m_RunLoopRef, VERR_INTERNAL_ERROR);
     134
     135    CFRetain(m->m_RunLoopRef);
    51136
    52137    CFArrayRef watchingArrayRef = CFArrayCreate(NULL,
     
    55140    if (!watchingArrayRef)
    56141    {
    57         CFRelease(g_DnsWatcher);
     142        CFRelease(m->m_DnsWatcher);
    58143        return E_OUTOFMEMORY;
    59144    }
    60145
    61     if(SCDynamicStoreSetNotificationKeys(g_store, watchingArrayRef, NULL))
    62         CFRunLoopAddSource(CFRunLoopGetCurrent(), g_DnsWatcher, kCFRunLoopCommonModes);
     146    if(SCDynamicStoreSetNotificationKeys(m->m_store, watchingArrayRef, NULL))
     147        CFRunLoopAddSource(CFRunLoopGetCurrent(), m->m_DnsWatcher, kCFRunLoopCommonModes);
    63148
    64149    CFRelease(watchingArrayRef);
    65150
    66     RTSemEventSignal(g_DnsInitEvent);
    67 
    68     CFRunLoopRun();
    69 
    70     CFRelease(g_RunLoopRef);
     151    monitorThreadInitializationDone();
     152
     153    while (!m->m_fStop)
     154    {
     155        CFRunLoopRun();
     156    }
     157
     158    CFRelease(m->m_RunLoopRef);
     159
     160    /* We're notifying stopper thread. */
     161    RTSemEventSignal(m->m_evtStop);
    71162
    72163    return VINF_SUCCESS;
     
    74165
    75166
    76 HostDnsServiceDarwin::HostDnsServiceDarwin(){}
    77 
    78 
    79 HostDnsServiceDarwin::~HostDnsServiceDarwin()
    80 {
    81     if (g_RunLoopRef)
    82         CFRunLoopStop(g_RunLoopRef);
    83 
    84     CFRelease(g_DnsWatcher);
    85 
    86     CFRelease(g_store);
    87 }
    88 
    89 
    90 void HostDnsServiceDarwin::hostDnsServiceStoreCallback(void *arg0, void *arg1, void *info)
    91 {
    92     HostDnsServiceDarwin *pThis = (HostDnsServiceDarwin *)info;
    93 
    94     NOREF(arg0); /* SCDynamicStore */
    95     NOREF(arg1); /* CFArrayRef */
    96 
    97     ALock l(pThis);
    98     pThis->updateInfo();
    99     pThis->notifyAll();
    100 }
    101 
    102 
    103 HRESULT HostDnsServiceDarwin::init()
    104 {
    105     SCDynamicStoreContext ctx;
    106     RT_ZERO(ctx);
    107 
    108     ctx.info = this;
    109 
    110     g_store = SCDynamicStoreCreate(NULL, CFSTR("org.virtualbox.VBoxSVC"),
    111                                    (SCDynamicStoreCallBack)HostDnsServiceDarwin::hostDnsServiceStoreCallback,
    112                                    &ctx);
    113     AssertReturn(g_store, E_FAIL);
    114 
    115     g_DnsWatcher = SCDynamicStoreCreateRunLoopSource(NULL, g_store, 0);
    116     if (!g_DnsWatcher)
    117         return E_OUTOFMEMORY;
    118 
    119     HRESULT hrc = HostDnsMonitor::init();
    120     AssertComRCReturn(hrc, hrc);
    121 
    122     int rc = RTSemEventCreate(&g_DnsInitEvent);
    123     AssertRCReturn(rc, E_FAIL);
    124 
    125     rc = RTThreadCreate(&g_DnsMonitoringThread, hostMonitoringRoutine,
    126                         this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
    127     AssertRCReturn(rc, E_FAIL);
    128 
    129     RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
    130     return updateInfo();
    131 }
    132 
    133 
    134167HRESULT HostDnsServiceDarwin::updateInfo()
    135168{
    136     CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(g_store,
     169    CFPropertyListRef propertyRef = SCDynamicStoreCopyValue(m->m_store,
    137170                                                            kStateNetworkGlobalDNSKey);
    138171    /**
     
    216249    return S_OK;
    217250}
     251
     252void HostDnsServiceDarwin::Data::performShutdownCallback(void *info)
     253{
     254    HostDnsServiceDarwin::Data *pThis = static_cast<HostDnsServiceDarwin::Data *>(info);
     255    pThis->m_fStop = true;
     256}
  • trunk/src/VBox/Main/src-server/linux/HostDnsServiceLinux.cpp

    r49460 r50263  
    3333#include <fcntl.h>
    3434
     35#include <linux/limits.h>
     36
    3537#include <sys/inotify.h>
    3638#include <sys/types.h>
     
    4244
    4345
    44 static RTTHREAD g_DnsMonitoringThread;
    45 static RTSEMEVENT g_DnsInitEvent;
    4646static int g_DnsMonitorStop[2];
     47
     48static const std::string g_EtcFolder = "/etc";
     49static const std::string g_ResolvConf = "resolv.conf";
     50static const std::string g_ResolvConfFullPath = "/etc/resolv.conf";
    4751
    4852class FileDescriptor
     
    7175        AssertReturnVoid(FileDescriptor::fd != -1);
    7276    }
    73 
    7477};
    7578
    76 
    77 class 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;
     79struct InotifyEventWithName
     80{
     81    struct inotify_event e;
     82    char name[NAME_MAX];
    10283};
    10384
    104 
    10585HostDnsServiceLinux::~HostDnsServiceLinux()
    10686{
    107     send(g_DnsMonitorStop[0], "", 1, 0);
     87    monitorThreadShutdown();
    10888}
    10989
    11090
    111 int HostDnsServiceLinux::hostMonitoringRoutine(RTTHREAD ThreadSelf, void *pvUser)
    112 {
    113     NOREF(ThreadSelf);
     91int HostDnsServiceLinux::monitorWorker()
     92{
     93
    11494    AutoNotify a;
    115     HostDnsServiceLinux *dns = static_cast<HostDnsServiceLinux *>(pvUser);
    116     AutoWatcher w(a, std::string(dns->resolvConf().c_str()));
    11795
    11896    int rc = socketpair(AF_LOCAL, SOCK_DGRAM, 0, g_DnsMonitorStop);
     
    131109    polls[1].events = POLLIN;
    132110
    133     RTSemEventSignal(g_DnsInitEvent);
    134 
     111    monitorThreadInitializationDone();
     112
     113    int wd[2];
     114    wd[0] = wd[1] = -1;
     115    /* inotify inialization */
     116    wd[0] = inotify_add_watch(a.fileDescriptor(),
     117                              g_ResolvConfFullPath.c_str(), IN_CLOSE_WRITE|IN_DELETE_SELF);
     118
     119    /**
     120     * If /etc/resolv.conf exists we want to listen for movements: because
     121     * # mv /etc/resolv.conf ...
     122     * won't arm IN_DELETE_SELF on wd[0] instead it will fire IN_MOVE_FROM on wd[1].
     123     *
     124     * Because on some distributions /etc/resolv.conf is link, wd[0] can't detect deletion,
     125     * it's recognizible on directory level (wd[1]) only.
     126     */
     127    wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     128                              wd[0] == -1 ? IN_MOVED_TO|IN_CREATE : IN_MOVED_FROM|IN_DELETE);
     129
     130    struct InotifyEventWithName combo;
    135131    while(true)
    136132    {
     
    148144        if (polls[0].revents & POLLIN)
    149145        {
    150             dns->readResolvConf();
    151             /* notifyAll() takes required locks */
    152             dns->notifyAll();
    153 
    154             polls[0].revents = 0;
    155 
    156             inotify_event ev;
    157             rc = read(a.fileDescriptor(), static_cast<void *>(&ev), sizeof(ev));
    158             AssertMsg(rc == sizeof(ev) && ev.wd == w.fileDescriptor(), ("Hmm, debug me"));
     146            RT_ZERO(combo);
     147            ssize_t r = read(polls[0].fd, static_cast<void *>(&combo), sizeof(combo));
     148
     149            if (combo.e.wd == wd[0])
     150            {
     151                if (combo.e.mask & IN_CLOSE_WRITE)
     152                {
     153                    readResolvConf();
     154                    /* notifyAll() takes required locks */
     155                    notifyAll();
     156                }
     157                else if (combo.e.mask & IN_DELETE_SELF)
     158                {
     159                    inotify_rm_watch(a.fileDescriptor(), wd[0]); /* removes file watcher */
     160                    inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     161                                      IN_MOVED_TO|IN_CREATE); /* alter folder watcher */
     162                }
     163                else if (combo.e.mask & IN_IGNORED)
     164                {
     165                    wd[0] = -1; /* we want receive any events on this watch */
     166                }
     167                else
     168                {
     169                    /**
     170                     * It shouldn't happen, in release we will just ignore in debug
     171                     * we will have to chance to look at into inotify_event
     172                     */
     173                    AssertMsgFailed(("Debug Me!!!"));
     174                }
     175            }
     176            else if (combo.e.wd == wd[1])
     177            {
     178                if (   combo.e.mask & IN_MOVED_FROM
     179                    || combo.e.mask & IN_DELETE)
     180                {
     181                    if (g_ResolvConf == combo.e.name)
     182                    {
     183                        /**
     184                         * Our file has been moved so we should change watching mode.
     185                         */
     186                        inotify_rm_watch(a.fileDescriptor(), wd[0]);
     187                        wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     188                                                  IN_MOVED_TO|IN_CREATE);
     189                        AssertMsg(wd[1] != -1,
     190                                  ("It shouldn't happen, further investigation is needed\n"));
     191                    }
     192                }
     193                else
     194                {
     195                    AssertMsg(combo.e.mask & (IN_MOVED_TO|IN_CREATE),
     196                              ("%RX32 event isn't expected, we are waiting for IN_MOVED|IN_CREATE\n",
     197                               combo.e.mask));
     198                    if (g_ResolvConf == combo.e.name)
     199                    {
     200                        AssertMsg(wd[0] == -1, ("We haven't removed file watcher first\n"));
     201
     202                        /* alter folder watcher*/
     203                        wd[1] = inotify_add_watch(a.fileDescriptor(), g_EtcFolder.c_str(),
     204                                                  IN_MOVED_FROM|IN_DELETE);
     205                        AssertMsg(wd[1] != -1, ("It shouldn't happen.\n"));
     206
     207                        wd[0] = inotify_add_watch(a.fileDescriptor(),
     208                                                  g_ResolvConfFullPath.c_str(),
     209                                                  IN_CLOSE_WRITE | IN_DELETE_SELF);
     210                        AssertMsg(wd[0] != -1, ("Adding watcher to file (%s) has been failed!\n",
     211                                                g_ResolvConfFullPath.c_str()));
     212
     213                        /* Notify our listeners */
     214                        readResolvConf();
     215                        notifyAll();
     216
     217                    }
     218                }
     219            }
     220            else
     221            {
     222                /* It shouldn't happen */
     223                AssertMsgFailed(("Shouldn't happen! Please debug me!"));
     224            }
    159225        }
    160226    }
     
    162228
    163229
    164 HRESULT HostDnsServiceLinux::init(const char *aResolvConfFileName)
    165 {
    166     HRESULT hrc = HostDnsServiceResolvConf::init(aResolvConfFileName);
    167     AssertComRCReturnRC(hrc);
    168 
    169     int rc = RTSemEventCreate(&g_DnsInitEvent);
    170     AssertRCReturn(rc, E_FAIL);
    171 
    172     rc = RTThreadCreate(&g_DnsMonitoringThread, HostDnsServiceLinux::hostMonitoringRoutine,
    173                         this, 128 * _1K, RTTHREADTYPE_IO, 0, "dns-monitor");
    174     AssertRCReturn(rc, E_FAIL);
    175 
    176     RTSemEventWait(g_DnsInitEvent, RT_INDEFINITE_WAIT);
    177 
    178     return S_OK;
     230void HostDnsServiceLinux::monitorThreadShutdown()
     231{
     232    send(g_DnsMonitorStop[0], "", 1, 0);
    179233}
  • trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp

    r49445 r50263  
    1313#include "../HostDnsService.h"
    1414
    15 static HKEY g_hKeyTcpipParameters;
    16 
    17 HostDnsServiceWin::HostDnsServiceWin()
    18 {
    19     RegOpenKeyEx(HKEY_LOCAL_MACHINE,
    20                  TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
    21                  0, KEY_READ, &g_hKeyTcpipParameters);
     15struct HostDnsServiceWin::Data
     16{
     17    HostDnsServiceWin::Data(){}
     18    HKEY hKeyTcpipParameters;
     19#define DATA_DNS_UPDATE_EVENT 0
     20#define DATA_SHUTDOWN_EVENT   1
     21#define DATA_MAX_EVENT        2
     22    HANDLE haDataEvent[DATA_MAX_EVENT];
     23};
     24
     25static inline int registerNotification(const HKEY& hKey, HANDLE& hEvent)
     26{
     27    LONG lrc = RegNotifyChangeKeyValue(hKey,
     28                                       TRUE,
     29                                       REG_NOTIFY_CHANGE_LAST_SET,
     30                                       hEvent,
     31                                       TRUE);
     32    AssertMsgReturn(lrc == ERROR_SUCCESS,
     33                    ("Failed to register event on the key. Please debug me!"),
     34                    VERR_INTERNAL_ERROR);
     35
     36    return VINF_SUCCESS;
     37}
     38
     39HostDnsServiceWin::HostDnsServiceWin():HostDnsMonitor(true), m(NULL)
     40{
     41    m = new Data();
     42
     43    m->haDataEvent[DATA_DNS_UPDATE_EVENT] = CreateEvent(NULL,
     44      TRUE, FALSE, NULL);
     45    AssertReleaseMsg(m->haDataEvent[DATA_DNS_UPDATE_EVENT],
     46      ("Failed to create event for DNS event (%d)\n", GetLastError()));
     47
     48    m->haDataEvent[DATA_SHUTDOWN_EVENT] = CreateEvent(NULL,
     49      TRUE, FALSE, NULL);
     50    AssertReleaseMsg(m->haDataEvent[DATA_SHUTDOWN_EVENT],
     51      ("Failed to create event for Shutdown signal (%d)\n", GetLastError()));
     52
     53    LONG lrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
     54      TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
     55      0, KEY_READ|KEY_NOTIFY, &m->hKeyTcpipParameters);
     56    AssertReleaseMsg(lrc == ERROR_SUCCESS,
     57      ("Failed to open Registry Key for read and update notifications (%d)\n",
     58      GetLastError()));
    2259}
    2360
     
    2562HostDnsServiceWin::~HostDnsServiceWin()
    2663{
    27     if (!g_hKeyTcpipParameters)
     64    if (m && !m->hKeyTcpipParameters)
    2865    {
    29         RegCloseKey(g_hKeyTcpipParameters);
    30         g_hKeyTcpipParameters = 0;
     66        RegCloseKey(m->hKeyTcpipParameters);
     67        m->hKeyTcpipParameters = 0;
     68
     69        CloseHandle(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
     70        CloseHandle(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
     71
     72        delete m;
     73
     74        m = NULL;
    3175    }
    3276}
     
    3983
    4084    return updateInfo();
     85}
     86
     87
     88void HostDnsServiceWin::monitorThreadShutdown()
     89{
     90    SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
     91}
     92
     93
     94int HostDnsServiceWin::monitorWorker()
     95{
     96    registerNotification(m->hKeyTcpipParameters,
     97                         m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
     98
     99    monitorThreadInitializationDone();
     100
     101    DWORD dwRc;
     102    while (true)
     103    {
     104        dwRc = WaitForMultipleObjects(DATA_MAX_EVENT,
     105                                      m->haDataEvent,
     106                                      FALSE,
     107                                      INFINITE);
     108        AssertMsgReturn(dwRc != WAIT_FAILED,
     109                        ("WaitForMultipleObjects failed (%d) to wait! Please debug",
     110                         GetLastError()), VERR_INTERNAL_ERROR);
     111
     112        if ((dwRc - WAIT_OBJECT_0) == DATA_DNS_UPDATE_EVENT)
     113        {
     114            updateInfo();
     115            notifyAll();
     116            ResetEvent(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
     117            registerNotification(m->hKeyTcpipParameters,
     118                                 m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
     119
     120        }
     121        else if ((dwRc - WAIT_OBJECT_0) == DATA_SHUTDOWN_EVENT)
     122        {
     123            break;
     124        }
     125        else
     126        {
     127            AssertMsgFailedReturn(
     128              ("WaitForMultipleObjects returns out of bound index %d. Please debug!",
     129                                   dwRc),
     130              VERR_INTERNAL_ERROR);
     131        }
     132    }
     133    return VINF_SUCCESS;
    41134}
    42135
     
    62155        DWORD cbKeyData = sizeof(keyData);
    63156
    64         hrc = RegEnumValueA(g_hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
     157        hrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
    65158                            &keyType, keyData, &cbKeyData);
    66159        if (   hrc == ERROR_SUCCESS
     
    113206
    114207
    115 
    116208void HostDnsServiceWin::strList2List(std::vector<std::string>& lst, char *strLst)
    117209{
Note: See TracChangeset for help on using the changeset viewer.

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