ROOT  6.06/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 "TSysEvtHandler.h"
35 #include "TError.h"
36 #include "TSystem.h"
37 
38 #include <arpa/inet.h>
39 
40 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Default ctor.
45 
46 TBonjourRegistrar::TBonjourRegistrar() : fDNSRef(0), fBonjourSocketHandler(0)
47 {
48  // silence Avahi about using Bonjour compat layer
49  gSystem->Setenv("AVAHI_COMPAT_NOWARN", "1");
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Cleanup.
54 
56 {
57  delete fBonjourSocketHandler;
58 
59  if (fDNSRef) {
60  DNSServiceRefDeallocate(fDNSRef);
61  fDNSRef = 0;
62  }
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Register Bonjour service.
67 /// Return -1 in case or error, 0 otherwise.
68 
70 {
71  if (fDNSRef) {
72  Warning("RegisterService", "already registered a service");
73  return 0;
74  }
75 
76  UShort_t sport = htons(servicePort);
77 
78  // register our service and callback
79  DNSServiceErrorType err = DNSServiceRegister(&fDNSRef, 0, kDNSServiceInterfaceIndexAny,
80  !strlen(record.GetServiceName()) ? 0
81  : record.GetServiceName(),
82  record.GetRegisteredType(),
83  !strlen(record.GetReplyDomain()) ? 0
84  : record.GetReplyDomain(),
85  0, sport,
86  record.GetTXTRecordsLength(),
87  !strlen(record.GetTXTRecords()) ? 0
88  : record.GetTXTRecords(),
89  (DNSServiceRegisterReply)BonjourRegisterService,
90  this);
91  if (err != kDNSServiceErr_NoError) {
92  Error("RegisterService", "error in DNSServiceRegister (%d)", err);
93  return -1;
94  }
95 
96  Int_t sockfd = DNSServiceRefSockFD(fDNSRef);
97  if (sockfd == -1) {
98  Error("RegisterService", "invalid sockfd");
99  return -1;
100  }
101 
103  fBonjourSocketHandler->Connect("Notified()", "TBonjourRegistrar", this, "BonjourSocketReadyRead()");
105 
106  return 0;
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Emit ServiceRegistered signal.
111 
113 {
114  Emit("ServiceRegistered(TBonjourRecord*)", (Long_t)record);
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// The Bonjour socket is ready for reading. Tell Bonjour to process the
119 /// information on the socket, this will invoke the BonjourRegisterService
120 /// callback. This is a private slot, used in RegisterService.
121 
123 {
124  DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef);
125  if (err != kDNSServiceErr_NoError)
126  Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult");
127 }
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 /// Static Bonjour register callback function.
131 
132 void TBonjourRegistrar::BonjourRegisterService(DNSServiceRef, DNSServiceFlags,
133  DNSServiceErrorType errCode,
134  const char *name, const char *regType,
135  const char *domain, void *context)
136 {
137  TBonjourRegistrar *registrar = static_cast<TBonjourRegistrar*>(context);
138  if (errCode != kDNSServiceErr_NoError) {
139  ::Error("TBonjourRegistrar::BonjourRegisterService", "error in BonjourRegisterService");
140  //registrar->Error(errorCode);
141  } else {
142  registrar->fFinalRecord = TBonjourRecord(name, regType, domain);
143  registrar->ServiceRegistered(&registrar->fFinalRecord);
144  }
145 }
ClassImp(TBonjourRegistrar) TBonjourRegistrar
Default ctor.
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
const char * GetServiceName() const
DNSServiceRef fDNSRef
void BonjourSocketReadyRead()
The Bonjour socket is ready for reading.
virtual ~TBonjourRegistrar()
Cleanup.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
void Emit(const char *signal)
Acitvate signal without args.
Definition: TQObject.cxx:559
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:1135
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1611
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
const char * GetReplyDomain() const
long Long_t
Definition: RtypesCore.h:50
Int_t GetTXTRecordsLength() const
TBonjourRecord fFinalRecord
const char * GetRegisteredType() const
#define name(a, b)
Definition: linkTestLib0.cpp:5
static void DNSSD_API BonjourRegisterService(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, const char *, const char *, const char *, void *)
Static Bonjour register callback function.
void ServiceRegistered(TBonjourRecord *record)
Emit ServiceRegistered signal.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904