Logo ROOT   6.16/01
Reference Guide
TBonjourRegistrar.cxx
Go to the documentation of this file.
1// @(#)root/bonjour:$Id$
2// Author: Fons Rademakers 29/05/2009
3
4/*************************************************************************
5 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// TBonjourRegistrar //
15// //
16// This class consists of one main member function, RegisterService(), //
17// that registers the service. As long as the object is alive, the //
18// service stays registered. The rest of the class wraps the various //
19// bits of Bonjour service registration. The static callback function //
20// is marked with the DNSSD_API macro to make sure that the callback //
21// has the correct calling convention on Windows. //
22// //
23// Bonjour works out-of-the-box on MacOS X. On Linux you have to //
24// install the Avahi package and run the avahi-daemon. To compile //
25// these classes and run Avahi on Linux you need to install the: //
26// avahi //
27// avahi-compat-libdns_sd-devel //
28// nss-mdns //
29// packages. After installation make sure the avahi-daemon is started. //
30// //
31//////////////////////////////////////////////////////////////////////////
32
33#include "TBonjourRegistrar.h"
34#include "TBonjourBrowser.h"
35#include "TSysEvtHandler.h"
36#include "TError.h"
37#include "TSystem.h"
38
39#include <arpa/inet.h>
40
41
43
44////////////////////////////////////////////////////////////////////////////////
45/// Default ctor.
46
47TBonjourRegistrar::TBonjourRegistrar() : fDNSRef(0), fBonjourSocketHandler(0)
48{
49 // silence Avahi about using Bonjour compat layer
50 gSystem->Setenv("AVAHI_COMPAT_NOWARN", "1");
51}
52
53////////////////////////////////////////////////////////////////////////////////
54/// Cleanup.
55
57{
59
60 if (fDNSRef) {
61 DNSServiceRefDeallocate(fDNSRef);
62 fDNSRef = 0;
63 }
64}
65
66////////////////////////////////////////////////////////////////////////////////
67/// Register Bonjour service.
68/// Return -1 in case or error, 0 otherwise.
69
71{
72 if (fDNSRef) {
73 Warning("RegisterService", "already registered a service");
74 return 0;
75 }
76
77 UShort_t sport = htons(servicePort);
78
79 // register our service and callback
80 DNSServiceErrorType err = DNSServiceRegister(&fDNSRef, 0, kDNSServiceInterfaceIndexAny,
81 !strlen(record.GetServiceName()) ? 0
82 : record.GetServiceName(),
83 record.GetRegisteredType(),
84 !strlen(record.GetReplyDomain()) ? 0
85 : record.GetReplyDomain(),
86 0, sport,
87 record.GetTXTRecordsLength(),
88 !strlen(record.GetTXTRecords()) ? 0
89 : record.GetTXTRecords(),
90 (DNSServiceRegisterReply)BonjourRegisterService,
91 this);
92 if (err != kDNSServiceErr_NoError) {
93 Error("RegisterService", "error in DNSServiceRegister (%d)", err);
94 return -1;
95 }
96
97 Int_t sockfd = DNSServiceRefSockFD(fDNSRef);
98 if (sockfd == -1) {
99 Error("RegisterService", "invalid sockfd");
100 return -1;
101 }
102
104 fBonjourSocketHandler->Connect("Notified()", "TBonjourRegistrar", this, "BonjourSocketReadyRead()");
106
107 return 0;
108}
109
110////////////////////////////////////////////////////////////////////////////////
111/// Emit ServiceRegistered signal.
112
114{
115 Emit("ServiceRegistered(TBonjourRecord*)", (Long_t)record);
116}
117
118////////////////////////////////////////////////////////////////////////////////
119/// The Bonjour socket is ready for reading. Tell Bonjour to process the
120/// information on the socket, this will invoke the BonjourRegisterService
121/// callback. This is a private slot, used in RegisterService.
122
124{
125 DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef);
126 if (err != kDNSServiceErr_NoError)
127 Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult");
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// Static Bonjour register callback function.
132
133void TBonjourRegistrar::BonjourRegisterService(DNSServiceRef, DNSServiceFlags,
134 DNSServiceErrorType errCode,
135 const char *name, const char *regType,
136 const char *domain, void *context)
137{
138 TBonjourRegistrar *registrar = static_cast<TBonjourRegistrar*>(context);
139 if (errCode != kDNSServiceErr_NoError) {
140 ::Error("TBonjourRegistrar::BonjourRegisterService", "error in BonjourRegisterService");
141 //registrar->Error(errorCode);
142 } else {
143 registrar->fFinalRecord = TBonjourRecord(name, regType, domain);
144 registrar->ServiceRegistered(&registrar->fFinalRecord);
145 }
146}
unsigned short UShort_t
Definition: RtypesCore.h:36
int Int_t
Definition: RtypesCore.h:41
long Long_t
Definition: RtypesCore.h:50
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
const char * GetReplyDomain() const
const char * GetServiceName() const
Int_t GetTXTRecordsLength() const
const char * GetTXTRecords() const
const char * GetRegisteredType() const
TFileHandler * fBonjourSocketHandler
Int_t RegisterService(const TBonjourRecord &record, UShort_t servicePort)
Register Bonjour service.
static void DNSSD_API BonjourRegisterService(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, const char *, const char *, const char *, void *)
Static Bonjour register callback function.
DNSServiceRef fDNSRef
TBonjourRecord fFinalRecord
TBonjourRegistrar()
Default ctor.
virtual ~TBonjourRegistrar()
Cleanup.
void ServiceRegistered(TBonjourRecord *record)
Emit ServiceRegistered signal.
void BonjourSocketReadyRead()
The Bonjour socket is ready for reading.
virtual void Add()
Add file event handler to system file handler list.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
void Emit(const char *signal, const T &arg)
Activate signal with single parameter.
Definition: TQObject.h:165
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot.
Definition: TQObject.cxx:867
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1636