// TODO: each builder should refcount its services, so a shared one does not get removed to early // (might disappear for one sd because of master breakdown) void DNSSDNetworkBuilder::removeService( DNSSD::RemoteService::Ptr service ) { QList<NetDevice>& deviceList = mNetworkPrivate->deviceList(); const QString hostName = service->hostName(); // device QMutableListIterator<NetDevice> it( deviceList ); while( it.hasNext()) { const NetDevice& device = it.next(); if( device.hostName() == hostName ) { // kDebug()<<hostName; QString id; const QString serviceType = service->type(); foreach( const DNSSDNetSystemAble* factory, mNetSystemFactoryList ) { if( factory->canCreateNetSystemFromDNSSD(serviceType) ) { id = factory->dnssdId( service ); break; } } NetDevicePrivate* d = device.dPtr(); NetService netService = d->removeService( id ); if( !netService.isValid() ) break; QList<NetService> removedServices; removedServices.append( netService ); mNetworkPrivate->emitServicesRemoved( removedServices ); // remove device on last service if( d->serviceList().count() == 0 ) { QList<NetDevice> removedDevices; removedDevices.append( device ); // remove only after taking copy from reference into removed list it.remove(); mNetworkPrivate->emitDevicesRemoved( removedDevices ); } break; } }
void DNSSDNetworkBuilder::addService( DNSSD::RemoteService::Ptr service ) { QList<NetDevice>& deviceList = mNetworkPrivate->deviceList(); QString hostName = service->hostName(); // TODO: this blocks. and the ip address should be delivered from DNS-SD with resolve const QHostAddress hostAddress = DNSSD::ServiceBrowser::resolveHostName( hostName ); const QString ipAddress = hostAddress.toString(); // forget domain name if just ip address if( hostName == ipAddress ) hostName.clear(); // device TODO: only search for if we can create the service? NetDevicePrivate* d = 0; const NetDevice* deviceOfService = 0; foreach( const NetDevice& device, deviceList ) { const QString deviceHostName = device.hostName(); const bool useIpAddress = ( deviceHostName.isEmpty() || hostName.isEmpty() ); const bool isSameAddress = useIpAddress ? ( device.ipAddress() == ipAddress ) : ( deviceHostName == hostName ); kDebug()<<"existing device:"<<deviceHostName<<"at"<<device.ipAddress()<<"vs."<<hostName<<"at"<<ipAddress<<":"<<isSameAddress; if( isSameAddress ) { d = device.dPtr(); // workaround: KDNSSD currently (4.7.0) emits two signals per service // just relying on service->serviceName() is fragile, but matches // current approach in removeService(...) QString id; const QString serviceType = service->type(); foreach( const DNSSDNetSystemAble* factory, mNetSystemFactoryList ) { if( factory->canCreateNetSystemFromDNSSD(serviceType) ) { id = factory->dnssdId( service ); break; } } if( d->hasService(id) ) return; deviceOfService = &device; break; } } if( !d ) { const QString deviceName = hostName.left( hostName.indexOf(QLatin1Char('.')) ); d = new NetDevicePrivate( deviceName ); d->setHostName( hostName ); d->setIpAddress( ipAddress ); NetDevice device( d ); deviceList.append( device ); deviceOfService = &deviceList.last(); QList<NetDevice> newDevices; newDevices.append( device ); // TODO: the new service will be announced two times, once with the new device and once alone. // what to do about that? which order? okay? for now just do not attach services before. find usecases. mNetworkPrivate->emitDevicesAdded( newDevices ); kDebug()<<"new device:"<<deviceName<<"at"<<hostName<<"by"<<service->type(); } else { if( d->hostName().isEmpty() && ! hostName.isEmpty() ) d->setHostName( hostName ); } const QString serviceType = service->type(); NetServicePrivate* netServicePrivate = 0; // do a priority based lookup who can build the object // TODO: priorisation foreach( const DNSSDNetSystemAble* factory, mNetSystemFactoryList ) { if( factory->canCreateNetSystemFromDNSSD(serviceType) ) { // TODO: here we should rather see if this service already exists netServicePrivate = factory->createNetService( service, *deviceOfService ); break; } } // TODO: create dummy service // if( ! netServicePrivate ) // netServicePrivate = new UnknownService; NetService netService( netServicePrivate ); d->addService( netService ); // try guessing the device type by the services on it // TODO: move into devicefactory NetDevice::Type deviceTypeByService = NetDevice::Unknown; QString deviceName; if( serviceType == QLatin1String("_workstation._tcp") ) { deviceTypeByService = NetDevice::Workstation; deviceName = service->serviceName().left( service->serviceName().lastIndexOf(QLatin1Char('[')) ).trimmed(); } else if( serviceType == QLatin1String("_net-assistant._udp") ) { deviceTypeByService = NetDevice::Workstation; deviceName = service->serviceName(); } else if( serviceType == QLatin1String("_airport._tcp") ) deviceTypeByService = NetDevice::Router; else if( serviceType == QLatin1String("_ipp._tcp") || serviceType == QLatin1String("_printer._tcp") || serviceType == QLatin1String("_pdl-datastream._tcp") ) { deviceTypeByService = NetDevice::Printer; deviceName = service->serviceName(); } if( deviceTypeByService != NetDevice::Unknown ) { if( deviceTypeByService > d->type() ) { d->setType( deviceTypeByService ); if( ! deviceName.isEmpty() ) d->setName( deviceName ); } } QList<NetService> newServices; newServices.append( netService ); mNetworkPrivate->emitServicesAdded( newServices ); }