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
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
00032 typedef void * (*XrdOucBonjourUpdateCallback)(void *);
00033
00034
00035
00036 typedef struct XrdOucBonjourRegisteredEntry {
00037 XrdOucBonjourRecord * record;
00038 unsigned short port;
00039
00040 #if defined(__macos__)
00041
00042 DNSServiceRef bonjourRef;
00043 #elif defined(__linux__)
00044
00045 struct {
00046 AvahiClient * avahiClient;
00047 AvahiEntryGroup * avahiEntryGroup;
00048 } avahiRef;
00049 #endif
00050 } XrdOucBonjourRegisteredEntry;
00051
00052
00053
00054 typedef struct XrdOucBonjourSubscribedEntry {
00055 XrdOucBonjourUpdateCallback callback;
00056 void * context;
00057 XrdOucString * serviceType;
00058
00059 #if defined(__linux__)
00060 AvahiClient * client;
00061 #endif
00062 } XrdOucBonjourSubscribedEntry;
00063
00064
00065 typedef struct XrdOucBonjourResolutionEntry {
00066 XrdOucBonjourNode * node;
00067 XrdOucBonjourSubscribedEntry * callbackID;
00068 } XrdOucBonjourResolutionEntry;
00069
00070
00071
00072
00073
00074
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
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
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
00223
00224
00225 class XrdOucBonjour {
00226 protected:
00227
00228 std::list<XrdOucBonjourNode *> ListOfNodes;
00229 XrdSysMutex ListOfNodesMutex;
00230
00231 public:
00232 XrdOucBonjour() { }
00233 virtual ~XrdOucBonjour() { }
00234
00235
00236
00237 virtual int RegisterService(XrdOucBonjourRecord &record,
00238 unsigned short port = 0) = 0;
00239
00240
00241
00242
00243
00244
00245 virtual int SubscribeForUpdates(const char * servicetype,
00246 XrdOucBonjourUpdateCallback callback,
00247 void * context) = 0;
00248
00249
00250
00251
00252
00253
00254 virtual int ResolveNodeInformation(XrdOucBonjourResolutionEntry * nodeAndCallback) = 0;
00255
00256
00257
00258 const std::list<XrdOucBonjourNode *> &GetCurrentNodeList() const {
00259 return ListOfNodes;
00260 }
00261
00262
00263
00264 void LockNodeList() {
00265 ListOfNodesMutex.Lock();
00266 }
00267 void UnLockNodeList() {
00268 ListOfNodesMutex.UnLock();
00269 }
00270
00271
00272 static XrdOucBonjour &getInstance();
00273 };
00274
00275
00276
00277
00278
00279 class XrdOucBonjourFactory {
00280 public:
00281 static XrdOucBonjourFactory *FactoryByPlatform();
00282
00283 virtual XrdOucBonjour &GetBonjourManager() = 0;
00284 virtual ~XrdOucBonjourFactory() { }
00285 };
00286
00287 #endif