コード例 #1
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
void HControlPointPrivate::deviceModelBuildDone(const Herqq::Upnp::HUdn& udn)
{
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);

    DeviceBuildTask* build = m_deviceBuildTasks.get(udn);
    Q_ASSERT(build);

    if (m_state == Initialized)
    {
        // The check is done because it is possible that a user has called
        // HControlPoint::quit() before this event is delivered.
        if (build->completionValue() == 0)
        {
            HLOG_INFO(QString("Device model for [%1] built successfully.").arg(
                          udn.toString()));

            HDefaultClientDevice* device = build->createdDevice();
            Q_ASSERT(device);

            for (qint32 i = 0; i < build->m_locations.size(); ++i)
            {
                device->addLocation(build->m_locations[i]);
            }

            processDeviceOnline(device, true);
        }
        else
        {
            HLOG_WARN(QString("Device model for [%1] could not be built: %2.").arg(
                          udn.toString(), build->errorString()));
        }
    }

    m_deviceBuildTasks.remove(udn);
}
コード例 #2
0
qint32 HServerAction::invoke(
    const HActionArguments& inArgs, HActionArguments* outArgs)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);
    *outArgs = h_ptr->m_info->outputArguments();
    return h_ptr->m_actionInvoke(inArgs, outArgs);
}
コード例 #3
0
qint32 HRenderingControlService::getVolumeDB(
    quint32 instanceId, const HChannel& channel, qint16* currentVolumeDb)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    bool ok = false;

    *currentVolumeDb =
        mediaConnection->rendererConnectionInfo()->volumeDb(channel, &ok);

    if (!ok)
    {
        return HRenderingControlInfo::InvalidChannel;
    }

    return UpnpSuccess;
}
コード例 #4
0
qint32 HRenderingControlService::getLoudness(
    quint32 instanceId, const HChannel& channel, bool* loudnessOn)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    bool ok = false;

    *loudnessOn =
        mediaConnection->rendererConnectionInfo()->loudnessEnabled(channel, &ok);

    if (!ok)
    {
        return HRenderingControlInfo::InvalidChannel;
    }

    return UpnpSuccess;
}
コード例 #5
0
void DeviceBuildTask::run()
{
    HLOG2(H_AT, H_FUN, m_owner->m_loggingIdentifier);

    QString err;
    QScopedPointer<HDefaultClientDevice> device;
    device.reset(
        m_owner->buildDevice(m_locations[0], m_cacheControlMaxAge, &err));
    // the returned device is a fully built root device containing every
    // embedded device and service advertised in the device and service descriptions
    // otherwise, the creation failed
    if (!device.data())
    {
        HLOG_WARN(QString("Couldn't create a device: %1").arg(err));

        m_completionValue = -1;
        m_errorString = err;
    }
    else
    {
        device->moveToThread(m_owner->thread());

        m_completionValue = 0;
        m_createdDevice.swap(device);
    }

    emit done(m_udn);
}
コード例 #6
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
void HControlPoint::setError(ControlPointError error, const QString& errorStr)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    h_ptr->m_lastError = error;
    h_ptr->m_lastErrorDescription = errorStr;
}
コード例 #7
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
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());
        }
    }
}
コード例 #8
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
HControlPoint::HControlPoint(
    const HControlPointConfiguration& configuration, QObject* parent) :
    QObject(parent), h_ptr(new HControlPointPrivate())
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    h_ptr->m_configuration.reset(configuration.clone());

    h_ptr->setParent(this);
    h_ptr->q_ptr = this;
}
コード例 #9
0
void HDataRetriever::timerEvent(QTimerEvent* event)
{
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);

    HLOG_WARN(QString("Request timed out."));

    quit();
    killTimer(event->timerId());

    m_success = false;
}
コード例 #10
0
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);
}
コード例 #11
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
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;
}
コード例 #12
0
/*******************************************************************************
 * DeviceBuildTask
 ******************************************************************************/
DeviceBuildTask::~DeviceBuildTask()
{
    HLOG2(H_AT, H_FUN, m_owner->m_loggingIdentifier);

    if (m_createdDevice.data())
    {
        m_createdDevice->deleteLater();
    }

    m_createdDevice.take();
}
コード例 #13
0
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));
}
コード例 #14
0
HDeviceHostHttpServer::~HDeviceHostHttpServer()
{
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);

    QList<QPair<QPointer<HHttpAsyncOperation>, HOpInfo> >::iterator it = m_ops.begin();
    for(; it != m_ops.end(); ++it)
    {
        if (it->first)
        {
            it->first->deleteLater();
        }
    }
}
コード例 #15
0
qint32 HRenderingControlService::setLoudness(
    quint32 instanceId, const HChannel& channel, bool loudnessOn)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    return mediaConnection->setLoudness(channel, loudnessOn);
}
コード例 #16
0
qint32 HRenderingControlService::setVolumeDB(
    quint32 instanceId, const HChannel& channel, qint16 desiredVolumeDb)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    return mediaConnection->setVolumeDb(channel, desiredVolumeDb);
}
コード例 #17
0
qint32 HRenderingControlService::setVerticalKeystone(
    quint32 instanceId, qint16 desiredVerticalKeyStone)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    return mediaConnection->setVerticalKeystone(desiredVerticalKeyStone);
}
コード例 #18
0
qint32 HRenderingControlService::setColorTemperature(
    quint32 instanceId, quint16 desiredColorTemperature)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    return mediaConnection->setRcsValue(
        HRendererConnectionInfo::ColorTemperature, desiredColorTemperature);
}
コード例 #19
0
qint32 HRenderingControlService::setBlueVideoBlackLevel(
    quint32 instanceId, quint16 desiredBlueVideoBlackLevel)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    return mediaConnection->setRcsValue(
        HRendererConnectionInfo::BlueVideoBlackLevel, desiredBlueVideoBlackLevel);
}
コード例 #20
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
bool HControlPointPrivate::processDeviceOffline(
    const HResourceUnavailable& msg, const HEndpoint& /*source*/,
    HControlPointSsdpHandler* /*origin*/)
{
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);
    Q_ASSERT(thread() == QThread::currentThread());

    HDefaultClientDevice* device =
        static_cast<HDefaultClientDevice*>(
            m_deviceStorage.searchDeviceByUdn(msg.usn().udn(), AllDevices));

    if (!device)
    {
        // the device is not known by us.
        // note that even service announcements contain the "UDN", which identifies
        // the device that contains them.
        return true;
    }

    if (device->deviceStatus()->online())
    {

        HLOG_INFO(QString("Resource [%1] is unavailable.").arg(
                      msg.usn().resourceType().toString()));

        // according to the UDA v1.1 specification, if a bye bye message of any kind
        // is received, the control point can assume that nothing in that
        // device tree is available anymore

        HDefaultClientDevice* root =
            static_cast<HDefaultClientDevice*>(device->rootDevice());

        Q_ASSERT(root);

        root->deviceStatus()->setOnline(false);

        m_eventSubscriber->remove(root, true);

        root->clearLocations();
        root->stopStatusNotifier(HDefaultClientDevice::All);

        emit q_ptr->rootDeviceOffline(root);
    }

    return true;
}
コード例 #21
0
qint32 HRenderingControlService::getColorTemperature(
    quint32 instanceId, quint16* currentColorTemperature)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    *currentColorTemperature =
        mediaConnection->rendererConnectionInfo()->rcsValue(HRendererConnectionInfo::ColorTemperature);

    return UpnpSuccess;
}
コード例 #22
0
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;
}
コード例 #23
0
qint32 HRenderingControlService::getVerticalKeystone(
    quint32 instanceId, qint16* currentVerticalKeyStone)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    *currentVerticalKeyStone =
        mediaConnection->rendererConnectionInfo()->verticalKeystone();

    return UpnpSuccess;
}
コード例 #24
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
/*******************************************************************************
 * HControlPoint
 ******************************************************************************/
HControlPoint::HControlPoint(QObject* parent) :
    QObject(parent), h_ptr(new HControlPointPrivate())
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    h_ptr->m_configuration.reset(new HControlPointConfiguration());

    h_ptr->setParent(this);
    h_ptr->q_ptr = this;

    bool ok = connect(
                  h_ptr->m_nam,
                  SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
                  this,
                  SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)));

    Q_ASSERT(ok);
    Q_UNUSED(ok)
}
コード例 #25
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
void HControlPointPrivate::deviceExpired(HDefaultClientDevice* source)
{
    HLOG2(H_AT, H_FUN, m_loggingIdentifier);
    Q_ASSERT(thread() == QThread::currentThread());

    // according to the UDA v1.1 a "device tree" (root, embedded and services)
    // are "timed out" only when every advertisement has timed out.

    source = static_cast<HDefaultClientDevice*>(source->rootDevice());

    if (source->isTimedout(HDefaultClientDevice::All))
    {
        source->deviceStatus()->setOnline(false);
        m_eventSubscriber->cancel(
            source, VisitThisRecursively, false);

        emit q_ptr->rootDeviceOffline(source);
    }
}
コード例 #26
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
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;
}
コード例 #27
0
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);
    }
コード例 #28
0
ファイル: hcontrolpoint.cpp プロジェクト: nholmgaard/nomacs
bool HControlPoint::init()
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    Q_ASSERT_X(
        thread() == QThread::currentThread(), H_AT,
        "The control point has to be initialized in the thread in which it is "
        "currently located.");

    if (h_ptr->m_state == HControlPointPrivate::Initialized)
    {
        setError(
            AlreadyInitializedError,
            "The control point is already initialized");

        return false;
    }

    Q_ASSERT(h_ptr->m_state == HControlPointPrivate::Uninitialized);

    bool ok = true;
    const QList<QHostAddress> addrs =
        h_ptr->m_configuration->networkAddressesToUse();

    h_ptr->m_state = HControlPointPrivate::Initializing;

    HLOG_INFO("ControlPoint initializing.");

    h_ptr->m_eventSubscriber = new HEventSubscriptionManager(h_ptr);

    ok = connect(
             h_ptr->m_eventSubscriber,
             SIGNAL(subscribed(Herqq::Upnp::HClientService*)),
             this,
             SIGNAL(subscriptionSucceeded(Herqq::Upnp::HClientService*)));

    ok = connect(
             h_ptr->m_eventSubscriber,
             SIGNAL(subscriptionFailed(Herqq::Upnp::HClientService*)),
             this,
             SIGNAL(subscriptionFailed(Herqq::Upnp::HClientService*)));

    Q_ASSERT(ok);

    ok = connect(
             h_ptr->m_eventSubscriber,
             SIGNAL(unsubscribed(Herqq::Upnp::HClientService*)),
             h_ptr,
             SLOT(unsubscribed(Herqq::Upnp::HClientService*)));

    Q_ASSERT(ok);

    h_ptr->m_server = new ControlPointHttpServer(h_ptr);

    if (!doInit())
    {
        // it is assumed that the derived class filled the error and
        // error description
        ok = false;
        goto end;
    }

    if (!h_ptr->m_server->init(convertHostAddressesToEndpoints(addrs)))
    {
        setError(CommunicationsError, "Failed to start HTTP server");
        ok = false;
        goto end;
    }

    foreach(const QHostAddress& ha, addrs)
    {
        quint32 netwAddr;
        ok = HSysInfo::instance().localNetwork(ha, &netwAddr);
        Q_ASSERT(ok);

        HControlPointSsdpHandler* ssdp = new HControlPointSsdpHandler(h_ptr);
        if (!ssdp->init(ha))
        {
            delete ssdp;
            setError(CommunicationsError, "Failed to start SSDP");
            ok = false;
            goto end;
        }
        h_ptr->m_ssdps.append(qMakePair(netwAddr, ssdp));
    }
コード例 #29
0
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));
    }
}
コード例 #30
0
qint32 HRenderingControlService::getStateVariables(
    quint32 instanceId, const QSet<QString>& stateVariableNames,
    QString* stateVariableValuePairs)
{
    HLOG2(H_AT, H_FUN, h_ptr->m_loggingIdentifier);

    Q_ASSERT(stateVariableValuePairs);

    HRendererConnection* mediaConnection =
        m_owner->findConnectionByRcsId(instanceId);

    if (!mediaConnection)
    {
        return HRenderingControlInfo::InvalidInstanceId;
    }

    QString retVal;
    QXmlStreamWriter writer(&retVal);

    writer.setCodec("UTF-8");
    writer.writeStartDocument();
    writer.writeStartElement("stateVariableValuePairs");
    writer.writeDefaultNamespace("urn:schemas-upnp-org:av:avs");
    writer.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    writer.writeAttribute("xsi:schemaLocation",
        "urn:schemas-upnp-org:av:avs" \
        "http://www.upnp.org/schemas/av/avs.xsd");

    QSet<QString> stateVarNames;
    if (stateVariableNames.contains("*"))
    {
        stateVarNames = HRenderingControlInfo::stateVariablesSetupData().names();
        QSet<QString>::iterator it = stateVarNames.begin();
        for(; it != stateVarNames.end();)
        {
            if (it->startsWith("A_ARG") || *it == "LastChange" ||
                *it == "PresetNameList")
            {
                it = stateVarNames.erase(it);
            }
            else
            {
                ++it;
            }
        }
    }
    else
    {
        stateVarNames = stateVariableNames;
    }

    foreach(QString svName, stateVarNames)
    {
        bool ok = false;
        svName = svName.trimmed();

        if (HRendererConnectionInfo::hasChannelAssociated(svName))
        {
            foreach(const HChannel& ch, HChannel::allChannels())
            {
                QString value = mediaConnection->value(svName, ch, &ok);
                if (ok && !value.isEmpty())
                {
                    writer.writeStartElement("stateVariable");
                    writer.writeAttribute("variableName", svName);
                    writer.writeAttribute("channel", ch.toString());
                    writer.writeCharacters(value);
                    writer.writeEndElement();
                }
            }
        }