• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

DNSSD

publicservice.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2004, 2005 Jakub Stachowski <qbast@go2.pl>
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Library General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Library General Public License
00016  * along with this library; see the file COPYING.LIB.  If not, write to
00017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include "config.h"
00022 
00023 #include "publicservice.h"
00024 #ifdef HAVE_SYS_TYPES_H
00025 #include <sys/types.h>
00026 #endif
00027 #include <netinet/in.h>
00028 #include <sys/socket.h>
00029 #include <qapplication.h>
00030 #include <network/ksocketaddress.h>
00031 #include <kurl.h>
00032 #include <unistd.h>
00033 #include "sdevent.h"
00034 #include "responder.h"
00035 #include "servicebrowser.h"
00036 #include "settings.h"
00037 
00038 namespace DNSSD
00039 {
00040 static unsigned long publicIP();
00041 #ifdef HAVE_DNSSD
00042 void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
00043                const char*, const char*, void *context);
00044 #endif
00045 class PublicServicePrivate : public Responder
00046 {
00047 public:
00048     PublicServicePrivate() : m_published(false)
00049     {}
00050     bool m_published;
00051 };
00052 
00053 PublicService::PublicService(const QString& name, const QString& type, unsigned int port,
00054                   const QString& domain)
00055         : QObject(), ServiceBase(name, type, QString::null, domain, port)
00056 {
00057     d = new PublicServicePrivate;
00058     if (domain.isNull())
00059         if (Configuration::publishType()==Configuration::EnumPublishType::LAN) m_domain="local.";
00060         else m_domain=Configuration::publishDomain();
00061 }
00062 
00063 
00064 PublicService::~PublicService()
00065 {
00066     stop();
00067     delete d;
00068 }
00069 
00070 void PublicService::setServiceName(const QString& serviceName)
00071 {
00072     m_serviceName = serviceName;
00073     if (d->isRunning()) {
00074         stop();
00075         publishAsync();
00076     }
00077 }
00078 
00079 void PublicService::setDomain(const QString& domain)
00080 {
00081     m_domain = domain;
00082     if (d->isRunning()) {
00083     stop();
00084     publishAsync();
00085     }
00086 }
00087 
00088 
00089 void PublicService::setType(const QString& type)
00090 {
00091     m_type = type;
00092     if (d->isRunning()) {
00093         stop();
00094         publishAsync();
00095     }
00096 }
00097 
00098 void PublicService::setPort(unsigned short port)
00099 {
00100     m_port = port;
00101     if (d->isRunning()) {
00102         stop();
00103         publishAsync();
00104     }
00105 }
00106 
00107 bool PublicService::isPublished() const
00108 {
00109     return d->m_published;
00110 }
00111 
00112 void PublicService::setTextData(const QMap<QString,QString>& textData)
00113 {
00114     m_textData = textData;
00115     if (d->isRunning()) {
00116         stop();
00117         publishAsync();
00118     }
00119 }
00120 
00121 bool PublicService::publish()
00122 {
00123     publishAsync();
00124     while (d->isRunning() && !d->m_published) d->process();
00125     return d->m_published;
00126 }
00127 
00128 void PublicService::stop()
00129 {
00130     d->stop();
00131     d->m_published = false;
00132 }
00133 
00134 void PublicService::publishAsync()
00135 {
00136     if (d->isRunning()) stop();
00137 #ifdef HAVE_DNSSD
00138     if (ServiceBrowser::isAvailable()==ServiceBrowser::Working) {
00139         TXTRecordRef txt;
00140         TXTRecordCreate(&txt,0,0);
00141         QMap<QString,QString>::ConstIterator itEnd = m_textData.end();
00142         for (QMap<QString,QString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it) {
00143             QCString value = it.data().utf8();
00144             if (TXTRecordSetValue(&txt,it.key().utf8(),value.length(),value)!=kDNSServiceErr_NoError) {
00145                 TXTRecordDeallocate(&txt);
00146                 emit published(false);
00147                 return;
00148             }
00149         }
00150         DNSServiceRef ref;
00151         if (DNSServiceRegister(&ref,0,0,m_serviceName.utf8(),m_type.ascii(),domainToDNS(m_domain),NULL,
00152             htons(m_port),TXTRecordGetLength(&txt),TXTRecordGetBytesPtr(&txt),publish_callback,
00153             reinterpret_cast<void*>(this)) == kDNSServiceErr_NoError) d->setRef(ref);
00154         TXTRecordDeallocate(&txt);
00155     }
00156 #endif
00157     if (!d->isRunning()) emit published(false);
00158 }
00159 
00160 #ifdef HAVE_DNSSD
00161 void publish_callback (DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
00162                const char*, const char*, void *context)
00163 {
00164     QObject *obj = reinterpret_cast<QObject*>(context);
00165     if (errorCode != kDNSServiceErr_NoError) {
00166         ErrorEvent err;
00167         QApplication::sendEvent(obj, &err);
00168     } else {
00169         PublishEvent pev(QString::fromUtf8(name));
00170         QApplication::sendEvent(obj, &pev);
00171     }
00172 }
00173 #endif
00174 
00175 const KURL PublicService::toInvitation(const QString& host)
00176 {
00177     KURL url;
00178     url.setProtocol("invitation");
00179     if (host.isEmpty()) { // select best address
00180         unsigned long s_address = publicIP();
00181         if (!s_address) return KURL();
00182         KNetwork::KIpAddress addr(s_address);
00183         url.setHost(addr.toString());
00184     } else  url.setHost(host);
00185     //FIXME: if there is no public interface, select any non-loopback
00186     url.setPort(m_port);
00187     url.setPath("/"+m_type+"/"+KURL::encode_string(m_serviceName));
00188     QString query;
00189     QMap<QString,QString>::ConstIterator itEnd = m_textData.end();
00190     for (QMap<QString,QString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it)
00191         url.addQueryItem(it.key(),it.data());;
00192     return url;
00193 }
00194 
00195 void PublicService::customEvent(QCustomEvent* event)
00196 {
00197     if (event->type()==QEvent::User+SD_ERROR) {
00198         stop();
00199         emit published(false);
00200     }
00201     if (event->type()==QEvent::User+SD_PUBLISH) {
00202         d->m_published=true;
00203         emit published(true);
00204         m_serviceName = static_cast<PublishEvent*>(event)->m_name;
00205     }
00206 }
00207 
00208 void PublicService::virtual_hook(int, void*)
00209 {
00210 }
00211 
00212 static unsigned long publicIP()
00213 {
00214     struct sockaddr_in addr;
00215     socklen_t len = sizeof(addr);
00216     int sock = socket(AF_INET,SOCK_DGRAM,0);
00217     if (sock == -1) return 0;
00218     addr.sin_family = AF_INET;
00219     addr.sin_port = 1;  // Not important, any port and public address will do
00220     addr.sin_addr.s_addr = 0x11111111;
00221     if ((connect(sock,(const struct sockaddr*)&addr,sizeof(addr))) == -1) { close(sock); return 0; }
00222     if ((getsockname(sock,(struct sockaddr*)&addr, &len)) == -1) { close(sock); return 0; }
00223     ::close(sock);
00224     return addr.sin_addr.s_addr;
00225 }
00226 
00227 
00228 }
00229 
00230 #include "publicservice.moc"

DNSSD

Skip menu "DNSSD"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal