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
107
108
109
110
111
112
113
114
115
use core::convert::TryFrom;
use std::io;
use tiny_http as http;
use crate::bootloader;
use anyhow::Result;
#[derive(Clone, Debug)]
pub struct HttpConfig {
pub addr: String,
pub port: u16,
pub timeout_ms: u64,
}
pub const DEFAULT_TIMEOUT_MILLISECONDS: u64 = 5000;
impl Default for HttpConfig {
fn default() -> Self {
Self {
addr: "127.0.0.1".to_owned(),
port: 2020,
timeout_ms: DEFAULT_TIMEOUT_MILLISECONDS,
}
}
}
pub struct Server {
config: HttpConfig,
server: http::Server,
bootloader: bootloader::Bootloader,
}
impl Server {
pub fn new(config: &HttpConfig, bootloader: bootloader::Bootloader) -> Result<Server> {
let server = http::Server::http(format!("{}:{}", &config.addr, config.port))
.map_err(|e| anyhow::format_err!("couldn't create HTTP server: {}", e))?;
Ok(Self {
config: config.clone(),
server,
bootloader,
})
}
pub fn run(&self) -> Result<()> {
info!("Server({:?}) run", &self.config);
loop {
self.handle_request()?;
}
}
pub fn handle_request(&self) -> Result<()> {
let request = self.server.recv()?;
let response = match *request.method() {
http::Method::Get => match request.url() {
"/" => Some(self.status()?),
"/pfr" => Some(self.pfr()?),
"/status" => Some(self.status()?),
_ => None,
},
_ => None,
}
.unwrap_or_else(|| {
http::Response::new(
http::StatusCode::from(404),
vec![],
io::Cursor::new(vec![]),
None,
None,
)
});
request.respond(response)?;
Ok(())
}
fn pfr(&self) -> Result<http::Response<io::Cursor<Vec<u8>>>> {
info!(
"lpc55::http[{:04x}:{:04x}, {}:{}]: GET /pfr",
&self.bootloader.vid, &self.bootloader.pid, &self.config.addr, &self.config.port,
);
let data = self.bootloader.read_memory(0x9_DE00, 7 * 512);
let pfr = crate::protected_flash::ProtectedFlash::try_from(&data[..]).unwrap();
let json = serde_json::to_string_pretty(&pfr).unwrap();
Ok(http::Response::from_string(json))
}
fn status(&self) -> Result<http::Response<io::Cursor<Vec<u8>>>> {
info!(
"lpc55::http[{:04x}:{:04x}, {}:{}]: GET /status",
&self.bootloader.vid, &self.bootloader.pid, &self.config.addr, &self.config.port,
);
let status = [
("status", "OK"),
("address", &self.config.addr),
("port", &self.config.port.to_string()),
("vid", &self.bootloader.vid.to_string()),
("pid", &self.bootloader.pid.to_string()),
];
let body = status
.iter()
.map(|(k, v)| [*k, *v].join("\n"))
.collect::<Vec<_>>()
.join("\n");
Ok(http::Response::from_string(body))
}
}