/*! \class TorcHTTPService * * \todo Support for complex parameter types via RPC (e.g. array etc). * \todo ProcessRequest implicitly assumes JSON-RPC (though applies to much of the RPC code). */ TorcHTTPService::TorcHTTPService(QObject *Parent, const QString &Signature, const QString &Name, const QMetaObject &MetaObject, const QString &Blacklist) : TorcHTTPHandler(SERVICES_DIRECTORY + Signature, Name), m_parent(Parent), m_version("Unknown"), m_metaObject(MetaObject), m_subscriberLock(new QMutex(QMutex::Recursive)) { QStringList blacklist = Blacklist.split(","); m_parent->setObjectName(Name); // the parent MUST implement SubscriberDeleted. if (MetaObject.indexOfSlot(QMetaObject::normalizedSignature("SubscriberDeleted(QObject*)")) < 0) { LOG(VB_GENERAL, LOG_ERR, QString("Service '%1' disabled - no SubscriberDeleted slot").arg(Name)); return; } // determine version int index = MetaObject.indexOfClassInfo("Version"); if (index > -1) m_version = MetaObject.classInfo(index).value(); else LOG(VB_GENERAL, LOG_WARNING, QString("Service '%1' is missing version information").arg(Name)); // analyse available methods for (int i = 0; i < m_metaObject.methodCount(); ++i) { QMetaMethod method = m_metaObject.method(i); if ((method.methodType() == QMetaMethod::Slot) && (method.access() == QMetaMethod::Public)) { QString name(method.methodSignature()); name = name.section('(', 0, 0); // discard unwanted slots if (name == "deleteLater" || name == "SubscriberDeleted" || blacklist.contains(name)) continue; // any Q_CLASSINFO for this method? // current 'schema' allows specification of allowed HTTP methods (PUT, GET etc) // and custom return types, which are used to improve the usability of maps and // lists when returned via XML, JSON, PLIST etc QString returntype; int customallowed = HTTPUnknownType; int index = m_metaObject.indexOfClassInfo(name.toLatin1()); if (index > -1) { QStringList infos = QString(m_metaObject.classInfo(index).value()).split(",", QString::SkipEmptyParts); foreach (QString info, infos) { if (info.startsWith("methods=")) customallowed = TorcHTTPRequest::StringToAllowed(info.mid(8)); else if (info.startsWith("type=")) returntype = info.mid(5); } } // determine allowed request types int allowed = HTTPOptions; if (customallowed != HTTPUnknownType) { allowed |= customallowed; } else if (name.startsWith("Get", Qt::CaseInsensitive)) { allowed += HTTPGet | HTTPHead; } else if (name.startsWith("Set", Qt::CaseInsensitive)) { // TODO Put or Post?? How to handle head requests for setters... allowed += HTTPPut; } else { LOG(VB_GENERAL, LOG_ERR, QString("Unable to determine request types of method '%1' for '%2' - ignoring").arg(name).arg(m_name)); continue; } MethodParameters *parameters = new MethodParameters(i, method, allowed, returntype); if (parameters->m_valid) m_methods.insert(name, parameters); else delete parameters; }