/* * SPDX-License-Identifier: LicenseRef-Unisoc-General-1.0 * Copyright 2016-2023 Unisoc (Shanghai) Technologies Co., Ltd * Licensed under the Unisoc General Software License, version 1.0 (the License); * you may not use this file except in compliance with the License. You may obtain a copy of the License at * https://www.unisoc.com/en_us/license/UNISOC_GENERAL_LICENSE_V1.0-EN_US * Software distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * See the Unisoc General Software License, version 1.0 for more details. */ #include #include #include #include "InternalError.h" #include "MessageInternal.h" #include "Debug.h" using namespace UDBus; static bool isBasicType(int typeCode) { switch (typeCode) { case DBUS_TYPE_DOUBLE: case DBUS_TYPE_UINT64: case DBUS_TYPE_INT64: case DBUS_TYPE_UINT32: case DBUS_TYPE_INT32: case DBUS_TYPE_UINT16: case DBUS_TYPE_INT16: case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: case DBUS_TYPE_UNIX_FD: case DBUS_TYPE_BYTE: case DBUS_TYPE_SIGNATURE: case DBUS_TYPE_BOOLEAN: return true; default: return false; } } MessageIter::MessageIter() : mPrivate(new UDBusPrivate), mMsg(nullptr) {} MessageIter::MessageIter(Message &msg) : mPrivate(new UDBusPrivate), mMsg(&msg) {} MessageIter::MessageIter(const MessageIter &iter) : mPrivate(new UDBusPrivate(*iter.mPrivate)), mMsg(iter.mMsg) {} MessageIter::~MessageIter() { delete mPrivate; mPrivate = nullptr; mMsg = nullptr; } MessageIter &MessageIter::operator =(const MessageIter &iter) { if (this != &iter) { *mPrivate = *iter.mPrivate; mMsg = iter.mMsg; } return *this; } bool MessageIter::AppendBasic(int type_id, void *value) { return dbus_message_iter_append_basic(&mPrivate->iter, type_id, value); } bool MessageIter::AppendFd(int fd) { return AppendBasic(DBUS_TYPE_UNIX_FD, &fd); } bool MessageIter::AppendSignature(const char *chars) { return AppendBasic(DBUS_TYPE_SIGNATURE, &chars); } bool MessageIter::AppendPath(const char *chars) { return AppendBasic(DBUS_TYPE_OBJECT_PATH, &chars); } bool MessageIter::AppendArray(char type, const void *ptr, size_t length) { return dbus_message_iter_append_fixed_array(&mPrivate->iter, type, &ptr, length); } bool MessageIter::AppendByte(unsigned char b) { return AppendBasic(DBUS_TYPE_BYTE, &b); } bool MessageIter::AppendDouble(double d) { return AppendBasic(DBUS_TYPE_DOUBLE, &d); } bool MessageIter::AppendUint64(unsigned long long u) { return AppendBasic(DBUS_TYPE_UINT64, &u); } bool MessageIter::AppendInt64(signed long long i) { return AppendBasic(DBUS_TYPE_INT64, &i); } bool MessageIter::AppendUint32(unsigned int u) { return AppendBasic(DBUS_TYPE_UINT32, &u); } bool MessageIter::AppendInt32(signed int i) { return AppendBasic(DBUS_TYPE_INT32, &i); } bool MessageIter::AppendUint16(unsigned short u) { return AppendBasic(DBUS_TYPE_UINT16, &u); } bool MessageIter::AppendInt16(signed short i) { return AppendBasic(DBUS_TYPE_INT16, &i); } bool MessageIter::AppendString(const char *chars) { return AppendBasic(DBUS_TYPE_STRING, &chars); } bool MessageIter::AppendBool(bool b) { dbus_bool_t db = b ? TRUE : FALSE; return AppendBasic(DBUS_TYPE_BOOLEAN, &db); } signed short MessageIter::GetInt16() { signed short i; GetBasic(DBUS_TYPE_INT16, &i); return i; } unsigned short MessageIter::GetUint16() { unsigned short u; GetBasic(DBUS_TYPE_UINT16, &u); return u; } signed int MessageIter::GetInt32() { signed int i; GetBasic(DBUS_TYPE_INT32, &i); return i; } unsigned int MessageIter::GetUint32() { unsigned int u; GetBasic(DBUS_TYPE_UINT32, &u); return u; } unsigned long long MessageIter::GetUint64() { unsigned long long u; GetBasic(DBUS_TYPE_UINT64, &u); return u; } signed long long MessageIter::GetInt64() { signed long long i; GetBasic(DBUS_TYPE_INT64, &i); return i; } double MessageIter::GetDouble() { double d; GetBasic(DBUS_TYPE_DOUBLE, &d); return d; } void MessageIter::GetBasic(int type_id, void *ptr) { if (Type() != type_id) throw ErrorInvalidArgs("type mismatch"); dbus_message_iter_get_basic(&mPrivate->iter, ptr); } unsigned char MessageIter::GetByte() { unsigned char b; GetBasic(DBUS_TYPE_BYTE, &b); return b; } bool MessageIter::GetBool() { dbus_bool_t db; GetBasic(DBUS_TYPE_BOOLEAN, &db); return db ? true : false; } const char *MessageIter::GetString() { char *chars; GetBasic(DBUS_TYPE_STRING, &chars); return chars; } const char *MessageIter::GetPath() { char *path; GetBasic(DBUS_TYPE_OBJECT_PATH, &path); return path; } const char *MessageIter::GetSignature() { char *signature; GetBasic(DBUS_TYPE_SIGNATURE, &signature); return signature; } int MessageIter::GetFd() { int fd; GetBasic(DBUS_TYPE_UNIX_FD, &fd); return fd; } int MessageIter::GetArray(void *ptr) { int length = 0; dbus_message_iter_get_fixed_array(&mPrivate->iter, ptr, &length); return length; } bool MessageIter::AtEnd() { return Type() == DBUS_TYPE_INVALID; } bool MessageIter::HasNext() { return dbus_message_iter_has_next(&mPrivate->iter); } char *MessageIter::Signature() const { return dbus_message_iter_get_signature(&mPrivate->iter); } int MessageIter::ArrayType() { return dbus_message_iter_get_element_type(&mPrivate->iter); } bool MessageIter::IsDict() { return IsArray() && dbus_message_iter_get_element_type(&mPrivate->iter) == DBUS_TYPE_DICT_ENTRY; } bool MessageIter::IsArray() { return dbus_message_iter_get_arg_type(&mPrivate->iter) == DBUS_TYPE_ARRAY; } int MessageIter::Type() { return dbus_message_iter_get_arg_type(&mPrivate->iter); } MessageIter MessageIter::CreateVariant(const char *sig) { MessageIter var(Msg()); dbus_message_iter_open_container( &mPrivate->iter, DBUS_TYPE_VARIANT, sig, &var.mPrivate->iter ); return var; } MessageIter MessageIter::CreateArray(const char *sig) { MessageIter arr(Msg()); dbus_message_iter_open_container( &mPrivate->iter, DBUS_TYPE_ARRAY, sig, &arr.mPrivate->iter ); return arr; } MessageIter MessageIter::CreateDictEntry() { MessageIter ent(Msg()); dbus_message_iter_open_container( &mPrivate->iter, DBUS_TYPE_DICT_ENTRY, nullptr, &ent.mPrivate->iter ); return ent; } MessageIter MessageIter::CreateStruct() { MessageIter stu(Msg()); dbus_message_iter_open_container( &mPrivate->iter, DBUS_TYPE_STRUCT, nullptr, &stu.mPrivate->iter ); return stu; } MessageIter MessageIter::Recurse() { MessageIter iter(Msg()); dbus_message_iter_recurse(&mPrivate->iter, &iter.mPrivate->iter); return iter; } void MessageIter::CloseContainer(MessageIter &container) { dbus_message_iter_close_container(&mPrivate->iter, &container.mPrivate->iter); } void MessageIter::CopyData(MessageIter &dest) { for (MessageIter &orig = *this; !orig.AtEnd(); ++orig) { if (isBasicType(orig.Type())) { unsigned char variant[8]; orig.GetBasic(orig.Type(), &variant); dest.AppendBasic(orig.Type(), &variant); } else { MessageIter dest_container (dest.Msg()); MessageIter orig_container = orig.Recurse(); char *signature = orig_container.Signature(); dbus_message_iter_open_container( &dest.mPrivate->iter, orig.Type(), orig.Type() == DBUS_TYPE_DICT_ENTRY || orig.Type() == DBUS_TYPE_STRUCT ? nullptr: signature, &dest_container.mPrivate->iter); orig_container.CopyData(dest_container); dest.CloseContainer(dest_container); free(signature); } } } MessageIter MessageIter::operator ++(int) { MessageIter copy(*this); ++(*this); return copy; } MessageIter &MessageIter::operator ++() { dbus_message_iter_next(&mPrivate->iter); return (*this); } /* */ Message::Message() : mPrivate(new UDBusPrivate) { isSync = true; } Message::Message(Message::UDBusPrivate *p, bool incref) : mPrivate(p) { if (mPrivate->msg && incref) dbus_message_ref(mPrivate->msg); isSync = true; } Message::Message(const Message &m) : mPrivate(m.mPrivate) { if (mPrivate->msg) dbus_message_ref(mPrivate->msg); isSync = true; } Message::~Message() { if (mPrivate->msg) dbus_message_unref(mPrivate->msg); } Message &Message::operator = (const Message &m) { if (&m != this) { if (mPrivate->msg) dbus_message_unref(mPrivate->msg); mPrivate = m.mPrivate; if (mPrivate->msg) dbus_message_ref(mPrivate->msg); } isSync = m.isSync; return *this; } bool Message::GetSync() { return isSync; } UDBus::Tag *Message::GetTag() const { return mPrivate->tag; } const char* Message::GetErrorName() const { return dbus_message_get_error_name(mPrivate->msg); } const char *Message::Destination() const { return dbus_message_get_destination(mPrivate->msg); } const char *Message::Sender() const { return dbus_message_get_sender(mPrivate->msg); } int Message::ReplySerial() const { return dbus_message_get_reply_serial(mPrivate->msg); } int Message::Serial() const { return dbus_message_get_serial(mPrivate->msg); } bool Message::SetReplySerial(int s) { return dbus_message_set_reply_serial(mPrivate->msg, s); } bool Message::SetSender(const char *s) { return dbus_message_set_sender(mPrivate->msg, s); } bool Message::SetDestination(const char *s) { return dbus_message_set_destination(mPrivate->msg, s); } void Message::SetSync(bool sync) { isSync = sync; } bool Message::IsError() const { return Type() == DBUS_MESSAGE_TYPE_ERROR; } bool Message::IsSignal(const char *interface, const char* member) const { return dbus_message_is_signal(mPrivate->msg, interface, member); } void Message::Terminate() { dbus_message_append_args(mPrivate->msg, DBUS_TYPE_INVALID); } int Message::Type() const { return dbus_message_get_type(mPrivate->msg); } Message Message::Copy() { UDBusPrivate *pvt = new UDBusPrivate(mPrivate->msg ? dbus_message_copy(mPrivate->msg) : nullptr); return Message(pvt); } MessageIter Message::Writer() { MessageIter iter(*this); dbus_message_iter_init_append(mPrivate->msg, &iter.mPrivate->iter); return iter; } bool Message::Append(int orig, ...) { va_list val_list; va_start(val_list, orig); bool ret = dbus_message_append_args_valist(mPrivate->msg, orig, val_list); va_end(val_list); return ret; } MessageIter Message::Reader() const { MessageIter iter(const_cast(*this)); dbus_message_iter_init(mPrivate->msg, &iter.mPrivate->iter); return iter; } void CallMessage::Ref(void) { if (mPrivate->msg) dbus_message_ref(mPrivate->msg); } void CallMessage::Unref(void) { if (mPrivate->msg) dbus_message_unref(mPrivate->msg); } UDbusErrorMessage::UDbusErrorMessage() { mPrivate->msg = dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); } UDbusErrorMessage::UDbusErrorMessage(const Message &to_reply, const char *name, const char *message) { mPrivate->msg = dbus_message_new_error(to_reply.mPrivate->msg, name, message); } bool UDbusErrorMessage::operator == (const UDbusErrorMessage &m) const { return dbus_message_is_error(mPrivate->msg, m.GetName()); } const char *UDbusErrorMessage::GetName() const { return dbus_message_get_error_name(mPrivate->msg); } bool UDbusErrorMessage::SetName(const char *n) { return dbus_message_set_error_name(mPrivate->msg, n); } /* */ SignalMessage::SignalMessage(const char *name) { mPrivate->msg = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL); SetMember(name); } SignalMessage::SignalMessage(const char *path, const char *interface, const char *name) { mPrivate->msg = dbus_message_new_signal(path, interface, name); } bool SignalMessage::operator == (const SignalMessage &m) const { return dbus_message_is_signal(mPrivate->msg, m.GetInterface(), m.GetMember()); } const char *SignalMessage::GetInterface() const { return dbus_message_get_interface(mPrivate->msg); } bool SignalMessage::SetInterface(const char *i) { return dbus_message_set_interface(mPrivate->msg, i); } const char *SignalMessage::GetMember() const { return dbus_message_get_member(mPrivate->msg); } bool SignalMessage::SetMember(const char *m) { return dbus_message_set_member(mPrivate->msg, m); } const char *SignalMessage::GetPath() const { return dbus_message_get_path(mPrivate->msg); } char **SignalMessage::GetPathSplit() const { char **p = nullptr; dbus_message_get_path_decomposed(mPrivate->msg, &p); //todo: return as a std::vector ? return p; } bool SignalMessage::SetPath(const char *p) { return dbus_message_set_path(mPrivate->msg, p); } /* */ CallMessage::CallMessage() { mPrivate->msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); } CallMessage &CallMessage::operator = (const CallMessage &m) { if (&m != this) { if (mPrivate->msg) dbus_message_unref(mPrivate->msg); mPrivate = m.mPrivate; if (mPrivate->msg) dbus_message_ref(mPrivate->msg); } return *this; } CallMessage::CallMessage(const char *dest, const char *path, const char *iface, const char *method) { mPrivate->msg = dbus_message_new_method_call(dest, path, iface, method); } bool CallMessage::operator == (const CallMessage &m) const { return dbus_message_is_method_call(mPrivate->msg, m.GetInterface(), m.GetMember()); } const char *CallMessage::GetInterface() const { return dbus_message_get_interface(mPrivate->msg); } bool CallMessage::SetInterface(const char *i) { return dbus_message_set_interface(mPrivate->msg, i); } const char *CallMessage::GetMember() const { return dbus_message_get_member(mPrivate->msg); } bool CallMessage::SetMember(const char *m) { return dbus_message_set_member(mPrivate->msg, m); } const char *CallMessage::GetPath() const { return dbus_message_get_path(mPrivate->msg); } char **CallMessage::GetPathSplit() const { char **p = nullptr; dbus_message_get_path_decomposed(mPrivate->msg, &p); return p; } bool CallMessage::SetPath(const char *p) { return dbus_message_set_path(mPrivate->msg, p); } const char *CallMessage::GetSignature() const { return dbus_message_get_signature(mPrivate->msg); } TagMessage::TagMessage(UDBus::Tag *tag) { mPrivate->tag = tag; } ReturnMessage::ReturnMessage(const CallMessage &callee) { mPrivate = new UDBusPrivate(dbus_message_new_method_return(callee.mPrivate->msg)); } ReturnMessage::ReturnMessage() { mPrivate = nullptr; } const char *ReturnMessage::GetSignature() const { return dbus_message_get_signature(mPrivate->msg); }