diff --git a/account.c b/account.c index b76434d..25d8454 100644 --- a/account.c +++ b/account.c @@ -28,6 +28,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] = { "tls", "normal" }, { "nickname", "" }, { "autoconnect", "" }, + { "resource", "" }, }; struct t_account *account__search(const char *name) diff --git a/account.h b/account.h index 8f2b040..b5fe1d1 100644 --- a/account.h +++ b/account.h @@ -15,6 +15,7 @@ enum t_account_option ACCOUNT_OPTION_TLS, ACCOUNT_OPTION_NICKNAME, ACCOUNT_OPTION_AUTOCONNECT, + ACCOUNT_OPTION_RESOURCE, ACCOUNT_NUM_OPTIONS, }; @@ -29,6 +30,13 @@ enum t_account_option #define account_jid(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_JID]) +#define account_jid_device(account) \ + xmpp_jid_new(account->context, \ + xmpp_jid_node(account->context, \ + weechat_config_string(account->options[ACCOUNT_OPTION_JID])), \ + xmpp_jid_domain(account->context, \ + weechat_config_string(account->options[ACCOUNT_OPTION_JID])), \ + "weechat") #define account_password(account) \ weechat_config_string(account->options[ACCOUNT_OPTION_PASSWORD]) #define account_tls(account) \ @@ -37,6 +45,8 @@ enum t_account_option weechat_config_string(account->options[ACCOUNT_OPTION_NICKNAME]) #define account_autoconnect(account) \ weechat_config_boolean(account->options[ACCOUNT_OPTION_AUTOCONNECT]) +#define account_resource(account) \ + weechat_config_string(account->options[ACCOUNT_OPTION_RESOURCE]) struct t_account { diff --git a/command.c b/command.c index 78bd7c4..55dacac 100644 --- a/command.c +++ b/command.c @@ -428,6 +428,7 @@ int command__open(const void *pointer, void *data, pres = xmpp_presence_new(ptr_account->context); xmpp_stanza_set_to(pres, jid); + xmpp_stanza_set_from(pres, account_jid(ptr_account)); xmpp_send(ptr_account->connection, pres); xmpp_stanza_release(pres); diff --git a/config.c b/config.c index b2cf31f..a963b31 100644 --- a/config.c +++ b/config.c @@ -154,6 +154,22 @@ config__account_new_option (struct t_config_file *config_file, callback_change_data, NULL, NULL, NULL); break; + case ACCOUNT_OPTION_RESOURCE: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("XMPP Account Resource"), + NULL, 0, 0, + default_value, value, + null_value_allowed, + callback_check_value, + callback_check_value_pointer, + callback_check_value_data, + callback_change, + callback_change_pointer, + callback_change_data, + NULL, NULL, NULL); + break; case ACCOUNT_NUM_OPTIONS: break; } diff --git a/connection.c b/connection.c index 241d588..7dbf5cd 100644 --- a/connection.c +++ b/connection.c @@ -2,7 +2,9 @@ // License, version 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +#include #include +#include #include #include #include @@ -141,6 +143,7 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, /* Send initial so that we appear online to contacts */ pres = xmpp_presence_new(account->context); + xmpp_stanza_set_from(pres, account_jid(account)); xmpp_send(conn, pres); xmpp_stanza_release(pres); } else { @@ -149,11 +152,41 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status, } } +char *const rand_string(int length) +{ + char *string = malloc(length); + srand(time(NULL)); + for(int i = 0; i < length; ++i){ + string[i] = '0' + rand()%72; // starting on '0', ending on '}' + if (!((string[i] >= '0' && string[i] <= '9') || + (string[i] >= 'A' && string[i] <= 'Z') || + (string[i] >= 'a' && string[i] <= 'z'))) + i--; // reroll + } + string[length] = 0; + return string; +} + int connection__connect(struct t_account *account, xmpp_conn_t **connection, const char* jid, const char* password, int tls) { *connection = xmpp_conn_new(account->context); - xmpp_conn_set_jid(*connection, jid); + char *resource = account_resource(account); + if (!(resource && strlen(resource))) + { + char *const rand = rand_string(8); + char ident[64] = {0}; + snprintf(ident, sizeof(ident), "weechat.%s", rand); + free(rand); + + account_option_set(account, ACCOUNT_OPTION_RESOURCE, ident); + resource = account_resource(account); + } + xmpp_conn_set_jid(*connection, + xmpp_jid_new(account->context, + xmpp_jid_node(account->context, jid), + xmpp_jid_domain(account->context, jid), + resource)); xmpp_conn_set_pass(*connection, password); auto flags = xmpp_conn_get_flags(*connection);