Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_shield/src/app/server.rs

5.5 KiB, 204 runs

created by r1870400018:4072, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1use crate::{
2 app::{
3 cfg::AppConfig,
4 constant as app_const,
5 tui::AppStatus,
6 },
7 srv::{
8 cfg::ServerConfig,
9 cmd::Command,
10 constant as srv_const,
11 context::ServerContext,
12 msg::{
13 protocol::{
14 DefaultProtocolTypes,
15 Protocol,
16 ProtocolMode,
17 },
18 syntax as srv_syntax,
19 },
20 schemes::WireSchemesInput,
21 server::{
22 answer_nothing,
23 Server,
24 },
25 },
26};
27
28use oxedyne_fe2o3_core::{
29 prelude::*,
30 alt::Alt,
31 channels::Simplex,
32 path::NormalPath,
33};
34use oxedyne_fe2o3_crypto::enc::EncryptionScheme;
35use oxedyne_fe2o3_hash::{
36 csum::ChecksumScheme,
37 hash::HashScheme,
38};
39use oxedyne_fe2o3_jdat::{
40 prelude::*,
41 cfg::Config,
42};
43use oxedyne_fe2o3_net::id;
44use oxedyne_fe2o3_o3db_sync::O3db;
45use oxedyne_fe2o3_syntax::{
46 msg::{
47 MsgCmd,
48 },
49};
50use oxedyne_fe2o3_tui::lib_tui::{
51 repl::Evaluation,
52};
53
54use std::{
55 path::Path,
56 time::Duration,
57};
58
59use tokio;
60
61
62pub async fn start_server(
63 app_cfg: &AppConfig,
64 stat: &AppStatus,
65 mut db: O3db<
66 { id::UID_LEN },
67 id::Uid,
68 EncryptionScheme,
69 HashScheme,
70 HashScheme,
71 ChecksumScheme,
72 >,
73 cmd: Option<&MsgCmd>,
74 test_stream: Option<String>, // Constains log stream id.
75)
76 -> Outcome<(
77 Evaluation,
78 Option<(
79 Simplex<Command>,
80 tokio::task::JoinHandle<Outcome<()>>,
81 )>,
82 )>
83{
84 msg!("log_stream = {}",async_log::stream());
85 let root_path = Path::new(&app_cfg.app_root)
86 .normalise() // Now a NormPathBuf.
87 .absolute();
88 debug!("Reading server config...");
89 let mut server_cfg = res!(ServerConfig::from_datmap(app_cfg.server_cfg.clone()));
90 info!("Validating server config...");
91 res!(server_cfg.check_and_fix());
92 res!(server_cfg.validate(&root_path));
93
94 // ┌───────────────────────┐
95 // │ Determine mode. │
96 // └───────────────────────┘
97 let mut mode = ProtocolMode::Production;
98 if let Some(msg_cmd) = cmd {
99 if msg_cmd.has_arg("dev") {
100 mode = ProtocolMode::Dev;
101 info!("Running in dev mode.");
102 }
103 }
104
105 if stat.first && matches!(mode, ProtocolMode::Production) {
106 return Ok((
107 Evaluation::Error(fmt!(
108 "You should update values in {} before running the server in production mode.",
109 app_const::CONFIG_NAME,
110 )),
111 None,
112 ));
113 }
114
115 // ┌───────────────────────┐
116 // │ Start database. │
117 // └───────────────────────┘
118 info!(async_log::stream(), "Starting database...");
119 res!(db.start(test_stream.clone().unwrap_or_else(|| fmt!("main"))));
120 res!(ok!(db.updated_api()).activate_gc(true));
121
122 std::thread::sleep(Duration::from_secs(1));
123
124 let uid = id::Uid::new(0);
125
126 // Ping all bots.
127 let (start, msgs) = res!(db.api().ping_bots(app_const::GET_DATA_WAIT));
128 info!(async_log::stream(), "{} ping replies received in {:?}.", msgs.len(), start.elapsed());
129
130 // ┌───────────────────────┐
131 // │ Start server. │
132 // └───────────────────────┘
133
134 let chunk_cfg = ServerConfig::new_chunk_cfg(1_000, 200, true, true);
135
136 let protocol: Protocol<
137 8,
138 {id::MID_LEN},
139 {id::SID_LEN},
140 {id::UID_LEN},
141 DefaultProtocolTypes<
142 {id::MID_LEN},
143 {id::SID_LEN},
144 {id::UID_LEN},
145 >,
146 > =
147 res!(Protocol::new(
148 &server_cfg,
149 WireSchemesInput {
150 enc: Alt::Specific(None::<EncryptionScheme>),
151 csum: Alt::Specific(None::<ChecksumScheme>),
152 powh: Alt::Specific(ServerConfig::default_packet_pow_hash_scheme()),
153 sign: Alt::Specific(ServerConfig::default_packet_signature_scheme()),
154 hsenc: Alt::Specific(None::<EncryptionScheme>),
155 chnk: Some(chunk_cfg),
156 },
157 [0u8; 8],
158 id::Mid::default(),
159 id::Sid::default(),
160 id::Uid::default(),
161 if test_stream.is_some() { ProtocolMode::Test } else { mode },
162 ));
163
164 let server_context = ServerContext::new(
165 server_cfg,
166 root_path.clone(),
167 Some((db.clone(), uid)),
168 protocol,
169 );
170
171 let syntax = res!(srv_syntax::base_msg());
172 let (mut server, cmd_chan) = Server::new(server_context, syntax.clone());
173
174 info!(async_log::stream(), "Starting server...");
175 for line in srv_const::SPLASH.lines() {
176 info!(async_log::stream(), "{}", line);
177 }
178
179 // The reference server has no application of its own, so it hears payloads
180 // and answers none of them. An application built on the library passes its
181 // own handler here.
182 let handle = tokio::spawn(async_log::LOG_STREAM_ID.scope(
183 test_stream.unwrap_or_else(|| fmt!("main")),
184 async move { server.start(answer_nothing).await },
185 ));
186
187 Ok((Evaluation::Exit, Some((cmd_chan, handle))))
188}