/* * session.c * vim: expandtab:ts=4:sts=4:sw=4 * * Copyright (C) 2012 - 2019 James Booth * * This file is part of Profanity. * * Profanity is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Profanity is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Profanity. If not, see . * * In addition, as a special exception, the copyright holders give permission to * link the code of portions of this program with the OpenSSL library under * certain conditions as described in each individual source file, and * distribute linked combinations including the two. * * You must obey the GNU General Public License in all respects for all of the * code used other than OpenSSL. If you modify file(s) with this exception, you * may extend this exception to your version of the file(s), but you are not * obligated to do so. If you do not wish to do so, delete this exception * statement from your version. If you delete this exception statement from all * source files in the program, then also delete it here. * */ #include "config.h" #include #include #include #include "profanity.h" #include "log.h" #include "common.h" #include "config/preferences.h" #include "plugins/plugins.h" #include "event/server_events.h" #include "event/client_events.h" #include "xmpp/bookmark.h" #include "xmpp/blocking.h" #include "xmpp/connection.h" #include "xmpp/capabilities.h" #include "xmpp/session.h" #include "xmpp/iq.h" #include "xmpp/message.h" #include "xmpp/presence.h" #include "xmpp/roster.h" #include "xmpp/stanza.h" #include "xmpp/xmpp.h" #include "xmpp/muc.h" #include "xmpp/chat_session.h" #include "xmpp/jid.h" #ifdef HAVE_OMEMO #include "omemo/omemo.h" #include "xmpp/omemo.h" #endif // for auto reconnect static struct { char *name; char *passwd; } saved_account; static struct { char *name; char *jid; char *passwd; char *altdomain; int port; char *tls_policy; } saved_details; typedef enum { ACTIVITY_ST_ACTIVE, ACTIVITY_ST_IDLE, ACTIVITY_ST_AWAY, ACTIVITY_ST_XA, } activity_state_t; static GTimer *reconnect_timer; static activity_state_t activity_state; static resource_presence_t saved_presence; static char *saved_status; static void _session_reconnect(void); static void _session_free_saved_account(void); static void _session_free_saved_details(void); void session_init(void) { log_info("Initialising XMPP"); connection_init(); presence_sub_requests_init(); caps_init(); } jabber_conn_status_t session_connect_with_account(const ProfAccount *const account) { assert(account != NULL); log_info("Connecting using account: %s", account->name); _session_free_saved_account(); _session_free_saved_details(); // save account name and password for reconnect saved_account.name = strdup(account->name); saved_account.passwd = strdup(account->password); char *jid = NULL; if (account->resource) { Jid *jidp = jid_create_from_bare_and_resource(account->jid, account->resource); jid = strdup(jidp->fulljid); jid_destroy(jidp); } else { jid = strdup(account->jid); } jabber_conn_status_t result = connection_connect( jid, account->password, account->server, account->port, account->tls_policy); free(jid); return result; } jabber_conn_status_t session_connect_with_details(const char *const jid, const char *const passwd, const char *const altdomain, const int port, const char *const tls_policy) { assert(jid != NULL); assert(passwd != NULL); _session_free_saved_account(); _session_free_saved_details(); // save details for reconnect, remember name for account creating on success saved_details.name = strdup(jid); saved_details.passwd = strdup(passwd); if (altdomain) { saved_details.altdomain = strdup(altdomain); } else { saved_details.altdomain = NULL; } if (port != 0) { saved_details.port = port; } else { saved_details.port = 0; } if (tls_policy) { saved_details.tls_policy = strdup(tls_policy); } else { saved_details.tls_policy = NULL; } // use 'profanity' when no resourcepart in provided jid Jid *jidp = jid_create(jid); if (jidp->resourcepart == NULL) { jid_destroy(jidp); char *resource = jid_random_resource(); jidp = jid_create_from_bare_and_resource(jid, resource); free(resource); saved_details.jid = strdup(jidp->fulljid); } else { saved_details.jid = strdup(jid); } jid_destroy(jidp); // connect with fulljid log_info("Connecting without account, JID: %s", saved_details.jid); return connection_connect( saved_details.jid, passwd, saved_details.altdomain, saved_details.port, saved_details.tls_policy); } void session_autoping_fail(void) { session_lost_connection(); } void session_disconnect(void) { // if connected, send end stream and wait for response if (connection_get_status() == JABBER_CONNECTED) { log_info("Closing connection"); char *account_name = session_get_account_name(); const char *fulljid = connection_get_fulljid(); plugins_on_disconnect(account_name, fulljid); accounts_set_last_activity(session_get_account_name()); iq_rooms_cache_clear(); iq_handlers_clear(); connection_disconnect(); message_handlers_clear(); connection_clear_data(); chat_sessions_clear(); presence_clear_sub_requests(); } connection_set_disconnected(); } void session_shutdown(void) { _session_free_saved_account(); _session_free_saved_details(); chat_sessions_clear(); presence_clear_sub_requests(); connection_shutdown(); if (saved_status) { free(saved_status); } } void session_process_events(void) { int reconnect_sec; jabber_conn_status_t conn_status = connection_get_status(); switch (conn_status) { case JABBER_CONNECTED: case JABBER_CONNECTING: case JABBER_DISCONNECTING: connection_check_events(); break; case JABBER_DISCONNECTED: reconnect_sec = prefs_get_reconnect(); if ((reconnect_sec != 0) && reconnect_timer) { int elapsed_sec = g_timer_elapsed(reconnect_timer, NULL); if (elapsed_sec > reconnect_sec) { _session_reconnect(); } } break; default: break; } } char* session_get_account_name(void) { return saved_account.name; } void session_lo
c{0: 0 (((1 integer)) <- ((copy)) ((2 literal))) -- nil
c{0: 1 (((2 integer)) <- ((copy)) ((23 literal))) -- nil
c{0: 2 (((3 boolean)) <- ((copy)) ((nil literal))) -- nil
c{0: 3 (((4 integer)) <- ((copy)) ((24 literal))) -- nil
c{0: 4 (((5 boolean)) <- ((copy)) ((t literal))) -- nil
c{0: 5 (((6 integer)) <- ((copy)) ((1 literal))) -- nil
c{0: 6 (((7 integer-boolean-pair-array-address)) <- ((copy)) ((1 literal))) -- nil
c{0: 7 (((8 integer-boolean-pair-address)) <- ((index-address)) ((7 integer-boolean-pair-array-address) (deref)) ((6 integer))) -- nil
c{1: 0 ✓ (((1 integer)) <- ((copy)) ((2 literal)))
c{1: 1 ✓ (((2 integer)) <- ((copy)) ((23 literal)))
c{1: 2 ✓ (((3 boolean)) <- ((copy)) ((nil literal)))
c{1: 3 ✓ (((4 integer)) <- ((copy)) ((24 literal)))
c{1: 4 ✓ (((5 boolean)) <- ((copy)) ((t literal)))
c{1: 5 ✓ (((6 integer)) <- ((copy)) ((1 literal)))
c{1: 6 ✓ (((7 integer-boolean-pair-array-address)) <- ((copy)) ((1 literal)))
c{1: 7 ✓ (((8 integer-boolean-pair-address)) <- ((index-address)) ((7 integer-boolean-pair-array-address) (deref)) ((6 integer)))
cn0: convert-names in main
cn0: (((1 integer)) <- ((copy)) ((2 literal))) nil nil
cn0: checking arg ((2 literal))
cn0: checking oarg ((1 integer))
maybe-add: ((1 integer))
cn0: (((2 integer)) <- ((copy)) ((23 literal))) nil nil
cn0: checking arg ((23 literal))
cn0: checking oarg ((2 integer))
maybe-add: ((2 integer))
cn0: (((3 boolean)) <- ((copy)) ((nil literal))) nil nil
cn0: checking arg ((nil literal))
cn0: checking oarg ((3 boolean))
maybe-add: ((3 boolean))
cn0: (((4 integer)) <- ((copy)) ((24 literal))) nil nil
cn0: checking arg ((24 literal))
cn0: checking oarg ((4 integer))
maybe-add: ((4 integer))
cn0: (((5 boolean)) <- ((copy)) ((t literal))) nil nil
cn0: checking arg ((t literal))
cn0: checking oarg ((5 boolean))
maybe-add: ((5 boolean))
cn0: (((6 integer)) <- ((copy)) ((1 literal))) nil nil
cn0: checking arg ((1 literal))
cn0: checking oarg ((6 integer))
maybe-add: ((6 integer))
cn0: (((7 integer-boolean-pair-array-address)) <- ((copy)) ((1 literal))) nil nil
cn0: checking arg ((1 literal))
cn0: checking oarg ((7 integer-boolean-pair-array-address))
maybe-add: ((7 integer-boolean-pair-array-address))
cn0: (((8 integer-boolean-pair-address)) <- ((index-address)) ((7 integer-boolean-pair-array-address) (deref)) ((6 integer))) nil nil
cn0: checking arg ((7 integer-boolean-pair-array-address) (deref))
maybe-add: ((7 integer-boolean-pair-array-address) (deref))
cn0: checking arg ((6 integer))
maybe-add: ((6 integer))
cn0: checking oarg ((8 integer-boolean-pair-address))
maybe-add: ((8 integer-boolean-pair-address))
cn1: (((1 integer)) <- ((copy)) ((2 literal)))
cn1: (((2 integer)) <- ((copy)) ((23 literal)))
cn1: (((3 boolean)) <- ((copy)) ((nil literal)))
cn1: (((4 integer)) <- ((copy)) ((24 literal)))
cn1: (((5 boolean)) <- ((copy)) ((t literal)))
cn1: (((6 integer)) <- ((copy)) ((1 literal)))
cn1: (((7 integer-boolean-pair-array-address)) <- ((copy)) ((1 literal)))
cn1: (((8 integer-boolean-pair-address)) <- ((index-address)) ((7 integer-boolean-pair-array-address) (