Skip to content

feat: Integrate StreamHandler with ClientSession and enhance XML parsing - #22

Merged
XenoSnowFox merged 27 commits into
mainfrom
feature/negotiation-stream-handler
Sep 16, 2026
Merged

XenoSnowFox merged 27 commits into
mainfrom
feature/negotiation-stream-handler

Conversation

@XenoSnowFox

Copy link
Copy Markdown
Contributor

No description provided.

XenoSnowFox and others added 27 commits September 6, 2026 13:12
Introduce a StreamHandler interface and UnimplementedStreamHandler singleton for default/error behavior. ClientSession now stores a non-owning active StreamHandler pointer protected by a mutex, with setActiveStreamHandler/getActiveStreamHandler accessors. Constructor implementation moved to .cpp to set the tokenizer observer and initialize the active handler to UnimplementedStreamHandler::instance(). Added new headers under include/xtrpg/xmpp/stream and updated src/xmpp/session/ClientSession.cpp accordingly.
Expose a convenience accessor on ClientSession for determining whether an active stream handler is currently set. This makes null checks explicit for callers and avoids repeated direct pointer comparisons.
Remove the default active stream handler initialization in the constructor and introduce a comprehensive parsing skeleton inside onXmlToken. New logic ignores comment tokens, detects stream start (stream:stream), handles declaration/invalid-tag cases, branches for secure vs non-secure connection (placeholders for negotiation, authentication, bind phases), and scaffolds close/open/empty/text node handling and stream-close behavior. Leaves original stream:stream open handling intact. This change prepares the session code for implementing concrete stream handlers and proper error handling.
Adds a mutex-protected current XML node pointer to ClientSession and cleans it up in the destructor. The session now properly handles the closing stream:stream tag by sending the closing XML and clearing the active stream handler instead of leaving the stream in an active state.
Add isBlank(const std::string&) and include <cctype>. Mark ltrim, rtrim, trim, toLowerCase, and countUtf8CodePoints as inline to prevent multiple-definition/ODR issues when the header is included in multiple translation units. Minor formatting changes in include/xtrpg/utils/String.hpp.
This change adds a diagnostic log when a client session is removed from the connection manager, printing the current active connection count. It helps track connection churn and diagnose lingering or unexpected disconnects during runtime.
Merge two session.sendRaw calls into a single stream opening that includes the error payload. Replace the <undefined-condition/> with <internal-server-error/> and inline the error into the <stream:stream> message so the handler emits a single, well-formed stream start containing the error text.
Add diagnostic logging for incoming XML tokens and ignore comments, declarations, and blank text. Validate that the first element is an opening stream:stream tag; on mismatch send an XMPP <stream:error> (bad-format) and shutdown the session. Add String.hpp for whitespace checks and include NegotiationStreamHandler (negotiation init currently commented out). Default to UnimplementedStreamHandler as a placeholder. These changes improve robustness and provide clearer diagnostics when handling stream start.
Remove several std::cout debug/log statements from TcpConnection (appendStateChangeCallback, upgrade, read, write, close) to reduce noisy output. No functional changes intended; existing behaviors (e.g., preserving read callback contract when closed) are preserved.
Replace the previous int placeholder for stanzas with a structured xml::node::TagNode reference. Added the TagNode include and updated StreamHandler::onStanza declaration and UnimplementedStreamHandler::onStanza override to accept const xml::node::TagNode&. This clarifies the API and enables passing full XML stanza data instead of an integer placeholder.
Adjust the IPv6 listener initialization to set the v6_only option before binding, then bind and listen on the configured port before storing the acceptor. This fixes Windows dual-stack socket creation issues while preserving IPv6 compatibility.
Adds a new NegotiationStreamHandler for the XMPP stream handshake. It opens the initial stream, advertises STARTTLS, validates the TLS proceed request, and returns a stream error if the client attempts to continue without TLS. This establishes the required TLS negotiation phase before transitioning to the next state.
The unimplemented stream handler now emits the initial <stream:stream> open tag before sending the <stream:error> payload. This keeps the stream error in a valid XMPP context for clients and ensures the session shuts down cleanly after reporting the unexpected failure.
ClientSession now serializes XML nodes to text and emits them through the existing raw send path. This also activates the negotiation stream handler for insecure client connections instead of falling through to the unimplemented handler, so new XMPP sessions begin in the correct phase.
Expose NodeContainer::append in TagNode so base-class append overloads aren't hidden by the template overloads. Add a templated ClientSession::send(tagname, consumer) convenience overload that constructs a TagNode, calls the consumer to populate it, and forwards it to the existing send(const xml::node::INode&). No behavior change—API convenience only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reword the append() documentation and collapse its implementation into a single-line forward to NodeContainer::append in include/xtrpg/xml/node/TagNode.hpp. This is a purely cosmetic change (comment and formatting only) with no behavioral impact.
Adds a convenience `set()` method to `IAttributes` so attribute assignment can use the same API style as XML nodes. The XMPP stream error handler now uses this helper for `xmlns` and `xml:lang` attributes, reducing repetitive `setAttribute()` calls and keeping attribute-setting code consistent.
Replace manual sendRaw XML with structured xml::node::TagNode builders in NegotiationStreamHandler (attributes and child elements are now created programmatically). Add TagNode::append(std::nullptr_t) to create empty tags without a consumer. Qualify TagNode in ClientSession::send as xml::node::TagNode. Improves safety and readability of stream/TLS negotiation by avoiding raw XML string assembly.
This change removes debug logging for ignored XML comments, declarations, and whitespace tokens, which was producing noisy output during normal session parsing. It also keeps a single warning when an incoming XML token cannot be processed, preserving visibility into real issues without cluttering normal traffic.
Replace raw sendRaw error reply with structured send() builder for well-formed stream error. Ignore blank/text-only tokens at root. Add support for EMPTY_TAG tokens by constructing a TagNode (copying attributes) and dispatching it to the active stream handler under a mutex. Ensure method returns after stanza-size shutdown to stop further processing. These changes make XML parsing and error handling more robust and thread-safe.
Add `AGENTS.md` to `.gitignore` so the local agent guidance file stays untracked.
Add the reserved Windows `nul` filename to `.gitignore` so editor or build output does not accidentally create a tracked file that cannot exist on Windows.
Introduces shared TLS settings loaded from config and validates certificate/key files at startup. TcpConnection now keeps the SSL context alive across async handshakes and avoids shutdown races during TLS negotiation. ClientSession upgrades XMPP sessions to TLS and handles shutdown/read cleanup more safely.
Move whitespace detection into `xtrpg::utils::string` and update `XmlStreamTokenizer` to use the shared helper instead of its local implementation. This centralizes character classification logic and avoids duplicating the same `isspace` check.
Relocates the server entry point from `apps/main.cpp` to `src/main.cpp` and updates the executable source path in `CMakeLists.txt` so builds continue to resolve the main target correctly.
@XenoSnowFox
XenoSnowFox merged commit 4a14573 into main Sep 16, 2026
4 checks passed
@XenoSnowFox
XenoSnowFox deleted the feature/negotiation-stream-handler branch September 16, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant