1
0
mirror of https://github.com/openSUSE/snapper.git synced 2026-02-05 15:46:00 +01:00
Files
snapper/dbus/DBusMessage.h
2025-08-06 09:04:01 +02:00

312 lines
7.4 KiB
C++

/*
* Copyright (c) 2012 Novell, Inc.
* Copyright (c) [2016-2025] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail, you may
* find current contact information at www.novell.com.
*/
#ifndef SNAPPER_DBUSMESSAGE_H
#define SNAPPER_DBUSMESSAGE_H
#include <dbus/dbus.h>
#include <ctime>
#include <string>
#include <vector>
#include <map>
#include "snapper/Exception.h"
using namespace snapper;
namespace DBus
{
using std::string;
using std::vector;
using std::map;
struct Exception : public snapper::Exception
{
explicit Exception() : snapper::Exception("dbus generic exception") {}
explicit Exception(const string& msg) : snapper::Exception(msg) {}
};
struct ErrorException : public Exception
{
explicit ErrorException(DBusError* err)
: Exception("dbus error exception"), err_name(err->name), err_message(err->message)
{
dbus_error_free(err);
}
const char* name() const { return err_name.c_str(); }
const char* message() const { return err_message.c_str(); }
const string err_name;
const string err_message;
};
struct MarshallingException : public Exception
{
explicit MarshallingException() : Exception("dbus marshalling exception") {}
};
struct FatalException : public Exception
{
explicit FatalException() : Exception("dbus fatal exception") {}
};
class Message
{
public:
Message(DBusMessage* m, bool ref);
Message(const Message& m);
~Message();
Message& operator=(const Message& m);
DBusMessage* get_message() { return msg; }
int get_type() const { return dbus_message_get_type(msg); }
string get_member() const { return dbus_message_get_member(msg); }
string get_sender() const { return dbus_message_get_sender(msg); }
string get_path() const { return dbus_message_get_path(msg); }
string get_interface() const { return dbus_message_get_interface(msg); }
string get_error_name() const { return dbus_message_get_error_name(msg); }
bool is_method_call(const char* interface, const char* method) const
{
return dbus_message_is_method_call(msg, interface, method);
}
bool is_signal(const char* interface, const char* name) const
{
return dbus_message_is_signal(msg, interface, name);
}
private:
DBusMessage* msg;
};
class MessageMethodCall : public Message
{
public:
MessageMethodCall(const char* service, const char* object, const char* interface,
const char* method)
: Message(dbus_message_new_method_call(service, object, interface, method), false)
{
}
};
class MessageMethodReturn : public Message
{
public:
MessageMethodReturn(Message& m)
: Message(dbus_message_new_method_return(m.get_message()), false)
{
if (m.get_type() != DBUS_MESSAGE_TYPE_METHOD_CALL)
SN_THROW(FatalException());
}
};
class MessageError : public Message
{
public:
MessageError(Message& m, const char* error_msg, const char* error_code)
: Message(dbus_message_new_error(m.get_message(), error_msg, error_code), false)
{
if (m.get_type() != DBUS_MESSAGE_TYPE_METHOD_CALL)
SN_THROW(FatalException());
}
};
class MessageSignal : public Message
{
public:
MessageSignal(const char* path, const char* interface, const char* name)
: Message(dbus_message_new_signal(path, interface, name), false)
{
}
};
template <typename Type> struct TypeInfo {};
template <> struct TypeInfo<dbus_int32_t> { static const char* signature; };
template <> struct TypeInfo<dbus_uint32_t> { static const char* signature; };
template <> struct TypeInfo<dbus_uint64_t> { static const char* signature; };
template <> struct TypeInfo<string> { static const char* signature; };
// Note: mashalling functions below are not exception safe: If an FatalException is
// thrown the internal state may be broken afterwards.
class Marshalling
{
public:
DBusMessageIter* top() { return &iters.back(); }
DBusMessageIter* second() { return &iters[iters.size() - 2]; }
int get_type() { return dbus_message_iter_get_arg_type(top()); }
string get_signature();
protected:
// According to the DBus documentation DBusMessageIter can be copied by assignment
// or memcpy(). So we are fine even if the vector gets resized.
vector<DBusMessageIter> iters;
};
class Unmarshaller : public Marshalling
{
public:
Unmarshaller(Message& msg);
~Unmarshaller();
void open_recurse();
void close_recurse();
static string unescape(const string&);
};
class Marshaller : public Marshalling
{
public:
Marshaller(Message& msg);
~Marshaller();
void open_struct();
void close_struct();
void open_array(const char* signature);
void close_array();
void open_dict_entry();
void close_dict_entry();
static string escape(const string&);
};
Unmarshaller& operator>>(Unmarshaller& unmarshaller, bool& data);
Marshaller& operator<<(Marshaller& marshaller, bool data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, dbus_uint16_t& data);
Marshaller& operator<<(Marshaller& marshaller, dbus_uint16_t data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, dbus_int32_t& data);
Marshaller& operator<<(Marshaller& marshaller, dbus_int32_t data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, dbus_uint32_t& data);
Marshaller& operator<<(Marshaller& marshaller, dbus_uint32_t data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, dbus_uint64_t& data);
Marshaller& operator<<(Marshaller& marshaller, dbus_uint64_t data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, time_t& data);
Marshaller& operator<<(Marshaller& marshaller, time_t data);
Marshaller& operator<<(Marshaller& marshaller, const char* data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, string& data);
Marshaller& operator<<(Marshaller& marshaller, const string& data);
Unmarshaller& operator>>(Unmarshaller& unmarshaller, map<string, string>& data);
Marshaller& operator<<(Marshaller& marshaller, const map<string, string>& data);
template <typename Type>
Unmarshaller& operator>>(Unmarshaller& unmarshaller, vector<Type>& data)
{
if (unmarshaller.get_type() != DBUS_TYPE_ARRAY)
SN_THROW(MarshallingException());
unmarshaller.open_recurse();
while (unmarshaller.get_type() != DBUS_TYPE_INVALID)
{
if (unmarshaller.get_signature() != TypeInfo<Type>::signature)
SN_THROW(MarshallingException());
Type tmp;
unmarshaller >> tmp;
data.push_back(tmp);
}
unmarshaller.close_recurse();
return unmarshaller;
}
template <typename Type>
Marshaller& operator<<(Marshaller& marshaller, const vector<Type>& data)
{
marshaller.open_array(TypeInfo<Type>::signature);
for (const Type& value : data)
{
marshaller << value;
}
marshaller.close_array();
return marshaller;
}
}
#endif