blob: 14029dfa8e47b2823c91b499f25d9413cb529b7c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::net_settings_types::*;
use {
failure::{bail, Error},
fuchsia_syslog::{fx_log_err, fx_log_info},
rouille,
rouille::{router, Request, Response},
serde::de::DeserializeOwned,
serde_json,
std::sync::Mutex,
};
#[derive(Debug, Clone)]
struct SettingsState {
wan_config: Option<WANConfiguration>,
dhcp_config: Option<DHCPConfiguration>,
ap_config: Option<APConfiguration>,
}
impl Default for SettingsState {
fn default() -> SettingsState {
SettingsState {
wan_config: Some(WANConfiguration {
addr: NetAddress::V4([0, 0, 0, 0], 32),
dynamically_assigned: false,
}),
// TODO(NET-1429): Secure defaults for this.
dhcp_config: Some(DHCPConfiguration {
dns_server_addr: NetAddress::V4([8, 8, 8, 8], 32),
netmask: NetAddress::V4([192, 168, 41, 0], 24),
addr_range: (
NetAddress::V4([192, 168, 41, 1], 32),
NetAddress::V4([192, 168, 41, 255], 32),
),
}),
// TODO(NET-1429): Secure defaults for this.
ap_config: Some(APConfiguration {
ssid: String::from("Basking Rootwalla").into_bytes(),
password: String::from(""),
}),
}
}
}
struct SettingsServer {
page: String,
current_settings: SettingsState,
}
impl SettingsServer {
fn new(frontend_webpage: String) -> SettingsServer {
SettingsServer {
page: frontend_webpage,
current_settings: SettingsState::default(),
}
}
// TODO(NET-1430): Hook up to wlancfg FIDL endpoints.
fn set_wan_config(&mut self, config: WANConfiguration) {
self.current_settings.wan_config = Some(config);
}
fn get_wan_config(&self) -> Option<WANConfiguration> {
self.current_settings.wan_config.as_ref().cloned()
}
// TODO(NET-1430): Hook up to netcfg FIDL endpoints.
fn set_dhcp_config(&mut self, config: DHCPConfiguration) {
self.current_settings.dhcp_config = Some(config);
}
fn get_dhcp_config(&self) -> Option<DHCPConfiguration> {
self.current_settings.dhcp_config.as_ref().cloned()
}
// TODO(NET-1430): Hook up to wlancfg FIDL endpoints.
fn set_ap_config(&mut self, config: APConfiguration) {
self.current_settings.ap_config = Some(config);
}
fn get_ap_config(&self) -> Option<APConfiguration> {
self.current_settings.ap_config.as_ref().cloned()
}
}
pub fn start_server(address: String, webpage: String) -> ! {
let server = Mutex::new(SettingsServer::new(webpage));
rouille::start_server(&address[..], move |request| {
let mut settings = &mut server.lock().unwrap();
handle_client_request(&mut settings, request)
});
}
fn parse_request<T: DeserializeOwned>(request: &Request) -> Result<T, Error> {
let data = match request.data() {
Some(d) => d,
None => bail!("Failed to parse request: no data"),
};
Ok(serde_json::from_reader(data)?)
}
fn success() -> Response {
Response::text("") // Empty success
}
fn handle_client_request(server: &mut SettingsServer, request: &Request) -> Response {
router!(request,
(GET) (/) => {
fx_log_info!(tag: "server", "Received GET for index page.");
Response::html(server.page.clone())
},
(GET) (/wan_info) => {
fx_log_info!(tag: "server", "Received GET for wan_info.");
match serde_json::to_string(&server.get_wan_config()) {
Ok(data) => {
Response::from_data("application/json", data.into_bytes())
},
Err(e) => {
fx_log_err!(tag: "server", "Couldn't create response! Error: {}", e);
Response::text("").with_status_code(500)
},
}
},
(PUT) (/wan_info) => {
fx_log_info!(tag: "server", "Received PUT for wan_info.");
let wan_info = match parse_request(request) {
Ok(info) => info,
Err(e) => {
fx_log_err!(tag: "server", "Bad Request: {}", e);
return Response::empty_400();
},
};
server.set_wan_config(wan_info);
success()
},
(GET) (/ssid_info) => {
fx_log_info!(tag: "server", "Received GET for ssid_info.");
match serde_json::to_string(&server.get_ap_config()) {
Ok(data) => {
Response::from_data("application/json", data.into_bytes())
},
Err(e) => {
fx_log_err!(tag: "server", "Couldn't create response! Error: {}", e);
Response::text("").with_status_code(500)
},
}
},
(PUT) (/ssid_info) => {
fx_log_info!(tag: "server", "Received PUT for ssid_info.");
let ssid_info = match parse_request(request) {
Ok(info) => info,
Err(e) => {
fx_log_err!(tag: "server", "Bad Request: {}", e);
return Response::empty_400();
},
};
server.set_ap_config(ssid_info);
success()
},
(GET) (/dhcp_info) => {
fx_log_info!(tag: "server", "Received GET for dhcp_info.");
match serde_json::to_string(&server.get_dhcp_config()) {
Ok(data) => {
Response::from_data("application/json", data.into_bytes())
},
Err(e) => {
fx_log_err!(tag: "server", "Couldn't create response! Error: {}", e);
Response::text("").with_status_code(500)
},
}
},
(PUT) (/dhcp_info) => {
fx_log_info!(tag: "server", "Received PUT for dhcp_info.");
let dhcp_info = match parse_request(request) {
Ok(info) => info,
Err(e) => {
fx_log_err!(tag: "server", "Bad Request: {}", e);
return Response::empty_400();
},
};
server.set_dhcp_config(dhcp_info);
success()
},
_ => {
fx_log_err!(tag: "server", "Received unknown request.");
Response::empty_404()
}
)
}