/*! \internal Constructs a QDBusMessage by parsing the given DBusMessage object. */ QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities) { QDBusMessage message; if (!dmsg) return message; message.d_ptr->type = q_dbus_message_get_type(dmsg); message.d_ptr->path = QString::fromUtf8(q_dbus_message_get_path(dmsg)); message.d_ptr->interface = QString::fromUtf8(q_dbus_message_get_interface(dmsg)); message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ? QString::fromUtf8(q_dbus_message_get_error_name(dmsg)) : QString::fromUtf8(q_dbus_message_get_member(dmsg)); message.d_ptr->service = QString::fromUtf8(q_dbus_message_get_sender(dmsg)); message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg)); message.d_ptr->msg = q_dbus_message_ref(dmsg); QDBusDemarshaller demarshaller(capabilities); demarshaller.message = q_dbus_message_ref(dmsg); if (q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator)) while (!demarshaller.atEnd()) message << demarshaller.toVariantInternal(); return message; }
bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) { int id = arg.userType(); if (id == QVariant::Invalid) { qWarning("QDBusMarshaller: cannot add an invalid QVariant"); error(QLatin1String("Variant containing QVariant::Invalid passed in arguments")); return false; } // intercept QDBusArgument parameters here if (id == QDBusMetaTypeId::argument()) { QDBusArgument dbusargument = qvariant_cast<QDBusArgument>(arg); QDBusArgumentPrivate *d = QDBusArgumentPrivate::d(dbusargument); if (!d->message) return false; // can't append this one... QDBusDemarshaller demarshaller(capabilities); demarshaller.message = q_dbus_message_ref(d->message); if (d->direction == Demarshalling) { // it's demarshalling; just copy demarshaller.iterator = static_cast<QDBusDemarshaller *>(d)->iterator; } else { // it's marshalling; start over if (!q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator)) return false; // error! } return appendCrossMarshalling(&demarshaller); } const char *signature = QDBusMetaType::typeToSignature( QVariant::Type(id) ); if (!signature) { qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " "Use qDBusRegisterMetaType to register it", QMetaType::typeName(id), id); error(QString::fromLatin1("Unregistered type %1 passed in arguments") .arg(QLatin1String(QMetaType::typeName(id)))); return false; } switch (*signature) { #ifdef __OPTIMIZE__ case DBUS_TYPE_BYTE: case DBUS_TYPE_INT16: case DBUS_TYPE_UINT16: case DBUS_TYPE_INT32: case DBUS_TYPE_UINT32: case DBUS_TYPE_INT64: case DBUS_TYPE_UINT64: case DBUS_TYPE_DOUBLE: qIterAppend(&iterator, ba, *signature, arg.constData()); return true; case DBUS_TYPE_BOOLEAN: append( arg.toBool() ); return true; #else case DBUS_TYPE_BYTE: append( qvariant_cast<uchar>(arg) ); return true; case DBUS_TYPE_BOOLEAN: append( arg.toBool() ); return true; case DBUS_TYPE_INT16: append( qvariant_cast<short>(arg) ); return true; case DBUS_TYPE_UINT16: append( qvariant_cast<ushort>(arg) ); return true; case DBUS_TYPE_INT32: append( static_cast<dbus_int32_t>(arg.toInt()) ); return true; case DBUS_TYPE_UINT32: append( static_cast<dbus_uint32_t>(arg.toUInt()) ); return true; case DBUS_TYPE_INT64: append( arg.toLongLong() ); return true; case DBUS_TYPE_UINT64: append( arg.toULongLong() ); return true; case DBUS_TYPE_DOUBLE: append( arg.toDouble() ); return true; #endif case DBUS_TYPE_STRING: append( arg.toString() ); return true; case DBUS_TYPE_OBJECT_PATH: append( qvariant_cast<QDBusObjectPath>(arg) ); return true; case DBUS_TYPE_SIGNATURE: append( qvariant_cast<QDBusSignature>(arg) ); return true; // compound types: case DBUS_TYPE_VARIANT: // nested QVariant return append( qvariant_cast<QDBusVariant>(arg) ); case DBUS_TYPE_ARRAY: // could be many things // find out what kind of array it is switch (arg.type()) { case QVariant::StringList: append( arg.toStringList() ); return true; case QVariant::ByteArray: append( arg.toByteArray() ); return true; default: ; } Q_FALLTHROUGH(); case DBUS_TYPE_STRUCT: case DBUS_STRUCT_BEGIN_CHAR: return appendRegisteredType( arg ); case DBUS_TYPE_DICT_ENTRY: case DBUS_DICT_ENTRY_BEGIN_CHAR: qFatal("QDBusMarshaller::appendVariantInternal got a DICT_ENTRY!"); return false; case DBUS_TYPE_UNIX_FD: if (capabilities & QDBusConnection::UnixFileDescriptorPassing || ba) { append(qvariant_cast<QDBusUnixFileDescriptor>(arg)); return true; } Q_FALLTHROUGH(); default: qWarning("QDBusMarshaller::appendVariantInternal: Found unknown D-BUS type '%s'", signature); return false; } return true; }
int Demarshal( int byte_order, const cMarshalType *type, void *d, const void *b ) { if ( IsSimpleType( type->m_type ) ) { return DemarshalSimpleTypes( byte_order, type->m_type, d, b ); } int size = 0; unsigned char *data = d; const unsigned char *buffer = b; switch( type->m_type ) { case eMtArray: { const size_t nelems = type->u.m_array.m_nelements; size_t i; for( i = 0; i < nelems; i++ ) { const cMarshalType *elem = type->u.m_array.m_element; const size_t elem_sizeof = type->u.m_array.m_element_sizeof; int cc = Demarshal( byte_order, elem, data, buffer ); if ( cc < 0 ) { CRIT( "Demarshal: %s[%d]: failure, cc = %d!", type->m_name, i, cc ); return cc; } data += elem_sizeof; buffer += cc; size += cc; } } break; case eMtStruct: { const cMarshalType *elems = &type->u.m_struct.m_elements[0]; size_t i; for( i = 0; elems[i].m_type == eMtStructElement; i++ ) { const cMarshalType *elem = elems[i].u.m_struct_element.m_element; const size_t offset = elems[i].u.m_struct_element.m_offset; int cc = 0; if ( elem->m_type == eMtUnion ) { const size_t mod2_idx = elem->u.m_union.m_mod_idx; if ( mod2_idx >= i ) { // NB: this is a limitation of demarshaling of unions CRIT( "Demarshal: %s:%s: mod field must be before union!", type->m_name, elems[i].m_name ); return -EINVAL; } const size_t mod2 = GetStructElementIntegerValue( type, mod2_idx, data ); const cMarshalType *elem2 = GetUnionElement( elem, mod2 ); if ( !elem2 ) { CRIT( "Demarshal: %s:%s: invalid mod value %u!", type->m_name, elems[i].m_name, (unsigned int)mod2 ); return -EINVAL; } cc = Demarshal( byte_order, elem2, data + offset, buffer ); if ( cc < 0 ) { CRIT( "Demarshal: %s:%s, mod %u: failure, cc = %d!", type->m_name, elems[i].m_name, (unsigned int)mod2, cc ); return cc; } } else if ( elem->m_type == eMtVarArray ) { const size_t nelems2_idx = elem->u.m_var_array.m_nelements_idx; const cMarshalType *elem2 = elem->u.m_var_array.m_element; const size_t elem2_sizeof = elem->u.m_var_array.m_element_sizeof; if ( nelems2_idx >= i ) { // NB: this is a limitation of demarshaling of var arrays CRIT( "Demarshal: %s:%s: nelements field must be before vararray!", type->m_name, elems[i].m_name ); return -EINVAL; } const size_t nelems2 = GetStructElementIntegerValue( type, nelems2_idx, data ); // allocate storage for var array content unsigned char *data2 = g_new0(unsigned char, nelems2 * elem2_sizeof ); // (data + offset ) points to pointer to var array content memcpy(data + offset, &data2, sizeof(void *)); const unsigned char *buffer2 = buffer; size_t i2; for( i2 = 0; i2 < nelems2; i2++ ) { int cc2 = Demarshal( byte_order, elem2, data2, buffer2 ); if ( cc2 < 0 ) { CRIT( "Demarshal: %s:%s[%d]: failure, cc = %d!", type->m_name, elems[i].m_name, i2, cc2 ); return cc2; } data2 += elem2_sizeof; buffer2 += cc2; cc += cc2; } } else { cc = Demarshal( byte_order, elem, data + offset, buffer ); if ( cc < 0 ) { CRIT( "Demarshal: %s:%s: failure, cc = %d!", type->m_name, elems[i].m_name, cc ); return cc; } } buffer += cc; size += cc; } } break; case eMtUserDefined: { tDemarshalFunction demarshaller = type->u.m_user_defined.m_demarshaller; void * user_data = type->u.m_user_defined.m_user_data; size = demarshaller ? demarshaller( byte_order, type, d, b, user_data ) : 0; } break; default: return -ENOSYS; }