Commit 3c4f6cd4 authored by Fawzi Mohamed's avatar Fawzi Mohamed
Browse files

zeroconf: correct txt record handling, small avahi fixes



Change-Id: I660c12773a39655eec45d5ab3e00f70f5590dda7
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@nokia.com>
parent 4245774c
......@@ -204,7 +204,7 @@ public:
return kDNSServiceErr_Unknown;
AvahiServiceResolver *resolver = m_serviceResolverNew(connection->client, interfaceIndex, AVAHI_PROTO_INET, name, regtype, domain, AVAHI_PROTO_INET,
AvahiLookupFlags(0), &cAvahiResolveReply, gatherer);
// *sdRef = reinterpret_cast<DNSServiceRef>(resolver); // as we delete in the callback we don't need it...
//*sdRef = reinterpret_cast<DNSServiceRef>(resolver); // add for restart?
if (!resolver)
return kDNSServiceErr_Unknown; // avahi_strerror(avahi_client_errno(connection->client));
return kDNSServiceErr_NoError;
......@@ -325,9 +325,11 @@ ZConfLib::Ptr ZConfLib::createAvahiLib(const QString &libName, ZConfLib::Ptr fal
return ZConfLib::Ptr(new AvahiZConfLib(libName, fallback));
}
extern "C" void cAvahiResolveReply( AvahiServiceResolver * r, AvahiIfIndex interface, AvahiProtocol /*protocol*/,
AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *hostName,
const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags /*flags*/, void* context)
extern "C" void cAvahiResolveReply(
AvahiServiceResolver * r, AvahiIfIndex interface, AvahiProtocol /*protocol*/,
AvahiResolverEvent event, const char * /*name*/, const char * /*type*/,
const char * /*domain*/, const char *hostName, const AvahiAddress *address, uint16_t port,
AvahiStringList *txt, AvahiLookupResultFlags /*flags*/, void* context)
{
enum { defaultTtl = 0 };
ServiceGatherer *sg = reinterpret_cast<ServiceGatherer *>(context);
......@@ -335,24 +337,18 @@ extern "C" void cAvahiResolveReply( AvahiServiceResolver * r, AvahiIfIndex inter
qDebug() << "context was null in cAvahiResolveReply";
return;
}
const unsigned char * txtPtr = 0;
unsigned short txtLen = 0;
AvahiStringList *txtAtt=0;
const unsigned char emptyTxt[1]="";
switch (event) {
case AVAHI_RESOLVER_FAILURE:
sg->serviceResolveReply(0, kDNSServiceErr_Timeout, interface, 0, QString(), 0, 0);
break;
case AVAHI_RESOLVER_FOUND:
if (txt) {
txtPtr = txt->text;
txtLen = static_cast<unsigned short>(txt->size);
qDebug() << "Error: txt was null in cAvahiResolveReply for service:" << name << " type:" << type << " domain:" << domain;
}
txtAtt=(txt?txt->next:0);
sg->serviceResolveReply(kDNSServiceFlagsAdd|((txtAtt || address)?kDNSServiceFlagsMoreComing:0), interface, kDNSServiceErr_NoError,
hostName, QString::number(port), txtLen, txtPtr);
hostName, QString::number(port), 0, emptyTxt);
txtAtt=txt;
while (txtAtt) {
sg->txtRecordReply(kDNSServiceFlagsAdd|((txtAtt->next || address)?kDNSServiceFlagsMoreComing:0),kDNSServiceErr_NoError,
sg->txtFieldReply(kDNSServiceFlagsAdd|((txtAtt->next || address)?kDNSServiceFlagsMoreComing:0),kDNSServiceErr_NoError,
static_cast<unsigned short>(txtAtt->size),txtAtt->text,-1);
txtAtt = txtAtt->next;
}
......@@ -366,11 +362,13 @@ extern "C" void cAvahiResolveReply( AvahiServiceResolver * r, AvahiIfIndex inter
ipv4.sin_family = AF_INET;
memcpy(&(ipv4.sin_addr),&(address->data.ipv4.address),sizeof(ipv4.sin_addr));
sg->addrReply(kDNSServiceFlagsAdd, kDNSServiceErr_NoError, hostName, reinterpret_cast<sockaddr*>(&ipv4), defaultTtl);
break;
case (AVAHI_PROTO_INET6):
memset(&ipv6,0,sizeof(ipv6));
ipv6.sin6_family = AF_INET6;
memcpy(&(ipv6.sin6_addr), &(address->data.ipv6.address), sizeof(ipv6.sin6_addr));
sg->addrReply(kDNSServiceFlagsAdd, kDNSServiceErr_NoError, hostName, reinterpret_cast<sockaddr*>(&ipv6), defaultTtl);
break;
default:
if (DEBUG_ZEROCONF)
qDebug() << "Warning: ignoring address with protocol " << address->proto << " for service " << sg->fullName();
......
......@@ -204,13 +204,14 @@ QDebug operator<<(QDebug dbg, const Service &service)
<< " fullName:" << service.fullName() << ", port:" << service.port()
<< ", txtRecord:{";
bool first=true;
const ServiceTxtRecord &txtRecord = service.txtRecord();
foreach (const QString &k, txtRecord){
QHashIterator<QString, QString> i(service.txtRecord());
while (i.hasNext()){
i.next();
if (first)
first = false;
else
dbg << ", ";
dbg << k << ":" << txtRecord.value(k);
dbg << i.key() << ":" << i.value();
}
dbg << "}, ";
if (const QHostInfo *host = service.host()){
......@@ -734,7 +735,6 @@ void ServiceGatherer::serviceResolveReply(DNSServiceFlags fl
}
if (publishedService) publishedService->invalidate(); // delay this to enactServiceChange?
serviceBrowser->updateFlowStatusForFlags(flags);
uint16_t nKeys = txtRecordGetCount(txtLen, rawTxtRecord);
for (uint16_t i = 0; i < nKeys; ++i){
enum { maxTxtLen= 256 };
......@@ -749,11 +749,7 @@ void ServiceGatherer::serviceResolveReply(DNSServiceFlags fl
break;
}
keyBuf[maxTxtLen-1] = 0; // just to be sure
if (flags & kDNSServiceFlagsAdd) {
txtRecord[QString::fromUtf8(keyBuf)] = QString::fromUtf8(valueCStr, valLen);
} else {
txtRecord.remove(QString::fromUtf8(keyBuf)); // check value???
}
currentService->m_txtRecord.insert(QString::fromUtf8(keyBuf),QString::fromUtf8(valueCStr, valLen));
}
currentService->m_interfaceNr = interfaceIndex;
currentService->m_port = port;
......@@ -809,23 +805,65 @@ void ServiceGatherer::txtRecordReply(DNSServiceFlags flags,
qDebug() << "ServiceBrowser " << serviceBrowser->serviceType << " error " << txtErr
<< " decoding txt record of service " << currentService->fullName();
if ((flags & kDNSServiceFlagsAdd) == 0)
txtRecord.clear();
currentService->m_txtRecord.clear();
break;
}
keyBuf[255] = 0; // just to be sure
if (flags & kDNSServiceFlagsAdd) {
txtRecord[QString::fromUtf8(keyBuf)] = QString::fromUtf8(valueCStr, valLen);
currentService->m_txtRecord.insert(QString::fromUtf8(keyBuf), QString::fromUtf8(valueCStr, valLen));
} else {
txtRecord.remove(QString::fromUtf8(keyBuf)); // check value???
currentService->m_txtRecord.remove(QString::fromUtf8(keyBuf)); // check value???
}
}
if ((flags & kDNSServiceFlagsAdd) != 0) {
status |= TxtConnectionSuccess;
}
if (txtRecord.count() != 0 && currentServiceCanBePublished())
if (currentService->m_txtRecord.count() != 0 && currentServiceCanBePublished())
serviceBrowser->pendingGathererAdd(gatherer());
}
void ServiceGatherer::txtFieldReply(DNSServiceFlags flags,
DNSServiceErrorType errorCode,
uint16_t txtLen,
const void *rawTxtRecord,
uint32_t /*ttl*/){
if (errorCode != kDNSServiceErr_NoError){
if (errorCode == kDNSServiceErr_Timeout){
if ((status & TxtConnectionSuccess) == 0){
qDebug() << "ServiceBrowser " << serviceBrowser->serviceType << " failed txt gathering for service "
<< currentService->fullName() << " as it did timeout";
status |= TxtConnectionFailed;
}
} else {
qDebug() << "ServiceBrowser " << serviceBrowser->serviceType << " failed txt gathering for service "
<< currentService->fullName() << " with error " << errorCode;
status |= TxtConnectionFailed;
}
if (status & TxtConnectionActive) {
status &= ~TxtConnectionActive;
lib()->refDeallocate(txtConnection);
serviceBrowser->updateFlowStatusForCancel();
}
return;
}
serviceBrowser->updateFlowStatusForFlags(flags);
uint16_t keyLen=0;
const char *txt=reinterpret_cast<const char *>(rawTxtRecord);
while (keyLen < txtLen) {
if (txt[keyLen]=='=')
break;
++keyLen;
}
if (flags & kDNSServiceFlagsAdd) {
currentService->m_txtRecord.insert(QString::fromUtf8(txt, keyLen),
QString::fromUtf8(txt + keyLen + 1,
((txtLen>keyLen)?txtLen - keyLen - 1:0)));
} else {
currentService->m_txtRecord.remove(QString::fromUtf8(txt, keyLen)); // check value???
}
}
void ServiceGatherer::addrReply(DNSServiceFlags flags,
DNSServiceErrorType errorCode,
const char *hostname,
......
......@@ -112,7 +112,6 @@ protected:
/// class that gathers all needed info on a service, all its methods (creation included) are supposed to be called by the listener/reaction thread
class ServiceGatherer {
public:
QHash<QString, QString> txtRecord;
QString hostName;
ServiceBrowserPrivate *serviceBrowser;
QHostInfo *host;
......@@ -158,6 +157,8 @@ public:
void txtRecordReply(DNSServiceFlags flags, DNSServiceErrorType errorCode,
uint16_t txtLen, const void *rawTxtRecord, uint32_t ttl);
void txtFieldReply(DNSServiceFlags flags, DNSServiceErrorType errorCode,
uint16_t txtLen, const void *rawTxtRecord, uint32_t ttl);
void addrReply(DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address,
uint32_t ttl);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment