/* This file is part of the KDE project * * Copyright (C) 2004, 2005 Jakub Stachowski * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include "publicservice.h" #include "servicebase_p.h" #include "mdnsd-sdevent.h" #include "mdnsd-responder.h" #include "settings.h" #define K_D PublicServicePrivate* d=static_cast(this->d) namespace DNSSD { void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char*, const char*, void *context); class PublicServicePrivate : public Responder, public ServiceBasePrivate { public: PublicServicePrivate(PublicService* parent, const QString& name, const QString& type, unsigned int port, const QString& domain) : Responder(), ServiceBasePrivate(name, type, domain, QString(), port), m_published(false), m_parent(parent) {} bool m_published; PublicService* m_parent; QStringList m_subtypes; virtual void customEvent(QEvent* event); }; PublicService::PublicService(const QString& name, const QString& type, unsigned int port, const QString& domain, const QStringList& subtypes) : QObject(), ServiceBase(new PublicServicePrivate(this, name, type, port, domain)) { K_D; if (domain.isNull()) d->m_domain="local."; d->m_subtypes=subtypes; } PublicService::~PublicService() { stop(); } void PublicService::setServiceName(const QString& serviceName) { K_D; d->m_serviceName = serviceName; if (d->isRunning()) { stop(); publishAsync(); } } void PublicService::setDomain(const QString& domain) { K_D; d->m_domain = domain; if (d->isRunning()) { stop(); publishAsync(); } } QStringList PublicService::subtypes() const { K_D; return d->m_subtypes; } void PublicService::setType(const QString& type) { K_D; d->m_type = type; if (d->isRunning()) { stop(); publishAsync(); } } void PublicService::setSubTypes(const QStringList& subtypes) { K_D; d->m_subtypes = subtypes; if (d->isRunning()) { stop(); publishAsync(); } } void PublicService::setPort(unsigned short port) { K_D; d->m_port = port; if (d->isRunning()) { stop(); publishAsync(); } } bool PublicService::isPublished() const { K_D; return d->m_published; } void PublicService::setTextData(const QMap& textData) { K_D; d->m_textData = textData; if (d->isRunning()) { stop(); publishAsync(); } } bool PublicService::publish() { K_D; publishAsync(); while (d->isRunning() && !d->m_published) d->process(); return d->m_published; } void PublicService::stop() { K_D; d->stop(); d->m_published = false; } void PublicService::publishAsync() { K_D; if (d->isRunning()) stop(); TXTRecordRef txt; TXTRecordCreate(&txt,0,0); QMap::ConstIterator itEnd = d->m_textData.end(); for (QMap::ConstIterator it = d->m_textData.begin(); it!=itEnd ; ++it) { if (TXTRecordSetValue(&txt,it.key().toUtf8(),it.value().length(),it.value())!=kDNSServiceErr_NoError) { TXTRecordDeallocate(&txt); emit published(false); return; } } DNSServiceRef ref; QString fullType=d->m_type; Q_FOREACH(const QString &subtype, d->m_subtypes) fullType+=','+subtype; if (DNSServiceRegister(&ref,0,0,d->m_serviceName.toUtf8(),fullType.toLatin1().constData(),domainToDNS(d->m_domain),NULL, htons(d->m_port),TXTRecordGetLength(&txt),TXTRecordGetBytesPtr(&txt),publish_callback, reinterpret_cast(d)) == kDNSServiceErr_NoError) d->setRef(ref); TXTRecordDeallocate(&txt); if (!d->isRunning()) emit published(false); } void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char*, const char*, void *context) { QObject *obj = reinterpret_cast(context); if (errorCode != kDNSServiceErr_NoError) { ErrorEvent err; QCoreApplication::sendEvent(obj, &err); } else { PublishEvent pev(QString::fromUtf8(name)); QCoreApplication::sendEvent(obj, &pev); } } void PublicServicePrivate::customEvent(QEvent* event) { if (event->type()==QEvent::User+SD_ERROR) { m_parent->stop(); emit m_parent->published(false); } if (event->type()==QEvent::User+SD_PUBLISH) { m_published=true; emit m_parent->published(true); m_serviceName = static_cast(event)->m_name; } } } #include "moc_publicservice.cpp"