summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/Messenger.c474
-rw-r--r--toxcore/Messenger.h195
-rw-r--r--toxcore/tox.c51
-rw-r--r--toxcore/tox.h144
4 files changed, 861 insertions, 3 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;
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 6c641a9a..a107d80f 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -36,6 +36,9 @@
36#define MAX_NAME_LENGTH 128 36#define MAX_NAME_LENGTH 128
37/* TODO: this must depend on other variable. */ 37/* TODO: this must depend on other variable. */
38#define MAX_STATUSMESSAGE_LENGTH 1007 38#define MAX_STATUSMESSAGE_LENGTH 1007
39#define MAX_AVATAR_DATA_LENGTH 16384
40#define AVATAR_HASH_LENGTH 32
41
39 42
40#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) 43#define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t))
41 44
@@ -46,6 +49,11 @@
46#define PACKET_ID_STATUSMESSAGE 49 49#define PACKET_ID_STATUSMESSAGE 49
47#define PACKET_ID_USERSTATUS 50 50#define PACKET_ID_USERSTATUS 50
48#define PACKET_ID_TYPING 51 51#define PACKET_ID_TYPING 51
52#define PACKET_ID_AVATAR_INFO_REQ 52
53#define PACKET_ID_AVATAR_INFO 53
54#define PACKET_ID_AVATAR_DATA_CONTROL 54
55#define PACKET_ID_AVATAR_DATA_START 55
56#define PACKET_ID_AVATAR_DATA_PUSH 56
49#define PACKET_ID_RECEIPT 63 57#define PACKET_ID_RECEIPT 63
50#define PACKET_ID_MESSAGE 64 58#define PACKET_ID_MESSAGE 64
51#define PACKET_ID_ACTION 65 59#define PACKET_ID_ACTION 65
@@ -109,6 +117,13 @@ enum {
109/* If no packets are received from friend in this time interval, kill the connection. */ 117/* If no packets are received from friend in this time interval, kill the connection. */
110#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 3) 118#define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 3)
111 119
120/* Must be < MAX_CRYPTO_DATA_SIZE */
121#define AVATAR_DATA_MAX_CHUNK_SIZE (MAX_CRYPTO_DATA_SIZE-1)
122
123/* Per-friend data limit for avatar data requests */
124#define AVATAR_DATA_TRANSFER_LIMIT (10*MAX_AVATAR_DATA_LENGTH)
125#define AVATAR_DATA_TRANSFER_TIMEOUT (60) /* 164kB every 60 seconds is not a lot */
126
112 127
113/* USERSTATUS - 128/* USERSTATUS -
114 * Represents userstatuses someone can have. 129 * Represents userstatuses someone can have.
@@ -122,6 +137,42 @@ typedef enum {
122} 137}
123USERSTATUS; 138USERSTATUS;
124 139
140/* AVATARFORMAT -
141 * Data formats for user avatar images
142 */
143typedef enum {
144 AVATARFORMAT_NONE,
145 AVATARFORMAT_PNG
146}
147AVATARFORMAT;
148
149/* AVATARDATACONTROL
150 * To control avatar data requests (PACKET_ID_AVATAR_DATA_CONTROL)
151 */
152typedef enum {
153 AVATARDATACONTROL_REQ,
154 AVATARDATACONTROL_ERROR
155}
156AVATARDATACONTROL;
157
158typedef struct {
159 uint8_t started;
160 AVATARFORMAT format;
161 uint8_t hash[AVATAR_HASH_LENGTH];
162 uint32_t total_length;
163 uint32_t bytes_received;
164 uint8_t data[MAX_AVATAR_DATA_LENGTH];
165}
166AVATARRECEIVEDATA;
167
168typedef struct {
169 /* Fields only used to limit the network usage from a given friend */
170 uint32_t bytes_sent; /* Total bytes send to this user */
171 uint64_t last_reset; /* Time the data counter was last reset */
172}
173AVATARSENDDATA;
174
175
125struct File_Transfers { 176struct File_Transfers {
126 uint64_t size; 177 uint64_t size;
127 uint64_t transferred; 178 uint64_t transferred;
@@ -163,6 +214,7 @@ typedef struct {
163 uint8_t statusmessage_sent; 214 uint8_t statusmessage_sent;
164 USERSTATUS userstatus; 215 USERSTATUS userstatus;
165 uint8_t userstatus_sent; 216 uint8_t userstatus_sent;
217 uint8_t avatar_info_sent;
166 uint8_t user_istyping; 218 uint8_t user_istyping;
167 uint8_t user_istyping_sent; 219 uint8_t user_istyping_sent;
168 uint8_t is_typing; 220 uint8_t is_typing;
@@ -178,6 +230,9 @@ typedef struct {
178 int invited_groups[MAX_INVITED_GROUPS]; 230 int invited_groups[MAX_INVITED_GROUPS];
179 uint16_t invited_groups_num; 231 uint16_t invited_groups_num;
180 232
233 AVATARSENDDATA avatar_send_data;
234 AVATARRECEIVEDATA *avatar_recv_data; // We are receiving avatar data from this friend.
235
181 struct { 236 struct {
182 int (*function)(void *object, const uint8_t *data, uint32_t len); 237 int (*function)(void *object, const uint8_t *data, uint32_t len);
183 void *object; 238 void *object;
@@ -209,6 +264,11 @@ typedef struct Messenger {
209 264
210 USERSTATUS userstatus; 265 USERSTATUS userstatus;
211 266
267 AVATARFORMAT avatar_format;
268 uint8_t *avatar_data;
269 uint32_t avatar_data_length;
270 uint8_t avatar_hash[AVATAR_HASH_LENGTH];
271
212 Friend *friendlist; 272 Friend *friendlist;
213 uint32_t numfriends; 273 uint32_t numfriends;
214 274
@@ -243,6 +303,10 @@ typedef struct Messenger {
243 void *friend_connectionstatuschange_userdata; 303 void *friend_connectionstatuschange_userdata;
244 void (*friend_connectionstatuschange_internal)(struct Messenger *m, int32_t, uint8_t, void *); 304 void (*friend_connectionstatuschange_internal)(struct Messenger *m, int32_t, uint8_t, void *);
245 void *friend_connectionstatuschange_internal_userdata; 305 void *friend_connectionstatuschange_internal_userdata;
306 void *avatar_info_recv_userdata;
307 void (*avatar_info_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, void *);
308 void *avatar_data_recv_userdata;
309 void (*avatar_data_recv)(struct Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t, void *);
246 310
247 void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, void *); 311 void (*group_invite)(struct Messenger *m, int32_t, const uint8_t *, void *);
248 void *group_invite_userdata; 312 void *group_invite_userdata;
@@ -437,6 +501,94 @@ int m_copy_self_statusmessage(const Messenger *m, uint8_t *buf, uint32_t maxlen)
437uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber); 501uint8_t m_get_userstatus(const Messenger *m, int32_t friendnumber);
438uint8_t m_get_self_userstatus(const Messenger *m); 502uint8_t m_get_self_userstatus(const Messenger *m);
439 503
504
505/* Set the user avatar image data.
506 * This should be made before connecting, so we will not announce that the user have no avatar
507 * before setting and announcing a new one, forcing the peers to re-download it.
508 *
509 * Notice that the library treats the image as raw data and does not interpret it by any way.
510 *
511 * Arguments:
512 * format - Avatar image format or NONE for user with no avatar (see AVATARFORMAT);
513 * data - pointer to the avatar data (may be NULL it the format is NONE);
514 * length - length of image data. Must be <= MAX_AVATAR_DATA_LENGTH.
515 *
516 * returns 0 on success
517 * returns -1 on failure.
518 */
519int m_set_avatar(Messenger *m, uint8_t format, const uint8_t *data, uint32_t length);
520
521/* Get avatar data from the current user.
522 * Copies the current user avatar data to the destination buffer and sets the image format
523 * accordingly.
524 *
525 * If the avatar format is NONE, the buffer 'buf' isleft uninitialized, 'hash' is zeroed, and
526 * 'length' is set to zero.
527 *
528 * If any of the pointers format, buf, length, and hash are NULL, that particular field will be ignored.
529 *
530 * Arguments:
531 * format - destination pointer to the avatar image format (see AVATARFORMAT);
532 * buf - destination buffer to the image data. Must have at least 'maxlen' bytes;
533 * length - destination pointer to the image data length;
534 * maxlen - length of the destination buffer 'buf';
535 * hash - destination pointer to the avatar hash (it must be exactly AVATAR_HASH_LENGTH bytes long).
536 *
537 * returns 0 on success;
538 * returns -1 on failure.
539 *
540 */
541int m_get_self_avatar(const Messenger *m, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen,
542 uint8_t *hash);
543
544/* Generates a cryptographic hash of the given avatar data.
545 * This function is a wrapper to internal message-digest functions and specifically provided
546 * to generate hashes from user avatars that may be memcmp()ed with the values returned by the
547 * other avatar functions. It is specially important to validate cached avatars.
548 *
549 * Arguments:
550 * hash - destination buffer for the hash data, it must be exactly AVATAR_HASH_LENGTH bytes long.
551 * data - avatar image data;
552 * datalen - length of the avatar image data; it must be <= MAX_AVATAR_DATA_LENGTH.
553 *
554 * returns 0 on success
555 * returns -1 on failure.
556 */
557int m_avatar_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen);
558
559/* Request avatar information from a friend.
560 * Asks a friend to provide their avatar information (image format and hash). The friend may
561 * or may not answer this request and, if answered, the information will be provided through
562 * the callback 'avatar_info'.
563 *
564 * returns 0 on success
565 * returns -1 on failure.
566 */
567int m_request_avatar_info(const Messenger *m, const int32_t friendnumber);
568
569/* Send an unrequested avatar information to a friend.
570 * Sends our avatar format and hash to a friend; he/she can use this information to validate
571 * an avatar from the cache and may (or not) reply with an avatar data request.
572 *
573 * Notice: it is NOT necessary to send these notification after changing the avatar or
574 * connecting. The library already does this.
575 *
576 * returns 0 on success
577 * returns -1 on failure.
578 */
579int m_send_avatar_info(const Messenger *m, const int32_t friendnumber);
580
581
582/* Request the avatar data from a friend.
583 * Ask a friend to send their avatar data. The friend may or may not answer this request and,
584 * if answered, the information will be provided in callback 'avatar_data'.
585 *
586 * returns 0 on sucess
587 * returns -1 on failure.
588 */
589int m_request_avatar_data(const Messenger *m, const int32_t friendnumber);
590
591
440/* returns timestamp of last time friendnumber was seen online, or 0 if never seen. 592/* returns timestamp of last time friendnumber was seen online, or 0 if never seen.
441 * returns -1 on error. 593 * returns -1 on error.
442 */ 594 */
@@ -533,6 +685,49 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in
533void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, void *), 685void m_callback_connectionstatus_internal_av(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, void *),
534 void *userdata); 686 void *userdata);
535 687
688
689/* Set the callback function for avatar information.
690 * This callback will be called when avatar information are received from friends. These events
691 * can arrive at anytime, but are usually received uppon connection and in reply of avatar
692 * information requests.
693 *
694 * Function format is:
695 * function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata)
696 *
697 * where 'format' is the avatar image format (see AVATARFORMAT) and 'hash' is the hash of
698 * the avatar data for caching purposes and it is exactly AVATAR_HASH_LENGTH long. If the
699 * image format is NONE, the hash is zeroed.
700 *
701 */
702void m_callback_avatar_info(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, void *),
703 void *userdata);
704
705
706/* Set the callback function for avatar data.
707 * This callback will be called when the complete avatar data was correctly received from a
708 * friend. This only happens in reply of a avatar data request (see tox_request_avatar_data);
709 *
710 * Function format is:
711 * function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata)
712 *
713 * where 'format' is the avatar image format (see AVATARFORMAT); 'hash' is the
714 * locally-calculated cryptographic hash of the avatar data and it is exactly
715 * AVATAR_HASH_LENGTH long; 'data' is the avatar image data and 'datalen' is the length
716 * of such data.
717 *
718 * If format is NONE, 'data' is NULL, 'datalen' is zero, and the hash is zeroed. The hash is
719 * always validated locally with the function tox_avatar_hash and ensured to match the image
720 * data, so this value can be safely used to compare with cached avatars.
721 *
722 * WARNING: users MUST treat all avatar image data received from another peer as untrusted and
723 * potentially malicious. The library only ensures that the data which arrived is the same the
724 * other user sent, and does not interpret or validate any image data.
725 */
726void m_callback_avatar_data(Messenger *m, void (*function)(Messenger *m, int32_t, uint8_t, uint8_t *, uint8_t *,
727 uint32_t, void *), void *userdata);
728
729
730
536/**********GROUP CHATS************/ 731/**********GROUP CHATS************/
537 732
538/* Set the callback for group invites. 733/* Set the callback for group invites.
diff --git a/toxcore/tox.c b/toxcore/tox.c
index a4413c4f..b44f0ee6 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -798,6 +798,57 @@ uint64_t tox_file_data_remaining(const Tox *tox, int32_t friendnumber, uint8_t f
798 return file_dataremaining(m, friendnumber, filenumber, send_receive); 798 return file_dataremaining(m, friendnumber, filenumber, send_receive);
799} 799}
800 800
801
802/****************AVATAR FUNCTIONS*****************/
803
804void tox_callback_avatar_info(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, void *), void *userdata)
805{
806 Messenger *m = tox;
807 m_callback_avatar_info(m, function, userdata);
808}
809
810void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t,
811 void *), void *userdata)
812{
813 Messenger *m = tox;
814 m_callback_avatar_data(m, function, userdata);
815}
816
817int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length)
818{
819 Messenger *m = tox;
820 return m_set_avatar(m, format, data, length);
821}
822
823int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, uint8_t *hash)
824{
825 const Messenger *m = tox;
826 return m_get_self_avatar(m, format, buf, length, maxlen, hash);
827}
828
829int tox_avatar_hash(const Tox *tox, uint8_t *hash, const uint8_t *data, const uint32_t datalen)
830{
831 return m_avatar_hash(hash, data, datalen);
832}
833
834int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber)
835{
836 const Messenger *m = tox;
837 return m_request_avatar_info(m, friendnumber);
838}
839
840int tox_send_avatar_info(Tox *tox, const int32_t friendnumber)
841{
842 const Messenger *m = tox;
843 return m_send_avatar_info(m, friendnumber);
844}
845
846int tox_request_avatar_data(const Tox *tox, const int32_t friendnumber)
847{
848 const Messenger *m = tox;
849 return m_request_avatar_data(m, friendnumber);
850}
851
801/***************END OF FILE SENDING FUNCTIONS******************/ 852/***************END OF FILE SENDING FUNCTIONS******************/
802 853
803/* Like tox_bootstrap_from_address but for TCP relays only. 854/* Like tox_bootstrap_from_address but for TCP relays only.
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 278a19cd..a5efee34 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -37,6 +37,8 @@ extern "C" {
37#define TOX_MAX_MESSAGE_LENGTH 1368 37#define TOX_MAX_MESSAGE_LENGTH 1368
38#define TOX_MAX_STATUSMESSAGE_LENGTH 1007 38#define TOX_MAX_STATUSMESSAGE_LENGTH 1007
39#define TOX_CLIENT_ID_SIZE 32 39#define TOX_CLIENT_ID_SIZE 32
40#define TOX_MAX_AVATAR_DATA_LENGTH 16384
41#define TOX_AVATAR_HASH_LENGTH 32
40 42
41#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) 43#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
42 44
@@ -70,6 +72,16 @@ typedef enum {
70} 72}
71TOX_USERSTATUS; 73TOX_USERSTATUS;
72 74
75
76/* AVATARFORMAT -
77 * Data formats for user avatar images
78 */
79typedef enum {
80 TOX_AVATARFORMAT_NONE,
81 TOX_AVATARFORMAT_PNG
82}
83TOX_AVATARFORMAT;
84
73#ifndef __TOX_DEFINED__ 85#ifndef __TOX_DEFINED__
74#define __TOX_DEFINED__ 86#define __TOX_DEFINED__
75typedef struct Tox Tox; 87typedef struct Tox Tox;
@@ -242,7 +254,6 @@ int tox_get_self_status_message(const Tox *tox, uint8_t *buf, uint32_t maxlen);
242uint8_t tox_get_user_status(const Tox *tox, int32_t friendnumber); 254uint8_t tox_get_user_status(const Tox *tox, int32_t friendnumber);
243uint8_t tox_get_self_user_status(const Tox *tox); 255uint8_t tox_get_self_user_status(const Tox *tox);
244 256
245
246/* returns timestamp of last time friendnumber was seen online, or 0 if never seen. 257/* returns timestamp of last time friendnumber was seen online, or 0 if never seen.
247 * returns -1 on error. 258 * returns -1 on error.
248 */ 259 */
@@ -517,6 +528,137 @@ uint32_t tox_count_chatlist(const Tox *tox);
517 * of out_list will be truncated to list_size. */ 528 * of out_list will be truncated to list_size. */
518uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size); 529uint32_t tox_get_chatlist(const Tox *tox, int *out_list, uint32_t list_size);
519 530
531/****************AVATAR FUNCTIONS*****************/
532
533/* Set the callback function for avatar information.
534 * This callback will be called when avatar information are received from friends. These events
535 * can arrive at anytime, but are usually received uppon connection and in reply of avatar
536 * information requests.
537 *
538 * Function format is:
539 * function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, void *userdata)
540 *
541 * where 'format' is the avatar image format (see TOX_AVATARFORMAT) and 'hash' is the hash of
542 * the avatar data for caching purposes and it is exactly TOX_AVATAR_HASH_LENGTH long. If the
543 * image format is NONE, the hash is zeroed.
544 *
545 */
546void tox_callback_avatar_info(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, void *),
547 void *userdata);
548
549
550/* Set the callback function for avatar data.
551 * This callback will be called when the complete avatar data was correctly received from a
552 * friend. This only happens in reply of a avatar data request (see tox_request_avatar_data);
553 *
554 * Function format is:
555 * function(Tox *tox, int32_t friendnumber, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata)
556 *
557 * where 'format' is the avatar image format (see TOX_AVATARFORMAT); 'hash' is the
558 * locally-calculated cryptographic hash of the avatar data and it is exactly
559 * TOX_AVATAR_HASH_LENGTH long; 'data' is the avatar image data and 'datalen' is the length
560 * of such data.
561 *
562 * If format is NONE, 'data' is NULL, 'datalen' is zero, and the hash is zeroed. The hash is
563 * always validated locally with the function tox_avatar_hash and ensured to match the image
564 * data, so this value can be safely used to compare with cached avatars.
565 *
566 * WARNING: users MUST treat all avatar image data received from another peer as untrusted and
567 * potentially malicious. The library only ensures that the data which arrived is the same the
568 * other user sent, and does not interpret or validate any image data.
569 */
570void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t *, uint8_t *, uint32_t,
571 void *), void *userdata);
572
573/* Set the user avatar image data.
574 * This should be made before connecting, so we will not announce that the user have no avatar
575 * before setting and announcing a new one, forcing the peers to re-download it.
576 *
577 * Notice that the library treats the image as raw data and does not interpret it by any way.
578 *
579 * Arguments:
580 * format - Avatar image format or NONE for user with no avatar (see TOX_AVATARFORMAT);
581 * data - pointer to the avatar data (may be NULL it the format is NONE);
582 * length - length of image data. Must be <= TOX_MAX_AVATAR_DATA_LENGTH.
583 *
584 * returns 0 on success
585 * returns -1 on failure.
586 */
587int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length);
588
589
590/* Get avatar data from the current user.
591 * Copies the current user avatar data to the destination buffer and sets the image format
592 * accordingly.
593 *
594 * If the avatar format is NONE, the buffer 'buf' isleft uninitialized, 'hash' is zeroed, and
595 * 'length' is set to zero.
596 *
597 * If any of the pointers format, buf, length, and hash are NULL, that particular field will be ignored.
598 *
599 * Arguments:
600 * format - destination pointer to the avatar image format (see TOX_AVATARFORMAT);
601 * buf - destination buffer to the image data. Must have at least 'maxlen' bytes;
602 * length - destination pointer to the image data length;
603 * maxlen - length of the destination buffer 'buf';
604 * hash - destination pointer to the avatar hash (it must be exactly TOX_AVATAR_HASH_LENGTH bytes long).
605 *
606 * returns 0 on success;
607 * returns -1 on failure.
608 *
609 */
610int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen,
611 uint8_t *hash);
612
613
614/* Generates a cryptographic hash of the given avatar data.
615 * This function is a wrapper to internal message-digest functions and specifically provided
616 * to generate hashes from user avatars that may be memcmp()ed with the values returned by the
617 * other avatar functions. It is specially important to validate cached avatars.
618 *
619 * Arguments:
620 * hash - destination buffer for the hash data, it must be exactly TOX_AVATAR_HASH_LENGTH bytes long.
621 * data - avatar image data;
622 * datalen - length of the avatar image data; it must be <= TOX_MAX_AVATAR_DATA_LENGTH.
623 *
624 * returns 0 on success
625 * returns -1 on failure.
626 */
627int tox_avatar_hash(const Tox *tox, uint8_t *hash, const uint8_t *data, const uint32_t datalen);
628
629
630/* Request avatar information from a friend.
631 * Asks a friend to provide their avatar information (image format and hash). The friend may
632 * or may not answer this request and, if answered, the information will be provided through
633 * the callback 'avatar_info'.
634 *
635 * returns 0 on success
636 * returns -1 on failure.
637 */
638int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber);
639
640
641/* Send an unrequested avatar information to a friend.
642 * Sends our avatar format and hash to a friend; he/she can use this information to validate
643 * an avatar from the cache and may (or not) reply with an avatar data request.
644 *
645 * Notice: it is NOT necessary to send these notification after changing the avatar or
646 * connecting. The library already does this.
647 *
648 * returns 0 on success
649 * returns -1 on failure.
650 */
651int tox_send_avatar_info(Tox *tox, const int32_t friendnumber);
652
653
654/* Request the avatar data from a friend.
655 * Ask a friend to send their avatar data. The friend may or may not answer this request and,
656 * if answered, the information will be provided in callback 'avatar_data'.
657 *
658 * returns 0 on sucess
659 * returns -1 on failure.
660 */
661int tox_request_avatar_data(const Tox *tox, const int32_t friendnumber);
520 662
521/****************FILE SENDING FUNCTIONS*****************/ 663/****************FILE SENDING FUNCTIONS*****************/
522/* NOTE: This how to will be updated. 664/* NOTE: This how to will be updated.