1 /*
2     This file is part of tgl-library
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License as published by the Free Software Foundation; either
7     version 2.1 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Lesser General Public License for more details.
13 
14     You should have received a copy of the GNU Lesser General Public
15     License along with this library; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 
18     Copyright Vitaly Valtman 2013-2015
19 */
20 #include "tgl.h"
21 #include "updates.h"
22 #include "mtproto-common.h"
23 #include "tgl-binlog.h"
24 #include "auto.h"
25 #include "auto/auto-types.h"
26 #include "auto/auto-skip.h"
27 #include "auto/auto-fetch-ds.h"
28 #include "auto/auto-free-ds.h"
29 #include "tgl-structures.h"
30 #include "tgl-methods-in.h"
31 #include "tree.h"
32 
33 #include <assert.h>
34 
35 void tgl_do_get_channel_difference (struct tgl_state *TLS, int channel_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra);
36 
fetch_dc_option(struct tgl_state * TLS,struct tl_ds_dc_option * DS_DO)37 static void fetch_dc_option (struct tgl_state *TLS, struct tl_ds_dc_option *DS_DO) {
38   vlogprintf (E_DEBUG, "id = %d, %.*s:%d\n", DS_LVAL (DS_DO->id), DS_RSTR (DS_DO->ip_address), DS_LVAL (DS_DO->port));
39 
40   bl_do_dc_option (TLS, DS_LVAL (DS_DO->flags), DS_LVAL (DS_DO->id), NULL, 0, DS_STR (DS_DO->ip_address), DS_LVAL (DS_DO->port));
41 }
42 
tgl_check_pts_diff(struct tgl_state * TLS,int pts,int pts_count)43 int tgl_check_pts_diff (struct tgl_state *TLS, int pts, int pts_count) {
44   vlogprintf (E_DEBUG - 1, "pts = %d, pts_count = %d\n", pts, pts_count);
45   if (!TLS->pts) {
46     return 1;
47   }
48   //assert (TLS->pts);
49   if (pts < TLS->pts + pts_count) {
50     vlogprintf (E_NOTICE, "Duplicate message with pts=%d\n", pts);
51     return -1;
52   }
53   if (pts > TLS->pts + pts_count) {
54     vlogprintf (E_NOTICE, "Hole in pts (pts = %d, count = %d, cur_pts = %d)\n", pts, pts_count, TLS->pts);
55     tgl_do_get_difference (TLS, 0, 0, 0);
56     return -1;
57   }
58   if (TLS->locks & TGL_LOCK_DIFF) {
59     vlogprintf (E_DEBUG, "Update during get_difference. pts = %d\n", pts);
60     return -1;
61   }
62   vlogprintf (E_DEBUG, "Ok update. pts = %d\n", pts);
63   return 1;
64 }
65 
tgl_check_qts_diff(struct tgl_state * TLS,int qts,int qts_count)66 int tgl_check_qts_diff (struct tgl_state *TLS, int qts, int qts_count) {
67   vlogprintf (E_ERROR, "qts = %d, qts_count = %d\n", qts, qts_count);
68   if (qts < TLS->qts + qts_count) {
69     vlogprintf (E_NOTICE, "Duplicate message with qts=%d\n", qts);
70     return -1;
71   }
72   if (qts > TLS->qts + qts_count) {
73     vlogprintf (E_NOTICE, "Hole in qts (qts = %d, count = %d, cur_qts = %d)\n", qts, qts_count, TLS->qts);
74     tgl_do_get_difference (TLS, 0, 0, 0);
75     return -1;
76   }
77   if (TLS->locks & TGL_LOCK_DIFF) {
78     vlogprintf (E_DEBUG, "Update during get_difference. qts = %d\n", qts);
79     return -1;
80   }
81   vlogprintf (E_DEBUG, "Ok update. qts = %d\n", qts);
82   return 1;
83 }
84 
tgl_check_channel_pts_diff(struct tgl_state * TLS,tgl_peer_t * _E,int pts,int pts_count)85 int tgl_check_channel_pts_diff (struct tgl_state *TLS, tgl_peer_t *_E, int pts, int pts_count) {
86   struct tgl_channel *E = &_E->channel;
87   vlogprintf (E_DEBUG - 1, "channel %d: pts = %d, pts_count = %d, current_pts = %d\n", tgl_get_peer_id (E->id), pts, pts_count, E->pts);
88   if (!E->pts) {
89     return 1;
90   }
91   //assert (TLS->pts);
92   if (pts < E->pts + pts_count) {
93     vlogprintf (E_NOTICE, "Duplicate message with pts=%d\n", pts);
94     return -1;
95   }
96   if (pts > E->pts + pts_count) {
97     vlogprintf (E_NOTICE, "Hole in pts (pts = %d, count = %d, cur_pts = %d)\n", pts, pts_count, E->pts);
98     tgl_do_get_channel_difference (TLS, tgl_get_peer_id (E->id), 0, 0);
99     return -1;
100   }
101   if (E->flags & TGLCHF_DIFF) {
102     vlogprintf (E_DEBUG, "Update during get_difference. pts = %d\n", pts);
103     return -1;
104   }
105   vlogprintf (E_DEBUG, "Ok update. pts = %d\n", pts);
106   return 1;
107 }
108 
do_skip_seq(struct tgl_state * TLS,int seq)109 static int do_skip_seq (struct tgl_state *TLS, int seq) {
110   if (!seq) {
111     vlogprintf (E_DEBUG, "Ok update. seq = %d\n", seq);
112     return 0;
113   }
114   if (TLS->seq) {
115     if (seq <= TLS->seq) {
116       vlogprintf (E_NOTICE, "Duplicate message with seq=%d\n", seq);
117       return -1;
118     }
119     if (seq > TLS->seq + 1) {
120       vlogprintf (E_NOTICE, "Hole in seq (seq = %d, cur_seq = %d)\n", seq, TLS->seq);
121       //vlogprintf (E_NOTICE, "lock_diff = %s\n", (TLS->locks & TGL_LOCK_DIFF) ? "true" : "false");
122       tgl_do_get_difference (TLS, 0, 0, 0);
123       return -1;
124     }
125     if (TLS->locks & TGL_LOCK_DIFF) {
126       vlogprintf (E_DEBUG, "Update during get_difference. seq = %d\n", seq);
127       return -1;
128     }
129     vlogprintf (E_DEBUG, "Ok update. seq = %d\n", seq);
130     return 0;
131   } else {
132     return -1;
133   }
134 }
135 
tglu_work_update(struct tgl_state * TLS,int check_only,struct tl_ds_update * DS_U)136 void tglu_work_update (struct tgl_state *TLS, int check_only, struct tl_ds_update *DS_U) {
137   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
138     vlogprintf (E_DEBUG, "Update during get_difference. DROP\n");
139     return;
140   }
141 
142   if (DS_U->pts) {
143     assert (DS_U->pts_count);
144 
145     if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) {
146       return;
147     }
148   }
149 
150   if (DS_U->qts) {
151     if (!check_only && tgl_check_qts_diff (TLS, DS_LVAL (DS_U->qts), 1) <= 0) {
152       return;
153     }
154   }
155 
156   if (DS_U->channel_pts) {
157     assert (DS_U->channel_pts_count);
158     int channel_id;
159     if (DS_U->channel_id) {
160       channel_id = DS_LVAL (DS_U->channel_id);
161     } else {
162       assert (DS_U->message);
163       if (!DS_U->message->to_id) {
164         return;
165       }
166       assert (DS_U->message->to_id);
167       assert (DS_U->message->to_id->magic == CODE_peer_channel);
168       channel_id = DS_LVAL (DS_U->message->to_id->channel_id);
169     }
170 
171     tgl_peer_t *E = tgl_peer_get (TLS, TGL_MK_CHANNEL (channel_id));
172     if (!E) {
173       return;
174     }
175 
176     if (!check_only && tgl_check_channel_pts_diff (TLS, E, DS_LVAL (DS_U->channel_pts), DS_LVAL (DS_U->channel_pts_count)) <= 0) {
177       return;
178     }
179   }
180 
181   vlogprintf (E_NOTICE, "update 0x%08x (check=%d)\n", DS_U->magic, check_only);
182   if (check_only > 0 && DS_U->magic != CODE_update_message_i_d) { return; }
183   switch (DS_U->magic) {
184   case CODE_update_new_message:
185     {
186       //struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_U->id));
187       //int new = (!N || !(N->flags & TGLMF_CREATED));
188       int new_msg = 0;
189       struct tgl_message *M = tglf_fetch_alloc_message (TLS, DS_U->message, &new_msg);
190       assert (M);
191       if (new_msg) {
192         bl_do_msg_update (TLS, &M->permanent_id);
193       }
194       break;
195     };
196   case CODE_update_message_i_d:
197     {
198       tgl_message_id_t msg_id;
199       msg_id.peer_type = TGL_PEER_RANDOM_ID;
200       msg_id.id = DS_LVAL (DS_U->random_id);
201       struct tgl_message *M = tgl_message_get (TLS, &msg_id);
202       if (M && (M->flags & TGLMF_PENDING)) {
203         msg_id = M->permanent_id;
204         msg_id.id = DS_LVAL (DS_U->id);
205         bl_do_set_msg_id (TLS, &M->permanent_id, &msg_id);
206         bl_do_msg_update (TLS, &msg_id);
207       }
208     }
209     break;
210 /*  case CODE_update_read_messages:
211     {
212       int n = DS_LVAL (DS_U->messages->cnt);
213 
214       int i;
215       for (i = 0; i < n; i++) {
216         struct tgl_message *M = tgl_message_get (TLS, DS_LVAL (DS_U->messages->data[i]));
217         if (M) {
218           tgl_peer_t *P;
219           if (M->flags & TGLMF_OUT) {
220             P = tgl_peer_get (TLS, M->to_id);
221             if (P && (P->flags & TGLMF_CREATED)) {
222               if (tgl_get_peer_type (P->id) == TGL_PEER_USER) {
223                 bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL, (int *)&M->id, TGL_FLAGS_UNCHANGED);
224               } else {
225                 bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (int *)&M->id, TGL_FLAGS_UNCHANGED);
226               }
227             }
228           } else {
229             if (tgl_get_peer_type (M->to_id) == TGL_PEER_USER) {
230               P = tgl_peer_get (TLS, M->from_id);
231             } else {
232               P = tgl_peer_get (TLS, M->to_id);
233             }
234             if (P && (P->flags & TGLMF_CREATED)) {
235               if (tgl_get_peer_type (P->id) == TGL_PEER_USER) {
236                 bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, NULL, (int *)&M->id, NULL, TGL_FLAGS_UNCHANGED);
237               } else {
238                 bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (int *)&M->id, NULL, TGL_FLAGS_UNCHANGED);
239               }
240             }
241           }
242         }
243       }
244     }
245     break;*/
246   case CODE_update_user_typing:
247     {
248       tgl_peer_id_t id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
249       tgl_peer_t *U = tgl_peer_get (TLS, id);
250       enum tgl_typing_status status = tglf_fetch_typing (DS_U->action);
251 
252       if (TLS->callback.type_notification && U) {
253         TLS->callback.type_notification (TLS, (void *)U, status);
254       }
255     }
256     break;
257   case CODE_update_chat_user_typing:
258     {
259       tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id));
260       tgl_peer_id_t id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
261       tgl_peer_t *C = tgl_peer_get (TLS, chat_id);
262       tgl_peer_t *U = tgl_peer_get (TLS, id);
263       enum tgl_typing_status status = tglf_fetch_typing (DS_U->action);
264 
265       if (U && C) {
266         if (TLS->callback.type_in_chat_notification) {
267           TLS->callback.type_in_chat_notification (TLS, (void *)U, (void *)C, status);
268         }
269       }
270     }
271     break;
272   case CODE_update_user_status:
273     {
274       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
275       tgl_peer_t *U = tgl_peer_get (TLS, user_id);
276       if (U) {
277         tglf_fetch_user_status (TLS, &U->user.status, &U->user, DS_U->status);
278 
279         if (TLS->callback.status_notification) {
280           TLS->callback.status_notification (TLS, (void *)U);
281         }
282       }
283     }
284     break;
285   case CODE_update_user_name:
286     {
287       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
288       tgl_peer_t *UC = tgl_peer_get (TLS, user_id);
289       if (UC && (UC->flags & TGLPF_CREATED)) {
290         bl_do_user (TLS, tgl_get_peer_id (user_id), NULL, DS_STR (DS_U->first_name), DS_STR (DS_U->last_name), NULL, 0, DS_STR (DS_U->username), NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED);
291       }
292     }
293     break;
294   case CODE_update_user_photo:
295     {
296       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
297       tgl_peer_t *UC = tgl_peer_get (TLS, user_id);
298 
299       if (UC && (UC->flags & TGLUF_CREATED)) {
300         bl_do_user (TLS, tgl_get_peer_id (user_id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, DS_U->photo, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED);
301       }
302     }
303     break;
304   case CODE_update_delete_messages:
305     {
306     }
307     break;
308   case CODE_update_chat_participants:
309     {
310       tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id));
311       tgl_peer_t *C = tgl_peer_get (TLS, chat_id);
312       if (C && (C->flags & TGLPF_CREATED) && DS_U->participants->magic == CODE_chat_participants) {
313         bl_do_chat (TLS, tgl_get_peer_id (chat_id), NULL, 0, NULL, NULL, DS_U->participants->version, (struct tl_ds_vector *)DS_U->participants->participants, NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED);
314       }
315     }
316     break;
317   case CODE_update_contact_registered:
318     {
319       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
320       tgl_peer_t *U = tgl_peer_get (TLS, user_id);
321       if (TLS->callback.user_registered && U) {
322         TLS->callback.user_registered (TLS, (void *)U);
323       }
324     }
325     break;
326   case CODE_update_contact_link:
327     {
328     }
329     break;
330   /*case CODE_update_activation:
331     {
332       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
333       tgl_peer_t *U = tgl_peer_get (TLS, user_id);
334 
335       if (TLS->callback.user_activated && U) {
336         TLS->callback.user_activated (TLS, (void *)U);
337       }
338     }
339     break;*/
340   case CODE_update_new_authorization:
341     {
342       if (TLS->callback.new_authorization) {
343         TLS->callback.new_authorization (TLS, DS_U->device->data, DS_U->location->data);
344       }
345     }
346     break;
347   /*case CODE_update_new_geo_chat_message:
348     {
349     }
350     break;*/
351   case CODE_update_new_encrypted_message:
352     {
353       struct tgl_message *M = tglf_fetch_alloc_encrypted_message (TLS, DS_U->encr_message);
354       if (M) {
355         bl_do_msg_update (TLS, &M->permanent_id);
356       }
357     }
358     break;
359   case CODE_update_encryption:
360     {
361       struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (TLS, DS_U->encr_chat);
362       vlogprintf (E_DEBUG, "Secret chat state = %d\n", E->state);
363       if (E->state == sc_ok) {
364         tgl_do_send_encr_chat_layer (TLS, E);
365       }
366     }
367     break;
368   case CODE_update_encrypted_chat_typing:
369     {
370       tgl_peer_id_t id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_U->chat_id));
371       tgl_peer_t *P = tgl_peer_get (TLS, id);
372 
373       if (P) {
374         if (TLS->callback.type_in_secret_chat_notification) {
375           TLS->callback.type_in_secret_chat_notification (TLS, (void *)P);
376         }
377       }
378     }
379     break;
380   case CODE_update_encrypted_messages_read:
381     {
382       tgl_peer_id_t id = TGL_MK_ENCR_CHAT (DS_LVAL (DS_U->chat_id));
383       tgl_peer_t *P = tgl_peer_get (TLS, id);
384 
385       if (P && P->last) {
386         struct tgl_message *M = P->last;
387         while (M && (!(M->flags & TGLMF_OUT) || (M->flags & TGLMF_UNREAD))) {
388           if (M->flags & TGLMF_OUT) {
389             bl_do_edit_message_encr (TLS, &M->permanent_id, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, M->flags & ~TGLMF_UNREAD);
390           }
391           M = M->next;
392         }
393       }
394     }
395     break;
396   case CODE_update_chat_participant_add:
397     {
398       tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id));
399       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
400       tgl_peer_id_t inviter_id = TGL_MK_USER (DS_LVAL (DS_U->inviter_id));
401       int version = DS_LVAL (DS_U->version);
402 
403       tgl_peer_t *C = tgl_peer_get (TLS, chat_id);
404       if (C && (C->flags & TGLPF_CREATED)) {
405         bl_do_chat_add_user (TLS, C->id, version, tgl_get_peer_id (user_id), tgl_get_peer_id (inviter_id), time (0));
406       }
407     }
408     break;
409   case CODE_update_chat_participant_delete:
410     {
411       tgl_peer_id_t chat_id = TGL_MK_CHAT (DS_LVAL (DS_U->chat_id));
412       tgl_peer_id_t user_id = TGL_MK_USER (DS_LVAL (DS_U->user_id));
413       int version = DS_LVAL (DS_U->version);
414 
415       tgl_peer_t *C = tgl_peer_get (TLS, chat_id);
416       if (C && (C->flags & TGLPF_CREATED)) {
417         bl_do_chat_del_user (TLS, C->id, version, tgl_get_peer_id (user_id));
418       }
419     }
420     break;
421   case CODE_update_dc_options:
422     {
423       int i;
424       for (i = 0; i < DS_LVAL (DS_U->dc_options->cnt); i++) {
425         fetch_dc_option (TLS, DS_U->dc_options->data[i]);
426       }
427     }
428     break;
429   case CODE_update_user_blocked:
430     {
431       int blocked = DS_BVAL (DS_U->blocked);
432       tgl_peer_t *P = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user_id)));
433       if (P && (P->flags & TGLPF_CREATED)) {
434         int flags = P->flags & 0xffff;
435         if (blocked) {
436           flags |= TGLUF_BLOCKED;
437         } else {
438           flags &= ~TGLUF_BLOCKED;
439         }
440         bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, flags);
441       }
442     }
443     break;
444   case CODE_update_notify_settings:
445     {
446     }
447     break;
448   case CODE_update_service_notification:
449     {
450       vlogprintf (E_ERROR, "Notification %.*s: %.*s\n", DS_RSTR (DS_U->type), DS_RSTR (DS_U->message_text));
451       if (TLS->callback.notification) {
452         TLS->callback.notification (TLS, DS_U->type->data, DS_U->message_text->data);
453       }
454     }
455     break;
456   case CODE_update_privacy:
457     vlogprintf (E_NOTICE, "privacy change update\n");
458     break;
459   case CODE_update_user_phone:
460     {
461       tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (DS_LVAL (DS_U->user_id)));
462       if (U && (U->flags & TGLPF_CREATED)) {
463         bl_do_user (TLS, tgl_get_peer_id (U->id), NULL, NULL, 0, NULL, 0, DS_STR (DS_U->phone), NULL, 0, NULL, NULL, NULL, NULL, NULL, TGL_FLAGS_UNCHANGED);
464       }
465     }
466     break;
467   case CODE_update_read_history_inbox:
468     {
469       tgl_peer_id_t id = tglf_fetch_peer_id (TLS, DS_U->peer);
470       tgl_peer_t *P = tgl_peer_get (TLS, id);
471       if (P && (P->flags & TGLPF_CREATED)) {
472         if (tgl_get_peer_type (P->id) == TGL_PEER_USER) {
473           bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, DS_U->max_id, NULL, NULL, TGL_FLAGS_UNCHANGED);
474         } else {
475           bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, DS_U->max_id, NULL, TGL_FLAGS_UNCHANGED);
476         }
477       }
478     }
479     break;
480   case CODE_update_read_history_outbox:
481     {
482       tgl_peer_id_t id = tglf_fetch_peer_id (TLS, DS_U->peer);
483       tgl_peer_t *P = tgl_peer_get (TLS, id);
484       if (P && (P->flags & TGLPF_CREATED)) {
485         if (tgl_get_peer_type (P->id) == TGL_PEER_USER) {
486           bl_do_user (TLS, tgl_get_peer_id (P->id), NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, NULL, DS_U->max_id, NULL, TGL_FLAGS_UNCHANGED);
487         } else {
488           bl_do_chat (TLS, tgl_get_peer_id (P->id), NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, DS_U->max_id, TGL_FLAGS_UNCHANGED);
489         }
490       }
491     }
492     break;
493   case CODE_update_web_page:
494     {
495     }
496     break;
497   /*case CODE_update_msg_update:
498     {
499       struct tgl_message *M = tgl_message_get (TLS, DS_LVAL (DS_U->id));
500       if (M) {
501         bl_do_msg_update (TLS, M->id);
502       }
503     }
504     break;*/
505   case CODE_update_read_messages_contents:
506     break;
507   case CODE_update_channel_too_long:
508     {
509       tgl_do_get_channel_difference (TLS, DS_LVAL (DS_U->channel_id), NULL, NULL);
510     }
511     break;
512   case CODE_update_channel:
513     break;
514   case CODE_update_channel_group:
515     break;
516   case CODE_update_new_channel_message:
517     {
518       int new_msg = 0;
519       struct tgl_message *M = tglf_fetch_alloc_message (TLS, DS_U->message, &new_msg);
520       if (M && new_msg) {
521         bl_do_msg_update (TLS, &M->permanent_id);
522       }
523     }
524     break;
525   case CODE_update_read_channel_inbox:
526     break;
527   case CODE_update_delete_channel_messages:
528     break;
529   case CODE_update_channel_message_views:
530     break;
531   case CODE_update_chat_admins:
532     break;
533   case CODE_update_chat_participant_admin:
534     break;
535   case CODE_update_new_sticker_set:
536     break;
537   case CODE_update_sticker_sets_order:
538     break;
539   case CODE_update_sticker_sets:
540     break;
541   case CODE_update_saved_gifs:
542     break;
543   case CODE_update_bot_inline_query:
544     break;
545   default:
546     assert (0);
547   }
548 
549   if (check_only) { return; }
550 
551   if (DS_U->pts) {
552     assert (DS_U->pts_count);
553 
554     bl_do_set_pts (TLS, DS_LVAL (DS_U->pts));
555   }
556   if (DS_U->qts) {
557     bl_do_set_qts (TLS, DS_LVAL (DS_U->qts));
558   }
559   if (DS_U->channel_pts) {
560     assert (DS_U->channel_pts_count);
561 
562     int channel_id;
563     if (DS_U->channel_id) {
564       channel_id = DS_LVAL (DS_U->channel_id);
565     } else {
566       assert (DS_U->message);
567       assert (DS_U->message->to_id);
568       assert (DS_U->message->to_id->magic == CODE_peer_channel);
569       channel_id = DS_LVAL (DS_U->message->to_id->channel_id);
570     }
571 
572     bl_do_set_channel_pts (TLS, channel_id, DS_LVAL (DS_U->channel_pts));
573   }
574 }
575 
tglu_work_updates(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U)576 void tglu_work_updates (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) {
577   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
578     return;
579   }
580 
581   if (!check_only && do_skip_seq (TLS, DS_LVAL (DS_U->seq)) < 0) {
582     return;
583   }
584   int i;
585   if (DS_U->users) {
586     for (i = 0; i < DS_LVAL (DS_U->users->cnt); i++) {
587       tglf_fetch_alloc_user (TLS, DS_U->users->data[i]);
588     }
589   }
590   if (DS_U->chats) {
591     for (i = 0; i < DS_LVAL (DS_U->chats->cnt); i++) {
592       tglf_fetch_alloc_chat (TLS, DS_U->chats->data[i]);
593     }
594   }
595   if (DS_U->updates) {
596     for (i = 0; i < DS_LVAL (DS_U->updates->cnt); i++) {
597       tglu_work_update (TLS, check_only, DS_U->updates->data[i]);
598     }
599   }
600 
601   if (check_only) { return; }
602   bl_do_set_date (TLS, DS_LVAL (DS_U->date));
603   bl_do_set_seq (TLS, DS_LVAL (DS_U->seq));
604 }
605 
tglu_work_updates_combined(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U)606 void tglu_work_updates_combined (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) {
607   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
608     return;
609   }
610 
611   if (!check_only && do_skip_seq (TLS, DS_LVAL (DS_U->seq_start)) < 0) {
612     return;
613   }
614 
615   int i;
616   for (i = 0; i < DS_LVAL (DS_U->users->cnt); i++) {
617     tglf_fetch_alloc_user (TLS, DS_U->users->data[i]);
618   }
619   for (i = 0; i < DS_LVAL (DS_U->chats->cnt); i++) {
620     tglf_fetch_alloc_chat (TLS, DS_U->chats->data[i]);
621   }
622   for (i = 0; i < DS_LVAL (DS_U->updates->cnt); i++) {
623     tglu_work_update (TLS, check_only, DS_U->updates->data[i]);
624   }
625 
626   if (check_only) { return; }
627   bl_do_set_date (TLS, DS_LVAL (DS_U->date));
628   bl_do_set_seq (TLS, DS_LVAL (DS_U->seq));
629 }
630 
tglu_work_update_short_message(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U)631 void tglu_work_update_short_message (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) {
632   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
633     return;
634   }
635 
636   if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) {
637     return;
638   }
639 
640   if (check_only > 0) { return; }
641 
642   //struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_U->id));
643   //int new = (!N || !(N->flags & TGLMF_CREATED));
644 
645   struct tgl_message *M = tglf_fetch_alloc_message_short (TLS, DS_U);
646 
647   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
648     return;
649   }
650   assert (M);
651 
652   if (1) {
653     bl_do_msg_update (TLS, &M->permanent_id);
654   }
655 
656   if (check_only) { return; }
657   bl_do_set_pts (TLS, DS_LVAL (DS_U->pts));
658 }
659 
tglu_work_update_short_chat_message(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U)660 void tglu_work_update_short_chat_message (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) {
661   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
662     return;
663   }
664 
665   if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) {
666     return;
667   }
668 
669   if (check_only > 0) { return; }
670 
671   //struct tgl_message *N = tgl_message_get (TLS, DS_LVAL (DS_U->id));
672   //int new = (!N || !(N->flags & TGLMF_CREATED));
673 
674   struct tgl_message *M = tglf_fetch_alloc_message_short_chat (TLS, DS_U);
675 
676   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
677     return;
678   }
679 
680   assert (M);
681 
682   if (1) {
683     bl_do_msg_update (TLS, &M->permanent_id);
684   }
685 
686   if (check_only) { return; }
687   bl_do_set_pts (TLS, DS_LVAL (DS_U->pts));
688 }
689 
tglu_work_updates_too_long(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U)690 void tglu_work_updates_too_long (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) {
691   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
692     return;
693   }
694   vlogprintf (E_NOTICE, "updates too long... Getting difference\n");
695   if (check_only) { return; }
696   tgl_do_get_difference (TLS, 0, 0, 0);
697 }
698 
tglu_work_update_short(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U)699 void tglu_work_update_short (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U) {
700   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
701     return;
702   }
703   tglu_work_update (TLS, check_only, DS_U->update);
704 }
705 
tglu_work_update_short_sent_message(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U,void * extra)706 void tglu_work_update_short_sent_message (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U, void *extra) {
707   if (DS_U->pts) {
708     assert (DS_U->pts_count);
709 
710     if (!check_only && tgl_check_pts_diff (TLS, DS_LVAL (DS_U->pts), DS_LVAL (DS_U->pts_count)) <= 0) {
711       return;
712     }
713   }
714   struct tgl_message *M = extra;
715 
716   if (!M) { return; }
717 
718   //long long random_id = M->permanent_id.id;
719   tgl_message_id_t msg_id = M->permanent_id;
720   msg_id.id = DS_LVAL (DS_U->id);
721   bl_do_set_msg_id (TLS, &M->permanent_id, &msg_id);
722   //tgls_insert_random2local (TLS, random_id, &msg_id);
723 
724   int f = DS_LVAL (DS_U->flags);
725 
726   unsigned flags = M->flags;
727   if (f & 1) {
728     flags |= TGLMF_UNREAD;
729   }
730   if (f & 2) {
731     flags |= TGLMF_OUT;
732   }
733   if (f & 16) {
734     flags |= TGLMF_MENTION;
735   }
736 
737   bl_do_edit_message (TLS, &M->permanent_id,
738     NULL,
739     NULL,
740     NULL,
741     NULL,
742     NULL,
743     NULL, 0,
744     DS_U->media,
745     NULL,
746     NULL,
747     NULL,
748     NULL,
749     flags);
750 
751   if (check_only) { return; }
752   bl_do_msg_update (TLS, &M->permanent_id);
753 
754   if (DS_U->pts) {
755     bl_do_set_pts (TLS, DS_LVAL (DS_U->pts));
756   }
757 }
758 
tglu_work_any_updates(struct tgl_state * TLS,int check_only,struct tl_ds_updates * DS_U,void * extra)759 void tglu_work_any_updates (struct tgl_state *TLS, int check_only, struct tl_ds_updates *DS_U, void *extra) {
760   if (check_only > 0 || (TLS->locks & TGL_LOCK_DIFF)) {
761     return;
762   }
763   switch (DS_U->magic) {
764   case CODE_updates_too_long:
765     tglu_work_updates_too_long (TLS, check_only, DS_U);
766     return;
767   case CODE_update_short_message:
768     tglu_work_update_short_message (TLS, check_only, DS_U);
769     return;
770   case CODE_update_short_chat_message:
771     tglu_work_update_short_chat_message (TLS, check_only, DS_U);
772     return;
773   case CODE_update_short:
774     tglu_work_update_short (TLS, check_only, DS_U);
775     return;
776   case CODE_updates_combined:
777     tglu_work_updates_combined (TLS, check_only, DS_U);
778     return;
779   case CODE_updates:
780     tglu_work_updates (TLS, check_only, DS_U);
781     return;
782   case CODE_update_short_sent_message:
783     tglu_work_update_short_sent_message (TLS, check_only, DS_U, extra);
784     return;
785   default:
786     assert (0);
787   }
788 }
789 
tglu_work_any_updates_buf(struct tgl_state * TLS)790 void tglu_work_any_updates_buf (struct tgl_state *TLS) {
791   struct tl_ds_updates *DS_U = fetch_ds_type_updates (TYPE_TO_PARAM (updates));
792   assert (DS_U);
793   tglu_work_any_updates (TLS, 1, DS_U, NULL);
794   tglu_work_any_updates (TLS, 0, DS_U, NULL);
795   free_ds_type_updates (DS_U, TYPE_TO_PARAM (updates));
796 }
797 
798 #define user_cmp(a,b) (tgl_get_peer_id ((a)->id) - tgl_get_peer_id ((b)->id))
799 DEFINE_TREE(user, struct tgl_user *,user_cmp,0)
800 
notify_status(struct tgl_user * U,void * ex)801 static void notify_status (struct tgl_user *U, void *ex) {
802   struct tgl_state *TLS = ex;
803   if (TLS->callback.user_status_update) {
804     TLS->callback.user_status_update (TLS, U);
805   }
806 }
807 
status_notify(struct tgl_state * TLS,void * arg)808 static void status_notify (struct tgl_state *TLS, void *arg) {
809   tree_act_ex_user (TLS->online_updates, notify_status, TLS);
810   tree_clear_user (TLS->online_updates);
811   TLS->online_updates = NULL;
812   TLS->timer_methods->free (TLS->online_updates_timer);
813   TLS->online_updates_timer = NULL;
814 }
815 
tgl_insert_status_update(struct tgl_state * TLS,struct tgl_user * U)816 void tgl_insert_status_update (struct tgl_state *TLS, struct tgl_user *U) {
817   if (!tree_lookup_user (TLS->online_updates, U)) {
818     TLS->online_updates = tree_insert_user (TLS->online_updates, U, rand ());
819   }
820   if (!TLS->online_updates_timer) {
821     TLS->online_updates_timer = TLS->timer_methods->alloc (TLS, status_notify, 0);
822     TLS->timer_methods->insert (TLS->online_updates_timer, 0);
823   }
824 }
825 
user_expire(struct tgl_state * TLS,void * arg)826 static void user_expire (struct tgl_state *TLS, void *arg) {
827   struct tgl_user *U = arg;
828   TLS->timer_methods->free (U->status.ev);
829   U->status.ev = 0;
830   U->status.online = -1;
831   U->status.when = tglt_get_double_time ();
832   tgl_insert_status_update (TLS, U);
833 }
834 
tgl_insert_status_expire(struct tgl_state * TLS,struct tgl_user * U)835 void tgl_insert_status_expire (struct tgl_state *TLS, struct tgl_user *U) {
836   assert (!U->status.ev);
837   U->status.ev = TLS->timer_methods->alloc (TLS, user_expire, U);
838   TLS->timer_methods->insert (U->status.ev, U->status.when - tglt_get_double_time ());
839 }
840 
tgl_remove_status_expire(struct tgl_state * TLS,struct tgl_user * U)841 void tgl_remove_status_expire (struct tgl_state *TLS, struct tgl_user *U) {
842   TLS->timer_methods->free (U->status.ev);
843   U->status.ev = 0;
844 }
845