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

ambee/giterated

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

Create `NetworkedSubstack`.

# giterated-protocol - Create `NetworkedSubstack` which will handle all networked operations giterated needs - Add support for `NetworkedSubstack` for both the daemon and client - Pipe everything through but leave APIs temp # `giterated-daemon` - Remove a bunch of random old code, dead code, and files that aren't needed. - Moved all connection handling to `client.rs`, simplified connection logic with new types

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨202bb12

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