Skip to main content

ssh_commander_core/
lib.rs

1//! ssh-commander-core: Rust domain layer for R-Shell.
2//!
3//! This crate owns all connection and protocol logic:
4//! SSH, PTY lifecycle, host-key handling, connection manager,
5//! SFTP, FTP, desktop protocol (RDP/VNC), and Keychain integration.
6//!
7//! # Thread Safety
8//!
9//! - `ConnectionManager`: `Send + Sync`. All public methods are `async`.
10//!   Callers must be running inside a Tokio runtime. Internally uses
11//!   `Arc<RwLock<HashMap>>` — fine to call from any task, but the task
12//!   must live on the Tokio runtime.
13//! - `SshClient`: `Send` (not `Sync`). Single-owner state; wrap in
14//!   `Arc<RwLock<SshClient>>` to share across tasks (as `ConnectionManager` does).
15//! - `StandaloneSftpClient`, `FtpClient`: Same pattern as `SshClient`.
16//! - `HostKeyStore`: `Send + Sync`. Uses `tokio::sync::Mutex` internally.
17//!   Safe to share via `Arc`.
18//! - `keychain` module: Synchronous only. Do **not** call from a Tokio
19//!   `spawn_blocking` is fine; do not hold an `.await` across a keychain call.
20//! - `PtySession`: `Send`. The `output_rx` field is `Arc<Mutex<Receiver>>`
21//!   for sharing. `input_tx` and `resize_tx` are cloneable `Sender`s.
22//! - `DesktopProtocol` trait: Requires `Send + Sync`. Implementations
23//!   (`RdpClient`, `VncClient`) are `Send` (not `Sync`) — wrap in
24//!   `Arc<RwLock<Box<dyn DesktopProtocol>>>`.
25
26// At least one protocol feature must be enabled — an empty build has no
27// `ManagedConnection` variants and the manager would be inert.
28#[cfg(not(any(
29    feature = "ssh",
30    feature = "sftp",
31    feature = "ftp",
32    feature = "desktop",
33    feature = "tools",
34    feature = "postgres"
35)))]
36compile_error!(
37    "ssh-commander-core needs at least one protocol feature enabled: \
38     ssh, sftp, ftp, desktop, tools, or postgres"
39);
40
41pub mod connection_manager;
42#[cfg(feature = "desktop")]
43pub mod desktop_protocol;
44// Protocol-agnostic file listing types — always available so the `ftp`
45// feature need not pull in the SSH stack just to share them.
46pub mod file_entry;
47#[cfg(feature = "ftp")]
48pub mod ftp_client;
49#[cfg(feature = "desktop")]
50pub mod rdp_client;
51#[cfg(feature = "sftp")]
52pub mod sftp_client;
53#[cfg(feature = "ssh")]
54pub mod ssh;
55#[cfg(feature = "tools")]
56pub mod tools;
57#[cfg(feature = "desktop")]
58pub mod vnc_client;
59
60pub mod event_bus;
61
62pub use connection_manager::{ConnectionManager, ManagedConnection, ProtocolKind};
63#[cfg(feature = "desktop")]
64pub use desktop_protocol::{
65    DesktopConnectRequest, DesktopConnectResponse, DesktopKind, DesktopProtocol, FrameUpdate,
66    RdpConfig, VncConfig,
67};
68pub use event_bus::CoreEvent;
69pub use file_entry::{FileEntry, FileEntryType, RemoteFileEntry};
70
71// The Keychain credential store lives in a sibling leaf crate; the
72// PostgreSQL layer (behind the `postgres` feature) in another. Re-export
73// them as modules so consumers keep using
74// `ssh_commander_core::keychain::*` / `::postgres::*`, alongside the flat
75// re-exports below.
76pub use ssh_commander_keychain as keychain;
77#[cfg(feature = "postgres")]
78pub use ssh_commander_pg as postgres;
79
80pub use keychain::{
81    CredentialKind, delete_password, is_supported, list_accounts, load_password, save_password,
82};
83#[cfg(feature = "postgres")]
84pub use postgres::{
85    ActiveCursor, BROWSER_SESSION_ID, ColumnDetail, ColumnMeta, DbSummary, ExecutionOutcome,
86    InsertColumnInput, InsertedRow, ObjectType, ObjectTypeKind, PageResult, PgAuthMethod, PgConfig,
87    PgError, PgPool, PgTlsMode, Relation, RelationKind, Routine, RoutineKind, SchemaContents,
88    SchemaSummary, Sequence, UpdateOutcome,
89};
90#[cfg(feature = "sftp")]
91pub use sftp_client::{SftpAuthMethod, SftpConfig, StandaloneSftpClient};
92#[cfg(feature = "ssh")]
93pub use ssh::{
94    AuthMethod, CommandOutput, HostKeyMismatch, HostKeyStore, HostKeyStoreAccessError,
95    HostKeyVerificationFailure, PtySession, SshClient, SshConfig, SshTunnel, SshTunnelRef,
96};
97#[cfg(feature = "tools")]
98pub use tools::{
99    DnsAnswer, DnsQuery, GitStatus, ListeningPort, TcpdumpEvent, TcpdumpRegistry, ToolsError,
100    dns_resolve_local, dns_resolve_remote, git_status, listening_ports,
101};
102
103pub fn core_version() -> &'static str {
104    env!("CARGO_PKG_VERSION")
105}