about summary refs log tree commit diff stats
path: root/src/xmpp
diff options
context:
space:
mode:
authorSteffen Jaeckel <jaeckel-floss@eyet-services.de>2023-01-09 18:00:47 +0100
committerSteffen Jaeckel <jaeckel-floss@eyet-services.de>2023-01-19 10:40:25 +0100
commitb535921484f1a1a083fc1582be5a21722abb16ee (patch)
treeff21a53f63a032272a25b1624106325f11b24179 /src/xmpp
parent1a85448bf21ee7c3e217e5cb0d51364516018075 (diff)
downloadprofani-tty-b535921484f1a1a083fc1582be5a21722abb16ee.tar.gz
introduce `auto_jid` and refcounting in `Jid`
This also fixes a memory leak from within `_handle_groupchat()` in [0].

[0] src/xmpp/message.c

Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
Diffstat (limited to 'src/xmpp')
-rw-r--r--src/xmpp/jid.c19
-rw-r--r--src/xmpp/jid.h5
-rw-r--r--src/xmpp/message.c38
3 files changed, 36 insertions, 26 deletions
diff --git a/src/xmpp/jid.c b/src/xmpp/jid.c
index 33c3d19f..af0a606b 100644
--- a/src/xmpp/jid.c
+++ b/src/xmpp/jid.c
@@ -76,6 +76,7 @@ jid_create(const gchar* const str)
     result->resourcepart = NULL;
     result->barejid = NULL;
     result->fulljid = NULL;
+    result->refcnt = 1;
 
     gchar* atp = g_utf8_strchr(trimmed, -1, '@');
     gchar* slashp = g_utf8_strchr(trimmed, -1, '/');
@@ -120,11 +121,29 @@ jid_create_from_bare_and_resource(const char* const barejid, const char* const r
 }
 
 void
+jid_auto_destroy(Jid** jid)
+{
+    if (jid == NULL)
+        return;
+    jid_destroy(*jid);
+}
+
+void
+jid_ref(Jid* jid)
+{
+    jid->refcnt++;
+}
+
+void
 jid_destroy(Jid* jid)
 {
     if (jid == NULL) {
         return;
     }
+    if (jid->refcnt > 1) {
+        jid->refcnt--;
+        return;
+    }
 
     g_free(jid->str);
     g_free(jid->localpart);
diff --git a/src/xmpp/jid.h b/src/xmpp/jid.h
index dae6cb2d..e55ea0c7 100644
--- a/src/xmpp/jid.h
+++ b/src/xmpp/jid.h
@@ -40,6 +40,7 @@
 
 struct jid_t
 {
+    unsigned int refcnt;
     char* str;
     char* localpart;
     char* domainpart;
@@ -53,6 +54,10 @@ typedef struct jid_t Jid;
 Jid* jid_create(const gchar* const str);
 Jid* jid_create_from_bare_and_resource(const char* const barejid, const char* const resource);
 void jid_destroy(Jid* jid);
+void jid_ref(Jid* jid);
+
+void jid_auto_destroy(Jid** str);
+#define auto_jid __attribute__((__cleanup__(jid_auto_destroy)))
 
 gboolean jid_is_valid_room_form(Jid* jid);
 char* create_fulljid(const char* const barejid, const char* const resource);
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index a81108fa..bc716b24 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -468,7 +468,7 @@ message_send_chat_pgp(const char* const barejid, const char* const msg, gboolean
     char* account_name = session_get_account_name();
     ProfAccount* account = accounts_get_account(account_name);
     if (account->pgp_keyid) {
-        Jid* jidp = jid_create(jid);
+        auto_jid Jid* jidp = jid_create(jid);
         char* encrypted = p_gpg_encrypt(jidp->barejid, msg, account->pgp_keyid);
         if (encrypted) {
             message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id);
@@ -487,7 +487,6 @@ message_send_chat_pgp(const char* const barejid, const char* const msg, gboolean
             message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id);
             xmpp_message_set_body(message, msg);
         }
-        jid_destroy(jidp);
     } else {
         message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id);
         xmpp_message_set_body(message, msg);
@@ -526,11 +525,10 @@ message_send_chat_ox(const char* const barejid, const char* const msg, gboolean
     xmpp_ctx_t* const ctx = connection_get_ctx();
 
     const char* state = chat_session_get_state(barejid);
-    char* jid = chat_session_get_jid(barejid);
+    auto_char char* jid = chat_session_get_jid(barejid);
     char* id = connection_create_stanza_id();
 
     xmpp_stanza_t* message = NULL;
-    Jid* jidp = jid_create(jid);
 
     char* account_name = session_get_account_name();
     ProfAccount* account = accounts_get_account(account_name);
@@ -561,8 +559,6 @@ message_send_chat_ox(const char* const barejid, const char* const msg, gboolean
     xmpp_stanza_to_text(message, &c, &s);
 
     account_free(account);
-    jid_destroy(jidp);
-    free(jid);
 
     if (state) {
         stanza_attach_state(ctx, message, state);
@@ -888,10 +884,9 @@ _handle_error(xmpp_stanza_t* const stanza)
         ui_handle_error(err_msg);
     } else {
         if (type && (strcmp(type, "cancel") == 0)) {
-            Jid* jidp = jid_create(jid);
+            auto_jid Jid* jidp = jid_create(jid);
             if (jidp) {
                 chat_session_remove(jidp->barejid);
-                jid_destroy(jidp);
             }
         }
         ui_handle_recipient_error(jid, err_msg);
@@ -928,7 +923,7 @@ _handle_muc_user(xmpp_stanza_t* const stanza)
         return;
     }
 
-    Jid* jidp = jid_create(invitor_jid);
+    auto_jid Jid* jidp = jid_create(invitor_jid);
     if (!jidp) {
         return;
     }
@@ -947,7 +942,6 @@ _handle_muc_user(xmpp_stanza_t* const stanza)
     }
 
     sv_ev_room_invite(INVITE_MEDIATED, invitor, room, reason, password);
-    jid_destroy(jidp);
     if (reason) {
         xmpp_free(ctx, reason);
     }
@@ -974,7 +968,7 @@ _handle_conference(xmpp_stanza_t* const stanza)
             return;
         }
 
-        Jid* jidp = jid_create(from);
+        auto_jid Jid* jidp = jid_create(from);
         if (!jidp) {
             return;
         }
@@ -984,7 +978,6 @@ _handle_conference(xmpp_stanza_t* const stanza)
         const char* password = xmpp_stanza_get_attribute(xns_conference, STANZA_ATTR_PASSWORD);
 
         sv_ev_room_invite(INVITE_DIRECT, jidp->barejid, room, reason, password);
-        jid_destroy(jidp);
     }
 }
 
@@ -1040,7 +1033,7 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
     if (!room_jid) {
         return;
     }
-    Jid* from_jid = jid_create(room_jid);
+    auto_jid Jid* from_jid = jid_create(room_jid);
     if (!from_jid) {
         return;
     }
@@ -1053,7 +1046,6 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
         sv_ev_room_subject(from_jid->barejid, from_jid->resourcepart, subject_text);
         xmpp_free(ctx, subject_text);
 
-        jid_destroy(from_jid);
         return;
     }
 
@@ -1084,31 +1076,28 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
                 }
             }
 
-            jid_destroy(from_jid);
             return;
         }
 
         sv_ev_room_broadcast(room_jid, broadcast);
         xmpp_free(ctx, broadcast);
 
-        jid_destroy(from_jid);
         return;
     }
 
     if (!jid_is_valid_room_form(from_jid)) {
         log_error("Invalid room JID: %s", from_jid->str);
-        jid_destroy(from_jid);
         return;
     }
 
     // room not active in profanity
     if (!muc_active(from_jid->barejid)) {
         log_error("Message received for inactive chat room: %s", from_jid->str);
-        jid_destroy(from_jid);
         return;
     }
 
     ProfMessage* message = message_init();
+    jid_ref(from_jid);
     message->from_jid = from_jid;
     message->type = PROF_MSG_TYPE_MUC;
 
@@ -1234,13 +1223,12 @@ _handle_receipt_received(xmpp_stanza_t* const stanza)
             return;
         }
 
-        Jid* jidp = jid_create(fulljid);
+        auto_jid Jid* jidp = jid_create(fulljid);
         if (!jidp) {
             return;
         }
 
         sv_ev_message_receipt(jidp->barejid, id);
-        jid_destroy(jidp);
     }
 }
 
@@ -1268,10 +1256,9 @@ _receipt_request_handler(xmpp_stanza_t* const stanza)
 
     const gchar* from = xmpp_stanza_get_from(stanza);
     if (from) {
-        Jid* jid = jid_create(from);
+        auto_jid Jid* jid = jid_create(from);
         if (jid) {
             _message_send_receipt(jid->fulljid, id);
-            jid_destroy(jid);
         }
     }
 }
@@ -1388,7 +1375,7 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c
     if (!from) {
         return;
     }
-    Jid* jid = jid_create(from);
+    auto_jid Jid* jid = jid_create(from);
     if (!jid) {
         return;
     }
@@ -1396,13 +1383,13 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c
     // private message from chat room use full jid (room/nick)
     if (muc_active(jid->barejid)) {
         _handle_muc_private_message(stanza);
-        jid_destroy(jid);
         return;
     }
 
     // standard chat message, use jid without resource
     ProfMessage* message = message_init();
     message->is_mam = is_mam;
+    jid_ref(jid);
     message->from_jid = jid;
     const gchar* to = xmpp_stanza_get_to(stanza);
     if (to) {
@@ -1761,9 +1748,8 @@ _should_ignore_based_on_silence(xmpp_stanza_t* const stanza)
 {
     if (prefs_get_boolean(PREF_SILENCE_NON_ROSTER)) {
         const char* const from = xmpp_stanza_get_from(stanza);
-        Jid* from_jid = jid_create(from);
+        auto_jid Jid* from_jid = jid_create(from);
         PContact contact = roster_get_contact(from_jid->barejid);
-        jid_destroy(from_jid);
         if (!contact) {
             log_debug("[Silence] Ignoring message from: %s", from);
             return TRUE;