📄 dnsservice.cpp
字号:
/** * 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 <cc++/thread.h>/** * Simple Empty Constructor */DNSService::DNSService(){ _start = false; _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 */voidDNSService::startScanServices() { for (std::vector<DNSQueryThread *>::iterator iter = _queryThread.begin();iter!=_queryThread.end();iter++) { (*iter)->start(); } _start = true;}/** * 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(); notify(); 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(); notify();}/** * Return every services */DNSServiceMapDNSService::getServices() { ost::MutexLock m(_mutex); return _services;}/** * 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(); } } notify();}void DNSServiceAddServicesCallback(DNSServiceRef, DNSServiceFlags flags, uint32_t, 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, DNSServiceFlags flags, uint32_t, DNSServiceErrorType errorCode, const char *fullname, uint16_t, uint16_t, uint16_t rdlen, const void *rdata, uint32_t, 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); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -