Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_steel/src/srv/smtps.rs

5.5 KiB, 26 runs

created by r1870400018:995, 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::srv::{
2 constant,
3 context::ServerContext,
4};
5
6use oxedyne_fe2o3_core::{
7 prelude::*,
8 rand::RanDef,
9};
10use oxedyne_fe2o3_iop_crypto::enc::Encrypter;
11use oxedyne_fe2o3_iop_db::api::Database;
12use oxedyne_fe2o3_iop_hash::api::Hasher;
13use oxedyne_fe2o3_jdat::id::{
14 IdDat,
15 NumIdDat,
16};
17use oxedyne_fe2o3_net::{
18 http::{
19 handler::WebHandler,
20 header::{
21 HttpHeadline,
22 HttpMethod,
23 },
24 msg::{
25 AsyncReadIterator,
26 HttpMessageReader,
27 HttpMessage,
28 },
29 status::HttpStatus,
30 },
31 smtp::{
32 handler::EmailHandler,
33 msg::SmtpMessageReader,
34 },
35 ws::handler::WebSocketHandler,
36};
37use oxedyne_fe2o3_syntax::SyntaxRef;
38
39use std::{
40 net::SocketAddr,
41 pin::Pin,
42 sync::Arc,
43};
44
45use tokio::{
46 net::TcpStream,
47 io::AsyncWriteExt,
48};
49use tokio_rustls::server::TlsStream;
50
51
52impl<
53 const UIDL: usize,
54 UID: NumIdDat<UIDL> + 'static,
55 ENC: Encrypter + 'static,
56 KH: Hasher + 'static,
57 DB: Database<UIDL, UID, ENC, KH> + 'static,
58 EH: EmailHandler + 'static,
59 WH: WebHandler + 'static,
60 WSH: WebSocketHandler + 'static,
61>
62 ServerContext<UIDL, UID, ENC, KH, DB, EH, WH, WSH>
63{
64 pub async fn handle_smtps(
65 self,
66 mut stream: TlsStream<TcpStream>,
67 handler: EH,
68 src_addr: SocketAddr,
69 )
70 -> Outcome<()>
71 {
72 let id = fmt!("Smtps|Cx:{}", IdDat::<4, u32>::randef()); // Cx = Connection id.
73
74 let (mut read_stream, mut write_stream) = tokio::io::split(&mut stream);
75
76 let mut reader: SmtpMessageReader<
77 '_,
78 { constant::SMTP_DEFAULT_CHUNK_SIZE },
79 _,
80 > = HttpMessageReader::new(Pin::new(&mut read_stream));
81
82 let log_level = res!(self.cfg.log_level());
83
84 loop {
85 let result = reader.next().await;
86 match result {
87 Some(Ok(request)) => {
88 log!(log_level, "{}: Incoming from {:?}:", id, src_addr);
89 request.log();
90
91 if request.is_websocket_upgrade() {
92 log!(log_level, "Connection upgrading to websocket...");
93 // Reunite the read and write streams before passing to the websocket handler.
94 let reunited_stream = read_stream.unsplit(write_stream);
95 return self.handle_websocket(
96 reunited_stream,
97 ws_handler,
98 ws_syntax,
99 request,
100 &id,
101 ).await;
102 }
103
104 let sid_opt = Self::get_session_id(&request, &src_addr);
105
106 let mut response = None;
107 let close_requested = request.get_connection_close(); // Close at end of request.
108 if close_requested {
109 let mut msg = HttpMessage::new_response(HttpStatus::OK);
110 msg.set_connection_close(true);
111 response = Some(msg);
112 }
113
114 match request.header.headline {
115 HttpHeadline::Request { method, loc } => {
116 let req_headers = Arc::new(
117 request.header.fields.clone(),
118 );
119 let body = request.body;
120 match method {
121 HttpMethod::GET => {
122 let result = handler.handle_get(
123 loc,
124 response,
125 body,
126 req_headers,
127 self.db.clone(),
128 &sid_opt,
129 &id,
130 ).await;
131 response = res!(result);
132 }
133 _ => fault!("{}: Unsupported HTTP request method '{}'.", id, method),
134 }
135 },
136 _ => fault!("{}: Unsupported HTTP '{:?}'.", id, request.header.headline),
137 }
138
139 log!(log_level, "Outgoing HTTPS message:");
140 match response {
141 Some(msg) => {
142 match msg.write_all(&mut write_stream, Some(log_level)).await {
143 Ok(()) => (),
144 Err(e) => return Err(err!(e,
145 "{}: Could not send response.", id;
146 IO, Network, Wire, Write)),
147 }
148 }
149 None => log!(log_level, " None"),
150 }
151 }
152 Some(Err(e)) => return Err(e),
153 None => {
154 break;
155 }
156 }
157 }
158
159 // Gracefully close the TLS connection
160 let reunited_stream = read_stream.unsplit(write_stream);
161 let result = reunited_stream.shutdown().await;
162 if let Err(e) = result {
163 error!(e.into());
164 }
165
166 log!(log_level, "{}: Connection with {:?} closed.", id, src_addr);
167
168 Ok(())
169 }
170
171}