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
extern crate irc_message;
extern crate many2many;
use std::io::Result as IoResult;
use std::io::{LineWriter, Write, BufReader, BufWriter, BufRead};
use std::thread;
use std::net::{ToSocketAddrs, TcpStream};
use std::sync::mpsc::channel;
use many2many::MReceiver;
use std::hash::Hash;
use irc_message::IrcMessage;
pub struct Sender {
stream: LineWriter<TcpStream>
}
impl Sender {
pub fn send<T: Hash + Eq + AsRef<str>>(&mut self, message: &IrcMessage<T>) -> IoResult<()> {
let string = format!("{}\n", message);
self.stream.write_all(string.as_bytes())
}
pub fn kill_channel(mut self) {
use std::net::Shutdown;
let _ = self.stream.get_mut().shutdown(Shutdown::Read);
}
}
impl Drop for Sender {
fn drop(&mut self) {
use std::net::Shutdown;
let _ = self.stream.get_mut().shutdown(Shutdown::Write);
}
}
pub fn irc_channel<A: ToSocketAddrs>(address: A, auto_pong: bool)
-> IoResult<(Sender, MReceiver<IrcMessage<String>>)> {
let conn1 = try!(TcpStream::connect(address));
let conn2 = try!(conn1.try_clone());
let conn3 = try!(conn1.try_clone());
let (sx, rx) = channel();
thread::spawn(move || {
let buf_stream = BufReader::new(conn2);
let mut out_buf_stream = BufWriter::new(conn3);
for line in buf_stream.lines() {
match line {
Ok(line) => {
if let Some(mut parsed) = IrcMessage::parse_own(&line) {
if auto_pong
&& parsed.command.is_some()
&& parsed.command.as_ref().unwrap() == "PING" {
parsed.command = Some("PONG".to_string());
let string = format!("{}\n", parsed);
let _ = out_buf_stream.write_all(string.as_bytes());
continue;
}
if let Err(_) = sx.send(parsed) {
break;
}
}
}
Err(_) => break
}
}
});
Ok((Sender {
stream: LineWriter::new(conn1)
}, MReceiver::from(rx)))
}