summaryrefslogtreecommitdiff
path: root/toxcore/Messenger.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/Messenger.c')
-rw-r--r--toxcore/Messenger.c474
1 files changed, 472 insertions, 2 deletions
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 21cb2671..3d96f6ca 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -42,6 +42,7 @@
42static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); 42static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status);
43static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data, 43static int write_cryptpacket_id(const Messenger *m, int32_t friendnumber, uint8_t packet_id, const uint8_t *data,
44 uint32_t length, uint8_t congestion_control); 44 uint32_t length, uint8_t congestion_control);
45static int send_avatar_data_control(const Messenger *m, const uint32_t friendnumber, uint8_t op);
45 46
46// friend_not_valid determines if the friendnumber passed is valid in the Messenger object 47// friend_not_valid determines if the friendnumber passed is valid in the Messenger object
47static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber) 48static uint8_t friend_not_valid(const Messenger *m, int32_t friendnumber)
@@ -247,6 +248,10 @@ int32_t m_addfriend(Messenger *m, const uint8_t *address, const uint8_t *data, u
247 m->friendlist[i].statusmessage = calloc(1, 1); 248 m->friendlist[i].statusmessage = calloc(1, 1);
248 m->friendlist[i].statusmessage_length = 1; 249 m->friendlist[i].statusmessage_length = 1;
249 m->friendlist[i].userstatus = USERSTATUS_NONE; 250 m->friendlist[i].userstatus = USERSTATUS_NONE;
251 m->friendlist[i].avatar_info_sent = 0;
252 m->friendlist[i].avatar_recv_data = NULL;
253 m->friendlist[i].avatar_send_data.bytes_sent = 0;
254 m->friendlist[i].avatar_send_data.last_reset = 0;
250 m->friendlist[i].is_typing = 0; 255 m->friendlist[i].is_typing = 0;
251 memcpy(m->friendlist[i].info, data, length); 256 memcpy(m->friendlist[i].info, data, length);
252 m->friendlist[i].info_size = length; 257 m->friendlist[i].info_size = length;
@@ -299,6 +304,10 @@ int32_t m_addfriend_norequest(Messenger *m, const uint8_t *client_id)
299 m->friendlist[i].statusmessage = calloc(1, 1); 304 m->friendlist[i].statusmessage = calloc(1, 1);
300 m->friendlist[i].statusmessage_length = 1; 305 m->friendlist[i].statusmessage_length = 1;
301 m->friendlist[i].userstatus = USERSTATUS_NONE; 306 m->friendlist[i].userstatus = USERSTATUS_NONE;
307 m->friendlist[i].avatar_info_sent = 0;
308 m->friendlist[i].avatar_recv_data = NULL;
309 m->friendlist[i].avatar_send_data.bytes_sent = 0;
310 m->friendlist[i].avatar_send_data.last_reset = 0;
302 m->friendlist[i].is_typing = 0; 311 m->friendlist[i].is_typing = 0;
303 m->friendlist[i].message_id = 0; 312 m->friendlist[i].message_id = 0;
304 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ 313 m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */
@@ -330,6 +339,7 @@ int m_delfriend(Messenger *m, int32_t friendnumber)
330 onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); 339 onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum);
331 crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); 340 crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id);
332 free(m->friendlist[friendnumber].statusmessage); 341 free(m->friendlist[friendnumber].statusmessage);
342 free(m->friendlist[friendnumber].avatar_recv_data);
333 remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id); 343 remove_request_received(&(m->fr), m->friendlist[friendnumber].client_id);
334 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); 344 memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
335 uint32_t i; 345 uint32_t i;
@@ -564,6 +574,131 @@ int m_set_userstatus(Messenger *m, uint8_t status)
564 return 0; 574 return 0;
565} 575}
566 576
577int m_set_avatar(Messenger *m, uint8_t format, const uint8_t *data, uint32_t length)
578{
579 if (length > MAX_AVATAR_DATA_LENGTH)
580 return -1;
581
582 if (format == AVATARFORMAT_NONE) {
583 free(m->avatar_data);
584 m->avatar_data = NULL;
585 m->avatar_data_length = 0;
586 m->avatar_format = format;
587 memset(m->avatar_hash, 0, AVATAR_HASH_LENGTH);
588 } else {
589 if (length == 0 || data == NULL)
590 return -1;
591
592 uint8_t *tmp = realloc(m->avatar_data, length);
593
594 if (tmp == NULL)
595 return -1;
596
597 m->avatar_format = format;
598 m->avatar_data = tmp;
599 m->avatar_data_length = length;
600 memcpy(m->avatar_data, data, length);
601
602 m_avatar_hash(m->avatar_hash, m->avatar_data, m->avatar_data_length);
603 }
604
605 uint32_t i;
606
607 for (i = 0; i < m->numfriends; ++i)
608 m->friendlist[i].avatar_info_sent = 0;
609
610 return 0;
611}
612
613int m_get_self_avatar(const Messenger *m, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen,
614 uint8_t *hash)
615{
616 if (format)
617 *format = m->avatar_format;
618
619 if (length)
620 *length = m->avatar_data_length;
621
622 if (hash)
623 memcpy(hash, m->avatar_hash, AVATAR_HASH_LENGTH);
624
625 if (buf != NULL && maxlen > 0) {
626 if (m->avatar_data_length <= maxlen)
627 memcpy(buf, m->avatar_data, m->avatar_data_length);
628 else
629 return -1;
630 }
631
632 return 0;
633}
634
635int m_avatar_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen)
636{
637 if (hash == NULL)
638 return -1;
639
640 crypto_hash_sha256(hash, data, datalen);
641 return 0;
642}
643
644
645int m_request_avatar_info(const Messenger *m, const int32_t friendnumber)
646{
647 if (friend_not_valid(m, friendnumber))
648 return -1;
649
650 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_INFO_REQ, 0, 0, 0))
651 return 0;
652 else
653 return -1;
654}
655
656int m_send_avatar_info(const Messenger *m, const int32_t friendnumber)
657{
658 if (friend_not_valid(m, friendnumber))
659 return -1;
660
661 uint8_t data[sizeof(uint8_t) + AVATAR_HASH_LENGTH];
662 data[0] = m->avatar_format;
663 memcpy(data + 1, m->avatar_hash, AVATAR_HASH_LENGTH);
664
665 if (write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_INFO, data, sizeof(data), 0))
666 return 0;
667 else
668 return -1;
669}
670
671int m_request_avatar_data(const Messenger *m, const int32_t friendnumber)
672{
673 if (friend_not_valid(m, friendnumber))
674 return -1;
675
676 AVATARRECEIVEDATA *avrd = m->friendlist[friendnumber].avatar_recv_data;
677
678 if (avrd == NULL) {
679 avrd = calloc(sizeof(AVATARRECEIVEDATA), 1);
680
681 if (avrd == NULL)
682 return -1;
683
684 avrd->started = 0;
685 m->friendlist[friendnumber].avatar_recv_data = avrd;
686 }
687
688 if (avrd->started) {
689 LOGGER_DEBUG("Resetting already started data request. "
690 "friendnumber == %u", friendnumber);
691 }
692
693 avrd->started = 0;
694 avrd->bytes_received = 0;
695 avrd->total_length = 0;
696 avrd->format = AVATARFORMAT_NONE;
697
698 return send_avatar_data_control(m, friendnumber, AVATARDATACONTROL_REQ);
699}
700
701
567/* return the size of friendnumber's user status. 702/* return the size of friendnumber's user status.
568 * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH. 703 * Guaranteed to be at most MAX_STATUSMESSAGE_LENGTH.
569 */ 704 */
@@ -806,6 +941,20 @@ void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Mess
806 m->friend_connectionstatuschange_internal_userdata = userdata; 941 m->friend_connectionstatuschange_internal_userdata = userdata;
807} 942}
808 943
944void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, void *),
945 void *userdata)
946{
947 m->avatar_info_recv = function;
948 m->avatar_info_recv_userdata = userdata;
949}
950
951void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *,
952 uint32_t, void *), void *userdata)
953{
954 m->avatar_data_recv = function;
955 m->avatar_data_recv_userdata = userdata;
956}
957
809static void break_files(const Messenger *m, int32_t friendnumber); 958static void break_files(const Messenger *m, int32_t friendnumber);
810static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status) 959static void check_friend_connectionstatus(Messenger *m, int32_t friendnumber, uint8_t status)
811{ 960{
@@ -1857,6 +2006,9 @@ Messenger *new_messenger(Messenger_Options *options)
1857 m->net = new_networking(ip, TOX_PORT_DEFAULT); 2006 m->net = new_networking(ip, TOX_PORT_DEFAULT);
1858 } 2007 }
1859 2008
2009 m->avatar_format = AVATARFORMAT_NONE;
2010 m->avatar_data = NULL;
2011
1860 if (m->net == NULL) { 2012 if (m->net == NULL) {
1861 free(m); 2013 free(m);
1862 return NULL; 2014 return NULL;
@@ -1930,10 +2082,11 @@ void kill_messenger(Messenger *m)
1930 kill_networking(m->net); 2082 kill_networking(m->net);
1931 2083
1932 for (i = 0; i < m->numfriends; ++i) { 2084 for (i = 0; i < m->numfriends; ++i) {
1933 if (m->friendlist[i].statusmessage) 2085 free(m->friendlist[i].statusmessage);
1934 free(m->friendlist[i].statusmessage); 2086 free(m->friendlist[i].avatar_recv_data);
1935 } 2087 }
1936 2088
2089 free(m->avatar_data);
1937 free(m->friendlist); 2090 free(m->friendlist);
1938 free(m); 2091 free(m);
1939} 2092}
@@ -1973,11 +2126,287 @@ static int handle_status(void *object, int i, uint8_t status)
1973 if (m->friendlist[i].status == FRIEND_ONLINE) { 2126 if (m->friendlist[i].status == FRIEND_ONLINE) {
1974 set_friend_status(m, i, FRIEND_CONFIRMED); 2127 set_friend_status(m, i, FRIEND_CONFIRMED);
1975 } 2128 }
2129
2130 /* Clear avatar transfer state */
2131 if (m->friendlist[i].avatar_recv_data) {
2132 free(m->friendlist[i].avatar_recv_data);
2133 m->friendlist[i].avatar_recv_data = NULL;
2134 }
1976 } 2135 }
1977 2136
1978 return 0; 2137 return 0;
1979} 2138}
1980 2139
2140
2141/* Sends an avatar data control packet to the peer. Usually to return status
2142 * values or request data.
2143 */
2144static int send_avatar_data_control(const Messenger *m, const uint32_t friendnumber,
2145 uint8_t op)
2146{
2147 int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_DATA_CONTROL,
2148 &op, sizeof(op), 0);
2149 LOGGER_DEBUG("friendnumber = %u, op = %u, ret = %d",
2150 friendnumber, op, ret);
2151 return ret ? 0 : -1;
2152}
2153
2154
2155static int handle_avatar_data_control(Messenger *m, uint32_t friendnumber,
2156 uint8_t *data, uint32_t data_length)
2157{
2158 if (data_length != 1) {
2159 LOGGER_DEBUG("Error: PACKET_ID_AVATAR_DATA_CONTROL with bad "
2160 "data_length = %u, friendnumber = %u",
2161 data_length, friendnumber);
2162 send_avatar_data_control(m, friendnumber, AVATARDATACONTROL_ERROR);
2163 return -1; /* Error */
2164 }
2165
2166 LOGGER_DEBUG("friendnumber = %u, op = %u", friendnumber, data[0]);
2167
2168 switch (data[0]) {
2169 case AVATARDATACONTROL_REQ: {
2170
2171 /* Check data transfer limits for this friend */
2172 AVATARSENDDATA *const avsd = &(m->friendlist[friendnumber].avatar_send_data);
2173
2174 if (avsd->bytes_sent >= AVATAR_DATA_TRANSFER_LIMIT) {
2175 /* User reached data limit. Check timeout */
2176 uint64_t now = unix_time();
2177
2178 if (avsd->last_reset > 0
2179 && (avsd->last_reset + AVATAR_DATA_TRANSFER_TIMEOUT < now)) {
2180 avsd->bytes_sent = 0;
2181 avsd->last_reset = now;
2182 } else {
2183 /* Friend still rate-limitted. Send an error and stops. */
2184 LOGGER_DEBUG("Avatar data transfer limit reached. "
2185 "friendnumber = %u", friendnumber);
2186 send_avatar_data_control(m, friendnumber, AVATARDATACONTROL_ERROR);
2187 return 0;
2188 }
2189 }
2190
2191 /* Start the transmission with a DATA_START message. Format:
2192 * uint8_t format
2193 * uint8_t hash[AVATAR_HASH_LENGTH]
2194 * uint32_t total_length
2195 */
2196 LOGGER_DEBUG("Sending start msg to friend number %u. "
2197 "m->avatar_format = %u, m->avatar_data_length = %u",
2198 friendnumber, m->avatar_format, m->avatar_data_length);
2199 uint8_t start_data[1 + AVATAR_HASH_LENGTH + sizeof(uint32_t)];
2200 uint32_t avatar_len = htonl(m->avatar_data_length);
2201
2202 start_data[0] = m->avatar_format;
2203 memcpy(start_data + 1, m->avatar_hash, AVATAR_HASH_LENGTH);
2204 memcpy(start_data + 1 + AVATAR_HASH_LENGTH, &avatar_len, sizeof(uint32_t));
2205
2206 avsd->bytes_sent += sizeof(start_data); /* For rate limit */
2207
2208 int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_AVATAR_DATA_START,
2209 start_data, sizeof(start_data), 0);
2210
2211 if (!ret) {
2212 /* Something went wrong, try to signal the error so the friend
2213 * can clear up the state. */
2214 send_avatar_data_control(m, friendnumber, AVATARDATACONTROL_ERROR);
2215 return 0;
2216 }
2217
2218 /* User have no avatar data, nothing more to do. */
2219 if (m->avatar_format == AVATARFORMAT_NONE)
2220 return 0;
2221
2222 /* Send the actual avatar data. */
2223 uint32_t offset = 0;
2224
2225 while (offset < m->avatar_data_length) {
2226 uint32_t chunk_len = m->avatar_data_length - offset;
2227
2228 if (chunk_len > AVATAR_DATA_MAX_CHUNK_SIZE)
2229 chunk_len = AVATAR_DATA_MAX_CHUNK_SIZE;
2230
2231 uint8_t chunk[AVATAR_DATA_MAX_CHUNK_SIZE];
2232 memcpy(chunk, m->avatar_data + offset, chunk_len);
2233 offset += chunk_len;
2234 avsd->bytes_sent += chunk_len; /* For rate limit */
2235
2236 int ret = write_cryptpacket_id(m, friendnumber,
2237 PACKET_ID_AVATAR_DATA_PUSH,
2238 chunk, chunk_len, 0);
2239
2240 if (!ret) {
2241 LOGGER_DEBUG("write_cryptpacket_id failed. ret = %d, "
2242 "friendnumber = %u, offset = %u",
2243 ret, friendnumber, offset);
2244 send_avatar_data_control(m, friendnumber, AVATARDATACONTROL_ERROR);
2245 return -1;
2246 }
2247 }
2248
2249 return 0;
2250 }
2251
2252 case AVATARDATACONTROL_ERROR: {
2253 if (m->friendlist[friendnumber].avatar_recv_data) {
2254 /* We were receiving the data, sender detected an error
2255 (eg. changing avatar) and asked us to stop. */
2256 free(m->friendlist[friendnumber].avatar_recv_data);
2257 m->friendlist[friendnumber].avatar_recv_data = NULL;
2258 }
2259
2260 return 0;
2261 }
2262 }
2263
2264 return -1;
2265}
2266
2267
2268static int handle_avatar_data_start(Messenger *m, uint32_t friendnumber,
2269 uint8_t *data, uint32_t data_length)
2270{
2271 LOGGER_DEBUG("data_length = %u, friendnumber = %u", data_length, friendnumber);
2272
2273 if (data_length != 1 + AVATAR_HASH_LENGTH + sizeof(uint32_t)) {
2274 LOGGER_DEBUG("Invalid msg length = %u, friendnumber = %u",
2275 data_length, friendnumber);
2276 return -1;
2277 }
2278
2279 AVATARRECEIVEDATA *avrd = m->friendlist[friendnumber].avatar_recv_data;
2280
2281 if (avrd == NULL) {
2282 LOGGER_DEBUG("Received an unrequested DATA_START, friendnumber = %u",
2283 friendnumber);
2284 return -1;
2285 }
2286
2287 if (avrd->started) {
2288 /* Already receiving data from this friend. Must be an error
2289 * or an malicious request, because we zeroed the started bit
2290 * when we requested the data. */
2291 LOGGER_DEBUG("Received an unrequested duplicated DATA_START, "
2292 "friendnumber = %u", friendnumber);
2293 return -1;
2294 }
2295
2296 /* Copy data from message to our control structure */
2297 avrd->started = 1;
2298 avrd->format = data[0];
2299 memcpy(avrd->hash, data + 1, AVATAR_HASH_LENGTH);
2300 uint32_t tmp_len;
2301 memcpy(&tmp_len, data + 1 + AVATAR_HASH_LENGTH, sizeof(uint32_t));
2302 avrd->total_length = ntohl(tmp_len);
2303 avrd->bytes_received = 0;
2304
2305 LOGGER_DEBUG("friendnumber = %u, avrd->format = %u, "
2306 "avrd->total_length = %u, avrd->bytes_received = %u",
2307 friendnumber, avrd->format, avrd->total_length,
2308 avrd->bytes_received);
2309
2310 if (avrd->total_length > MAX_AVATAR_DATA_LENGTH) {
2311 /* Invalid data length. Stops. */
2312 LOGGER_DEBUG("Error: total_length > MAX_AVATAR_DATA_LENGTH, "
2313 "friendnumber = %u", friendnumber);
2314 free(avrd);
2315 avrd = NULL;
2316 m->friendlist[friendnumber].avatar_recv_data = NULL;
2317 return 0;
2318 }
2319
2320 if (avrd->format == AVATARFORMAT_NONE || avrd->total_length == 0) {
2321 /* No real data to receive. Run callback function and finish. */
2322 LOGGER_DEBUG("format == NONE, friendnumber = %u", friendnumber);
2323
2324 if (m->avatar_data_recv) {
2325 memset(avrd->hash, 0, AVATAR_HASH_LENGTH);
2326 (m->avatar_data_recv)(m, friendnumber, avrd->format, avrd->hash,
2327 NULL, 0, m->avatar_data_recv_userdata);
2328 }
2329
2330 free(avrd);
2331 avrd = NULL;
2332 m->friendlist[friendnumber].avatar_recv_data = NULL;
2333 return 0;
2334 }
2335
2336 /* Waits for more data to be received */
2337 return 0;
2338}
2339
2340
2341static int handle_avatar_data_push(Messenger *m, uint32_t friendnumber,
2342 uint8_t *data, uint32_t data_length)
2343{
2344 LOGGER_DEBUG("friendnumber = %u, data_length = %u", friendnumber, data_length);
2345
2346 AVATARRECEIVEDATA *avrd = m->friendlist[friendnumber].avatar_recv_data;
2347
2348 if (avrd == NULL) {
2349 /* No active transfer. It must be an error or a malicious request,
2350 * because we set the avatar_recv_data on the first DATA_START. */
2351 LOGGER_DEBUG("Error: avrd == NULL, friendnumber = %u", friendnumber);
2352 return -1; /* Error */
2353 }
2354
2355 if (avrd->started == 0) {
2356 /* Receiving data for a non-started request. Must be an error
2357 * or an malicious request. */
2358 LOGGER_DEBUG("Received an data push for a yet non started data "
2359 "request. friendnumber = %u", friendnumber);
2360 return -1; /* Error */
2361 }
2362
2363 uint32_t new_length = avrd->bytes_received + data_length;
2364
2365 if (new_length > avrd->total_length
2366 || new_length >= MAX_AVATAR_DATA_LENGTH) {
2367 /* Invalid data length due to error or malice. Stops. */
2368 LOGGER_DEBUG("Invalid data length. friendnumber = %u, "
2369 "new_length = %u, avrd->total_length = %u",
2370 friendnumber, new_length, avrd->total_length);
2371 free(avrd);
2372 m->friendlist[friendnumber].avatar_recv_data = NULL;
2373 return 0;
2374 }
2375
2376 memcpy(avrd->data + avrd->bytes_received, data, data_length);
2377 avrd->bytes_received += data_length;
2378
2379 if (avrd->bytes_received == avrd->total_length) {
2380 LOGGER_DEBUG("All data received. friendnumber = %u", friendnumber);
2381
2382 /* All data was received. Check if the hashes match. It the
2383 * requester's responsability to do this. The sender may have done
2384 * anything with its avatar data between the DATA_START and now.
2385 */
2386 uint8_t cur_hash[AVATAR_HASH_LENGTH];
2387 m_avatar_hash(cur_hash, avrd->data, avrd->bytes_received);
2388
2389 if (memcmp(cur_hash, avrd->hash, AVATAR_HASH_LENGTH) == 0) {
2390 /* Avatar successfuly received! */
2391 if (m->avatar_data_recv) {
2392 (m->avatar_data_recv)(m, friendnumber, avrd->format, cur_hash,
2393 avrd->data, avrd->bytes_received, m->avatar_data_recv_userdata);
2394 }
2395 } else {
2396 LOGGER_DEBUG("Avatar hash error. friendnumber = %u", friendnumber);
2397 }
2398
2399 free(avrd);
2400 m->friendlist[friendnumber].avatar_recv_data = NULL;
2401 return 0;
2402 }
2403
2404 /* Waits for more data to be received */
2405 return 0;
2406}
2407
2408
2409
1981static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) 2410static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
1982{ 2411{
1983 if (len == 0) 2412 if (len == 0)
@@ -2115,6 +2544,42 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
2115 break; 2544 break;
2116 } 2545 }
2117 2546
2547 case PACKET_ID_AVATAR_INFO_REQ: {
2548 /* Send our avatar information */
2549 m_send_avatar_info(m, i);
2550 break;
2551 }
2552
2553 case PACKET_ID_AVATAR_INFO: {
2554 if (m->avatar_info_recv) {
2555 /*
2556 * A malicious user may send an incomplete avatar info message.
2557 * Check if it have the correct size for the format:
2558 * [1 uint8_t: avatar format] [32 uint8_t: hash]
2559 */
2560 if (data_length == AVATAR_HASH_LENGTH + 1) {
2561 (m->avatar_info_recv)(m, i, data[0], data + 1, m->avatar_info_recv_userdata);
2562 }
2563 }
2564
2565 break;
2566 }
2567
2568 case PACKET_ID_AVATAR_DATA_CONTROL: {
2569 handle_avatar_data_control(m, i, data, data_length);
2570 break;
2571 }
2572
2573 case PACKET_ID_AVATAR_DATA_START: {
2574 handle_avatar_data_start(m, i, data, data_length);
2575 break;
2576 }
2577
2578 case PACKET_ID_AVATAR_DATA_PUSH: {
2579 handle_avatar_data_push(m, i, data, data_length);
2580 break;
2581 }
2582
2118 case PACKET_ID_RECEIPT: { 2583 case PACKET_ID_RECEIPT: {
2119 uint32_t msgid; 2584 uint32_t msgid;
2120 2585
@@ -2343,6 +2808,11 @@ void do_friends(Messenger *m)
2343 m->friendlist[i].userstatus_sent = 1; 2808 m->friendlist[i].userstatus_sent = 1;
2344 } 2809 }
2345 2810
2811 if (m->friendlist[i].avatar_info_sent == 0) {
2812 if (m_send_avatar_info(m, i) == 0)
2813 m->friendlist[i].avatar_info_sent = 1;
2814 }
2815
2346 if (m->friendlist[i].user_istyping_sent == 0) { 2816 if (m->friendlist[i].user_istyping_sent == 0) {
2347 if (send_user_istyping(m, i, m->friendlist[i].user_istyping)) 2817 if (send_user_istyping(m, i, m->friendlist[i].user_istyping))
2348 m->friendlist[i].user_istyping_sent = 1; 2818 m->friendlist[i].user_istyping_sent = 1;