version a0.0.1
This commit is contained in:
commit
9469ef10b6
19 files changed
+4281
No files matched your search
+180
@@ -0,0 +1,180 @@
|
||||
mod discovery;
|
||||
mod models;
|
||||
mod p2p;
|
||||
mod tls;
|
||||
mod ui;
|
||||
|
||||
use axum::{
|
||||
extract::DefaultBodyLimit,
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use axum_server::tls_rustls::RustlsConfig;
|
||||
use local_ip_address::local_ip;
|
||||
use models::{AppState, MAX_PAYLOAD_SIZE, MAX_RAM_TEXTS, MEDIA_DIR};
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
net::SocketAddr,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// 0. Регистрация глобального CryptoProvider (ring) для rustls 0.23+
|
||||
let _ = rustls::crypto::ring::default_provider().install_default();
|
||||
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
let mut device_name = "My-Device".to_string();
|
||||
let mut p2p_port: u16 = 8443;
|
||||
let mut ui_port: u16 = 8080;
|
||||
let mut custom_ip: Option<String> = None;
|
||||
|
||||
let mut i = 1;
|
||||
let mut positional_idx = 0;
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"--ip" => {
|
||||
if i + 1 < args.len() {
|
||||
custom_ip = Some(args[i + 1].clone());
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
"--name" => {
|
||||
if i + 1 < args.len() {
|
||||
device_name = args[i + 1].clone();
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
"--p2p-port" => {
|
||||
if i + 1 < args.len() {
|
||||
if let Ok(p) = args[i + 1].parse() {
|
||||
p2p_port = p;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
"--ui-port" => {
|
||||
if i + 1 < args.len() {
|
||||
if let Ok(p) = args[i + 1].parse() {
|
||||
ui_port = p;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
arg if !arg.starts_with("--") => {
|
||||
match positional_idx {
|
||||
0 => device_name = arg.to_string(),
|
||||
1 => {
|
||||
if let Ok(p) = arg.parse() {
|
||||
p2p_port = p;
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
if let Ok(p) = arg.parse() {
|
||||
ui_port = p;
|
||||
}
|
||||
}
|
||||
3 => custom_ip = Some(arg.to_string()),
|
||||
_ => {}
|
||||
}
|
||||
positional_idx += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let (bind_ip, my_ip) = match custom_ip {
|
||||
Some(ip) => {
|
||||
if ip == "0.0.0.0" {
|
||||
let detected = local_ip()
|
||||
.map(|addr| addr.to_string())
|
||||
.unwrap_or_else(|_| "127.0.0.1".to_string());
|
||||
("0.0.0.0".to_string(), detected)
|
||||
} else {
|
||||
(ip.clone(), ip)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let detected = local_ip().expect("Не удалось определить локальный IP").to_string();
|
||||
("0.0.0.0".to_string(), detected)
|
||||
}
|
||||
};
|
||||
|
||||
tokio::fs::create_dir_all(MEDIA_DIR)
|
||||
.await
|
||||
.expect("Не удалось создать папку received_media на диске");
|
||||
|
||||
// 1. Генерация сертификата в ОЗУ под выбранный IP и настройка HTTPS-клиентов
|
||||
let (cert_der, key_der, my_fingerprint) = tls::generate_in_memory_cert(&my_ip);
|
||||
let trusted_fingerprints = Arc::new(RwLock::new(HashMap::new()));
|
||||
let http_client = tls::build_pinned_http_client(trusted_fingerprints.clone());
|
||||
let probe_client = tls::build_probe_http_client();
|
||||
|
||||
let state = Arc::new(AppState {
|
||||
device_name: device_name.clone(),
|
||||
my_ip: my_ip.clone(),
|
||||
p2p_port,
|
||||
my_fingerprint: my_fingerprint.clone(),
|
||||
ram_texts: RwLock::new(VecDeque::with_capacity(MAX_RAM_TEXTS)),
|
||||
disk_media: RwLock::new(VecDeque::new()),
|
||||
peers: RwLock::new(HashMap::new()),
|
||||
trusted_fingerprints,
|
||||
http_client,
|
||||
probe_client,
|
||||
});
|
||||
|
||||
// 2. Запуск широковещательного UDP-маяка на порт 5354
|
||||
discovery::start_discovery(state.clone());
|
||||
|
||||
// 3. Запуск внешнего P2P HTTPS-сервера
|
||||
let tls_config = RustlsConfig::from_der(vec![cert_der], key_der)
|
||||
.await
|
||||
.expect("Ошибка конфигурации TLS");
|
||||
|
||||
let p2p_router = Router::new()
|
||||
.route("/p2p/info", get(p2p::p2p_info))
|
||||
.route("/p2p/text", post(p2p::p2p_receive_text))
|
||||
.route("/p2p/media", post(p2p::p2p_receive_media))
|
||||
.layer(DefaultBodyLimit::max(MAX_PAYLOAD_SIZE))
|
||||
.with_state(state.clone());
|
||||
|
||||
let p2p_addr: SocketAddr = format!("{}:{}", bind_ip, p2p_port)
|
||||
.parse()
|
||||
.unwrap_or_else(|_| panic!("Некорректный сокет: {}:{}", bind_ip, p2p_port));
|
||||
|
||||
tokio::spawn(async move {
|
||||
axum_server::bind_rustls(p2p_addr, tls_config)
|
||||
.serve(p2p_router.into_make_service())
|
||||
.await
|
||||
.expect("Ошибка P2P HTTPS-сервера");
|
||||
});
|
||||
|
||||
// 4. Запуск локального UI-сервера (127.0.0.1)
|
||||
let ui_router = Router::new()
|
||||
.route("/", get(ui::ui_index))
|
||||
.route("/ui/state", get(ui::ui_get_state))
|
||||
.route("/ui/manual-peer", post(ui::ui_add_manual_peer))
|
||||
.route("/ui/trust", post(ui::ui_trust_peer))
|
||||
.route("/ui/clear-ram", post(ui::ui_clear_ram))
|
||||
.route("/ui/send-text", post(ui::ui_send_text))
|
||||
.route("/ui/send-media", post(ui::ui_send_media))
|
||||
.route("/ui/files/:filename", get(ui::ui_serve_saved_file))
|
||||
.layer(DefaultBodyLimit::max(MAX_PAYLOAD_SIZE))
|
||||
.with_state(state);
|
||||
|
||||
let ui_addr: SocketAddr = format!("127.0.0.1:{}", ui_port).parse().unwrap();
|
||||
println!("==============================================================");
|
||||
println!(" Устройство: {}", device_name);
|
||||
println!(" P2P сокет (HTTPS): https://{}:{}", bind_ip, p2p_port);
|
||||
println!(" Маяк обнаружения (UDP): 255.255.255.255:5354");
|
||||
println!(" КОД СВЕРКИ СЕРТИФИКАТА (PIN): [ {} ]", &my_fingerprint[..8].to_uppercase());
|
||||
println!(" Хранилище медиа: ./{}/", MEDIA_DIR);
|
||||
println!("--------------------------------------------------------------");
|
||||
println!(" ОТКРОЙТЕ ИНТЕРФЕЙС В БРАУЗЕРЕ: http://127.0.0.1:{}", ui_port);
|
||||
println!("==============================================================");
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(ui_addr).await.unwrap();
|
||||
axum::serve(listener, ui_router).await.unwrap();
|
||||
}
|
||||
Reference in new issue
Block a user