diff --git a/Makefile b/Makefile index 0dcc65da8e1334ea341b331afe89b5ca9fd30efc..abd7453e6ede1c6aeec6fcb7d940818563017416 100644 --- a/Makefile +++ b/Makefile @@ -146,6 +146,9 @@ endif ifeq ($(BUILDGLITE),yes) MODULES += net/glite endif +ifeq ($(BUILDBONJOUR),yes) +MODULES += net/bonjour +endif ifeq ($(BUILDCHIRP),yes) MODULES += io/chirp endif @@ -281,7 +284,7 @@ MODULES += core/unix core/winnt graf2d/x11 graf2d/x11ttf \ cint/cint7 roofit/roofitcore roofit/roofit roofit/roostats \ math/minuit2 net/monalisa math/fftw sql/odbc math/unuran \ geom/gdml graf3d/eve montecarlo/g4root net/glite misc/memstat \ - math/genvector + math/genvector net/bonjour MODULES := $(sort $(MODULES)) # removes duplicates endif diff --git a/config/Makefile.in b/config/Makefile.in index 7f3a6346783bd222b196e1c9f526462fef4ac621..002f6659442abb6efeedc886718d57685129867b 100644 --- a/config/Makefile.in +++ b/config/Makefile.in @@ -151,6 +151,11 @@ GAW_CPPFLAGS := $(filter-out /usr/include, @gaw_cppflags@) BUILDMEMSTAT := @buildmemstat@ +BUILDBONJOUR := @buildbonjour@ +DNSSDLBDIR := @dnssdlibdir@ +DNSSDLIB := @dnssdlib@ +DNSSDINCDIR := $(filter-out /usr/include, @dnssdincdir@) + BUILDCHIRP := @buildchirp@ CHIRPLIBDIR := @chirplibdir@ CHIRPCLILIB := @chirplib@ diff --git a/configure b/configure index 3c17d49359b732732d7d45bd52f378dff30d6261..e1730d32bc4f0af57415002100f8e54281b7afac 100755 --- a/configure +++ b/configure @@ -37,6 +37,7 @@ options=" \ enable_alien \ enable_asimage \ enable_astiff \ + enable_bonjour \ enable_builtin_afterimage \ enable_builtin_ftgl \ enable_builtin_freetype \ @@ -155,6 +156,7 @@ FFTW3 \ PYTHONDIR \ DCACHE \ CHIRP \ +DNSSD \ ALIEN \ ASIMAGE \ LDAP \ @@ -1007,6 +1009,7 @@ enable/disable options, prefix with either --enable- or --disable- alien AliEn support, requires libgapiUI from ALICE asimage Image processing support, requires libAfterImage astiff Include tiff support in image processing + bonjour Bonjour support, requires libdns_sd builtin-afterimage Built included libAfterImage, or use system libAfterImage builtin-ftgl Built included libFTGL, or use system libftgl builtin-freetype Built included libfreetype, or use system libfreetype @@ -1079,6 +1082,8 @@ with options, prefix with --with-, enables corresponding support dcap-incdir dCache support, location of dcap.h dcap-libdir dCache support, location of libdcap dicttype dictionary type: "cint" (default), "reflex", or "gccxml" + dnssd-libdir Bonjour support, location of libdns_sd + dnssd-incdir Bonjour support, location of dns_sd.h ftgl-incdir FTGL support, location of FTGL.h ftgl-libdir FTGL support, location of libftgl fftw3-incdir FFTW3 support, location of fftw3.h @@ -1287,6 +1292,8 @@ if test $# -gt 0 ; then --with-dcap-incdir=*) dcapincdir=$optarg ; enable_dcache="yes" ;; --with-dcap-libdir=*) dcaplibdir=$optarg ; enable_dcache="yes" ;; --with-dicttype=*) dicttype=$optarg ;; + --with-dnssd-incdir=*) dnssdincdir=$optarg ; enable_bonjour="yes" ;; + --with-dnssd-libdir=*) dnssdlibdir=$optarg ; enable_bonjour="yes" ;; --with-ftgl-incdir=*) ftglincdir=$optarg ; enable_builtin_ftgl=no;; --with-ftgl-libdir=*) ftgllibdir=$optarg ; enable_builtin_ftgl=no;; --with-fftw3-incdir=*) fftw3incdir=$optarg ; enable_fftw3="yes" ;; @@ -2803,6 +2810,36 @@ fi check_explicit "$enable_chirp" "$enable_chirp_explicit" \ "Explicitly required Chirp dependencies not fulfilled" +###################################################################### +# +### echo %%% Bonjour Support - Third party libraries +# +# (See http://developer.apple.com/networking/bonjour/index.html) +# +# By default available on MacOS X and on Linux via the Avahi package. +# +# Check for libdns_sd +# +if test ! "x$enable_bonjour" = "xno" ; then + # Bonjour is built-in on MacOS X (i.e. available in libSystem) + if test ! "x$platform" = "xmacosx"; then + check_header "dns_sd.h" "$dnssdincdir" $DNSSD $DNSSD/include \ + /opt/dnssd/include /usr/include /usr/local/include + dnssdincdir=$found_dir + + check_library "libdns_sd" "$enable_shared" "$dnssdlibdir" \ + $DNSSD $DNSSD/lib /opt/dnssd/lib /usr/lib /usr/local/lib + dnssdlib=$found_lib + dnssdlibdir=$found_dir + + if test "x$dnssdincdir" = "x" || test "x$dnssdlib" = "x"; then + enable_bonjour="no" + fi + fi +fi +check_explicit "$enable_bonjour" "$enable_bonjour_explicit" \ + "Explicitly required Bonjour dependencies not fulfilled" + ###################################################################### # ### echo %%% gLite Support - Third party libraries @@ -4324,7 +4361,7 @@ else result "no" fi -if test "x${enable_cint5}${enable_cint7}" = "x"; then +if test "x${enable_cint5}${enable_cint7}" = "x"; then result "`basename $0`: Need to enable at least one of cint5 and cint7" exit 1 fi @@ -4613,6 +4650,7 @@ if test "x$show_pkglist" = "xyes" ; then test "x$enable_g4root" = "xyes" && pl="$pl root-plugin-montecarlo-g4root" test "x$enable_pythia6" = "xyes" && pl="$pl root-plugin-montecarlo-pythia6" test "x$enable_alien" = "xyes" && pl="$pl root-plugin-net-alien" + test "x$enable_bonjour" = "xyes" && pl="$pl root-plugin-net-bonjour" test "x$enable_globus" = "xyes" && pl="$pl root-plugin-net-globus" test "x$enable_krb5" = "xyes" && pl="$pl root-plugin-net-krb5" test "x$enable_monalisa" = "xyes" && pl="$pl root-plugin-net-monalisa" @@ -5051,6 +5089,9 @@ sed -e "s|@globusincdir@|$globusincdir|" \ -e "s|@fftw3incdir@|$fftw3incdir|" \ -e "s|@fftw3lib@|$fftw3lib|" \ -e "s|@fftw3libdir@|$fftw3libdir|" \ + -e "s|@dnssdincdir@|$dnssdincdir|" \ + -e "s|@dnssdlib@|$dnssdlib|" \ + -e "s|@dnssdlibdir@|$dnssdlibdir|" \ -e "s|@mysqlincdir@|$mysqlincdir|" \ -e "s|@mysqllib@|$mysqllib|" \ -e "s|@mysqllibdir@|$mysqllibdir|" \ @@ -5141,6 +5182,7 @@ sed -e "s|@srcdir@|$srcdir|" \ -e "s|@buildfftw3@|$enable_fftw3|" \ -e "s|@buildgfal@|$enable_gfal|" \ -e "s|@buildg4root@|$enable_g4root|" \ + -e "s|@buildbonjour@|$enable_bonjour|" \ -e "s|@buildchirp@|$enable_chirp|" \ -e "s|@buildalien@|$enable_alien|" \ -e "s|@buildasimage@|$enable_asimage|" \ diff --git a/net/bonjour/Module.mk b/net/bonjour/Module.mk new file mode 100644 index 0000000000000000000000000000000000000000..6b0f54affb6ef278f9876730e309dbc12dd1c8f7 --- /dev/null +++ b/net/bonjour/Module.mk @@ -0,0 +1,70 @@ +# Module.mk for bonjour module +# Copyright (c) 2009 Rene Brun and Fons Rademakers +# +# Author: Fons Rademakers, 29/05/2009 + +MODNAME := bonjour +MODDIR := net/$(MODNAME) +MODDIRS := $(MODDIR)/src +MODDIRI := $(MODDIR)/inc + +BONJDIR := $(MODDIR) +BONJDIRS := $(BONJDIR)/src +BONJDIRI := $(BONJDIR)/inc + +##### libBonjour ##### +BONJL := $(MODDIRI)/LinkDef.h +BONJDS := $(MODDIRS)/G__BONJ.cxx +BONJDO := $(BONJDS:.cxx=.o) +BONJDH := $(BONJDS:.cxx=.h) + +BONJH := $(filter-out $(MODDIRI)/LinkDef%,$(wildcard $(MODDIRI)/*.h)) +BONJS := $(filter-out $(MODDIRS)/G__%,$(wildcard $(MODDIRS)/*.cxx)) +BONJO := $(BONJS:.cxx=.o) + +BONJDEP := $(BONJO:.o=.d) $(BONJDO:.o=.d) + +BONJLIB := $(LPATH)/libBonjour.$(SOEXT) +BONJMAP := $(BONJLIB:.$(SOEXT)=.rootmap) + +# used in the main Makefile +ALLHDRS += $(patsubst $(MODDIRI)/%.h,include/%.h,$(BONJH)) +ALLLIBS += $(BONJLIB) +ALLMAPS += $(BONJMAP) + +# include all dependency files +INCLUDEFILES += $(BONJDEP) + +##### local rules ##### +.PHONY: all-$(MODNAME) clean-$(MODNAME) distclean-$(MODNAME) + +include/%.h: $(BONJDIRI)/%.h + cp $< $@ + +$(BONJLIB): $(BONJO) $(BONJDO) $(ORDER_) $(MAINLIBS) + @$(MAKELIB) $(PLATFORM) $(LD) "$(LDFLAGS)" \ + "$(SOFLAGS)" libBonjour.$(SOEXT) $@ "$(BONJO) $(BONJDO)" \ + "$(BONJLIBEXTRA) $(BONJLIBDIR) $(BONJCLILIB)" + +$(BONJDS): $(BONJH) $(BONJL) $(ROOTCINTTMPDEP) + @echo "Generating dictionary $@..." + $(ROOTCINTTMP) -f $@ -c $(BONJH) $(BONJL) + +$(BONJMAP): $(RLIBMAP) $(MAKEFILEDEP) $(BONJL) + $(RLIBMAP) -o $(BONJMAP) -l $(BONJLIB) \ + -d $(BONJLIBDEPM) -c $(BONJL) + +all-$(MODNAME): $(BONJLIB) $(BONJMAP) + +clean-$(MODNAME): + @rm -f $(BONJO) $(BONJDO) + +clean:: clean-$(MODNAME) + +distclean-$(MODNAME): clean-$(MODNAME) + @rm -f $(BONJDEP) $(BONJDS) $(BONJDH) $(BONJLIB) $(BONJMAP) + +distclean:: distclean-$(MODNAME) + +##### extra rules ###### +$(BONJO): CXXFLAGS += $(BONJINCDIR:%=-I%) diff --git a/net/bonjour/inc/LinkDef.h b/net/bonjour/inc/LinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..eecfc42da49be91f1b3c564a59c1cca9cb8b3cc6 --- /dev/null +++ b/net/bonjour/inc/LinkDef.h @@ -0,0 +1,18 @@ +/* @(#)root/bonjour:$Id$ */ + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifdef __CINT__ + +#pragma link C++ class TBonjourRecord; +#pragma link C++ class TBonjourRegistrar; +#pragma link C++ class TBonjourBrowser; +#pragma link C++ class TBonjourResolver; + +#endif diff --git a/net/bonjour/inc/TBonjourBrowser.h b/net/bonjour/inc/TBonjourBrowser.h new file mode 100644 index 0000000000000000000000000000000000000000..cf28ff19aa7572281cde9e75c7c0069e1009103f --- /dev/null +++ b/net/bonjour/inc/TBonjourBrowser.h @@ -0,0 +1,86 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TBonjourBrowser +#define ROOT_TBonjourBrowser + + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourBrowser // +// // +// This class consists of one main member function, // +// BrowseForServiceType(), that looks for the service. // +// The rest of the class wraps the various bits of Bonjour service // +// browser. The static callback function is marked with the DNSSD_API // +// macro to make sure that the callback has the correct calling // +// convention on Windows. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TObject +#include "TObject.h" +#endif +#ifndef ROOT_TQObject +#include "TQObject.h" +#endif +#ifndef ROOT_TString +#include "TString.h" +#endif + +#if !defined(__CINT__) +#include <dns_sd.h> +#else +typedef ULong_t DNSServiceRef; +typedef UInt_t DNSServiceFlags; +typedef Int_t DNSServiceErrorType; +#endif + +class TFileHandler; +class TList; + + +class TBonjourBrowser : public TObject, public TQObject { + +private: + DNSServiceRef fDNSRef; + TFileHandler *fBonjourSocketHandler; + TList *fBonjourRecords; + TString fBrowsingType; + + void *GetSender() { return this; } // used to get gTQSender + +#if !defined(__CINT__) + static void DNSSD_API BonjourBrowseReply(DNSServiceRef, + DNSServiceFlags, UInt_t, DNSServiceErrorType, + const char *, const char *, const char *, void *); +#else + static void BonjourBrowseReply(DNSServiceRef, + DNSServiceFlags, Int_t, DNSServiceErrorType, + const char *, const char *, const char *, void *); +#endif + +public: + TBonjourBrowser(); + virtual ~TBonjourBrowser(); + + Int_t BrowseForServiceType(const char *serviceType); + TList *CurrentRecords() const { return fBonjourRecords; } + const char *ServiceType() const { return fBrowsingType; } + + void CurrentBonjourRecordsChanged(TList *bonjourRecords); //*SIGNAL* + + void BonjourSocketReadyRead(); // private slot + + ClassDef(TBonjourBrowser,0) // Browse hosts for specific bonjour service type +}; + +#endif diff --git a/net/bonjour/inc/TBonjourRecord.h b/net/bonjour/inc/TBonjourRecord.h new file mode 100644 index 0000000000000000000000000000000000000000..f4718dc6f0280da39c7585b0a5558d7f75cf1db5 --- /dev/null +++ b/net/bonjour/inc/TBonjourRecord.h @@ -0,0 +1,64 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TBonjourRecord +#define ROOT_TBonjourRecord + + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourRecord // +// // +// Contains all information concerning a Bonjour entry. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TObject +#include "TObject.h" +#endif + +#ifndef ROOT_TString +#include "TString.h" +#endif + + + +class TBonjourRecord : public TObject { + +private: + TString fServiceName; + TString fRegisteredType; + TString fReplyDomain; + +public: + TBonjourRecord() { } + TBonjourRecord(const char *name, const char *regType, const char *domain) : + fServiceName(name), fRegisteredType(regType), fReplyDomain(domain) { } + virtual ~TBonjourRecord() { } + + Bool_t operator==(const TBonjourRecord &other) const { + return fServiceName == other.fServiceName && + fRegisteredType == other.fRegisteredType && + fReplyDomain == other.fReplyDomain; + } + + Bool_t IsEqual(const TObject *obj) const { return *this == *(TBonjourRecord*)obj; } + + const char *GetServiceName() const { return fServiceName; } + const char *GetRegisteredType() const { return fRegisteredType; } + const char *GetReplyDomain() const { return fReplyDomain; } + + void Print(Option_t *opt = "") const; + + ClassDef(TBonjourRecord,0) // Bonjour information record +}; + +#endif diff --git a/net/bonjour/inc/TBonjourRegistrar.h b/net/bonjour/inc/TBonjourRegistrar.h new file mode 100644 index 0000000000000000000000000000000000000000..c27ca096449612db36efe84d9fa302b1381e26b7 --- /dev/null +++ b/net/bonjour/inc/TBonjourRegistrar.h @@ -0,0 +1,81 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TBonjourRegistrar +#define ROOT_TBonjourRegistrar + + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourRegistrar // +// // +// This class consists of one main member function, RegisterService(), // +// that registers the service. As long as the object is alive, the // +// service stays registered. The rest of the class wraps the various // +// bits of Bonjour service registration. The static callback function // +// is marked with the DNSSD_API macro to make sure that the callback // +// has the correct calling convention on Windows. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TObject +#include "TObject.h" +#endif +#ifndef ROOT_TQObject +#include "TQObject.h" +#endif +#ifndef ROOT_TBonjourRecord +#include "TBonjourRecord.h" +#endif + +#if !defined(__CINT__) +#include <dns_sd.h> +#else +typedef ULong_t DNSServiceRef; +typedef UInt_t DNSServiceFlags; +typedef Int_t DNSServiceErrorType; +#endif + +class TFileHandler; + + +class TBonjourRegistrar : public TObject, public TQObject { + +private: + DNSServiceRef fDNSRef; + TFileHandler *fBonjourSocketHandler; + TBonjourRecord fFinalRecord; + + void *GetSender() { return this; } // used to get gTQSender + +#if !defined(__CINT__) + static void DNSSD_API BonjourRegisterService(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, + const char *, const char *, const char *, void *); +#else + static void BonjourRegisterService(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, + const char *, const char *, const char *, void *); +#endif + +public: + TBonjourRegistrar(); + virtual ~TBonjourRegistrar(); + + Int_t RegisterService(const TBonjourRecord &record, UShort_t servicePort); + TBonjourRecord RegisteredRecord() const { return fFinalRecord; } + + void ServiceRegistered(TBonjourRecord *record); //*SIGNAL* + + void BonjourSocketReadyRead(); // private slot + + ClassDef(TBonjourRegistrar,0) // Register Bonjour service +}; + +#endif diff --git a/net/bonjour/inc/TBonjourResolver.h b/net/bonjour/inc/TBonjourResolver.h new file mode 100644 index 0000000000000000000000000000000000000000..792b19478bc66374d2442c050f3c766828e6fcaa --- /dev/null +++ b/net/bonjour/inc/TBonjourResolver.h @@ -0,0 +1,86 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TBonjourResolver +#define ROOT_TBonjourResolver + + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourResolver // +// // +// This class consists of one main member function, // +// ResolveBonjourRecord(), that resolves the service to an actual // +// IP address and port number. The rest of the class wraps the various // +// bits of Bonjour service resolver. The static callback function // +// is marked with the DNSSD_API macro to make sure that the callback // +// has the correct calling convention on Windows. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TObject +#include "TObject.h" +#endif +#ifndef ROOT_TQObject +#include "TQObject.h" +#endif +#ifndef ROOT_TInetAddress +#include "TInetAddress.h" +#endif + +#if !defined(__CINT__) +#include <dns_sd.h> +#else +typedef ULong_t DNSServiceRef; +typedef UInt_t DNSServiceFlags; +typedef Int_t DNSServiceErrorType; +#endif + +class TFileHandler; +class TBonjourRecord; + + +class TBonjourResolver : public TObject, public TQObject { + +private: + DNSServiceRef fDNSRef; + TFileHandler *fBonjourSocketHandler; + TInetAddress fHostAddress; + Int_t fPort; + + void *GetSender() { return this; } // used to get gTQSender + +#if !defined(__CINT__) + static void DNSSD_API BonjourResolveReply(DNSServiceRef, DNSServiceFlags, UInt_t, + DNSServiceErrorType, + const char *, const char *, + UShort_t, UShort_t, const unsigned char *, void *); +#else + static void BonjourResolveReply(DNSServiceRef, DNSServiceFlags, UInt_t, + DNSServiceErrorType, + const char *, const char *, + UShort_t, UShort_t, const unsigned char *, void *); +#endif + +public: + TBonjourResolver(); + virtual ~TBonjourResolver(); + + Int_t ResolveBonjourRecord(const TBonjourRecord &record); + + void RecordResolved(const TInetAddress *hostInfo, Int_t port); //*SIGNAL* + + void BonjourSocketReadyRead(); // private slot + + ClassDef(TBonjourResolver,0) // Resolve Bonjour to actual IP address and port +}; + +#endif diff --git a/net/bonjour/src/TBonjourBrowser.cxx b/net/bonjour/src/TBonjourBrowser.cxx new file mode 100644 index 0000000000000000000000000000000000000000..55f7e4d317be7c56fb6648f013ebbda12ca2f550 --- /dev/null +++ b/net/bonjour/src/TBonjourBrowser.cxx @@ -0,0 +1,133 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourBrowser // +// // +// This class consists of one main member function, // +// BrowseForServiceType(), that looks for the service. // +// The rest of the class wraps the various bits of Bonjour service // +// browser. The static callback function is marked with the DNSSD_API // +// macro to make sure that the callback has the correct calling // +// convention on Windows. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TBonjourBrowser.h" +#include "TBonjourRecord.h" +#include "TSysEvtHandler.h" +#include "TList.h" +#include "TError.h" + + +ClassImp(TBonjourBrowser) + +//______________________________________________________________________________ +TBonjourBrowser::TBonjourBrowser() : fDNSRef(0), fBonjourSocketHandler(0) +{ + // Default ctor. + + fBonjourRecords = new TList; + fBonjourRecords->SetOwner(); +} + +//______________________________________________________________________________ +TBonjourBrowser::~TBonjourBrowser() +{ + // Cleanup. + + delete fBonjourRecords; + delete fBonjourSocketHandler; + + if (fDNSRef) { + DNSServiceRefDeallocate(fDNSRef); + fDNSRef = 0; + } +} + +//______________________________________________________________________________ +Int_t TBonjourBrowser::BrowseForServiceType(const char *serviceType) +{ + // Tell Bonjour to start browsing for a specific type of service. + // Returns -1 in case of error, 0 otherwise. + + DNSServiceErrorType err = DNSServiceBrowse(&fDNSRef, 0, + 0, serviceType, 0, + BonjourBrowseReply, this); + if (err != kDNSServiceErr_NoError) { + Error("BrowseForServiceType", "error in DNSServiceBrowse (%d)", err); + return -1; + } + + Int_t sockfd = DNSServiceRefSockFD(fDNSRef); + if (sockfd == -1) { + Error("BrowseForServiceType", "invalid sockfd"); + return -1; + } + + fBonjourSocketHandler = new TFileHandler(sockfd, TFileHandler::kRead); + fBonjourSocketHandler->Connect("Notified()", "TBonjourBrowser", this, "BonjourSocketReadyRead()"); + fBonjourSocketHandler->Add(); + + return 0; +} + +//______________________________________________________________________________ +void TBonjourBrowser::CurrentBonjourRecordsChanged(TList *bonjourRecords) +{ + // Emit CurrentBonjourRecordsChanged signal. + + Emit("CurrentBonjourRecordsChanged(TList*)", (Long_t)bonjourRecords); +} + +//______________________________________________________________________________ +void TBonjourBrowser::BonjourSocketReadyRead() +{ + // The Bonjour socket is ready for reading. Tell Bonjour to process the + // information on the socket, this will invoke the BonjourBrowseReply + // callback. This is a private slot, used in BrowseForServiceType. + + DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef); + if (err != kDNSServiceErr_NoError) + Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult"); +} + +//______________________________________________________________________________ +void TBonjourBrowser::BonjourBrowseReply(DNSServiceRef, + DNSServiceFlags flags, UInt_t, + DNSServiceErrorType errorCode, + const char *serviceName, const char *regType, + const char *replyDomain, void *context) +{ + // Static Bonjour browser callback function. + + TBonjourBrowser *browser = static_cast<TBonjourBrowser*>(context); + if (errorCode != kDNSServiceErr_NoError) { + ::Error("TBonjourBrowser::BonjourBrowseReply", "error in BonjourBrowseReply"); + //browser->Error(errorCode); + } else { + TBonjourRecord *record = new TBonjourRecord(serviceName, regType, replyDomain); + if (flags & kDNSServiceFlagsAdd) { + if (!browser->fBonjourRecords->FindObject(record)) + browser->fBonjourRecords->Add(record); + else + delete record; + } else { + TBonjourRecord *r = (TBonjourRecord*)browser->fBonjourRecords->Remove(record); + delete r; + delete record; + } + if (!(flags & kDNSServiceFlagsMoreComing)) { + browser->CurrentBonjourRecordsChanged(browser->fBonjourRecords); + } + } +} diff --git a/net/bonjour/src/TBonjourRecord.cxx b/net/bonjour/src/TBonjourRecord.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1f1cda5ee860cfe81ca7284e5b59eb2a6773d90a --- /dev/null +++ b/net/bonjour/src/TBonjourRecord.cxx @@ -0,0 +1,33 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourRecord // +// // +// Contains all information concerning a Bonjour entry. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TBonjourRecord.h" +#include "Riostream.h" + + +ClassImp(TBonjourRecord) + +//______________________________________________________________________________ +void TBonjourRecord::Print(Option_t *) const +{ + // Print TBonjourRecord. + + cout << "TBonjourRecord:" << "\t" << GetServiceName() + << "\t" << GetRegisteredType() << "\t" << GetReplyDomain() << endl; +} diff --git a/net/bonjour/src/TBonjourRegistrar.cxx b/net/bonjour/src/TBonjourRegistrar.cxx new file mode 100644 index 0000000000000000000000000000000000000000..94573bbc761877666e45034270b47de2bf8ce00d --- /dev/null +++ b/net/bonjour/src/TBonjourRegistrar.cxx @@ -0,0 +1,128 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourRegistrar // +// // +// This class consists of one main member function, RegisterService(), // +// that registers the service. As long as the object is alive, the // +// service stays registered. The rest of the class wraps the various // +// bits of Bonjour service registration. The static callback function // +// is marked with the DNSSD_API macro to make sure that the callback // +// has the correct calling convention on Windows. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TBonjourRegistrar.h" +#include "TSysEvtHandler.h" +#include "TError.h" + +#include <arpa/inet.h> + + +ClassImp(TBonjourRegistrar) + +//______________________________________________________________________________ +TBonjourRegistrar::TBonjourRegistrar() : fDNSRef(0), fBonjourSocketHandler(0) +{ + // Default ctor. +} + +//______________________________________________________________________________ +TBonjourRegistrar::~TBonjourRegistrar() +{ + // Cleanup. + + delete fBonjourSocketHandler; + + if (fDNSRef) { + DNSServiceRefDeallocate(fDNSRef); + fDNSRef = 0; + } +} + +//______________________________________________________________________________ +Int_t TBonjourRegistrar::RegisterService(const TBonjourRecord &record, UShort_t servicePort) +{ + // Register Bonjour service. + // Return -1 in case or error, 0 otherwise. + + if (fDNSRef) { + Warning("RegisterService", "already registered a service"); + return 0; + } + + UShort_t sport = htons(servicePort); + + // register our service and callback + DNSServiceErrorType err = DNSServiceRegister(&fDNSRef, 0, kDNSServiceInterfaceIndexAny, + record.GetServiceName(), + record.GetRegisteredType(), + !strlen(record.GetReplyDomain()) ? 0 + : record.GetReplyDomain(), + 0, sport, 0, 0, BonjourRegisterService, + this); + if (err != kDNSServiceErr_NoError) { + Error("RegisterService", "error in DNSServiceRegister (%d)", err); + return -1; + } + + Int_t sockfd = DNSServiceRefSockFD(fDNSRef); + if (sockfd == -1) { + Error("RegisterService", "invalid sockfd"); + return -1; + } + + fBonjourSocketHandler = new TFileHandler(sockfd, TFileHandler::kRead); + fBonjourSocketHandler->Connect("Notified()", "TBonjourRegistrar", this, "BonjourSocketReadyRead()"); + fBonjourSocketHandler->Add(); + + return 0; +} + +//______________________________________________________________________________ +void TBonjourRegistrar::ServiceRegistered(TBonjourRecord *record) +{ + // Emit ServiceRegistered signal. + + Emit("ServiceRegistered(TBonjourRecord*)", (Long_t)record); +} + +//______________________________________________________________________________ +void TBonjourRegistrar::BonjourSocketReadyRead() +{ + // The Bonjour socket is ready for reading. Tell Bonjour to process the + // information on the socket, this will invoke the BonjourRegisterService + // callback. This is a private slot, used in RegisterService. + + DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef); + if (err != kDNSServiceErr_NoError) + Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult"); +} + +//______________________________________________________________________________ +void TBonjourRegistrar::BonjourRegisterService(DNSServiceRef, DNSServiceFlags, + DNSServiceErrorType errCode, + const char *name, const char *regType, + const char *domain, void *context) +{ + // Static Bonjour register callback function. + + TBonjourRegistrar *registrar = static_cast<TBonjourRegistrar*>(context); + if (errCode != kDNSServiceErr_NoError) { + ::Error("TBonjourRegistrar::BonjourRegisterService", "error in BonjourRegisterService"); + //registrar->Error(errorCode); + } else { + registrar->fFinalRecord = TBonjourRecord(name, regType, domain); + registrar->ServiceRegistered(®istrar->fFinalRecord); + } +} diff --git a/net/bonjour/src/TBonjourResolver.cxx b/net/bonjour/src/TBonjourResolver.cxx new file mode 100644 index 0000000000000000000000000000000000000000..d0b0ac4ab9b08e70d925c38b932415478953279b --- /dev/null +++ b/net/bonjour/src/TBonjourResolver.cxx @@ -0,0 +1,131 @@ +// @(#)root/bonjour:$Id$ +// Author: Fons Rademakers 29/05/2009 + +/************************************************************************* + * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TBonjourResolver // +// // +// This class consists of one main member function, // +// ResolveBonjourRecord(), that resolves the service to an actual // +// IP address and port number. The rest of the class wraps the various // +// bits of Bonjour service resolver. The static callback function // +// is marked with the DNSSD_API macro to make sure that the callback // +// has the correct calling convention on Windows. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TBonjourResolver.h" +#include "TBonjourRecord.h" +#include "TSysEvtHandler.h" +#include "TSystem.h" +#include "TError.h" + +#include <arpa/inet.h> + + +ClassImp(TBonjourResolver) + +//______________________________________________________________________________ +TBonjourResolver::TBonjourResolver() : fDNSRef(0), fBonjourSocketHandler(0) +{ + // Default ctor. +} + +//______________________________________________________________________________ +TBonjourResolver::~TBonjourResolver() +{ + // Cleanup. + + delete fBonjourSocketHandler; + + if (fDNSRef) { + DNSServiceRefDeallocate(fDNSRef); + fDNSRef = 0; + } +} + +//______________________________________________________________________________ +Int_t TBonjourResolver::ResolveBonjourRecord(const TBonjourRecord &record) +{ + // Resolve Bonjour service to IP address and port. + // Returns -1 in case of error, 0 otherwise. + + if (fDNSRef) { + Warning("ResolveBonjourRecord", "resolve already in process"); + return 0; + } + + DNSServiceErrorType err = DNSServiceResolve(&fDNSRef, 0, 0, + record.GetServiceName(), + record.GetRegisteredType(), + record.GetReplyDomain(), + BonjourResolveReply, this); + if (err != kDNSServiceErr_NoError) { + Error("ResolveBonjourRecord", "error in DNSServiceResolve (%d)", err); + return -1; + } + + Int_t sockfd = DNSServiceRefSockFD(fDNSRef); + if (sockfd == -1) { + Error("ResolveBonjourRecord", "invalide sockfd"); + return -1; + } + + fBonjourSocketHandler = new TFileHandler(sockfd, TFileHandler::kRead); + fBonjourSocketHandler->Connect("Notified()", "TBonjourResolver", this, "BonjourSocketReadyRead()"); + fBonjourSocketHandler->Add(); + + return 0; +} + +//______________________________________________________________________________ +void TBonjourResolver::RecordResolved(const TInetAddress *hostInfo, Int_t port) +{ + // Emit RecordResolved signal. + + Long_t args[2]; + args[0] = (Long_t) hostInfo; + args[1] = port; + + Emit("RecordResolved(TInetAddress*,Int_t)", args); +} + +//______________________________________________________________________________ +void TBonjourResolver::BonjourSocketReadyRead() +{ + // The Bonjour socket is ready for reading. Tell Bonjour to process the + // information on the socket, this will invoke the BonjourResolveReply + // callback. This is a private slot, used in ResolveBonjourRecord. + + DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef); + if (err != kDNSServiceErr_NoError) + Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult"); +} + +//______________________________________________________________________________ +void TBonjourResolver::BonjourResolveReply(DNSServiceRef, + DNSServiceFlags, UInt_t, + DNSServiceErrorType errorCode, const char *, + const char *hostTarget, UShort_t port, UShort_t, + const unsigned char *, void *context) +{ + // Static Bonjour resolver callback function. + + TBonjourResolver *resolver = static_cast<TBonjourResolver *>(context); + if (errorCode != kDNSServiceErr_NoError) { + ::Error("TBonjourResolver::BonjourResolveReply", "error in BonjourResolveReply"); + //resolver->Error(errorCode); + } else { + resolver->fPort = ntohs(port); + resolver->fHostAddress = gSystem->GetHostByName(hostTarget); + resolver->RecordResolved(&resolver->fHostAddress, resolver->fPort); + } +}