Logo ROOT   6.10/09
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 
47 TBonjourRegistrar::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 {
58  delete fBonjourSocketHandler;
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 
133 void 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 }
Int_t GetTXTRecordsLength() const
unsigned short UShort_t
Definition: RtypesCore.h:36
Int_t RegisterService(const TBonjourRecord &record, UShort_t servicePort)
Register Bonjour service.
TFileHandler * fBonjourSocketHandler
virtual void Add()
Add file event handler to system file handler list.
int Int_t
Definition: RtypesCore.h:41
const char * GetTXTRecords() const
DNSServiceRef fDNSRef
void BonjourSocketReadyRead()
The Bonjour socket is ready for reading.
virtual ~TBonjourRegistrar()
Cleanup.
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:1618
R__EXTERN TSystem * gSystem
Definition: TSystem.h:539
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:873
long Long_t
Definition: RtypesCore.h:50
#define ClassImp(name)
Definition: Rtypes.h:336
TBonjourRecord fFinalRecord
const char * GetReplyDomain() const
static void DNSSD_API BonjourRegisterService(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, const char *, const char *, const char *, void *)
Static Bonjour register callback function.
const char * GetServiceName() const
void Emit(const char *signal, const T &arg)
Activate signal with single parameter.
Definition: TQObject.h:164
const char * GetRegisteredType() const
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:859
void ServiceRegistered(TBonjourRecord *record)
Emit ServiceRegistered signal.