1use std::{
8 sync::{
9 Arc,
10 atomic::{AtomicU64, Ordering},
11 },
12 time::Duration,
13};
14
15use thiserror::Error;
16use tokio::{net::TcpListener, task, time};
17
18use crate::{
19 conn::{Connection, ConnectionConfig},
20 log,
21 routing::{DefaultRouter, Handler},
22};
23
24pub struct Server {
26 addr: String,
27 handler: Arc<dyn Handler>,
28 next_id: AtomicU64,
29 config: ConnectionConfig,
30}
31
32impl Server {
33 pub fn builder() -> ServerBuilder {
35 ServerBuilder::default()
36 }
37
38 pub fn addr(&self) -> &str {
40 &self.addr
41 }
42
43 pub async fn run(&self) -> Result<(), ServerError> {
45 log::init();
46 let listener = TcpListener::bind(&self.addr)
47 .await
48 .map_err(|error| ServerError::Bind {
49 addr: self.addr.clone(),
50 source: error,
51 })?;
52
53 loop {
54 let (stream, _peer) = match listener.accept().await {
55 Ok(pair) => pair,
56 Err(error) => {
57 log::warn(&format!("accept failed: {error}"));
58 time::sleep(Duration::from_millis(100)).await;
60 continue;
61 }
62 };
63
64 if let Err(error) = stream.set_nodelay(true) {
65 log::warn(&format!("failed to set TCP_NODELAY: {error}"));
66 }
67
68 let handler = Arc::clone(&self.handler);
69 let connection_id = self.next_id.fetch_add(1, Ordering::Relaxed);
70 let config = self.config.clone();
71
72 task::spawn(async move {
73 let connection = Connection::new(connection_id, stream, handler, config);
74 if let Err(error) = connection.run().await {
75 log::warn(&format!(
76 "connection {connection_id} closed with error: {error}"
77 ));
78 }
79 });
80 }
81 }
82}
83
84pub struct ServerBuilder {
86 addr: String,
87 handler: Arc<dyn Handler>,
88 config: ConnectionConfig,
89}
90
91impl Default for ServerBuilder {
92 fn default() -> Self {
93 Self {
94 addr: String::from("127.0.0.1:3000"),
95 handler: Arc::new(DefaultRouter),
96 config: ConnectionConfig::default(),
97 }
98 }
99}
100
101impl ServerBuilder {
102 pub fn with_addr(mut self, addr: impl Into<String>) -> Self {
104 self.addr = addr.into();
105 self
106 }
107
108 pub fn with_handler<H>(mut self, handler: H) -> Self
110 where
111 H: Handler,
112 {
113 self.handler = Arc::new(handler);
114 self
115 }
116
117 pub fn with_header_read_timeout(mut self, timeout: Duration) -> Self {
119 self.config.header_read_timeout = timeout;
120 self
121 }
122
123 pub fn with_body_read_timeout(mut self, timeout: Duration) -> Self {
125 self.config.body_read_timeout = timeout;
126 self
127 }
128
129 pub fn with_idle_timeout(mut self, timeout: Duration) -> Self {
131 self.config.idle_timeout = timeout;
132 self
133 }
134
135 pub fn with_connection_config(mut self, config: ConnectionConfig) -> Self {
137 self.config = config;
138 self
139 }
140
141 pub fn build(self) -> Server {
143 Server {
144 addr: self.addr,
145 handler: self.handler,
146 next_id: AtomicU64::new(1),
147 config: self.config,
148 }
149 }
150}
151
152#[derive(Debug, Error)]
154pub enum ServerError {
155 #[error("failed to bind {addr}: {source}")]
156 Bind {
157 addr: String,
158 source: std::io::Error,
159 },
160}