topic "Design Notes"; [l288;i1120;a17;O9;~~~.1408;2 $$1,0#10431211400427159095818037425705:param] [a83;*R6 $$2,5#31310162474203024125188417583966:caption] [H4;b83;*4 $$3,5#07864147445237544204411237157677:title] [i288;O9;C2 $$4,6#40027414424643823182269349404212:item] [b42;a42;ph2 $$5,5#45413000475342174754091244180557:text] [l288;b17;a17;2 $$6,6#27521748481378242620020725143825:desc] [l321;C@5+75 $$7,7#20902679421464641399138805415013:code] [b2503;2 $$8,0#65142375456100023862071332075487:separator] [*@(0.0.255)2 $$9,0#83433469410354161042741608181528:base] [C2 $$10,0#37138531426314131251341829483380:class] [l288;a17;*1 $$11,11#70004532496200323422659154056402:requirement] [i417;b42;a42;O9;~~~.416;2 $$12,12#10566046415157235020018451313112:tparam] [b167;C2 $$13,13#92430459443460461911108080531343:item1] [i288;a42;O9;C2 $$14,14#77422149456609303542238260500223:item2] [*@2$(0.128.128)2 $$15,15#34511555403152284025741354420178:NewsDate] [l321;*C$7;2 $$16,16#03451589433145915344929335295360:result] [l321;b83;a83;*C$7;2 $$17,17#07531550463529505371228428965313:result`-line] [l160;*C+117 $$18,5#88603949442205825958800053222425:package`-title] [2 $$19,0#53580023442335529039900623488521:gap] [C2 $$20,20#70211524482531209251820423858195:class`-nested] [b50;2 $$21,21#03324558446220344731010354752573:Par] [b83;* $$22,22#78EB85B566C7E078B53494D0FD53D992:subtitle] [2 $$0,0#00000000000000000000000000000000:Default] [{_} [s2; Design Notes&] [s0; &] [s0; [*4 Table of Contents]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#1^ 1. Overview]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#2^ 2. Architectural Model]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#3^ 3. Execution Model]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#4^ 4. State Model]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#5^ 5. Error Handling Strategy]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#6^ 6. Threading Model]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#7^ 7. Memory Model]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#8^ 8. Identity `& RTTI]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#9^ 9. Subsystem Responsibilities]&] [s0; [^topic`:`/`/Core`/SSH`/srcdoc`/Design`_en`-us`#10^ 10. Design Principles]&] [s9;^`#11^ &] [s3;:1: 1. Overview&] [s5; The SSH package is a layered, RAII`-driven wrapper around libssh2, designed to integrate naturally with the U`+`+ ecosystem. &] [s5; Its goals: &] [s5;l192;i150;O0;~~~0; Provide a unified object`-oriented SSH abstraction&] [s5;l192;i150;O0;~~~0; Preserve libssh2’s flexibility without exposing its procedural complexity&] [s5;l192;i150;O0;~~~0; Support both GUI and console applications&] [s5;l192;i150;O0;~~~0; Be cross`-platform (POSIX `+ Windows)&] [s5;l192;i150;O0;~~~0; Support multithreading&] [s5;l192;i150;O0; Follow U`+`+ idioms (pick semantics, Event, RTTI, memory manager)&] [s5; At the center of the architecture is the [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Base`_en`-us`#Upp`:`:Ssh`:`:class^@(0.0.255) S sh ]base class (the “core” abstraction). &] [s3;:2: 2. Architectural Model&] [s22; 2.1 Layered Design&] [s6; [@(0.0.255)1 Ssh (Core)]&] [s6; [@(0.0.255)1 ├── SshSession]&] [s6; [@(0.0.255)1 │ ├── SshChannel]&] [s6; [@(0.0.255)1 │ │ ├── Scp]&] [s6; [@(0.0.255)1 │ │ ├── SshExec]&] [s6; [@(0.0.255)1 │ │ ├── SshShell]&] [s6; [@(0.0.255)1 │ │ └── SshTunnel]&] [s6; [@(0.0.255)1 │ └── SFtp]&] [s6; [@(0.0.255)1 │ └── SFtpStream]&] [s6; [@(0.0.255)1 └── SshHosts ]&] [s22; 2.2 Responsibilities by Layer&] [s5; The [C^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Base`_en`-us`#Upp`:`:Ssh`:`:class^@5 S sh][^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Base`_en`-us`#Upp`:`:Ssh`:`:class^ ]class provides: &] [s5;l192;i150;O0; State machine&] [s5;l192;i150;O0; Error handling&] [s5;l192;i150;O0; Timeout handling&] [s5;l192;i150;O0; Abort support&] [s5;l192;i150;O0; Thread synchronization&] [s5;l192;i150;O0; Event`-driven wait loop&] [s5;l192;i150;O0; Common diagnostics/tracing&] [s5;l192;i150;O0; Polymorphic base (RTTI`-enabled)&] [s5; It encapsulates: &] [s5;l192;i150;O0; LIBSSH2`_SESSION`*&] [s5;l192;i150;O0; Socket state&] [s5;l192;i150;O0; Timing state&] [s5;l192;i150;O0; Error state&] [s5;l192;i150;O0; Status flags (IDLE, WORKING, FAILED, ABORTED)&] [s5; It does [* not] represent a concrete SSH entity. It represents the execution model. &] [s3;:3: 3. Execution Model&] [s22; 3.1 Cooperative Run Loop&] [s5; Core execution is handled by: &] [s7; [*@(0.0.255) bool] Ssh[@(0.0.255) `::]Run(Gate[@(0.0.255) <>`&`&] fn, [*@(0.0.255) bool] abortable)&] [s5; Design intent: &] [s5;l192;i150;O0; Wrap libssh2’s non`-blocking behavior&] [s5;l192;i150;O0; Centralize timeout and abort checks&] [s5;l192;i150;O0; Serialize critical SSH operations&] [s5;l192;i150;O0; Ensure proper socket direction handling&] [s5; Flow: &] [s5;l192;i150;O0; Set status `= WORKING&] [s5;l192;i150;O0; Record start time&] [s5;l192;i150;O0; Repeatedly:&] [s5;l416;i150;O0; Validate timeout&] [s5;l416;i150;O0; Validate abort&] [s5;l416;i150;O0; Validate socket state&] [s5;l416;i150;O0; Lazily initialize session&] [s5;l416;i150;O0; Execute user`-provided operation&] [s5;l416;i150;O0; Call Wait() if libssh2 indicates blocking&] [s5;l192;i150;O0; Transition to IDLE or FAILED&] [s5; This abstracts libssh2’s EAGAIN`-style state machine into a higher`-level loop.&] [s22; 3.2 Wait Strategy&] [s0;b20;t300; &] [s7; void Ssh`::Wait()&] [s5; Uses: &] [s5;l192;i150;O0; libssh2`_session`_block`_directions()&] [s5;l192;i150;O0; SocketWaitEvent&] [s5;l192;i150;O0; WAIT`_READ / WAIT`_WRITE mask&] [s5;l192;i150;O0; Configurable wait step&] [s5; Design goals: &] [s5;l192;i150;O0; Respect non`-blocking semantics&] [s5;l192;i150;O0; Avoid busy looping&] [s5;l192;i150;O0; Integrate cleanly with U`+`+ event loop&] [s5;l192;i150;O0; Support both console and GUI contexts&] [s3;:4: 4. State Model&] [s5; Core states: &] [s5;l192;i150;O0; IDLE&] [s5;l192;i150;O0; WORKING&] [s5;l192;i150;O0; FAILED&] [s5;l192;i150;O0; ABORTED&] [s5; Transitions:&] [s5;l192;i150;O0;~~~0; IDLE → WORKING (Run begins)&] [s5;l192;i150;O0;~~~0; WORKING → IDLE (Success)&] [s5;l192;i150;O0;~~~0; WORKING → FAILED (Error)&] [s5;l192;i150;O0;~~~0; WORKING → ABORTED (User abort)&] [s5; Abort is cooperative:&] [s5;l192;i150;O0; Sets status flag&] [s5;l192;i150;O0; Next Run iteration throws&] [s3;:5: 5. Error Handling Strategy&] [s5; Errors are captured via: &] [s5; -|[@(0.0.255)1 struct Error : Exc]&] [s5; Properties: &] [s5;l192;i150;O0; Numeric error code&] [s5;l192;i150;O0; Descriptive message&] [s5;l192;i150;O0; Propagated via exceptions&] [s5;l192;i150;O0; Normalized into internal state via [C@(0.0.255) SetError()]&] [s5; This ensures:&] [s5;l192;i150;O0; Consistent error propagation&] [s5;l192;i150;O0; Clean user`-facing API&] [s5;l192;i150;O0; libssh2 error translation&] [s5; All public operations return status via [C@(0.0.255)1 operator bool(), IsError(), GetError(), GetErrorDesc()]&] [s3;:6: 6. Threading Model&] [s5; Key aspects:&] [s5;l192;i150;O0; Static global mutex protects critical operations&] [s5;l192;i150;O0; Designed for multithreaded usage at object level&] [s5;l192;i150;O0; Internal operations are serialized&] [s5; This design ensures:&] [s5;l192;i150;O0; No race conditions inside libssh2 calls&] [s5;l192;i150;O0; Controlled concurrency model&] [s5;l192;i150;O0; Predictable behavior under load&] [s3;:7: 7. Memory Model&] [s5;l192;i150;O0; RAII`-based lifecycle&] [s5;l192;i150;O0; Pick semantics supported&] [s5;l192;i150;O0; Compatible with U`+`+ memory manager&] [s5;l192;i150;O0; Optional native malloc mode&] [s5;l192;i150;O0; Object lifetime is deterministic.&] [s5;l192;i150;O0; Resources (session, channel, socket) are released in destructors. &] [s3;:8: 8. Identity `& RTTI&] [s5; Supports:&] [s5;l192;i150;O0; Polymorphic storage&] [s5;l192;i150;O0; Runtime casting via [C@(0.0.255) To()]&] [s5;l192;i150;O0; Type checking via [C@(0.0.255) Is()]&] [s5; Design goal: safe polymorphism without losing performance. &] [s0;H1;h(220)G &] [s3;:9: 9. Subsystem Responsibilities&] [s5; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Session`_en`-us`#Upp`:`:SshSession`:`:class^ S shSession]&] [s5;l192;i150;O0; Authentication&] [s5;l192;i150;O0; Handshake&] [s5;l192;i150;O0; Agent support&] [s5;l192;i150;O0; Known hosts verification&] [s5;l192;i150;O0; Proxy support&] [s5; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Channels`_en`-us^ SshChannel]&] [s5;l192;i150;O0; Abstract channel handling&] [s5;l192;i150;O0; Shared channel lifecycle logic&] [s5;l192;i150;O0; Derived specializations: &] [s5;l416;i150;O0; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Channels`_en`-us`#Upp`:`:Scp`:`:class^ S cp] → file transfer&] [s5;l416;i150;O0; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Channels`_en`-us`#Upp`:`:SshExec`:`:class^ S shExec] → command execution&] [s5;l416;i150;O0; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Channels`_en`-us`#Upp`:`:SshShell`:`:class^ S shShell] → interactive shell `+ X11&] [s5;l416;i150;O0; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Channels`_en`-us`#Upp`:`:SshTunnel`:`:class^ S shTunnel] → port forwarding&] [s5; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_SFtp`_en`-us`#Upp`:`:SFtp`:`:class^ SFtp]&] [s5;l192;i150;O0; Subsystem initialization&] [s5;l192;i150;O0; Directory traversal&] [s5;l192;i150;O0; File operations&] [s5;l192;i150;O0; Stream interface ([^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_SFtpStream`_en`-us`#Upp`:`:SFtpStream`:`:class^ S FtpStream])&] [s5; [^topic`:`/`/Core`/SSH`/src`/Upp`_Ssh`_Hosts`_en`-us`#Upp`:`:SshHosts`:`:class^ Ss hHosts]&] [s5;l192;i150;O0;~~~0; Known host verification&] [s5;l192;i150;O0;~~~0; Host fingerprint management&] [s0;H1;h(220)G &] [s3;:10: 10. Design Principles&] [s5;l192;i150;O0; Non`-blocking core wrapped in controlled blocking loop&] [s5;l192;i150;O0; RAII discipline&] [s5;l192;i150;O0; Clear separation of session vs channel vs subsystem&] [s5;l192;i150;O0; Cross`-platform behavior abstraction&] [s5;l192;i150;O0; Debug traceability at object granularity&] [s5;l192;i150;O0; Avoid leaking libssh2 procedural complexity to users]]