Use PresenceFull where necessary
Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
65c7383745
commit
5239a19871
5 changed files with 162 additions and 90 deletions
|
@ -84,7 +84,7 @@ async fn handle_presence_full_available<C: ComponentTrait>(
|
|||
debug!("Presence received to existing room: {}", &roomjid);
|
||||
if let ControlFlow::Break(_) = muc {
|
||||
// <{muc}x/> was found
|
||||
match room.add_session(component, *presence.clone()).await {
|
||||
match room.add_session(component, presence.clone()).await {
|
||||
Ok(_) => (),
|
||||
Err(Error::NickAlreadyAssigned(nick)) => {
|
||||
let error = Presence::new(PresenceType::Error)
|
||||
|
@ -103,7 +103,7 @@ async fn handle_presence_full_available<C: ComponentTrait>(
|
|||
}
|
||||
} else if let ControlFlow::Continue(_) = muc {
|
||||
// <{muc}x/> wasn't found
|
||||
match room.update_presence(component, *presence.clone()).await {
|
||||
match room.update_presence(component, presence.clone()).await {
|
||||
Ok(()) => (),
|
||||
Err(Error::ParticipantNotFound(_)) => {
|
||||
let error = Presence::new(PresenceType::Unavailable)
|
||||
|
@ -131,9 +131,7 @@ async fn handle_presence_full_available<C: ComponentTrait>(
|
|||
} else {
|
||||
debug!("Presence received to new room: {}", &roomjid);
|
||||
let mut room = Room::new(roomjid.clone());
|
||||
room.add_session(component, *presence.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
room.add_session(component, presence.clone()).await.unwrap();
|
||||
let _ = rooms.insert(roomjid, room);
|
||||
}
|
||||
|
||||
|
@ -165,7 +163,7 @@ async fn handle_presence_full_unavailable<C: ComponentTrait>(
|
|||
)
|
||||
.into()]);
|
||||
if let Some(mut room) = rooms.remove(&roomjid) {
|
||||
match room.remove_session(component, *presence.clone()).await {
|
||||
match room.remove_session(component, presence.clone()).await {
|
||||
Ok(()) => (),
|
||||
Err(Error::NonexistantSession(_)) => {
|
||||
component.send_stanza(error).await.unwrap();
|
||||
|
|
|
@ -14,11 +14,12 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::presence::PresenceFull;
|
||||
use crate::session::{Nick, Session};
|
||||
|
||||
use std::iter::IntoIterator;
|
||||
|
||||
use xmpp_parsers::{presence::Presence, BareJid, FullJid, Jid};
|
||||
use xmpp_parsers::{BareJid, FullJid, Jid};
|
||||
|
||||
/// An occupant in a room. May contain multiple sessions (Multi-Session Nicks)
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -32,7 +33,7 @@ pub struct Occupant {
|
|||
|
||||
impl Occupant {
|
||||
/// New occupant
|
||||
pub fn new(presence: Presence) -> Result<Occupant, Error> {
|
||||
pub fn new(presence: PresenceFull) -> Result<Occupant, Error> {
|
||||
let participant = presence.to.clone().map(FullJid::try_from).unwrap().unwrap();
|
||||
let session = Session::try_from(presence)?;
|
||||
Ok(Occupant {
|
||||
|
@ -50,7 +51,7 @@ impl Occupant {
|
|||
}
|
||||
|
||||
/// Add a new session to the occupant
|
||||
pub fn add_session(&mut self, presence: Presence) -> Result<(), Error> {
|
||||
pub fn add_session(&mut self, presence: PresenceFull) -> Result<(), Error> {
|
||||
let new_session = Session::try_from(presence)?;
|
||||
if BareJid::from(new_session.real().clone()) != self.real {
|
||||
return Err(Error::MismatchJids(
|
||||
|
@ -70,7 +71,7 @@ impl Occupant {
|
|||
}
|
||||
|
||||
/// Remove a session from the occupant
|
||||
pub fn remove_session(&mut self, presence: Presence) -> Result<(), Error> {
|
||||
pub fn remove_session(&mut self, presence: PresenceFull) -> Result<(), Error> {
|
||||
let own_session = Session::try_from(presence)?;
|
||||
|
||||
let len = self.sessions.len();
|
||||
|
@ -86,7 +87,7 @@ impl Occupant {
|
|||
}
|
||||
|
||||
/// Update session presence
|
||||
pub fn update_presence(&mut self, presence: Presence) -> Result<(), Error> {
|
||||
pub fn update_presence(&mut self, presence: PresenceFull) -> Result<(), Error> {
|
||||
let own_session = Session::try_from(presence)?;
|
||||
|
||||
for (i, session) in self.sessions.iter().enumerate() {
|
||||
|
@ -142,38 +143,52 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn test_occupant_update_presence() {
|
||||
let presence_louise1 = Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL1.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone());
|
||||
let presence_louise2 = Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL2.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone());
|
||||
let presence_louise1 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL1.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
let presence_louise2 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL2.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut occupant = Occupant::new(presence_louise1).unwrap();
|
||||
occupant.add_session(presence_louise2).unwrap();
|
||||
|
||||
let presence1 = Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL1.clone())
|
||||
.with_to(ROOM1_BARE.clone())
|
||||
.with_show(PresenceShow::Away)
|
||||
.with_payloads(vec![
|
||||
Muc::new().into(),
|
||||
MucUser {
|
||||
status: Vec::new(),
|
||||
items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)],
|
||||
}
|
||||
.into(),
|
||||
]);
|
||||
let presence1 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL1.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone())
|
||||
.with_show(PresenceShow::Away)
|
||||
.with_payloads(vec![
|
||||
Muc::new().into(),
|
||||
MucUser {
|
||||
status: Vec::new(),
|
||||
items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)],
|
||||
}
|
||||
.into(),
|
||||
]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
match occupant.update_presence(presence1.clone()) {
|
||||
Ok(()) => (),
|
||||
err => panic!("Err: {:?}", err),
|
||||
}
|
||||
|
||||
assert_eq!(occupant.sessions[0].presence, presence1);
|
||||
|
||||
let presence2 = Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL2.clone())
|
||||
.with_to(ROOM1_BARE.clone())
|
||||
.with_show(PresenceShow::Xa);
|
||||
let presence2 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL2.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone())
|
||||
.with_show(PresenceShow::Xa),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
match occupant.update_presence(presence2.clone()) {
|
||||
Err(Error::SecondarySession(session)) if session.real() == &*LOUISE_FULL2 => (),
|
||||
|
@ -187,9 +202,12 @@ mod tests {
|
|||
Session::try_from(presence2.clone()).unwrap()
|
||||
);
|
||||
|
||||
let presence_leave_louise2 = Presence::new(PresenceType::Unavailable)
|
||||
.with_from(LOUISE_FULL2.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone());
|
||||
let presence_leave_louise2 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::Unavailable)
|
||||
.with_from(LOUISE_FULL2.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
occupant.remove_session(presence_leave_louise2).unwrap();
|
||||
|
||||
match occupant.update_presence(presence2) {
|
||||
|
|
126
src/room.rs
126
src/room.rs
|
@ -16,6 +16,7 @@
|
|||
use crate::component::ComponentTrait;
|
||||
use crate::error::Error;
|
||||
use crate::occupant::Occupant;
|
||||
use crate::presence::PresenceFull;
|
||||
use crate::session::{Nick, Session};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
@ -69,7 +70,7 @@ impl Room {
|
|||
&self,
|
||||
component: &mut C,
|
||||
own_occupant: &Occupant,
|
||||
presence: Presence,
|
||||
presence: PresenceFull,
|
||||
mode: BroadcastPresence,
|
||||
) -> Result<(), Error> {
|
||||
let leave = matches!(mode, BroadcastPresence::Leave);
|
||||
|
@ -243,7 +244,7 @@ impl Room {
|
|||
pub async fn add_session<C: ComponentTrait>(
|
||||
&mut self,
|
||||
component: &mut C,
|
||||
presence: Presence,
|
||||
presence: PresenceFull,
|
||||
) -> Result<(), Error> {
|
||||
let new_session = Session::try_from(presence)?;
|
||||
let new_nick = new_session.participant().resource.clone();
|
||||
|
@ -310,7 +311,7 @@ impl Room {
|
|||
pub async fn update_presence<C: ComponentTrait>(
|
||||
&mut self,
|
||||
component: &mut C,
|
||||
presence: Presence,
|
||||
presence: PresenceFull,
|
||||
) -> Result<(), Error> {
|
||||
let session = Session::try_from(presence)?;
|
||||
|
||||
|
@ -334,7 +335,7 @@ impl Room {
|
|||
pub async fn remove_session<C: ComponentTrait>(
|
||||
&mut self,
|
||||
component: &mut C,
|
||||
presence: Presence,
|
||||
presence: PresenceFull,
|
||||
) -> Result<(), Error> {
|
||||
let session = Session::try_from(presence)?;
|
||||
// If occupant doesn't exist, ignore.
|
||||
|
@ -425,17 +426,26 @@ mod tests {
|
|||
let realjid3 = FullJid::from_str("bar@qxx/foo").unwrap();
|
||||
let participant3 = roomjid.clone().with_resource(String::from("nick3"));
|
||||
|
||||
let presence1 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid1.clone())
|
||||
.with_to(participant1.clone());
|
||||
let presence1 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid1.clone())
|
||||
.with_to(participant1.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence2 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid2.clone())
|
||||
.with_to(participant2.clone());
|
||||
let presence2 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid2.clone())
|
||||
.with_to(participant2.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence3 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid3.clone())
|
||||
.with_to(participant3.clone());
|
||||
let presence3 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid3.clone())
|
||||
.with_to(participant3.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut room = Room::new(roomjid.clone());
|
||||
|
||||
|
@ -514,17 +524,26 @@ mod tests {
|
|||
let realjid3 = FullJid::from_str("bar@qxx/foo").unwrap();
|
||||
let participant3 = roomjid.clone().with_resource(String::from("nick3"));
|
||||
|
||||
let presence1 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid1.clone())
|
||||
.with_to(participant1.clone());
|
||||
let presence1 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid1.clone())
|
||||
.with_to(participant1.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence2 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid2.clone())
|
||||
.with_to(participant2.clone());
|
||||
let presence2 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid2.clone())
|
||||
.with_to(participant2.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence3 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid3.clone())
|
||||
.with_to(participant3.clone());
|
||||
let presence3 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid3.clone())
|
||||
.with_to(participant3.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut room = Room::new(roomjid.clone());
|
||||
|
||||
|
@ -586,17 +605,26 @@ mod tests {
|
|||
let realjid3 = FullJid::from_str("bar@qxx/foo").unwrap();
|
||||
let participant3 = roomjid.clone().with_resource(String::from("nick3"));
|
||||
|
||||
let presence1 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid1.clone())
|
||||
.with_to(participant1.clone());
|
||||
let presence1 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid1.clone())
|
||||
.with_to(participant1.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence2 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid2.clone())
|
||||
.with_to(participant2.clone());
|
||||
let presence2 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid2.clone())
|
||||
.with_to(participant2.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence3 = Presence::new(PresenceType::None)
|
||||
.with_from(realjid3.clone())
|
||||
.with_to(participant3.clone());
|
||||
let presence3 = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(realjid3.clone())
|
||||
.with_to(participant3.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut room = Room::new(roomjid.clone());
|
||||
|
||||
|
@ -689,17 +717,26 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn test_broadcast_presence_leave() {
|
||||
let presence_louise = Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL1.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone());
|
||||
let presence_louise = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(LOUISE_FULL1.clone())
|
||||
.with_to(LOUISE_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence_sugako = Presence::new(PresenceType::None)
|
||||
.with_from(SUGAKO_FULL1.clone())
|
||||
.with_to(SUGAKO_ROOM1_PART.clone());
|
||||
let presence_sugako = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(SUGAKO_FULL1.clone())
|
||||
.with_to(SUGAKO_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let presence_rosa = Presence::new(PresenceType::None)
|
||||
.with_from(ROSA_FULL1.clone())
|
||||
.with_to(ROSA_ROOM1_PART.clone());
|
||||
let presence_rosa = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_from(ROSA_FULL1.clone())
|
||||
.with_to(ROSA_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut room = Room::new(ROOM1_BARE.clone());
|
||||
|
||||
|
@ -756,9 +793,12 @@ mod tests {
|
|||
.into()]),
|
||||
);
|
||||
|
||||
let presence_leave = Presence::new(PresenceType::Unavailable)
|
||||
.with_from(ROSA_FULL1.clone())
|
||||
.with_to(ROSA_ROOM1_PART.clone());
|
||||
let presence_leave = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::Unavailable)
|
||||
.with_from(ROSA_FULL1.clone())
|
||||
.with_to(ROSA_ROOM1_PART.clone()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
room.broadcast_presence(
|
||||
&mut component,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::presence::PresenceFull;
|
||||
|
||||
use xmpp_parsers::{presence::Presence, FullJid, Jid};
|
||||
|
||||
|
@ -22,12 +23,12 @@ pub type Nick = String;
|
|||
/// An occupant session
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Session {
|
||||
pub presence: Presence,
|
||||
pub presence: PresenceFull,
|
||||
}
|
||||
|
||||
impl Session {
|
||||
/// Ensure presence doesn't contain payloads that would impersonate us
|
||||
fn filter_presence(presence: Presence) -> Presence {
|
||||
fn filter_presence(presence: PresenceFull) -> PresenceFull {
|
||||
presence
|
||||
}
|
||||
|
||||
|
@ -48,7 +49,16 @@ impl Session {
|
|||
|
||||
impl PartialEq for Session {
|
||||
fn eq(&self, other: &Session) -> bool {
|
||||
self.real() == other.real() && self.participant() == other.participant()
|
||||
self.real() == other.real() // && self.participant() == other.participant()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PresenceFull> for Session {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(presence: PresenceFull) -> Result<Session, Error> {
|
||||
let presence = Session::filter_presence(presence);
|
||||
Ok(Session { presence })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +66,9 @@ impl TryFrom<Presence> for Session {
|
|||
type Error = Error;
|
||||
|
||||
fn try_from(presence: Presence) -> Result<Session, Error> {
|
||||
let presence = Session::filter_presence(presence);
|
||||
Ok(Session { presence })
|
||||
let presence: PresenceFull = PresenceFull::try_from(presence)?;
|
||||
Ok(Session {
|
||||
presence: Session::filter_presence(presence),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::occupant::Occupant;
|
||||
use crate::presence::PresenceFull;
|
||||
use crate::room::Room;
|
||||
use crate::session::Nick;
|
||||
use std::str::FromStr;
|
||||
|
@ -79,7 +80,7 @@ pub fn one_participant_room(roomjid: BareJid) -> Room {
|
|||
.with_to(LOUISE_ROOM1_PART.clone());
|
||||
room.occupants.insert(
|
||||
String::from(LOUISE_NICK),
|
||||
Occupant::new(presence_louise).unwrap(),
|
||||
Occupant::new(PresenceFull::try_from(presence_louise).unwrap()).unwrap(),
|
||||
);
|
||||
room
|
||||
}
|
||||
|
@ -94,11 +95,11 @@ pub fn two_participant_room(roomjid: BareJid) -> Room {
|
|||
.with_to(SUGAKO_ROOM1_PART.clone());
|
||||
room.occupants.insert(
|
||||
String::from(LOUISE_NICK),
|
||||
Occupant::new(presence_louise).unwrap(),
|
||||
Occupant::new(PresenceFull::try_from(presence_louise).unwrap()).unwrap(),
|
||||
);
|
||||
room.occupants.insert(
|
||||
String::from(SUGAKO_NICK),
|
||||
Occupant::new(presence_sugako).unwrap(),
|
||||
Occupant::new(PresenceFull::try_from(presence_sugako).unwrap()).unwrap(),
|
||||
);
|
||||
room
|
||||
}
|
||||
|
@ -111,9 +112,12 @@ pub async fn new_room<N: Into<Nick>>(roomjid: BareJid, sessions: Vec<(FullJid, N
|
|||
let nick: Nick = nick.into();
|
||||
|
||||
let participant = roomjid.clone().with_resource(nick.clone());
|
||||
let presence = Presence::new(PresenceType::None)
|
||||
.with_to(participant)
|
||||
.with_from(session);
|
||||
let presence = PresenceFull::try_from(
|
||||
Presence::new(PresenceType::None)
|
||||
.with_to(participant)
|
||||
.with_from(session),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
match room.occupants.get_mut(&nick) {
|
||||
Some(occupant) => occupant.add_session(presence).unwrap(),
|
||||
|
|
Loading…
Reference in a new issue