Initial migration to MTP [Broken]

This commit is contained in:
Alex Emmet 2026-06-28 13:51:17 +02:00
commit da86bdaf5a
10 changed files with 693 additions and 563 deletions

2
.cargo/config.toml Normal file
View file

@ -0,0 +1,2 @@
[env]
MTP_TYPE_MAPS = { value = "type-maps.yaml", relative = true }

551
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -4,8 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
ttp-core = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-core" } mtp = { git = "https://git.methanium.net/methanium/mtp", features = ["host"] }
ttp-native = { git = "https://git.methanium.net/Tensamin/TTP.git", package = "ttp-native" }
actix-web = { version = "4.12.1", features = ["rustls-0_23"] } actix-web = { version = "4.12.1", features = ["rustls-0_23"] }
aes-gcm = "*" aes-gcm = "*"

View file

@ -2,12 +2,12 @@ use crate::log;
use crate::util::file_util::load_file_vec; use crate::util::file_util::load_file_vec;
use crate::util::logger::PrintType; use crate::util::logger::PrintType;
use dashmap::DashMap; use dashmap::DashMap;
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
use mtp::transport::{Host, Policy, Receiver, SendMode, Sender, host};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tokio::sync::futures;
use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue};
use ttp_native::{Host, Policy, Receiver, SendMode, Sender};
pub struct TauriConnection { pub struct TauriConnection {
pub user_id: i64, pub user_id: i64,
@ -20,7 +20,8 @@ pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error>> {
let cert_pem = load_file_vec("certs", "transport_cert.pem").expect("Error loading Pemfile"); let cert_pem = load_file_vec("certs", "transport_cert.pem").expect("Error loading Pemfile");
let key_pem = load_file_vec("certs", "transport_key.pem").expect("Error loading Keyfile"); let key_pem = load_file_vec("certs", "transport_key.pem").expect("Error loading Keyfile");
let mut host: Host = ttp_native::host( let mut host: Host = host(
IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
port, port,
cert_pem, cert_pem,
key_pem, key_pem,
@ -59,45 +60,41 @@ async fn handle_connection(sender: Sender, receiver: &mut Receiver) {
let sender = Arc::new(sender); let sender = Arc::new(sender);
while let Ok(cv) = receiver.receive().await { while let Ok(cv) = receiver.receive().await {
match cv.get_type() { if cv.is_type(CommunicationType::TauriIdentification) {
CommunicationType::tauri_identification => { let user_id = cv.get_data(DataType::UserId).as_number().unwrap_or(0) as i64;
let user_id = cv.get_data(DataTypes::user_id).as_number().unwrap_or(0); if user_id != 0 {
if user_id != 0 { current_user_id = user_id;
current_user_id = user_id; let conn = Arc::new(TauriConnection {
let conn = Arc::new(TauriConnection { user_id,
user_id, sender: sender.clone(),
sender: sender.clone(), });
});
TAURI_CONNECTIONS TAURI_CONNECTIONS
.entry(user_id) .entry(user_id)
.and_modify(|conns| { .and_modify(|conns| {
conns.retain(|c| !Arc::ptr_eq(&c.sender.handle(), &sender.handle())); conns.retain(|c| !Arc::ptr_eq(&c.sender.handle(), &sender.handle()));
conns.push(conn.clone()); conns.push(conn.clone());
}) })
.or_insert_with(|| vec![conn]); .or_insert_with(|| vec![conn]);
let response =
CommunicationValue::new(CommunicationType::success).with_id(cv.get_id());
if let Err(e) = sender.send(&response).await {
log!(
PrintType::General,
"Failed to send tauri success response: {}",
e
);
} else {
log!(user_id, PrintType::Client, "Tauri device registered");
}
}
}
CommunicationType::ping => {
let response = let response =
CommunicationValue::new(CommunicationType::pong).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::Success).with_id(cv.get_id());
if let Err(_) = sender.send(&response).await { if let Err(e) = sender.send(&response).await {
break; log!(
PrintType::General,
"Failed to send tauri success response: {}",
e
);
} else {
log!(user_id, PrintType::Client, "Tauri device registered");
} }
} }
_ => {} } else if cv.is_type(CommunicationType::Ping) {
let response =
CommunicationValue::new(CommunicationType::Pong).with_id(cv.get_id());
if let Err(_) = sender.send(&response).await {
break;
}
} }
} }
@ -116,8 +113,8 @@ pub async fn send_notification(user_id: i64, sender_id: i64) {
}; };
if let Some(conns) = conns_opt { if let Some(conns) = conns_opt {
let cv = CommunicationValue::new(CommunicationType::push_notification) let cv = CommunicationValue::new(CommunicationType::PushNotification)
.add_data(DataTypes::sender_id, DataValue::Number(sender_id)); .add_typed_default(DataType::SenderId, DataValue::SignedNumber(sender_id as i128));
let mut remove_needed = false; let mut remove_needed = false;
for conn in conns.iter() { for conn in conns.iter() {
@ -141,8 +138,8 @@ pub async fn remove_notification(user_id: i64, sender_id: i64) {
}; };
if let Some(conns) = conns_opt { if let Some(conns) = conns_opt {
let cv = CommunicationValue::new(CommunicationType::read_notification) let cv = CommunicationValue::new(CommunicationType::ReadNotification)
.add_data(DataTypes::sender_id, DataValue::Number(sender_id)); .add_typed_default(DataType::SenderId, DataValue::SignedNumber(sender_id as i128));
let mut remove_needed = false; let mut remove_needed = false;
for conn in conns.iter() { for conn in conns.iter() {

View file

@ -28,7 +28,7 @@ pub async fn start(port: u16) -> anyhow::Result<()> {
.with_no_client_auth() .with_no_client_auth()
.with_single_cert(cert_chain, key)?; .with_single_cert(cert_chain, key)?;
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; config.alpn_protocols = vec![b"h2".to_vec(), b"hmtp/1.1".to_vec()];
let bind_addr = std::env::var("BIND_ADDRESS").unwrap_or_else(|_| "0.0.0.0".to_string()); let bind_addr = std::env::var("BIND_ADDRESS").unwrap_or_else(|_| "0.0.0.0".to_string());
let addr = format!("{}:{}", bind_addr, port); let addr = format!("{}:{}", bind_addr, port);

View file

@ -11,7 +11,7 @@ pub async fn add_short_link(long: &str) -> Result<String, ()> {
LINKS.insert(raw.clone(), long.to_string()); LINKS.insert(raw.clone(), long.to_string());
Ok(format!( Ok(format!(
"https://omega.tensamin.net/direct/{}", "hmtps://omega.tensamin.net/direct/{}",
format_with_dashes(&raw) format_with_dashes(&raw)
)) ))
} }

View file

@ -11,6 +11,9 @@ use crate::{
}; };
use base64::{Engine as _, engine::general_purpose::STANDARD}; use base64::{Engine as _, engine::general_purpose::STANDARD};
use dashmap::DashMap; use dashmap::DashMap;
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
use mtp::transport::{Host, Policy, Receiver, SendMode, Sender, host};
use std::net::{IpAddr, Ipv4Addr};
use rand::{Rng, distributions::Alphanumeric}; use rand::{Rng, distributions::Alphanumeric};
use std::{ use std::{
sync::Arc, sync::Arc,
@ -20,8 +23,6 @@ use tokio::{
sync::{Mutex, RwLock}, sync::{Mutex, RwLock},
time::interval, time::interval,
}; };
use ttp_core::{CommunicationType, CommunicationValue, DataTypes, DataValue};
use ttp_native::{Host, Policy, Receiver, SendMode, Sender};
use x448::PublicKey; use x448::PublicKey;
// ============================================================================ // ============================================================================
@ -92,7 +93,7 @@ impl AuthState {
} }
// ============================================================================ // ============================================================================
// Omikron Connection (ttp/QUIC-based) // Omikron Connection (mtp/QUIC-based)
// ============================================================================ // ============================================================================
pub struct OmikronConnection { pub struct OmikronConnection {
@ -180,7 +181,7 @@ impl OmikronConnection {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
async fn process_message(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn process_message(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
if !cv.is_type(CommunicationType::pong) && !cv.is_type(CommunicationType::ping) { if !cv.is_type(CommunicationType::Pong) && !cv.is_type(CommunicationType::Ping) {
log_cv_in!(PrintType::Omikron, &cv); log_cv_in!(PrintType::Omikron, &cv);
} }
@ -193,7 +194,7 @@ impl OmikronConnection {
} }
// Handle ping regardless of auth state // Handle ping regardless of auth state
if cv.is_type(CommunicationType::ping) { if cv.is_type(CommunicationType::Ping) {
return self.handle_ping(cv).await; return self.handle_ping(cv).await;
} }
@ -213,22 +214,22 @@ impl OmikronConnection {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
async fn handle_unauthenticated(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_unauthenticated(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
if !cv.is_type(CommunicationType::identification) { if !cv.is_type(CommunicationType::Identification) {
let _ = self let _ = self
.send_error_response(cv.get_id(), CommunicationType::error_not_authenticated) .send_error_response(cv.get_id(), CommunicationType::ErrorNotAuthenticated)
.await; .await;
return Err(OmikronError::NotAuthenticated); return Err(OmikronError::NotAuthenticated);
} }
// Extract omikron ID // Extract omikron ID
let omikron_id = cv let omikron_id = cv
.get_data(DataTypes::omikron_id) .get_data(DataType::OmikronId)
.as_number() .as_number()
.ok_or(OmikronError::InvalidResponse)?; .ok_or(OmikronError::InvalidResponse)?;
log!("Omikron {:?} connected", omikron_id); log!("Omikron {:?} connected", omikron_id);
// Lookup omikron in database // Lookup omikron in database
let (public_key, _) = get_omikron_by_id(omikron_id) let (public_key, _) = get_omikron_by_id(omikron_id as i64)
.await .await
.map_err(|e| OmikronError::Sql(e.to_string()))?; .map_err(|e| OmikronError::Sql(e.to_string()))?;
@ -261,7 +262,9 @@ impl OmikronConnection {
log!("Stored Pubkey"); log!("Stored Pubkey");
*self.state.write().await = AuthState::Identified { omikron_id }; *self.state.write().await = AuthState::Identified {
omikron_id: omikron_id as i64,
};
log!("Stored State"); log!("Stored State");
@ -279,28 +282,28 @@ impl OmikronConnection {
log!("Encrypted Challenge"); log!("Encrypted Challenge");
// Send challenge response // Send challenge response
let response = CommunicationValue::new(CommunicationType::challenge) let response = CommunicationValue::new(CommunicationType::Challenge)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data( .add_typed_default(
DataTypes::public_key, DataType::PublicKey,
DataValue::Str(STANDARD.encode(get_public_key().as_bytes())), DataValue::Str(STANDARD.encode(get_public_key().as_bytes())),
) )
.add_data(DataTypes::challenge, DataValue::Str(encrypted)); .add_typed_default(DataType::Content, DataValue::Str(encrypted));
log!("Sending Challenge"); log!("Sending Challenge");
self.send(&response).await self.send(&response).await
} }
async fn handle_identified(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_identified(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
if !cv.is_type(CommunicationType::challenge_response) { if !cv.is_type(CommunicationType::ChallengeResponse) {
let _ = self let _ = self
.send_error_response(cv.get_id(), CommunicationType::error_not_authenticated) .send_error_response(cv.get_id(), CommunicationType::ErrorNotAuthenticated)
.await; .await;
return Err(OmikronError::NotAuthenticated); return Err(OmikronError::NotAuthenticated);
} }
let client_response = cv let client_response = cv
.get_data(DataTypes::challenge) .get_data(DataType::Content)
.as_str() .as_str()
.ok_or(OmikronError::InvalidResponse)?; .ok_or(OmikronError::InvalidResponse)?;
@ -312,16 +315,16 @@ impl OmikronConnection {
omikron_manager::add_omikron(self.clone()).await; omikron_manager::add_omikron(self.clone()).await;
let response = CommunicationValue::new(CommunicationType::identification_response) let response = CommunicationValue::new(CommunicationType::IdentificationResponse)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::accepted, DataValue::Bool(true)); .add_typed_default(DataType::Accepted, DataValue::Bool(true));
self.clone().send(&response).await?; self.clone().send(&response).await?;
log_in!(omikron_id, PrintType::Omega, "Omikron authenticated"); log_in!(omikron_id, PrintType::Omega, "Omikron authenticated");
Ok(()) Ok(())
} else { } else {
let _ = self let _ = self
.send_error_response(cv.get_id(), CommunicationType::error_invalid_challenge) .send_error_response(cv.get_id(), CommunicationType::ErrorInvalidChallenge)
.await; .await;
Err(OmikronError::AuthenticationFailed) Err(OmikronError::AuthenticationFailed)
} }
@ -336,52 +339,53 @@ impl OmikronConnection {
cv: CommunicationValue, cv: CommunicationValue,
omikron_id: i64, omikron_id: i64,
) -> OmikronResult<()> { ) -> OmikronResult<()> {
match cv.get_type() { let comm_type = cv.get_comm_type_enum();
match comm_type {
// Link shortening // Link shortening
CommunicationType::shorten_link => self.handle_shorten_link(cv).await, Some(CommunicationType::ShortenLink) => self.handle_shorten_link(cv).await,
// Online status tracking // Online status tracking
CommunicationType::user_connected => { Some(CommunicationType::UserConnected) => {
self.handle_user_connected(cv, omikron_id).await; self.handle_user_connected(cv, omikron_id).await;
Ok(()) Ok(())
} }
CommunicationType::user_disconnected => { Some(CommunicationType::UserDisconnected) => {
self.handle_user_disconnected(cv, omikron_id).await; self.handle_user_disconnected(cv, omikron_id).await;
Ok(()) Ok(())
} }
CommunicationType::iota_connected => { Some(CommunicationType::IotaConnected) => {
self.handle_iota_connected(cv, omikron_id).await; self.handle_iota_connected(cv, omikron_id).await;
Ok(()) Ok(())
} }
CommunicationType::iota_disconnected => { Some(CommunicationType::IotaDisconnected) => {
self.handle_iota_disconnected(cv, omikron_id).await; self.handle_iota_disconnected(cv, omikron_id).await;
Ok(()) Ok(())
} }
CommunicationType::sync_client_iota_status => { Some(CommunicationType::SyncClientIotaStatus) => {
self.handle_sync_status(cv, omikron_id).await; self.handle_sync_status(cv, omikron_id).await;
Ok(()) Ok(())
} }
CommunicationType::get_user_data => self.handle_get_user_data(cv).await, Some(CommunicationType::GetUserData) => self.handle_get_user_data(cv).await,
CommunicationType::get_iota_data => self.handle_get_iota_data(cv).await, Some(CommunicationType::GetIotaData) => self.handle_get_iota_data(cv).await,
CommunicationType::get_register => self.handle_get_register(cv).await, Some(CommunicationType::GetRegister) => self.handle_get_register(cv).await,
CommunicationType::complete_register_iota => { Some(CommunicationType::CompleteRegisterIota) => {
self.handle_complete_register_iota(cv).await self.handle_complete_register_iota(cv).await
} }
CommunicationType::complete_register_user => { Some(CommunicationType::CompleteRegisterUser) => {
self.handle_complete_register_user(cv).await self.handle_complete_register_user(cv).await
} }
CommunicationType::change_user_data => self.handle_change_user_data(cv).await, Some(CommunicationType::ChangeUserData) => self.handle_change_user_data(cv).await,
CommunicationType::change_iota_data => self.handle_change_iota_data(cv).await, Some(CommunicationType::ChangeIotaData) => self.handle_change_iota_data(cv).await,
CommunicationType::delete_user => self.handle_delete_user(cv).await, Some(CommunicationType::DeleteUser) => self.handle_delete_user(cv).await,
CommunicationType::delete_iota => self.handle_delete_iota(cv).await, Some(CommunicationType::DeleteIota) => self.handle_delete_iota(cv).await,
CommunicationType::get_notifications => self.handle_get_notifications(cv).await, Some(CommunicationType::GetNotifications) => self.handle_get_notifications(cv).await,
CommunicationType::read_notification => self.handle_read_notification(cv).await, Some(CommunicationType::ReadNotification) => self.handle_read_notification(cv).await,
CommunicationType::push_notification => self.handle_push_notification(cv).await, Some(CommunicationType::PushNotification) => self.handle_push_notification(cv).await,
CommunicationType::get_states => self.handle_get_states(cv).await, Some(CommunicationType::GetStates) => self.handle_get_states(cv).await,
_ => { _ => {
log_err!( log_err!(
@ -401,7 +405,7 @@ impl OmikronConnection {
async fn handle_shorten_link(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_shorten_link(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
let link = cv let link = cv
.get_data(DataTypes::link) .get_data(DataType::Link)
.as_str() .as_str()
.ok_or(OmikronError::InvalidResponse)?; .ok_or(OmikronError::InvalidResponse)?;
@ -409,32 +413,28 @@ impl OmikronConnection {
.await .await
.map_err(|_| OmikronError::Sql("Shortend link Error".to_string()))?; .map_err(|_| OmikronError::Sql("Shortend link Error".to_string()))?;
let response = CommunicationValue::new(CommunicationType::shorten_link) let response = CommunicationValue::new(CommunicationType::ShortenLink)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::link, DataValue::Str(short)); .add_typed_default(DataType::Link, DataValue::Str(short));
self.send(&response).await self.send(&response).await
} }
async fn handle_user_connected(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) { async fn handle_user_connected(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) {
log_in!(PrintType::Omega, "User connected"); log_in!(PrintType::Omega, "User connected");
if let Some(user_id) = cv.get_data(DataTypes::user_id).as_number() { if let Some(user_id) = cv.get_data(DataType::UserId).as_number() {
let status = cv let status = cv
.get_data(DataTypes::user_state) .get_data(DataType::UserState)
.as_str() .as_str()
.and_then(|s| UserStatus::from_str(s)) .and_then(|s| UserStatus::from_str(s))
.unwrap_or(UserStatus::user_online); .unwrap_or(UserStatus::user_online);
user_online_tracker::track_user_status( user_online_tracker::track_user_status(user_id.try_into().unwrap(), status, omikron_id);
user_id.try_into().unwrap(),
status,
omikron_id,
);
} }
} }
async fn handle_user_disconnected(self: Arc<Self>, cv: CommunicationValue, _omikron_id: i64) { async fn handle_user_disconnected(self: Arc<Self>, cv: CommunicationValue, _omikron_id: i64) {
log_in!(PrintType::Omega, "User disconnected"); log_in!(PrintType::Omega, "User disconnected");
if let Some(user_id) = cv.get_data(DataTypes::user_id).as_number() { if let Some(user_id) = cv.get_data(DataType::UserId).as_number() {
if let Some(status) = user_online_tracker::get_user_status(user_id as i64) { if let Some(status) = user_online_tracker::get_user_status(user_id as i64) {
user_online_tracker::track_user_status( user_online_tracker::track_user_status(
user_id as i64, user_id as i64,
@ -447,7 +447,7 @@ impl OmikronConnection {
async fn handle_iota_connected(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) { async fn handle_iota_connected(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) {
log_in!(PrintType::Omega, "IOTA connected"); log_in!(PrintType::Omega, "IOTA connected");
let iota_id = match cv.get_data(DataTypes::iota_id).as_number() { let iota_id = match cv.get_data(DataType::IotaId).as_number() {
Some(id) => id as i64, Some(id) => id as i64,
None => return, None => return,
}; };
@ -456,7 +456,7 @@ impl OmikronConnection {
let mut user_ids = Vec::new(); let mut user_ids = Vec::new();
if let Ok(users) = sql::get_users_by_iota_id(iota_id.try_into().unwrap()).await { if let Ok(users) = sql::get_users_by_iota_id(iota_id.try_into().unwrap()).await {
for (user_id, _, _, _, _, _, _, _, _, _, _, _) in users { for (user_id, _, _, _, _, _, _, _, _, _, _, _) in users {
user_ids.push(DataValue::Number(user_id.try_into().unwrap())); user_ids.push(DataValue::SignedNumber(user_id.try_into().unwrap()));
user_online_tracker::track_user_status( user_online_tracker::track_user_status(
user_id.try_into().unwrap(), user_id.try_into().unwrap(),
UserStatus::user_offline, UserStatus::user_offline,
@ -467,16 +467,16 @@ impl OmikronConnection {
log_in!(PrintType::General, "SQL error loading users for IOTA"); log_in!(PrintType::General, "SQL error loading users for IOTA");
} }
let response = CommunicationValue::new(CommunicationType::iota_user_data) let response = CommunicationValue::new(CommunicationType::IotaUserData)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::user_ids, DataValue::Array(user_ids)); .add_typed_default(DataType::UserIds, DataValue::Array(user_ids));
let _ = self.send(&response).await; let _ = self.send(&response).await;
} }
async fn handle_iota_disconnected(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) { async fn handle_iota_disconnected(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) {
log_in!(PrintType::Omega, "IOTA disconnected"); log_in!(PrintType::Omega, "IOTA disconnected");
let iota_id = match cv.get_data(DataTypes::iota_id).as_number() { let iota_id = match cv.get_data(DataType::IotaId).as_number() {
Some(id) => id as i64, Some(id) => id as i64,
None => return, None => return,
}; };
@ -490,11 +490,11 @@ impl OmikronConnection {
} }
async fn handle_sync_status(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) { async fn handle_sync_status(self: Arc<Self>, cv: CommunicationValue, omikron_id: i64) {
if let DataValue::Array(user_ids) = cv.get_data(DataTypes::user_ids) { if let DataValue::Array(user_ids) = cv.get_data(DataType::UserIds) {
for user_id_val in user_ids { for user_id_val in user_ids {
if let DataValue::Number(user_id) = user_id_val { if let DataValue::SignedNumber(user_id) = user_id_val {
user_online_tracker::track_user_status( user_online_tracker::track_user_status(
*user_id, *user_id as i64,
UserStatus::user_offline, UserStatus::user_offline,
omikron_id, omikron_id,
); );
@ -502,10 +502,10 @@ impl OmikronConnection {
} }
} }
if let DataValue::Array(iota_ids) = cv.get_data(DataTypes::iota_ids) { if let DataValue::Array(iota_ids) = cv.get_data(DataType::IotaIds) {
for iota_id_val in iota_ids { for iota_id_val in iota_ids {
if let DataValue::Number(iota_id) = iota_id_val { if let DataValue::SignedNumber(iota_id) = iota_id_val {
user_online_tracker::track_iota_connection(*iota_id, omikron_id, true); user_online_tracker::track_iota_connection(*iota_id as i64, omikron_id, true);
} }
} }
} }
@ -513,7 +513,7 @@ impl OmikronConnection {
async fn handle_get_user_data(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_get_user_data(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
// Try by user_id first // Try by user_id first
if let Some(user_id) = cv.get_data(DataTypes::user_id).as_number() { if let Some(user_id) = cv.get_data(DataType::UserId).as_number() {
if let Ok(user_data) = get_by_user_id(user_id as i64).await { if let Ok(user_data) = get_by_user_id(user_id as i64).await {
let response = self let response = self
.clone() .clone()
@ -524,7 +524,7 @@ impl OmikronConnection {
} }
// Try by username // Try by username
if let Some(username) = cv.get_data(DataTypes::username).as_str() { if let Some(username) = cv.get_data(DataType::Username).as_str() {
if let Ok(user_data) = get_by_username(username).await { if let Ok(user_data) = get_by_username(username).await {
let response = self let response = self
.clone() .clone()
@ -536,7 +536,7 @@ impl OmikronConnection {
// Not found // Not found
let response = let response =
CommunicationValue::new(CommunicationType::error_not_found).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::ErrorNotFound).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
@ -573,28 +573,28 @@ impl OmikronConnection {
_, _,
) = user; ) = user;
let mut response = CommunicationValue::new(CommunicationType::get_user_data) let mut response = CommunicationValue::new(CommunicationType::GetUserData)
.with_id(msg_id) .with_id(msg_id)
.add_data(DataTypes::username, DataValue::Str(username.clone())) .add_typed_default(DataType::Username, DataValue::Str(username.clone()))
.add_data(DataTypes::public_key, DataValue::Str(public_key)) .add_typed_default(DataType::PublicKey, DataValue::Str(public_key))
.add_data(DataTypes::user_id, DataValue::Number(id)) .add_typed_default(DataType::UserId, DataValue::SignedNumber(id.into()))
.add_data(DataTypes::iota_id, DataValue::Number(iota_id)) .add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id.into()))
.add_data(DataTypes::sub_level, DataValue::Number(sub_level as i64)) .add_typed_default(DataType::SubLevel, DataValue::SignedNumber(sub_level as i128))
.add_data(DataTypes::sub_end, DataValue::Number(sub_end)); .add_typed_default(DataType::SubEnd, DataValue::SignedNumber(sub_end.into()));
// Display name (fallback to username) // Display name (fallback to username)
let display_name = display.filter(|d| !d.is_empty()).unwrap_or(username); let display_name = display.filter(|d| !d.is_empty()).unwrap_or(username);
response = response.add_data(DataTypes::display, DataValue::Str(display_name)); response = response.add_typed_default(DataType::Display, DataValue::Str(display_name));
// Optional fields // Optional fields
if let Some(s) = status.filter(|s| !s.is_empty()) { if let Some(s) = status.filter(|s| !s.is_empty()) {
response = response.add_data(DataTypes::status, DataValue::Str(s)); response = response.add_typed_default(DataType::Status, DataValue::Str(s));
} }
if let Some(a) = about.filter(|a| !a.is_empty()) { if let Some(a) = about.filter(|a| !a.is_empty()) {
response = response.add_data(DataTypes::about, DataValue::Str(a)); response = response.add_typed_default(DataType::About, DataValue::Str(a));
} }
if let Some(av) = avatar { if let Some(av) = avatar {
response = response.add_data(DataTypes::avatar, DataValue::Str(STANDARD.encode(av))); response = response.add_typed_default(DataType::Avatar, DataValue::Str(STANDARD.encode(av)));
} }
// Online status // Online status
@ -608,24 +608,24 @@ impl OmikronConnection {
} else { } else {
us.connection_type.clone() us.connection_type.clone()
}; };
response = response.add_data( response = response.add_typed_default(
DataTypes::online_status, DataType::OnlineStatus,
DataValue::Str(display_status.to_string()), DataValue::Str(display_status.to_string()),
); );
response = response.add_data(DataTypes::omikron_id, DataValue::Number(us.omikron_id)); response = response.add_typed_default(DataType::OmikronId, DataValue::SignedNumber(us.omikron_id.into()));
} else { } else {
response = response.add_data( response = response.add_typed_default(
DataTypes::online_status, DataType::OnlineStatus,
DataValue::Str(UserStatus::iota_offline.to_string()), DataValue::Str(UserStatus::iota_offline.to_string()),
); );
} }
response = response.add_data( response = response.add_typed_default(
DataTypes::omikron_connections, DataType::OmikronConnections,
DataValue::Array( DataValue::Array(
iota_connections iota_connections
.into_iter() .into_iter()
.map(DataValue::Number) .map(|id| DataValue::SignedNumber(id as i128))
.collect(), .collect(),
), ),
); );
@ -635,7 +635,7 @@ impl OmikronConnection {
async fn handle_get_iota_data(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_get_iota_data(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
// Try by iota_id // Try by iota_id
if let Some(iota_id) = cv.get_data(DataTypes::iota_id).as_number() { if let Some(iota_id) = cv.get_data(DataType::IotaId).as_number() {
if let Ok((iota_id, public_key)) = get_iota_by_id(iota_id as i64).await { if let Ok((iota_id, public_key)) = get_iota_by_id(iota_id as i64).await {
let response = self let response = self
.clone() .clone()
@ -646,7 +646,7 @@ impl OmikronConnection {
} }
// Try by user_id // Try by user_id
if let Some(user_id) = cv.get_data(DataTypes::user_id).as_number() { if let Some(user_id) = cv.get_data(DataType::UserId).as_number() {
if let Ok((_, iota_id, _, _, _, _, _, _, _, _, _, _)) = if let Ok((_, iota_id, _, _, _, _, _, _, _, _, _, _)) =
get_by_user_id(user_id as i64).await get_by_user_id(user_id as i64).await
{ {
@ -667,7 +667,7 @@ impl OmikronConnection {
} }
// Try by username // Try by username
if let Some(username) = cv.get_data(DataTypes::username).as_str() { if let Some(username) = cv.get_data(DataType::Username).as_str() {
if let Ok((user_id, iota_id, _, _, _, _, _, _, _, _, _, _)) = if let Ok((user_id, iota_id, _, _, _, _, _, _, _, _, _, _)) =
get_by_username(username).await get_by_username(username).await
{ {
@ -688,7 +688,7 @@ impl OmikronConnection {
} }
let response = let response =
CommunicationValue::new(CommunicationType::error_not_found).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::ErrorNotFound).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
@ -700,27 +700,27 @@ impl OmikronConnection {
user_id: Option<i64>, user_id: Option<i64>,
username: Option<String>, username: Option<String>,
) -> CommunicationValue { ) -> CommunicationValue {
let mut response = CommunicationValue::new(CommunicationType::get_iota_data) let mut response = CommunicationValue::new(CommunicationType::GetIotaData)
.with_id(msg_id) .with_id(msg_id)
.add_data(DataTypes::public_key, DataValue::Str(public_key)) .add_typed_default(DataType::PublicKey, DataValue::Str(public_key))
.add_data(DataTypes::iota_id, DataValue::Number(iota_id)); .add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id.into()));
if let Some(uid) = user_id { if let Some(uid) = user_id {
response = response.add_data(DataTypes::user_id, DataValue::Number(uid)); response = response.add_typed_default(DataType::UserId, DataValue::SignedNumber(uid.into()));
} }
if let Some(uname) = username { if let Some(uname) = username {
response = response.add_data(DataTypes::username, DataValue::Str(uname)); response = response.add_typed_default(DataType::Username, DataValue::Str(uname));
} }
let iota_connections = let iota_connections =
user_online_tracker::get_iota_omikron_connections(iota_id).unwrap_or_default(); user_online_tracker::get_iota_omikron_connections(iota_id).unwrap_or_default();
response.add_data( response.add_typed_default(
DataTypes::omikron_connections, DataType::OmikronConnections,
DataValue::Array( DataValue::Array(
iota_connections iota_connections
.into_iter() .into_iter()
.map(DataValue::Number) .map(|id| DataValue::SignedNumber(id as i128))
.collect(), .collect(),
), ),
) )
@ -728,9 +728,9 @@ impl OmikronConnection {
async fn handle_get_register(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_get_register(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
let register_id = sql::get_register_id().await; let register_id = sql::get_register_id().await;
let response = CommunicationValue::new(CommunicationType::get_register) let response = CommunicationValue::new(CommunicationType::GetRegister)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::user_id, DataValue::Number(register_id as i64)); .add_typed_default(DataType::UserId, DataValue::SignedNumber(register_id as i128));
self.send(&response).await self.send(&response).await
} }
@ -738,24 +738,21 @@ impl OmikronConnection {
self: Arc<Self>, self: Arc<Self>,
cv: CommunicationValue, cv: CommunicationValue,
) -> OmikronResult<()> { ) -> OmikronResult<()> {
let iota_id_opt = cv let iota_id_opt = cv.get_data(DataType::IotaId).as_number().map(|n| n as i64);
.get_data(DataTypes::iota_id)
.as_number()
.map(|n| n as i64);
if let Some(public_key) = cv.get_data(DataTypes::public_key).as_str() { if let Some(public_key) = cv.get_data(DataType::PublicKey).as_str() {
if let Some(iota_id) = iota_id_opt { if let Some(iota_id) = iota_id_opt {
// Register existing IOTA // Register existing IOTA
match sql::register_complete_iota(iota_id, public_key.to_string()).await { match sql::register_complete_iota(iota_id, public_key.to_string()).await {
Ok(_) => { Ok(_) => {
let response = CommunicationValue::new(CommunicationType::success) let response = CommunicationValue::new(CommunicationType::Success)
.with_id(cv.get_id()); .with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
Err(e) => { Err(e) => {
let response = CommunicationValue::new(CommunicationType::error_internal) let response = CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(e.to_string())); .add_typed_default(DataType::ErrorType, DataValue::Str(e.to_string()));
self.send(&response).await self.send(&response).await
} }
} }
@ -764,21 +761,21 @@ impl OmikronConnection {
match sql::create_new_iota(public_key.to_string()).await { match sql::create_new_iota(public_key.to_string()).await {
Ok(new_iota_id) => { Ok(new_iota_id) => {
let response = let response =
CommunicationValue::new(CommunicationType::complete_register_iota) CommunicationValue::new(CommunicationType::CompleteRegisterIota)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::iota_id, DataValue::Number(new_iota_id)); .add_typed_default(DataType::IotaId, DataValue::SignedNumber(new_iota_id.into()));
self.send(&response).await self.send(&response).await
} }
Err(e) => { Err(e) => {
let response = CommunicationValue::new(CommunicationType::error_internal) let response = CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(e.to_string())); .add_typed_default(DataType::ErrorType, DataValue::Str(e.to_string()));
self.send(&response).await self.send(&response).await
} }
} }
} }
} else { } else {
self.send_error_response(cv.get_id(), CommunicationType::error_invalid_data) self.send_error_response(cv.get_id(), CommunicationType::ErrorInvalidData)
.await .await
} }
} }
@ -787,21 +784,18 @@ impl OmikronConnection {
self: Arc<Self>, self: Arc<Self>,
cv: CommunicationValue, cv: CommunicationValue,
) -> OmikronResult<()> { ) -> OmikronResult<()> {
let user_id = cv let user_id = cv.get_data(DataType::UserId).as_number().map(|n| n as i64);
.get_data(DataTypes::user_id)
.as_number()
.map(|n| n as i64);
let username = cv let username = cv
.get_data(DataTypes::username) .get_data(DataType::Username)
.as_str() .as_str()
.map(|s| s.to_string()); .map(|s| s.to_string());
let public_key = cv let public_key = cv
.get_data(DataTypes::public_key) .get_data(DataType::PublicKey)
.as_str() .as_str()
.map(|s| s.to_string()); .map(|s| s.to_string());
let iota_id = cv.get_sender(); let iota_id = cv.get_sender();
let reset_token = cv let reset_token = cv
.get_data(DataTypes::reset_token) .get_data(DataType::ResetToken)
.as_str() .as_str()
.map(|s| s.to_string()); .map(|s| s.to_string());
@ -811,18 +805,18 @@ impl OmikronConnection {
match sql::register_complete_user(uid, uname, pk, iota_id as i64, rt).await { match sql::register_complete_user(uid, uname, pk, iota_id as i64, rt).await {
Ok(_) => { Ok(_) => {
let response = let response =
CommunicationValue::new(CommunicationType::success).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::Success).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
Err(e) => { Err(e) => {
let response = CommunicationValue::new(CommunicationType::error_internal) let response = CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(e.to_string())); .add_typed_default(DataType::ErrorType, DataValue::Str(e.to_string()));
self.send(&response).await self.send(&response).await
} }
} }
} else { } else {
self.send_error_response(cv.get_id(), CommunicationType::error_invalid_data) self.send_error_response(cv.get_id(), CommunicationType::ErrorInvalidData)
.await .await
} }
} }
@ -833,39 +827,39 @@ impl OmikronConnection {
let mut error_message = String::new(); let mut error_message = String::new();
// Process each field // Process each field
if let Some(username) = cv.get_data(DataTypes::username).as_str() { if let Some(username) = cv.get_data(DataType::Username).as_str() {
if let Err(e) = sql::change_username(user_id, username.to_string()).await { if let Err(e) = sql::change_username(user_id, username.to_string()).await {
success = false; success = false;
error_message = e.to_string(); error_message = e.to_string();
} }
} }
if let Some(display) = cv.get_data(DataTypes::display).as_str() { if let Some(display) = cv.get_data(DataType::Display).as_str() {
if let Err(e) = sql::change_display_name(user_id, display.to_string()).await { if let Err(e) = sql::change_display_name(user_id, display.to_string()).await {
success = false; success = false;
error_message = e.to_string(); error_message = e.to_string();
} }
} }
if let Some(avatar) = cv.get_data(DataTypes::avatar).as_str() { if let Some(avatar) = cv.get_data(DataType::Avatar).as_str() {
if let Err(e) = sql::change_avatar(user_id, avatar.to_string()).await { if let Err(e) = sql::change_avatar(user_id, avatar.to_string()).await {
success = false; success = false;
error_message = e.to_string(); error_message = e.to_string();
} }
} }
if let Some(about) = cv.get_data(DataTypes::about).as_str() { if let Some(about) = cv.get_data(DataType::About).as_str() {
if let Err(e) = sql::change_about(user_id, about.to_string()).await { if let Err(e) = sql::change_about(user_id, about.to_string()).await {
success = false; success = false;
error_message = e.to_string(); error_message = e.to_string();
} }
} }
if let Some(status) = cv.get_data(DataTypes::status).as_str() { if let Some(status) = cv.get_data(DataType::Status).as_str() {
if let Err(e) = sql::change_status(user_id, status.to_string()).await { if let Err(e) = sql::change_status(user_id, status.to_string()).await {
success = false; success = false;
error_message = e.to_string(); error_message = e.to_string();
} }
} }
if let (Some(public_key), Some(private_key_hash)) = ( if let (Some(public_key), Some(private_key_hash)) = (
cv.get_data(DataTypes::public_key).as_str(), cv.get_data(DataType::PublicKey).as_str(),
cv.get_data(DataTypes::private_key_hash).as_str(), cv.get_data(DataType::PrivateKeyHash).as_str(),
) { ) {
if let Err(e) = sql::change_keys( if let Err(e) = sql::change_keys(
user_id, user_id,
@ -880,12 +874,12 @@ impl OmikronConnection {
} }
if success { if success {
let response = CommunicationValue::new(CommunicationType::success).with_id(cv.get_id()); let response = CommunicationValue::new(CommunicationType::Success).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} else { } else {
let response = CommunicationValue::new(CommunicationType::error_internal) let response = CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(error_message)); .add_typed_default(DataType::ErrorType, DataValue::Str(error_message));
self.send(&response).await self.send(&response).await
} }
} }
@ -895,8 +889,8 @@ impl OmikronConnection {
if let (iota_id, Some(reset_token), Some(new_token)) = ( if let (iota_id, Some(reset_token), Some(new_token)) = (
cv.get_sender(), cv.get_sender(),
cv.get_data(DataTypes::reset_token).as_str(), cv.get_data(DataType::ResetToken).as_str(),
cv.get_data(DataTypes::new_token).as_str(), cv.get_data(DataType::NewToken).as_str(),
) { ) {
match sql::get_by_user_id(user_id).await { match sql::get_by_user_id(user_id).await {
Ok(user) => { Ok(user) => {
@ -918,31 +912,31 @@ impl OmikronConnection {
} }
if success { if success {
let response = CommunicationValue::new(CommunicationType::success) let response = CommunicationValue::new(CommunicationType::Success)
.with_id(cv.get_id()); .with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} else { } else {
let response = let response =
CommunicationValue::new(CommunicationType::error_internal) CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(error_message)); .add_typed_default(DataType::ErrorType, DataValue::Str(error_message));
self.send(&response).await self.send(&response).await
} }
} else { } else {
self.send_error_response( self.send_error_response(
cv.get_id(), cv.get_id(),
CommunicationType::error_invalid_challenge, CommunicationType::ErrorInvalidChallenge,
) )
.await .await
} }
} }
Err(_) => { Err(_) => {
self.send_error_response(cv.get_id(), CommunicationType::error_not_found) self.send_error_response(cv.get_id(), CommunicationType::ErrorNotFound)
.await .await
} }
} }
} else { } else {
self.send_error_response(cv.get_id(), CommunicationType::error_invalid_data) self.send_error_response(cv.get_id(), CommunicationType::ErrorInvalidData)
.await .await
} }
} }
@ -952,13 +946,13 @@ impl OmikronConnection {
match sql::delete_user(user_id).await { match sql::delete_user(user_id).await {
Ok(_) => { Ok(_) => {
let response = let response =
CommunicationValue::new(CommunicationType::success).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::Success).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
Err(e) => { Err(e) => {
let response = CommunicationValue::new(CommunicationType::error_internal) let response = CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(e.to_string())); .add_typed_default(DataType::ErrorType, DataValue::Str(e.to_string()));
self.send(&response).await self.send(&response).await
} }
} }
@ -969,13 +963,13 @@ impl OmikronConnection {
match sql::delete_iota(iota_id as i64).await { match sql::delete_iota(iota_id as i64).await {
Ok(_) => { Ok(_) => {
let response = let response =
CommunicationValue::new(CommunicationType::success).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::Success).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
Err(e) => { Err(e) => {
let response = CommunicationValue::new(CommunicationType::error_internal) let response = CommunicationValue::new(CommunicationType::ErrorInternal)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::error_type, DataValue::Str(e.to_string())); .add_typed_default(DataType::ErrorType, DataValue::Str(e.to_string()));
self.send(&response).await self.send(&response).await
} }
} }
@ -990,9 +984,10 @@ impl OmikronConnection {
Ok(notifications) => notifications Ok(notifications) => notifications
.into_iter() .into_iter()
.map(|(sender, amount)| { .map(|(sender, amount)| {
let tm = mtp::type_map::TypeMap::latest();
DataValue::Container(vec![ DataValue::Container(vec![
(DataTypes::sender_id, DataValue::Number(sender)), (DataType::SenderId.to_id(&tm), DataValue::SignedNumber(sender.into())),
(DataTypes::amount, DataValue::Number(amount)), (DataType::Amount.to_id(&tm), DataValue::SignedNumber(amount.into())),
]) ])
}) })
.collect(), .collect(),
@ -1002,9 +997,9 @@ impl OmikronConnection {
} }
}; };
let response = CommunicationValue::new(CommunicationType::get_notifications) let response = CommunicationValue::new(CommunicationType::GetNotifications)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::notifications, DataValue::Array(response_array)); .add_typed_default(DataType::Notifications, DataValue::Array(response_array));
self.send(&response).await self.send(&response).await
} }
@ -1014,21 +1009,21 @@ impl OmikronConnection {
) -> OmikronResult<()> { ) -> OmikronResult<()> {
let receiver_id = match cv.get_sender() { let receiver_id = match cv.get_sender() {
s if s > 0 => s as i64, s if s > 0 => s as i64,
_ => match cv.get_data(DataTypes::receiver_id).as_number() { _ => match cv.get_data(DataType::ReceiverId).as_number() {
Some(id) => id as i64, Some(id) => id as i64,
None => return Ok(()), None => return Ok(()),
}, },
}; };
if let Some(other_id) = cv if let Some(other_id) = cv
.get_data(DataTypes::sender_id) .get_data(DataType::SenderId)
.as_number() .as_number()
.map(|n| n as i64) .map(|n| n as i64)
{ {
if let Err(e) = sql::read_notification(receiver_id, other_id).await { if let Err(e) = sql::read_notification(receiver_id, other_id).await {
log!(PrintType::General, "SQL read_notification error: {}", e); log!(PrintType::General, "SQL read_notification error: {}", e);
} else { } else {
let response = CommunicationValue::new(CommunicationType::read_notification) let response = CommunicationValue::new(CommunicationType::ReadNotification)
.with_id(cv.get_id()); .with_id(cv.get_id());
let _ = self.send(&response).await; let _ = self.send(&response).await;
@ -1036,9 +1031,9 @@ impl OmikronConnection {
crate::notifications::tauri::remove_notification(receiver_id, other_id).await; crate::notifications::tauri::remove_notification(receiver_id, other_id).await;
// Sync with other Omikron clients // Sync with other Omikron clients
let sync_cv = CommunicationValue::new(CommunicationType::read_notification) let sync_cv = CommunicationValue::new(CommunicationType::ReadNotification)
.with_receiver(receiver_id as u64) .with_receiver(receiver_id as u64)
.add_data(DataTypes::sender_id, DataValue::Number(other_id)); .add_typed_default(DataType::SenderId, DataValue::SignedNumber(other_id.into()));
crate::transport::omikron_manager::send_to_user(receiver_id, &sync_cv).await; crate::transport::omikron_manager::send_to_user(receiver_id, &sync_cv).await;
} }
} }
@ -1051,13 +1046,13 @@ impl OmikronConnection {
) -> OmikronResult<()> { ) -> OmikronResult<()> {
let receiver_id = match cv.get_receiver() { let receiver_id = match cv.get_receiver() {
r if r > 0 => r as i64, r if r > 0 => r as i64,
_ => match cv.get_data(DataTypes::receiver_id).as_number() { _ => match cv.get_data(DataType::ReceiverId).as_number() {
Some(id) => id as i64, Some(id) => id as i64,
None => return Ok(()), None => return Ok(()),
}, },
}; };
let sender_id = match cv.get_data(DataTypes::sender_id).as_number() { let sender_id = match cv.get_data(DataType::SenderId).as_number() {
Some(id) => id as i64, Some(id) => id as i64,
None => cv.get_sender() as i64, None => cv.get_sender() as i64,
}; };
@ -1066,31 +1061,31 @@ impl OmikronConnection {
log!(PrintType::General, "SQL add_notification error: {}", e); log!(PrintType::General, "SQL add_notification error: {}", e);
} else { } else {
let response = let response =
CommunicationValue::new(CommunicationType::push_notification).with_id(cv.get_id()); CommunicationValue::new(CommunicationType::PushNotification).with_id(cv.get_id());
let _ = self.send(&response).await; let _ = self.send(&response).await;
// Sync with Tauri // Sync with Tauri
crate::notifications::tauri::send_notification(receiver_id, sender_id).await; crate::notifications::tauri::send_notification(receiver_id, sender_id).await;
// Sync with other Omikron clients // Sync with other Omikron clients
let push_cv = CommunicationValue::new(CommunicationType::push_notification) let push_cv = CommunicationValue::new(CommunicationType::PushNotification)
.with_receiver(receiver_id as u64) .with_receiver(receiver_id as u64)
.add_data(DataTypes::sender_id, DataValue::Number(sender_id)); .add_typed_default(DataType::SenderId, DataValue::SignedNumber(sender_id.into()));
crate::transport::omikron_manager::send_to_user(receiver_id, &push_cv).await; crate::transport::omikron_manager::send_to_user(receiver_id, &push_cv).await;
} }
Ok(()) Ok(())
} }
async fn handle_get_states(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_get_states(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
let user_ids = match cv.get_data(DataTypes::user_ids) { let user_ids = match cv.get_data(DataType::UserIds) {
DataValue::Array(ids) => ids, DataValue::Array(ids) => ids,
_ => return Ok(()), _ => return Ok(()),
}; };
let mut states = Vec::new(); let mut states = Vec::new();
for id_val in user_ids { for id_val in user_ids {
if let DataValue::Number(user_id) = id_val { if let DataValue::SignedNumber(user_id) = id_val {
let user_id = *user_id; let user_id = *user_id as i64;
let status = user_online_tracker::get_user_status(user_id); let status = user_online_tracker::get_user_status(user_id);
let status_str = match status { let status_str = match status {
Some(ref us) => { Some(ref us) => {
@ -1102,25 +1097,26 @@ impl OmikronConnection {
} }
None => UserStatus::iota_offline.to_string(), None => UserStatus::iota_offline.to_string(),
}; };
let tm = mtp::type_map::TypeMap::latest();
let mut map = Vec::new(); let mut map = Vec::new();
map.push((DataTypes::user_id, DataValue::Number(user_id))); map.push((DataType::UserId.to_id(&tm), DataValue::SignedNumber(user_id.into())));
map.push((DataTypes::user_state, DataValue::Str(status_str))); map.push((DataType::UserState.to_id(&tm), DataValue::Str(status_str)));
states.push(DataValue::Container(map)); states.push(DataValue::Container(map));
} }
} }
let response = CommunicationValue::new(CommunicationType::get_states) let response = CommunicationValue::new(CommunicationType::GetStates)
.with_id(cv.get_id()) .with_id(cv.get_id())
.add_data(DataTypes::user_states, DataValue::Array(states)); .add_typed_default(DataType::UserStates, DataValue::Array(states));
self.send(&response).await self.send(&response).await
} }
async fn handle_ping(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> { async fn handle_ping(self: Arc<Self>, cv: CommunicationValue) -> OmikronResult<()> {
if let DataValue::Number(last_ping) = cv.get_data(DataTypes::last_ping) { if let DataValue::SignedNumber(last_ping) = cv.get_data(DataType::LastPing) {
*self.ping.write().await = *last_ping; *self.ping.write().await = *last_ping as i64;
} }
let response = CommunicationValue::new(CommunicationType::pong).with_id(cv.get_id()); let response = CommunicationValue::new(CommunicationType::Pong).with_id(cv.get_id());
self.send(&response).await self.send(&response).await
} }
@ -1129,7 +1125,7 @@ impl OmikronConnection {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
async fn send(self: Arc<Self>, cv: &CommunicationValue) -> OmikronResult<()> { async fn send(self: Arc<Self>, cv: &CommunicationValue) -> OmikronResult<()> {
if !cv.is_type(CommunicationType::pong) && !cv.is_type(CommunicationType::ping) { if !cv.is_type(CommunicationType::Pong) && !cv.is_type(CommunicationType::Ping) {
log_cv_out!(PrintType::Omikron, cv); log_cv_out!(PrintType::Omikron, cv);
} }
@ -1196,7 +1192,8 @@ pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error>> {
let key_pem = load_file_vec("certs", "transport_key.pem").expect("Error loading Keyfile"); let key_pem = load_file_vec("certs", "transport_key.pem").expect("Error loading Keyfile");
let mut host: Host = ttp_native::host( let mut host: Host = host(
IpAddr::from(Ipv4Addr::new(0, 0, 0, 0)),
port, port,
cert_pem, cert_pem,
key_pem, key_pem,

View file

@ -1,9 +1,9 @@
use crate::transport::omikron_connection::OmikronConnection; use crate::transport::omikron_connection::OmikronConnection;
use dashmap::DashMap; use dashmap::DashMap;
use mtp::codec::CommunicationValue;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rand::prelude::IteratorRandom; use rand::prelude::IteratorRandom;
use std::sync::Arc; use std::sync::Arc;
use ttp_core::CommunicationValue;
pub static OMIKRON_CONNECTIONS: Lazy<DashMap<i64, Arc<OmikronConnection>>> = pub static OMIKRON_CONNECTIONS: Lazy<DashMap<i64, Arc<OmikronConnection>>> =
Lazy::new(|| DashMap::new()); Lazy::new(|| DashMap::new());

View file

@ -1,5 +1,4 @@
use std::{ use std::{
collections::BTreeMap,
fs::{self, OpenOptions}, fs::{self, OpenOptions},
io::Write, io::Write,
path::Path, path::Path,
@ -9,7 +8,7 @@ use std::{
}; };
use ansi_term::Color; use ansi_term::Color;
use ttp_core::{CommunicationValue, DataTypes, DataValue}; use mtp::codec::{CommunicationValue, DataTypeId, DataValue, Version};
use crate::util::file_util::get_directory; use crate::util::file_util::get_directory;
@ -248,17 +247,19 @@ pub fn format_cv(cv: &CommunicationValue) -> String {
let comm_type = cv.get_type().to_string(); let comm_type = cv.get_type().to_string();
parts.push(format!("{}", comm_type)); parts.push(format!("{}", comm_type));
let data: &BTreeMap<DataTypes, DataValue> = cv.get_data_container(); let data = cv.data();
let formated_data = let formated_data = format_data_container(
format_data_container(data.iter().map(|(k, v)| (k.clone(), v.clone())).collect()); data.iter().map(|(k, v)| (*k, v.clone())).collect(),
Version(1, 0),
);
parts.push(format!("{}", formated_data)); parts.push(format!("{}", formated_data));
parts.join(": ") parts.join(": ")
} }
fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String { fn format_data_container(data: Vec<(DataTypeId, DataValue)>, version: Version) -> String {
let parts: Vec<String> = data let parts: Vec<String> = data
.into_iter() .into_iter()
.map(|(key, value)| { .map(|(key, value)| {
@ -268,12 +269,13 @@ fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String {
DataValue::Str(s) => format!("{}=\"{}\"", key_str, s), DataValue::Str(s) => format!("{}=\"{}\"", key_str, s),
DataValue::Container(inner) => { DataValue::Container(inner) => {
let inner_formatted = format_data_container(inner); let inner_formatted =
format_data_container(inner, version.clone());
format!("{}={{ {} }}", key_str, inner_formatted) format!("{}={{ {} }}", key_str, inner_formatted)
} }
DataValue::Array(arr) => { DataValue::Array(arr) => {
let arr_formatted = format_array(arr); let arr_formatted = format_array(arr, version.clone());
format!("{}=[{}]", key_str, arr_formatted) format!("{}=[{}]", key_str, arr_formatted)
} }
@ -282,7 +284,7 @@ fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String {
DataValue::BoolTrue => format!("{}=true", key_str), DataValue::BoolTrue => format!("{}=true", key_str),
DataValue::BoolFalse => format!("{}=false", key_str), DataValue::BoolFalse => format!("{}=false", key_str),
DataValue::Number(num) => format!("{}={}", key_str, num), DataValue::SignedNumber(num) => format!("{}={}", key_str, num),
_ => "".to_string(), _ => "".to_string(),
} }
@ -292,19 +294,19 @@ fn format_data_container(data: Vec<(DataTypes, DataValue)>) -> String {
parts.join(", ") parts.join(", ")
} }
fn format_array(arr: Vec<DataValue>) -> String { fn format_array(arr: Vec<DataValue>, version: Version) -> String {
let parts: Vec<String> = arr let parts: Vec<String> = arr
.into_iter() .into_iter()
.map(|value| match value { .map(|value| match value {
DataValue::Str(s) => format!("\"{}\"", s), DataValue::Str(s) => format!("\"{}\"", s),
DataValue::Container(inner) => { DataValue::Container(inner) => {
let inner_formatted = format_data_container(inner); let inner_formatted = format_data_container(inner, version.clone());
format!("{{ {} }}", inner_formatted) format!("{{ {} }}", inner_formatted)
} }
DataValue::Array(inner_arr) => { DataValue::Array(inner_arr) => {
let formatted = format_array(inner_arr); let formatted = format_array(inner_arr, version.clone());
format!("[{}]", formatted) format!("[{}]", formatted)
} }
@ -313,7 +315,7 @@ fn format_array(arr: Vec<DataValue>) -> String {
DataValue::BoolTrue => "true".to_string(), DataValue::BoolTrue => "true".to_string(),
DataValue::BoolFalse => "false".to_string(), DataValue::BoolFalse => "false".to_string(),
DataValue::Number(num) => num.to_string(), DataValue::SignedNumber(num) => num.to_string(),
_ => String::new(), _ => String::new(),
}) })

240
type-maps.yaml Normal file
View file

@ -0,0 +1,240 @@
# The version a Client should use
protocol_version: "1.0"
# Note that markers 0 to 31 are reserved for default use, manually working with them is not recommended
# Fixed CommunicationType markers are:
# Error: 0
# ErrorParsing: 1
# ErrorBadVersion: 2
# Disconnect: 3
# Redirect: 4
# Shutdown: 5
# BadRequest: 6
# Unauthorized: 7
# Forbidden: 8
# NotFound: 9
# TooManyRequests: 10
# InternalServerError: 11
# BadGateway: 12
# ServiceUnavailable: 13
# GatewayTimeout: 14
# Identification: 15
# IdentificationResponse: 16
# Register: 17
# RegisterResponse: 18
# Ping: 19
# Pong: 20
#
# Fixed Data Type markers are:
# Error: 0
# ErrorParsing: 1
# ErrorMessage: 2
# Version: 3
# Description: 4
# Timestamp: 5
# Id: 6
# ClientNonce: 7
# ServerNonce: 8
# PublicKeys: 9
# Signature: 10
# Connected: 11
#
# If a Type can't be used it will be mapped to 0
type_maps:
"1.0": # Protocol version 1.0
CommunicationTypes:
ErrorProtocol: 33
ErrorAnonymous: 34
ErrorInternal: 35
ErrorInvalidData: 36
ErrorInvalidUserId: 37
ErrorInvalidOmikronId: 38
ErrorNotFound: 39
ErrorNotAuthenticated: 40
ErrorNoIota: 41
ErrorInvalidChallenge: 42
ErrorInvalidSecret: 43
ErrorInvalidPrivateKey: 44
ErrorInvalidPublicKey: 45
ErrorNoUserId: 46
ErrorNoCallId: 47
ErrorInvalidCallId: 48
Success: 49
ShortenLink: 50
SettingsSave: 51
SettingsLoad: 52
SettingsList: 53
GlobalSettingsSave: 54
GlobalSettingsLoad: 55
Message: 56
MessageState: 57
MessageSend: 58
MessageLive: 59
MessageOtherIota: 60
MessageChunk: 61
MessagesGet: 62
PushNotification: 63
ReadNotification: 64
GetNotifications: 65
TauriIdentification: 66
ChangeConfirm: 67
ConfirmReceive: 68
ConfirmRead: 69
GetChats: 70
GetStates: 71
AddCommunity: 72
RemoveCommunity: 73
GetCommunities: 74
RegisterIota: 81
RegisterIotaSuccess: 82
AddConversation: 85
SendChat: 86
ClientChanged: 87
ClientConnected: 88
ClientDisconnected: 89
ClientClosed: 90
PublicKey: 91
PrivateKey: 92
WebrtcSdp: 93
WebrtcIce: 94
StartStream: 95
EndStream: 96
WatchStream: 97
CallToken: 98
CallInvite: 99
CallDisconnectUser: 100
CallTimeoutUser: 101
CallSetAnonymousJoining: 102
CallData: 103
EndCall: 104
Function: 105
Update: 106
CreateUser: 107
RhoUpdate: 108
UserConnected: 109
UserDisconnected: 110
IotaConnected: 111
IotaDisconnected: 112
SyncClientIotaStatus: 113
GetUserData: 114
GetIotaData: 115
IotaUserData: 116
ChangeUserData: 117
ChangeIotaData: 118
GetRegister: 119
CompleteRegisterUser: 120
CompleteRegisterIota: 121
DeleteUser: 122
DeleteIota: 123
StartRegister: 124
CompleteRegister: 125
GetApp: 126
CreateApp: 127
DeleteApp: 128
SaveAppData: 129
LoadAppData: 130
AppIdentification: 131
AppChallenge: 132
AppChallengeResponse: 133
AppIdentificationResponse: 134
LoadTxtRecord: 135
DataTypes:
ErrorType: 32
ErrorProtocol: 33
AcceptedIds: 34
Uuid: 35
RegisterId: 36
Link: 37
Settings: 38
SettingsName: 39
ChatPartnerId: 40
ChatPartnerName: 41
IotaId: 42
UserId: 43
UserIds: 44
IotaIds: 45
UserState: 46
UserStates: 47
UserPings: 48
CallState: 49
ScreenShare: 50
PrivateKeyHash: 51
Accepted: 52
AcceptedProfiles: 53
DeniedProfiles: 54
Content: 55
Messages: 56
Notifications: 57
SendTime: 58
GetTime: 59
GetVariant: 60
SharedSecretOwn: 61
SharedSecretOther: 62
SharedSecretSign: 63
SharedSecret: 64
CallId: 65
CallToken: 66
CallSecret: 67
Untill: 68
Enabled: 69
StartDate: 70
EndDate: 71
ReceiverId: 72
SenderId: 73
Signed: 75
Message: 76
MessageState: 77
LastPing: 78
PingIota: 79
PingClients: 80
Matches: 81
Omikron: 82
Offset: 83
Amount: 84
Position: 85
Name: 86
Path: 87
Codec: 88
Function: 89
Payload: 90
Result: 91
Interactables: 92
WantToWatch: 93
Watcher: 94
CreatedAt: 95
Username: 96
Display: 97
Avatar: 98
About: 99
Status: 100
PublicKey: 101
SubLevel: 102
SubEnd: 103
CommunityAddress: 104
CommunityTitle: 106
Communities: 107
RhoConnections: 108
User: 109
OnlineStatus: 110
OmikronId: 111
OmikronConnections: 112
ResetToken: 113
NewToken: 114
CallInvited: 115
CallMembers: 116
Calls: 117
Timeout: 118
HasAdmin: 119
LastMessageAt: 120
Height: 121
SentBySelf: 122
SessionId: 123
Contacts: 124
LastMessage: 125
AppIdentifier: 127
AppPrivateKey: 128
AppPublicKey: 129
AppSession: 130
AppData: 131
TauriToken: 132