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
104
105
106
#[macro_use]
extern crate slog;
use std::io;
use std::net;
use std::error::Error;
pub mod options;
pub mod packet;
mod packetreader;
mod packetwriter;
pub mod rrq;
use self::options::Options;
use self::packet::{Filename, Packet, TransferMode};
pub fn serve(
addr: net::SocketAddr, handler: &Handler, logger: &slog::Logger)
-> io::Result<()>
{
let socket = try!(net::UdpSocket::bind(addr));
info!(logger, "Listening"; "address" => format!("{}", addr));
let mut bufin = [0; 512];
let mut bufout = [0; 4 + 512];
loop {
match socket.recv_from(&mut bufin) {
Ok((size, src)) => {
match Packet::parse(&mut bufin[..size]) {
Ok(packet) => {
match handler.handle(addr, src, packet) {
Some(packet) => {
let size = packet.write(&mut bufout)?;
socket.send_to(&bufout[..size], &src)?;
},
None => {},
};
},
Err(error) => warn!(
logger, "Ignoring malformed packet";
"error" => error.description()),
}
},
Err(error) => return Err(error),
}
};
}
pub trait Handler {
fn handle(
&self, local: net::SocketAddr, remote: net::SocketAddr, packet: Packet)
-> Option<Packet>
{
match packet {
Packet::Read(filename, txmode, options) =>
self.handle_rrq(local, remote, filename, txmode, options),
Packet::Write(filename, txmode, options) =>
self.handle_wrq(local, remote, filename, txmode, options),
packet =>
self.handle_other(local, remote, packet),
}
}
fn handle_rrq(
&self, _local: net::SocketAddr, _remote: net::SocketAddr,
_filename: Filename, _txmode: TransferMode, _options: Options)
-> Option<Packet>
{
Some(Packet::Error(
packet::ErrorCode::AccessViolation,
packet::ErrorMessage("read not supported".to_owned()),
))
}
fn handle_wrq(
&self, _local: net::SocketAddr, _remote: net::SocketAddr,
_filename: Filename, _txmode: TransferMode, _options: Options)
-> Option<Packet>
{
Some(Packet::Error(
packet::ErrorCode::AccessViolation,
packet::ErrorMessage("write not supported".to_owned()),
))
}
fn handle_other(
&self, _local: net::SocketAddr, _remote: net::SocketAddr,
_packet: Packet)
-> Option<Packet>
{
None
}
}
fn make_socket(peer: net::SocketAddr) -> io::Result<net::UdpSocket> {
match peer {
net::SocketAddr::V4(_) => net::UdpSocket::bind(("0.0.0.0", 0)),
net::SocketAddr::V6(_) => net::UdpSocket::bind(("::", 0)),
}
}