diff options
author | irungentoo <irungentoo@gmail.com> | 2015-03-25 10:30:01 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2015-03-25 10:30:01 -0400 |
commit | 7001aa5dd04c50d1d74512c8cf7e662ce4b7d255 (patch) | |
tree | c5aa87ea481a63de386481ed6136d19592ae4650 /docs | |
parent | 45858e26785114612ae08b9090f418b49c7b5acc (diff) |
Removed old avatar doc.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/Avatars.md | 631 |
1 files changed, 0 insertions, 631 deletions
diff --git a/docs/Avatars.md b/docs/Avatars.md deleted file mode 100644 index 9dd43079..00000000 --- a/docs/Avatars.md +++ /dev/null | |||
@@ -1,631 +0,0 @@ | |||
1 | # User avatars in Tox | ||
2 | |||
3 | |||
4 | |||
5 | ## Introduction and rationale | ||
6 | |||
7 | User avatars are small icons or images used to identify users in the friend | ||
8 | list; they exist in virtually all VoIP and IM protocols and provide an easy | ||
9 | way for one user to identify another in the friend list. | ||
10 | |||
11 | This document describes the implementation of avatars in the Tox protocol, | ||
12 | according to the following design considerations: | ||
13 | |||
14 | - Avatars are handled as private information, i.e., they are only exchanged | ||
15 | over Tox encrypted channels among previously authenticated friends. | ||
16 | |||
17 | - The library treats all images as blobs and does not interpret or | ||
18 | understand image formats. It only ensures that the avatar data sent by | ||
19 | a user is correctly received by the other. The client application is | ||
20 | responsible for validating, decoding, resizing, and presenting the | ||
21 | image to the user. | ||
22 | |||
23 | - There is a strict limit of 16 KiB to the avatar raw data size -- this | ||
24 | seems suitable for practical use as, for example, the raw data of an | ||
25 | uncompressed 64 x 64 pixels 24 bpp RGB bitmap is 12288 bytes long; the | ||
26 | data limit provides enough space for larger bitmaps if the usual | ||
27 | compressed formats are used. | ||
28 | |||
29 | **Notice:** As designed, this limit can be changed in the future without | ||
30 | breaking the protocol compatibility, but clients using the original | ||
31 | limit will reject larger avatars. | ||
32 | |||
33 | - The protocol MUST provide means to allow caching and avoid unnecessary | ||
34 | data transfers. | ||
35 | |||
36 | - Avatars are transferred between clients in a background operation. | ||
37 | |||
38 | - Avatars are served on a "best effort" basis, without breaking clients | ||
39 | which do not support them. | ||
40 | |||
41 | - The protocol MUST resist to malicious users. | ||
42 | |||
43 | - The protocol MUST work with both UDP and TCP networks. | ||
44 | |||
45 | |||
46 | The Single Tox Standard Draft v.0.1.0 recommends implementing avatars as | ||
47 | a purely client-side feature through a procedure that can be summarized as | ||
48 | sending a specially named file as a file transfer request and accepting | ||
49 | it silently. This procedure can be improved to provide the previously stated | ||
50 | design considerations, but this requires a higher integration with the core | ||
51 | protocol. Moving this feature to the core protocol also: | ||
52 | |||
53 | - provides a simpler and cleaner interface for client applications; | ||
54 | |||
55 | - hides protocol complexities from the client; | ||
56 | |||
57 | - avoids code duplication and ad-hoc protocols in the clients; | ||
58 | |||
59 | - avoids incompatibility between client implementations; | ||
60 | |||
61 | - allows important optimizations, such as lightweight notification of | ||
62 | removed and updated avatars; | ||
63 | |||
64 | - plays well with cache schemes; | ||
65 | |||
66 | - makes avatar transfer essentially a background operation. | ||
67 | |||
68 | |||
69 | |||
70 | |||
71 | |||
72 | |||
73 | ## High level description | ||
74 | |||
75 | |||
76 | This is a very high level description. The usage patterns expected from | ||
77 | client applications are described in the section "Using Avatars in Client | ||
78 | Applications", and a low level protocol description is available in the | ||
79 | section "Internal Protocol Description"). | ||
80 | The avatar exchange is implemented with the following new elements in the | ||
81 | Tox protocol: | ||
82 | |||
83 | - **Avatar Information Notifications** are events which may be sent by | ||
84 | a user to another anytime, but are usually sent after one of them | ||
85 | connects to the network, changes his avatar, or in reply to an **avatar | ||
86 | information request**. They are delivered by a very lightweight message | ||
87 | but with enough information to allow a user to validate or discard an | ||
88 | avatar from the local cache and to decide if it is interesting to request | ||
89 | the avatar data from the peer. | ||
90 | |||
91 | This event contains two data fields: (1) the image format, and (2) the | ||
92 | cryptographic hash of the current image data. The image format may be | ||
93 | NONE (for users who have no avatar or removed their avatars) or PNG. The | ||
94 | cryptographic hash is intended to be compared with the hash of the | ||
95 | currently cached avatar (if any) in order to check if it is still up to | ||
96 | date. | ||
97 | |||
98 | - **Avatar Information Requests** are very lightweight messages sent by a | ||
99 | user asking for an **avatar information notification**. They may be sent | ||
100 | as part of the login process or when the client thinks the currently | ||
101 | cached avatar is outdated. The receiver may or may not answer to this | ||
102 | request. This message contains no data fields. | ||
103 | |||
104 | - An **Avatar Data Request** is sent by a user asking another for his | ||
105 | complete avatar data. It is sent only when the requesting user decides | ||
106 | the avatar does not exist in the local cache or is outdated. The receiver | ||
107 | may or may not answer to this request. This message contains no data | ||
108 | fields. | ||
109 | |||
110 | - An **Avatar Data Notification** is an event signaling the client that | ||
111 | the complete avatar image data of another user is available. The actual | ||
112 | data transfer is implemented using several data and control messages, | ||
113 | but the details are hidden from the client applications. This event can | ||
114 | only arrive in reply to an **avatar data request**. | ||
115 | |||
116 | This event contains three data fields: (1) the image format, (2) the | ||
117 | cryptographic hash of the image data, and (3) the raw image data. If the | ||
118 | image format is NONE (i.e. no avatar), the hash is zeroed and the image | ||
119 | data is empty. The raw image data is locally validated and ensured to | ||
120 | match the hash (the event is **not** triggered otherwise). | ||
121 | |||
122 | |||
123 | |||
124 | |||
125 | |||
126 | ## API | ||
127 | |||
128 | To implement this feature, the following public symbols were added. The | ||
129 | complete API documentation is available in `tox.h`. | ||
130 | |||
131 | |||
132 | ``` | ||
133 | #define TOX_AVATAR_MAX_DATA_LENGTH 16384 | ||
134 | #define TOX_HASH_LENGTH 32 | ||
135 | |||
136 | |||
137 | /* Data formats for user avatar images */ | ||
138 | typedef enum { | ||
139 | TOX_AVATAR_FORMAT_NONE, | ||
140 | TOX_AVATAR_FORMAT_PNG | ||
141 | } | ||
142 | TOX_AVATAR_FORMAT; | ||
143 | |||
144 | |||
145 | |||
146 | /* Set the user avatar image data. */ | ||
147 | int tox_set_avatar(Tox *tox, uint8_t format, const uint8_t *data, uint32_t length); | ||
148 | |||
149 | /* Remove the user avatar image data. */ | ||
150 | int tox_unset_avatar(Tox *tox); | ||
151 | |||
152 | /* Get avatar data from the current user. */ | ||
153 | int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t *length, uint32_t maxlen, uint8_t *hash); | ||
154 | |||
155 | /* Generate a cryptographic hash of the given data (usually a cached avatar). */ | ||
156 | int tox_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen); | ||
157 | |||
158 | /* Request avatar information from a friend. */ | ||
159 | int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber); | ||
160 | |||
161 | /* Send an unrequested avatar information to a friend. */ | ||
162 | int tox_send_avatar_info(Tox *tox, const int32_t friendnumber); | ||
163 | |||
164 | /* Request the avatar data from a friend. */ | ||
165 | int tox_request_avatar_data(const Tox *tox, const int32_t friendnumber); | ||
166 | |||
167 | /* Set the callback function for avatar data. */ | ||
168 | void tox_callback_avatar_info(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t*, void *), void *userdata); | ||
169 | |||
170 | /* Set the callback function for avatar data. */ | ||
171 | void tox_callback_avatar_data(Tox *tox, void (*function)(Tox *tox, int32_t, uint8_t, uint8_t*, uint8_t*, uint32_t, void *), void *userdata); | ||
172 | ``` | ||
173 | |||
174 | |||
175 | |||
176 | |||
177 | ## Using Avatars in Client Applications | ||
178 | |||
179 | |||
180 | ### General recommendations | ||
181 | |||
182 | - Clients MUST NOT imply the availability of avatars in other users. | ||
183 | Avatars are an optional feature and not all users and clients may | ||
184 | support them. | ||
185 | |||
186 | - Clients MUST NOT block waiting for avatar information and avatar data | ||
187 | packets. | ||
188 | |||
189 | - Clients MUST treat avatar data as insecure and potentially malicious. | ||
190 | For example, users may accidentally use corrupted images as avatars, | ||
191 | a malicious user may send a specially crafted image to exploit a known | ||
192 | vulnerability in an image decoding library, etc. It is recommended to | ||
193 | handle the avatar image data in the same way as an image downloaded | ||
194 | from an unknown Internet source. | ||
195 | |||
196 | - The peers MUST NOT assume any coupling between the operations of | ||
197 | receiving an avatar information packet, sending unrequested avatar | ||
198 | information packets, requesting avatar data, or receiving avatar data. | ||
199 | |||
200 | For example, the following situations are valid: | ||
201 | |||
202 | * A text-mode client may send avatars to other users, but never | ||
203 | request them. | ||
204 | |||
205 | * A client may not understand a particular image format and ignore | ||
206 | avatars using it, but request and handle other formats. | ||
207 | |||
208 | * A client on a slow mobile network may ask for avatar information to | ||
209 | ensure its cached avatars are still valid, but not request avatar | ||
210 | data. The same client may start asking for avatar data once it | ||
211 | connects through a fast network. | ||
212 | |||
213 | - Clients SHOULD implement a local cache of avatars and not request | ||
214 | avatar data from other peers unless necessary. | ||
215 | |||
216 | - When avatar information is received, the client should delete the | ||
217 | avatar if the new avatar format is NONE or compare the hash received | ||
218 | from the peer with the hash of the currently cached avatar. If they | ||
219 | differ, send an avatar data request. | ||
220 | |||
221 | - If the cached avatar is older than a given threshold, the client may | ||
222 | also send an avatar info request to that friend once he is online and | ||
223 | mark the avatar as updated *before* any avatar information is received | ||
224 | (to not spam the peer with such requests). | ||
225 | |||
226 | - When an avatar data notification is received, the client must update | ||
227 | the cached avatar with the new one. | ||
228 | |||
229 | - Clients should resize or crop the image such that it better adapts | ||
230 | to the client's user interface. | ||
231 | |||
232 | - If the user already has an avatar defined in the client configuration, | ||
233 | it must be set before connecting to the network to avoid spurious avatar | ||
234 | change notifications and unnecessary data transfers. | ||
235 | |||
236 | - If no avatar data is available for a given friend, the client should | ||
237 | show a placeholder image. | ||
238 | |||
239 | |||
240 | |||
241 | ### Interoperability and sharing avatars among different clients | ||
242 | |||
243 | **This section is a tentative recommendation of how clients should store | ||
244 | avatars to ensure local interoperability, and should be revised if this | ||
245 | code is accepted into Tox core.** | ||
246 | |||
247 | It is desirable that the user avatar and the cached friends' avatars could be | ||
248 | shared among different Tox clients in the same system, in the spirit of the | ||
249 | proposed Single Tox Standard. This not only makes switching from one client | ||
250 | to another easier, but also minimizes the need of data transfers, as avatars | ||
251 | already downloaded by other clients can be reused. | ||
252 | |||
253 | Given the Tox data directory described in STS Draft v0.1.0: | ||
254 | |||
255 | - Avatars are stored in a directory called "avatars" and named | ||
256 | as "xxxxx.png", where "xxxxx" is the complete public key (but not friend | ||
257 | address!) encoded as an uppercase hexadecimal string and "png" is the | ||
258 | extension for the PNG avatar. As new image formats may be used in the | ||
259 | future, clients should ensure no other file "xxxxx.*" exists. No file | ||
260 | should be kept for a user who has no avatar. | ||
261 | |||
262 | - The client's own avatar is not special and is stored like any other. This | ||
263 | is partially for simplicity, and partially in anticipation of profiles. | ||
264 | |||
265 | - The avatar should be stored as it was received, before any modifications by | ||
266 | the client for display purposes. | ||
267 | |||
268 | - The hash, as calculated by toxcore and passed into the data callback, | ||
269 | should be saved in "avatars/xxxxx.hash" where "xxxxx" means the | ||
270 | same thing as for avatars. (The filename is longer than the file :) ) | ||
271 | |||
272 | **To be discussed:** User keys are usually presented in Tox clients as | ||
273 | upper case strings, but lower case file names are more usual. | ||
274 | |||
275 | |||
276 | Example for Linux and other Unix systems, assuming a user called "gildor": | ||
277 | |||
278 | Tox data directory: /home/gildor/.config/tox/ | ||
279 | Tox data file: /home/gildor/.config/tox/data | ||
280 | Avatar data dir: /home/gildor/.config/tox/avatars/ | ||
281 | Gildor's avatar: /home/gildor/.config/tox/avatars/446F4E6F744D6564646C65496E546865416666616972734F6657697A61726473.png | ||
282 | Elrond's avatar: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.png | ||
283 | Elrond's hash: /home/gildor/.config/tox/avatars/43656C65627269616E20646F6E277420546F782E426164206D656D6F72696573.hash | ||
284 | Elladan's avatar: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.png | ||
285 | Elladan's hash: /home/gildor/.config/tox/avatars/49486174655768656E48756D616E735468696E6B49416D4D7942726F74686572.hash | ||
286 | Elrohir's avatar /home/gildor/.config/tox/avatars/726568746F7242794D6D41496B6E696854736E616D75486E6568576574614849.png | ||
287 | Elrohir's hash: /home/gildor/.config/tox/avatars/726568746F7242794D6D41496B6E696854736E616D75486E6568576574614849.hash | ||
288 | |||
289 | This recommendation is partially implemented by "testing/test_avatars.c". | ||
290 | |||
291 | |||
292 | |||
293 | |||
294 | |||
295 | ### Common operations | ||
296 | |||
297 | These are minimal examples of how to perform common operations with avatar | ||
298 | functions. For a complete working example, see `testing/test_avatars.c`. | ||
299 | |||
300 | |||
301 | #### Setting an avatar for the current user | ||
302 | |||
303 | In this example, `load_data_file` is just a hypothetical function that loads | ||
304 | data from a file into the buffer and sets the length accordingly. | ||
305 | |||
306 | uint8_t buf[TOX_AVATAR_MAX_DATA_LENGTH]; | ||
307 | uint32_t len; | ||
308 | |||
309 | if (load_data_file("avatar.png", buf, &len) == 0) | ||
310 | if (tox_set_avatar(tox, TOX_AVATAR_FORMAT_PNG, buf, len) != 0) | ||
311 | fprintf(stderr, "Failed to set avatar.\n"); | ||
312 | |||
313 | If the user is connected, this function will also notify all connected | ||
314 | friends about the avatar change. | ||
315 | |||
316 | If the user already has an avatar defined in the client configuration, it | ||
317 | must be set before connecting to the network to avoid spurious avatar change | ||
318 | notifications and unnecessary data transfers. | ||
319 | |||
320 | |||
321 | |||
322 | |||
323 | #### Removing the avatar from the current user | ||
324 | |||
325 | To remove the current avatar, an application must call | ||
326 | |||
327 | tox_unset_avatar(tox); | ||
328 | |||
329 | the effect is the same as setting the avatar format to `TOX_AVATAR_FORMAT_NONE` | ||
330 | with no data: | ||
331 | |||
332 | tox_set_avatar(tox, TOX_AVATAR_FORMAT_NONE, NULL, 0); | ||
333 | |||
334 | If the user is connected, this function will also notify all connected | ||
335 | friends about the avatar change. | ||
336 | |||
337 | |||
338 | |||
339 | |||
340 | |||
341 | #### Receiving avatar information from friends | ||
342 | |||
343 | All avatar information is passed to a callback function with the prototype: | ||
344 | |||
345 | void function(Tox *tox, int32_t friendnumber, uint8_t format, | ||
346 | uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata) | ||
347 | |||
348 | As in this example: | ||
349 | |||
350 | static void avatar_info_cb(Tox *tox, int32_t friendnumber, uint8_t format, | ||
351 | uint8_t *hash, void *userdata) | ||
352 | { | ||
353 | printf("Receiving avatar information from friend %d. Format = %d\n", | ||
354 | friendnumber, format); | ||
355 | printf("Data hash: "); | ||
356 | hex_printf(hash, TOX_HASH_LENGTH); /* Hypothetical function */ | ||
357 | printf("\n"); | ||
358 | } | ||
359 | |||
360 | And, somewhere in the Tox initialization calls, set it as the callback to be | ||
361 | triggered when an avatar information event arrives: | ||
362 | |||
363 | tox_callback_avatar_info(tox, avatar_info_cb, NULL); | ||
364 | |||
365 | |||
366 | A typical client will test the currently cached avatar against the hash given | ||
367 | in the avatar information event and, if needed, request the avatar data. | ||
368 | |||
369 | |||
370 | |||
371 | #### Receiving avatar data from friends | ||
372 | |||
373 | Avatar data events are only delivered in reply to avatar data requests, which | ||
374 | **should** only be sent after getting the user avatar information (format | ||
375 | and hash) from an avatar information event and checking it against a local | ||
376 | cache. | ||
377 | |||
378 | For this, an application must define an avatar information callback which | ||
379 | checks the local avatar cache and emits an avatar data request if necessary: | ||
380 | |||
381 | static void avatar_info_cb(Tox *tox, int32_t friendnumber, uint8_t format, | ||
382 | uint8_t *hash, void *userdata) | ||
383 | { | ||
384 | printf("Receiving avatar information from friend %d. Format = %d\n", | ||
385 | friendnumber, format); | ||
386 | if (format = TOX_AVATAR_FORMAT_NONE) { | ||
387 | /* User has no avatar or removed the avatar */ | ||
388 | delete_avatar_from_cache(tox, friendnumber); | ||
389 | } else { | ||
390 | /* Use the received hash to check if the cached avatar is | ||
391 | still up to date. */ | ||
392 | if (!is_user_cached_avatar_updated(tox, friendnumber, hash)) { | ||
393 | /* User avatar is outdated, send data request */ | ||
394 | tox_request_avatar_data(tox, friendnumber); | ||
395 | } | ||
396 | } | ||
397 | } | ||
398 | |||
399 | |||
400 | Then define an avatar data callback to store the received data in the local | ||
401 | cache: | ||
402 | |||
403 | static void avatar_data_cb(Tox *tox, int32_t friendnumber, uint8_t format, | ||
404 | uint8_t *hash, uint8_t *data, uint32_t datalen, void *userdata) | ||
405 | { | ||
406 | if (format = TOX_AVATAR_FORMAT_NONE) { | ||
407 | /* User has no avatar or removed the avatar */ | ||
408 | delete_avatar_from_cache(tox, friendnumber); | ||
409 | } else { | ||
410 | save_avatar_data_to_cache(tox, friendnumber, format, hash, | ||
411 | data, datalen); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | |||
416 | And, finally, register both callbacks somewhere in the Tox initialization | ||
417 | calls: | ||
418 | |||
419 | tox_callback_avatar_info(tox, avatar_info_cb, NULL); | ||
420 | tox_callback_avatar_data(tox, avatar_data_cb, NULL); | ||
421 | |||
422 | |||
423 | In the previous examples, implementation of the functions to check, store, | ||
424 | and retrieve data from the cache were omitted for brevity. These functions | ||
425 | will also need to get the friend public key (client id) from the friend | ||
426 | number and, usually, convert it from a byte string to a hexadecimal | ||
427 | string. A complete, yet more complex, example is available in the file | ||
428 | `testing/test_avatars.c`. | ||
429 | |||
430 | |||
431 | |||
432 | |||
433 | |||
434 | |||
435 | |||
436 | |||
437 | |||
438 | |||
439 | |||
440 | ## Internal Protocol Description | ||
441 | |||
442 | ### New packet types | ||
443 | |||
444 | The avatar transfer protocol adds the following new packet types and ids: | ||
445 | |||
446 | PACKET_ID_AVATAR_INFO_REQ = 52 | ||
447 | PACKET_ID_AVATAR_INFO = 53 | ||
448 | PACKET_ID_AVATAR_DATA_CONTROL = 54 | ||
449 | PACKET_ID_AVATAR_DATA_START = 55 | ||
450 | PACKET_ID_AVATAR_DATA_PUSH = 56 | ||
451 | |||
452 | |||
453 | |||
454 | |||
455 | ### Requesting avatar information | ||
456 | |||
457 | To request avatar information, a user must send a packet of type | ||
458 | `PACKET_ID_AVATAR_INFO_REQ`. This packet has no data fields. Upon | ||
459 | receiving this packet, a client which supports avatars should answer with | ||
460 | a `PACKET_ID_AVATAR_INFO`. The sender must accept that the friend may | ||
461 | not answer at all. | ||
462 | |||
463 | |||
464 | |||
465 | |||
466 | ### Receiving avatar information | ||
467 | |||
468 | Avatar information arrives in a packet of type `PACKET_ID_AVATAR_INFO` with | ||
469 | the following structure: | ||
470 | |||
471 | PACKET_ID_AVATAR_INFO (53) | ||
472 | Packet data size: 33 bytes | ||
473 | [1: uint8_t format][32: uint8_t hash] | ||
474 | |||
475 | where 'format' is the image data format, one of the following: | ||
476 | |||
477 | 0 = AVATAR_FORMAT_NONE (no avatar set) | ||
478 | 1 = AVATAR_FORMAT_PNG | ||
479 | |||
480 | and 'hash' is the SHA-256 message digest of the avatar data. | ||
481 | |||
482 | This packet may be sent at any time and no previous request is required. | ||
483 | Clients should send this packet upon connection or when a friend | ||
484 | connects, in the same way Tox sends name, status and action information. | ||
485 | |||
486 | |||
487 | |||
488 | |||
489 | |||
490 | ### Requesting avatar data | ||
491 | |||
492 | Transmission of avatar data is a multi-step procedure using three new packet | ||
493 | types. | ||
494 | |||
495 | - Packet `PACKET_ID_AVATAR_DATA_CONTROL` has the format: | ||
496 | |||
497 | PACKET_ID_AVATAR_DATA_CONTROL (54) | ||
498 | Packet data size: 1 byte | ||
499 | [1: uint8_t op] | ||
500 | |||
501 | where 'op' is a code signaling either an operation request or a status | ||
502 | return, the semantics of which are explained below. The following values are | ||
503 | defined: | ||
504 | |||
505 | 0 = AVATAR_DATACONTROL_REQ | ||
506 | 1 = AVATAR_DATACONTROL_ERROR | ||
507 | |||
508 | |||
509 | - Packet `PACKET_ID_AVATAR_DATA_START` has the following format: | ||
510 | |||
511 | PACKET_ID_AVATAR_DATA_START (55) | ||
512 | Packet data size: 37 bytes | ||
513 | [1: uint8_t format][32: uint8_t hash][1: uint32_t data_length] | ||
514 | |||
515 | |||
516 | where 'format' is the image format, with the same values accepted for | ||
517 | the field 'format' in packet type `PACKET_ID_AVATAR_INFO`, 'hash' is | ||
518 | the SHA-256 cryptographic hash of the avatar raw data, and 'data_length' | ||
519 | is the total number of bytes the raw avatar data. | ||
520 | |||
521 | |||
522 | - Packet `PACKET_ID_AVATAR_DATA_PUSH` has no format structure, just up | ||
523 | to `AVATAR_DATA_MAX_CHUNK_SIZE` bytes of raw avatar image data; this | ||
524 | value is defined according to the maximum amount of data a Tox encrypted | ||
525 | packet can hold. | ||
526 | |||
527 | |||
528 | |||
529 | The following procedure assumes that a client "A" is requesting avatar data | ||
530 | from a client "B": | ||
531 | |||
532 | - "A" must initialize its control structures and mark its data transfer | ||
533 | as not yet started. Then it requests avatar data from "B" by sending a | ||
534 | packet `PACKET_ID_AVATAR_DATA_CONTROL` with 'op' set to | ||
535 | `AVATAR_DATACONTROL_REQ`. | ||
536 | |||
537 | - If "B" accepts this transfer, it answers by sending a | ||
538 | `PACKET_ID_AVATAR_DATA_START` with the fields 'format', 'hash', and | ||
539 | 'data_length' set to the respective values of the current avatar. | ||
540 | If "B" has no avatar set, 'format' must be `AVATAR_FORMAT_NONE`, 'hash' | ||
541 | must be zeroed and 'data_length' must be zero. | ||
542 | |||
543 | If "B" does not accept sending the avatar, it may send a packet | ||
544 | `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | ||
545 | `AVATAR_DATACONTROL_ERROR` or simply ignore this request. "A" must cope | ||
546 | with this. | ||
547 | |||
548 | If "B" has an avatar, it sends a variable number of | ||
549 | `PACKET_ID_AVATAR_DATA_PUSH` packets with the avatar data in a single | ||
550 | shot. | ||
551 | |||
552 | - Upon receiving a `PACKET_ID_AVATAR_DATA_START`, "A" checks if it | ||
553 | has sent a data request to "B". If not, it simply ignores the packet. | ||
554 | |||
555 | If "A" really requested avatar data and the format is `AVATAR_FORMAT_NONE`, | ||
556 | it triggers the avatar data callback, and clears all the temporary data, | ||
557 | finishing the process. For other formats, "A" just waits for packets | ||
558 | of type `PACKET_ID_AVATAR_DATA_PUSH`. | ||
559 | |||
560 | - Upon receiving a `PACKET_ID_AVATAR_DATA_PUSH`, "A" checks if it really | ||
561 | sent an avatar data request and if the `PACKET_ID_AVATAR_DATA_START` was | ||
562 | already received. If these conditions were met, it checks if the total | ||
563 | length of the data already stored in the receiving buffer plus the data | ||
564 | present in the push packet is still less or equal than | ||
565 | `TOX_AVATAR_MAX_DATA_LENGTH`. If that is not the case, it replies with a | ||
566 | `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' set to | ||
567 | `AVATAR_DATACONTROL_ERROR`. | ||
568 | |||
569 | If valid, "A" updates the 'bytes_received' counter and concatenates the | ||
570 | newly arrived data to the buffer. | ||
571 | |||
572 | Then "A" checks if all the data has already been received, by comparing the | ||
573 | counter 'bytes_received' with the field 'total_length'. If they are | ||
574 | equal, "A" takes a SHA-256 hash of the data and compares it with the | ||
575 | hash stored in the field 'hash' received with the first | ||
576 | `PACKET_ID_AVATAR_DATA_START`. | ||
577 | |||
578 | If the hashes match, the avatar data was correctly received, and "A" | ||
579 | triggers the avatar data callback and clears all the temporary data, | ||
580 | finishing the process. | ||
581 | |||
582 | If not all data was received, "A" simply waits for more data. | ||
583 | |||
584 | Client "A" is always responsible for controlling the transfer and | ||
585 | validating the data received. "B" doesn't need to keep any state for the | ||
586 | protocol, have full control over the data sent and should implement | ||
587 | some transfer limit for the data it sends. | ||
588 | |||
589 | - Any peer receiving a `PACKET_ID_AVATAR_DATA_CONTROL` with the field 'op' | ||
590 | set to `AVATAR_DATACONTROL_ERROR` clears any existing control state and | ||
591 | aborts sending or receiving data. | ||
592 | |||
593 | |||
594 | |||
595 | |||
596 | |||
597 | ## Security considerations | ||
598 | |||
599 | The major security implication of background data transfers of large objects, | ||
600 | like avatars, is the possibility of exhausting the network resources of a | ||
601 | client. This problem is exacerbated when there is the possibility of an | ||
602 | amplification attack, as happens, for example, when sending a very small | ||
603 | avatar request message will force the user to reply with a larger avatar | ||
604 | data message. | ||
605 | |||
606 | The present proposal mitigates this situation by: | ||
607 | |||
608 | - only transferring data between previously authenticated friends, | ||
609 | |||
610 | - enforcing strict limits on the avatar data size, | ||
611 | |||
612 | - providing an alternate, smaller message for cooperative users to refresh | ||
613 | avatar information when nothing has changed (`PACKET_ID_AVATAR_INFO`), | ||
614 | |||
615 | - having a per-friend data transfer limit. As the current protocol still | ||
616 | allows a user to request avatar data again and again, the implementation | ||
617 | limits the amount of data a particular user can request for some time. The | ||
618 | exact values are defined in constants `AVATAR_DATA_TRANSFER_LIMIT` and | ||
619 | `AVATAR_DATA_TRANSFER_TIMEOUT` in file `Messenger.c`. | ||
620 | |||
621 | - making the requester responsible for storing partial data and state | ||
622 | information | ||
623 | |||
624 | Another problem present in avatars is the possibility of a friend sending | ||
625 | a maliciously crafted image intended to exploit vulnerabilities in image | ||
626 | decoders. Without an intermediate server to recompress, validate, and | ||
627 | convert the images to neutral formats, the client applications must handle | ||
628 | this situation by themselves using stable and secure image libraries and | ||
629 | imposing limits on the maximum amount of system resources the decoding | ||
630 | process can take. Images coming from Tox friends must be treated in the same | ||
631 | way as images coming from random Internet sources. | ||