Add message rewriting module for editing messages
Useful for proxying individual destinations
This commit is contained in:
parent
49045ae88c
commit
d6d075ea34
2 changed files with 148 additions and 0 deletions
|
|
@ -1 +1,2 @@
|
|||
pub mod raw;
|
||||
pub mod rewrite;
|
||||
|
|
|
|||
147
sidebus-common/src/rewrite.rs
Normal file
147
sidebus-common/src/rewrite.rs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
//! Utility for rewriting zbus::Messages (since they're immutable, we need to do this to "edit" them)
|
||||
|
||||
pub struct RewriteMessage<'a> {
|
||||
builder: zbus::message::Builder<'a>,
|
||||
header: zbus::message::Header<'a>,
|
||||
body: zbus::message::Body,
|
||||
}
|
||||
|
||||
impl<'a> RewriteMessage<'a> {
|
||||
#[inline]
|
||||
pub fn new(original: &'a zbus::Message) -> zbus::Result<Self> {
|
||||
let header = original.header();
|
||||
let mut builder = match original.message_type() {
|
||||
zbus::message::Type::MethodCall => {
|
||||
zbus::Message::method_call(header.path().unwrap(), header.member().unwrap())?
|
||||
}
|
||||
zbus::message::Type::MethodReturn => {
|
||||
zbus::Message::method_return(&header)?.reply_serial(header.reply_serial())
|
||||
}
|
||||
zbus::message::Type::Error => {
|
||||
zbus::Message::error(&header, header.error_name().unwrap())?
|
||||
.reply_serial(header.reply_serial())
|
||||
}
|
||||
zbus::message::Type::Signal => zbus::Message::signal(
|
||||
header.path().unwrap(),
|
||||
header.interface().unwrap(),
|
||||
header.member().unwrap(),
|
||||
)?,
|
||||
}
|
||||
.serial(header.primary().serial_num())
|
||||
.endian(header.primary().endian_sig().into());
|
||||
for flag in header.primary().flags().iter() {
|
||||
builder = builder.with_flags(flag)?;
|
||||
}
|
||||
if let Some(sender) = header.sender() {
|
||||
builder = builder.sender(sender)?;
|
||||
}
|
||||
if let Some(destination) = header.destination() {
|
||||
builder = builder.destination(destination)?;
|
||||
}
|
||||
if let Some(iface) = header.interface() {
|
||||
builder = builder.interface(iface)?;
|
||||
}
|
||||
Ok(RewriteMessage {
|
||||
builder,
|
||||
header,
|
||||
body: original.body(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sender_unless_well_known(
|
||||
mut self,
|
||||
sender: Option<&zbus::names::UniqueName<'a>>,
|
||||
) -> zbus::Result<Self> {
|
||||
if let Some(new_sender) = self
|
||||
.header
|
||||
.sender()
|
||||
.filter(|s| !s.starts_with(":"))
|
||||
.or(sender)
|
||||
{
|
||||
self.builder = self.builder.sender(new_sender)?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn destination_unless_well_known(
|
||||
mut self,
|
||||
destination: Option<&zbus::names::BusName<'a>>,
|
||||
) -> zbus::Result<Self> {
|
||||
if let Some(new_destination) = self
|
||||
.header
|
||||
.destination()
|
||||
.filter(|s| !s.starts_with(":"))
|
||||
.or(destination)
|
||||
{
|
||||
self.builder = self.builder.destination(new_destination)?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn build(self) -> zbus::Result<zbus::Message> {
|
||||
unsafe {
|
||||
self.builder
|
||||
.build_raw_body(self.body.data(), self.body.signature(), vec![])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use zbus::names::{
|
||||
BusName, InterfaceName, MemberName, OwnedUniqueName, UniqueName, WellKnownName,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_rewrite() -> zbus::Result<()> {
|
||||
let msg = zbus::Message::method_call("/org/freedesktop/portal/desktop", "OpenURI")?
|
||||
.interface("org.freedesktop.portal.OpenURI")?
|
||||
.destination("org.freedesktop.portal.Desktop")?
|
||||
.serial(1337u32.try_into().unwrap())
|
||||
.sender(UniqueName::from_static_str_unchecked(":12.34"))?
|
||||
.build(&("what", "ever"))?;
|
||||
let new_sender = OwnedUniqueName::try_from(":rw.1234")?;
|
||||
let new_msg = RewriteMessage::new(&msg.clone())?
|
||||
.sender_unless_well_known(Some(&new_sender))?
|
||||
.destination_unless_well_known(Some(&BusName::WellKnown(
|
||||
WellKnownName::from_static_str("lol.clan.Test")?,
|
||||
)))?
|
||||
.build()?;
|
||||
let new_hdr = new_msg.header();
|
||||
assert_eq!(new_hdr.message_type(), zbus::message::Type::MethodCall);
|
||||
assert_eq!(new_hdr.reply_serial(), None);
|
||||
assert_eq!(
|
||||
new_hdr.interface(),
|
||||
Some(InterfaceName::from_static_str_unchecked(
|
||||
"org.freedesktop.portal.OpenURI"
|
||||
))
|
||||
.as_ref()
|
||||
);
|
||||
assert_eq!(
|
||||
new_hdr.member(),
|
||||
Some(MemberName::from_static_str_unchecked("OpenURI")).as_ref()
|
||||
);
|
||||
assert_eq!(
|
||||
new_hdr.sender(),
|
||||
Some(UniqueName::from_static_str_unchecked(":rw.1234")).as_ref()
|
||||
);
|
||||
assert_eq!(
|
||||
new_hdr.destination(),
|
||||
// Not rewritten, as the original was well-known (not a :12.34 type thing)
|
||||
Some(BusName::WellKnown(
|
||||
WellKnownName::from_static_str_unchecked("org.freedesktop.portal.Desktop")
|
||||
))
|
||||
.as_ref()
|
||||
);
|
||||
assert_eq!(
|
||||
new_msg.body().deserialize::<(&str, &str)>()?,
|
||||
("what", "ever")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue