00001
00002
00003
00004
00005
00006
00007 #include <arpa/inet.h>
00008 #include <net/if.h>
00009 #include <sys/select.h>
00010 #include <cstdlib>
00011 #include "XrdOuc/XrdOucBonjour.hh"
00012 #include "XrdSys/XrdSysError.hh"
00013 #include "Xrd/XrdProtLoad.hh"
00014
00015
00016 #include "XrdOuc/XrdOucFactoryBonjour.hh"
00017
00018
00019
00020
00021
00022 extern XrdSysError XrdLog;
00023
00024
00025
00026
00027
00028 #if !defined(__macos__)
00029 AvahiStringList *XrdOucBonjourRecord::GetTXTAvahiList()
00030 {
00031 AvahiStringList *list;
00032 uint16_t len, i;
00033 char key[256];
00034 const void *rawData, *value;
00035 uint8_t valueLen;
00036 XrdOucString entry;
00037 char valueTrimmed[1024];
00038
00039
00040 list = NULL;
00041 i = 0;
00042 key[0] = '\0';
00043 value = NULL;
00044
00045
00046 rawData = TXTRecordGetBytesPtr(&TXTRecord);
00047 len = TXTRecordGetLength(&TXTRecord);
00048
00049
00050
00051 while (TXTRecordGetItemAtIndex(len, rawData, i, 256, key, &valueLen, &value) != kDNSServiceErr_Invalid) {
00052
00053 entry.hardreset();
00054
00055 entry.append(key);
00056 if (value != NULL) {
00057 entry.append("=");
00058 if (valueLen > 0) {
00059
00060 strncpy(valueTrimmed, (const char *)value, valueLen);
00061
00062 valueTrimmed[valueLen] = '\0';
00063
00064 entry.append(valueTrimmed);
00065 }
00066 }
00067
00068
00069 list = avahi_string_list_add(list, entry.c_str());
00070 i++;
00071 }
00072
00073
00074 return list;
00075 }
00076 #endif
00077
00078 void XrdOucBonjourRecord::AddTXTRecord(const char * key, const char * value)
00079 {
00080 TXTRecordSetValue(&TXTRecord, key, strlen(value), value);
00081 }
00082
00083 void XrdOucBonjourRecord::AddTXTRecord(const char * key, int value)
00084 {
00085 char value_str[256];
00086
00087 snprintf(value_str, 256, "%d", value);
00088
00089 AddTXTRecord(key, value_str);
00090 }
00091
00092 void XrdOucBonjourRecord::SetServiceName(const char * name)
00093 {
00094
00095
00096
00097
00098
00099 ServiceName.assign(name, 0);
00100 }
00101
00102 void XrdOucBonjourRecord::SetRegisteredType(const char * type)
00103 {
00104 RegisteredType.assign(type, 0);
00105 }
00106
00107 void XrdOucBonjourRecord::SetReplyDomain(const char * domain)
00108 {
00109 ReplyDomain.assign(domain, 0);
00110 }
00111
00112 void XrdOucBonjourRecord::DeleteTXTRecord()
00113 {
00114 TXTRecordDeallocate(&TXTRecord);
00115 InitTXTRecord();
00116 }
00117
00118 XrdOucBonjourRecord & XrdOucBonjourRecord::operator=(const XrdOucBonjourRecord &other)
00119 {
00120 if (this != &other) {
00121 ServiceName.assign(other.ServiceName, 0);
00122 RegisteredType.assign(other.RegisteredType, 0);
00123 ReplyDomain.assign(other.ReplyDomain, 0);
00124 TXTRecordDeallocate(&TXTRecord);
00125 InitTXTRecord();
00126 CopyTXTRecord(other.TXTRecord);
00127 }
00128
00129 return *this;
00130 }
00131
00132 void XrdOucBonjourRecord::Print() const
00133 {
00134 XrdLog.Say("INFO: Bonjour RECORD = ", GetServiceName(), GetRegisteredType(), GetReplyDomain());
00135 XrdLog.Say("INFO: Bonjour TXT = ", GetTXTRecordData());
00136 }
00137
00138 void XrdOucBonjourRecord::AddRawTXTRecord(const char * rawData)
00139 {
00140 uint16_t i = 0, len;
00141 char key[256];
00142 uint8_t valueLen;
00143 const void * value;
00144
00145 TXTRecordDeallocate(&TXTRecord);
00146 InitTXTRecord();
00147
00148 len = strlen(rawData);
00149 while (TXTRecordGetItemAtIndex(len, rawData, i, 256, key, &valueLen, &value) != kDNSServiceErr_Invalid) {
00150 TXTRecordSetValue(&TXTRecord, key, valueLen, value);
00151 i++;
00152 }
00153 }
00154
00155 void XrdOucBonjourRecord::InitTXTRecord()
00156 {
00157 TXTRecordCreate(&TXTRecord, 0, NULL);
00158 }
00159
00160 void XrdOucBonjourRecord::CopyTXTRecord(const TXTRecordRef &otherRecord)
00161 {
00162 uint16_t i = 0, len;
00163 const void * rawTXT;
00164 char key[256];
00165 uint8_t valueLen;
00166 const void * value;
00167
00168 len = TXTRecordGetLength(&otherRecord);
00169 rawTXT = TXTRecordGetBytesPtr(&otherRecord);
00170 while (TXTRecordGetItemAtIndex(len, rawTXT, i, 256, key, &valueLen, &value) != kDNSServiceErr_Invalid) {
00171 TXTRecordSetValue(&TXTRecord, key, valueLen, value);
00172 i++;
00173 }
00174 }
00175
00176 const char * XrdOucBonjourRecord::GetTXTValue(const char * key, int &valueLen) const
00177 {
00178 uint16_t len;
00179 uint8_t valLen;
00180 const void * rawTXT;
00181
00182 len = TXTRecordGetLength(&TXTRecord);
00183 rawTXT = TXTRecordGetBytesPtr(&TXTRecord);
00184
00185
00186 rawTXT = TXTRecordGetValuePtr(len, rawTXT, key, &valLen);
00187 valueLen = valLen;
00188
00189 return (const char *)rawTXT;
00190 }
00191
00192
00193
00194
00195
00196 void XrdOucBonjourNode::SetHostName(const char * hostName)
00197 {
00198 HostName.assign(hostName, 0);
00199 }
00200
00201 void XrdOucBonjourNode::SetPort(unsigned short port)
00202 {
00203 Port = port;
00204 }
00205
00206 void XrdOucBonjourNode::SetBonjourRecord(const XrdOucBonjourRecord &record)
00207 {
00208 BonjourInfo = record;
00209 }
00210
00211 XrdOucBonjourNode & XrdOucBonjourNode::operator=(const XrdOucBonjourNode &other)
00212 {
00213 if (this != &other) {
00214 HostName.assign(other.HostName, 0);
00215 Port = other.Port;
00216 BonjourInfo = other.BonjourInfo;
00217 }
00218
00219 return *this;
00220 }
00221
00222 void XrdOucBonjourNode::Print() const
00223 {
00224 char port[36];
00225 snprintf(port, 36, "%d (%p)", GetPort(), this);
00226 const char *host = GetHostName() ? GetHostName() : "<empty>";
00227 XrdLog.Say("INFO: Bonjour NODE = ", host, ":", port);
00228 GetBonjourRecord().Print();
00229 }
00230
00231
00232
00233
00234
00235 XrdOucBonjourFactory *XrdOucBonjourFactory::FactoryByPlatform()
00236 {
00237
00238
00239
00240
00241
00242 #if defined(__macos__) // We are on Mac OS X, so load the mDNS version.
00243 return new XrdOucAppleBonjourFactory();
00244 #elif defined(__linux__) // We are on GNU/Linux, so load the Avahi version.
00245 return new XrdOucAvahiBonjourFactory();
00246 #else // Currently, Windows is not supported (altough with mDNS can be).
00247 return NULL;
00248 #endif
00249 }