diff --git a/src/client/connection.rs b/src/client/connection.rs index b606438..1c9fc27 100644 --- a/src/client/connection.rs +++ b/src/client/connection.rs @@ -15,7 +15,7 @@ use glib::{ pub struct Connection { pub socket_connection: SocketConnection, - pub tls_client_connection: TlsClientConnection, + pub tls_client_connection: Option, } impl Connection { @@ -28,30 +28,17 @@ impl Connection { server_identity: Option, ) -> Result { Ok(Self { - tls_client_connection: match TlsClientConnection::new( - &socket_connection, - server_identity.as_ref(), - ) { - Ok(tls_client_connection) => { - // Prevent session resumption (on certificate change in runtime) - tls_client_connection.set_property("session-resumption-enabled", false); - - // Is user session - // https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates - if let Some(ref certificate) = certificate { - tls_client_connection.set_certificate(certificate); + tls_client_connection: match certificate { + Some(ref certificate) => { + match new_tls_client_connection(&socket_connection, server_identity.as_ref()) { + Ok(tls_client_connection) => { + tls_client_connection.set_certificate(certificate); + Some(tls_client_connection) + } + Err(e) => return Err(e), } - - // @TODO handle - // https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections - tls_client_connection.set_require_close_notify(true); - - // @TODO validate - // https://geminiprotocol.net/docs/protocol-specification.gmi#tls-server-certificate-validation - tls_client_connection.connect_accept_certificate(|_, _, _| true); - tls_client_connection } - Err(e) => return Err(Error::TlsClientConnection(e)), + None => None, }, socket_connection, }) @@ -68,27 +55,22 @@ impl Connection { cancellable: Cancellable, callback: impl Fn(Result) + 'static, ) { - self.tls_client_connection - .output_stream() - .write_bytes_async( - &Bytes::from(format!("{query}\r\n").as_bytes()), - priority, - Some(&cancellable.clone()), - move |result| match result { - Ok(_) => Response::from_connection_async( - self, - priority, - cancellable, - move |result| { - callback(match result { - Ok(response) => Ok(response), - Err(e) => Err(Error::Response(e)), - }) - }, - ), - Err(e) => callback(Err(Error::Stream(e))), - }, - ); + self.stream().output_stream().write_bytes_async( + &Bytes::from(format!("{query}\r\n").as_bytes()), + priority, + Some(&cancellable.clone()), + move |result| match result { + Ok(_) => { + Response::from_connection_async(self, priority, cancellable, move |result| { + callback(match result { + Ok(response) => Ok(response), + Err(e) => Err(Error::Response(e)), + }) + }) + } + Err(e) => callback(Err(Error::Stream(e))), + }, + ); } // Getters @@ -101,9 +83,35 @@ impl Connection { pub fn stream(&self) -> impl IsA { // * do not replace with `tls_client_connection.base_io_stream()` // as it will not work properly for user certificate sessions! - match self.tls_client_connection.certificate().is_some() { - true => self.tls_client_connection.clone().upcast::(), // is user session - false => self.socket_connection.clone().upcast::(), // is guest session + match self.tls_client_connection.is_some() { + true => self + .tls_client_connection + .clone() + .unwrap() + .upcast::(), // is user session + false => self.socket_connection.clone().upcast::(), // is guest session } } } + +fn new_tls_client_connection( + socket_connection: &SocketConnection, + server_identity: Option<&NetworkAddress>, +) -> Result { + match TlsClientConnection::new(socket_connection, server_identity) { + Ok(tls_client_connection) => { + // Prevent session resumption (on certificate change in runtime) + tls_client_connection.set_property("session-resumption-enabled", false); + + // @TODO handle + // https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections + tls_client_connection.set_require_close_notify(true); + + // @TODO validate + // https://geminiprotocol.net/docs/protocol-specification.gmi#tls-server-certificate-validation + tls_client_connection.connect_accept_certificate(|_, _, _| true); + Ok(tls_client_connection) + } + Err(e) => Err(Error::TlsClientConnection(e)), + } +}