1
1
mirror of https://github.com/profanity-im/profanity.git synced 2025-02-02 15:08:15 -05:00

Merge pull request #1631 from profanity-im/fix-1628

Fix #1628
This commit is contained in:
Michael Vetter 2022-02-01 16:51:12 +01:00 committed by GitHub
commit 9a1311a826
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 291 additions and 148 deletions

View File

@ -22,6 +22,7 @@ AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true AllowAllArgumentsOnNextLine: true
AllowShortBlocksOnASingleLine: true AllowShortBlocksOnASingleLine: true
IndentGotoLabels: false
IndentWidth: 4 IndentWidth: 4
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BraceWrapping: BraceWrapping:

View File

@ -388,7 +388,9 @@ omemo_publish_crypto_materials(void)
omemo_bundle_publish(true); omemo_bundle_publish(true);
} }
static void _acquire_sender_devices_list(void) { static void
_acquire_sender_devices_list(void)
{
char* barejid = connection_get_barejid(); char* barejid = connection_get_barejid();
g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_own_device_list); g_hash_table_insert(omemo_ctx.device_list_handler, strdup(barejid), _handle_own_device_list);

View File

@ -872,6 +872,106 @@ connection_set_priority(const int priority)
conn.priority = priority; conn.priority = priority;
} }
#if defined(LIBXMPP_VERSION_MAJOR) && defined(LIBXMPP_VERSION_MINOR) \
&& ((LIBXMPP_VERSION_MAJOR > 0) || (LIBXMPP_VERSION_MINOR >= 12))
static xmpp_stanza_t*
_get_soh_error(xmpp_stanza_t* error_stanza)
{
return xmpp_stanza_get_child_by_path(error_stanza,
XMPP_STANZA_NAME_IN_NS("error", STANZA_NS_STREAMS),
XMPP_STANZA_NAME_IN_NS("see-other-host", STANZA_NS_XMPP_STREAMS),
NULL);
}
#else
static xmpp_stanza_t*
_get_soh_error(xmpp_stanza_t* error_stanza)
{
const char* name = xmpp_stanza_get_name(error_stanza);
const char* ns = xmpp_stanza_get_ns(error_stanza);
if (!name || !ns || strcmp(name, "error") || strcmp(ns, STANZA_NS_STREAMS)) {
log_debug("_get_soh_error: could not find error stanza");
return NULL;
}
return xmpp_stanza_get_child_by_name_and_ns(error_stanza, "see-other-host", STANZA_NS_XMPP_STREAMS);
}
#endif
#if GLIB_CHECK_VERSION(2, 66, 0)
static gboolean
_split_url(const char* alturi, gchar** host, gint* port)
{
/* Construct a valid URI with `schema://` as `g_uri_split_network()`
* requires this to be there.
*/
const char* xmpp = "xmpp://";
char* xmpp_uri = malloc(strlen(xmpp) + strlen(alturi) + 1);
if (!xmpp_uri) {
log_debug("_get_other_host: malloc failed \"%s\"", alturi);
return false;
}
memcpy(xmpp_uri, xmpp, strlen(xmpp));
memcpy(xmpp_uri + strlen(xmpp), alturi, strlen(alturi) + 1);
gboolean ret = g_uri_split_network(xmpp_uri, 0, NULL, host, port, NULL);
free(xmpp_uri);
/* fix-up `port` as g_uri_split_network() sets port to `-1` if it's missing
* in the passed-in URI, but libstrophe expects a "missing port"
* to be passed as `0` (which then results in connecting to the standard port).
*/
if (*port == -1)
*port = 0;
return ret;
}
#else
/* poor-mans URL splitting */
static gboolean
_split_url(const char* alturi, gchar** host, gint* port)
{
ptrdiff_t hostlen;
/* search ':' from start and end
* if `first` matches `last` it's a `hostname:port` combination
* if `first` is different than `last` it's `[ip:v6]:port`
*/
char* first = strchr(alturi, ':');
char* last = strrchr(alturi, ':');
if (first && first == last) {
hostlen = last - alturi;
if (!strtoi_range(last + 1, port, 1, 65535, NULL))
return FALSE;
} else {
hostlen = strlen(alturi) + 1;
*port = 0;
}
gchar* buf = g_malloc(hostlen);
if (!buf)
return FALSE;
memcpy(buf, alturi, hostlen);
buf[hostlen - 1] = '\0';
*host = buf;
return TRUE;
}
#endif
static bool
_get_other_host(xmpp_stanza_t* error_stanza, gchar** host, int* port)
{
xmpp_stanza_t* soh_error = _get_soh_error(error_stanza);
if (!soh_error || !xmpp_stanza_get_children(soh_error)) {
log_debug("_get_other_host: stream-error contains no see-other-host");
return false;
}
const char* alturi = xmpp_stanza_get_text_ptr(xmpp_stanza_get_children(soh_error));
if (!alturi) {
log_debug("_get_other_host: see-other-host contains no text");
return false;
}
if (!_split_url(alturi, host, port)) {
log_debug("_get_other_host: Could not split \"%s\"", alturi);
return false;
}
return true;
}
static void static void
_connection_handler(xmpp_conn_t* const xmpp_conn, const xmpp_conn_event_t status, const int error, _connection_handler(xmpp_conn_t* const xmpp_conn, const xmpp_conn_event_t status, const int error,
xmpp_stream_error_t* const stream_error, void* const userdata) xmpp_stream_error_t* const stream_error, void* const userdata)
@ -924,6 +1024,14 @@ _connection_handler(xmpp_conn_t* const xmpp_conn, const xmpp_conn_event_t status
// login attempt failed // login attempt failed
} else if (conn.conn_status != JABBER_DISCONNECTING) { } else if (conn.conn_status != JABBER_DISCONNECTING) {
gchar* host;
int port;
if (stream_error && stream_error->stanza && _get_other_host(stream_error->stanza, &host, &port)) {
session_reconnect(host, port);
log_debug("Connection handler: Forcing a re-connect to \"%s\"", host);
conn.conn_status = JABBER_RECONNECT;
return;
}
log_debug("Connection handler: Login failed"); log_debug("Connection handler: Login failed");
session_login_failed(); session_login_failed();
} }

View File

@ -98,7 +98,7 @@ static char* saved_status;
static void _session_reconnect(void); static void _session_reconnect(void);
static void _session_free_saved_account(void); static void _session_free_internals(void);
static void _session_free_saved_details(void); static void _session_free_saved_details(void);
void void
@ -117,8 +117,7 @@ session_connect_with_account(const ProfAccount* const account)
log_info("Connecting using account: %s", account->name); log_info("Connecting using account: %s", account->name);
_session_free_saved_account(); _session_free_internals();
_session_free_saved_details();
// save account name and password for reconnect // save account name and password for reconnect
saved_account.name = strdup(account->name); saved_account.name = strdup(account->name);
@ -152,8 +151,7 @@ session_connect_with_details(const char* const jid, const char* const passwd, co
assert(jid != NULL); assert(jid != NULL);
assert(passwd != NULL); assert(passwd != NULL);
_session_free_saved_account(); _session_free_internals();
_session_free_saved_details();
// save details for reconnect, remember name for account creating on success // save details for reconnect, remember name for account creating on success
saved_details.name = strdup(jid); saved_details.name = strdup(jid);
@ -240,8 +238,7 @@ session_disconnect(void)
void void
session_shutdown(void) session_shutdown(void)
{ {
_session_free_saved_account(); _session_free_internals();
_session_free_saved_details();
chat_sessions_clear(); chat_sessions_clear();
presence_clear_sub_requests(); presence_clear_sub_requests();
@ -275,6 +272,9 @@ session_process_events(void)
} }
} }
break; break;
case JABBER_RECONNECT:
_session_reconnect();
break;
default: default:
break; break;
} }
@ -371,8 +371,7 @@ session_login_failed(void)
if (reconnect_timer == NULL) { if (reconnect_timer == NULL) {
log_debug("Connection handler: No reconnect timer"); log_debug("Connection handler: No reconnect timer");
sv_ev_failed_login(); sv_ev_failed_login();
_session_free_saved_account(); _session_free_internals();
_session_free_saved_details();
} else { } else {
log_debug("Connection handler: Restarting reconnect timer"); log_debug("Connection handler: Restarting reconnect timer");
if (prefs_get_reconnect() != 0) { if (prefs_get_reconnect() != 0) {
@ -394,8 +393,7 @@ session_lost_connection(void)
assert(reconnect_timer == NULL); assert(reconnect_timer == NULL);
reconnect_timer = g_timer_new(); reconnect_timer = g_timer_new();
} else { } else {
_session_free_saved_account(); _session_free_internals();
_session_free_saved_details();
} }
} }
@ -537,6 +535,24 @@ session_check_autoaway(void)
g_free(mode); g_free(mode);
} }
static struct
{
gchar* altdomain;
unsigned short altport;
} reconnect;
/* This takes ownership of `altdomain`, i.e. the caller must not
* free the value after calling this function.
*/
void
session_reconnect(gchar* altdomain, unsigned short altport)
{
reconnect.altdomain = altdomain;
reconnect.altport = altport;
assert(reconnect_timer == NULL);
reconnect_timer = g_timer_new();
}
static void static void
_session_reconnect(void) _session_reconnect(void)
{ {
@ -553,19 +569,30 @@ _session_reconnect(void)
} else { } else {
jid = strdup(account->jid); jid = strdup(account->jid);
} }
const char* server;
unsigned short port;
if (reconnect.altdomain) {
server = reconnect.altdomain;
port = reconnect.altport;
} else {
server = account->server;
port = account->port;
}
log_debug("Attempting reconnect with account %s", account->name); log_debug("Attempting reconnect with account %s", account->name);
connection_connect(jid, saved_account.passwd, account->server, account->port, account->tls_policy, account->auth_policy); connection_connect(jid, saved_account.passwd, server, port, account->tls_policy, account->auth_policy);
free(jid); free(jid);
account_free(account); account_free(account);
g_timer_start(reconnect_timer); g_timer_start(reconnect_timer);
} }
static void static void
_session_free_saved_account(void) _session_free_internals(void)
{ {
FREE_SET_NULL(saved_account.name); FREE_SET_NULL(saved_account.name);
FREE_SET_NULL(saved_account.passwd); FREE_SET_NULL(saved_account.passwd);
GFREE_SET_NULL(reconnect.altdomain);
_session_free_saved_details();
} }
static void static void

View File

@ -46,4 +46,6 @@ void session_autoping_fail(void);
void session_init_activity(void); void session_init_activity(void);
void session_check_autoaway(void); void session_check_autoaway(void);
void session_reconnect(gchar* altdomain, unsigned short altport);
#endif #endif

View File

@ -245,6 +245,8 @@
#define STANZA_NS_REPORTING "urn:xmpp:reporting:1" #define STANZA_NS_REPORTING "urn:xmpp:reporting:1"
#define STANZA_NS_MOOD "http://jabber.org/protocol/mood" #define STANZA_NS_MOOD "http://jabber.org/protocol/mood"
#define STANZA_NS_MOOD_NOTIFY "http://jabber.org/protocol/mood+notify" #define STANZA_NS_MOOD_NOTIFY "http://jabber.org/protocol/mood+notify"
#define STANZA_NS_STREAMS "http://etherx.jabber.org/streams"
#define STANZA_NS_XMPP_STREAMS "urn:ietf:params:xml:ns:xmpp-streams"
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo" #define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"

View File

@ -72,7 +72,8 @@ typedef enum {
JABBER_DISCONNECTING, JABBER_DISCONNECTING,
JABBER_DISCONNECTED, JABBER_DISCONNECTED,
JABBER_RAW_CONNECTING, JABBER_RAW_CONNECTING,
JABBER_RAW_CONNECTED JABBER_RAW_CONNECTED,
JABBER_RECONNECT
} jabber_conn_status_t; } jabber_conn_status_t;
typedef enum { typedef enum {