23 #include "publicservice.h"
24 #ifdef HAVE_SYS_TYPES_H
25 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <sys/socket.h>
29 #include <tqapplication.h>
30 #include <network/tdesocketaddress.h>
34 #include <avahi-client/client.h>
36 #include <avahi-client/publish.h>
38 #include <avahi-common/alternative.h>
39 #include <avahi-common/strlst.h>
42 #include "responder.h"
43 #include "servicebrowser.h"
48 static unsigned long publicIP();
51 void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s,
void *context);
54 class PublicServicePrivate
57 PublicServicePrivate() : m_published(false), m_running(false), m_collision(false)
66 AvahiEntryGroup* m_group;
71 if (!m_collision) avahi_entry_group_commit(m_group);
78 const TQString& domain)
79 : TQObject(),
ServiceBase(name, type, TQString::null, domain, port)
81 d =
new PublicServicePrivate;
83 if (Responder::self().client()) {
84 d->m_group = avahi_entry_group_new(Responder::self().client(), publish_callback,
this);
85 connect(&Responder::self(),TQT_SIGNAL(stateChanged(AvahiClientState)),
this,TQT_SLOT(clientState(AvahiClientState)));
89 if (Configuration::publishType()==Configuration::EnumPublishType::LAN) m_domain=
"local.";
90 else m_domain=Configuration::publishDomain();
94 PublicService::~PublicService()
97 if (d->m_group) avahi_entry_group_free(d->m_group);
102 void PublicService::tryApply()
104 if (fillEntryGroup()) d->commit();
116 avahi_entry_group_reset(d->m_group);
127 avahi_entry_group_reset(d->m_group);
139 avahi_entry_group_reset(d->m_group);
150 avahi_entry_group_reset(d->m_group);
161 avahi_entry_group_reset(d->m_group);
169 return d->m_published;
175 while (d->m_running && !d->m_published) Responder::self().process();
176 return d->m_published;
182 if (d->m_group) avahi_entry_group_reset(d->m_group);
184 d->m_published =
false;
186 bool PublicService::fillEntryGroup()
189 AvahiStringList *s=0;
190 TQMap<TQString,TQString>::ConstIterator itEnd =
m_textData.end();
191 for (TQMap<TQString,TQString>::ConstIterator it =
m_textData.begin(); it!=itEnd ; ++it)
192 s = avahi_string_list_add_pair(s, it.key().utf8(),it.data().utf8());
194 bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, (AvahiPublishFlags)0,
195 m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
196 m_type.ascii(),domainToDNS(m_domain),m_hostName.utf8(),m_port,s));
198 bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
199 m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
200 m_type.ascii(),m_domain.utf8(),m_hostName.utf8(),m_port,s));
202 avahi_string_list_free(s);
209 void PublicService::clientState(AvahiClientState s)
211 if (!d->m_running)
return;
215 case AVAHI_CLIENT_FAILURE:
217 case AVAHI_CLIENT_S_INVALID:
218 case AVAHI_CLIENT_DISCONNECTED:
223 case AVAHI_CLIENT_S_REGISTERING:
224 case AVAHI_CLIENT_S_COLLISION:
225 avahi_entry_group_reset(d->m_group);
228 case AVAHI_CLIENT_S_RUNNING:
229 if (d->m_collision) {
230 d->m_collision=
false;
239 if (d->m_running)
stop();
246 AvahiClientState s=Responder::self().state();
256 void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s,
void *context)
258 TQObject *obj =
reinterpret_cast<TQObject*
>(context);
259 if (s!=AVAHI_ENTRY_GROUP_ESTABLISHED && s!=AVAHI_ENTRY_GROUP_COLLISION)
return;
260 PublishEvent* pev=
new PublishEvent(s==AVAHI_ENTRY_GROUP_ESTABLISHED);
261 TQApplication::postEvent(obj, pev);
268 url.setProtocol(
"invitation");
269 if (host.isEmpty()) {
270 unsigned long s_address = publicIP();
271 if (!s_address)
return KURL();
272 KNetwork::KIpAddress addr(s_address);
273 url.setHost(addr.toString());
274 }
else url.setHost(host);
277 url.setPath(
"/"+m_type+
"/"+KURL::encode_string(m_serviceName));
279 TQMap<TQString,TQString>::ConstIterator itEnd =
m_textData.end();
280 for (TQMap<TQString,TQString>::ConstIterator it =
m_textData.begin(); it!=itEnd ; ++it)
281 url.addQueryItem(it.key(),it.data());;
285 void PublicService::customEvent(TQCustomEvent* event)
288 if (event->type()==TQEvent::User+SD_PUBLISH) {
289 if (!static_cast<PublishEvent*>(event)->m_ok) {
290 setServiceName(TQString::fromUtf8(avahi_alternative_service_name(m_serviceName.utf8())));
299 void PublicService::virtual_hook(
int,
void*)
303 static unsigned long publicIP()
305 struct sockaddr_in addr;
306 socklen_t len =
sizeof(addr);
307 int sock = socket(AF_INET,SOCK_DGRAM,0);
308 if (sock == -1)
return 0;
309 addr.sin_family = AF_INET;
311 addr.sin_addr.s_addr = 0x11111111;
312 if ((connect(sock,(
const struct sockaddr*)&addr,
sizeof(addr))) == -1) { close(sock);
return 0; }
313 if ((getsockname(sock,(
struct sockaddr*)&addr, &len)) == -1) { close(sock);
return 0; }
315 return addr.sin_addr.s_addr;
321 #include "publicservice.moc"
void stop()
Stops publishing or abort incomplete publish request.
void publishAsync()
Asynchronous version of publish().
bool publish()
Synchrounous publish.
void setServiceName(const TQString &serviceName)
Sets name of the service.
const TQString & domain() const
Returns domain that given service belongs to.
This class is used to carry information about service.
bool isPublished() const
Returns true is currently published.
unsigned short port() const
Returns port number.
const TQMap< TQString, TQString > & textData() const
Returns read only map of text properties.
void setPort(unsigned short port)
Sets port.
TQMap< TQString, TQString > m_textData
Map of TXT properties.
PublicService(const TQString &name=TQString::null, const TQString &type=TQString::null, unsigned int port=0, const TQString &domain=TQString::null)
const KURL toInvitation(const TQString &host=TQString::null)
Translates service into URL that can be sent to another user.
const TQString & type() const
Returns type of service.
void setType(const TQString &type)
Sets type of service.
void published(bool)
Emitted when publishing is complete - parameter is set to true if it was successfull.
void setDomain(const TQString &domain)
Sets domain where service is published.
const TQString & serviceName() const
Returns name of service.
void setTextData(const TQMap< TQString, TQString > &textData)
Sets new text properties.