Skip to content
Snippets Groups Projects
Select Git revision
  • 4ca867750560e3a129c5cdd2afca1eaf2ce12861
  • master default protected
  • release/202005
  • release/202001
  • release/201912
  • release/201911
  • release/releaseWindowsTestOne
  • release/windowsReleaseTest
  • release/releaseTest
  • release/releaseWindowsTest
  • release/201910
  • release/qt/201910
  • release/windows-test/201910
  • release/201908
  • release/201906
  • release/201905
  • release/201904
  • release/201903
  • release/201902
  • release/201901
  • release/201812
  • 4.0.0
  • 2.2.0
  • 2.1.0
  • 2.0.1
  • 2.0.0
  • 1.4.1
  • 1.4.0
  • 1.3.0
  • 1.2.0
  • 1.1.0
31 results

ConfigurationManager.hpp

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    DNSService.cpp 6.84 KiB
    /**
     *  Copyright (C) 2005 Savoir-Faire Linux inc.
     *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
     *                                                                              
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 2 of the License, or
     *  (at your option) any later version.
     *                                                                                
     *  This program is distributed in the hope that it will be useful,
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     *  GNU General Public License for more details.
     *                                                                              
     *  You should have received a copy of the GNU General Public License
     *  along with this program; if not, write to the Free Software
     *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     */
     
     /**
      * Inspired by http://braden.machacking.net/zerobrowse.cpp and
      * http://developer.kde.org/documentation/library/3.4-api/dnssd/html/remoteservice_8cpp-source.html
      */
    #include "DNSService.h"
    #include "DNSServiceTXTRecord.h"
    #include "DNSQueryThread.h"
    #include "../global.h" // for _debug()
    
    #include <cc++/thread.h>
    
    /**
     * Simple Empty Constructor
     */
    DNSService::DNSService()
    {
      _regtypeList.push_back("_sip._udp");
    #ifdef USE_IAX2
      _regtypeList.push_back("_iax._udp");
    #endif
      
      // for the thread, the ifdef add a dynamic _regtypeList problem
      for (std::list<std::string>::iterator iterThread=_regtypeList.begin();
           iterThread!=_regtypeList.end();
           iterThread++) {
        _queryThread.push_back(new DNSQueryThread(this, (*iterThread).c_str()));
      }
    }
    
    /**
     * Simple Empty Destructor
     */
    DNSService::~DNSService()
    {
      int cntThread = _queryThread.size();
      for (int iThread=0;iThread<cntThread;iThread++) {
        delete _queryThread[iThread];
        _queryThread[iThread] = NULL;
      }
    }
    
    /**
     * Look for zeroconf services and add them to _services
     */
    void
    DNSService::scanServices() 
    {
      for (std::vector<DNSQueryThread *>::iterator iter = _queryThread.begin();iter!=_queryThread.end();iter++) {
        (*iter)->start();
      }
    }
    
    /**
     * Add one service to the list of actual services
     * @param service Service to add to the list
     */
    void DNSService::addService(const std::string &service) 
    {
      DNSServiceTXTRecord txtRecord;
      _mutex.enterMutex();
      _services[service] = txtRecord;
      // we leave before the queryService since, each 
      // thread will modify a DNSServiceTXTRecord of a difference services
      _mutex.leaveMutex();
      queryService(service);
    }
    
    /**
     * Remove one service to the list of actual services
     * @param service Service to remove to the list
     */
    void DNSService::removeService(const std::string &service) 
    {
      _mutex.enterMutex();
      _services.erase(service);
      _mutex.leaveMutex();
    }
    
    /**
     * Display the list of available services
     * run() method should be call before
     */
    void 
    DNSService::listServices() 
    {
      _debug("Number of services detected: %d\n", _services.size());
      DNSServiceMap::iterator iterTR;
      for (iterTR = _services.begin(); iterTR != _services.end(); iterTR++) {
        _debug("name: %s\n", iterTR->first.c_str());
        _debug("size: %d\n", iterTR->second.size());
        iterTR->second.listValue();
      }
    }
    
    /**
     * Query a service and wait for the anwser
     * the queryCallback will show the result
     * @param service The service full adress
     */
    void 
    DNSService::queryService(const std::string &service) 
    {
      DNSServiceErrorType theErr=0;
      DNSServiceRef       myServRef=0;
      DNSServiceFlags     resultFlags=0;
      
      theErr = DNSServiceQueryRecord(&myServRef, 
    				 resultFlags, 
    				 0, 
    				 service.c_str(), 
    				 kDNSServiceType_TXT, 
    				 kDNSServiceClass_IN, 
    				 DNSServiceQueryRecordCallback, 
    				 (void*)this);
      if (theErr == kDNSServiceErr_NoError) {
        DNSServiceProcessResult(myServRef); // blockage...
        DNSServiceRefDeallocate(myServRef);
      }
    }
    
    /**
     * Overloadding queryService
     * @param service service name
     * @param regtype registred type of service
     * @param domain  domain (habitually local.)
     */
    void 
    DNSService::queryService(const char *service, const char *regtype, const char *domain) 
    {
      char serviceName[kDNSServiceMaxDomainName+1];
      DNSServiceConstructFullName(serviceName, service, regtype, domain);
      queryService(std::string(serviceName));
    }
    
    /**
     * Add a txt record with the queryService callback answser data
     * @param rdlen the length of the txt record data
     * @param rdata txt record data
     */
    void 
    DNSService::addTXTRecord(const char *fullname, uint16_t rdlen, const void *rdata) 
    {
      char key[256];
      
      const char *value;
      uint8_t valueLen; // 0 to 256 by type restriction
      char valueTab[256];
      
      
      uint16_t keyCount = TXTRecordGetCount(rdlen, rdata);
      for (int iKey=0; iKey<keyCount; iKey++) {
        TXTRecordGetItemAtIndex (rdlen, rdata, iKey, 256, key, &valueLen, (const void **)(&value));
        if (value) {
          bcopy(value, valueTab, valueLen);
          valueTab[valueLen]='\0';
          _mutex.enterMutex(); // extra-careful
          _services[fullname].addKeyValue(key, valueTab);
          _mutex.leaveMutex();
        } else {
          _mutex.enterMutex();
          _services[fullname].removeKey(key);
          _mutex.leaveMutex();
        }
      }
    
      // TODO: remove this call, when we do not debug..
      // addTXTRecord is a good function to know changes... 
      listServices();
    }
    
    void 
    DNSServiceAddServicesCallback(DNSServiceRef sdRef,
    						DNSServiceFlags flags,
    						uint32_t interfaceIndex,
    						DNSServiceErrorType errorCode,
    						const char *serviceName,
    						const char *replyType,
    						const char *replyDomain,
    						void *context)
    {
      if (errorCode==kDNSServiceErr_NoError) {
      
        if (flags) {
          DNSService *service = (DNSService*)context;
          std::string tempService;
          tempService = std::string(serviceName) + "." + std::string(replyType) + std::string(replyDomain);
          if (flags&kDNSServiceFlagsAdd) {
            _debug("DNSServiceAddServicesCallback call addService\n");
            service->addService(tempService);
          } else {
            _debug("DNSServiceAddServicesCallback call removeService\n");
            service->removeService(tempService);
          }
        }
      } else {
         // TODO: error handling
      }
    }
    
    void 
    DNSServiceQueryRecordCallback(
    	DNSServiceRef DNSServiceRef,
    	DNSServiceFlags flags,
    	uint32_t interfaceIndex,
    	DNSServiceErrorType errorCode,
    	const char *fullname,
    	uint16_t rrtype,
    	uint16_t rrclass,
    	uint16_t rdlen,
    	const void *rdata,
    	uint32_t ttl,
    	void *context)
    {
      if (errorCode==kDNSServiceErr_NoError) {
        if (flags&kDNSServiceFlagsAdd) {
          _debug("DNSServiceQueryRecordCallback call addTXTRecord\n");
          ((DNSService *)context)->addTXTRecord(fullname, rdlen, rdata);
        } else {
          _debug("DNSServiceQueryRecordCallback call removeService\n");
          ((DNSService *)context)->removeService(fullname);
        }
      }
    }