1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
use internal::Timer;
use model::id::GuildId;
use std::{
sync::mpsc::{Receiver as MpscReceiver, TryRecvError},
thread::Builder as ThreadBuilder
};
use super::{
connection::Connection,
Status
};
pub(crate) fn start(guild_id: GuildId, rx: MpscReceiver<Status>) {
let name = format!("Serenity Voice (G{})", guild_id);
ThreadBuilder::new()
.name(name)
.spawn(move || runner(&rx))
.expect(&format!("[Voice] Error starting guild: {:?}", guild_id));
}
fn runner(rx: &MpscReceiver<Status>) {
let mut senders = Vec::new();
let mut receiver = None;
let mut connection = None;
let mut timer = Timer::new(20);
'runner: loop {
loop {
match rx.try_recv() {
Ok(Status::Connect(info)) => {
connection = match Connection::new(info) {
Ok(connection) => Some(connection),
Err(why) => {
warn!("[Voice] Error connecting: {:?}", why);
None
},
};
},
Ok(Status::Disconnect) => {
connection = None;
},
Ok(Status::SetReceiver(r)) => {
receiver = r;
},
Ok(Status::SetSender(s)) => {
senders.clear();
if let Some(aud) = s {
senders.push(aud);
}
},
Ok(Status::AddSender(s)) => {
senders.push(s);
},
Err(TryRecvError::Empty) => {
// If we received nothing, then we can perform an update.
break;
},
Err(TryRecvError::Disconnected) => {
break 'runner;
},
}
}
// Overall here, check if there's an error.
//
// If there is a connection, try to send an update. This should not
// error. If there is though for some spurious reason, then set `error`
// to `true`.
//
// Otherwise, wait out the timer and do _not_ error and wait to receive
// another event.
let error = match connection.as_mut() {
Some(connection) => {
let cycle = connection.cycle(&mut senders, &mut receiver, &mut timer);
match cycle {
Ok(()) => false,
Err(why) => {
error!(
"(╯°□°)╯︵ ┻━┻ Error updating connection: {:?}",
why
);
true
},
}
},
None => {
timer.await();
false
},
};
// If there was an error, then just reset the connection and try to get
// another.
if error {
connection = None;
}
}
}
|