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
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/file.h>
29 #include <stdlib.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <assert.h>
35 #include "crypto/bn.h"
36
37 #include "tgl-binlog.h"
38 #include "mtproto-common.h"
39 //#include "net.h"
40 #include "mtproto-client.h"
41 #include "mtproto-utils.h"
42
43 #include "tgl.h"
44 #include "auto.h"
45 #include "auto/auto-types.h"
46 #include "auto/auto-skip.h"
47 #include "auto/auto-store-ds.h"
48 #include "auto/auto-fetch-ds.h"
49 #include "auto/auto-free-ds.h"
50
51 #include "tgl-structures.h"
52 #include "tgl-methods-in.h"
53
54 #include "crypto/sha.h"
55
mystreq1(const char * a,const char * b,int l)56 static int mystreq1 (const char *a, const char *b, int l) {
57 if ((int)strlen (a) != l) { return 1; }
58 return memcmp (a, b, l);
59 }
60
bl_do_dc_option(struct tgl_state * TLS,int flags,int id,const char * name,int l1,const char * ip,int l2,int port)61 void bl_do_dc_option (struct tgl_state *TLS, int flags, int id, const char *name, int l1, const char *ip, int l2, int port) /* {{{ */ {
62 struct tgl_dc *DC = TLS->DC_list[id];
63
64 if (DC) {
65 struct tgl_dc_option *O = DC->options[flags & 3];
66 while (O) {
67 if (!strncmp (O->ip, ip, l2)) {
68 return;
69 }
70 O = O->next;
71 }
72 }
73
74 vlogprintf (E_NOTICE, "DC%d '%.*s' update: %.*s:%d\n",
75 id,
76 l1, name,
77 l2, ip,
78 port
79 );
80
81 tglmp_alloc_dc (TLS,
82 flags,
83 id,
84 tstrndup (ip, l2),
85 port
86 );
87 }
88 /* }}} */
89
bl_do_set_working_dc(struct tgl_state * TLS,int num)90 void bl_do_set_working_dc (struct tgl_state *TLS, int num) /* {{{ */ {
91 assert (num > 0 && num <= MAX_DC_ID);
92 TLS->DC_working = TLS->DC_list[num];
93 TLS->dc_working_num = num;
94 }
95 /* }}} */
96
bl_do_dc_signed(struct tgl_state * TLS,int num)97 void bl_do_dc_signed (struct tgl_state *TLS, int num) /* {{{ */ {
98 assert (num > 0 && num <= MAX_DC_ID);
99 assert (TLS->DC_list[num]);
100 TLS->DC_list[num]->flags |= TGLDCF_LOGGED_IN;
101 }
102 /* }}} */
103
bl_do_set_auth_key(struct tgl_state * TLS,int num,unsigned char * buf)104 void bl_do_set_auth_key (struct tgl_state *TLS, int num, unsigned char *buf) /* {{{ */ {
105 assert (num > 0 && num <= MAX_DC_ID);
106 assert (TLS->DC_list[num]);
107
108 if (TLS->DC_list[num]->auth_key != (char *)buf)
109 memcpy (TLS->DC_list[num]->auth_key, buf, 256);
110
111 static unsigned char sha1_buffer[20];
112 TGLC_sha1 ((void *)TLS->DC_list[num]->auth_key, 256, sha1_buffer);
113 TLS->DC_list[num]->auth_key_id = *(long long *)(sha1_buffer + 12);
114
115 TLS->DC_list[num]->flags |= TGLDCF_AUTHORIZED;
116 }
117 /* }}} */
118
bl_do_set_our_id(struct tgl_state * TLS,tgl_peer_id_t id)119 void bl_do_set_our_id (struct tgl_state *TLS, tgl_peer_id_t id) /* {{{ */ {
120 /*if (TLS->our_id.peer_type) {
121 assert (!tgl_cmp_peer_id (TLS->our_id, id));
122 return;
123 }*/
124
125 TLS->our_id = id;
126
127 if (TLS->callback.our_id) {
128 TLS->callback.our_id (TLS, TLS->our_id);
129 }
130 }
131 /* }}} */
132
bl_do_set_dh_params(struct tgl_state * TLS,int root,unsigned char prime[],int version)133 void bl_do_set_dh_params (struct tgl_state *TLS, int root, unsigned char prime[], int version) /* {{{ */ {
134 if (TLS->encr_prime) { tfree (TLS->encr_prime, 256); TGLC_bn_free (TLS->encr_prime_bn); }
135
136 TLS->encr_root = root;
137
138 TLS->encr_prime = talloc (256);
139 memcpy (TLS->encr_prime, prime, 256);
140 TLS->encr_prime_bn = TGLC_bn_new ();
141 TGLC_bn_bin2bn ((void *)TLS->encr_prime, 256, TLS->encr_prime_bn);
142
143 TLS->encr_param_version = version;
144
145 assert (tglmp_check_DH_params (TLS, TLS->encr_prime_bn, TLS->encr_root) >= 0);
146 }
147 /* }}} */
148
bl_do_set_pts(struct tgl_state * TLS,int pts)149 void bl_do_set_pts (struct tgl_state *TLS, int pts) /* {{{ */ {
150 if (TLS->locks & TGL_LOCK_DIFF) { return; }
151 if (pts <= TLS->pts) { return; }
152
153 TLS->pts = pts;
154 }
155 /* }}} */
156
bl_do_set_channel_pts(struct tgl_state * TLS,int id,int pts)157 void bl_do_set_channel_pts (struct tgl_state *TLS, int id, int pts) /* {{{ */ {
158 tgl_peer_t *E = tgl_peer_get (TLS, TGL_MK_CHANNEL (id));
159 if (!E || !(E->flags & TGLPF_CREATED)) { return; }
160 if (E->flags & TGLCHF_DIFF) { return ; }
161 if (E->channel.pts <= pts) { return; }
162 E->channel.pts = pts;
163 }
164 /* }}} */
165
bl_do_set_qts(struct tgl_state * TLS,int qts)166 void bl_do_set_qts (struct tgl_state *TLS, int qts) /* {{{ */ {
167 if (TLS->locks & TGL_LOCK_DIFF) { return; }
168 if (qts <= TLS->qts) { return; }
169
170 TLS->qts = qts;
171 }
172 /* }}} */
173
bl_do_set_date(struct tgl_state * TLS,int date)174 void bl_do_set_date (struct tgl_state *TLS, int date) /* {{{ */ {
175 if (TLS->locks & TGL_LOCK_DIFF) { return; }
176 if (date <= TLS->date) { return; }
177
178 TLS->date = date;
179 }
180 /* }}} */
181
bl_do_set_seq(struct tgl_state * TLS,int seq)182 void bl_do_set_seq (struct tgl_state *TLS, int seq) /* {{{ */ {
183 if (TLS->locks & TGL_LOCK_DIFF) { return; }
184 if (seq <= TLS->seq) { return; }
185
186 TLS->seq = seq;
187 }
188 /* }}} */
189
bl_do_set_msg_id(struct tgl_state * TLS,tgl_message_id_t * old_id,tgl_message_id_t * new_id)190 void bl_do_set_msg_id (struct tgl_state *TLS, tgl_message_id_t *old_id, tgl_message_id_t *new_id) /* {{{ */ {
191 if (!memcmp (old_id, new_id, sizeof (tgl_message_id_t))) {
192 return;
193 }
194
195 struct tgl_message *M = tgl_message_get (TLS, old_id);
196 assert (M);
197
198
199 if (M->flags & TGLMF_PENDING) {
200 tglm_message_remove_unsent (TLS, M);
201 M->flags &= ~TGLMF_PENDING;
202 }
203
204 tglm_message_remove_tree (TLS, M);
205 tglm_message_del_peer (TLS, M);
206
207 M->permanent_id = *new_id;
208 if (tgl_message_get (TLS, new_id)) {
209 tglm_message_del_use (TLS, M);
210 tglm_message_del_temp_id (TLS, M);
211 tglm_message_del_random_id (TLS, M);
212 tgls_free_message (TLS, M);
213 } else {
214 tglm_message_insert_tree (TLS, M);
215 tglm_message_add_peer (TLS, M);
216 }
217
218 M->server_id = new_id->id;
219 }
220 /* }}} */
221
bl_do_chat_add_user(struct tgl_state * TLS,tgl_peer_id_t id,int version,int user,int inviter,int date)222 void bl_do_chat_add_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user, int inviter, int date) /* {{{ */ {
223 tgl_peer_t *P = tgl_peer_get (TLS, id);
224 if (!P || !(P->flags & TGLPF_CREATED)) { return; }
225
226 struct tgl_chat *C = &P->chat;
227 if (C->user_list_version >= version || !C->user_list_version) { return; }
228
229 int i;
230 for (i = 0; i < C->user_list_size; i++) {
231 if (C->user_list[i].user_id == user) {
232 return;
233 }
234 }
235
236 C->user_list_size ++;
237 C->user_list = trealloc (C->user_list, 12 * C->user_list_size - 12, 12 * C->user_list_size);
238 C->user_list[C->user_list_size - 1].user_id = user;
239 C->user_list[C->user_list_size - 1].inviter_id = inviter;
240 C->user_list[C->user_list_size - 1].date = date;
241 C->user_list_version = version;
242
243 if (TLS->callback.chat_update) {
244 TLS->callback.chat_update (TLS, C, TGL_UPDATE_MEMBERS);
245 }
246 }
247 /* }}} */
248
bl_do_chat_del_user(struct tgl_state * TLS,tgl_peer_id_t id,int version,int user)249 void bl_do_chat_del_user (struct tgl_state *TLS, tgl_peer_id_t id, int version, int user) /* {{{ */ {
250 tgl_peer_t *P = tgl_peer_get (TLS, id);
251 if (!P || !(P->flags & TGLPF_CREATED)) { return; }
252
253 struct tgl_chat *C = &P->chat;
254 if (C->user_list_version >= version || !C->user_list_version) { return; }
255
256 int i;
257 for (i = 0; i < C->user_list_size; i++) {
258 if (C->user_list[i].user_id == user) {
259 struct tgl_chat_user t;
260 t = C->user_list[i];
261 C->user_list[i] = C->user_list[C->user_list_size - 1];
262 C->user_list[C->user_list_size - 1] = t;
263 }
264 }
265 if (C->user_list[C->user_list_size - 1].user_id != user) { return; }
266
267 assert (C->user_list[C->user_list_size - 1].user_id == user);
268 C->user_list_size --;
269 C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size);
270 C->user_list_version = version;
271
272 if (TLS->callback.chat_update) {
273 TLS->callback.chat_update (TLS, C, TGL_UPDATE_MEMBERS);
274 }
275 }
276 /* }}} */
277
bl_do_edit_message(struct tgl_state * TLS,tgl_message_id_t * id,tgl_peer_id_t * from_id,tgl_peer_id_t * to_id,tgl_peer_id_t * fwd_from_id,int * fwd_date,int * date,const char * message,int message_len,struct tl_ds_message_media * media,struct tl_ds_message_action * action,int * reply_id,struct tl_ds_reply_markup * reply_markup,struct tl_ds_vector * entities,int flags)278 void bl_do_edit_message (struct tgl_state *TLS, tgl_message_id_t *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, tgl_peer_id_t *fwd_from_id, int *fwd_date, int *date, const char *message, int message_len, struct tl_ds_message_media *media, struct tl_ds_message_action *action, int *reply_id, struct tl_ds_reply_markup *reply_markup, struct tl_ds_vector *entities, int flags) /* {{{ */ {
279 assert (!(flags & 0xfffe0000));
280
281 struct tgl_message *M = tgl_message_get (TLS, id);
282
283 assert (flags & TGLMF_CREATED);
284 assert (!(flags & TGLMF_ENCRYPTED));
285
286 if (flags & (1 << 16)) {
287 if (!M) {
288 M = tglm_message_alloc (TLS, id);
289 }
290 M->server_id = id->id;
291 assert (!(M->flags & TGLMF_CREATED));
292 } else {
293 assert (M->flags & TGLMF_CREATED);
294 }
295
296 assert (M);
297 assert (!(M->flags & TGLMF_ENCRYPTED));
298
299 if ((M->flags & TGLMF_PENDING) && !(flags & TGLMF_PENDING)){
300 tglm_message_remove_unsent (TLS, M);
301 }
302 if (!(M->flags & TGLMF_PENDING) && (flags & TGLMF_PENDING)){
303 tglm_message_insert_unsent (TLS, M);
304 }
305
306 if ((M->flags & TGLMF_UNREAD) && !(flags & TGLMF_UNREAD)) {
307 M->flags = (flags & 0xffff) | TGLMF_UNREAD;
308 } else {
309 M->flags = (flags & 0xffff);
310 }
311
312 if (from_id) {
313 M->from_id = *from_id;
314 } else {
315 if (!M->from_id.peer_type) {
316 assert (to_id);
317 M->from_id = *to_id;
318 }
319 }
320
321 if (to_id) {
322 assert (flags & 0x10000);
323 M->to_id = *to_id;
324 }
325
326 if (date) {
327 M->date = *date;
328 }
329
330 if (fwd_from_id) {
331 assert (fwd_date);
332 M->fwd_from_id = *fwd_from_id;
333 M->fwd_date = *fwd_date;;
334 }
335
336 if (action) {
337 tglf_fetch_message_action (TLS, &M->action, action);
338 M->flags |= TGLMF_SERVICE;
339 }
340
341 if (message) {
342 M->message_len = message_len;
343 M->message = tstrndup (message, message_len);
344 assert (!(M->flags & TGLMF_SERVICE));
345 }
346
347 if (media) {
348 tglf_fetch_message_media (TLS, &M->media, media);
349 assert (!(M->flags & TGLMF_SERVICE));
350 }
351
352 if (entities) {
353 tglf_fetch_message_entities (TLS, M, entities);
354 }
355
356 if (reply_id) {
357 M->reply_id = *reply_id;
358 }
359
360 if (flags & 0x10000) {
361 tglm_message_insert (TLS, M);
362 }
363
364 if (!(flags & TGLMF_UNREAD) && (M->flags & TGLMF_UNREAD)) {
365 tgls_messages_mark_read (TLS, M, M->flags & TGLMF_OUT, M->permanent_id.id);
366 }
367
368 if (reply_markup) {
369 M->reply_markup = tglf_fetch_alloc_reply_markup (TLS, M->next, reply_markup);
370 }
371
372 if (M->flags & TGLMF_PENDING) {
373 tgls_message_change_random_id (TLS, M, M->permanent_id.id);
374 }
375
376 if (!M->temp_id) {
377 tgls_message_change_temp_id (TLS, M, ++TLS->last_temp_id);
378 }
379 }
380 /* }}} */
381
bl_do_edit_message_encr(struct tgl_state * TLS,tgl_message_id_t * id,tgl_peer_id_t * from_id,tgl_peer_id_t * to_id,int * date,const char * message,int message_len,struct tl_ds_decrypted_message_media * media,struct tl_ds_decrypted_message_action * action,struct tl_ds_encrypted_file * file,int flags)382 void bl_do_edit_message_encr (struct tgl_state *TLS, tgl_message_id_t *id, tgl_peer_id_t *from_id, tgl_peer_id_t *to_id, int *date, const char *message, int message_len, struct tl_ds_decrypted_message_media *media, struct tl_ds_decrypted_message_action *action, struct tl_ds_encrypted_file *file, int flags) /* {{{ */ {
383 clear_packet ();
384 assert (!(flags & 0xfffe0000));
385
386 struct tgl_message *M = tgl_message_get (TLS, id);
387
388 if (flags & (1 << 16)) {
389 if (!M) {
390 M = tglm_message_alloc (TLS, id);
391 } else {
392 assert (!(M->flags & TGLMF_CREATED));
393 }
394 assert (!(M->flags & TGLMF_CREATED));
395 } else {
396 assert (M->flags & TGLMF_CREATED);
397 }
398
399 assert (flags & TGLMF_CREATED);
400 assert (flags & TGLMF_ENCRYPTED);
401
402 if ((M->flags & TGLMF_PENDING) && !(flags & TGLMF_PENDING)){
403 tglm_message_remove_unsent (TLS, M);
404 }
405 if (!(M->flags & TGLMF_PENDING) && (flags & TGLMF_PENDING)){
406 tglm_message_insert_unsent (TLS, M);
407 }
408
409 M->flags = flags & 0xffff;
410
411 if (from_id) {
412 M->from_id = *from_id;
413 }
414 if (to_id) {
415 assert (flags & 0x10000);
416 M->to_id = *to_id;
417 }
418
419 if (date) {
420 M->date = *date;
421 }
422
423 struct tgl_secret_chat *E = (void *)tgl_peer_get (TLS, M->to_id);
424 assert (E);
425
426 if (action) {
427 tglf_fetch_message_action_encrypted (TLS, &M->action, action);
428 M->flags |= TGLMF_SERVICE;
429 }
430
431 if (message) {
432 M->message_len = message_len;
433 M->message = tstrndup (message, message_len);
434 assert (!(M->flags & TGLMF_SERVICE));
435 }
436
437 if (media) {
438 tglf_fetch_message_media_encrypted (TLS, &M->media, media);
439 assert (!(M->flags & TGLMF_SERVICE));
440 }
441
442 if (file) {
443 tglf_fetch_encrypted_message_file (TLS, &M->media, file);
444 assert (!(M->flags & TGLMF_SERVICE));
445 }
446
447 if (action && !(M->flags & TGLMF_OUT) && M->action.type == tgl_message_action_notify_layer) {
448 E->layer = M->action.layer;
449 }
450
451 if ((flags & TGLMF_CREATE) && (flags & TGLMF_OUT)) {
452 E->out_seq_no ++;
453 }
454
455 if (flags & 0x10000) {
456 tglm_message_insert (TLS, M);
457 }
458 }
459 /* }}} */
460
bl_do_message_delete(struct tgl_state * TLS,tgl_message_id_t * id)461 void bl_do_message_delete (struct tgl_state *TLS, tgl_message_id_t *id) /* {{{ */ {
462 struct tgl_message *M = tgl_message_get (TLS, id);
463 if (!M) { return; }
464 assert (M);
465 if (M->flags & TGLMF_PENDING) {
466 tglm_message_remove_unsent (TLS, M);
467 M->flags &= ~TGLMF_PENDING;
468 }
469
470 tglm_message_remove_tree (TLS, M);
471 tglm_message_del_peer (TLS, M);
472 tglm_message_del_use (TLS, M);
473 tglm_message_del_temp_id (TLS, M);
474 tglm_message_del_random_id (TLS, M);
475 tgls_free_message (TLS, M);
476 }
477 /* }}} */
478
bl_do_msg_update(struct tgl_state * TLS,tgl_message_id_t * id)479 void bl_do_msg_update (struct tgl_state *TLS, tgl_message_id_t *id) /* {{{ */ {
480 struct tgl_message *M = tgl_message_get (TLS, id);
481 if (!M) { return; }
482 assert (M);
483
484 if (!(M->flags & TGLMF_ENCRYPTED)) {
485 if (TLS->max_msg_id < M->server_id) {
486 TLS->max_msg_id = M->server_id;
487 }
488 }
489
490 if (TLS->callback.msg_receive) {
491 TLS->callback.msg_receive (TLS, M);
492 }
493 }
494 /* }}} */
495
bl_do_reset_authorization(struct tgl_state * TLS)496 void bl_do_reset_authorization (struct tgl_state *TLS) /* {{{ */ {
497 int i;
498 for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) {
499 struct tgl_dc *D = TLS->DC_list[i];
500 D->flags = 0;
501 D->state = st_init;
502 D->auth_key_id = D->temp_auth_key_id = 0;
503 }
504 TLS->seq = 0;
505 TLS->qts = 0;
506 }
507 /* }}} */
508
bl_do_encr_chat_exchange(struct tgl_state * TLS,tgl_peer_id_t id,long long * exchange_id,const void * key,int * state)509 void bl_do_encr_chat_exchange (struct tgl_state *TLS, tgl_peer_id_t id, long long *exchange_id, const void *key, int *state) /* {{{ */ {
510 tgl_peer_t *P = tgl_peer_get (TLS, id);
511 if (!P) { return; }
512
513 if (state) {
514 P->encr_chat.exchange_state = *state;
515 }
516 if (exchange_id) {
517 P->encr_chat.exchange_id = *exchange_id;
518 }
519
520 static unsigned char sha_buffer[20];
521 switch (P->encr_chat.exchange_state) {
522 case tgl_sce_requested:
523 memcpy (P->encr_chat.exchange_key, key, 256);
524 break;
525 case tgl_sce_accepted:
526 memcpy (P->encr_chat.exchange_key, key, 256);
527
528 TGLC_sha1 ((unsigned char *)P->encr_chat.exchange_key, 256, sha_buffer);
529 P->encr_chat.exchange_key_fingerprint = *(long long *)(sha_buffer + 12);
530 break;
531 case tgl_sce_committed:
532 memcpy (P->encr_chat.exchange_key, P->encr_chat.key, 256);
533 P->encr_chat.exchange_key_fingerprint = P->encr_chat.key_fingerprint;
534
535 memcpy (P->encr_chat.key, key, 256);
536
537 TGLC_sha1 ((unsigned char *)P->encr_chat.key, 256, sha_buffer);
538 P->encr_chat.key_fingerprint = *(long long *)(sha_buffer + 12);
539 break;
540 case tgl_sce_confirmed:
541 P->encr_chat.exchange_state = tgl_sce_none;
542 if (P->encr_chat.exchange_state != tgl_sce_committed) {
543 memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
544 P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint;
545 }
546 break;
547 case tgl_sce_aborted:
548 P->encr_chat.exchange_state = tgl_sce_none;
549 if (P->encr_chat.exchange_state == tgl_sce_committed) {
550 memcpy (P->encr_chat.key, P->encr_chat.exchange_key, 256);
551 P->encr_chat.key_fingerprint = P->encr_chat.exchange_key_fingerprint;
552 }
553 break;
554 default:
555 assert (0);
556 }
557 }
558 /* }}} */
559
bl_do_user(struct tgl_state * TLS,int id,long long * access_hash,const char * first_name,int first_name_len,const char * last_name,int last_name_len,const char * phone,int phone_len,const char * username,int username_len,struct tl_ds_photo * photo,struct tl_ds_user_profile_photo * profile_photo,int * last_read_in,int * last_read_out,struct tl_ds_bot_info * bot_info,int flags)560 void bl_do_user (struct tgl_state *TLS, int id, long long *access_hash, const char *first_name, int first_name_len, const char *last_name, int last_name_len, const char *phone, int phone_len, const char *username, int username_len, struct tl_ds_photo *photo, struct tl_ds_user_profile_photo *profile_photo, int *last_read_in, int *last_read_out, struct tl_ds_bot_info *bot_info, int flags) /* {{{ */ {
561 tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_USER (id));
562
563 unsigned updates = 0;
564
565 if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
566 if (!_U) {
567 _U = talloc0 (sizeof (*_U));
568 _U->id = TGL_MK_USER (id);
569 tglp_insert_user (TLS, _U);
570 } else {
571 assert (!(_U->flags & TGLPF_CREATED));
572 }
573 updates |= TGL_UPDATE_CREATED;
574 } else {
575 assert (_U->flags & TGLPF_CREATED);
576 }
577
578 struct tgl_user *U = (void *)_U;
579 if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; }
580 flags &= TGLUF_TYPE_MASK;
581
582 if ((flags & TGLUF_TYPE_MASK) != (U->flags & TGLUF_TYPE_MASK)) {
583 updates |= TGL_UPDATE_FLAGS;
584 }
585 U->flags = (U->flags & ~TGLUF_TYPE_MASK) | flags;
586
587 if (access_hash && *access_hash != U->access_hash) {
588 U->access_hash = *access_hash;
589 U->id.access_hash = *access_hash;
590 updates |= TGL_UPDATE_ACCESS_HASH;
591 }
592
593 if (first_name || last_name) {
594 if (!U->first_name || !U->last_name || mystreq1 (U->first_name, first_name, first_name_len) || mystreq1 (U->last_name, last_name, last_name_len)) {
595 if (U->first_name) {
596 tfree_str (U->first_name);
597 }
598 U->first_name = tstrndup (first_name, first_name_len);
599 if (U->last_name) {
600 tfree_str (U->last_name);
601 }
602 U->last_name = tstrndup (last_name, last_name_len);
603
604 updates |= TGL_UPDATE_NAME;
605
606 if (U->print_name) {
607 tglp_peer_delete_name (TLS, (void *)U);
608 tfree_str (U->print_name);
609 }
610 U->print_name = TLS->callback.create_print_name (TLS, U->id, U->first_name, U->last_name, 0, 0);
611 tglp_peer_insert_name (TLS, (void *)U);
612 }
613 }
614
615 if (phone && (!U->phone || mystreq1 (U->phone, phone, phone_len))) {
616 if (U->phone) {
617 tfree_str (U->phone);
618 }
619 U->phone = tstrndup (phone, phone_len);
620 updates |= TGL_UPDATE_PHONE;
621 }
622
623 if (username && (!U->username || mystreq1 (U->username, username, username_len))) {
624 if (U->username) {
625 tfree_str (U->username);
626 }
627 U->username = tstrndup (username, username_len);
628 updates |= TGL_UPDATE_USERNAME;
629 }
630
631 if (photo) {
632 if (!U->photo || U->photo->id != DS_LVAL (photo->id)) {
633 if (U->photo) {
634 tgls_free_photo (TLS, U->photo);
635 }
636 U->photo = tglf_fetch_alloc_photo (TLS, photo);
637 U->flags |= TGLUF_HAS_PHOTO;
638 }
639 }
640
641 if (profile_photo) {
642 if (U->photo_id != DS_LVAL (profile_photo->photo_id)) {
643 U->photo_id = DS_LVAL (profile_photo->photo_id);
644 tglf_fetch_file_location (TLS, &U->photo_big, profile_photo->photo_big);
645 tglf_fetch_file_location (TLS, &U->photo_small, profile_photo->photo_small);
646 updates |= TGL_UPDATE_PHOTO;
647 }
648 }
649
650 if (last_read_in) {
651 U->last_read_in = *last_read_in;
652 tgls_messages_mark_read (TLS, U->last, 0, U->last_read_in);
653 }
654 if (last_read_out) {
655 U->last_read_out = *last_read_out;
656 tgls_messages_mark_read (TLS, U->last, TGLMF_OUT, U->last_read_out);
657 }
658
659 if (bot_info) {
660 if (!U->bot_info || U->bot_info->version != DS_LVAL (bot_info->version)) {
661 if (U->bot_info) {
662 tgls_free_bot_info (TLS, U->bot_info);
663 }
664 U->bot_info = tglf_fetch_alloc_bot_info (TLS, bot_info);
665 }
666 }
667
668 if (TLS->callback.user_update && updates) {
669 TLS->callback.user_update (TLS, U, updates);
670 }
671 }
672 /* }}} */
673
bl_do_chat(struct tgl_state * TLS,int id,const char * title,int title_len,int * user_num,int * date,int * version,struct tl_ds_vector * participants,struct tl_ds_chat_photo * chat_photo,struct tl_ds_photo * photo,int * admin,int * last_read_in,int * last_read_out,int flags)674 void bl_do_chat (struct tgl_state *TLS, int id, const char *title, int title_len, int *user_num, int *date, int *version, struct tl_ds_vector *participants, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *admin, int *last_read_in, int *last_read_out, int flags) /* {{{ */ {
675 tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHAT (id));
676
677 unsigned updates = 0;
678
679 if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
680 if (!_U) {
681 _U = talloc0 (sizeof (*_U));
682 _U->id = TGL_MK_CHAT (id);
683 tglp_insert_chat (TLS, _U);
684 } else {
685 assert (!(_U->flags & TGLPF_CREATED));
686 }
687 updates |= TGL_UPDATE_CREATED;
688 } else {
689 assert (_U->flags & TGLPF_CREATED);
690 }
691
692 struct tgl_chat *C = &_U->chat;
693 if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; }
694 flags &= TGLCF_TYPE_MASK;
695
696 if ((flags & TGLCF_TYPE_MASK) != (C->flags & TGLCF_TYPE_MASK)) {
697 updates |= TGL_UPDATE_FLAGS;
698 }
699 C->flags = (C->flags & ~TGLCF_TYPE_MASK) | flags;
700
701 if (title && (!C->title || mystreq1 (C->title, title, title_len))) {
702 if (C->title) {
703 tfree_str (C->title);
704 }
705 C->title = tstrndup (title, title_len);
706
707 if (C->print_title) {
708 tglp_peer_delete_name (TLS, (void *)C);
709 tfree_str (C->print_title);
710 }
711 C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0);
712 tglp_peer_insert_name (TLS, (void *)C);
713
714 updates |= TGL_UPDATE_TITLE;
715 }
716
717 if (user_num) {
718 C->users_num = *user_num;
719 }
720
721 if (date) {
722 C->date = *date;
723 }
724
725 if (chat_photo && chat_photo->photo_big) {
726 if (DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) {
727 tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big);
728 tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small);
729 updates |= TGL_UPDATE_PHOTO;
730 }
731 }
732
733 if (photo) {
734 if (!C->photo || C->photo->id != DS_LVAL (photo->id)) {
735 if (C->photo) {
736 tgls_free_photo (TLS, C->photo);
737 }
738 C->photo = tglf_fetch_alloc_photo (TLS, photo);
739 C->flags |= TGLPF_HAS_PHOTO;
740 //updates |= TGL_UPDATE_PHOTO;
741 }
742 }
743
744 if (admin && *admin != C->admin_id) {
745 C->admin_id = *admin;
746 updates |= TGL_UPDATE_ADMIN;
747 }
748
749 if (version) {
750 assert (participants);
751 if (*version > C->version) {
752 C->version = *version;
753
754 if (C->user_list) { tfree (C->user_list, 12 * C->user_list_size); }
755
756 C->user_list_size = DS_LVAL (participants->f1);
757 C->user_list = talloc (12 * C->user_list_size);
758
759 int i;
760 for (i = 0; i < C->user_list_size; i++) {
761 struct tl_ds_chat_participant *DS_P = participants->f2[i];
762 C->user_list[i].user_id = DS_LVAL (DS_P->user_id);
763 C->user_list[i].inviter_id = DS_LVAL (DS_P->inviter_id);
764 C->user_list[i].date = DS_LVAL (DS_P->date);
765 }
766
767 updates |= TGL_UPDATE_MEMBERS;
768 }
769 }
770
771 if (last_read_in) {
772 C->last_read_in = *last_read_in;
773 tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in);
774 }
775
776 if (last_read_out) {
777 C->last_read_out = *last_read_out;
778 tgls_messages_mark_read (TLS, C->last, TGLMF_OUT, C->last_read_out);
779 }
780
781
782 if (TLS->callback.chat_update && updates) {
783 TLS->callback.chat_update (TLS, C, updates);
784 }
785 }
786 /* }}} */
787
bl_do_encr_chat(struct tgl_state * TLS,int id,long long * access_hash,int * date,int * admin,int * user_id,void * key,void * g_key,void * first_key_id,int * state,int * ttl,int * layer,int * in_seq_no,int * last_in_seq_no,int * out_seq_no,long long * key_fingerprint,int flags,const char * print_name,int print_name_len)788 void bl_do_encr_chat (struct tgl_state *TLS, int id, long long *access_hash, int *date, int *admin, int *user_id, void *key, void *g_key, void *first_key_id, int *state, int *ttl, int *layer, int *in_seq_no, int *last_in_seq_no, int *out_seq_no, long long *key_fingerprint, int flags, const char *print_name, int print_name_len) /* {{{ */ {
789 tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (id));
790
791 unsigned updates = 0;
792
793 if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
794 if (!_U) {
795 _U = talloc0 (sizeof (*_U));
796 _U->id = TGL_MK_ENCR_CHAT (id);
797 tglp_insert_encrypted_chat (TLS, _U);
798 } else {
799 assert (!(_U->flags & TGLPF_CREATED));
800 }
801 updates |= TGL_UPDATE_CREATED;
802 } else {
803 assert (_U->flags & TGLPF_CREATED);
804 }
805
806 struct tgl_secret_chat *U = (void *)_U;
807 if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; }
808 flags &= TGLECF_TYPE_MASK;
809
810 if ((flags & TGLECF_TYPE_MASK) != (U->flags & TGLECF_TYPE_MASK)) {
811 updates |= TGL_UPDATE_FLAGS;
812 }
813 U->flags = (U->flags & ~TGLECF_TYPE_MASK) | flags;
814
815 if (access_hash && *access_hash != U->access_hash) {
816 U->access_hash = *access_hash;
817 U->id.access_hash = *access_hash;
818 updates |= TGL_UPDATE_ACCESS_HASH;
819 }
820
821 if (date) {
822 U->date = *date;
823 }
824
825 if (admin) {
826 U->admin_id = *admin;
827 }
828
829 if (user_id) {
830 U->user_id = *user_id;
831 }
832
833 if (key_fingerprint) {
834 U->key_fingerprint = *key_fingerprint;
835 }
836
837 if (in_seq_no) {
838 U->in_seq_no = *in_seq_no;
839 }
840 if (out_seq_no) {
841 U->out_seq_no = *out_seq_no;
842 }
843 if (last_in_seq_no) {
844 U->last_in_seq_no = *last_in_seq_no;
845 }
846
847 tgl_peer_t *Us = tgl_peer_get (TLS, TGL_MK_USER (U->user_id));
848
849 if (!U->print_name) {
850 if (print_name) {
851 U->print_name = tstrndup (print_name, print_name_len);
852 } else {
853 if (Us) {
854 U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", Us->user.first_name, Us->user.last_name, 0);
855 } else {
856 static char buf[100];
857 tsnprintf (buf, 99, "user#%d", U->user_id);
858 U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", buf, 0, 0);
859 }
860 tglp_peer_insert_name (TLS, (void *)U);
861 }
862 }
863
864 if (g_key) {
865 if (!U->g_key) {
866 U->g_key = talloc (256);
867 }
868 memcpy (U->g_key, g_key, 256);
869 }
870
871 if (key) {
872 memcpy (U->key, key, 256);
873 }
874
875 if (first_key_id) {
876 memcpy (U->first_key_sha, first_key_id, 20);
877 }
878
879 if (state) {
880 if (U->state == sc_waiting && *state == sc_ok) {
881 tgl_do_create_keys_end (TLS, U);
882 }
883 if ((int)U->state != *state) {
884 switch (*state) {
885 case sc_request:
886 updates |= TGL_UPDATE_REQUESTED;
887 break;
888 case sc_ok:
889 updates |= TGL_UPDATE_WORKING;
890 vlogprintf (E_WARNING, "Secret chat in ok state\n");
891 break;
892 default:
893 break;
894 }
895 }
896 U->state = *state;
897 }
898
899 if (TLS->callback.secret_chat_update && updates) {
900 TLS->callback.secret_chat_update (TLS, U, updates);
901 }
902 }
903 /* }}} */
904
bl_do_channel(struct tgl_state * TLS,int id,long long * access_hash,int * date,const char * title,int title_len,const char * username,int username_len,struct tl_ds_chat_photo * chat_photo,struct tl_ds_photo * photo,int * version,char * about,int about_len,int * participants_count,int * admins_count,int * kicked_count,int * last_read_in,int flags)905 void bl_do_channel (struct tgl_state *TLS, int id, long long *access_hash, int *date, const char *title, int title_len, const char *username, int username_len, struct tl_ds_chat_photo *chat_photo, struct tl_ds_photo *photo, int *version, char *about, int about_len, int *participants_count, int *admins_count, int *kicked_count, int *last_read_in, int flags) /* {{{ */ {
906 tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_CHANNEL (id));
907
908 unsigned updates = 0;
909
910 if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) {
911 if (!_U) {
912 _U = talloc0 (sizeof (*_U));
913 _U->id = TGL_MK_CHANNEL (id);
914 tglp_insert_channel (TLS, _U);
915 } else {
916 assert (!(_U->flags & TGLPF_CREATED));
917 }
918 updates |= TGL_UPDATE_CREATED;
919 } else {
920 assert (_U->flags & TGLPF_CREATED);
921 }
922
923 struct tgl_channel *C = &_U->channel;
924 if (flags == TGL_FLAGS_UNCHANGED) { flags = C->flags; }
925 flags &= TGLCHF_TYPE_MASK;
926
927 if ((flags & TGLCHF_TYPE_MASK) != (C->flags & TGLCHF_TYPE_MASK)) {
928 updates |= TGL_UPDATE_FLAGS;
929 }
930 C->flags = (C->flags & ~TGLCHF_TYPE_MASK) | flags;
931
932 if (access_hash && *access_hash != C->access_hash) {
933 C->access_hash = *access_hash;
934 C->id.access_hash = *access_hash;
935 updates |= TGL_UPDATE_ACCESS_HASH;
936 }
937
938 if (date) {
939 C->date = *date;
940 }
941
942 if (title && (!C->title || mystreq1 (C->title, title, title_len))) {
943 if (C->title) {
944 tfree_str (C->title);
945 }
946 C->title = tstrndup (title, title_len);
947
948 if (C->print_title) {
949 tglp_peer_delete_name (TLS, (void *)C);
950 tfree_str (C->print_title);
951 }
952 C->print_title = TLS->callback.create_print_name (TLS, C->id, C->title, 0, 0, 0);
953 tglp_peer_insert_name (TLS, (void *)C);
954
955 updates |= TGL_UPDATE_TITLE;
956 }
957
958 if (chat_photo) {
959 if (chat_photo->photo_big && DS_LVAL (chat_photo->photo_big->secret) != C->photo_big.secret) {
960 tglf_fetch_file_location (TLS, &C->photo_big, chat_photo->photo_big);
961 tglf_fetch_file_location (TLS, &C->photo_small, chat_photo->photo_small);
962 updates |= TGL_UPDATE_PHOTO;
963 }
964 }
965
966 if (photo) {
967 if (!C->photo || C->photo->id != DS_LVAL (photo->id)) {
968 if (C->photo) {
969 tgls_free_photo (TLS, C->photo);
970 }
971 C->photo = tglf_fetch_alloc_photo (TLS, photo);
972 C->flags |= TGLPF_HAS_PHOTO;
973 }
974 }
975
976 if (username) {
977 if (!C->username || mystreq1 (C->username, username, username_len)) {
978 if (C->username) {
979 tfree_str (C->username);
980 }
981 C->username = tstrndup (username, username_len);
982 updates |= TGL_UPDATE_USERNAME;
983 }
984 }
985
986 if (about) {
987 if (!C->about || mystreq1 (C->about, about, about_len)) {
988 tfree_str (C->about);
989 }
990 C->about = tstrndup (about, about_len);
991 }
992
993 if (admins_count) {
994 C->admins_count = *admins_count;
995 }
996
997 if (participants_count) {
998 C->participants_count = *participants_count;
999 }
1000
1001 if (kicked_count) {
1002 C->kicked_count = *kicked_count;
1003 }
1004
1005 if (last_read_in) {
1006 C->last_read_in = *last_read_in;
1007 tgls_messages_mark_read (TLS, C->last, 0, C->last_read_in);
1008 }
1009
1010 if (TLS->callback.channel_update && updates) {
1011 TLS->callback.channel_update (TLS, C, updates);
1012 }
1013 }
1014 /* }}} */
1015
bl_do_peer_delete(struct tgl_state * TLS,tgl_peer_id_t id)1016 void bl_do_peer_delete (struct tgl_state *TLS, tgl_peer_id_t id) /* {{{ */ {
1017 tgl_peer_t *P = tgl_peer_get (TLS, id);
1018 if (!P || !(P->flags & TGLPF_CREATED)) { return; }
1019
1020 if (P->flags & TGLPF_DELETED) { return; }
1021 P->flags |= TGLPF_DELETED;
1022
1023 switch (id.peer_type) {
1024 case TGL_PEER_USER:
1025 if (TLS->callback.user_update) {
1026 TLS->callback.user_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1027 }
1028 break;
1029 case TGL_PEER_CHAT:
1030 if (TLS->callback.chat_update) {
1031 TLS->callback.chat_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1032 }
1033 break;
1034 case TGL_PEER_ENCR_CHAT:
1035 if (TLS->callback.secret_chat_update) {
1036 TLS->callback.secret_chat_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1037 }
1038 break;
1039 case TGL_PEER_CHANNEL:
1040 if (TLS->callback.channel_update) {
1041 TLS->callback.channel_update (TLS, (void *)P, TGL_UPDATE_DELETED);
1042 }
1043 break;
1044 default:
1045 assert (0);
1046 }
1047 }
1048 /* }}} */
1049