session: Remove two FullJids from Session

They're already stored in the presence we own and we can get them for
free.

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2022-12-25 01:00:52 +01:00
parent 6e73112251
commit 65c7383745
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2
4 changed files with 52 additions and 67 deletions

View file

@ -36,8 +36,10 @@ pub enum Error {
/// Raised whenever an operation is applied to a session which isn't the primary session, used /// Raised whenever an operation is applied to a session which isn't the primary session, used
/// for Multi-Session Nick support. /// for Multi-Session Nick support.
SecondarySession(Session), SecondarySession(Session),
/// Raised when a JID was supposed to be present /// The origin (from) JID isn't of the expected for (bare or full)
MissingJid, InvalidOriginJid,
/// The destination (to) JID isn't of the expected for (bare or full)
InvalidDestinationJid,
/// Unhandled Iq with error description /// Unhandled Iq with error description
UnhandledIq(String), UnhandledIq(String),
/// Jid Parse errors /// Jid Parse errors
@ -59,7 +61,8 @@ impl fmt::Display for Error {
Error::SessionAlreadyExists(err) => write!(f, "Session already exist: {:?}", err), Error::SessionAlreadyExists(err) => write!(f, "Session already exist: {:?}", err),
Error::ParticipantNotFound(err) => write!(f, "Participant not found: {}", err), Error::ParticipantNotFound(err) => write!(f, "Participant not found: {}", err),
Error::SecondarySession(err) => write!(f, "Secondary session: {:?}", err), Error::SecondarySession(err) => write!(f, "Secondary session: {:?}", err),
Error::MissingJid => write!(f, "Missing JID"), Error::InvalidOriginJid => write!(f, "Invalid origin JID"),
Error::InvalidDestinationJid => write!(f, "Invalid destination JID"),
Error::UnhandledIq(err) => write!(f, "Unhandled Iq: {:?}", err), Error::UnhandledIq(err) => write!(f, "Unhandled Iq: {:?}", err),
Error::Jid(err) => write!(f, "Jid Parse error: {}", err), Error::Jid(err) => write!(f, "Jid Parse error: {}", err),
Error::Xmpp(err) => write!(f, "XMPP error: {}", err), Error::Xmpp(err) => write!(f, "XMPP error: {}", err),

View file

@ -33,11 +33,12 @@ pub struct Occupant {
impl Occupant { impl Occupant {
/// New occupant /// New occupant
pub fn new(presence: Presence) -> Result<Occupant, Error> { pub fn new(presence: Presence) -> Result<Occupant, Error> {
let participant = presence.to.clone().map(FullJid::try_from).unwrap().unwrap();
let session = Session::try_from(presence)?; let session = Session::try_from(presence)?;
Ok(Occupant { Ok(Occupant {
real: BareJid::from(session.real.clone()), real: BareJid::from(session.real().clone()),
participant: session.participant.clone(), nick: participant.resource.clone(),
nick: session.participant.resource.clone(), participant: participant,
sessions: vec![session], sessions: vec![session],
}) })
} }
@ -51,15 +52,15 @@ impl Occupant {
/// Add a new session to the 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: Presence) -> Result<(), Error> {
let new_session = Session::try_from(presence)?; let new_session = Session::try_from(presence)?;
if BareJid::from(new_session.real.clone()) != self.real { if BareJid::from(new_session.real().clone()) != self.real {
return Err(Error::MismatchJids( return Err(Error::MismatchJids(
Jid::from(self.real.clone()), Jid::from(self.real.clone()),
Jid::from(new_session.real), Jid::from(new_session.real().clone()),
)); ));
} }
for session in &self.sessions { for session in &self.sessions {
if &new_session.real == &session.real { if new_session.real() == session.real() {
return Err(Error::SessionAlreadyExists(new_session)); return Err(Error::SessionAlreadyExists(new_session));
} }
} }
@ -74,7 +75,7 @@ impl Occupant {
let len = self.sessions.len(); let len = self.sessions.len();
self.sessions self.sessions
.retain(|session| session.real != own_session.real); .retain(|session| session.real() != own_session.real());
// An item has been removed // An item has been removed
if len != self.sessions.len() { if len != self.sessions.len() {
@ -86,7 +87,7 @@ impl Occupant {
/// Update session presence /// Update session presence
pub fn update_presence(&mut self, presence: Presence) -> Result<(), Error> { pub fn update_presence(&mut self, presence: Presence) -> Result<(), Error> {
let own_session = Session::with_nick(presence, self.participant.resource.clone())?; let own_session = Session::try_from(presence)?;
for (i, session) in self.sessions.iter().enumerate() { for (i, session) in self.sessions.iter().enumerate() {
if &own_session == session { if &own_session == session {
@ -175,7 +176,7 @@ mod tests {
.with_show(PresenceShow::Xa); .with_show(PresenceShow::Xa);
match occupant.update_presence(presence2.clone()) { match occupant.update_presence(presence2.clone()) {
Err(Error::SecondarySession(session)) if session.real == *LOUISE_FULL2 => (), Err(Error::SecondarySession(session)) if session.real() == &*LOUISE_FULL2 => (),
err => panic!( err => panic!(
"Should return Error::SecondarySession(Session {{ {:?} }}), returned: {:?}", "Should return Error::SecondarySession(Session {{ {:?} }}), returned: {:?}",
*LOUISE_FULL2, err, *LOUISE_FULL2, err,
@ -183,7 +184,7 @@ mod tests {
} }
assert_eq!( assert_eq!(
occupant.sessions[1], occupant.sessions[1],
Session::with_nick(presence2.clone(), LOUISE_NICK.clone()).unwrap() Session::try_from(presence2.clone()).unwrap()
); );
let presence_leave_louise2 = Presence::new(PresenceType::Unavailable) let presence_leave_louise2 = Presence::new(PresenceType::Unavailable)
@ -192,7 +193,7 @@ mod tests {
occupant.remove_session(presence_leave_louise2).unwrap(); occupant.remove_session(presence_leave_louise2).unwrap();
match occupant.update_presence(presence2) { match occupant.update_presence(presence2) {
Err(Error::NonexistantSession(session)) if session.real == *LOUISE_FULL2 => (), Err(Error::NonexistantSession(session)) if session.real() == &*LOUISE_FULL2 => (),
err => panic!( err => panic!(
"Should return Error::SecondarySession(Session {{ {:?} }}), returned: {:?}", "Should return Error::SecondarySession(Session {{ {:?} }}), returned: {:?}",
*LOUISE_FULL2, err, *LOUISE_FULL2, err,

View file

@ -85,7 +85,7 @@ impl Room {
} else { } else {
PresenceType::None PresenceType::None
}) })
.with_to(Jid::Full(own_session.real.clone())) .with_to(Jid::Full(own_session.real().clone()))
.with_payloads(vec![MucUser { .with_payloads(vec![MucUser {
status: Vec::new(), status: Vec::new(),
items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)], items: vec![MucItem::new(Affiliation::Owner, Role::Moderator)],
@ -98,7 +98,7 @@ impl Room {
} else { } else {
PresenceType::None PresenceType::None
}) })
.with_from(Jid::Full(own_session.participant.clone())) .with_from(Jid::Full(own_occupant.participant.clone()))
.with_payloads(vec![MucUser { .with_payloads(vec![MucUser {
status: Vec::new(), status: Vec::new(),
items: vec![MucItem::new( items: vec![MucItem::new(
@ -124,7 +124,7 @@ impl Room {
// Send presence from participant to others. // Send presence from participant to others.
for session in other.iter() { for session in other.iter() {
// Skip sending if it's us. // Skip sending if it's us.
if session.real == own_session.real { if session.real() == own_session.real() {
continue; continue;
} }
// If own_session is leaving, and it is not the primary // If own_session is leaving, and it is not the primary
@ -135,7 +135,7 @@ impl Room {
let presence = presence_to_old let presence = presence_to_old
.clone() .clone()
.with_to(Jid::Full(session.real.clone())); .with_to(Jid::Full(session.real().clone()));
component.send_stanza(presence).await?; component.send_stanza(presence).await?;
} }
} }
@ -151,7 +151,7 @@ impl Room {
} else { } else {
Role::Moderator Role::Moderator
}, },
jid: Some(session.real.clone()), jid: Some(session.real().clone()),
nick: None, nick: None,
actor: None, actor: None,
continue_: None, continue_: None,
@ -174,7 +174,7 @@ impl Room {
} }
let presence = session_presence let presence = session_presence
.clone() .clone()
.with_to(Jid::Full(session.real.clone())) .with_to(Jid::Full(session.real().clone()))
.with_payloads(vec![MucUser { .with_payloads(vec![MucUser {
status: vec![], status: vec![],
items: self_items.clone(), items: self_items.clone(),
@ -192,7 +192,7 @@ impl Room {
PresenceType::None PresenceType::None
}) })
.with_from(Jid::Full(own_occupant.participant.clone())) .with_from(Jid::Full(own_occupant.participant.clone()))
.with_to(own_session.real.clone()) .with_to(own_session.real().clone())
.with_payloads(vec![MucUser { .with_payloads(vec![MucUser {
status: if leave { status: if leave {
vec![MucStatus::SelfPresence] vec![MucStatus::SelfPresence]
@ -222,7 +222,7 @@ impl Room {
self.subject = Some((subject, setter, stamp)); self.subject = Some((subject, setter, stamp));
} }
let mut subject = Message::new(Some(Jid::Full(session.real))); let mut subject = Message::new(Some(Jid::Full(session.real().clone())));
subject.from = Some(Jid::Full( subject.from = Some(Jid::Full(
self.subject.as_ref().unwrap().1.participant.clone(), self.subject.as_ref().unwrap().1.participant.clone(),
)); ));
@ -246,8 +246,8 @@ impl Room {
presence: Presence, presence: Presence,
) -> Result<(), Error> { ) -> Result<(), Error> {
let new_session = Session::try_from(presence)?; let new_session = Session::try_from(presence)?;
let new_nick = new_session.participant.resource.clone(); let new_nick = new_session.participant().resource.clone();
let realjid = new_session.real.clone(); let realjid = new_session.real().clone();
// Ensure nick isn't already assigned // Ensure nick isn't already assigned
self.occupants.iter().try_for_each(|(nick, occupant)| { self.occupants.iter().try_for_each(|(nick, occupant)| {
@ -338,7 +338,7 @@ impl Room {
) -> Result<(), Error> { ) -> Result<(), Error> {
let session = Session::try_from(presence)?; let session = Session::try_from(presence)?;
// If occupant doesn't exist, ignore. // If occupant doesn't exist, ignore.
if let Some(mut occupant) = self.occupants.remove(&session.participant.resource) { if let Some(mut occupant) = self.occupants.remove(&session.participant().resource) {
self.broadcast_presence( self.broadcast_presence(
component, component,
&occupant, &occupant,
@ -347,11 +347,11 @@ impl Room {
) )
.await?; .await?;
occupant.remove_session(session.presence)?; occupant.remove_session(session.presence.clone())?;
if occupant.iter().len() > 0 { if occupant.iter().len() > 0 {
let _ = self let _ = self
.occupants .occupants
.insert(session.participant.resource.clone(), occupant); .insert(session.participant().resource.clone(), occupant);
} }
} else { } else {
// TODO: Error // TODO: Error
@ -363,15 +363,15 @@ impl Room {
/// Fetch the occupant associated with the provided nick and ensure the session is part of /// Fetch the occupant associated with the provided nick and ensure the session is part of
/// it. /// it.
pub fn get_occupant(&self, session: &Session) -> Result<&Occupant, Error> { pub fn get_occupant(&self, session: &Session) -> Result<&Occupant, Error> {
if let Some(occupant) = self.occupants.get(&session.participant.resource) { if let Some(occupant) = self.occupants.get(&session.participant().resource) {
if occupant.contains(&session.real) { if occupant.contains(session.real()) {
Ok(occupant) Ok(occupant)
} else { } else {
Err(Error::NonexistantSession(session.clone())) Err(Error::NonexistantSession(session.clone()))
} }
} else { } else {
Err(Error::ParticipantNotFound( Err(Error::ParticipantNotFound(
session.participant.resource.clone(), session.participant().resource.clone(),
)) ))
} }
} }
@ -379,15 +379,15 @@ impl Room {
/// Fetch a mutable reference of the occupant associated with the provided nick and ensure the /// Fetch a mutable reference of the occupant associated with the provided nick and ensure the
/// session is part of it. /// session is part of it.
pub fn get_mut_occupant(&mut self, session: &Session) -> Result<&mut Occupant, Error> { pub fn get_mut_occupant(&mut self, session: &Session) -> Result<&mut Occupant, Error> {
if let Some(occupant) = self.occupants.get_mut(&session.participant.resource) { if let Some(occupant) = self.occupants.get_mut(&session.participant().resource) {
if occupant.contains(&session.real) { if occupant.contains(session.real()) {
Ok(occupant) Ok(occupant)
} else { } else {
Err(Error::NonexistantSession(session.clone())) Err(Error::NonexistantSession(session.clone()))
} }
} else { } else {
Err(Error::ParticipantNotFound( Err(Error::ParticipantNotFound(
session.participant.resource.clone(), session.participant().resource.clone(),
)) ))
} }
} }

View file

@ -15,7 +15,7 @@
use crate::error::Error; use crate::error::Error;
use xmpp_parsers::{presence::Presence, BareJid, FullJid}; use xmpp_parsers::{presence::Presence, FullJid, Jid};
pub type Nick = String; pub type Nick = String;
@ -23,8 +23,6 @@ pub type Nick = String;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Session { pub struct Session {
pub presence: Presence, pub presence: Presence,
pub real: FullJid,
pub participant: FullJid,
} }
impl Session { impl Session {
@ -33,29 +31,24 @@ impl Session {
presence presence
} }
/// Instanciate a Session from a presence which is adressed to the room JID. pub fn real(&self) -> &FullJid {
pub fn with_nick<N: Into<Nick>>(presence: Presence, nick: N) -> Result<Session, Error> { match &self.presence.from {
let presence = Session::filter_presence(presence); Some(Jid::Full(full)) => full,
Ok(Session { _ => unreachable!(),
real: presence }
.from }
.clone()
.map(FullJid::try_from) pub fn participant(&self) -> &FullJid {
.ok_or(Error::MissingJid)??, match &self.presence.to {
participant: presence Some(Jid::Full(full)) => full,
.to _ => unreachable!(),
.clone() }
.map(BareJid::from)
.ok_or(Error::MissingJid)?
.with_resource(nick.into()),
presence,
})
} }
} }
impl PartialEq for Session { impl PartialEq for Session {
fn eq(&self, other: &Session) -> bool { fn eq(&self, other: &Session) -> bool {
self.real == other.real && self.participant == other.participant self.real() == other.real() && self.participant() == other.participant()
} }
} }
@ -64,18 +57,6 @@ impl TryFrom<Presence> for Session {
fn try_from(presence: Presence) -> Result<Session, Error> { fn try_from(presence: Presence) -> Result<Session, Error> {
let presence = Session::filter_presence(presence); let presence = Session::filter_presence(presence);
Ok(Session { Ok(Session { presence })
real: presence
.from
.clone()
.map(FullJid::try_from)
.ok_or(Error::MissingJid)??,
participant: presence
.to
.clone()
.map(FullJid::try_from)
.ok_or(Error::MissingJid)??,
presence,
})
} }
} }