From 5b5f109824b08619b9167cc82a8b56072a1ed477 Mon Sep 17 00:00:00 2001 From: defanor Date: Mon, 30 Nov 2020 17:56:44 +0300 Subject: Reconnect on "reset" and "system-shutdown" stream errors --- README | 6 +++--- src/rexmpp.c | 25 +++++++++++++++++++------ src/rexmpp.h | 4 +++- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README b/README index 61e39e6..5b4d422 100644 --- a/README +++ b/README @@ -23,8 +23,8 @@ A rough roadmap: - Basic protocol: -[+] XMPP core (RFC 6120). A prototype is mostly ready, though it can - use more of error handling and refinement. +[+] XMPP core (RFC 6120). Mostly ready, though would be nice to + review and refactor. - Reliable and predictable message delivery: @@ -38,7 +38,7 @@ A rough roadmap: [+] "Happy Eyeballs" (RFC 8305). [+] XEP-0368 v1.1: SRV records for XMPP over TLS. -[+] SOCKS5 (RFC 1928) support. Implemented, though can be improved. +[+] SOCKS5 (RFC 1928) support. Implemented, though no authentication. [+] XEP-0199 v2.0: XMPP Ping. [.] Certificate verification using DANE (experimental). diff --git a/src/rexmpp.c b/src/rexmpp.c index 2594089..0857209 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -1091,9 +1091,12 @@ rexmpp_err_t rexmpp_recv (rexmpp_t *s) { } rexmpp_log(s, LOG_INFO, "TCP disconnected"); rexmpp_cleanup(s); - s->tcp_state = REXMPP_TCP_CLOSED; - if (s->stream_state == REXMPP_STREAM_READY) { + if (s->stream_state == REXMPP_STREAM_READY || + s->stream_state == REXMPP_STREAM_ERROR_RECONNECT) { + s->tcp_state = REXMPP_TCP_NONE; rexmpp_schedule_reconnect(s); + } else { + s->tcp_state = REXMPP_TCP_CLOSED; } } else { if (s->tls_state == REXMPP_TLS_ACTIVE) { @@ -2054,9 +2057,18 @@ rexmpp_err_t rexmpp_process_element (rexmpp_t *s, xmlNodePtr elem) { /* Stream errors, https://tools.ietf.org/html/rfc6120#section-4.9 */ if (rexmpp_xml_match(elem, "http://etherx.jabber.org/streams", "error")) { - rexmpp_log(s, LOG_ERR, "stream error"); - s->stream_state = REXMPP_STREAM_ERROR; - return REXMPP_E_STREAM; + if (rexmpp_xml_find_child(elem, "urn:ietf:params:xml:ns:xmpp-streams", + "reset") != NULL || + rexmpp_xml_find_child(elem, "urn:ietf:params:xml:ns:xmpp-streams", + "system-shutdown") != NULL) { + rexmpp_log(s, LOG_WARNING, "Server reset or shutdown."); + s->stream_state = REXMPP_STREAM_ERROR_RECONNECT; + return REXMPP_E_AGAIN; + } else { + rexmpp_log(s, LOG_ERR, "Stream error"); + s->stream_state = REXMPP_STREAM_ERROR; + return REXMPP_E_STREAM; + } } /* STARTTLS negotiation, @@ -2503,7 +2515,8 @@ rexmpp_err_t rexmpp_run (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds) { } } - if (s->tcp_state == REXMPP_TCP_CLOSED) { + if (s->tcp_state == REXMPP_TCP_CLOSED && + s->stream_state != REXMPP_STREAM_ERROR_RECONNECT) { rexmpp_console_on_run(s, REXMPP_SUCCESS); return REXMPP_SUCCESS; } else { diff --git a/src/rexmpp.h b/src/rexmpp.h index bd6f8cb..2f21fce 100644 --- a/src/rexmpp.h +++ b/src/rexmpp.h @@ -112,7 +112,9 @@ enum stream_st { /** The server-to-client stream is closed. */ REXMPP_STREAM_CLOSED, /** A stream error was detected in the server-to-client stream. */ - REXMPP_STREAM_ERROR + REXMPP_STREAM_ERROR, + /** A stream error that should be fixed by a reconnect. */ + REXMPP_STREAM_ERROR_RECONNECT }; /** @brief TLS state */ -- cgit v1.2.3