Skip to content
This repository was archived by the owner on Jan 26, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand Down Expand Up @@ -89,8 +89,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand All @@ -117,8 +117,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand Down Expand Up @@ -149,8 +149,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand Down Expand Up @@ -183,8 +183,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand Down Expand Up @@ -218,8 +218,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand Down Expand Up @@ -266,8 +266,8 @@ jobs:
libssl-dev \
pkg-config \
libgtk-3-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.1-dev \
libjavascriptcoregtk-4.1-dev \
libsoup-3.0-dev \
libayatana-appindicator3-dev \
librsvg2-dev
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "cfost"
version = "0.1.0"
edition = "2024"
edition = "2021"
authors = ["CFOST Contributors"]
license = "MIT OR Apache-2.0"
description = "CFOST (Conflict-Free Offline Synchronization Tool) - Cross-platform database synchronization infrastructure with P2P networking, CRDT conflict resolution, and offline-first architecture"
Expand Down
2 changes: 1 addition & 1 deletion src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
/// from an already authorized device.
use crate::models::Device;
use chrono::{DateTime, Duration, Utc};
use libp2p::PeerId;
use libp2p::identity::Keypair;
use libp2p::PeerId;
use rusqlite::Connection;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::cli::daemon as daemon_utils;
use crate::cli::errors::{CliError, CliResult};
use crate::cli::output;
use crate::db::operations::initialize_database;
use crate::logic::sync::{P2PConfig, create_swarm};
use crate::logic::sync::{create_swarm, P2PConfig};
use crate::logic::sync_manager::SyncManager;
use std::sync::{Arc, Mutex};
use std::time::Duration;
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::cli::output;
use std::fs::File;
use std::io::{BufRead, BufReader, Seek, SeekFrom};
use std::path::Path;
use tokio::time::{Duration, sleep};
use tokio::time::{sleep, Duration};

pub async fn view(
follow: bool,
Expand Down
2 changes: 1 addition & 1 deletion src/crdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl HybridLogicalClock {

impl PartialOrd for HybridLogicalClock {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.timestamp.partial_cmp(&other.timestamp)
Some(self.cmp(other))
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/db/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

use crate::models::{Device, OplogEntry, Peer, User};
use chrono::{DateTime, Utc};
use rusqlite::{Connection, Result, Row, params, types::Type};
use rusqlite::{params, types::Type, Connection, Result, Row};
use uuid::Uuid;

/// Initialize the database with migrations
Expand Down
38 changes: 17 additions & 21 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ pub type DbConnection = Connection;
/// The caller is responsible for calling `nexus_close_database` to free the connection.
/// The `db_path` must be a valid, null-terminated C string.
#[unsafe(no_mangle)]
pub extern "C" fn nexus_initialize_database(db_path: *const c_char) -> *mut DbConnection {
pub unsafe extern "C" fn nexus_initialize_database(db_path: *const c_char) -> *mut DbConnection {
if db_path.is_null() {
return ptr::null_mut();
}

let c_str = unsafe { CStr::from_ptr(db_path) };
let c_str = CStr::from_ptr(db_path);
let path = match c_str.to_str() {
Ok(s) => s,
Err(_) => return ptr::null_mut(),
Expand Down Expand Up @@ -56,22 +56,20 @@ pub unsafe extern "C" fn nexus_close_database(conn_ptr: *mut DbConnection) {
/// The `username`, `email`, and `password` must be valid, null-terminated C strings.
/// The caller is responsible for calling `nexus_free_string` on the returned pointer.
#[unsafe(no_mangle)]
pub extern "C" fn nexus_register_user(
pub unsafe extern "C" fn nexus_register_user(
conn_ptr: *mut DbConnection,
username: *const c_char,
email: *const c_char,
password: *const c_char,
) -> *mut c_char {
let conn = unsafe {
if conn_ptr.is_null() {
return ptr::null_mut();
}
&*conn_ptr
};
if conn_ptr.is_null() {
return ptr::null_mut();
}
let conn = &*conn_ptr;

let username = unsafe { CStr::from_ptr(username).to_str().unwrap() };
let email = unsafe { CStr::from_ptr(email).to_str().unwrap() };
let password = unsafe { CStr::from_ptr(password).to_str().unwrap() };
let username = CStr::from_ptr(username).to_str().unwrap();
let email = CStr::from_ptr(email).to_str().unwrap();
let password = CStr::from_ptr(password).to_str().unwrap();

match crate::logic::register_user(
conn,
Expand Down Expand Up @@ -109,20 +107,18 @@ pub unsafe extern "C" fn nexus_free_string(s_ptr: *mut c_char) {
/// The `username` and `password` must be valid, null-terminated C strings.
/// The caller is responsible for calling `nexus_free_string` on the returned pointer.
#[unsafe(no_mangle)]
pub extern "C" fn nexus_login_user(
pub unsafe extern "C" fn nexus_login_user(
conn_ptr: *mut DbConnection,
username: *const c_char,
password: *const c_char,
) -> *mut c_char {
let conn = unsafe {
if conn_ptr.is_null() {
return ptr::null_mut();
}
&*conn_ptr
};
if conn_ptr.is_null() {
return ptr::null_mut();
}
let conn = &*conn_ptr;

let username = unsafe { CStr::from_ptr(username).to_str().unwrap() };
let password = unsafe { CStr::from_ptr(password).to_str().unwrap() };
let username = CStr::from_ptr(username).to_str().unwrap();
let password = CStr::from_ptr(password).to_str().unwrap();

match crate::logic::login_user(conn, username, password) {
Ok(user) => {
Expand Down
12 changes: 6 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ pub use logic::build_oplog_entry;
// ============================================================================

pub use logic::sync::{
NexusBehaviour, P2PConfig, SyncMessage, connect_to_bootstrap_nodes, connect_to_relay_servers,
create_swarm, create_swarm_default, decode_sync_message, encode_sync_message,
generate_device_id, handle_sync_message, parse_multiaddr_peer_id, update_peer_info,
connect_to_bootstrap_nodes, connect_to_relay_servers, create_swarm, create_swarm_default,
decode_sync_message, encode_sync_message, generate_device_id, handle_sync_message,
parse_multiaddr_peer_id, update_peer_info, NexusBehaviour, P2PConfig, SyncMessage,
};

// Sync manager for orchestrating P2P operations
Expand All @@ -118,15 +118,15 @@ pub use logic::sync_manager::SyncManager;
// ============================================================================

pub use auth::{
AuthChallenge, AuthResponse, AuthResult, AuthorizerWorkflow, DeviceAuthManager,
NewDeviceWorkflow, PairingSession, create_auth_response,
create_auth_response, AuthChallenge, AuthResponse, AuthResult, AuthorizerWorkflow,
DeviceAuthManager, NewDeviceWorkflow, PairingSession,
};

// ============================================================================
// CRDT Operations
// ============================================================================

pub use crdt::{HybridLogicalClock, local_apply, merge};
pub use crdt::{local_apply, merge, HybridLogicalClock};

// ============================================================================
// Tests
Expand Down
2 changes: 1 addition & 1 deletion src/logic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod sync_manager;
use crate::crdt;
use crate::db::operations;
use crate::models::{Device, OplogEntry, User};
use argon2::password_hash::{SaltString, rand_core::OsRng};
use argon2::password_hash::{rand_core::OsRng, SaltString};
use argon2::{Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
use chrono::Utc;
use rusqlite::Connection;
Expand Down
6 changes: 3 additions & 3 deletions src/logic/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::models::{OplogEntry, Peer};
use chrono::Utc;
use libp2p::gossipsub::{MessageAuthenticity, ValidationMode};
use libp2p::{
PeerId, Swarm, Transport, core::upgrade, dcutr, gossipsub, identity, mdns, multiaddr::Protocol,
noise, relay, swarm::NetworkBehaviour, tcp, yamux,
core::upgrade, dcutr, gossipsub, identity, mdns, multiaddr::Protocol, noise, relay,
swarm::NetworkBehaviour, tcp, yamux, PeerId, Swarm, Transport,
};
use rusqlite::Connection;
use std::time::Duration;
Expand Down Expand Up @@ -275,7 +275,7 @@ pub fn update_peer_info(
conn: &Connection,
user_id: Uuid,
device_id: Uuid,
peer_id: String,
_peer_id: String,
ip_address: Option<String>,
) -> Result<(), String> {
// Check if peer exists
Expand Down
31 changes: 14 additions & 17 deletions src/logic/sync_manager.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::logic::sync::{
NexusBehaviour, NexusBehaviourEvent, P2PConfig, SyncMessage, connect_to_bootstrap_nodes,
connect_to_relay_servers, create_swarm, encode_sync_message,
connect_to_bootstrap_nodes, connect_to_relay_servers, create_swarm, encode_sync_message,
NexusBehaviour, NexusBehaviourEvent, P2PConfig, SyncMessage,
};
use crate::models::OplogEntry;
use chrono::{DateTime, Utc};
use libp2p::PeerId;
use libp2p::swarm::SwarmEvent;
use libp2p::{Swarm, gossipsub, identity, mdns};
use libp2p::PeerId;
use libp2p::{gossipsub, identity, mdns, Swarm};
use rusqlite::Connection;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
Expand All @@ -23,7 +23,7 @@ pub struct SyncManager {
/// Device ID for this device
device_id: Uuid,
/// Database connection (thread-safe)
conn: Arc<Mutex<Connection>>,
_conn: Arc<Mutex<Connection>>,
/// Gossipsub topic for sync messages
topic: gossipsub::IdentTopic,
/// Is the manager currently actively syncing/connected to peers
Expand Down Expand Up @@ -59,7 +59,7 @@ impl SyncManager {
swarm,
user_id,
device_id,
conn,
_conn: conn,
topic,
is_syncing: false,
last_sync_time: None,
Expand All @@ -85,7 +85,7 @@ impl SyncManager {
swarm,
user_id,
device_id,
conn,
_conn: conn,
topic,
is_syncing: false,
last_sync_time: None,
Expand Down Expand Up @@ -128,7 +128,7 @@ impl SyncManager {
peer_id: peer_id.to_string(),
};

let encoded = encode_sync_message(&message).map_err(|e| std::io::Error::other(e))?;
let encoded = encode_sync_message(&message).map_err(std::io::Error::other)?;

self.swarm
.behaviour_mut()
Expand All @@ -149,7 +149,7 @@ impl SyncManager {
since_timestamp: since_timestamp.timestamp(),
};

let encoded = encode_sync_message(&message).map_err(|e| std::io::Error::other(e))?;
let encoded = encode_sync_message(&message).map_err(std::io::Error::other)?;

self.swarm
.behaviour_mut()
Expand All @@ -170,7 +170,7 @@ impl SyncManager {
entries,
};

let encoded = encode_sync_message(&message).map_err(|e| std::io::Error::other(e))?;
let encoded = encode_sync_message(&message).map_err(std::io::Error::other)?;

self.swarm
.behaviour_mut()
Expand Down Expand Up @@ -212,7 +212,7 @@ impl SyncManager {
#[cfg(not(feature = "tauri-api"))]
fn emit_sync_status(&self) {
// No-op when tauri feature is not enabled
let _ = (&self.connected_peers);
let _ = &self.connected_peers;
}

#[cfg(feature = "tauri-api")]
Expand Down Expand Up @@ -349,12 +349,9 @@ impl SyncManager {
message: gossipsub::Message,
) -> Result<(), Box<dyn std::error::Error>> {
let sync_message = crate::logic::sync::decode_sync_message(&message.data)?;
match sync_message {
SyncMessage::SyncData { .. } => {
self.last_sync_time = Some(Utc::now());
self.emit_sync_status();
}
_ => {}
if let SyncMessage::SyncData { .. } = sync_message {
self.last_sync_time = Some(Utc::now());
self.emit_sync_status();
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion tests/logic_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ fn test_generate_device_id() {

#[test]
fn test_sync_message_encode_decode() {
use cfost::logic::sync::{SyncMessage, decode_sync_message, encode_sync_message};
use cfost::logic::sync::{decode_sync_message, encode_sync_message, SyncMessage};

let user_id = Uuid::new_v4();
let device_id = Uuid::new_v4();
Expand Down
Loading