make session resumption optional

This commit is contained in:
yggverse 2024-12-01 12:57:54 +02:00
parent 096bd1d862
commit 94d63bd6de
2 changed files with 44 additions and 22 deletions

View file

@ -10,13 +10,17 @@ pub use error::Error;
use gio::{prelude::SocketClientExt, Cancellable, SocketClient, SocketProtocol, TlsCertificate}; use gio::{prelude::SocketClientExt, Cancellable, SocketClient, SocketProtocol, TlsCertificate};
use glib::{Priority, Uri}; use glib::{Priority, Uri};
// Defaults
pub const DEFAULT_TIMEOUT: u32 = 10; pub const DEFAULT_TIMEOUT: u32 = 10;
pub const DEFAULT_SESSION_RESUMPTION: bool = false;
/// Main point where connect external crate /// Main point where connect external crate
/// ///
/// Provides high-level API for session-safe interaction with /// Provides high-level API for session-safe interaction with
/// [Gemini](https://geminiprotocol.net) socket server /// [Gemini](https://geminiprotocol.net) socket server
pub struct Client { pub struct Client {
is_session_resumption: bool,
pub socket: SocketClient, pub socket: SocketClient,
} }
@ -39,7 +43,10 @@ impl Client {
socket.set_timeout(DEFAULT_TIMEOUT); socket.set_timeout(DEFAULT_TIMEOUT);
// Done // Done
Self { socket } Self {
is_session_resumption: DEFAULT_SESSION_RESUMPTION,
socket,
}
} }
// Actions // Actions
@ -60,29 +67,41 @@ impl Client {
// * [NetworkAddress](https://docs.gtk.org/gio/class.NetworkAddress.html) required for valid // * [NetworkAddress](https://docs.gtk.org/gio/class.NetworkAddress.html) required for valid
// [SNI](https://geminiprotocol.net/docs/protocol-specification.gmi#server-name-indication) // [SNI](https://geminiprotocol.net/docs/protocol-specification.gmi#server-name-indication)
match crate::gio::network_address::from_uri(&uri, crate::DEFAULT_PORT) { match crate::gio::network_address::from_uri(&uri, crate::DEFAULT_PORT) {
Ok(network_address) => self.socket.connect_async( Ok(network_address) => {
&network_address.clone(), self.socket
Some(&cancellable.clone()), .connect_async(&network_address.clone(), Some(&cancellable.clone()), {
move |result| match result { let is_session_resumption = self.is_session_resumption;
Ok(socket_connection) => { move |result| match result {
match Connection::new(socket_connection, certificate, Some(network_address)) Ok(socket_connection) => {
{ match Connection::new(
Ok(connection) => connection.request_async( socket_connection,
uri.to_string(), certificate,
priority, Some(network_address),
cancellable, is_session_resumption,
move |result| match result { ) {
Ok(response) => callback(Ok(response)), Ok(connection) => connection.request_async(
uri.to_string(),
priority,
cancellable,
move |result| match result {
Ok(response) => callback(Ok(response)),
Err(e) => callback(Err(Error::Connection(e))),
},
),
Err(e) => callback(Err(Error::Connection(e))), Err(e) => callback(Err(Error::Connection(e))),
}, }
), }
Err(e) => callback(Err(Error::Connection(e))), Err(e) => callback(Err(Error::Connect(e))),
} }
} })
Err(e) => callback(Err(Error::Connect(e))), }
},
),
Err(e) => callback(Err(Error::NetworkAddress(e))), Err(e) => callback(Err(Error::NetworkAddress(e))),
} }
} }
// Setters
pub fn set_session_resumption(&mut self, is_enabled: bool) {
self.is_session_resumption = is_enabled
}
} }

View file

@ -25,11 +25,13 @@ impl Connection {
socket_connection: SocketConnection, socket_connection: SocketConnection,
certificate: Option<TlsCertificate>, certificate: Option<TlsCertificate>,
server_identity: Option<NetworkAddress>, server_identity: Option<NetworkAddress>,
is_session_resumption: bool,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
Ok(Self { Ok(Self {
tls_client_connection: match new_tls_client_connection( tls_client_connection: match new_tls_client_connection(
&socket_connection, &socket_connection,
server_identity.as_ref(), server_identity.as_ref(),
is_session_resumption,
) { ) {
Ok(tls_client_connection) => { Ok(tls_client_connection) => {
if let Some(ref certificate) = certificate { if let Some(ref certificate) = certificate {
@ -92,11 +94,12 @@ impl Connection {
pub fn new_tls_client_connection( pub fn new_tls_client_connection(
socket_connection: &SocketConnection, socket_connection: &SocketConnection,
server_identity: Option<&NetworkAddress>, server_identity: Option<&NetworkAddress>,
is_session_resumption: bool,
) -> Result<TlsClientConnection, Error> { ) -> Result<TlsClientConnection, Error> {
match TlsClientConnection::new(socket_connection, server_identity) { match TlsClientConnection::new(socket_connection, server_identity) {
Ok(tls_client_connection) => { Ok(tls_client_connection) => {
// Prevent session resumption (certificate change ability in runtime) // Prevent session resumption (certificate change ability in runtime)
tls_client_connection.set_property("session-resumption-enabled", false); tls_client_connection.set_property("session-resumption-enabled", is_session_resumption);
// @TODO handle // @TODO handle
// https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections // https://geminiprotocol.net/docs/protocol-specification.gmi#closing-connections