TBonjourBrowser.cxx

Go to the documentation of this file.
00001 // @(#)root/bonjour:$Id: TBonjourBrowser.cxx 34481 2010-07-19 14:51:45Z rdm $
00002 // Author: Fons Rademakers   29/05/2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TBonjourBrowser                                                      //
00015 //                                                                      //
00016 // This class consists of one main member function,                     //
00017 // BrowseForServiceType(), that looks for the service.                  //
00018 // The rest of the class wraps the various bits of Bonjour service      //
00019 // browser. The static callback function is marked with the DNSSD_API   //
00020 // macro to make sure that the callback has the correct calling         //
00021 // convention on Windows.                                               //
00022 //                                                                      //
00023 // Bonjour works out-of-the-box on MacOS X. On Linux you have to        //
00024 // install the Avahi package and run the avahi-daemon. To compile       //
00025 // these classes and run Avahi on Linux you need to install the:        //
00026 //    avahi                                                             //
00027 //    avahi-compat-libdns_sd-devel                                      //
00028 //    nss-mdns                                                          //
00029 // packages. After installation make sure the avahi-daemon is started.  //
00030 //                                                                      //
00031 //////////////////////////////////////////////////////////////////////////
00032 
00033 #include "TBonjourBrowser.h"
00034 #include "TBonjourRecord.h"
00035 #include "TSysEvtHandler.h"
00036 #include "TList.h"
00037 #include "TError.h"
00038 #include "TSystem.h"
00039 
00040 
00041 ClassImp(TBonjourBrowser)
00042 
00043 //______________________________________________________________________________
00044 TBonjourBrowser::TBonjourBrowser() : fDNSRef(0), fBonjourSocketHandler(0)
00045 {
00046    // Default ctor.
00047 
00048    fBonjourRecords = new TList;
00049    fBonjourRecords->SetOwner();
00050 
00051    // silence Avahi about using Bonjour compat layer
00052    gSystem->Setenv("AVAHI_COMPAT_NOWARN", "1");
00053 }
00054 
00055 //______________________________________________________________________________
00056 TBonjourBrowser::~TBonjourBrowser()
00057 {
00058    // Cleanup.
00059 
00060    delete fBonjourRecords;
00061    delete fBonjourSocketHandler;
00062 
00063    if (fDNSRef) {
00064       DNSServiceRefDeallocate(fDNSRef);
00065       fDNSRef = 0;
00066    }
00067 }
00068 
00069 //______________________________________________________________________________
00070 Int_t TBonjourBrowser::BrowseForServiceType(const char *serviceType)
00071 {
00072    // Tell Bonjour to start browsing for a specific type of service.
00073    // Returns -1 in case of error, 0 otherwise.
00074 
00075    DNSServiceErrorType err = DNSServiceBrowse(&fDNSRef, 0,
00076                                               0, serviceType, 0,
00077                                               (DNSServiceBrowseReply)BonjourBrowseReply,
00078                                               this);
00079    if (err != kDNSServiceErr_NoError) {
00080       Error("BrowseForServiceType", "error in DNSServiceBrowse (%d)", err);
00081       return -1;
00082    }
00083 
00084    Int_t sockfd = DNSServiceRefSockFD(fDNSRef);
00085    if (sockfd == -1) {
00086       Error("BrowseForServiceType", "invalid sockfd");
00087       return -1;
00088    }
00089 
00090    fBonjourSocketHandler = new TFileHandler(sockfd, TFileHandler::kRead);
00091    fBonjourSocketHandler->Connect("Notified()", "TBonjourBrowser", this, "BonjourSocketReadyRead()");
00092    fBonjourSocketHandler->Add();
00093 
00094    return 0;
00095 }
00096 
00097 //______________________________________________________________________________
00098 void TBonjourBrowser::CurrentBonjourRecordsChanged(TList *bonjourRecords)
00099 {
00100    // Emit CurrentBonjourRecordsChanged signal.
00101 
00102    Emit("CurrentBonjourRecordsChanged(TList*)", (Long_t)bonjourRecords);
00103 }
00104 
00105 //______________________________________________________________________________
00106 void TBonjourBrowser::BonjourSocketReadyRead()
00107 {
00108    // The Bonjour socket is ready for reading. Tell Bonjour to process the
00109    // information on the socket, this will invoke the BonjourBrowseReply
00110    // callback. This is a private slot, used in BrowseForServiceType.
00111 
00112    // in case the browser has already been deleted
00113    if (!fDNSRef) return;
00114 
00115    DNSServiceErrorType err = DNSServiceProcessResult(fDNSRef);
00116    if (err != kDNSServiceErr_NoError)
00117       Error("BonjourSocketReadyRead", "error in DNSServiceProcessResult");
00118 }
00119 
00120 //______________________________________________________________________________
00121 void TBonjourBrowser::BonjourBrowseReply(DNSServiceRef,
00122                                          DNSServiceFlags flags, UInt_t,
00123                                          DNSServiceErrorType errorCode,
00124                                          const char *serviceName, const char *regType,
00125                                          const char *replyDomain, void *context)
00126 {
00127    // Static Bonjour browser callback function.
00128 
00129    TBonjourBrowser *browser = static_cast<TBonjourBrowser*>(context);
00130    if (errorCode != kDNSServiceErr_NoError) {
00131       ::Error("TBonjourBrowser::BonjourBrowseReply", "error in BonjourBrowseReply");
00132       //browser->Error(errorCode);
00133    } else {
00134       TBonjourRecord *record = new TBonjourRecord(serviceName, regType, replyDomain);
00135       if (flags & kDNSServiceFlagsAdd) {
00136          if (!browser->fBonjourRecords->FindObject(record))
00137             browser->fBonjourRecords->Add(record);
00138          else
00139             delete record;
00140       } else {
00141          TBonjourRecord *r = (TBonjourRecord*)browser->fBonjourRecords->Remove(record);
00142          delete r;
00143          delete record;
00144       }
00145       if (!(flags & kDNSServiceFlagsMoreComing)) {
00146          browser->CurrentBonjourRecordsChanged(browser->fBonjourRecords);
00147       }
00148    }
00149 }

Generated on Tue Jul 5 14:45:39 2011 for ROOT_528-00b_version by  doxygen 1.5.1