JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Log binding ip and port

Emilia - ⁨1⁩ year ago

parent: tbd commit: ⁨29408ae

⁨giterated-daemon/src/main.rs⁩ - ⁨5527⁩ bytes
Raw
1 use anyhow::Error;
2 use giterated_cache::CacheSubstack;
3 use giterated_daemon::{
4 authentication::AuthenticationTokenGranter,
5 backend::{
6 git::GitBackend, settings::DatabaseSettings, user::UserAuth, RepositoryBackend, UserBackend,
7 },
8 client::client_wrapper,
9 database_backend::DatabaseBackend,
10 };
11
12 use giterated_models::instance::Instance;
13
14 use giterated_protocol::NetworkedSubstack;
15 use giterated_stack::GiteratedStackBuilder;
16 use sqlx::{postgres::PgConnectOptions, ConnectOptions, PgPool};
17 use std::{net::SocketAddr, str::FromStr, sync::Arc};
18 use tokio::{
19 fs::File,
20 io::{AsyncRead, AsyncReadExt, AsyncWrite},
21 net::{TcpListener, TcpStream},
22 sync::{Mutex, OnceCell},
23 };
24 use tokio_tungstenite::{accept_async, WebSocketStream};
25 use tokio_util::task::LocalPoolHandle;
26 use toml::Table;
27
28 #[macro_use]
29 extern crate tracing;
30
31 #[tokio::main]
32 async fn main() -> Result<(), Error> {
33 tracing_subscriber::fmt::init();
34 let config: Table = {
35 let mut file = File::open("Giterated.toml").await?;
36 let mut text = String::new();
37 file.read_to_string(&mut text).await?;
38 text.parse()?
39 };
40 let mut listener = TcpListener::bind(config["giterated"]["bind"].as_str().unwrap()).await?;
41 info!("Going to listen at {}", config["giterated"]["bind"].as_str().unwrap());
42
43 let db_conn_options = PgConnectOptions::new()
44 .host(config["postgres"]["host"].as_str().unwrap())
45 .port(config["postgres"]["port"].as_integer().unwrap() as u16)
46 .database(config["postgres"]["database"].as_str().unwrap())
47 .username(config["postgres"]["user"].as_str().unwrap())
48 .password(config["postgres"]["password"].as_str().unwrap())
49 .log_statements(log::LevelFilter::Off);
50 let db_pool = PgPool::connect_with(db_conn_options).await?;
51
52 debug!("Running database migrations...");
53 sqlx::migrate!().run(&db_pool).await?;
54 info!("Connected");
55
56 let stack_cell = Arc::new(OnceCell::default());
57
58 let settings = Arc::new(Mutex::new(DatabaseSettings {
59 pg_pool: db_pool.clone(),
60 stack: stack_cell.clone(),
61 }));
62
63 let repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>> =
64 Arc::new(Mutex::new(GitBackend::new(
65 &db_pool,
66 &String::from(
67 config["giterated"]["backend"]["git"]["root"]
68 .as_str()
69 .unwrap(),
70 ),
71 Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
72 stack_cell.clone(),
73 )));
74
75 let token_granter = Arc::new(Mutex::new(AuthenticationTokenGranter {
76 config: config.clone(),
77 instance: Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
78 }));
79
80 let user_backend: Arc<Mutex<dyn UserBackend + Send>> = Arc::new(Mutex::new(UserAuth::new(
81 db_pool.clone(),
82 &Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
83 token_granter.clone(),
84 settings.clone(),
85 )));
86
87 info!("Connected");
88
89 let database_backend = DatabaseBackend::new(
90 Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(),
91 user_backend.clone(),
92 repository_backend.clone(),
93 db_pool.clone(),
94 stack_cell.clone(),
95 );
96
97 let mut runtime = GiteratedStackBuilder::default();
98
99 let database_backend = database_backend.into_substack();
100 runtime.merge_builder(database_backend);
101
102 let cache_backend = CacheSubstack::default();
103 runtime.merge_builder(cache_backend.into_substack());
104
105 let networked_stack = NetworkedSubstack {
106 home_uri: Some(
107 Instance::from_str(config["giterated"]["instance"].as_str().unwrap())
108 .unwrap()
109 .0,
110 ),
111 };
112 runtime.merge_builder(networked_stack.into_server_substack());
113
114 let runtime = runtime.finish();
115
116 stack_cell
117 .set(runtime.clone())
118 .expect("failed to store global daemon stack");
119
120 let pool = LocalPoolHandle::new(5);
121
122 loop {
123 let stream = accept_stream(&mut listener).await;
124 info!("Connected");
125
126 let (stream, address) = match stream {
127 Ok(stream) => stream,
128 Err(err) => {
129 error!("Failed to accept connection. {:?}", err);
130 continue;
131 }
132 };
133
134 info!("Accepted connection from {}", address);
135
136 let connection = accept_websocket_connection(stream).await;
137
138 let connection = match connection {
139 Ok(connection) => connection,
140 Err(err) => {
141 error!(
142 "Failed to initiate Websocket connection from {}. {:?}",
143 address, err
144 );
145 continue;
146 }
147 };
148
149 info!("Websocket connection established with {}", address);
150
151 let our_instance =
152 Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap();
153 let runtime = runtime.clone();
154
155 pool.spawn_pinned(move || client_wrapper(our_instance, connection, runtime));
156 }
157 }
158
159 async fn accept_stream(listener: &mut TcpListener) -> Result<(TcpStream, SocketAddr), Error> {
160 let stream = listener.accept().await?;
161
162 Ok(stream)
163 }
164
165 async fn accept_websocket_connection<S: AsyncRead + AsyncWrite + Unpin>(
166 stream: S,
167 ) -> Result<WebSocketStream<S>, Error> {
168 let connection = accept_async(stream).await?;
169
170 Ok(connection)
171 }
172