void HControlPointPrivate::processDeviceOnline( HDefaultClientDevice* device, bool newDevice) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HControlPoint::DeviceDiscoveryAction actionToTake = q_ptr->acceptRootDevice(device); bool subscribe = false; switch(actionToTake) { case HControlPoint::IgnoreDevice: HLOG_DBG(QString("Discarding device with UDN %1").arg( device->info().udn().toString())); if (newDevice) { delete device; device = 0; } break; case HControlPoint::AddDevice: break; case HControlPoint::AddDevice_SubscribeEventsIfConfigured: subscribe = m_configuration->subscribeToEvents(); break; case HControlPoint::AddDevice_SubscribeAllEvents: subscribe = true; break; default: Q_ASSERT(false); break; }; if (device) { if (newDevice) { if (!addRootDevice(device)) { delete device; return; } } if (subscribe) { m_eventSubscriber->subscribe( device, VisitThisRecursively, m_configuration->desiredSubscriptionTimeout()); } } }
bool HDataRetriever::retrieveIcon( const QUrl& deviceLocation, const QUrl& iconUrl, QByteArray* data) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG(QString( "Attempting to retrieve icon [%1] from: [%2]").arg( iconUrl.toString(), deviceLocation.toString())); return retrieveData(deviceLocation, iconUrl, data); }
bool HControlPointPrivate::addRootDevice(HDefaultClientDevice* newRootDevice) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); Q_ASSERT(thread() == QThread::currentThread()); HDefaultClientDevice* existingDevice = static_cast<HDefaultClientDevice*>( m_deviceStorage.searchDeviceByUdn( newRootDevice->info().udn(), AllDevices)); if (existingDevice) { // it seems that the device we've built has already been added // (it is possible, although unlikely, we begin multiple device build // processes of the same device tree) // in this case we only make sure that the device's location list is // updated if necessary existingDevice = static_cast<HDefaultClientDevice*>(existingDevice->rootDevice()); existingDevice->addLocations(newRootDevice->locations()); return false; } if (q_ptr->acceptRootDevice(newRootDevice) == HControlPoint::IgnoreDevice) { HLOG_DBG(QString("Device [%1] rejected").arg( newRootDevice->info().udn().toString())); return false; } newRootDevice->setParent(this); newRootDevice->startStatusNotifier(HDefaultClientDevice::All); bool ok = connect( newRootDevice, SIGNAL(statusTimeout(HDefaultClientDevice*)), this, SLOT(deviceExpired(HDefaultClientDevice*))); Q_ASSERT(ok); Q_UNUSED(ok) if (!m_deviceStorage.addRootDevice(newRootDevice)) { HLOG_WARN(QString( "Failed to add root device [UDN: %1]: %2").arg( newRootDevice->info().udn().toSimpleUuid(), m_deviceStorage.lastError())); return false; } emit q_ptr->rootDeviceOnline(newRootDevice); return true; }
void HDeviceHostHttpServer::incomingUnsubscriptionRequest( HMessagingInfo* mi, const HUnsubscribeRequest& usreq) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG("Unsubscription received."); bool ok = m_eventNotifier.removeSubscriber(usreq); mi->setKeepAlive(false); m_httpHandler->send( mi, HHttpMessageCreator::createResponse(ok ? Ok : PreconditionFailed, *mi)); }
HCdsObjectData* HCdsFileSystemReaderPrivate::scan( const HRootDir& rdir, const QString& parentId, QList<HCdsObjectData*>* result) { HLOG(H_AT, H_FUN); QDir dir = rdir.dir(); HLOG_DBG(QString("Entering directory %1").arg(dir.absolutePath())); HStorageFolder* folder = new HStorageFolder(dir.dirName(), parentId); QString id = folder->id(); HCdsObjectData* item = new HCdsObjectData(folder, dir.absolutePath()); result->append(item); QSet<QString> childIds; QFileInfoList infoList = dir.entryInfoList(QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot); for(qint32 i = 0; i < infoList.size(); ++i) { QFileInfo finfo = infoList[i]; if (finfo.isDir() && rdir.scanMode() == HRootDir::RecursiveScan) { if (QDir(finfo.absoluteFilePath()) == dir) { continue; } HRootDir subdir(QDir(finfo.absoluteFilePath()), HRootDir::RecursiveScan); HCdsObjectData* child = scan(subdir, id, result); Q_ASSERT(child); childIds.insert(child->object()->id()); continue; } HCdsObjectData* child = indexFile(finfo, id); if (child) { result->append(child); childIds.insert(child->object()->id()); } } folder->setChildIds(childIds); return item; }
bool HDataRetriever::retrieveDeviceDescription( const QUrl& deviceLocation, QString* data) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG(QString( "Attempting to fetch a device description from: [%1]").arg( deviceLocation.toString())); QByteArray tmp; if (!retrieveData(deviceLocation, QUrl(), &tmp)) { return false; } *data = QString::fromUtf8(tmp); return true; }
void HDeviceHostHttpServer::incomingControlRequest( HMessagingInfo* mi, const HInvokeActionRequest& invokeActionRequest) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG(QString("Control message to [%1] received.").arg( invokeActionRequest.soapAction())); QUuid udn = extractUdn(invokeActionRequest.serviceUrl()); HServerDevice* device = !udn.isNull() ? m_deviceStorage.searchDeviceByUdn(HUdn(udn), AllDevices) : 0; HServerService* service = 0; if (!device) { // the request did not have the UDN prefix, which means that either // 1) the request was for a ControlURL that was defined as an absolute URL // in the device description or // 2) the request is invalid service = m_deviceStorage.searchServiceByControlUrl( invokeActionRequest.serviceUrl()); if (!service) { HLOG_WARN(QString( "Ignoring invalid action invocation to: [%1].").arg( invokeActionRequest.serviceUrl().toString())); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( BadRequest, *mi)); return; } } else if (!service) { service = m_deviceStorage.searchServiceByControlUrl( device, extractRequestExludingUdn(invokeActionRequest.serviceUrl())); } if (!service) { HLOG_WARN(QString("Ignoring invalid action invocation to: [%1].").arg( invokeActionRequest.serviceUrl().toString())); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( BadRequest, *mi)); return; } const QtSoapMessage* soapMsg = invokeActionRequest.soapMsg(); const QtSoapType& method = soapMsg->method(); if (!method.isValid()) { HLOG_WARN("Invalid control method."); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( BadRequest, *mi)); return; } HServerAction* action = service->actions().value(method.name().name()); if (!action) { HLOG_WARN(QString("The service has no action named [%1].").arg( method.name().name())); mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, UpnpInvalidArgs, soapMsg->toXmlString())); return; } HActionArguments iargs = action->info().inputArguments(); HActionArguments::iterator it = iargs.begin(); for(; it != iargs.end(); ++it) { HActionArgument iarg = *it; const QtSoapType& arg = method[iarg.name()]; if (!arg.isValid()) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, UpnpInvalidArgs, soapMsg->toXmlString())); return; } if (!iarg.setValue( HUpnpDataTypes::convertToRightVariantType( arg.value().toString(), iarg.dataType()))) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, UpnpInvalidArgs, soapMsg->toXmlString())); return; } } HActionArguments outArgs = action->info().outputArguments(); qint32 retVal = action->invoke(iargs, &outArgs); if (retVal != UpnpSuccess) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse( *mi, retVal, soapMsg->toXmlString())); return; } QtSoapNamespaces::instance().registerNamespace( "u", service->info().serviceType().toString()); QtSoapMessage soapResponse; soapResponse.setMethod(QtSoapQName( QString("%1%2").arg(action->info().name(), "Response"), service->info().serviceType().toString())); foreach(const HActionArgument& oarg, outArgs) { QtSoapType* soapArg = new SoapType(oarg.name(), oarg.dataType(), oarg.value()); soapResponse.addMethodArgument(soapArg); }
void HDeviceHostHttpServer::incomingSubscriptionRequest( HMessagingInfo* mi, const HSubscribeRequest& sreq) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); HLOG_DBG("Subscription received."); QUuid udn = extractUdn(sreq.eventUrl()); HServerDevice* device = !udn.isNull() ? m_deviceStorage.searchDeviceByUdn(HUdn(udn), AllDevices) : 0; HServerService* service = 0; if (!device) { // the request did not have the UDN prefix, which means that either // 1) the request was for a EventUrl that was defined as an absolute URL // in the device description or // 2) the request is invalid service = m_deviceStorage.searchServiceByEventUrl(sreq.eventUrl()); if (!service) { HLOG_WARN(QString( "Ignoring invalid event subscription to: [%1].").arg( sreq.eventUrl().toString())); mi->setKeepAlive(false); m_httpHandler->send( mi, HHttpMessageCreator::createResponse(BadRequest, *mi)); return; } } else if (!service) { service = m_deviceStorage.searchServiceByEventUrl( device, extractRequestExludingUdn(sreq.eventUrl())); } if (!service) { HLOG_WARN(QString("Subscription defined as [%1] is invalid.").arg( sreq.eventUrl().path())); mi->setKeepAlive(false); m_httpHandler->send( mi, HHttpMessageCreator::createResponse(BadRequest, *mi)); return; } // The UDA v1.1 does not specify what to do when a subscription is received // to a service that is not evented. A "safe" route was taken here and // all subscriptions are accepted rather than returning some error. However, // in such a case the timeout is adjusted to a day and no events are ever sent. HSid sid; StatusCode sc; if (sreq.isRenewal()) { sc = m_eventNotifier.renewSubscription(sreq, &sid); } else { sc = m_eventNotifier.addSubscriber(service, sreq, &sid); } if (sc != Ok) { mi->setKeepAlive(false); m_httpHandler->send(mi, HHttpMessageCreator::createResponse(sc, *mi)); return; } HServiceEventSubscriber* subscriber = m_eventNotifier.remoteClient(sid); HSubscribeResponse response( subscriber->sid(), HSysInfo::instance().herqqProductTokens(), subscriber->timeout()); HHttpAsyncOperation* op = m_httpHandler->send(mi, HHttpMessageCreator::create(response, *mi)); if (op) { HOpInfo opInfo(service, sreq, subscriber); m_ops.append(qMakePair(QPointer<HHttpAsyncOperation>(op), opInfo)); } }
bool HControlPointPrivate::processDeviceDiscovery( const Msg& msg, const HEndpoint& source, HControlPointSsdpHandler*) { HLOG2(H_AT, H_FUN, m_loggingIdentifier); const HUdn& resourceUdn = msg.usn().udn(); HDefaultClientDevice* device = static_cast<HDefaultClientDevice*>( m_deviceStorage.searchDeviceByUdn(msg.usn().udn(), AllDevices)); if (device) { // according to the UDA v1.1 spec, if a control point receives an // alive announcement of any type for a device tree, the control point // can assume that all devices and services are available. // ==> reset timeouts for entire device tree and all services. device = static_cast<HDefaultClientDevice*>(device->rootDevice()); device->startStatusNotifier(HDefaultClientDevice::All); // it cannot be that only some embedded device is available at certain // interface, since the device description is always fetched from the // the location that the root device specifies ==> the entire device // tree has to be available at that location. if (device->addLocation(msg.location())) { HLOG_DBG(QString("Existing device [%1] now available at [%2]").arg( resourceUdn.toString(), msg.location().toString())); } if (!device->deviceStatus()->online()) { device->deviceStatus()->setOnline(true); emit q_ptr->rootDeviceOnline(device); processDeviceOnline(device, false); } return true; } // it does not matter if the device is an embedded device, since the // location of the device always points to the root device's description // and the internal device model is built of that. Hence, any advertisement // will do to build the entire model correctly. DeviceBuildTask* dbp = m_deviceBuildTasks.get(msg); if (dbp) { if (!dbp->m_locations.contains(msg.location())) { dbp->m_locations.push_back(msg.location()); } return true; } if (!q_ptr->acceptResource(msg.usn(), source)) { HLOG_DBG(QString("Resource advertisement [%1] rejected").arg( msg.usn().toString())); return true; } DeviceBuildTask* newBuildTask = new DeviceBuildTask(this, msg); newBuildTask->setAutoDelete(false); m_deviceBuildTasks.add(newBuildTask); bool ok = connect( newBuildTask, SIGNAL(done(Herqq::Upnp::HUdn)), this, SLOT(deviceModelBuildDone(Herqq::Upnp::HUdn))); Q_ASSERT(ok); Q_UNUSED(ok) HLOG_INFO(QString( "New resource [%1] is available @ [%2]. " "Attempting to build the device model.").arg( msg.usn().toString(), msg.location().toString())); m_threadPool->start(newBuildTask); return true; }