00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avahi-publicservice_p.h"
00022
00023 #include <QtCore/QCoreApplication>
00024 #include <QtCore/QStringList>
00025
00026 #include "publicservice.h"
00027 #ifdef HAVE_SYS_TYPES_H
00028 #include <sys/types.h>
00029 #endif
00030 #include "servicebrowser.h"
00031 #include "settings.h"
00032 #include "avahi_server_interface.h"
00033 #include "avahi_entrygroup_interface.h"
00034 #ifndef KDE_USE_FINAL
00035 Q_DECLARE_METATYPE(QList<QByteArray>)
00036 #endif
00037
00038 namespace DNSSD
00039 {
00040
00041 PublicService::PublicService(const QString& name, const QString& type, unsigned int port,
00042 const QString& domain, const QStringList& subtypes)
00043 : QObject(), ServiceBase(new PublicServicePrivate(this, name, type, domain, port))
00044 {
00045 K_D;
00046 if (domain.isNull()) d->m_domain="local.";
00047 d->m_subtypes=subtypes;
00048 }
00049
00050
00051 PublicService::~PublicService()
00052 {
00053 stop();
00054 }
00055
00056 void PublicServicePrivate::tryApply()
00057 {
00058 if (fillEntryGroup()) commit();
00059 else {
00060 m_parent->stop();
00061 emit m_parent->published(false);
00062 }
00063 }
00064
00065 void PublicService::setServiceName(const QString& serviceName)
00066 {
00067 K_D;
00068 d->m_serviceName = serviceName;
00069 if (d->m_running) {
00070 d->m_group->Reset();
00071 d->tryApply();
00072 }
00073 }
00074
00075 void PublicService::setDomain(const QString& domain)
00076 {
00077 K_D;
00078 d->m_domain = domain;
00079 if (d->m_running) {
00080 d->m_group->Reset();
00081 d->tryApply();
00082 }
00083 }
00084
00085
00086 void PublicService::setType(const QString& type)
00087 {
00088 K_D;
00089 d->m_type = type;
00090 if (d->m_running) {
00091 d->m_group->Reset();
00092 d->tryApply();
00093 }
00094 }
00095
00096 void PublicService::setSubTypes(const QStringList& subtypes)
00097 {
00098 K_D;
00099 d->m_subtypes = subtypes;
00100 if (d->m_running) {
00101 d->m_group->Reset();
00102 d->tryApply();
00103 }
00104 }
00105
00106 QStringList PublicService::subtypes() const
00107 {
00108 K_D;
00109 return d->m_subtypes;
00110 }
00111
00112 void PublicService::setPort(unsigned short port)
00113 {
00114 K_D;
00115 d->m_port = port;
00116 if (d->m_running) {
00117 d->m_group->Reset();
00118 d->tryApply();
00119 }
00120 }
00121
00122 void PublicService::setTextData(const QMap<QString,QByteArray>& textData)
00123 {
00124 K_D;
00125 d->m_textData = textData;
00126 if (d->m_running) {
00127 d->m_group->Reset();
00128 d->tryApply();
00129 }
00130 }
00131
00132 bool PublicService::isPublished() const
00133 {
00134 K_D;
00135 return d->m_published;
00136 }
00137
00138 bool PublicService::publish()
00139 {
00140 K_D;
00141 publishAsync();
00142 while (d->m_running && !d->m_published) QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
00143 return d->m_published;
00144 }
00145
00146 void PublicService::stop()
00147 {
00148 K_D;
00149 if (d->m_group) d->m_group->Reset();
00150 d->m_published = false;
00151 }
00152 bool PublicServicePrivate::fillEntryGroup()
00153 {
00154 registerTypes();
00155 if (!m_group) {
00156 QDBusReply<QDBusObjectPath> rep=m_server->EntryGroupNew();
00157 if (!rep.isValid()) return false;
00158 m_group=new org::freedesktop::Avahi::EntryGroup("org.freedesktop.Avahi",rep.value().path(), QDBusConnection::systemBus());
00159 connect(m_group,SIGNAL(StateChanged(int,const QString&)), this, SLOT(groupStateChanged(int,const QString&)));
00160 }
00161 if (m_serviceName.isNull()) {
00162 QDBusReply<QString> rep=m_server->GetHostName();
00163 if (!rep.isValid()) return false;
00164 m_serviceName=rep.value();
00165 }
00166
00167 QList<QByteArray> txt;
00168 QMap<QString,QByteArray>::ConstIterator itEnd = m_textData.end();
00169 for (QMap<QString,QByteArray>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it)
00170 if (it.value().isNull()) txt.append(it.key().toAscii());
00171 else txt.append(it.key().toAscii()+'='+it.value());
00172 m_group->AddService(-1,-1, 0, m_serviceName, m_type , domainToDNS(m_domain) ,
00173 m_hostName, m_port,txt);
00174 Q_FOREACH(const QString &subtype, m_subtypes)
00175 m_group->AddServiceSubtype(-1,-1, 0, m_serviceName, m_type, domainToDNS(m_domain) , subtype);
00176 return true;
00177 }
00178
00179 void PublicServicePrivate::serverStateChanged(int s,const QString&)
00180 {
00181 if (!m_running) return;
00182 switch (s) {
00183 case AVAHI_SERVER_INVALID:
00184 m_parent->stop();
00185 emit m_parent->published(false);
00186 break;
00187 case AVAHI_SERVER_REGISTERING:
00188 case AVAHI_SERVER_COLLISION:
00189 m_group->Reset();
00190 m_collision=true;
00191 break;
00192 case AVAHI_SERVER_RUNNING:
00193 if (m_collision) {
00194 m_collision=false;
00195 tryApply();
00196 }
00197 }
00198 }
00199
00200 void PublicService::publishAsync()
00201 {
00202 K_D;
00203 if (d->m_running) stop();
00204
00205 if (!d->m_server) {
00206 d->m_server = new org::freedesktop::Avahi::Server("org.freedesktop.Avahi","/",QDBusConnection::systemBus());
00207 connect(d->m_server,SIGNAL(StateChanged(int,const QString&)),d,SLOT(serverStateChanged(int,const QString&)));
00208 }
00209
00210 int state=AVAHI_SERVER_INVALID;
00211 QDBusReply<int> rep=d->m_server->GetState();
00212
00213 if (rep.isValid()) state=rep.value();
00214
00215 d->m_running=true;
00216 d->m_collision=true;
00217 d->serverStateChanged(state, QString());
00218 }
00219
00220
00221 void PublicServicePrivate::groupStateChanged(int s, const QString& reason)
00222 {
00223 switch (s) {
00224 case AVAHI_ENTRY_GROUP_COLLISION: {
00225 QDBusReply<QString> rep=m_server->GetAlternativeServiceName(m_serviceName);
00226 if (rep.isValid()) m_parent->setServiceName(rep.value());
00227 else serverStateChanged(AVAHI_SERVER_INVALID, reason);
00228 break;
00229 }
00230 case AVAHI_ENTRY_GROUP_ESTABLISHED:
00231 m_published=true;
00232 emit m_parent->published(true);
00233 break;
00234 case AVAHI_ENTRY_GROUP_FAILURE:
00235 serverStateChanged(AVAHI_SERVER_INVALID, reason);
00236 default:
00237 break;
00238 }
00239 }
00240
00241 void PublicService::virtual_hook(int, void*)
00242 {
00243 }
00244
00245
00246 }
00247
00248 #include "publicservice.moc"
00249 #include "avahi-publicservice_p.moc"