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