Beispiel #1
0
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);
}
Beispiel #3
0
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));
    }
}
Beispiel #9
0
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;
}