XrdOucBonjour.hh

Go to the documentation of this file.
00001 #ifndef __XRDOUCBONJOUR_HH__
00002 #define __XRDOUCBONJOUR_HH__
00003 
00004 #include <dns_sd.h>
00005 #include <list>
00006 #include "XrdOuc/XrdOucString.hh"
00007 #include "XrdSys/XrdSysPthread.hh"
00008 
00009 #if defined(__linux__)
00010 #include <avahi-client/client.h>
00011 #include <avahi-client/publish.h>
00012 #include <avahi-common/strlst.h>
00013 #endif
00014 
00015 class XrdOucBonjourRecord;
00016 class XrdOucBonjourNode;
00017 class XrdOucBonjour;
00018 
00019 /******************************************************************************/
00020 /*                      T y p e   d e f i n i t i o n s                       */
00021 /******************************************************************************/
00022 
00023 #define TXT_LENGTH 100
00024 #define TIMEOUT 30
00025 
00026 #define kBonjourSrvDisabled -1
00027 #define kBonjourSrvBrowse    0
00028 #define kBonjourSrvRegister  1
00029 #define kBonjourSrvBoth      2
00030 
00031 // Type definition for the callback function.
00032 typedef void * (*XrdOucBonjourUpdateCallback)(void *);
00033 
00034 // Typedef of an struct to store the registration information. Since it is only
00035 // DCO, we do not need to define a class for that.
00036 typedef struct XrdOucBonjourRegisteredEntry {
00037    XrdOucBonjourRecord * record;
00038    unsigned short port;
00039    // Data for the service reference, both Avahi and Bonjour.
00040 #if defined(__macos__)
00041    // We must mantain this reference alive, since its our link to the mDNS.
00042    DNSServiceRef bonjourRef;
00043 #elif defined(__linux__)
00044    // In the case we are using Avahi, lets store the client info structure.
00045    struct {
00046       AvahiClient * avahiClient;
00047       AvahiEntryGroup * avahiEntryGroup;
00048    } avahiRef;
00049 #endif
00050 } XrdOucBonjourRegisteredEntry;
00051 
00052 // Typedef of an struct to store the subcription information. Since it is only
00053 // DCO, we not define a class for that.
00054 typedef struct XrdOucBonjourSubscribedEntry {
00055    XrdOucBonjourUpdateCallback callback;
00056    void * context;
00057    XrdOucString * serviceType;
00058    // Used to carry the Avahi browser information.
00059 #if defined(__linux__)
00060    AvahiClient * client;
00061 #endif
00062 } XrdOucBonjourSubscribedEntry;
00063 
00064 // Used to make the resolution dinamycally.
00065 typedef struct XrdOucBonjourResolutionEntry {
00066    XrdOucBonjourNode * node;
00067    XrdOucBonjourSubscribedEntry * callbackID;
00068 } XrdOucBonjourResolutionEntry;
00069 
00070 /******************************************************************************/
00071 /*                        B o n j o u r   r e c o r d                         */
00072 /******************************************************************************/
00073 
00074 // Note that this class depends on the compatibility layer of Avahi.
00075 class XrdOucBonjourRecord {
00076 private:
00077    XrdOucString ServiceName;
00078    XrdOucString RegisteredType;
00079    XrdOucString ReplyDomain;
00080    TXTRecordRef TXTRecord;
00081    void InitTXTRecord();
00082    void CopyTXTRecord(const TXTRecordRef &otherRecord);
00083 
00084 public:
00085    XrdOucBonjourRecord() {
00086       InitTXTRecord();
00087    }
00088 
00089    XrdOucBonjourRecord(const char * name,
00090                        const char * type,
00091                        const char * domain) :
00092       ServiceName(name), RegisteredType(type), ReplyDomain(domain) {
00093       InitTXTRecord();
00094    }
00095 
00096    XrdOucBonjourRecord(const XrdOucBonjourRecord &other) :
00097       ServiceName(other.ServiceName), RegisteredType(other.RegisteredType),
00098       ReplyDomain(other.ReplyDomain) {
00099       InitTXTRecord();
00100       CopyTXTRecord(other.TXTRecord);
00101    }
00102 
00103    virtual ~XrdOucBonjourRecord() {
00104       TXTRecordDeallocate(&TXTRecord);
00105    }
00106 
00107    const char *GetServiceName() const {
00108       return ServiceName.length() ? ServiceName.c_str() : NULL;
00109    }
00110    const char *GetRegisteredType() const {
00111       return RegisteredType.length() ? RegisteredType.c_str() : NULL;
00112    }
00113    const char *GetReplyDomain() const {
00114       return ReplyDomain.length() ? ReplyDomain.c_str() : NULL;
00115    }
00116    const char *GetTXTRecordData() const {
00117       return (const char *)TXTRecordGetBytesPtr(&TXTRecord);
00118    }
00119    const char *GetTXTValue(const char * key, int &len) const;
00120    int GetTXTRecordLength() const {
00121       return TXTRecordGetLength(&TXTRecord);
00122    }
00123 
00124 #if defined(__linux__)
00125    AvahiStringList *GetTXTAvahiList();
00126 #endif
00127 
00128    int MatchesServiceName(const char * pattern) const {
00129       return (const_cast<XrdOucString &>(ServiceName)).beginswith(pattern);
00130    }
00131    int MatchesRegisteredType(const char * pattern) const {
00132       return (const_cast<XrdOucString &>(RegisteredType)).beginswith(pattern);
00133    }
00134    int MatchesReplyDomain(const char * pattern) const {
00135       return (const_cast<XrdOucString &>(ReplyDomain)).beginswith(pattern);
00136    }
00137 
00138    void AddTXTRecord(const char * key, const char * value);
00139    void AddTXTRecord(const char * key, int value);
00140    void AddRawTXTRecord(const char * rawData);
00141    void SetServiceName(const char * name);
00142    void SetRegisteredType(const char * type);
00143    void SetReplyDomain(const char * domain);
00144    void DeleteTXTRecord();
00145 
00146    XrdOucBonjourRecord &operator=(const XrdOucBonjourRecord &other);
00147 
00148    void Print() const;
00149 };
00150 
00151 /******************************************************************************/
00152 /*                          B o n j o u r   n o d e                           */
00153 /******************************************************************************/
00154 
00155 class XrdOucBonjourNode {
00156 private:
00157    XrdOucString HostName;
00158    unsigned short Port;
00159    XrdOucBonjourRecord BonjourInfo;
00160 
00161 public:
00162    XrdOucBonjourNode() {
00163       Port = 0;
00164    }
00165 
00166    XrdOucBonjourNode(const char * hostName,
00167                      unsigned short port) :
00168       HostName(hostName) {
00169       Port = port;
00170    }
00171 
00172    XrdOucBonjourNode(const char * hostName,
00173                      unsigned short port,
00174                      XrdOucBonjourRecord const &bonjourInfo) :
00175       HostName(hostName), BonjourInfo(bonjourInfo) {
00176       Port = port;
00177    }
00178 
00179    XrdOucBonjourNode(XrdOucBonjourRecord const &bonjourInfo) :
00180       BonjourInfo(bonjourInfo) {
00181       Port = 0;
00182    }
00183 
00184    // A handful constructor for the browse reply callback
00185    XrdOucBonjourNode(const char * name,
00186                      const char * type,
00187                      const char * domain) :
00188       BonjourInfo(name, type, domain) {
00189       Port = 0;
00190    }
00191 
00192    XrdOucBonjourNode(const XrdOucBonjourNode &other) :
00193       HostName(other.HostName), BonjourInfo(other.BonjourInfo) {
00194       Port = other.Port;
00195    }
00196 
00197    virtual ~XrdOucBonjourNode() { }
00198 
00199    const char *GetHostName() const {
00200       return HostName.length() ? HostName.c_str() : NULL;
00201    }
00202    unsigned short GetPort() const  {
00203       return Port;
00204    }
00205    const XrdOucBonjourRecord &GetBonjourRecord() const {
00206       return BonjourInfo;
00207    }
00208    XrdOucBonjourRecord &GetBonjourRecord() {
00209       return BonjourInfo;
00210    }
00211 
00212    void SetHostName(const char * hostName);
00213    void SetPort(unsigned short port);
00214    void SetBonjourRecord(const XrdOucBonjourRecord &record);
00215 
00216    XrdOucBonjourNode &operator=(const XrdOucBonjourNode &other);
00217 
00218    void Print() const;
00219 };
00220 
00221 /******************************************************************************/
00222 /*                      B o n j o u r   s e r v i c e s                       */
00223 /******************************************************************************/
00224 
00225 class XrdOucBonjour {
00226 protected:
00227    // List of registered services we have.
00228    std::list<XrdOucBonjourNode *> ListOfNodes;
00229    XrdSysMutex ListOfNodesMutex;
00230 
00231 public:
00232    XrdOucBonjour() { }
00233    virtual ~XrdOucBonjour() { }
00234 
00235    // Register a service on the mDNS local service. This function also
00236    // subscribes the sender for updates on the discoverage service.
00237    virtual int RegisterService(XrdOucBonjourRecord &record,
00238                                unsigned short port = 0) = 0;
00239 
00240    // Subscribes a new client to receive updates about service discoveries.
00241    // This will detatch a new thread to process the updates, running (when
00242    // a new update arrives) the callback function in its own thread. This
00243    // function mush be thread-safe, and its responsability of the client
00244    // to ensure that.
00245    virtual int SubscribeForUpdates(const char * servicetype,
00246                                    XrdOucBonjourUpdateCallback callback,
00247                                    void * context) = 0;
00248 
00249    // Resolves the name of a node. If you provide a pointer to a node
00250    // object, this function completes the current information about hostname
00251    // and port. It is important to use the resolution by-demand since the list
00252    // may not contain updated information due to the use of highly dynamical
00253    // DHCP and APIPA addresses.
00254    virtual int ResolveNodeInformation(XrdOucBonjourResolutionEntry * nodeAndCallback) = 0;
00255 
00256    // Returns the current list of discovered nodes through the Bonjour local
00257    // mDNS. This list cannot be modified by clients of the class.
00258    const std::list<XrdOucBonjourNode *> &GetCurrentNodeList() const {
00259       return ListOfNodes;
00260    }
00261 
00262    // Methods for locking and unlocking the node table in the case that it
00263    // will be modified or an exclusive access is needed.
00264    void LockNodeList() {
00265       ListOfNodesMutex.Lock();
00266    }
00267    void UnLockNodeList() {
00268       ListOfNodesMutex.UnLock();
00269    }
00270 
00271    // Accessor to get the singleton instance.
00272    static XrdOucBonjour &getInstance();
00273 };
00274 
00275 /******************************************************************************/
00276 /*                      A b s t r a c t   f a c t o r y                       */
00277 /******************************************************************************/
00278 
00279 class XrdOucBonjourFactory {
00280 public:
00281    static XrdOucBonjourFactory *FactoryByPlatform();
00282 
00283    virtual XrdOucBonjour &GetBonjourManager() = 0;
00284    virtual ~XrdOucBonjourFactory() { }
00285 };
00286 
00287 #endif

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