ROOT logo
// @(#)root/bonjour:$Id: TBonjourResolver.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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// 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(),
                                               (DNSServiceResolveReply)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.

   // in case the resolver has already been deleted
   if (!fDNSRef) return;

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