ArnLib  4.0.x
Active Registry Network
ArnDiscover.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2022 Michael Wiklund.
2 // All rights reserved.
3 // Contact: arnlib@wiklunden.se
4 //
5 // This file is part of the ArnLib - Active Registry Network.
6 // Parts of ArnLib depend on Qt and/or other libraries that have their own
7 // licenses. Usage of these other libraries is subject to their respective
8 // license agreements.
9 //
10 // GNU Lesser General Public License Usage
11 // This file may be used under the terms of the GNU Lesser General Public
12 // License version 2.1 as published by the Free Software Foundation and
13 // appearing in the file LICENSE_LGPL.txt included in the packaging of this
14 // file. In addition, as a special exception, you may use the rights described
15 // in the Nokia Qt LGPL Exception version 1.1, included in the file
16 // LGPL_EXCEPTION.txt in this package.
17 //
18 // GNU General Public License Usage
19 // Alternatively, this file may be used under the terms of the GNU General Public
20 // License version 3.0 as published by the Free Software Foundation and appearing
21 // in the file LICENSE_GPL.txt included in the packaging of this file.
22 //
23 // Other Usage
24 // Alternatively, this file may be used in accordance with the terms and conditions
25 // contained in a signed written agreement between you and Michael Wiklund.
26 //
27 // This program is distributed in the hope that it will be useful, but WITHOUT ANY
28 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
29 // PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
30 //
31 
32 #include "ArnInc/ArnDiscover.hpp"
33 #include "private/ArnDiscover_p.hpp"
34 #include "ArnInc/ArnZeroConf.hpp"
35 #include "ArnInc/ArnM.hpp"
36 #include "ArnInc/ArnLib.hpp"
37 #include <QHostInfo>
38 #include <QNetworkInterface>
39 #include <QTimer>
40 
41 using Arn::XStringMap;
42 
43 
45 
46 ArnDiscoverInfoPrivate::ArnDiscoverInfoPrivate()
47 {
48  _id = -1; // Unknown
49  _resolvCode = ArnZeroConf::Error::Ok;
50  _hostPort = 0;
51  _stopState = ArnDiscoverInfo::State::HostIp;
52 }
53 
54 
55 ArnDiscoverInfoPrivate::~ArnDiscoverInfoPrivate()
56 {
57 }
58 
59 
61  : d_ptr( new ArnDiscoverInfoPrivate)
62 {
63 }
64 
65 
66 ArnDiscoverInfo::ArnDiscoverInfo( ArnDiscoverInfoPrivate& dd)
67  : d_ptr( &dd)
68 {
69 }
70 
71 
73  : d_ptr( new ArnDiscoverInfoPrivate( *other.d_ptr))
74 {
75 }
76 
77 
79 {
80  *d_ptr = *other.d_ptr;
81 
82  return *this;
83 }
84 
85 
87 {
88 
89  delete d_ptr;
90 }
91 
92 
94 {
95  Q_D(const ArnDiscoverInfo);
96 
97  return (d->_state < d->_stopState) && !isError();
98 }
99 
100 
102 {
103  Q_D(const ArnDiscoverInfo);
104 
105  return (d->_state == State::HostInfoErr) || (d->_state == State::HostIpErr);
106 }
107 
108 
110 {
111  Q_D(const ArnDiscoverInfo);
112 
113  return d->_state;
114 }
115 
116 
118 {
119  Q_D(const ArnDiscoverInfo);
120 
121  return d->_stopState;
122 }
123 
124 
126 {
127  Q_D(const ArnDiscoverInfo);
128 
129  return d->_type;
130 }
131 
132 
133 QStringList ArnDiscoverInfo::groups() const
134 {
135  Q_D(const ArnDiscoverInfo);
136 
137  return d->_properties.values("group");
138 }
139 
140 
142 {
143  Q_D(const ArnDiscoverInfo);
144 
145  return d->_serviceName;
146 }
147 
148 
149 QString ArnDiscoverInfo::domain() const
150 {
151  Q_D(const ArnDiscoverInfo);
152 
153  return d->_domain;
154 }
155 
156 
158 {
159  Q_D(const ArnDiscoverInfo);
160 
161  return d->_hostName;
162 }
163 
164 
166 {
167  Q_D(const ArnDiscoverInfo);
168 
169  return d->_hostPort;
170 }
171 
172 
173 QHostAddress ArnDiscoverInfo::hostIp() const
174 {
175  Q_D(const ArnDiscoverInfo);
176 
177  return d->_hostIp;
178 }
179 
180 
182 {
183  Q_D(const ArnDiscoverInfo);
184 
185  return d->_properties;
186 }
187 
188 
190 {
191  Q_D(const ArnDiscoverInfo);
192 
193  if (d->_state < State::HostInfo) return QString();
194 
195  switch (d->_type) {
196  case ArnDiscover::Type::Server: return "Server";
197  case ArnDiscover::Type::Client: return "Client";
199  // Fall throu
200  default: return "Unknown";
201  }
202 }
203 
204 
206 {
207  Q_D(const ArnDiscoverInfo);
208 
209  return d->_state < State::HostInfo ? QString() : QString::number( d->_hostPort);
210 }
211 
212 
214 {
215  Q_D(const ArnDiscoverInfo);
216 
217  return d->_state < State::HostIp ? QString() : d->_hostIp.toString();
218 }
219 
220 
222 {
224 }
225 
226 
228 {
229  Q_D(const ArnDiscoverInfo);
230 
231  return d->_resolvCode;
232 }
233 
234 
236 
238  ArnDiscoverBrowserB( parent)
239 {
240 }
241 
242 
244 
245 ArnDiscoverResolverPrivate::ArnDiscoverResolverPrivate()
246 {
247  _defaultService = "Arn Default Service";
248 }
249 
250 
251 ArnDiscoverResolverPrivate::~ArnDiscoverResolverPrivate()
252 {
253 }
254 
255 
257  : ArnDiscoverBrowserB( *new ArnDiscoverResolverPrivate, parent)
258 {
259 }
260 
261 
262 ArnDiscoverResolver::ArnDiscoverResolver( ArnDiscoverResolverPrivate& dd, QObject* parent)
263  : ArnDiscoverBrowserB( dd, parent)
264 {
265 }
266 
267 
268 int ArnDiscoverResolver::resolve( const QString& serviceName, bool forceUpdate)
269 {
270  Q_D(ArnDiscoverResolver);
271 
272  return ArnDiscoverBrowserB::resolve( serviceName.isEmpty() ? d->_defaultService : serviceName, forceUpdate);
273 }
274 
275 
277 {
278  Q_D(const ArnDiscoverResolver);
279 
280  return d->_defaultService;
281 }
282 
283 
284 void ArnDiscoverResolver::setDefaultService( const QString& defaultService)
285 {
286  Q_D(ArnDiscoverResolver);
287 
288  if (!defaultService.isEmpty())
289  d->_defaultService = defaultService;
290 }
291 
292 
294 
295 ArnDiscoverBrowserBPrivate::ArnDiscoverBrowserBPrivate()
296 {
297  _defaultStopState = ArnDiscoverInfo::State::HostIp;
298  _serviceBrowser = new ArnZeroConfBrowser;
299 }
300 
301 
302 ArnDiscoverBrowserBPrivate::~ArnDiscoverBrowserBPrivate()
303 {
304  delete _serviceBrowser;
305 }
306 
307 
308 void ArnDiscoverBrowserB::init()
309 {
310  Q_D(ArnDiscoverBrowserB);
311 
312  connect( d->_serviceBrowser, SIGNAL(browseError(int)),
313  this, SLOT(onBrowseError(int)));
314  connect( d->_serviceBrowser, SIGNAL(serviceAdded(int,QString,QString)),
315  this, SLOT(onServiceAdded(int,QString,QString)));
316  connect( d->_serviceBrowser, SIGNAL(serviceRemoved(int,QString,QString)),
317  this, SLOT(onServiceRemoved(int,QString,QString)));
318 
320  foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) {
321  QNetworkInterface::InterfaceFlags flags = interface.flags();
322  if (!flags.testFlag( QNetworkInterface::IsUp)
323  || flags.testFlag( QNetworkInterface::IsPointToPoint)
324  || flags.testFlag( QNetworkInterface::IsLoopBack))
325  continue;
326 
327  foreach (QNetworkAddressEntry entry, interface.addressEntries()) {
328  QAbstractSocket::NetworkLayerProtocol prot = entry.ip().protocol();
329  if ((prot != QAbstractSocket::IPv4Protocol) && (prot != QAbstractSocket::IPv6Protocol))
330  continue;
331 
332  int prefixLen = entry.prefixLength();
333  if (prefixLen < 0) {
334  // This is a bug in some Qt for android, windows ... (Not linux)
335  prefixLen = 24;
336  if (Arn::warningMDNS) qWarning() << "Bad netmask: nif=" << interface.humanReadableName()
337  << ", asume prefixLen=" << prefixLen;
338  }
339  ArnDiscoverBrowserBPrivate::SubNet subNet( entry.ip(), prefixLen);
340  d->_localHostNetList += subNet;
341  }
342  }
343 }
344 
345 
347  QObject( parent)
348  , d_ptr( new ArnDiscoverBrowserBPrivate)
349 {
350  init();
351 }
352 
353 
355 {
356  delete d_ptr;
357 }
358 
359 
360 ArnDiscoverBrowserB::ArnDiscoverBrowserB( ArnDiscoverBrowserBPrivate& dd, QObject* parent)
361  : QObject( parent)
362  , d_ptr( &dd)
363 {
364  init();
365 }
366 
367 
369 {
370  Q_D(const ArnDiscoverBrowserB);
371 
372  return d->_activeServInfos.size();
373 }
374 
375 
377 {
378  Q_D(ArnDiscoverBrowserB);
379 
380  static ArnDiscoverInfo nullInfo;
381 
382  if ((index < 0) || (index >= d->_activeServInfos.size())) return nullInfo;
383 
384  return d->_activeServInfos.at( index);
385 }
386 
387 
389 {
390  Q_D(ArnDiscoverBrowserB);
391 
392  int index = d->_activeServIds.indexOf( id);
393  return infoByIndex( index);
394 }
395 
396 
397 const ArnDiscoverInfo& ArnDiscoverBrowserB::infoByName( const QString& serviceName)
398 {
399  return infoById( serviceNameToId( serviceName));
400 }
401 
402 
404 {
405  Q_D(ArnDiscoverBrowserB);
406 
407  if ((index < 0) || (index >= d->_activeServIds.size())) return -1;
408 
409  return d->_activeServIds.at( index);
410 }
411 
412 
414 {
415  Q_D(ArnDiscoverBrowserB);
416 
417  return d->_activeServIds.indexOf( id);
418 }
419 
420 
421 int ArnDiscoverBrowserB::serviceNameToId( const QString& name)
422 {
423  Q_D(ArnDiscoverBrowserB);
424 
425  foreach (const ArnDiscoverInfo& info, d->_activeServInfos) {
426  if (info.d_ptr->_serviceName == name)
427  return info.d_ptr->_id;
428  }
429  return -1; // Not found
430 }
431 
432 
433 bool ArnDiscoverBrowserB::isBrowsing() const
434 {
435  Q_D(const ArnDiscoverBrowserB);
436 
437  return d->_serviceBrowser->isBrowsing();
438 }
439 
440 
441 void ArnDiscoverBrowserB::setFilter( ArnDiscover::Type typeFilter)
442 {
443  Q_D(ArnDiscoverBrowserB);
444 
445  switch (typeFilter) {
446  case ArnDiscover::Type::Server: d->_filter = "server"; break;
447  case ArnDiscover::Type::Client: d->_filter = "client"; break;
449  // Fall throu
450  default: d->_filter = "";
451  }
452 }
453 
454 
455 void ArnDiscoverBrowserB::setFilter( const QString& group)
456 {
457  Q_D(ArnDiscoverBrowserB);
458 
459  d->_filter = group;
460 }
461 
462 
464 {
465  Q_D(const ArnDiscoverBrowserB);
466 
467  return d->_defaultStopState;
468 }
469 
470 
472 {
473  Q_D(ArnDiscoverBrowserB);
474 
475  d->_defaultStopState = defaultStopState;
476 }
477 
478 
480 {
481  Q_D(ArnDiscoverBrowserB);
482 
483  if ((index < 0) || (index >= d->_activeServInfos.size())) return false; // Out of index
484 
485  ArnDiscoverInfo& info = d->_activeServInfos[ index];
486  if (state <= info.state()) return false; // Can only go forward
487 
488  if (info.inProgress()) { // Next state is in progress
489  info.d_ptr->_stopState = state; // Just update final state
490  }
491  else if (info.state() <= info.stopState()) { // Nothing in progress
492  info.d_ptr->_stopState = state; // Update for new final state
493  doNextState( info); // Startup state change
494  }
495  else {
496  Q_ASSERT_X(false, "ArnDiscoverBrowser::goTowardState()", "State passed stopState");
497  return false; // Internal error
498  }
499 
500  return true;
501 }
502 
503 
504 void ArnDiscoverBrowserB::browse( bool enable)
505 {
506  Q_D(ArnDiscoverBrowserB);
507 
508  if (!enable) return stopBrowse();
509  if (isBrowsing()) return; // Already browsing
510 
511  d->_activeServIds.clear();
512  d->_activeServInfos.clear();
513 
514  d->_serviceBrowser->setSubType( d->_filter);
515  d->_serviceBrowser->browse( enable);
516 }
517 
518 
519 void ArnDiscoverBrowserB::stopBrowse()
520 {
521  Q_D(ArnDiscoverBrowserB);
522 
523  d->_serviceBrowser->stopBrowse();
524 }
525 
526 
527 int ArnDiscoverBrowserB::resolve( const QString& serviceName, bool forceUpdate)
528 {
529  Q_D(ArnDiscoverBrowserB);
530 
531  if (Arn::debugDiscover) qDebug() << "Man resolve Service: name=" << serviceName;
532 
533  int id = serviceNameToId( serviceName);
534  if ((id >= 0) && forceUpdate) {
535  int index = IdToIndex( id);
536  removeServiceInfo( index);
537  id = -1; // Mark not found
538  }
539 
540  ArnDiscoverInfo* info = arnNullptr;
541  int index = -1;
542  if (id < 0) { // Not found, resolve new service
544  index = newServiceInfo( id, serviceName, QString());
545  Q_ASSERT(index >= 0); // Already resolving, internal error ...
546 
547  info = &d->_activeServInfos[ index];
548  doNextState( *info);
549  }
550  else { // Already resolving / resolved
551  index = IdToIndex( id);
552  info = &d->_activeServInfos[ index];
553  if (!info->inProgress()) // Not in progress, possibly do retry error
554  doNextState( *info);
555  }
556  Q_ASSERT(info && (index >= 0));
557 
558  if (info->inProgress()) {
559  info->d_ptr->_resolvCode = ArnZeroConf::Error::Running;
560  }
561  emit infoUpdated( index, info->state());
562 
563  return index;
564 }
565 
566 
567 void ArnDiscoverBrowserB::onBrowseError( int code)
568 {
569  if (Arn::debugDiscover) qDebug() << "Browse Error code=" << code;
570 }
571 
572 
573 void ArnDiscoverBrowserB::onServiceAdded( int id, const QString& name, const QString& domain)
574 {
575  Q_D(ArnDiscoverBrowserB);
576 
577  if (Arn::debugDiscover) qDebug() << "Browse Service added: name=" << name << " domain=" << domain
578  << " escFullDomain=" << d->_serviceBrowser->escapedFullDomain();
579 
580  int index = newServiceInfo( id, name, domain);
581  Q_ASSERT(index >= 0);
582 
583  emit serviceAdded( index, name);
584  doNextState( d->_activeServInfos[ index]);
585 }
586 
587 
588 void ArnDiscoverBrowserB::onServiceRemoved( int id, const QString& name, const QString& domain)
589 {
590  Q_D(ArnDiscoverBrowserB);
591 
592  if (Arn::debugDiscover) qDebug() << "Browse Service removed: name=" << name << " domain=" << domain;
593  int index = d->_activeServIds.indexOf( id);
594  removeServiceInfo( index);
595 
596  emit serviceRemoved( index);
597 }
598 
599 
600 void ArnDiscoverBrowserB::onResolveError( int id, int code)
601 {
602  Q_D(ArnDiscoverBrowserB);
603 
604  ArnZeroConfResolve* ds = qobject_cast<ArnZeroConfResolve*>( sender());
605  Q_ASSERT(ds);
606 
607  if (Arn::debugDiscover) qDebug() << "Resolve Error code=" << code;
608 
609  int index = d->_activeServIds.indexOf( id);
610  if (index >= 0) { // Service still exist
611  ArnDiscoverInfo& info = d->_activeServInfos[ index];
612  info.d_ptr->_state = ArnDiscoverInfo::State::HostInfoErr;
613  info.d_ptr->_resolvCode = code;
614 
615  emit infoUpdated( index, info.state());
616  // Will not go to next state during error
617  }
618 
619  ds->releaseResolve();
620  ds->deleteLater();
621 }
622 
623 
624 void ArnDiscoverBrowserB::onResolved( int id, const QByteArray& escFullDomain)
625 {
626  Q_UNUSED(escFullDomain)
627  Q_D(ArnDiscoverBrowserB);
628 
629  ArnZeroConfResolve* ds = qobject_cast<ArnZeroConfResolve*>( sender());
630  Q_ASSERT(ds);
631 
632  QString name = ds->serviceName();
633  if (Arn::debugDiscover) qDebug() << "Resolved Service: name=" << name
634  << " escFullDomain=" << ds->escapedFullDomain();
635  int index = d->_activeServIds.indexOf( id);
636  if (index >= 0) { // Service still exist
637  ArnDiscoverInfo& info = d->_activeServInfos[ index];
638  XStringMap xsmTxt;
639  ds->getTxtRecordMap( xsmTxt);
640  if (xsmTxt.key( xsmTxt.size() - 1) == "protovers") // Mitigate reversed order from ZeroConfig manipulation
641  xsmTxt.reverseOrder();
642  QByteArray servProp = xsmTxt.value("server");
643  info.d_ptr->_type = servProp.isNull() ? ArnDiscover::Type::None
644  : (servProp.toInt() ? ArnDiscover::Type::Server
646  info.d_ptr->_state = ArnDiscoverInfo::State::HostInfo;
647  info.d_ptr->_resolvCode = ArnZeroConf::Error::Ok;
648  info.d_ptr->_hostName = ds->host();
649  info.d_ptr->_hostPort = ds->port();
650  info.d_ptr->_properties = xsmTxt;
651 
652  emit infoUpdated( index, info.state());
653  doNextState( info);
654  }
655 
656  ds->releaseResolve();
657  ds->deleteLater();
658 }
659 
660 
661 void ArnDiscoverBrowserB::onLookupError( int id, int code)
662 {
663  Q_D(ArnDiscoverBrowserB);
664 
665  ArnZeroConfLookup* ds = qobject_cast<ArnZeroConfLookup*>( sender());
666  Q_ASSERT(ds);
667 
668  if (Arn::debugDiscover) qDebug() << "Lookup Error code=" << code;
669 
670  int index = d->_activeServIds.indexOf( id);
671  if (index >= 0) { // Service still exist
672  ArnDiscoverInfo& info = d->_activeServInfos[ index];
673  info.d_ptr->_state = ArnDiscoverInfo::State::HostIpErr;
674  info.d_ptr->_resolvCode = code; // MW: Ok?
675 
676  emit infoUpdated( index, info.state());
677  // Will not go to next state during error
678  }
679 
680  ds->releaseLookup();
681  ds->deleteLater();
682 }
683 
684 
685 void ArnDiscoverBrowserB::onLookuped( int id)
686 {
687  Q_D(ArnDiscoverBrowserB);
688 
689  ArnZeroConfLookup* ds = qobject_cast<ArnZeroConfLookup*>( sender());
690  Q_ASSERT(ds);
691 
692  QString hostName = ds->host();
693  if (Arn::debugDiscover) qDebug() << "Lookuped host: name=" << hostName;
694  int index = d->_activeServIds.indexOf( id);
695  if (index >= 0) { // Service still exist
696  ArnDiscoverInfo& info = d->_activeServInfos[ index];
697  info.d_ptr->_state = ArnDiscoverInfo::State::HostIp;
698  info.d_ptr->_hostIpLookup = ds->hostAddr();
699  info.d_ptr->_hostIp = info.d_ptr->_hostIpLookup; // Prelimary
700  info.d_ptr->_resolvCode = ArnZeroConf::Error::Ok; // MW: Ok?
701  doHostIpLogic( info);
702 
703  emit infoUpdated( index, info.state());
704  }
705 
706  ds->releaseLookup();
707  ds->deleteLater();
708 }
709 
710 
711 void ArnDiscoverBrowserB::doHostIpLogic( ArnDiscoverInfo& info)
712 {
713  Q_D(ArnDiscoverBrowserB);
714 
715  QList<QHostAddress> remHostIpList;
716  remHostIpList += info.d_ptr->_hostIpLookup; // Lookup Ip has first prio
717 
718  XStringMap& xsm = info.d_ptr->_properties;
719  for (uint i = 0; true; ++i) {
720  QString hostIpTxt = xsm.valueString( "hostIp", i);
721  if (hostIpTxt.isNull()) break;
722  QHostAddress hostIp( hostIpTxt);
723  if (hostIp.isNull()) continue; // Not valid address
724 
725  remHostIpList += hostIp;
726  }
727 
728  foreach (const QHostAddress& remHostIp, remHostIpList) {
729  foreach ( const ArnDiscoverBrowserBPrivate::SubNet& subNet, d->_localHostNetList) {
730  if (remHostIp.isInSubnet( subNet)) { // This remote host can be reached in a local net
731  info.d_ptr->_hostIp = remHostIp; // Modify to use this address (can be same)
732  }
733  }
734  }
735 }
736 
737 
738 int ArnDiscoverBrowserB::newServiceInfo( int id, const QString& name, const QString& domain)
739 {
740  Q_D(ArnDiscoverBrowserB);
741 
742  ArnDiscoverInfo info;
743  info.d_ptr->_id = id;
744  info.d_ptr->_state = ArnDiscoverInfo::State::ServiceName;
745  info.d_ptr->_serviceName = name;
746  info.d_ptr->_domain = domain;
747  info.d_ptr->_stopState = d->_defaultStopState;
748 
749  int index;
750  for (index = 0; index < d->_activeServInfos.size(); ++index) {
751  const QString& indexName = d->_activeServInfos.at( index).serviceName();
752  if (name == indexName) return -1; // Error already exist
753  if (name < indexName) break; // Sorting place found
754  }
755  d->_activeServIds.insert( index, id);
756  d->_activeServInfos.insert( index, info);
757 
758  return index;
759 }
760 
761 
762 void ArnDiscoverBrowserB::removeServiceInfo( int index)
763 {
764  Q_D(ArnDiscoverBrowserB);
765 
766  if ((index < 0) || (index >= d->_activeServIds.size())) return;
767 
768  d->_activeServIds.removeAt( index);
769  d->_activeServInfos.removeAt( index);
770 }
771 
772 
773 void ArnDiscoverBrowserB::doNextState( ArnDiscoverInfo& info)
774 {
775  if (info.state() >= info.stopState()) return; // At stop state, do nothing more now
776 
777  switch (info.state()) {
778  case ArnDiscoverInfo::State::HostInfoErr: // Will retry resolv
779  // Fall throu
781  {
782  info.d_ptr->_state = ArnDiscoverInfo::State::ServiceName;
783 
784  ArnZeroConfResolve* ds = new ArnZeroConfResolve( info.serviceName(), this);
785  ds->setId( info.d_ptr->_id);
786  connect( ds, SIGNAL(resolveError(int,int)), this, SLOT(onResolveError(int,int)));
787  connect( ds, SIGNAL(resolved(int,QByteArray)), this, SLOT(onResolved(int,QByteArray)));
788  ds->resolve();
789  break;
790  }
791  case ArnDiscoverInfo::State::HostIpErr: // Will retry ip lookup
792  // Fall throu
794  {
795  info.d_ptr->_state = ArnDiscoverInfo::State::HostInfo;
796 
797  ArnZeroConfLookup* ds = new ArnZeroConfLookup( info.hostName(), this);
798  ds->setId( info.d_ptr->_id);
799  connect( ds, SIGNAL(lookupError(int,int)), this, SLOT(onLookupError(int,int)));
800  connect( ds, SIGNAL(lookuped(int)), this, SLOT(onLookuped(int)));
801  if (Arn::debugDiscover) qDebug() << "LookingUp host=" << info.hostName() << " Id=" << info.d_ptr->_id;
802  ds->lookup();
803  break;
804  }
805  default:
806  break;
807  }
808 }
809 
810 
812 
813 ArnDiscoverAdvertisePrivate::ArnDiscoverAdvertisePrivate()
814 {
815  _hasSetupAdvertise = false;
816  _arnZCReg = new ArnZeroConfRegister;
817 }
818 
819 
820 ArnDiscoverAdvertisePrivate::~ArnDiscoverAdvertisePrivate()
821 {
822  delete _arnZCReg;
823 }
824 
825 
826 void ArnDiscoverAdvertise::init()
827 {
828 }
829 
830 
832  QObject( parent)
833  , d_ptr( new ArnDiscoverAdvertisePrivate)
834 {
835  init();
836 }
837 
838 
839 ArnDiscoverAdvertise::ArnDiscoverAdvertise( ArnDiscoverAdvertisePrivate& dd, QObject* parent)
840  : QObject( parent)
841  , d_ptr( &dd)
842 {
843  init();
844 }
845 
846 
848 {
849 
850  delete d_ptr;
851 }
852 
853 
854 void ArnDiscoverAdvertise::advertiseService( ArnDiscover::Type discoverType, const QString& serviceName,
855  int port, const QString& hostName)
856 {
858 
859  if (Arn::debugDiscover) qDebug() << "Discover advertise setup: serviceName=" << serviceName
860  << " port=" << port << " hostName=" << hostName;
861  d->_discoverType = discoverType;
862  d->_service = serviceName;
863 
864  XStringMap xsm;
865  xsm.add("protovers", "1.1"); // Should be first
866  xsm.add("arnlibVers", XStringMap( ArnM::info()).value("Ver"));
867  xsm.add("server", QByteArray::number( d->_discoverType == ArnDiscover::Type::Server));
868  d->_arnZCReg->setSubTypes( d->_groups);
869  d->_arnZCReg->addSubType( d->_discoverType == ArnDiscover::Type::Server ? "server" : "client");
870  for (int i = 0; i < d->_groups.size(); ++i) {
871  xsm.add("group", uint(i), d->_groups.at(i));
872  }
873  for (int i = 0; i < d->_hostIpList.size(); ++i) {
874  xsm.add("hostIp", uint(i), d->_hostIpList.at(i));
875  }
876  xsm += d->_customProperties;
877 
878  d->_arnZCReg->setTxtRecordMap( xsm);
879  d->_arnZCReg->setHost( hostName);
880  d->_arnZCReg->setPort( port >= 0 ? port : Arn::defaultTcpPort);
881 
882  connect( d->_arnZCReg, SIGNAL(registered(QString)), this, SLOT(serviceRegistered(QString)));
883  connect( d->_arnZCReg, SIGNAL(registrationError(int)), this, SLOT(serviceRegistrationError(int)));
884 
885  QTimer::singleShot(0, this, SLOT(postSetupThis())); // Ĺet persistance service etc init before ...
886 }
887 
888 
889 void ArnDiscoverAdvertise::postSetupThis()
890 {
892 
893  d->_hasSetupAdvertise = true;
894  if (Arn::debugDiscover) qDebug() << "DiscoverAdvertise setup has finnished";
895  if (!d->_service.isEmpty())
896  setService( d->_service);
897 }
898 
899 
900 void ArnDiscoverAdvertise::serviceRegistered( const QString& serviceName)
901 {
902  if (Arn::debugDiscover) qDebug() << "DiscoverAdvertice Service registered: serviceName=" << serviceName;
903 
904  emit serviceChanged( serviceName);
905 }
906 
907 
908 void ArnDiscoverAdvertise::serviceRegistrationError(int code)
909 {
910  if (Arn::debugDiscover) qDebug() << "Service registration error: code=" << code;
911 
912  emit serviceChangeError( code);
913 }
914 
915 
917 {
918  Q_D(const ArnDiscoverAdvertise);
919 
920  return d->_customProperties;
921 }
922 
923 
925 {
927 
928  d->_customProperties = customProperties;
929 }
930 
931 
932 void ArnDiscoverAdvertise::addCustomProperty(const QString& key, const QString& val)
933 {
935 
936  d->_customProperties.add( key, val);
937 }
938 
939 
940 bool ArnDiscoverAdvertise::hasSetupAdvertise() const
941 {
942  Q_D(const ArnDiscoverAdvertise);
943 
944  return d->_hasSetupAdvertise;
945 }
946 
947 
948 void ArnDiscoverAdvertise::setHostIpList( const QStringList& hostIpList)
949 {
951 
952  d->_hostIpList = hostIpList;
953 }
954 
955 
957 {
958  Q_D(const ArnDiscoverAdvertise);
959 
960  return d->_service;
961 }
962 
963 
965 {
966  Q_D(const ArnDiscoverAdvertise);
967 
968  return d->_hasSetupAdvertise ? d->_arnZCReg->currentServiceName() : d->_service;
969 }
970 
971 
973 {
974  Q_D(const ArnDiscoverAdvertise);
975 
976  return State::fromInt( d->_arnZCReg->state());
977 }
978 
979 
980 void ArnDiscoverAdvertise::setService( const QString& service)
981 {
983 
984  if (Arn::debugDiscover) qDebug() << "DiscoverAdvertise setService: serviceName=" << service;
985 
986  d->_service = service;
987  if (!d->_hasSetupAdvertise) return;
988  if (service.isEmpty()) return;
989 
990  if (Arn::debugDiscover) qDebug() << "DiscoverAdvertise Service will change: serviceName=" << d->_service;
991  if (d->_arnZCReg->state() != ArnZeroConf::State::None)
992  d->_arnZCReg->releaseService();
993  d->_arnZCReg->setServiceName( d->_service);
994  d->_arnZCReg->registerService();
995 }
996 
997 
998 QStringList ArnDiscoverAdvertise::groups() const
999 {
1000  Q_D(const ArnDiscoverAdvertise);
1001 
1002  return d->_groups;
1003 }
1004 
1005 
1006 void ArnDiscoverAdvertise::setGroups( const QStringList& groups)
1007 {
1008  Q_D(ArnDiscoverAdvertise);
1009 
1010  d->_groups = groups;
1011 }
1012 
1013 
1014 void ArnDiscoverAdvertise::addGroup( const QString& group)
1015 {
1016  Q_D(ArnDiscoverAdvertise);
1017 
1018  d->_groups += group;
1019 }
void setGroups(const QStringList &groups)
Set service discover groups used for filter browsing.
QStringList groups() const
Return service discover groups used for filter browsing.
bool goTowardState(int index, ArnDiscoverInfo::State state)
Command a service to go towards a stop state.
bool warningMDNS
Definition: ArnLib.cpp:51
Registering a ZeroConfig service.
static QByteArray info()
Give information about this library.
Definition: ArnM.cpp:967
ArnDiscoverInfo::State defaultStopState() const
Return the default stop state for this service discover browser.
void setId(int id)
Sets the id number for this this lookup.
QString hostName() const
Return the host name for this service.
ArnDiscoverResolver(QObject *parent=arnNullptr)
Lookup a host.
static int getNextId()
Return the next id number for zero config objects.
bool debugDiscover
Definition: ArnLib.cpp:48
State of Arn discover browse data. Can be tested by relative order.
Definition: ArnDiscover.hpp:79
QStringList groups() const
Return the groups for this service.
quint16 port() const
Returns the port number for connecting to the service.
QString hostIpString() const
Return the printable host ip-address for this service.
void advertiseService(ArnDiscover::Type discoverType, const QString &serviceName, int port=-1, const QString &hostName=QString())
Start advertising the service.
QString serviceName() const
Returns the service name used for this resolv.
State state() const
Return the state for this service.
void serviceRemoved(int index)
Indicate service has been removed.
State stopState() const
Return the stop state for this service.
void serviceChangeError(int code)
Indicate unsuccessfull advertise of service.
Container class with string representation for serialized data.
Definition: XStringMap.hpp:107
int resolvCode() const
Return the latest resolv error code for this service.
Operation in progress.
Definition: ArnZeroConf.hpp:58
Advertise an Arn service.
Browsing for ZeroConfig services.
Ok, defined as kDNSServiceErr_NoError in dns_sd.h.
Definition: ArnZeroConf.hpp:56
const ArnDiscoverInfo & infoByIndex(int index)
Return the discover service info by its index.
ArnDiscoverInfo & operator=(const ArnDiscoverInfo &other)
Definition: ArnDiscover.cpp:78
void addGroup(const QString &group)
Add a service discover group.
const quint16 defaultTcpPort
Definition: Arn.hpp:50
QString host() const
Returns the host name for this resolv.
Got service name and domain (from browsing)
Definition: ArnDiscover.hpp:84
void serviceAdded(int index, const QString &name)
Indicate service has been added (discovered)
int indexToId(int index)
Return the discover service id by its index.
int resolve(const QString &serviceName, bool forceUpdate=true)
Resolve a specific service name.
Got error during resolving HostName, HostPort, type and properties.
Definition: ArnDiscover.hpp:86
Client Arn discover.
Definition: ArnDiscover.hpp:59
QString service() const
Returns the requested service name for this Advertise.
void releaseLookup()
Release the lookup.
ArnDiscoverBrowserB(QObject *parent=arnNullptr)
Inactive state.
Definition: ArnZeroConf.hpp:74
QHostAddress hostIp() const
Return the host ip-address for this service.
QByteArray value(int i, const char *def=arnNullptr) const
bool inProgress() const
Is discover in progress for this service.
Definition: ArnDiscover.cpp:93
Types of Arn discover advertise.
Definition: ArnDiscover.hpp:52
QString hostWithInfo() const
Get the the HostWithInfo string.
Arn::XStringMap customProperties() const
Return service custom properties.
QString currentService() const
Returns the current service name for this Advertise.
QString hostPortString() const
Return the printable host port for this service.
QString serviceName() const
Return the service name for this service.
int IdToIndex(int id)
Return the discover service index by its id.
void resolve(bool forceMulticast=false)
Resolve the service.
void lookup(bool forceMulticast=false)
Lookup the host address.
int serviceNameToId(const QString &name)
Return the discover service id by its name.
void addCustomProperty(const QString &key, const QString &val)
Add service custom property.
States of DiscoverAdvertise / These values must be synced with: ArnZeroConf::State.
QHostAddress hostAddr() const
Returns the host address for this Lookup.
Arn::XStringMap properties() const
Return the properties for this service.
Got error during DNS lookup HostIp.
Definition: ArnDiscover.hpp:90
void setDefaultService(const QString &defaultService)
Set the default service name.
void setCustomProperties(const Arn::XStringMap &customProperties)
Set service custom properties.
QString valueString(int i, const QString &def=QString()) const
ArnDiscoverBrowser(QObject *parent=arnNullptr)
void setDefaultStopState(ArnDiscoverInfo::State defaultStopState)
Set the default stop state for this service discover browser.
void releaseResolve()
Release the resolving.
Also got HostName, HostPort, type and properties (from resolving)
Definition: ArnDiscover.hpp:88
void setId(int id)
Sets the id number for this this resolv.
QByteArray key(int i, const char *def=arnNullptr) const
Resolv a ZeroConfig service.
Server Arn discover.
Definition: ArnDiscover.hpp:57
Browse() and resolve() together, may never be used to the same instance.
QString typeString() const
Return the printable type for this service.
void serviceChanged(const QString &serviceName)
Indicate successfull advertise of service.
Also got HostIp (from DNS lookup)
Definition: ArnDiscover.hpp:92
bool isError() const
Is in an error state for this service.
Class for holding current discover info of one service.
Definition: ArnDiscover.hpp:72
Resolv an Arn service.
QString defaultService() const
Return the default service name.
XStringMap & add(const char *key, const QByteArray &val)
void infoUpdated(int index, ArnDiscoverInfo::State state)
Indicate service has been updated.
State state() const
Returns the state for this Advertise.
const ArnDiscoverInfo & infoByName(const QString &serviceName)
Return the discover service info by its name.
quint16 hostPort() const
Return the port for this service.
bool getTxtRecordMap(Arn::XStringMap &xsm)
Load a XStringMap with parameters from the Txt Record.
QString makeHostWithInfo(const QString &host, const QString &info)
Make a combined host and info string, i.e. HostWithInfo
Definition: Arn.cpp:235
int size() const
Definition: XStringMap.hpp:121
int serviceCount() const
Return the number of active discover services.
QString domain() const
Return the domain for this service.
ArnDiscover::Type type() const
Return the discover type for this service.
QString host() const
Returns the host name for this Lookup.
const ArnDiscoverInfo & infoById(int id)
Return the discover service info by its id.
ArnDiscoverAdvertise(QObject *parent=arnNullptr)
Undefined Arn discover.
Definition: ArnDiscover.hpp:55
virtual void setService(const QString &service)
Set the service name.