feat: Integrate StreamHandler with ClientSession and enhance XML parsing - #22
Merged
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.