Working connection and display of info
This commit is contained in:
parent
a7b3ecf178
commit
a667c6d98b
3
.cargo/config.toml
Normal file
3
.cargo/config.toml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
[build]
|
||||||
|
rustflags = ["--cfg", "tokio_unstable"]
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
|
/vendor
|
||||||
|
/Cargo.lock
|
||||||
|
.vscode/launch.json
|
||||||
|
1379
Cargo.lock
generated
1379
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -22,11 +22,16 @@ pki-types = { package = "rustls-pki-types", version = "1.0", features = [
|
|||||||
tokio-rustls = { version = "0.25" }
|
tokio-rustls = { version = "0.25" }
|
||||||
env_logger = "0.10.1"
|
env_logger = "0.10.1"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
tokio = { version = "1.34.0", features = ["full"] }
|
tokio = { version = "1.34.0", features = ["full", "tracing"] }
|
||||||
webpki-roots = "0.26.0"
|
webpki-roots = "0.26.0"
|
||||||
nom = "7.1.3"
|
nom = "7.1.3"
|
||||||
managesieve = { path = "../managesieve" }
|
managesieve = { path = "../managesieve" }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
gtk4 = { version = "0.7.3", features = ["gnome_45"] }
|
gtk4 = { version = "0.7", features = ["gnome_45", "blueprint"] }
|
||||||
serde = { version = "1.0.193", features = ["derive"] }
|
serde = { version = "1.0.193", features = ["derive"] }
|
||||||
|
libadwaita = { version = "0.5.3", features = ["gtk_v4_10", "v1_4"] }
|
||||||
|
gtk-blueprint = "0.2"
|
||||||
|
phf = "0.11"
|
||||||
|
tracing = "0.1"
|
||||||
|
console-subscriber = "0.2"
|
||||||
|
3
build.rs
Normal file
3
build.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=**/*.blp");
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8' standalone='no'?>
|
|
||||||
<!DOCTYPE cambalache-project SYSTEM "cambalache-project.dtd">
|
|
||||||
<cambalache-project version="0.13.1" target_tk="gtk-4.0">
|
|
||||||
<ui>
|
|
||||||
(1,None,"sieverman.ui","sieverman.ui",None,None,"Franz Dietrich",None,None,None,None)
|
|
||||||
</ui>
|
|
||||||
<object>
|
|
||||||
(1,1,"GtkApplicationWindow","sieverman",None,None,None,None,-1,None),
|
|
||||||
(1,2,"GtkBox",None,1,None,None,None,-1,None),
|
|
||||||
(1,3,"GtkBox",None,2,None,None,None,1,None),
|
|
||||||
(1,4,"GtkActionBar",None,2,None,None,None,None,None),
|
|
||||||
(1,5,"GtkStatusbar",None,2,None,None,None,2,None),
|
|
||||||
(1,6,"GtkSpinner",None,3,None,None,None,1,None),
|
|
||||||
(1,7,"GtkLabel","messages",3,None,None,None,None,None),
|
|
||||||
(1,9,"GtkFrame",None,3,None,None,None,2,None),
|
|
||||||
(1,10,"GtkLabel","serverstatus_2",9,None,None,None,None,None)
|
|
||||||
</object>
|
|
||||||
<object_property>
|
|
||||||
(1,2,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
|
|
||||||
(1,3,"GtkBox","baseline-child","0",None,None,None,None,None,None,None,None,None),
|
|
||||||
(1,3,"GtkBox","homogeneous","True",None,None,None,None,None,None,None,None,None),
|
|
||||||
(1,6,"GtkSpinner","spinning","True",None,None,None,None,None,None,None,None,None),
|
|
||||||
(1,7,"GtkLabel","label","Loading",None,None,None,None,None,None,None,None,None),
|
|
||||||
(1,10,"GtkLabel","label","Loading…",None,None,None,None,None,None,None,None,None)
|
|
||||||
</object_property>
|
|
||||||
<object_data>
|
|
||||||
(1,3,"GtkWidget",1,1,None,None,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,2,None,1,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,3,None,1,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,4,None,1,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,5,None,1,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,6,None,1,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,7,None,1,None,None,None,None),
|
|
||||||
(1,3,"GtkWidget",2,8,None,1,None,None,None,None)
|
|
||||||
</object_data>
|
|
||||||
</cambalache-project>
|
|
45
gui/main_window.blp
Normal file
45
gui/main_window.blp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
Adw.ApplicationWindow window {
|
||||||
|
default-width: 900;
|
||||||
|
default-height: 500;
|
||||||
|
|
||||||
|
content: Gtk.Box {
|
||||||
|
orientation: vertical;
|
||||||
|
|
||||||
|
Adw.HeaderBar{
|
||||||
|
title-widget: Adw.WindowTitle {
|
||||||
|
title: "Sieverman";
|
||||||
|
};
|
||||||
|
|
||||||
|
Gtk.Button { label: "Neu";}
|
||||||
|
}
|
||||||
|
Gtk.Box {
|
||||||
|
orientation: horizontal;
|
||||||
|
|
||||||
|
vexpand: true;
|
||||||
|
halign: fill;
|
||||||
|
|
||||||
|
Gtk.Label{
|
||||||
|
label: "Log information";
|
||||||
|
hexpand: true;
|
||||||
|
}
|
||||||
|
Gtk.ScrolledWindow server_info {
|
||||||
|
width-request: 100;
|
||||||
|
Adw.PreferencesPage {
|
||||||
|
Adw.PreferencesGroup server_settings{
|
||||||
|
vexpand: true;
|
||||||
|
valign: center;
|
||||||
|
title: "Server Information";
|
||||||
|
description: "The information the server published on connection";
|
||||||
|
}}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Gtk.Statusbar{Gtk.Label{
|
||||||
|
label: "Status";
|
||||||
|
}}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
12
gui/server_info_row.blp
Normal file
12
gui/server_info_row.blp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
|
||||||
|
Adw.ActionRow server_info_row {
|
||||||
|
title: "Server2";
|
||||||
|
|
||||||
|
|
||||||
|
Gtk.Label server_info_row_value{
|
||||||
|
label: "Stalwart";
|
||||||
|
}}
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<!-- Created with Cambalache 0.16.0 -->
|
|
||||||
<interface>
|
|
||||||
<!-- interface-name sieverman.ui -->
|
|
||||||
<!-- interface-authors Franz Dietrich -->
|
|
||||||
<requires lib="gtk" version="4.12"/>
|
|
||||||
<object class="GtkApplicationWindow" id="sieverman">
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkActionBar"/>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="baseline-child">0</property>
|
|
||||||
<property name="homogeneous">True</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="messages">
|
|
||||||
<property name="label">Loading</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkSpinner">
|
|
||||||
<property name="spinning">True</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="serverstatus">
|
|
||||||
<property name="label">Loading…</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkStatusbar"/>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
@ -1,36 +1,29 @@
|
|||||||
use log::{info, trace};
|
|
||||||
use sieverman::ConnectionInfo;
|
use sieverman::ConnectionInfo;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
use crate::protocol::BackToFront;
|
use crate::protocol::BackToFront;
|
||||||
|
|
||||||
pub(crate) async fn run(
|
pub(crate) async fn run(
|
||||||
to_frontend_tx: tokio::sync::mpsc::Sender<BackToFront>,
|
to_frontend_tx: tokio::sync::mpsc::Sender<BackToFront>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
trace!("Starting up sieverman…");
|
info!("Starting up sieverman…");
|
||||||
|
info!("Creating connection info");
|
||||||
let info = ConnectionInfo::new("teilgedanken.de", 4190);
|
let info = ConnectionInfo::new("teilgedanken.de", 4190);
|
||||||
let mut connected = info.connect().await.unwrap();
|
info!("connecting…");
|
||||||
info!("connected to the server");
|
let future_info = info.connect();
|
||||||
loop {
|
info!("waiting for the connection to be established");
|
||||||
match connected.read_introduction().await {
|
let mut connected = match future_info.await {
|
||||||
Ok(sieverman::IsComplete::Yes(c)) => {
|
Ok(v) => v,
|
||||||
connected = c;
|
Err(e) => {
|
||||||
break;
|
info!("Failed to connect: {:?}", e);
|
||||||
}
|
panic!("Something went wrong");
|
||||||
Ok(sieverman::IsComplete::No(c)) => {
|
}
|
||||||
trace!("Incomplete data waiting for some time…");
|
};
|
||||||
connected = c
|
|
||||||
}
|
info!("Fully read the introduction:");
|
||||||
Err(e) => return Err(anyhow::anyhow!("something went wrong: {}", e)),
|
|
||||||
};
|
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
|
||||||
connected.log_buffer().await;
|
|
||||||
}
|
|
||||||
trace!("Fully read the introduction:");
|
|
||||||
connected.log_buffer().await;
|
|
||||||
connected.log_server_settings().await;
|
|
||||||
to_frontend_tx
|
to_frontend_tx
|
||||||
.send(BackToFront::ServerConnected(
|
.send(BackToFront::ServerConnected(
|
||||||
connected.get_server_capabilities(),
|
connected.get_server_capabilities().clone(),
|
||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
use std::{cell::RefCell, fmt::Display, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use crate::__COMPILED_BLUEPRINT_MAP__;
|
||||||
use gtk4::{
|
use gtk4::{
|
||||||
glib,
|
glib,
|
||||||
prelude::{ApplicationExt, BoxExt, GtkWindowExt, WidgetExt},
|
prelude::{ApplicationExt, GtkWindowExt},
|
||||||
Application, ApplicationWindow, Builder, Label,
|
Application,
|
||||||
};
|
};
|
||||||
use log::trace;
|
use gtk_blueprint::get_blp;
|
||||||
|
use libadwaita::prelude::{PreferencesGroupExt, PreferencesRowExt};
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::protocol::BackToFront;
|
use crate::protocol::BackToFront;
|
||||||
|
|
||||||
@ -25,50 +28,30 @@ fn build_ui(
|
|||||||
app: >k4::Application,
|
app: >k4::Application,
|
||||||
from_backend_rx: Rc<RefCell<Option<tokio::sync::mpsc::Receiver<BackToFront>>>>,
|
from_backend_rx: Rc<RefCell<Option<tokio::sync::mpsc::Receiver<BackToFront>>>>,
|
||||||
) {
|
) {
|
||||||
let action_content_status = gtk4::Box::builder()
|
let builder = gtk4::Builder::new();
|
||||||
.orientation(gtk4::Orientation::Vertical)
|
builder
|
||||||
.spacing(5)
|
.add_from_string(get_blp!("gui/main_window.blp"))
|
||||||
.build();
|
.expect("Failed to parse blueprint");
|
||||||
let action = gtk4::ActionBar::new();
|
let main_window = builder
|
||||||
let status = gtk4::Statusbar::new();
|
.object::<libadwaita::ApplicationWindow>("window")
|
||||||
let main_log_server_info = gtk4::Box::builder()
|
.unwrap();
|
||||||
.orientation(gtk4::Orientation::Horizontal)
|
let prefrences_group = builder
|
||||||
.hexpand(true)
|
.object::<libadwaita::PreferencesGroup>("server_settings")
|
||||||
.vexpand(true)
|
.unwrap();
|
||||||
.halign(gtk4::Align::Fill)
|
main_window.set_application(Some(app));
|
||||||
.build();
|
|
||||||
action_content_status.append(&action);
|
|
||||||
action_content_status.append(&main_log_server_info);
|
|
||||||
action_content_status.append(&status);
|
|
||||||
let log = gtk4::Label::builder().label("Log").hexpand(true).build();
|
|
||||||
let server_info_content = gtk4::Label::builder().label("Server Info").build();
|
|
||||||
let server_info_container = gtk4::ScrolledWindow::builder()
|
|
||||||
.child(&server_info_content)
|
|
||||||
.width_request(400)
|
|
||||||
.build();
|
|
||||||
main_log_server_info.append(&log);
|
|
||||||
main_log_server_info.append(&server_info_container);
|
|
||||||
let main_window = gtk4::ApplicationWindow::builder()
|
|
||||||
.application(app)
|
|
||||||
.title("Sieverman")
|
|
||||||
.height_request(400)
|
|
||||||
.width_request(400)
|
|
||||||
.child(&action_content_status)
|
|
||||||
.build();
|
|
||||||
main_window.present();
|
|
||||||
|
|
||||||
let server_info = Rc::new(RefCell::new(server_info_content));
|
|
||||||
|
|
||||||
let future = {
|
let future = {
|
||||||
let mut data_event_receiver = from_backend_rx.take().expect("data_event_reciver");
|
let mut data_event_receiver = from_backend_rx.take().expect("data_event_reciver");
|
||||||
async move {
|
async move {
|
||||||
while let Some(event) = data_event_receiver.recv().await {
|
while let Some(event) = data_event_receiver.recv().await {
|
||||||
trace!("data event: {:?}", event);
|
|
||||||
match event {
|
match event {
|
||||||
BackToFront::ServerConnected(message) => {
|
BackToFront::ServerConnected(caps) => {
|
||||||
server_info
|
prefrences_group.add(&row_in_settings("Greeting", &caps.implementation));
|
||||||
.borrow_mut()
|
prefrences_group
|
||||||
.set_label(&format!("{:#?}", message));
|
.add(&row_in_settings("Authentication", &caps.sasl.join(",")));
|
||||||
|
prefrences_group
|
||||||
|
.add(&row_in_settings("Starttls", &caps.starttls.to_string()));
|
||||||
|
prefrences_group.add(&row_in_settings("Version", &caps.version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,4 +61,22 @@ fn build_ui(
|
|||||||
let c = glib::MainContext::default();
|
let c = glib::MainContext::default();
|
||||||
c.spawn_local(future);
|
c.spawn_local(future);
|
||||||
main_window.present();
|
main_window.present();
|
||||||
|
trace!("Window is visible");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn row_in_settings(name: &str, value: &str) -> libadwaita::ActionRow {
|
||||||
|
let builder = gtk4::Builder::new();
|
||||||
|
builder
|
||||||
|
.add_from_string(get_blp!("gui/server_info_row.blp"))
|
||||||
|
.expect("Failed to parse blueprint");
|
||||||
|
|
||||||
|
let row = builder
|
||||||
|
.object::<libadwaita::ActionRow>("server_info_row")
|
||||||
|
.unwrap();
|
||||||
|
row.set_title(name);
|
||||||
|
let label = builder
|
||||||
|
.object::<gtk4::Label>("server_info_row_value")
|
||||||
|
.unwrap();
|
||||||
|
label.set_label(value);
|
||||||
|
row
|
||||||
}
|
}
|
||||||
|
48
src/bin/old/bluep_test.rs
Normal file
48
src/bin/old/bluep_test.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use gtk4::prelude::{ApplicationExt, ApplicationExtManual, GtkWindowExt};
|
||||||
|
// We're using gtk-builder feature here
|
||||||
|
use gtk_blueprint::get_blp;
|
||||||
|
use libadwaita::prelude::PreferencesGroupExt;
|
||||||
|
|
||||||
|
gtk_blueprint::gen_blp_map!("gui");
|
||||||
|
fn main() {
|
||||||
|
gtk4::init().expect("GTK initialization failed");
|
||||||
|
libadwaita::init().expect("Adwaita initialization failed");
|
||||||
|
|
||||||
|
// Create app
|
||||||
|
let application = gtk4::Application::builder()
|
||||||
|
.application_id("de.teilgedanken.sieverman")
|
||||||
|
.build();
|
||||||
|
// Init app window and show it
|
||||||
|
application.connect_activate(|app| {
|
||||||
|
// You also can parse blueprint with Parser::parse
|
||||||
|
// and then use it in gtk4::Builder
|
||||||
|
let builder = gtk4::Builder::new();
|
||||||
|
builder
|
||||||
|
.add_from_string(get_blp!("gui/main_window.blp"))
|
||||||
|
.expect("Failed to parse blueprint");
|
||||||
|
|
||||||
|
let window = builder
|
||||||
|
.object::<libadwaita::ApplicationWindow>("window")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let settings: libadwaita::PreferencesGroup = builder
|
||||||
|
.object("server_settings")
|
||||||
|
.expect("get server settings");
|
||||||
|
for _ in 0..5 {
|
||||||
|
let builder = gtk4::Builder::new();
|
||||||
|
builder
|
||||||
|
.add_from_string(get_blp!("gui/headerbar.blp"))
|
||||||
|
.expect("Failed to parse blueprint");
|
||||||
|
let widget: libadwaita::PreferencesRow = builder
|
||||||
|
.object("server_info_row")
|
||||||
|
.expect("Couldn't get widget");
|
||||||
|
settings.add(&widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.set_application(Some(app));
|
||||||
|
window.present();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Run app
|
||||||
|
application.run();
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
use log::info;
|
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::is_not;
|
use nom::bytes::complete::is_not;
|
||||||
use nom::character::is_space;
|
use nom::character::is_space;
|
||||||
@ -12,6 +11,7 @@ use nom::{character, number};
|
|||||||
use sieverman::parser::parse_server_config;
|
use sieverman::parser::parse_server_config;
|
||||||
use sieverman::{Methods, ServerSettings};
|
use sieverman::{Methods, ServerSettings};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
env_logger::init();
|
env_logger::init();
|
@ -9,7 +9,6 @@
|
|||||||
/// that is sensible outside of example code.
|
/// that is sensible outside of example code.
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use log::{error, info, trace};
|
|
||||||
use managesieve::{Capability, MSResult, Response};
|
use managesieve::{Capability, MSResult, Response};
|
||||||
use nom::{error::ParseError, IResult};
|
use nom::{error::ParseError, IResult};
|
||||||
use sieverman::parser::parse_server_config;
|
use sieverman::parser::parse_server_config;
|
||||||
@ -23,6 +22,7 @@ use tokio_rustls::{
|
|||||||
rustls::{ClientConfig, KeyLogFile, RootCertStore},
|
rustls::{ClientConfig, KeyLogFile, RootCertStore},
|
||||||
TlsConnector,
|
TlsConnector,
|
||||||
};
|
};
|
||||||
|
use tracing::{error, info, trace};
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! parse_response {
|
macro_rules! parse_response {
|
@ -1,7 +1,7 @@
|
|||||||
use managesieve::Capability;
|
use managesieve::Capabilities;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub enum BackToFront {
|
pub enum BackToFront {
|
||||||
ServerConnected(Vec<Capability>),
|
ServerConnected(Capabilities),
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,27 @@
|
|||||||
mod backend;
|
mod backend;
|
||||||
mod gui;
|
mod gui;
|
||||||
pub mod protocol;
|
pub mod protocol;
|
||||||
use std::{cell::RefCell, rc::Rc, thread};
|
use std::{cell::RefCell, rc::Rc, thread, time::Duration};
|
||||||
|
|
||||||
use gtk4::{glib, prelude::ApplicationExtManual as _};
|
use gtk4::{glib, prelude::ApplicationExtManual as _};
|
||||||
|
use tracing::{info, trace};
|
||||||
|
|
||||||
|
gtk_blueprint::gen_blp_map!("gui");
|
||||||
|
|
||||||
fn main() -> glib::ExitCode {
|
fn main() -> glib::ExitCode {
|
||||||
env_logger::init();
|
console_subscriber::ConsoleLayer::builder()
|
||||||
|
// set how long the console will retain data from completed tasks
|
||||||
|
.retention(Duration::from_secs(60))
|
||||||
|
// set the address the server is bound to
|
||||||
|
.server_addr(([127, 0, 0, 1], 6669))
|
||||||
|
.init();
|
||||||
|
|
||||||
gtk4::init().expect("Failed to initialize GTK");
|
gtk4::init().expect("Failed to initialize GTK");
|
||||||
|
libadwaita::init().expect("Adwaita initialization failed");
|
||||||
|
|
||||||
let (to_frontent_tx, from_backend_rx) = tokio::sync::mpsc::channel(5);
|
let (to_frontent_tx, from_backend_rx) = tokio::sync::mpsc::channel(5);
|
||||||
let _handle = thread::spawn(move || {
|
let _handle = thread::spawn(move || {
|
||||||
|
info!("Running Backend");
|
||||||
tokio::runtime::Builder::new_current_thread()
|
tokio::runtime::Builder::new_current_thread()
|
||||||
.enable_io()
|
.enable_io()
|
||||||
.enable_time()
|
.enable_time()
|
||||||
@ -21,5 +33,8 @@ fn main() -> glib::ExitCode {
|
|||||||
|
|
||||||
let app = gui::main_window::get_app(Rc::new(RefCell::new(Some(from_backend_rx))));
|
let app = gui::main_window::get_app(Rc::new(RefCell::new(Some(from_backend_rx))));
|
||||||
|
|
||||||
app.run()
|
let res = app.run();
|
||||||
|
trace!("End");
|
||||||
|
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
95
src/lib.rs
95
src/lib.rs
@ -1,20 +1,18 @@
|
|||||||
use std::{any, net::SocketAddr, sync::Arc, time::Duration};
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
use log::{error, info, trace};
|
use managesieve::Capabilities;
|
||||||
use managesieve::Capability;
|
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{split, AsyncBufReadExt, BufReader, ReadHalf, WriteHalf},
|
io::{split, AsyncBufReadExt, BufReader, WriteHalf},
|
||||||
net::TcpStream,
|
net::TcpStream,
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
task::JoinHandle,
|
|
||||||
};
|
};
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
client::TlsStream,
|
client::TlsStream,
|
||||||
rustls::{ClientConfig, KeyLogFile, RootCertStore},
|
rustls::{ClientConfig, KeyLogFile, RootCertStore},
|
||||||
TlsConnector,
|
TlsConnector,
|
||||||
};
|
};
|
||||||
|
use tracing::{error, info, trace};
|
||||||
|
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
@ -32,6 +30,7 @@ impl ConnectionInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn connect(self) -> Result<ConnectionConnected, anyhow::Error> {
|
pub async fn connect(self) -> Result<ConnectionConnected, anyhow::Error> {
|
||||||
|
info!("connecting to the server");
|
||||||
trace!("Building Cert Store");
|
trace!("Building Cert Store");
|
||||||
let mut root_store = RootCertStore::empty();
|
let mut root_store = RootCertStore::empty();
|
||||||
root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
|
||||||
@ -48,11 +47,11 @@ impl ConnectionInfo {
|
|||||||
let domain = pki_types::ServerName::try_from(self.domain.clone())?.to_owned();
|
let domain = pki_types::ServerName::try_from(self.domain.clone())?.to_owned();
|
||||||
trace!("Attach the connector");
|
trace!("Attach the connector");
|
||||||
let stream = connector.connect(domain, stream).await?;
|
let stream = connector.connect(domain, stream).await?;
|
||||||
let (reader, mut writer) = split(stream);
|
let (reader, writer) = split(stream);
|
||||||
let buffer = Arc::new(Mutex::new(String::new()));
|
let buffer = Arc::new(Mutex::new(String::new()));
|
||||||
let spawned_buffer = buffer.clone();
|
let spawned_buffer = buffer.clone();
|
||||||
|
|
||||||
let join_handle = tokio::spawn(async move {
|
let _join_handle = tokio::spawn(async move {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let mut reader = BufReader::new(reader);
|
let mut reader = BufReader::new(reader);
|
||||||
loop {
|
loop {
|
||||||
@ -67,13 +66,36 @@ impl ConnectionInfo {
|
|||||||
}
|
}
|
||||||
buf.clear();
|
buf.clear();
|
||||||
};
|
};
|
||||||
|
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let caps = loop {
|
||||||
|
let mut buf = buffer.lock().await;
|
||||||
|
trace!("reading new input:\n{}", buf);
|
||||||
|
match managesieve::response_capability(&buf.to_string()) {
|
||||||
|
Ok((rest, caps, resp)) => match resp.tag {
|
||||||
|
managesieve::OkNoBye::Ok => {
|
||||||
|
buf.clear();
|
||||||
|
buf.push_str(rest);
|
||||||
|
info!("Read the introduction");
|
||||||
|
break caps;
|
||||||
|
}
|
||||||
|
managesieve::OkNoBye::No | managesieve::OkNoBye::Bye => {
|
||||||
|
trace!("Connection closed!");
|
||||||
|
//panic!("Invalid Response")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => trace!("(temporary) error: {}", e),
|
||||||
|
}
|
||||||
|
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||||
|
};
|
||||||
|
trace!("Capabilities read: {:#?}", &caps);
|
||||||
Ok(ConnectionConnected {
|
Ok(ConnectionConnected {
|
||||||
info: self,
|
info: self,
|
||||||
writer: Arc::new(writer), //server_settings: todo!(),
|
writer: Arc::new(writer),
|
||||||
buffer,
|
buffer,
|
||||||
server_settings: Vec::new(), //join_handle: Arc::new(join_handle),
|
server_settings: caps,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +107,7 @@ pub struct ConnectionConnected {
|
|||||||
writer: Arc<WriteHalf<TlsStream<TcpStream>>>,
|
writer: Arc<WriteHalf<TlsStream<TcpStream>>>,
|
||||||
buffer: Arc<Mutex<String>>,
|
buffer: Arc<Mutex<String>>,
|
||||||
//pub join_handle: Arc<JoinHandle<()>>,
|
//pub join_handle: Arc<JoinHandle<()>>,
|
||||||
server_settings: Vec<Capability>,
|
server_settings: Capabilities,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@ -95,7 +117,7 @@ pub enum ReadError {
|
|||||||
#[error("The data the server responded was invalid")]
|
#[error("The data the server responded was invalid")]
|
||||||
InvalidResponse(#[source] managesieve::Error),
|
InvalidResponse(#[source] managesieve::Error),
|
||||||
}
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum IsComplete<T> {
|
pub enum IsComplete<T> {
|
||||||
Yes(T),
|
Yes(T),
|
||||||
No(T),
|
No(T),
|
||||||
@ -103,11 +125,12 @@ pub enum IsComplete<T> {
|
|||||||
|
|
||||||
impl ConnectionConnected {
|
impl ConnectionConnected {
|
||||||
pub async fn log_buffer(&self) {
|
pub async fn log_buffer(&self) {
|
||||||
trace!("Buffer is: \n{}", self.buffer.lock().await)
|
info!("Buffer is: \n{}", self.buffer.lock().await)
|
||||||
}
|
}
|
||||||
pub async fn log_server_settings(&self) {
|
pub async fn log_server_settings(&self) {
|
||||||
trace!("Serversettings:\n{:?}", self.server_settings)
|
info!("Serversettings:\n{:?}", self.server_settings)
|
||||||
}
|
}
|
||||||
|
#[tracing::instrument(name = "gettin the intro")]
|
||||||
pub async fn read_introduction(self) -> Result<IsComplete<Self>, anyhow::Error> {
|
pub async fn read_introduction(self) -> Result<IsComplete<Self>, anyhow::Error> {
|
||||||
let Self {
|
let Self {
|
||||||
info,
|
info,
|
||||||
@ -116,12 +139,11 @@ impl ConnectionConnected {
|
|||||||
buffer,
|
buffer,
|
||||||
server_settings,
|
server_settings,
|
||||||
} = self;
|
} = self;
|
||||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||||
let mut bf = buffer.lock().await;
|
let mut bf = buffer.lock().await;
|
||||||
let bf_str = bf.clone();
|
let response = match managesieve::response_capability(&bf.to_string()) {
|
||||||
match managesieve::response_capability(&bf_str) {
|
|
||||||
Ok((rest, capability, response)) => {
|
Ok((rest, capability, response)) => {
|
||||||
trace!("{:?}", response);
|
info!("Successfully read the introduction {:?}", response);
|
||||||
bf.clear();
|
bf.clear();
|
||||||
bf.push_str(rest);
|
bf.push_str(rest);
|
||||||
drop(bf);
|
drop(bf);
|
||||||
@ -132,12 +154,15 @@ impl ConnectionConnected {
|
|||||||
server_settings: capability,
|
server_settings: capability,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Err(managesieve::Error::IncompleteResponse) => Ok(IsComplete::No(Self {
|
Err(managesieve::Error::IncompleteResponse) => {
|
||||||
info,
|
trace!("incomplete introduction");
|
||||||
writer,
|
Ok(IsComplete::No(Self {
|
||||||
buffer: buffer.clone(),
|
info,
|
||||||
server_settings,
|
writer,
|
||||||
})),
|
buffer: buffer.clone(),
|
||||||
|
server_settings,
|
||||||
|
}))
|
||||||
|
}
|
||||||
Err(managesieve::Error::InvalidResponse) => {
|
Err(managesieve::Error::InvalidResponse) => {
|
||||||
error!("invalid response");
|
error!("invalid response");
|
||||||
Err(managesieve::Error::InvalidResponse)?
|
Err(managesieve::Error::InvalidResponse)?
|
||||||
@ -146,18 +171,20 @@ impl ConnectionConnected {
|
|||||||
error!("invalid input");
|
error!("invalid input");
|
||||||
Err(managesieve::Error::InvalidResponse)?
|
Err(managesieve::Error::InvalidResponse)?
|
||||||
}
|
}
|
||||||
}
|
Err(managesieve::Error::MissingLine(line)) => {
|
||||||
}
|
error!("a capability line was missing: {:?}", line);
|
||||||
pub fn get_greeting(&self) -> Option<String> {
|
Err(managesieve::Error::InvalidResponse)?
|
||||||
for c in self.server_settings.iter() {
|
|
||||||
if let Capability::Implementation(s) = c {
|
|
||||||
return Some(s.clone());
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
None
|
|
||||||
|
response
|
||||||
}
|
}
|
||||||
pub fn get_server_capabilities(&self) -> Vec<Capability> {
|
|
||||||
self.server_settings.clone()
|
pub fn get_greeting(&self) -> String {
|
||||||
|
self.server_settings.implementation.to_string()
|
||||||
|
}
|
||||||
|
pub fn get_server_capabilities(&self) -> &Capabilities {
|
||||||
|
&self.server_settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use log::{info, trace};
|
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::is_not,
|
bytes::complete::is_not,
|
||||||
@ -11,6 +10,7 @@ use nom::{
|
|||||||
sequence::preceded,
|
sequence::preceded,
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{parser::utils::key_value, Methods, ServerSettings};
|
use crate::{parser::utils::key_value, Methods, ServerSettings};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user