1pub mod channel;
2pub mod server;
3pub mod user;
4
5use crate::audio::{sound_effects::NotificationEvents, AudioInput, AudioOutput};
6use crate::error::StateError;
7use crate::network::tcp::{DisconnectedReason, TcpEvent, TcpEventData};
8use crate::network::{ConnectionInfo, VoiceStreamType};
9use crate::notifications;
10use crate::state::server::{ConnectingServer, Server};
11use crate::state::user::User;
12
13use chrono::NaiveDateTime;
14use log::*;
15use mumble_protocol::control::{msgs, ControlPacket};
16use mumble_protocol::ping::PongPacket;
17use mumble_protocol::voice::Serverbound;
18use mumlib::command::{
19 ChannelTarget, Command, CommandResponse, MessageTarget, MumbleEvent, MumbleEventKind,
20};
21use mumlib::config::Config;
22use mumlib::Error;
23use std::fmt::Debug;
24use std::iter;
25use std::net::{SocketAddr, ToSocketAddrs};
26use std::sync::{Arc, RwLock};
27use tokio::sync::{mpsc, watch};
28
29macro_rules! at {
30 ( $( $event:expr => $generator:expr ),+ $(,)? ) => {
31 ExecutionContext::TcpEventCallback(vec![
32 $( ($event, Box::new($generator)), )+
33 ])
34 };
35}
36
37macro_rules! now {
38 ($data:expr) => {
39 ExecutionContext::Now(Box::new(move || Box::new(iter::once($data))))
40 };
41}
42
43type Responses = Box<dyn Iterator<Item = mumlib::error::Result<Option<CommandResponse>>>>;
44
45type TcpEventCallback = Box<dyn FnOnce(TcpEventData<'_>) -> Responses>;
46type TcpEventSubscriberCallback = Box<
47 dyn FnMut(
48 TcpEventData<'_>,
49 &mut mpsc::UnboundedSender<mumlib::error::Result<Option<CommandResponse>>>,
50 ) -> bool,
51>;
52
53pub enum ExecutionContext {
55 TcpEventCallback(Vec<(TcpEvent, TcpEventCallback)>),
56 TcpEventSubscriber(TcpEvent, TcpEventSubscriberCallback),
57 Now(Box<dyn FnOnce() -> Responses>),
58 Ping(
59 Box<dyn FnOnce() -> mumlib::error::Result<SocketAddr>>,
60 Box<
61 dyn FnOnce(Option<PongPacket>) -> mumlib::error::Result<Option<CommandResponse>> + Send,
62 >,
63 ),
64}
65
66impl Debug for ExecutionContext {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 f.debug_tuple(match self {
69 ExecutionContext::TcpEventCallback(_) => "TcpEventCallback",
70 ExecutionContext::TcpEventSubscriber(_, _) => "TcpEventSubscriber",
71 ExecutionContext::Now(_) => "Now",
72 ExecutionContext::Ping(_, _) => "Ping",
73 })
74 .finish()
75 }
76}
77
78#[derive(Clone, Copy, Debug, Eq, PartialEq)]
79pub enum StatePhase {
80 Disconnected,
81 Connecting,
82 Connected(VoiceStreamType),
83}
84
85#[derive(Debug)]
86pub struct State {
87 config: Config,
88 server: Server,
89 audio_input: AudioInput,
90 audio_output: AudioOutput,
91 message_buffer: Vec<(NaiveDateTime, String, u32)>,
92
93 phase_watcher: (watch::Sender<StatePhase>, watch::Receiver<StatePhase>),
94
95 events: Vec<MumbleEvent>,
96}
97
98impl State {
99 pub fn new() -> Result<Self, StateError> {
100 let config = mumlib::config::read_cfg(&mumlib::config::default_cfg_path())?;
101 let phase_watcher = watch::channel(StatePhase::Disconnected);
102 let audio_input = AudioInput::new(
103 config
104 .audio
105 .as_ref()
106 .and_then(|audio| audio.input_volume)
107 .unwrap_or(1.0),
108 config
109 .audio
110 .as_ref()
111 .and_then(|audio| audio.disable_noise_gate)
112 .unwrap_or(false),
113 phase_watcher.1.clone(),
114 )
115 .map_err(StateError::AudioError)?;
116 let audio_output = AudioOutput::new(
117 config
118 .audio
119 .as_ref()
120 .and_then(|audio| audio.output_volume)
121 .unwrap_or(1.0),
122 )
123 .map_err(StateError::AudioError)?;
124 let mut state = Self {
125 config,
126 server: Server::Disconnected,
127 audio_input,
128 audio_output,
129 message_buffer: Vec::new(),
130 phase_watcher,
131 events: Vec::new(),
132 };
133 state.reload_config();
134 Ok(state)
135 }
136
137 pub fn user_state(&mut self, msg: msgs::UserState) {
138 match &mut self.server {
139 Server::Connecting(sb) => sb.user_state(msg),
140 Server::Connected(s) => {
141 let mut events = Vec::new();
142 let to_channel = msg.get_channel_id();
143 let this_channel = s.users_channel(s.session_id());
144 let this_channel_name = s
145 .channels()
146 .get(&this_channel)
147 .map(|c| c.name())
148 .unwrap_or("<unnamed channel>")
149 .to_owned();
150
151 if msg.get_session() != s.session_id() {
152 if let Some(user) = s.users().get(&msg.get_session()) {
153 let from_channel = user.channel();
155 if from_channel != to_channel {
156 if from_channel == this_channel {
157 if let Some(channel) = s.channels().get(&to_channel) {
159 notifications::send(format!(
160 "{} moved to channel {}",
161 user.name(),
162 channel.name(),
163 ));
164 events.push(MumbleEventKind::UserLeftChannel(
165 user.name().to_owned(),
166 channel.name().to_owned(),
167 ));
168 }
169 self.audio_output
170 .play_effect(NotificationEvents::UserLeftChannel);
171 } else if to_channel == this_channel {
172 if let Some(channel) = s.channels().get(&from_channel) {
174 notifications::send(format!(
175 "{} moved to your channel from {}",
176 user.name(),
177 channel.name(),
178 ));
179 events.push(MumbleEventKind::UserJoinedChannel(
180 user.name().to_owned(),
181 channel.name().to_owned(),
182 ));
183 }
184 self.audio_output
185 .play_effect(NotificationEvents::UserJoinedChannel);
186 }
187 }
188
189 let mute = (msg.has_self_mute() && user.self_mute() != msg.get_self_mute())
190 .then(|| msg.get_self_mute());
191 let deaf = (msg.has_self_deaf() && user.self_deaf() != msg.get_self_deaf())
192 .then(|| msg.get_self_deaf());
193
194 if mute != None || deaf != None {
196 let mut s = user.name().to_owned();
197 if let Some(mute) = mute {
198 s += if mute { " muted" } else { " unmuted" };
199 }
200 if mute.is_some() && deaf.is_some() {
201 s += " and";
202 }
203 if let Some(deaf) = deaf {
204 s += if deaf { " deafened" } else { " undeafened" };
205 }
206 s += " themselves";
207 notifications::send(s.clone());
208 events.push(MumbleEventKind::UserMuteStateChanged(s));
209 }
210 } else {
211 if this_channel == to_channel {
213 notifications::send(format!(
214 "{} connected and joined {}",
215 msg.get_name(),
216 this_channel_name,
217 ));
218 events.push(MumbleEventKind::UserConnected(
219 msg.get_name().to_string(),
220 this_channel_name,
221 ));
222 self.audio_output
223 .play_effect(NotificationEvents::UserConnected);
224 }
225 }
226 }
227
228 s.user_state(msg);
229 for event in events {
230 self.push_event(event);
231 }
232 }
233 Server::Disconnected => warn!("Tried to parse a user state while disconnected"),
234 }
235 }
236
237 pub fn remove_user(&mut self, msg: msgs::UserRemove) {
238 match &mut self.server {
239 Server::Disconnected => warn!("Tried to remove user while disconnected"),
240 Server::Connecting(sb) => sb.user_remove(msg),
241 Server::Connected(s) => {
242 let mut events = Vec::new();
243 let this_channel = s.users_channel(s.session_id());
244 let other_channel = s.users_channel(msg.get_session());
245 if this_channel == other_channel {
246 let channel_name = s
247 .channels()
248 .get(&this_channel)
249 .map(|c| c.name())
250 .unwrap_or("<unnamed channel>")
251 .to_owned();
252 let user_name = s
253 .users()
254 .get(&msg.get_session())
255 .map(|u| u.name())
256 .unwrap_or("<unknown user>")
257 .to_owned();
258 notifications::send(format!("{} disconnected", user_name));
259 events.push(MumbleEventKind::UserDisconnected(user_name, channel_name));
260 self.audio_output
261 .play_effect(NotificationEvents::UserDisconnected);
262 }
263
264 s.user_remove(msg);
265 for event in events {
266 self.push_event(event);
267 }
268 }
269 }
270 }
271
272 pub fn reload_config(&mut self) {
273 match mumlib::config::read_cfg(&mumlib::config::default_cfg_path()) {
274 Ok(config) => {
275 self.config = config;
276 }
277 Err(e) => error!("Couldn't read config: {}", e),
278 }
279 if let Some(input_volume) = self
280 .config
281 .audio
282 .as_ref()
283 .and_then(|audio| audio.input_volume)
284 {
285 self.audio_input.set_volume(input_volume);
286 }
287 if let Some(output_volume) = self
288 .config
289 .audio
290 .as_ref()
291 .and_then(|audio| audio.output_volume)
292 {
293 self.audio_output.set_volume(output_volume);
294 }
295 if let Some(sound_effects) = self
296 .config
297 .audio
298 .as_ref()
299 .and_then(|audio| audio.sound_effects.as_ref())
300 {
301 self.audio_output.load_sound_effects(sound_effects);
302 }
303 }
304
305 pub fn register_message(&mut self, msg: (String, u32)) {
306 self.message_buffer
307 .push((chrono::Local::now().naive_local(), msg.0, msg.1));
308 }
309
310 pub fn broadcast_phase(&self, phase: StatePhase) {
311 self.phase_watcher.0.send(phase).unwrap();
312 }
313
314 pub fn initialized(&self) {
315 self.broadcast_phase(StatePhase::Connected(VoiceStreamType::Tcp));
316 self.audio_output
317 .play_effect(NotificationEvents::ServerConnect);
318 }
319
320 pub fn push_event(&mut self, kind: MumbleEventKind) {
322 self.events.push(MumbleEvent {
323 timestamp: chrono::Local::now().naive_local(),
324 kind,
325 });
326 }
327
328 pub fn audio_input(&self) -> &AudioInput {
329 &self.audio_input
330 }
331
332 pub fn audio_output(&self) -> &AudioOutput {
333 &self.audio_output
334 }
335
336 pub fn phase_receiver(&self) -> watch::Receiver<StatePhase> {
337 self.phase_watcher.1.clone()
338 }
339
340 pub(crate) fn server(&self) -> &Server {
341 &self.server
342 }
343
344 pub(crate) fn server_mut(&mut self) -> &mut Server {
345 &mut self.server
346 }
347
348 pub fn username(&self) -> Option<&str> {
349 match self.server() {
350 Server::Disconnected => None,
351 Server::Connecting(sb) => Some(sb.username()),
352 Server::Connected(s) => Some(s.username()),
353 }
354 }
355
356 pub fn password(&self) -> Option<&str> {
357 match self.server() {
358 Server::Disconnected => None,
359 Server::Connecting(sb) => sb.password(),
360 Server::Connected(_) => None,
361 }
362 }
363
364 fn get_user_name(&self, user: u32) -> Option<String> {
368 match &self.server {
369 Server::Disconnected => None,
370 Server::Connecting(_) => None,
371 Server::Connected(s) => Some(
372 s.users()
373 .get(&user)
374 .map(User::name)
375 .map(ToOwned::to_owned)
376 .unwrap_or(format!("Unknown user {}", user)),
377 ),
378 }
379 }
380}
381
382pub fn handle_command(
383 og_state: Arc<RwLock<State>>,
384 command: Command,
385 packet_sender: &mut mpsc::UnboundedSender<ControlPacket<Serverbound>>,
386 connection_info_sender: &mut watch::Sender<Option<ConnectionInfo>>,
387) -> ExecutionContext {
388 let mut state = &mut *og_state.write().unwrap();
390 match command {
391 Command::ChannelJoin { channel_identifier } => {
392 if let Server::Connected(s) = state.server() {
393 let id = match s.channel_name(&channel_identifier) {
394 Ok((id, _)) => id,
395 Err(e) => {
396 return now!(Err(Error::ChannelIdentifierError(channel_identifier, e)))
397 }
398 };
399
400 let mut msg = msgs::UserState::new();
401 msg.set_session(s.session_id());
402 msg.set_channel_id(id);
403 packet_sender.send(msg.into()).unwrap();
404 now!(Ok(None))
405 } else {
406 now!(Err(Error::Disconnected))
407 }
408 }
409 Command::ChannelList => {
410 if let Server::Connected(s) = state.server() {
411 let list = channel::into_channel(s.channels(), s.users());
412 now!(Ok(Some(CommandResponse::ChannelList { channels: list })))
413 } else {
414 now!(Err(Error::Disconnected))
415 }
416 }
417 Command::ConfigReload => {
418 state.reload_config();
419 now!(Ok(None))
420 }
421 Command::DeafenSelf(toggle) => {
422 if let Server::Connected(server) = &mut state.server {
423 let audio_output = &mut state.audio_output;
424 let action = match (toggle, server.muted(), server.deafened()) {
425 (Some(false), false, false) => None,
426 (Some(false), false, true) => Some((false, false)),
427 (Some(false), true, false) => None,
428 (Some(false), true, true) => Some((true, false)),
429 (Some(true), false, false) => Some((false, true)),
430 (Some(true), false, true) => None,
431 (Some(true), true, false) => Some((true, true)),
432 (Some(true), true, true) => None,
433 (None, false, false) => Some((false, true)),
434 (None, false, true) => Some((false, false)),
435 (None, true, false) => Some((true, true)),
436 (None, true, true) => Some((true, false)),
437 };
438
439 let mut new_deaf = None;
440 if let Some((mute, deafen)) = action {
441 if server.deafened() != deafen {
442 audio_output.play_effect(if deafen {
443 NotificationEvents::Deafen
444 } else {
445 NotificationEvents::Undeafen
446 });
447 } else if server.muted() != mute {
448 audio_output.play_effect(if mute {
449 NotificationEvents::Mute
450 } else {
451 NotificationEvents::Unmute
452 });
453 }
454 let mut msg = msgs::UserState::new();
455 if server.muted() != mute {
456 msg.set_self_mute(mute);
457 } else if !mute && !deafen && server.deafened() {
458 msg.set_self_mute(false);
459 }
460 if server.deafened() != deafen {
461 msg.set_self_deaf(deafen);
462 new_deaf = Some(deafen);
463 }
464 server.set_muted(mute);
465 server.set_deafened(deafen);
466 packet_sender.send(msg.into()).unwrap();
467 }
468
469 now!(Ok(
470 new_deaf.map(|b| CommandResponse::DeafenStatus { is_deafened: b })
471 ))
472 } else {
473 now!(Err(Error::Disconnected))
474 }
475 }
476 Command::Events { block } => {
477 if block {
478 warn!("Blocking event list is unimplemented");
479 now!(Err(Error::Unimplemented))
480 } else {
481 let events: Vec<_> = state
482 .events
483 .iter()
484 .map(|event| {
485 Ok(Some(CommandResponse::Event {
486 event: event.clone(),
487 }))
488 })
489 .collect();
490 ExecutionContext::Now(Box::new(move || Box::new(events.into_iter())))
491 }
492 }
493 Command::InputVolumeSet(volume) => {
494 state.audio_input.set_volume(volume);
495 now!(Ok(None))
496 }
497 Command::MuteOther(username, toggle) => {
498 if let Server::Connected(s) = state.server_mut() {
499 let id = s
500 .users_mut()
501 .iter_mut()
502 .find(|(_, user)| user.name() == username);
503
504 let (id, user) = match id {
505 Some(id) => (*id.0, id.1),
506 None => return now!(Err(Error::InvalidUsername(username))),
507 };
508
509 let action = match toggle {
510 Some(state) => {
511 if user.suppressed() != state {
512 Some(state)
513 } else {
514 None
515 }
516 }
517 None => Some(!user.suppressed()),
518 };
519
520 if let Some(action) = action {
521 user.set_suppressed(action);
522 state.audio_output.set_mute(id, action);
523 }
524
525 now!(Ok(None))
526 } else {
527 now!(Err(Error::Disconnected))
528 }
529 }
530 Command::MuteSelf(toggle) => {
531 if let Server::Connected(server) = &mut state.server {
532 let audio_output = &mut state.audio_output;
533 let action = match (toggle, server.muted(), server.deafened()) {
534 (Some(false), false, false) => None,
535 (Some(false), false, true) => Some((false, false)),
536 (Some(false), true, false) => Some((false, false)),
537 (Some(false), true, true) => Some((false, false)),
538 (Some(true), false, false) => Some((true, false)),
539 (Some(true), false, true) => None,
540 (Some(true), true, false) => None,
541 (Some(true), true, true) => None,
542 (None, false, false) => Some((true, false)),
543 (None, false, true) => Some((false, false)),
544 (None, true, false) => Some((false, false)),
545 (None, true, true) => Some((false, false)),
546 };
547
548 let mut new_mute = None;
549 if let Some((mute, deafen)) = action {
550 if server.deafened() != deafen {
551 audio_output.play_effect(if deafen {
552 NotificationEvents::Deafen
553 } else {
554 NotificationEvents::Undeafen
555 });
556 } else if server.muted() != mute {
557 audio_output.play_effect(if mute {
558 NotificationEvents::Mute
559 } else {
560 NotificationEvents::Unmute
561 });
562 }
563 let mut msg = msgs::UserState::new();
564 if server.muted() != mute {
565 msg.set_self_mute(mute);
566 new_mute = Some(mute)
567 } else if !mute && !deafen && server.deafened() {
568 msg.set_self_mute(false);
569 new_mute = Some(false)
570 }
571 if server.deafened() != deafen {
572 msg.set_self_deaf(deafen);
573 }
574 server.set_muted(mute);
575 server.set_deafened(deafen);
576 packet_sender.send(msg.into()).unwrap();
577 }
578
579 now!(Ok(
580 new_mute.map(|b| CommandResponse::MuteStatus { is_muted: b })
581 ))
582 } else {
583 now!(Err(Error::Disconnected))
584 }
585 }
586 Command::OutputVolumeSet(volume) => {
587 state.audio_output.set_volume(volume);
588 now!(Ok(None))
589 }
590 Command::Ping => {
591 now!(Ok(Some(CommandResponse::Pong)))
592 }
593 Command::ServerConnect {
594 host,
595 port,
596 username,
597 password,
598 accept_invalid_cert,
599 } => {
600 if let Server::Disconnected = state.server() {
601 let server =
602 ConnectingServer::new(format!("{}:{}", host, port), username, password);
603 state.server = Server::Connecting(server);
604 state.phase_watcher.0.send(StatePhase::Connecting).unwrap();
605
606 let socket_addr = match (host.as_ref(), port)
607 .to_socket_addrs()
608 .map(|mut e| e.next())
609 {
610 Ok(Some(v)) => v,
611 _ => {
612 warn!("Error parsing server addr");
613 return now!(Err(Error::InvalidServerAddr(host, port)));
614 }
615 };
616 connection_info_sender
617 .send(Some(ConnectionInfo::new(
618 socket_addr,
619 host,
620 accept_invalid_cert,
621 )))
622 .unwrap();
623 let state = Arc::clone(&og_state);
624 at!(
625 TcpEvent::Connected => move |res| {
626 if let TcpEventData::Connected(res) = res {
628 Box::new(iter::once(res.map(|msg| {
629 Some(CommandResponse::ServerConnect {
630 welcome_message: if msg.has_welcome_text() {
631 Some(msg.get_welcome_text().to_string())
632 } else {
633 None
634 },
635 server_state: if let Server::Connected(s) = &state.read().unwrap().server {
636 mumlib::state::Server::from(s)
637 } else {
638 unreachable!("Server should be set to connected when Tcp Connected events resolve")
639 },
640 })
641 })))
642 } else {
643 unreachable!("callback should be provided with a TcpEventData::Connected");
644 }
645 },
646 TcpEvent::Disconnected(DisconnectedReason::InvalidTls) => |_| {
647 Box::new(iter::once(Err(Error::ServerCertReject)))
648 }
649 )
650 } else {
651 now!(Err(Error::Disconnected))
652 }
653 }
654 Command::ServerDisconnect => {
655 if let Server::Connected(_) = state.server() {
656 state.server = Server::Disconnected;
657 state
658 .phase_watcher
659 .0
660 .send(StatePhase::Disconnected)
661 .unwrap();
662
663 state
664 .audio_output
665 .play_effect(NotificationEvents::ServerDisconnect);
666 now!(Ok(None))
667 } else {
668 now!(Err(Error::Disconnected))
669 }
670 }
671 Command::ServerStatus { host, port } => ExecutionContext::Ping(
672 Box::new(move || {
673 match (host.as_str(), port)
674 .to_socket_addrs()
675 .map(|mut e| e.next())
676 {
677 Ok(Some(v)) => Ok(v),
678 _ => Err(Error::InvalidServerAddr(host, port)),
679 }
680 }),
681 Box::new(move |pong| {
682 Ok(pong.map(|pong| CommandResponse::ServerStatus {
683 version: pong.version,
684 users: pong.users,
685 max_users: pong.max_users,
686 bandwidth: pong.bandwidth,
687 }))
688 }),
689 ),
690 Command::Status => {
691 if let Server::Connected(s) = state.server() {
692 let server_state = mumlib::state::Server::from(s);
693 now!(Ok(Some(CommandResponse::Status { server_state })))
694 } else {
695 now!(Err(Error::Disconnected))
696 }
697 }
698 Command::UserVolumeSet(username, volume) => {
699 if let Server::Connected(s) = state.server() {
700 let user_id = match s
701 .users()
702 .iter()
703 .find(|e| e.1.name() == username)
704 .map(|e| *e.0)
705 {
706 None => return now!(Err(Error::InvalidUsername(username))),
707 Some(v) => v,
708 };
709
710 state.audio_output.set_user_volume(user_id, volume);
711 now!(Ok(None))
712 } else {
713 now!(Err(Error::Disconnected))
714 }
715 }
716 Command::PastMessages { block } => {
717 if let Server::Connected(_) = state.server() {
719 if block {
720 let ref_state = Arc::clone(&og_state);
721 ExecutionContext::TcpEventSubscriber(
722 TcpEvent::TextMessage,
723 Box::new(move |data, sender| {
724 if let TcpEventData::TextMessage(a) = data {
725 let message = (
726 chrono::Local::now().naive_local(),
727 a.get_message().to_owned(),
728 ref_state
729 .read()
730 .unwrap()
731 .get_user_name(a.get_actor())
732 .unwrap(),
733 );
734 sender
735 .send(Ok(Some(CommandResponse::PastMessage { message })))
736 .is_ok()
737 } else {
738 unreachable!("Should only receive a TextMessage data when listening to TextMessage events");
739 }
740 }),
741 )
742 } else {
743 let messages = std::mem::take(&mut state.message_buffer);
744 let messages: Vec<_> = messages
745 .into_iter()
746 .map(|(timestamp, msg, user)| {
747 (timestamp, msg, state.get_user_name(user).unwrap())
748 })
749 .map(|e| Ok(Some(CommandResponse::PastMessage { message: e })))
750 .collect();
751
752 ExecutionContext::Now(Box::new(move || Box::new(messages.into_iter())))
753 }
754 } else {
755 now!(Err(Error::Disconnected))
756 }
757 }
758 Command::SendMessage { message, targets } => {
759 if let Server::Connected(s) = state.server() {
760 let mut msg = msgs::TextMessage::new();
761
762 msg.set_message(message);
763
764 match targets {
765 MessageTarget::Channel(channels) => {
766 for (channel, recursive) in channels {
767 let channel_id = if let ChannelTarget::Named(name) = channel {
768 let channel = s.channel_name(&name);
769 match channel {
770 Ok(channel) => channel.0,
771 Err(e) => {
772 return now!(Err(Error::ChannelIdentifierError(name, e)))
773 }
774 }
775 } else {
776 s.current_channel().0
777 };
778
779 let ids = if recursive {
780 msg.mut_tree_id()
781 } else {
782 msg.mut_channel_id()
783 };
784 ids.push(channel_id);
785 }
786 }
787 MessageTarget::User(names) => {
788 for name in names {
789 let id = s
790 .users()
791 .iter()
792 .find(|(_, user)| user.name() == name)
793 .map(|(e, _)| *e);
794
795 let id = match id {
796 Some(id) => id,
797 None => return now!(Err(Error::InvalidUsername(name))),
798 };
799
800 msg.mut_session().push(id);
801 }
802 }
803 }
804 packet_sender.send(msg.into()).unwrap();
805
806 now!(Ok(None))
807 } else {
808 now!(Err(Error::Disconnected))
809 }
810 }
811 }
812}