ROOT logo
// @(#)root/bonjour:$Id: TBonjourRegistrar.cxx 34481 2010-07-19 14:51:45Z rdm $
// 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.                       //
//                                                                      //
// Bonjour works out-of-the-box on MacOS X. On Linux you have to        //
// install the Avahi package and run the avahi-daemon. To compile       //
// these classes and run Avahi on Linux you need to install the:        //
//    avahi                                                             //
//    avahi-compat-libdns_sd-devel                                      //
//    nss-mdns                                                          //
// packages. After installation make sure the avahi-daemon is started.  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBonjourRegistrar.h"
#include "TSysEvtHandler.h"
#include "TError.h"
#include "TSystem.h"

#include <arpa/inet.h>


ClassImp(TBonjourRegistrar)

//______________________________________________________________________________
TBonjourRegistrar::TBonjourRegistrar() : fDNSRef(0), fBonjourSocketHandler(0)
{
   // Default ctor.

   // silence Avahi about using Bonjour compat layer
   gSystem->Setenv("AVAHI_COMPAT_NOWARN", "1");
}

//______________________________________________________________________________
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,
                                                !strlen(record.GetServiceName()) ? 0
                                                : record.GetServiceName(),
                                                record.GetRegisteredType(),
                                                !strlen(record.GetReplyDomain()) ? 0
                                                : record.GetReplyDomain(),
                                                0, sport,
                                                record.GetTXTRecordsLength(),
                                                !strlen(record.GetTXTRecords()) ? 0
                                                : record.GetTXTRecords(),
                                                (DNSServiceRegisterReply)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(&registrar->fFinalRecord);
   }
}
 TBonjourRegistrar.cxx:1
 TBonjourRegistrar.cxx:2
 TBonjourRegistrar.cxx:3
 TBonjourRegistrar.cxx:4
 TBonjourRegistrar.cxx:5
 TBonjourRegistrar.cxx:6
 TBonjourRegistrar.cxx:7
 TBonjourRegistrar.cxx:8
 TBonjourRegistrar.cxx:9
 TBonjourRegistrar.cxx:10
 TBonjourRegistrar.cxx:11
 TBonjourRegistrar.cxx:12
 TBonjourRegistrar.cxx:13
 TBonjourRegistrar.cxx:14
 TBonjourRegistrar.cxx:15
 TBonjourRegistrar.cxx:16
 TBonjourRegistrar.cxx:17
 TBonjourRegistrar.cxx:18
 TBonjourRegistrar.cxx:19
 TBonjourRegistrar.cxx:20
 TBonjourRegistrar.cxx:21
 TBonjourRegistrar.cxx:22
 TBonjourRegistrar.cxx:23
 TBonjourRegistrar.cxx:24
 TBonjourRegistrar.cxx:25
 TBonjourRegistrar.cxx:26
 TBonjourRegistrar.cxx:27
 TBonjourRegistrar.cxx:28
 TBonjourRegistrar.cxx:29
 TBonjourRegistrar.cxx:30
 TBonjourRegistrar.cxx:31
 TBonjourRegistrar.cxx:32
 TBonjourRegistrar.cxx:33
 TBonjourRegistrar.cxx:34
 TBonjourRegistrar.cxx:35
 TBonjourRegistrar.cxx:36
 TBonjourRegistrar.cxx:37
 TBonjourRegistrar.cxx:38
 TBonjourRegistrar.cxx:39
 TBonjourRegistrar.cxx:40
 TBonjourRegistrar.cxx:41
 TBonjourRegistrar.cxx:42
 TBonjourRegistrar.cxx:43
 TBonjourRegistrar.cxx:44
 TBonjourRegistrar.cxx:45
 TBonjourRegistrar.cxx:46
 TBonjourRegistrar.cxx:47
 TBonjourRegistrar.cxx:48
 TBonjourRegistrar.cxx:49
 TBonjourRegistrar.cxx:50
 TBonjourRegistrar.cxx:51
 TBonjourRegistrar.cxx:52
 TBonjourRegistrar.cxx:53
 TBonjourRegistrar.cxx:54
 TBonjourRegistrar.cxx:55
 TBonjourRegistrar.cxx:56
 TBonjourRegistrar.cxx:57
 TBonjourRegistrar.cxx:58
 TBonjourRegistrar.cxx:59
 TBonjourRegistrar.cxx:60
 TBonjourRegistrar.cxx:61
 TBonjourRegistrar.cxx:62
 TBonjourRegistrar.cxx:63
 TBonjourRegistrar.cxx:64
 TBonjourRegistrar.cxx:65
 TBonjourRegistrar.cxx:66
 TBonjourRegistrar.cxx:67
 TBonjourRegistrar.cxx:68
 TBonjourRegistrar.cxx:69
 TBonjourRegistrar.cxx:70
 TBonjourRegistrar.cxx:71
 TBonjourRegistrar.cxx:72
 TBonjourRegistrar.cxx:73
 TBonjourRegistrar.cxx:74
 TBonjourRegistrar.cxx:75
 TBonjourRegistrar.cxx:76
 TBonjourRegistrar.cxx:77
 TBonjourRegistrar.cxx:78
 TBonjourRegistrar.cxx:79
 TBonjourRegistrar.cxx:80
 TBonjourRegistrar.cxx:81
 TBonjourRegistrar.cxx:82
 TBonjourRegistrar.cxx:83
 TBonjourRegistrar.cxx:84
 TBonjourRegistrar.cxx:85
 TBonjourRegistrar.cxx:86
 TBonjourRegistrar.cxx:87
 TBonjourRegistrar.cxx:88
 TBonjourRegistrar.cxx:89
 TBonjourRegistrar.cxx:90
 TBonjourRegistrar.cxx:91
 TBonjourRegistrar.cxx:92
 TBonjourRegistrar.cxx:93
 TBonjourRegistrar.cxx:94
 TBonjourRegistrar.cxx:95
 TBonjourRegistrar.cxx:96
 TBonjourRegistrar.cxx:97
 TBonjourRegistrar.cxx:98
 TBonjourRegistrar.cxx:99
 TBonjourRegistrar.cxx:100
 TBonjourRegistrar.cxx:101
 TBonjourRegistrar.cxx:102
 TBonjourRegistrar.cxx:103
 TBonjourRegistrar.cxx:104
 TBonjourRegistrar.cxx:105
 TBonjourRegistrar.cxx:106
 TBonjourRegistrar.cxx:107
 TBonjourRegistrar.cxx:108
 TBonjourRegistrar.cxx:109
 TBonjourRegistrar.cxx:110
 TBonjourRegistrar.cxx:111
 TBonjourRegistrar.cxx:112
 TBonjourRegistrar.cxx:113
 TBonjourRegistrar.cxx:114
 TBonjourRegistrar.cxx:115
 TBonjourRegistrar.cxx:116
 TBonjourRegistrar.cxx:117
 TBonjourRegistrar.cxx:118
 TBonjourRegistrar.cxx:119
 TBonjourRegistrar.cxx:120
 TBonjourRegistrar.cxx:121
 TBonjourRegistrar.cxx:122
 TBonjourRegistrar.cxx:123
 TBonjourRegistrar.cxx:124
 TBonjourRegistrar.cxx:125
 TBonjourRegistrar.cxx:126
 TBonjourRegistrar.cxx:127
 TBonjourRegistrar.cxx:128
 TBonjourRegistrar.cxx:129
 TBonjourRegistrar.cxx:130
 TBonjourRegistrar.cxx:131
 TBonjourRegistrar.cxx:132
 TBonjourRegistrar.cxx:133
 TBonjourRegistrar.cxx:134
 TBonjourRegistrar.cxx:135
 TBonjourRegistrar.cxx:136
 TBonjourRegistrar.cxx:137
 TBonjourRegistrar.cxx:138
 TBonjourRegistrar.cxx:139
 TBonjourRegistrar.cxx:140
 TBonjourRegistrar.cxx:141
 TBonjourRegistrar.cxx:142
 TBonjourRegistrar.cxx:143
 TBonjourRegistrar.cxx:144
 TBonjourRegistrar.cxx:145