ROOT  6.06/09
Reference Guide
TBonjourBrowser.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 // TBonjourBrowser //
15 // //
16 // This class consists of one main member function, //
17 // BrowseForServiceType(), that looks for the service. //
18 // The rest of the class wraps the various bits of Bonjour service //
19 // browser. The static callback function is marked with the DNSSD_API //
20 // macro to make sure that the callback has the correct calling //
21 // 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 "TBonjourBrowser.h"
34 #include "TBonjourRecord.h"
35 #include "TSysEvtHandler.h"
36 #include "TList.h"
37 #include "TError.h"
38 #include "TSystem.h"
39 
40 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Default ctor.
45 
46 TBonjourBrowser::TBonjourBrowser() : fDNSRef(0), fBonjourSocketHandler(0)
47 {
48  fBonjourRecords = new TList;
49  fBonjourRecords->SetOwner();
50 
51  // silence Avahi about using Bonjour compat layer
52  gSystem->Setenv("AVAHI_COMPAT_NOWARN", "1");
53 }
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 /// Cleanup.
57 
59 {
60  delete fBonjourRecords;
61  delete fBonjourSocketHandler;
62 
63  if (fDNSRef) {
64  DNSServiceRefDeallocate(fDNSRef);
65  fDNSRef = 0;
66  }
67 }
68 
69 ////////////////////////////////////////////////////////////////////////////////
70 /// Tell Bonjour to start browsing for a specific type of service.
71 /// Returns -1 in case of error, 0 otherwise.
72 
74 {
75  DNSServiceErrorType err = DNSServiceBrowse(&fDNSRef, 0,
76  0, serviceType, 0,
77  (DNSServiceBrowseReply)BonjourBrowseReply,
78  this);
79  if (err != kDNSServiceErr_NoError) {
80  Error("BrowseForServiceType", "error in DNSServiceBrowse (%d)", err);
81  return -1;
82  }
83 
84  Int_t sockfd = DNSServiceRefSockFD(fDNSRef);
85  if (sockfd == -1) {
86  Error("BrowseForServiceType", "invalid sockfd");
87  return -1;
88  }
89 
91  fBonjourSocketHandler->Connect("Notified()", "TBonjourBrowser", this, "BonjourSocketReadyRead()");
93 
94  return 0;
95 }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 /// Emit CurrentBonjourRecordsChanged signal.
99 
101 {
102  Emit("CurrentBonjourRecordsChanged(TList*)", (Long_t)bonjourRecords);
103 }
104 
105 ////////////////////////////////////////////////////////////////////////////////
106 /// The Bonjour socket is ready for reading. Tell Bonjour to process the
107 /// information on the socket, this will invoke the BonjourBrowseReply
108 /// callback. This is a private slot, used in BrowseForServiceType.
109 
111 {
112  // in case the browser has already been deleted
113  if (!fDNSRef) return;
114 
115  DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef);
116  if (err != kDNSServiceErr_NoError)
117  Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult");
118 }
119 
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Static Bonjour browser callback function.
122 
124  DNSServiceFlags flags, UInt_t,
125  DNSServiceErrorType errorCode,
126  const char *serviceName, const char *regType,
127  const char *replyDomain, void *context)
128 {
129  TBonjourBrowser *browser = static_cast<TBonjourBrowser*>(context);
130  if (errorCode != kDNSServiceErr_NoError) {
131  ::Error("TBonjourBrowser::BonjourBrowseReply", "error in BonjourBrowseReply");
132  //browser->Error(errorCode);
133  } else {
134  TBonjourRecord *record = new TBonjourRecord(serviceName, regType, replyDomain);
135  if (flags & kDNSServiceFlagsAdd) {
136  if (!browser->fBonjourRecords->FindObject(record))
137  browser->fBonjourRecords->Add(record);
138  else
139  delete record;
140  } else {
141  TBonjourRecord *r = (TBonjourRecord*)browser->fBonjourRecords->Remove(record);
142  delete r;
143  delete record;
144  }
145  if (!(flags & kDNSServiceFlagsMoreComing)) {
147  }
148  }
149 }
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
void BonjourSocketReadyRead()
The Bonjour socket is ready for reading.
virtual void Add()
Add file event handler to system file handler list.
int Int_t
Definition: RtypesCore.h:41
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
static void DNSSD_API BonjourBrowseReply(DNSServiceRef, DNSServiceFlags, UInt_t, DNSServiceErrorType, const char *, const char *, const char *, void *)
Static Bonjour browser callback function.
TList * fBonjourRecords
void CurrentBonjourRecordsChanged(TList *bonjourRecords)
Emit CurrentBonjourRecordsChanged signal.
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
A doubly linked list.
Definition: TList.h:47
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
DNSServiceRef fDNSRef
ClassImp(TBonjourBrowser) TBonjourBrowser
Default ctor.
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition: TSystem.cxx:1611
ROOT::R::TRInterface & r
Definition: Object.C:4
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
TFileHandler * fBonjourSocketHandler
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual ~TBonjourBrowser()
Cleanup.
long Long_t
Definition: RtypesCore.h:50
virtual void Add(TObject *obj)
Definition: TList.h:81
Int_t BrowseForServiceType(const char *serviceType)
Tell Bonjour to start browsing for a specific type of service.