22
33use std:: { any:: Any , pin:: Pin , sync:: Arc , time:: Duration } ;
44use std:: panic:: { AssertUnwindSafe , catch_unwind} ;
5- use crate :: __rt__:: TcpStream ;
5+ use crate :: __rt__:: { AsyncRead , AsyncWrite } ;
66use crate :: response:: Upgrade ;
77use crate :: util:: timeout_in;
88use crate :: router:: r#final:: Router ;
99use crate :: { Request , Response } ;
1010
11- pub ( crate ) struct Session {
12- router : Arc < Router > ,
13- connection : TcpStream ,
14- ip : std:: net:: IpAddr ,
11+ #[ cfg( feature="ws" ) ]
12+ use crate :: __rt__:: TcpStream ;
13+
14+ pub ( crate ) struct Session < S > {
15+ router : Arc < Router > ,
16+ connection : S ,
17+ ip : std:: net:: IpAddr ,
18+ }
19+
20+ #[ cfg( feature="ws" ) ]
21+ pub ( crate ) trait WebSocketUpgradeable {
22+ fn into_websocket_stream ( self ) -> Result < TcpStream , & ' static str > ;
1523}
1624
17- impl Session {
25+ #[ cfg( feature="ws" ) ]
26+ impl WebSocketUpgradeable for TcpStream {
27+ fn into_websocket_stream ( self ) -> Result < TcpStream , & ' static str > {
28+ Ok ( self )
29+ }
30+ }
31+
32+ #[ cfg( feature="ws" ) ]
33+ impl < S > Session < S >
34+ where
35+ S : AsyncRead + AsyncWrite + Unpin + WebSocketUpgradeable ,
36+ {
1837 pub ( crate ) fn new (
19- router : Arc < Router > ,
20- connection : TcpStream ,
21- ip : std:: net:: IpAddr
38+ router : Arc < Router > ,
39+ connection : S ,
40+ ip : std:: net:: IpAddr
2241 ) -> Self {
2342 Self {
2443 router,
@@ -31,11 +50,11 @@ impl Session {
3150 #[ cold] #[ inline( never) ]
3251 fn panicking ( panic : Box < dyn Any + Send > ) -> Response {
3352 if let Some ( msg) = panic. downcast_ref :: < String > ( ) {
34- crate :: WARNING !( "panic : {msg}" ) ;
53+ crate :: WARNING !( "[Panicked] : {msg}" ) ;
3554 } else if let Some ( msg) = panic. downcast_ref :: < & str > ( ) {
36- crate :: WARNING !( "panic : {msg}" ) ;
55+ crate :: WARNING !( "[Panicked] : {msg}" ) ;
3756 } else {
38- crate :: WARNING !( "panic " ) ;
57+ crate :: WARNING !( "[Panicked] " ) ;
3958 }
4059 crate :: Response :: InternalServerError ( )
4160 }
@@ -66,33 +85,107 @@ impl Session {
6685 }
6786 }
6887 } ) . await {
69- None => crate :: WARNING !( "\
88+ None => crate :: WARNING !( "[WARNING] \
7089 Session timeouted. In Ohkami, Keep-Alive timeout \
7190 is set to 42 seconds by default and is configurable \
7291 by `OHKAMI_KEEPALIVE_TIMEOUT` environment variable.\
7392 ") ,
7493
7594 Some ( Upgrade :: None ) => crate :: DEBUG !( "about to shutdown connection" ) ,
7695
77- #[ cfg( feature="ws" ) ]
7896 Some ( Upgrade :: WebSocket ( ws) ) => {
79- crate :: DEBUG !( "WebSocket session started" ) ;
80-
81- let aborted = ws. manage_with_timeout (
82- Duration :: from_secs ( crate :: CONFIG . websocket_timeout ( ) ) ,
83- self . connection
84- ) . await ;
85- if aborted {
86- crate :: WARNING !( "\
87- WebSocket session aborted by timeout. In Ohkami, \
88- WebSocket timeout is set to 3600 seconds (1 hour) \
89- by default and is configurable by `OHKAMI_WEBSOCKET_TIMEOUT` \
90- environment variable.\
91- ") ;
92- }
97+ match self . connection . into_websocket_stream ( ) {
98+ Ok ( tcp_stream) => {
99+ crate :: DEBUG !( "WebSocket session started" ) ;
93100
94- crate :: DEBUG !( "WebSocket session finished" ) ;
101+ let aborted = ws. manage_with_timeout (
102+ Duration :: from_secs ( crate :: CONFIG . websocket_timeout ( ) ) ,
103+ tcp_stream
104+ ) . await ;
105+ if aborted {
106+ crate :: WARNING !( "[WARNING] \
107+ WebSocket session aborted by timeout. In Ohkami, \
108+ WebSocket timeout is set to 3600 seconds (1 hour) \
109+ by default and is configurable by `OHKAMI_WEBSOCKET_TIMEOUT` \
110+ environment variable.\
111+ ") ;
112+ }
113+
114+ crate :: DEBUG !( "WebSocket session finished" ) ;
115+ }
116+ Err ( msg) => {
117+ crate :: WARNING !( "[WARNING] {}" , msg) ;
118+ }
119+ }
95120 }
96121 }
97122 }
98123}
124+
125+ // There has to be some cleaner implementation to apply the conditional trait bounds in this...
126+ #[ cfg( not( feature="ws" ) ) ]
127+ impl < S > Session < S >
128+ where
129+ S : AsyncRead + AsyncWrite + Unpin ,
130+ {
131+ pub ( crate ) fn new (
132+ router : Arc < Router > ,
133+ connection : S ,
134+ ip : std:: net:: IpAddr
135+ ) -> Self {
136+ Self {
137+ router,
138+ connection,
139+ ip
140+ }
141+ }
142+
143+ pub ( crate ) async fn manage ( mut self ) {
144+ #[ cold] #[ inline( never) ]
145+ fn panicking ( panic : Box < dyn Any + Send > ) -> Response {
146+ if let Some ( msg) = panic. downcast_ref :: < String > ( ) {
147+ crate :: WARNING !( "[Panicked]: {msg}" ) ;
148+ } else if let Some ( msg) = panic. downcast_ref :: < & str > ( ) {
149+ crate :: WARNING !( "[Panicked]: {msg}" ) ;
150+ } else {
151+ crate :: WARNING !( "[Panicked]" ) ;
152+ }
153+ crate :: Response :: InternalServerError ( )
154+ }
155+
156+ match timeout_in ( Duration :: from_secs ( crate :: CONFIG . keepalive_timeout ( ) ) , async {
157+ let mut req = Request :: init ( self . ip ) ;
158+ let mut req = unsafe { Pin :: new_unchecked ( & mut req) } ;
159+ loop {
160+ req. clear ( ) ;
161+ match req. as_mut ( ) . read ( & mut self . connection ) . await {
162+ Ok ( Some ( ( ) ) ) => {
163+ let close = matches ! ( req. headers. Connection ( ) , Some ( "close" | "Close" ) ) ;
164+
165+ let res = match catch_unwind ( AssertUnwindSafe ( {
166+ let req = req. as_mut ( ) ;
167+ || self . router . handle ( req. get_mut ( ) )
168+ } ) ) {
169+ Ok ( future) => future. await ,
170+ Err ( panic) => panicking ( panic) ,
171+ } ;
172+ let upgrade = res. send ( & mut self . connection ) . await ;
173+
174+ if !upgrade. is_none ( ) { break upgrade}
175+ if close { break Upgrade :: None }
176+ }
177+ Ok ( None ) => break Upgrade :: None ,
178+ Err ( res) => { res. send ( & mut self . connection ) . await ; } ,
179+ }
180+ }
181+ } ) . await {
182+ None => crate :: WARNING !( "[WARNING] \
183+ Session timeouted. In Ohkami, Keep-Alive timeout \
184+ is set to 42 seconds by default and is configurable \
185+ by `OHKAMI_KEEPALIVE_TIMEOUT` environment variable.\
186+ ") ,
187+
188+ Some ( Upgrade :: None ) => crate :: DEBUG !( "about to shutdown connection" ) ,
189+ }
190+ }
191+ }
0 commit comments