commit f9a7099bcf2a37095384bbf9418afce815d67138
Author: zoff99 <zoff99@users.noreply.github.com>
Date:   Sat Apr 16 10:21:57 2022 +0200

    capabilites

diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 715b23fd9..d7388d54d 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -113,6 +113,15 @@ static bool send_online_packet(Messenger *m, int32_t friendnumber)
         return false;
     }
 
+    uint8_t buf[TOX_CAPABILITIES_SIZE + 1];
+    buf[0] = PACKET_ID_ONLINE;
+    net_pack_u64(buf + 1, TOX_CAPABILITIES_CURRENT);
+
+    if (write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
+                          m->friendlist[friendnumber].friendcon_id), buf, (TOX_CAPABILITIES_SIZE + 1), false) == -1) {
+        return false;
+    }
+
     uint8_t packet = PACKET_ID_ONLINE;
     return write_cryptpacket(m->net_crypto, friend_connection_crypt_connection_id(m->fr_c,
                              m->friendlist[friendnumber].friendcon_id), &packet, sizeof(packet), false) != -1;
@@ -166,6 +175,7 @@ static int32_t init_new_friend(Messenger *m, const uint8_t *real_pk, uint8_t sta
             m->friendlist[i].userstatus = USERSTATUS_NONE;
             m->friendlist[i].is_typing = false;
             m->friendlist[i].message_id = 0;
+            m->friendlist[i].toxcore_capabilities = TOX_CAPABILITY_BASIC;
             friend_connection_callbacks(m->fr_c, friendcon_id, MESSENGER_CALLBACK_INDEX, &m_handle_status, &m_handle_packet,
                                         &m_handle_lossy_packet, m, i);
 
@@ -1862,6 +1872,19 @@ static int m_handle_status(void *object, int i, bool status, void *userdata)
     return 0;
 }
 
+/* get capabilities of friend's toxcore
+ * return TOX_CAPABILITY_BASIC on any error
+ */
+uint64_t m_get_friend_toxcore_capabilities(const Messenger *m, int32_t friendnumber)
+{
+    if (!m_friend_exists(m, friendnumber)) {
+        return TOX_CAPABILITY_BASIC;
+    }
+
+    // return toxcore_capabilities for friend, not matter if ONLINE or OFFLINE
+    return m->friendlist[friendnumber].toxcore_capabilities;
+}
+
 static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t len, void *userdata)
 {
     if (len == 0) {
@@ -1874,9 +1897,20 @@ static int m_handle_packet(void *object, int i, const uint8_t *temp, uint16_t le
     const uint16_t data_length = len - 1;
 
     if (m->friendlist[i].status != FRIEND_ONLINE) {
-        if (packet_id == PACKET_ID_ONLINE && len == 1) {
-            set_friend_status(m, i, FRIEND_ONLINE, userdata);
-            send_online_packet(m, i);
+        if (packet_id == PACKET_ID_ONLINE) {
+            if (len == (TOX_CAPABILITIES_SIZE + 1)) {
+                uint64_t received_caps;
+                net_unpack_u64(data, &received_caps);
+                m->friendlist[i].toxcore_capabilities = received_caps;
+                LOGGER_DEBUG(m->log, "got capabilties: %llu friendnum: %d",
+                             (long long unsigned int)m->friendlist[i].toxcore_capabilities, (int)i);
+            } else if (len == 1) {
+                set_friend_status(m, i, FRIEND_ONLINE, userdata);
+                send_online_packet(m, i);
+                LOGGER_DEBUG(m->log, "got online packet for friendnum: %d", (int)i);
+            } else {
+                return -1;
+            }
         } else {
             return -1;
         }
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 3bb818a32..dce79eed2 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -72,6 +72,30 @@ typedef struct Messenger_Options {
     uint8_t state_plugins_length;
 } Messenger_Options;
 
+/* this means no special capabilities, in other words clients that are older
+ * and did not implement this feature yet
+ */
+#define TOX_CAPABILITY_BASIC 0
+/* ATTENTION: if you are adding new flags in your fork or toxcore,
+ * or in c-toxcore master,
+ * please coordinate with us first!
+ * thank you, the Tox Devs.
+ */
+#define TOX_CAPABILITY_CAPABILITIES ((uint64_t)1) << 0
+#define TOX_CAPABILITY_MSGV2 ((uint64_t)1) << 1
+#define TOX_CAPABILITY_TOXAV_H264 ((uint64_t)1) << 2
+#define TOX_CAPABILITY_MSGV3 ((uint64_t)1) << 3
+/* add new flags/bits here */
+/* if the TOX_CAPABILITY_NEXT_IMPLEMENTATION flag is set it means
+ * we are using a different system for indicating capabilities now,
+ * and TOX_CAPABILITIES_* should be ignored and just the new (not yet known)
+ * system should be used
+ */
+#define TOX_CAPABILITY_NEXT_IMPLEMENTATION ((uint64_t)1) << 63
+/* hardcoded capabilities of this version/branch of toxcore */
+#define TOX_CAPABILITIES_CURRENT (uint64_t)(TOX_CAPABILITY_CAPABILITIES | TOX_CAPABILITY_MSGV3)
+/* size of the FLAGS in bytes */
+#define TOX_CAPABILITIES_SIZE sizeof(uint64_t)
 
 struct Receipts {
     uint32_t packet_num;
@@ -226,6 +254,7 @@ typedef struct Friend {
 
     struct Receipts *receipts_start;
     struct Receipts *receipts_end;
+    uint64_t toxcore_capabilities;
 } Friend;
 
 struct Messenger {
@@ -494,6 +523,10 @@ non_null() int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf);
 non_null() uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);
 non_null() uint8_t m_get_self_userstatus(const Messenger *m);
 
+/* get capabilities of friend's toxcore
+ * return TOX_CAPABILITY_BASIC on any error
+ */
+uint64_t m_get_friend_toxcore_capabilities(const Messenger *m, int32_t friendnumber);
 
 /** @brief returns timestamp of last time friendnumber was seen online or 0 if never seen.
  * if friendnumber is invalid this function will return UINT64_MAX.
diff --git a/toxcore/tox.c b/toxcore/tox.c
index cf350c59e..845bee680 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -1299,6 +1299,20 @@ uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, Tox_
     return timestamp;
 }
 
+uint64_t tox_friend_get_capabilities(const Tox *tox, uint32_t friend_number)
+{
+    tox_lock(tox);
+    const uint64_t capabilities = m_get_friend_toxcore_capabilities(tox->m, friend_number);
+    tox_unlock(tox);
+
+    return capabilities;
+}
+
+uint64_t tox_self_get_capabilities(void)
+{
+    return (TOX_CAPABILITIES_CURRENT);
+}
+
 size_t tox_self_get_friend_list_size(const Tox *tox)
 {
     assert(tox != nullptr);
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 56f9daf05..2ce668c42 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -1136,9 +1136,12 @@ void tox_self_get_public_key(const Tox *tox, uint8_t *public_key);
  */
 void tox_self_get_secret_key(const Tox *tox, uint8_t *secret_key);
 
+/**
+ * Return the capabilities flags for this tox instance.
+ */
+uint64_t tox_self_get_capabilities(void);
 /** @} */
 
-
 /** @{
  * @name User-visible client information (nickname/status)
  */
@@ -1525,6 +1528,11 @@ typedef enum Tox_Err_Friend_Query {
 
 } Tox_Err_Friend_Query;
 
+/**
+ * Return the capabilities flags for a friend. If the friend number is invalid, the
+ * return value is unspecified.
+ */
+uint64_t tox_friend_get_capabilities(const Tox *tox, uint32_t friend_number);
 
 /**
  * @brief Return the length of the friend's name.
