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(),TQ_SIGNAL(stateChanged(AvahiClientState)),
this,TQ_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 setType(const TQString &type)
Sets type of service.
bool isPublished() const
Returns true is currently published.
void setTextData(const TQMap< TQString, TQString > &textData)
Sets new text properties.
void published(bool)
Emitted when publishing is complete - parameter is set to true if it was successfull.
void setPort(unsigned short port)
Sets port.
const KURL toInvitation(const TQString &host=TQString::null)
Translates service into URL that can be sent to another user.
void publishAsync()
Asynchronous version of publish().
PublicService(const TQString &name=TQString::null, const TQString &type=TQString::null, unsigned int port=0, const TQString &domain=TQString::null)
bool publish()
Synchrounous publish.
void setServiceName(const TQString &serviceName)
Sets name of the service.
void stop()
Stops publishing or abort incomplete publish request.
void setDomain(const TQString &domain)
Sets domain where service is published.
This class is used to carry information about service.
const TQString & domain() const
Returns domain that given service belongs to.
TQMap< TQString, TQString > m_textData
Map of TXT properties.
const TQString & type() const
Returns type of service.
const TQMap< TQString, TQString > & textData() const
Returns read only map of text properties.
unsigned short port() const
Returns port number.
const TQString & serviceName() const
Returns name of service.