diff options
-rw-r--r-- | src/chat_session.c | 95 | ||||
-rw-r--r-- | src/chat_session.h | 5 | ||||
-rw-r--r-- | src/command/command.c | 33 | ||||
-rw-r--r-- | src/command/commands.c | 93 | ||||
-rw-r--r-- | src/otr/otr.c | 11 | ||||
-rw-r--r-- | src/server_events.c | 22 | ||||
-rw-r--r-- | src/xmpp/message.c | 19 | ||||
-rw-r--r-- | src/xmpp/stanza.c | 5 | ||||
-rw-r--r-- | src/xmpp/stanza.h | 2 | ||||
-rw-r--r-- | src/xmpp/xmpp.h | 8 | ||||
-rw-r--r-- | tests/test_server_events.c | 3 |
11 files changed, 209 insertions, 87 deletions
diff --git a/src/chat_session.c b/src/chat_session.c index d27a3449..8185ee8e 100644 --- a/src/chat_session.c +++ b/src/chat_session.c @@ -66,11 +66,11 @@ typedef struct chat_session_t { static GHashTable *sessions; static ChatSession* -_chat_session_new(const char * const barejid, gboolean supported) +_chat_session_new(const char * const barejid, const char * const resource, gboolean supported) { ChatSession *new_session = malloc(sizeof(struct chat_session_t)); new_session->barejid = strdup(barejid); - new_session->resource = NULL; + new_session->resource = strdup(resource); new_session->supported = supported; new_session->state = CHAT_STATE_STARTED; new_session->active_timer = g_timer_new(); @@ -84,6 +84,7 @@ _chat_session_free(ChatSession *session) { if (session != NULL) { free(session->barejid); + free(session->resource); if (session->active_timer != NULL) { g_timer_destroy(session->active_timer); session->active_timer = NULL; @@ -107,17 +108,31 @@ chat_sessions_clear(void) } gboolean +chat_session_exists(const char * const barejid) +{ + ChatSession *session = g_hash_table_lookup(sessions, barejid); + return (session != NULL); +} + +char* +chat_session_get_resource(const char * const barejid) +{ + ChatSession *session = g_hash_table_lookup(sessions, barejid); + if (session) { + return session->resource; + } else { + return NULL; + } +} + +gboolean chat_session_on_message_send(const char * const barejid) { gboolean send_state = FALSE; + if (prefs_get_boolean(PREF_STATES)) { ChatSession *session = g_hash_table_lookup(sessions, barejid); - if (!session) { - session = _chat_session_new(barejid, TRUE); - g_hash_table_insert(sessions, strdup(barejid), session); - - } - if (session->supported) { + if (session && session->supported) { session->state = CHAT_STATE_ACTIVE; g_timer_start(session->active_timer); session->sent = TRUE; @@ -129,26 +144,28 @@ chat_session_on_message_send(const char * const barejid) } void -chat_session_on_incoming_message(const char * const barejid, gboolean supported) +chat_session_on_incoming_message(const char * const barejid, const char * const resource, gboolean supported) { ChatSession *session = g_hash_table_lookup(sessions, barejid); - if (!session) { - session = _chat_session_new(barejid, supported); - g_hash_table_insert(sessions, strdup(barejid), session); - } else { - session->supported = supported; - } -} -void -chat_session_on_window_open(const char * const barejid) -{ - if (prefs_get_boolean(PREF_STATES)) { - ChatSession *session = g_hash_table_lookup(sessions, barejid); - if (!session) { - session = _chat_session_new(barejid, TRUE); + if (resource) { + if (session) { + if (g_strcmp0(session->resource, resource) != 0) { + log_info("Replacing chat session %s/%s, with new session %s/%s", session->barejid, session->resource, barejid, resource); + g_hash_table_remove(sessions, session); + session = _chat_session_new(barejid, resource, supported); + g_hash_table_insert(sessions, strdup(barejid), session); + } else { + session->supported = supported; + } + } else { + log_info("Starting chat session with %s/%s", barejid, resource); + session = _chat_session_new(barejid, resource, supported); g_hash_table_insert(sessions, strdup(barejid), session); } + } else if (session) { + log_info("Ending chat session with %s/%s, message received with no resource", session->barejid, session->resource); + g_hash_table_remove(sessions, session); } } @@ -158,7 +175,7 @@ chat_session_on_window_close(const char * const barejid) if (prefs_get_boolean(PREF_STATES)) { ChatSession *session = g_hash_table_lookup(sessions, barejid); // send <gone/> chat state before closing - if (session->supported) { + if (session && session->supported) { session->state = CHAT_STATE_GONE; message_send_gone(barejid); session->sent = TRUE; @@ -182,19 +199,19 @@ void chat_session_on_activity(const char * const barejid) { ChatSession *session = g_hash_table_lookup(sessions, barejid); - if (session) { - if (session->supported) { - if (session->state != CHAT_STATE_COMPOSING) { - session->sent = FALSE; - } + if (session && session->supported) { + if (session->state != CHAT_STATE_COMPOSING) { + session->sent = FALSE; + } - session->state = CHAT_STATE_COMPOSING; - g_timer_start(session->active_timer); + session->state = CHAT_STATE_COMPOSING; + g_timer_start(session->active_timer); - if (!session->sent || session->state == CHAT_STATE_PAUSED) { - message_send_composing(barejid); - session->sent = TRUE; - } + if (!session->sent || session->state == CHAT_STATE_PAUSED) { + Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource); + message_send_composing(jidp->fulljid); + session->sent = TRUE; + jid_destroy(jidp); } } } @@ -228,16 +245,18 @@ chat_session_on_inactivity(const char * const barejid) } if (session->sent == FALSE) { + Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource); if (session->state == CHAT_STATE_GONE) { - message_send_gone(barejid); + message_send_gone(jidp->fulljid); session->sent = TRUE; } else if (session->state == CHAT_STATE_INACTIVE) { - message_send_inactive(barejid); + message_send_inactive(jidp->fulljid); session->sent = TRUE; } else if (session->state == CHAT_STATE_PAUSED && prefs_get_boolean(PREF_OUTTYPE)) { - message_send_paused(barejid); + message_send_paused(jidp->fulljid); session->sent = TRUE; } + jid_destroy(jidp); } } } \ No newline at end of file diff --git a/src/chat_session.h b/src/chat_session.h index d1815f44..f9f47586 100644 --- a/src/chat_session.h +++ b/src/chat_session.h @@ -40,10 +40,11 @@ void chat_sessions_init(void); void chat_sessions_clear(void); +gboolean chat_session_exists(const char * const barejid); +char* chat_session_get_resource(const char * const barejid); gboolean chat_session_on_message_send(const char * const barejid); -void chat_session_on_window_open(const char * const barejid); void chat_session_on_window_close(const char * const barejid); -void chat_session_on_incoming_message(const char * const barejid, gboolean supported); +void chat_session_on_incoming_message(const char * const barejid, const char * const resource, gboolean supported); void chat_session_on_cancel(const char * const jid); void chat_session_on_activity(const char * const barejid); void chat_session_on_inactivity(const char * const recipient); diff --git a/src/command/command.c b/src/command/command.c index 5c1f858d..470bb886 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -1814,8 +1814,15 @@ cmd_execute_default(const char * inp) if (otr_is_secure(chatwin->barejid)) { char *encrypted = otr_encrypt_message(chatwin->barejid, inp); if (encrypted != NULL) { - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, chatwin->resource, encrypted, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, encrypted, send_state); otr_free_message(encrypted); if (prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_fulljid(); @@ -1835,8 +1842,15 @@ cmd_execute_default(const char * inp) cons_show_error("Failed to send message."); } } else { - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, chatwin->resource, inp, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, inp, send_state); if (prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_fulljid(); Jid *jidp = jid_create(jid); @@ -1847,8 +1861,15 @@ cmd_execute_default(const char * inp) ui_outgoing_chat_msg("me", chatwin->barejid, inp); } #else - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, chatwin->resource, inp, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, inp, send_state); if (prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_fulljid(); Jid *jidp = jid_create(jid); diff --git a/src/command/commands.c b/src/command/commands.c index 5b5bd95e..89fe9557 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1219,7 +1219,14 @@ cmd_msg(gchar **args, struct cmd_help_t help) if (otr_is_secure(barejid)) { char *encrypted = otr_encrypt_message(barejid, msg); if (encrypted != NULL) { - gboolean send_state = chat_session_on_message_send(barejid); + resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } message_send_chat(barejid, resource, encrypted, send_state); otr_free_message(encrypted); ui_outgoing_chat_msg("me", barejid, msg); @@ -1249,12 +1256,26 @@ cmd_msg(gchar **args, struct cmd_help_t help) GString *otr_message = g_string_new(msg); g_string_append(otr_message, OTRL_MESSAGE_TAG_BASE); g_string_append(otr_message, OTRL_MESSAGE_TAG_V2); - gboolean send_state = chat_session_on_message_send(barejid); + resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } message_send_chat(barejid, resource, otr_message->str, send_state); g_string_free(otr_message, TRUE); } else { - gboolean send_state = chat_session_on_message_send(barejid); + resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } message_send_chat(barejid, resource, msg, send_state); } ui_outgoing_chat_msg("me", barejid, msg); @@ -1268,7 +1289,14 @@ cmd_msg(gchar **args, struct cmd_help_t help) } return TRUE; #else - gboolean send_state = chat_session_on_message_send(barejid); + resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } message_send_chat(barejid, resource, msg, send_state); ui_outgoing_chat_msg("me", barejid, msg); @@ -1282,7 +1310,6 @@ cmd_msg(gchar **args, struct cmd_help_t help) #endif } else { // msg == NULL - chat_session_on_window_open(barejid); ui_new_chat_win(barejid); #ifdef HAVE_LIBOTR if (otr_is_secure(barejid)) { @@ -3009,8 +3036,15 @@ cmd_tiny(gchar **args, struct cmd_help_t help) if (otr_is_secure(chatwin->barejid)) { char *encrypted = otr_encrypt_message(chatwin->barejid, tiny); if (encrypted != NULL) { - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, chatwin->resource, encrypted, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, encrypted, send_state); otr_free_message(encrypted); if (prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_fulljid(); @@ -3030,8 +3064,15 @@ cmd_tiny(gchar **args, struct cmd_help_t help) cons_show_error("Failed to send message."); } } else { - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, chatwin->resource, tiny, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, tiny, send_state); if (prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_fulljid(); Jid *jidp = jid_create(jid); @@ -3042,8 +3083,15 @@ cmd_tiny(gchar **args, struct cmd_help_t help) ui_outgoing_chat_msg("me", chatwin->barejid, tiny); } #else - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, chatwin->resource, tiny, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, tiny, send_state); if (prefs_get_boolean(PREF_CHLOG)) { const char *jid = jabber_get_fulljid(); Jid *jidp = jid_create(jid); @@ -3951,7 +3999,6 @@ cmd_otr(gchar **args, struct cmd_help_t help) barejid = contact; } - chat_session_on_window_open(barejid); ui_new_chat_win(barejid); if (ui_current_win_is_otr()) { @@ -3961,8 +4008,15 @@ cmd_otr(gchar **args, struct cmd_help_t help) ui_current_print_formatted_line('!', 0, "You have not generated or loaded a private key, use '/otr gen'"); } else if (!otr_is_secure(barejid)) { char *otr_query_message = otr_start_query(); - gboolean send_state = chat_session_on_message_send(barejid); - message_send_chat(barejid, NULL, otr_query_message, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } + message_send_chat(barejid, resource, otr_query_message, send_state); } else { ui_gone_secure(barejid, otr_is_trusted(barejid)); } @@ -3980,8 +4034,15 @@ cmd_otr(gchar **args, struct cmd_help_t help) } else { ProfChatWin *chatwin = ui_get_current_chat(); char *otr_query_message = otr_start_query(); - gboolean send_state = chat_session_on_message_send(chatwin->barejid); - message_send_chat(chatwin->barejid, NULL, otr_query_message, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(chatwin->barejid)) { + resource = chat_session_get_resource(chatwin->barejid); + send_state = chat_session_on_message_send(chatwin->barejid); + } else { + send_state = TRUE; + } + message_send_chat(chatwin->barejid, resource, otr_query_message, send_state); } } } diff --git a/src/otr/otr.c b/src/otr/otr.c index 680c4c10..8e579b87 100644 --- a/src/otr/otr.c +++ b/src/otr/otr.c @@ -110,8 +110,15 @@ static void cb_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) { - gboolean send_state = chat_session_on_message_send(recipient); - message_send_chat(recipient, NULL, message, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(recipient)) { + resource = chat_session_get_resource(recipient); + send_state = chat_session_on_message_send(recipient); + } else { + send_state = TRUE; + } + message_send_chat(recipient, resource, message, send_state); } static void diff --git a/src/server_events.c b/src/server_events.c index 9d7883d6..f6874222 100644 --- a/src/server_events.c +++ b/src/server_events.c @@ -318,8 +318,15 @@ handle_incoming_message(char *barejid, char *message) memmove(whitespace_base, whitespace_base+tag_length, tag_length); char *otr_query_message = otr_start_query(); cons_show("OTR Whitespace pattern detected. Attempting to start OTR session..."); - gboolean send_state = chat_session_on_message_send(barejid); - message_send_chat(barejid, NULL, otr_query_message, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } + message_send_chat(barejid, resource, otr_query_message, send_state); } } } @@ -333,8 +340,15 @@ handle_incoming_message(char *barejid, char *message) if (policy == PROF_OTRPOLICY_ALWAYS && !was_decrypted && !whitespace_base) { char *otr_query_message = otr_start_query(); cons_show("Attempting to start OTR session..."); - gboolean send_state = chat_session_on_message_send(barejid); - message_send_chat(barejid, NULL, otr_query_message, send_state); + char *resource = NULL; + gboolean send_state = FALSE; + if (chat_session_exists(barejid)) { + resource = chat_session_get_resource(barejid); + send_state = chat_session_on_message_send(barejid); + } else { + send_state = TRUE; + } + message_send_chat(barejid, resource, otr_query_message, send_state); } ui_incoming_msg(barejid, newmessage, NULL); diff --git a/src/xmpp/message.c b/src/xmpp/message.c index d87c5fb2..4b2a517f 100644 --- a/src/xmpp/message.c +++ b/src/xmpp/message.c @@ -149,23 +149,22 @@ message_send_invite(const char * const roomjid, const char * const contact, } void -message_send_composing(const char * const barejid) +message_send_composing(const char * const fulljid) { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid, - STANZA_NAME_COMPOSING); + xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, fulljid, STANZA_NAME_COMPOSING); xmpp_send(conn, stanza); xmpp_stanza_release(stanza); } void -message_send_paused(const char * const barejid) +message_send_paused(const char * const fulljid) { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid, + xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, fulljid, STANZA_NAME_PAUSED); xmpp_send(conn, stanza); @@ -173,11 +172,11 @@ message_send_paused(const char * const barejid) } void -message_send_inactive(const char * const barejid) +message_send_inactive(const char * const fulljid) { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid, + xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, fulljid, STANZA_NAME_INACTIVE); xmpp_send(conn, stanza); @@ -185,11 +184,11 @@ message_send_inactive(const char * const barejid) } void -message_send_gone(const char * const barejid) +message_send_gone(const char * const fulljid) { xmpp_conn_t * const conn = connection_get_conn(); xmpp_ctx_t * const ctx = connection_get_ctx(); - xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, barejid, + xmpp_stanza_t *stanza = stanza_create_chat_state(ctx, fulljid, STANZA_NAME_GONE); xmpp_send(conn, stanza); @@ -469,7 +468,7 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, } // create or update chat session - chat_session_on_incoming_message(jid->barejid, recipient_supports); + chat_session_on_incoming_message(jid->barejid, jid->resourcepart, recipient_supports); // determine if the notifications happened whilst offline GTimeVal tv_stamp; diff --git a/src/xmpp/stanza.c b/src/xmpp/stanza.c index 1766fe26..4f1d412d 100644 --- a/src/xmpp/stanza.c +++ b/src/xmpp/stanza.c @@ -199,15 +199,14 @@ stanza_create_bookmarks_pubsub_add(xmpp_ctx_t *ctx, const char * const jid, #endif xmpp_stanza_t * -stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const recipient, - const char * const state) +stanza_create_chat_state(xmpp_ctx_t *ctx, const char * const fulljid, const char * const state) { xmpp_stanza_t *msg, *chat_state; msg = xmpp_stanza_new(ctx); xmpp_stanza_set_name(msg, STANZA_NAME_MESSAGE); xmpp_stanza_set_type(msg, STANZA_TYPE_CHAT); - xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, recipient); + xmpp_stanza_set_attribute(msg, STANZA_ATTR_TO, fulljid); char *id = create_unique_id(NULL); xmpp_stanza_set_id(msg, id); free(id); diff --git a/src/xmpp/stanza.h b/src/xmpp/stanza.h index e60e9fe1..84282401 100644 --- a/src/xmpp/stanza.h +++ b/src/xmpp/stanza.h @@ -179,7 +179,7 @@ typedef enum { xmpp_stanza_t* stanza_create_bookmarks_storage_request(xmpp_ctx_t *ctx); xmpp_stanza_t* stanza_create_chat_state(xmpp_ctx_t *ctx, - const char * const recipient, const char * const state); + const char * const fulljid, const char * const state); xmpp_stanza_t* stanza_create_message(xmpp_ctx_t *ctx, const char * const recipient, const char * const type, diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 2499d008..d4d35c6b 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -151,10 +151,10 @@ void message_send_private(const char * const fulljid, const char * const msg); void message_send_groupchat(const char * const roomjid, const char * const msg); void message_send_groupchat_subject(const char * const roomjid, const char * const subject); -void message_send_inactive(const char * const barejid); -void message_send_composing(const char * const barejid); -void message_send_paused(const char * const barejid); -void message_send_gone(const char * const barejid); +void message_send_inactive(const char * const fulljid); +void message_send_composing(const char * const fulljid); +void message_send_paused(const char * const fulljid); +void message_send_gone(const char * const fulljid); void message_send_invite(const char * const room, const char * const contact, const char * const reason); diff --git a/tests/test_server_events.c b/tests/test_server_events.c index 435493a2..67d4ecb2 100644 --- a/tests/test_server_events.c +++ b/tests/test_server_events.c @@ -130,11 +130,12 @@ void handle_message_error_when_recipient_cancel_disables_chat_session(void **sta { char *err_msg = "Some error."; char *from = "bob@server.com"; + char *resource = "resource"; char *type = "cancel"; prefs_set_boolean(PREF_STATES, TRUE); chat_sessions_init(); - chat_session_on_incoming_message(from, TRUE); + chat_session_on_incoming_message(from, resource, TRUE); expect_any(ui_handle_recipient_not_found, recipient); expect_any(ui_handle_recipient_not_found, err_msg); |