tg/structures.c

1901 lines
53 KiB
C
Raw Normal View History

/*
This file is part of tgl-library
2013-10-23 10:26:17 -04:00
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
2013-10-23 10:26:17 -04:00
This library is distributed in the hope that it will be useful,
2013-10-23 10:26:17 -04:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
2013-10-23 10:26:17 -04:00
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2013-10-23 10:26:17 -04:00
Copyright Vitaly Valtman 2013-2014
2013-10-23 10:26:17 -04:00
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
2013-10-11 16:52:20 -04:00
#include <assert.h>
#include <string.h>
2013-10-11 16:52:20 -04:00
#include "structures.h"
#include "mtproto-common.h"
//#include "telegram.h"
#include "tree.h"
2013-10-18 15:30:24 -04:00
#include "loop.h"
#include <openssl/aes.h>
#include <openssl/sha.h>
2013-11-05 17:24:26 -05:00
#include "queries.h"
#include "binlog.h"
2014-08-14 14:03:33 -04:00
#include "updates.h"
#include "mtproto-client.h"
2014-08-13 08:56:55 -04:00
#include "tgl.h"
#define sha1 SHA1
#ifndef TGL_MAX_PEER_NUM
# define TGL_MAX_PEER_NUM 100000
#endif
2014-08-13 08:56:55 -04:00
2014-08-13 11:55:16 -04:00
static int id_cmp (struct tgl_message *M1, struct tgl_message *M2);
#define peer_cmp(a,b) (tgl_cmp_peer_id (a->id, b->id))
2014-01-31 11:03:40 -05:00
#define peer_cmp_name(a,b) (strcmp (a->print_name, b->print_name))
2014-08-13 11:55:16 -04:00
DEFINE_TREE(peer,tgl_peer_t *,peer_cmp,0)
DEFINE_TREE(peer_by_name,tgl_peer_t *,peer_cmp_name,0)
DEFINE_TREE(message,struct tgl_message *,id_cmp,0)
2013-11-25 11:13:36 -05:00
2014-08-13 11:55:16 -04:00
static struct tgl_message message_list = {
2013-11-25 11:13:36 -05:00
.next_use = &message_list,
.prev_use = &message_list
};
2014-08-13 11:55:16 -04:00
static struct tree_peer *tgl_peer_tree;
2014-08-13 08:56:55 -04:00
static struct tree_peer_by_name *peer_by_name_tree;
static struct tree_message *message_tree;
static struct tree_message *message_unsent_tree;
2013-11-25 11:13:36 -05:00
2014-08-13 08:56:55 -04:00
static int users_allocated;
static int chats_allocated;
static int messages_allocated;
static int peer_num;
static int encr_chats_allocated;
static int geo_chats_allocated;
2013-12-02 12:19:08 -05:00
2014-08-13 11:55:16 -04:00
static tgl_peer_t *Peers[TGL_MAX_PEER_NUM];
2013-12-02 12:19:08 -05:00
2013-11-25 11:13:36 -05:00
2014-08-20 18:33:19 -04:00
char *tgls_default_create_print_name (tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4) {
2014-08-12 11:15:04 -04:00
const char *d[4];
d[0] = a1; d[1] = a2; d[2] = a3; d[3] = a4;
static char buf[10000];
buf[0] = 0;
int i;
int p = 0;
for (i = 0; i < 4; i++) {
if (d[i] && strlen (d[i])) {
p += tsnprintf (buf + p, 9999 - p, "%s%s", p ? "_" : "", d[i]);
assert (p < 9990);
}
}
char *s = buf;
while (*s) {
2014-09-17 17:03:20 -04:00
if (((unsigned char)*s) <= ' ') { *s = '_'; }
if (*s == '#') { *s = '@'; }
2014-08-12 11:15:04 -04:00
s++;
}
s = buf;
int fl = strlen (s);
int cc = 0;
while (1) {
2014-08-13 11:55:16 -04:00
tgl_peer_t *P = tgl_peer_get_by_name (s);
if (!P || !tgl_cmp_peer_id (P->id, id)) {
2014-08-12 11:15:04 -04:00
break;
}
cc ++;
assert (cc <= 9999);
tsnprintf (s + fl, 9999 - fl, "#%d", cc);
}
return tstrdup (s);
}
2013-12-02 12:19:08 -05:00
2014-08-13 11:55:16 -04:00
/* {{{ Fetch */
2013-11-21 14:35:49 -05:00
2014-08-13 11:55:16 -04:00
int tglf_fetch_file_location (struct tgl_file_location *loc) {
2013-11-21 14:35:49 -05:00
int x = fetch_int ();
2014-08-12 11:15:04 -04:00
assert (x == CODE_file_location_unavailable || x == CODE_file_location);
2013-11-21 14:35:49 -05:00
if (x == CODE_file_location_unavailable) {
loc->dc = -1;
loc->volume = fetch_long ();
loc->local_id = fetch_int ();
loc->secret = fetch_long ();
} else {
loc->dc = fetch_int ();
loc->volume = fetch_long ();
loc->local_id = fetch_int ();
loc->secret = fetch_long ();
}
2013-11-21 14:35:49 -05:00
return 0;
}
2014-08-13 11:55:16 -04:00
int tglf_fetch_user_status (struct tgl_user_status *S) {
2013-11-21 14:35:49 -05:00
unsigned x = fetch_int ();
2014-08-12 11:15:04 -04:00
assert (x == CODE_user_status_empty || x == CODE_user_status_online || x == CODE_user_status_offline);
2013-10-11 16:52:20 -04:00
switch (x) {
case CODE_user_status_empty:
S->online = 0;
2013-11-21 14:35:49 -05:00
S->when = 0;
2013-10-11 16:52:20 -04:00
break;
case CODE_user_status_online:
S->online = 1;
S->when = fetch_int ();
break;
case CODE_user_status_offline:
S->online = -1;
S->when = fetch_int ();
break;
default:
assert (0);
}
2013-11-21 14:35:49 -05:00
return 0;
2013-10-11 16:52:20 -04:00
}
2014-08-13 11:55:16 -04:00
long long tglf_fetch_user_photo (struct tgl_user *U) {
2013-11-21 14:35:49 -05:00
unsigned x = fetch_int ();
2014-08-12 11:15:04 -04:00
assert (x == CODE_user_profile_photo || x == CODE_user_profile_photo_old || x == CODE_user_profile_photo_empty);
2013-11-21 14:35:49 -05:00
if (x == CODE_user_profile_photo_empty) {
bl_do_set_user_profile_photo (U, 0, 0, 0);
return 0;
}
long long photo_id = 1;
if (x == CODE_user_profile_photo) {
photo_id = fetch_long ();
}
2014-08-13 11:55:16 -04:00
static struct tgl_file_location big;
static struct tgl_file_location small;
2014-08-13 08:56:55 -04:00
assert (tglf_fetch_file_location (&small) >= 0);
assert (tglf_fetch_file_location (&big) >= 0);
2013-11-21 14:35:49 -05:00
bl_do_set_user_profile_photo (U, photo_id, &big, &small);
return 0;
}
2014-08-13 11:55:16 -04:00
int tglf_fetch_user (struct tgl_user *U) {
2013-11-04 12:34:27 -05:00
unsigned x = fetch_int ();
2014-08-12 11:15:04 -04:00
assert (x == CODE_user_empty || x == CODE_user_self || x == CODE_user_contact || x == CODE_user_request || x == CODE_user_foreign || x == CODE_user_deleted);
2014-08-13 11:55:16 -04:00
U->id = TGL_MK_USER (fetch_int ());
2013-11-04 12:34:27 -05:00
if (x == CODE_user_empty) {
return 0;
2013-11-04 12:34:27 -05:00
}
2013-11-21 14:35:49 -05:00
2013-11-04 12:34:27 -05:00
if (x == CODE_user_self) {
2014-08-13 11:55:16 -04:00
bl_do_set_our_id (tgl_get_peer_id (U->id));
2013-11-04 12:34:27 -05:00
}
2013-11-21 14:35:49 -05:00
2014-08-12 11:15:04 -04:00
int new = !(U->flags & FLAG_CREATED);
2013-11-21 14:35:49 -05:00
if (new) {
int l1 = prefetch_strlen ();
2014-08-12 11:15:04 -04:00
assert (l1 >= 0);
2013-11-21 14:35:49 -05:00
char *s1 = fetch_str (l1);
int l2 = prefetch_strlen ();
2014-08-12 11:15:04 -04:00
assert (l2 >= 0);
2013-11-21 14:35:49 -05:00
char *s2 = fetch_str (l2);
if (x == CODE_user_deleted && !(U->flags & FLAG_DELETED)) {
2014-08-13 11:55:16 -04:00
bl_do_user_add (tgl_get_peer_id (U->id), s1, l1, s2, l2, 0, 0, 0, 0);
2013-11-21 14:35:49 -05:00
bl_do_user_delete (U);
}
2013-11-21 14:35:49 -05:00
if (x != CODE_user_deleted) {
2014-08-13 08:56:55 -04:00
long long access_hash = 0;
2013-11-21 14:35:49 -05:00
if (x != CODE_user_self) {
2014-08-13 08:56:55 -04:00
access_hash = fetch_long ();
2013-11-21 14:35:49 -05:00
}
int phone_len = 0;
char *phone = 0;
if (x != CODE_user_foreign) {
phone_len = prefetch_strlen ();
2014-08-12 11:15:04 -04:00
assert (phone_len >= 0);
2013-11-21 14:35:49 -05:00
phone = fetch_str (phone_len);
}
2014-08-13 11:55:16 -04:00
bl_do_user_add (tgl_get_peer_id (U->id), s1, l1, s2, l2, access_hash, phone, phone_len, x == CODE_user_contact);
2014-08-13 08:56:55 -04:00
assert (tglf_fetch_user_photo (U) >= 0);
assert (tglf_fetch_user_status (&U->status) >= 0);
2013-11-21 14:35:49 -05:00
if (x == CODE_user_self) {
fetch_bool ();
2013-11-16 08:04:53 -05:00
}
}
2013-11-21 14:35:49 -05:00
} else {
int l1 = prefetch_strlen ();
char *s1 = fetch_str (l1);
int l2 = prefetch_strlen ();
char *s2 = fetch_str (l2);
2014-08-12 17:32:11 -04:00
bl_do_user_set_name (U, s1, l1, s2, l2);
2013-11-21 14:35:49 -05:00
if (x == CODE_user_deleted && !(U->flags & FLAG_DELETED)) {
bl_do_user_delete (U);
}
2013-11-21 14:35:49 -05:00
if (x != CODE_user_deleted) {
if (x != CODE_user_self) {
2014-08-12 17:32:11 -04:00
bl_do_user_set_access_hash (U, fetch_long ());
2013-11-21 14:35:49 -05:00
}
if (x != CODE_user_foreign) {
int l = prefetch_strlen ();
char *s = fetch_str (l);
2014-08-12 17:32:11 -04:00
bl_do_user_set_phone (U, s, l);
2013-11-21 14:35:49 -05:00
}
2014-08-13 08:56:55 -04:00
assert (tglf_fetch_user_photo (U) >= 0);
2013-11-21 14:35:49 -05:00
2014-08-13 08:56:55 -04:00
tglf_fetch_user_status (&U->status);
2013-11-21 14:35:49 -05:00
if (x == CODE_user_self) {
fetch_bool ();
}
if (x == CODE_user_contact) {
2014-08-12 17:32:11 -04:00
bl_do_user_set_friend (U, 1);
2014-08-19 08:57:55 -04:00
} else {
2014-08-12 17:32:11 -04:00
bl_do_user_set_friend (U, 0);
2013-11-21 14:35:49 -05:00
}
2013-10-25 15:50:10 -04:00
}
2013-10-11 16:52:20 -04:00
}
2013-11-21 14:35:49 -05:00
return 0;
2013-10-11 16:52:20 -04:00
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_user_full (struct tgl_user *U) {
2014-08-13 08:56:55 -04:00
assert (fetch_int () == CODE_user_full);
tglf_fetch_alloc_user ();
assert (skip_type_any (TYPE_TO_PARAM (contacts_link)) >= 0);
int *start = in_ptr;
assert (skip_type_any (TYPE_TO_PARAM (photo)) >= 0);
bl_do_user_set_full_photo (U, start, 4 * (in_ptr - start));
assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0);
bl_do_user_set_blocked (U, fetch_bool ());
int l1 = prefetch_strlen ();
char *s1 = fetch_str (l1);
int l2 = prefetch_strlen ();
char *s2 = fetch_str (l2);
if (U && (U->flags & FLAG_CREATED)) {
bl_do_user_set_real_name (U, s1, l1, s2, l2);
}
2014-08-13 08:56:55 -04:00
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_encrypted_chat (struct tgl_secret_chat *U) {
unsigned x = fetch_int ();
assert (x == CODE_encrypted_chat_empty || x == CODE_encrypted_chat_waiting || x == CODE_encrypted_chat_requested || x == CODE_encrypted_chat || x == CODE_encrypted_chat_discarded);
2014-08-13 11:55:16 -04:00
U->id = TGL_MK_ENCR_CHAT (fetch_int ());
if (x == CODE_encrypted_chat_empty) {
return;
}
2013-11-21 14:35:49 -05:00
int new = !(U->flags & FLAG_CREATED);
if (x == CODE_encrypted_chat_discarded) {
2013-11-21 14:35:49 -05:00
if (new) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Unknown chat in deleted state. May be we forgot something...\n");
2013-11-21 14:35:49 -05:00
return;
2013-11-04 12:34:27 -05:00
}
2013-11-21 14:35:49 -05:00
bl_do_encr_chat_delete (U);
2014-08-14 18:16:01 -04:00
//write_secret_chat_file ();
return;
}
2013-11-04 12:34:27 -05:00
2013-11-21 14:35:49 -05:00
static char g_key[256];
static char nonce[256];
if (new) {
long long access_hash = fetch_long ();
int date = fetch_int ();
int admin_id = fetch_int ();
2014-08-13 08:56:55 -04:00
int user_id = fetch_int () + admin_id - tgl_state.our_id;
2013-11-21 14:35:49 -05:00
if (x == CODE_encrypted_chat_waiting) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Unknown chat in waiting state. May be we forgot something...\n");
2013-11-21 14:35:49 -05:00
return;
}
2013-11-21 14:35:49 -05:00
if (x == CODE_encrypted_chat_requested || x == CODE_encrypted_chat) {
memset (g_key, 0, sizeof (g_key));
}
2014-08-12 11:15:04 -04:00
fetch256 (g_key);
2013-11-21 14:35:49 -05:00
if (x == CODE_encrypted_chat) {
fetch_long (); // fingerprint
}
if (x == CODE_encrypted_chat) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Unknown chat in ok state. May be we forgot something...\n");
2013-11-21 14:35:49 -05:00
return;
}
2013-11-21 14:35:49 -05:00
bl_do_encr_chat_requested (U, access_hash, date, admin_id, user_id, (void *)g_key, (void *)nonce);
2014-08-14 18:16:01 -04:00
//write_secret_chat_file ();
} else {
2014-08-12 17:51:16 -04:00
bl_do_encr_chat_set_access_hash (U, fetch_long ());
bl_do_encr_chat_set_date (U, fetch_int ());
2013-11-21 14:35:49 -05:00
if (fetch_int () != U->admin_id) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Changed admin in secret chat. WTF?\n");
2013-11-21 14:35:49 -05:00
return;
}
2014-08-13 08:56:55 -04:00
if (U->user_id != U->admin_id + fetch_int () - tgl_state.our_id) {
vlogprintf (E_WARNING, "Changed partner in secret chat. WTF?\n");
2013-11-21 14:35:49 -05:00
return;
}
2013-11-21 14:35:49 -05:00
if (x == CODE_encrypted_chat_waiting) {
2014-08-12 17:51:16 -04:00
bl_do_encr_chat_set_state (U, sc_waiting);
2014-08-14 18:16:01 -04:00
//write_secret_chat_file ();
2013-11-21 14:35:49 -05:00
return; // We needed only access hash from here
}
if (x == CODE_encrypted_chat_requested || x == CODE_encrypted_chat) {
memset (g_key, 0, sizeof (g_key));
2013-11-04 12:34:27 -05:00
}
2013-11-21 14:35:49 -05:00
2014-08-12 11:15:04 -04:00
fetch256 (g_key);
2013-11-21 14:35:49 -05:00
if (x == CODE_encrypted_chat_requested) {
return; // Duplicate?
2013-11-05 17:24:26 -05:00
}
2013-11-21 14:35:49 -05:00
bl_do_encr_chat_accepted (U, (void *)g_key, (void *)nonce, fetch_long ());
2014-08-14 18:16:01 -04:00
//write_secret_chat_file ();
}
2013-10-25 13:29:02 -04:00
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_chat (struct tgl_chat *C) {
unsigned x = fetch_int ();
assert (x == CODE_chat_empty || x == CODE_chat || x == CODE_chat_forbidden);
2014-08-13 11:55:16 -04:00
C->id = TGL_MK_CHAT (fetch_int ());
if (x == CODE_chat_empty) {
return;
}
2013-11-22 18:26:35 -05:00
int new = !(C->flags & FLAG_CREATED);
if (new) {
int y = 0;
if (x == CODE_chat_forbidden) {
y |= FLAG_FORBIDDEN;
}
2013-11-22 18:26:35 -05:00
int l = prefetch_strlen ();
char *s = fetch_str (l);
2014-08-13 11:55:16 -04:00
struct tgl_file_location small;
struct tgl_file_location big;
2013-11-22 18:26:35 -05:00
memset (&small, 0, sizeof (small));
memset (&big, 0, sizeof (big));
int users_num = -1;
int date = 0;
int version = -1;
if (x == CODE_chat) {
unsigned z = fetch_int ();
if (z == CODE_chat_photo_empty) {
2013-11-22 18:26:35 -05:00
small.dc = -2;
big.dc = -2;
} else {
assert (z == CODE_chat_photo);
2014-08-13 08:56:55 -04:00
tglf_fetch_file_location (&small);
tglf_fetch_file_location (&big);
2013-11-22 18:26:35 -05:00
}
users_num = fetch_int ();
date = fetch_int ();
if (fetch_bool ()) {
y |= FLAG_CHAT_IN_CHAT;
}
version = fetch_int ();
} else {
small.dc = -2;
big.dc = -2;
users_num = -1;
date = fetch_int ();
version = -1;
}
2013-11-22 18:26:35 -05:00
bl_do_create_chat (C, y, s, l, users_num, date, version, &big, &small);
} else {
2013-11-22 18:26:35 -05:00
if (x == CODE_chat_forbidden) {
bl_do_chat_forbid (C, 1);
} else {
bl_do_chat_forbid (C, 0);
}
int l = prefetch_strlen ();
char *s = fetch_str (l);
2014-08-12 17:51:16 -04:00
bl_do_chat_set_title (C, s, l);
2013-11-22 18:26:35 -05:00
2014-08-13 11:55:16 -04:00
struct tgl_file_location small;
struct tgl_file_location big;
2013-11-22 18:26:35 -05:00
memset (&small, 0, sizeof (small));
memset (&big, 0, sizeof (big));
if (x == CODE_chat) {
unsigned y = fetch_int ();
if (y == CODE_chat_photo_empty) {
small.dc = -2;
big.dc = -2;
} else {
assert (y == CODE_chat_photo);
2014-08-13 08:56:55 -04:00
tglf_fetch_file_location (&small);
tglf_fetch_file_location (&big);
2013-11-22 18:26:35 -05:00
}
2014-08-12 17:51:16 -04:00
bl_do_chat_set_photo (C, &big, &small);
2013-11-22 18:26:35 -05:00
int users_num = fetch_int ();
2014-08-12 17:51:16 -04:00
bl_do_chat_set_date (C, fetch_int ());
bl_do_chat_set_set_in_chat (C, fetch_bool ());
bl_do_chat_set_version (C, users_num, fetch_int ());
2013-11-22 18:26:35 -05:00
} else {
2014-08-12 17:51:16 -04:00
bl_do_chat_set_date (C, fetch_int ());
2013-11-22 18:26:35 -05:00
}
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_chat_full (struct tgl_chat *C) {
2013-10-24 13:04:44 -04:00
unsigned x = fetch_int ();
assert (x == CODE_messages_chat_full);
assert (fetch_int () == CODE_chat_full);
2014-08-13 11:55:16 -04:00
C->id = TGL_MK_CHAT (fetch_int ());
2013-10-24 13:04:44 -04:00
x = fetch_int ();
2013-11-25 11:13:36 -05:00
int version = 0;
2014-08-13 11:55:16 -04:00
struct tgl_chat_user *users = 0;
2013-11-25 11:13:36 -05:00
int users_num = 0;
int admin_id = 0;
2013-10-24 13:04:44 -04:00
if (x == CODE_chat_participants) {
2014-08-13 11:55:16 -04:00
assert (fetch_int () == tgl_get_peer_id (C->id));
2013-11-25 11:13:36 -05:00
admin_id = fetch_int ();
2013-10-24 13:04:44 -04:00
assert (fetch_int () == CODE_vector);
2013-11-25 11:13:36 -05:00
users_num = fetch_int ();
2014-08-13 11:55:16 -04:00
users = talloc (sizeof (struct tgl_chat_user) * users_num);
2013-10-24 13:04:44 -04:00
int i;
2013-11-25 12:16:34 -05:00
for (i = 0; i < users_num; i++) {
2013-10-24 13:04:44 -04:00
assert (fetch_int () == (int)CODE_chat_participant);
2013-11-25 11:13:36 -05:00
users[i].user_id = fetch_int ();
users[i].inviter_id = fetch_int ();
users[i].date = fetch_int ();
2013-10-24 13:04:44 -04:00
}
2013-11-25 11:13:36 -05:00
version = fetch_int ();
} else {
fetch_int ();
2013-10-24 13:04:44 -04:00
}
2013-11-25 11:13:36 -05:00
int *start = in_ptr;
2014-08-12 17:32:11 -04:00
assert (skip_type_any (TYPE_TO_PARAM (photo)) >= 0);
2013-11-25 11:13:36 -05:00
int *end = in_ptr;
2014-08-12 17:32:11 -04:00
assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0);
2013-10-24 13:04:44 -04:00
int n, i;
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
2014-08-13 08:56:55 -04:00
tglf_fetch_alloc_chat ();
2013-10-24 13:04:44 -04:00
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
2014-08-13 08:56:55 -04:00
tglf_fetch_alloc_user ();
2013-10-24 13:04:44 -04:00
}
2013-11-25 11:13:36 -05:00
if (admin_id) {
2014-08-12 17:51:16 -04:00
bl_do_chat_set_admin (C, admin_id);
2013-11-25 11:13:36 -05:00
}
if (version > 0) {
2014-08-12 17:51:16 -04:00
bl_do_chat_set_participants (C, version, users_num, users);
2014-08-13 11:55:16 -04:00
tfree (users, sizeof (struct tgl_chat_user) * users_num);
2013-11-25 11:13:36 -05:00
}
2014-08-12 17:51:16 -04:00
bl_do_chat_set_full_photo (C, start, 4 * (end - start));
2013-10-24 13:04:44 -04:00
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_photo_size (struct tgl_photo_size *S) {
memset (S, 0, sizeof (*S));
unsigned x = fetch_int ();
assert (x == CODE_photo_size || x == CODE_photo_cached_size || x == CODE_photo_size_empty);
S->type = fetch_str_dup ();
if (x != CODE_photo_size_empty) {
2014-08-13 08:56:55 -04:00
tglf_fetch_file_location (&S->loc);
S->w = fetch_int ();
S->h = fetch_int ();
if (x == CODE_photo_size) {
S->size = fetch_int ();
} else {
S->size = prefetch_strlen ();
2013-11-11 13:35:31 -05:00
fetch_str (S->size);
}
}
}
2014-08-14 14:03:33 -04:00
void tglf_fetch_geo (struct tgl_geo *G) {
unsigned x = fetch_int ();
if (x == CODE_geo_point) {
G->longitude = fetch_double ();
G->latitude = fetch_double ();
} else {
assert (x == CODE_geo_point_empty);
G->longitude = 0;
G->latitude = 0;
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_photo (struct tgl_photo *P) {
memset (P, 0, sizeof (*P));
unsigned x = fetch_int ();
2013-10-24 13:04:44 -04:00
assert (x == CODE_photo_empty || x == CODE_photo);
P->id = fetch_long ();
if (x == CODE_photo_empty) { return; }
P->access_hash = fetch_long ();
P->user_id = fetch_int ();
P->date = fetch_int ();
P->caption = fetch_str_dup ();
2014-08-14 14:03:33 -04:00
tglf_fetch_geo (&P->geo);
assert (fetch_int () == CODE_vector);
P->sizes_num = fetch_int ();
2014-08-13 11:55:16 -04:00
P->sizes = talloc (sizeof (struct tgl_photo_size) * P->sizes_num);
int i;
for (i = 0; i < P->sizes_num; i++) {
2014-08-13 08:56:55 -04:00
tglf_fetch_photo_size (&P->sizes[i]);
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_video (struct tgl_video *V) {
memset (V, 0, sizeof (*V));
unsigned x = fetch_int ();
V->id = fetch_long ();
if (x == CODE_video_empty) { return; }
V->access_hash = fetch_long ();
V->user_id = fetch_int ();
V->date = fetch_int ();
V->caption = fetch_str_dup ();
V->duration = fetch_int ();
2014-08-12 21:22:15 -04:00
V->mime_type = fetch_str_dup ();
V->size = fetch_int ();
2014-08-13 08:56:55 -04:00
tglf_fetch_photo_size (&V->thumb);
V->dc_id = fetch_int ();
V->w = fetch_int ();
V->h = fetch_int ();
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_audio (struct tgl_audio *V) {
2013-11-15 05:37:14 -05:00
memset (V, 0, sizeof (*V));
unsigned x = fetch_int ();
V->id = fetch_long ();
if (x == CODE_audio_empty) { return; }
V->access_hash = fetch_long ();
V->user_id = fetch_int ();
V->date = fetch_int ();
V->duration = fetch_int ();
2014-08-12 21:22:15 -04:00
V->mime_type = fetch_str_dup ();
2013-11-15 05:37:14 -05:00
V->size = fetch_int ();
V->dc_id = fetch_int ();
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_document (struct tgl_document *V) {
2013-11-15 05:37:14 -05:00
memset (V, 0, sizeof (*V));
unsigned x = fetch_int ();
V->id = fetch_long ();
if (x == CODE_document_empty) { return; }
V->access_hash = fetch_long ();
V->user_id = fetch_int ();
V->date = fetch_int ();
V->caption = fetch_str_dup ();
V->mime_type = fetch_str_dup ();
V->size = fetch_int ();
2014-08-13 08:56:55 -04:00
tglf_fetch_photo_size (&V->thumb);
2013-11-15 05:37:14 -05:00
V->dc_id = fetch_int ();
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message_action (struct tgl_message_action *M) {
memset (M, 0, sizeof (*M));
unsigned x = fetch_int ();
switch (x) {
case CODE_message_action_empty:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_none;
break;
2013-11-22 18:26:35 -05:00
case CODE_message_action_geo_chat_create:
{
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_geo_chat_create;
2013-11-22 18:26:35 -05:00
int l = prefetch_strlen (); // title
char *s = fetch_str (l);
int l2 = prefetch_strlen (); // checkin
char *s2 = fetch_str (l2);
2014-08-13 08:56:55 -04:00
vlogprintf (E_ERROR, "Message action: Created geochat %.*s in address %.*s. You are in magic land now, since nobody ever tested geochats in this app\n", l, s, l2, s2);
2013-11-22 18:26:35 -05:00
}
break;
case CODE_message_action_geo_chat_checkin:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_geo_chat_checkin;
2013-11-22 18:26:35 -05:00
break;
case CODE_message_action_chat_create:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_chat_create;
M->title = fetch_str_dup ();
assert (fetch_int () == (int)CODE_vector);
M->user_num = fetch_int ();
M->users = talloc (M->user_num * 4);
fetch_ints (M->users, M->user_num);
break;
case CODE_message_action_chat_edit_title:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_chat_edit_title;
M->new_title = fetch_str_dup ();
break;
case CODE_message_action_chat_edit_photo:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_chat_edit_photo;
2014-08-13 08:56:55 -04:00
tglf_fetch_photo (&M->photo);
break;
case CODE_message_action_chat_delete_photo:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_chat_delete_photo;
break;
case CODE_message_action_chat_add_user:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_chat_add_user;
M->user = fetch_int ();
break;
case CODE_message_action_chat_delete_user:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_chat_delete_user;
M->user = fetch_int ();
break;
default:
vlogprintf (E_ERROR, "type = %d\n", x);
assert (0);
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message_short (struct tgl_message *M) {
int new = !(M->flags & FLAG_CREATED);
if (new) {
int id = fetch_int ();
int from_id = fetch_int ();
2014-08-13 08:56:55 -04:00
int to_id = tgl_state.our_id;
int l = prefetch_strlen ();
char *s = fetch_str (l);
2014-09-07 14:44:19 -04:00
int pts = fetch_int ();
int date = fetch_int ();
2014-08-20 12:36:45 -04:00
//tglu_fetch_seq ();
2014-08-25 10:12:17 -04:00
int seq = fetch_int ();
assert (seq == tgl_state.seq + 1);
bl_do_create_message_text (id, from_id, TGL_PEER_USER, to_id, date, 1, l, s);
2014-09-07 14:44:19 -04:00
tgl_peer_t *P = tgl_peer_get (TGL_MK_USER (from_id));
if (!P || !(P->flags & FLAG_CREATED)) {
tgl_do_get_difference (0, 0, 0);
} else {
bl_do_set_pts (pts);
bl_do_set_date (date);
}
2014-08-25 16:48:22 -04:00
//bl_do_msg_seq_update (id);
} else {
2014-08-25 16:48:22 -04:00
fetch_int (); // id
fetch_int (); // from_id
int l = prefetch_strlen ();
fetch_str (l); // text
2014-08-14 14:03:33 -04:00
tglu_fetch_pts ();
fetch_int ();
2014-08-20 12:36:45 -04:00
//tglu_fetch_seq ();
2014-08-25 10:12:17 -04:00
int seq = fetch_int ();
assert (seq == tgl_state.seq + 1);
2014-08-25 16:48:22 -04:00
//bl_do_msg_seq_update (id);
}
2013-10-16 15:19:39 -04:00
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message_short_chat (struct tgl_message *M) {
int new = !(M->flags & FLAG_CREATED);
if (new) {
int id = fetch_int ();
int from_id = fetch_int ();
int to_id = fetch_int ();
int l = prefetch_strlen ();
char *s = fetch_str (l);
2014-09-07 14:44:19 -04:00
int pts = fetch_int ();
int date = fetch_int ();
2014-08-20 12:36:45 -04:00
//tglu_fetch_seq ();
2014-08-25 10:12:17 -04:00
int seq = fetch_int ();
assert (seq == tgl_state.seq + 1);
bl_do_create_message_text (id, from_id, TGL_PEER_CHAT, to_id, date, 1, l, s);
2014-09-07 14:44:19 -04:00
tgl_peer_t *P = tgl_peer_get (TGL_MK_CHAT (to_id));
if (!P || !(P->flags & FLAG_CREATED)) {
tgl_do_get_difference (0, 0, 0);
} else {
P = tgl_peer_get (TGL_MK_USER (from_id));
if (!P || !(P->flags & FLAG_CREATED)) {
tgl_do_get_difference (0, 0, 0);
} else {
bl_do_set_pts (pts);
bl_do_set_date (date);
}
}
2014-08-25 16:48:22 -04:00
//bl_do_msg_seq_update (id);
} else {
2014-08-25 16:48:22 -04:00
fetch_int (); // id
fetch_int (); // from_id
fetch_int (); // to_id
int l = prefetch_strlen ();
fetch_str (l); // text
2014-08-14 14:03:33 -04:00
tglu_fetch_pts ();
fetch_int ();
2014-08-20 12:36:45 -04:00
//tglu_fetch_seq ();
2014-08-25 10:12:17 -04:00
int seq = fetch_int ();
assert (seq == tgl_state.seq + 1);
2014-08-25 16:48:22 -04:00
//bl_do_msg_seq_update (id);
}
2013-10-16 15:19:39 -04:00
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message_media (struct tgl_message_media *M) {
memset (M, 0, sizeof (*M));
2014-08-18 12:39:04 -04:00
//M->type = fetch_int ();
int x = fetch_int ();
switch (x) {
case CODE_message_media_empty:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_none;
break;
case CODE_message_media_photo:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_photo;
2014-08-13 08:56:55 -04:00
tglf_fetch_photo (&M->photo);
break;
case CODE_message_media_video:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_video;
2014-08-13 11:55:16 -04:00
tglf_fetch_video (&M->video);
break;
2013-11-15 05:37:14 -05:00
case CODE_message_media_audio:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_audio;
2014-08-13 11:55:16 -04:00
tglf_fetch_audio (&M->audio);
2013-11-15 05:37:14 -05:00
break;
case CODE_message_media_document:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_document;
2014-08-13 11:55:16 -04:00
tglf_fetch_document (&M->document);
2013-11-15 05:37:14 -05:00
break;
case CODE_message_media_geo:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_geo;
2014-08-14 14:03:33 -04:00
tglf_fetch_geo (&M->geo);
break;
case CODE_message_media_contact:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_contact;
M->phone = fetch_str_dup ();
M->first_name = fetch_str_dup ();
M->last_name = fetch_str_dup ();
M->user_id = fetch_int ();
break;
case CODE_message_media_unsupported:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_unsupported;
M->data_size = prefetch_strlen ();
M->data = talloc (M->data_size);
memcpy (M->data, fetch_str (M->data_size), M->data_size);
break;
default:
2014-08-13 08:56:55 -04:00
vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
assert (0);
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message_media_encrypted (struct tgl_message_media *M) {
memset (M, 0, sizeof (*M));
unsigned x = fetch_int ();
int l;
2013-11-04 12:34:27 -05:00
switch (x) {
case CODE_decrypted_message_media_empty:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_none;
//M->type = CODE_message_media_empty;
break;
case CODE_decrypted_message_media_photo:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_photo_encr;
//M->type = x;
l = prefetch_strlen ();
fetch_str (l); // thumb
fetch_int (); // thumb_w
fetch_int (); // thumb_h
M->encr_photo.w = fetch_int ();
M->encr_photo.h = fetch_int ();
M->encr_photo.size = fetch_int ();
2013-11-04 12:34:27 -05:00
l = prefetch_strlen ();
assert (l > 0);
M->encr_photo.key = talloc (32);
2013-11-04 12:34:27 -05:00
memset (M->encr_photo.key, 0, 32);
if (l <= 32) {
memcpy (M->encr_photo.key + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_photo.key, fetch_str (l) + (l - 32), 32);
}
M->encr_photo.iv = talloc (32);
2013-11-04 12:34:27 -05:00
l = prefetch_strlen ();
assert (l > 0);
memset (M->encr_photo.iv, 0, 32);
if (l <= 32) {
memcpy (M->encr_photo.iv + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_photo.iv, fetch_str (l) + (l - 32), 32);
}
break;
case CODE_decrypted_message_media_video:
2014-08-12 21:22:15 -04:00
case CODE_decrypted_message_media_video_l12:
2014-08-18 12:39:04 -04:00
//M->type = CODE_decrypted_message_media_video;
M->type = tgl_message_media_video_encr;
l = prefetch_strlen ();
fetch_str (l); // thumb
fetch_int (); // thumb_w
fetch_int (); // thumb_h
2013-11-15 05:37:14 -05:00
M->encr_video.duration = fetch_int ();
2014-08-12 21:22:15 -04:00
if (x == CODE_decrypted_message_media_video) {
M->encr_video.mime_type = fetch_str_dup ();
}
M->encr_video.w = fetch_int ();
M->encr_video.h = fetch_int ();
M->encr_video.size = fetch_int ();
2013-11-15 05:37:14 -05:00
l = prefetch_strlen ();
assert (l > 0);
M->encr_video.key = talloc0 (32);
2013-11-15 05:37:14 -05:00
if (l <= 32) {
memcpy (M->encr_video.key + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_video.key, fetch_str (l) + (l - 32), 32);
}
M->encr_video.iv = talloc (32);
2013-11-15 05:37:14 -05:00
l = prefetch_strlen ();
assert (l > 0);
memset (M->encr_video.iv, 0, 32);
if (l <= 32) {
memcpy (M->encr_video.iv + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_video.iv, fetch_str (l) + (l - 32), 32);
}
break;
case CODE_decrypted_message_media_audio:
2014-08-12 21:22:15 -04:00
case CODE_decrypted_message_media_audio_l12:
2014-08-18 12:39:04 -04:00
//M->type = CODE_decrypted_message_media_audio;
M->type = tgl_message_media_audio_encr;
2013-11-15 05:37:14 -05:00
M->encr_audio.duration = fetch_int ();
2014-08-12 21:22:15 -04:00
if (x == CODE_decrypted_message_media_audio) {
M->encr_audio.mime_type = fetch_str_dup ();
}
2013-11-15 05:37:14 -05:00
M->encr_audio.size = fetch_int ();
l = prefetch_strlen ();
assert (l > 0);
M->encr_video.key = talloc0 (32);
2013-11-15 05:37:14 -05:00
if (l <= 32) {
memcpy (M->encr_video.key + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_video.key, fetch_str (l) + (l - 32), 32);
}
M->encr_video.iv = talloc0 (32);
2013-11-15 05:37:14 -05:00
l = prefetch_strlen ();
assert (l > 0);
if (l <= 32) {
memcpy (M->encr_video.iv + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_video.iv, fetch_str (l) + (l - 32), 32);
}
break;
case CODE_decrypted_message_media_document:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_document_encr;
2013-11-15 05:37:14 -05:00
l = prefetch_strlen ();
fetch_str (l); // thumb
fetch_int (); // thumb_w
fetch_int (); // thumb_h
M->encr_document.file_name = fetch_str_dup ();
M->encr_document.mime_type = fetch_str_dup ();
M->encr_video.size = fetch_int ();
2013-11-04 12:34:27 -05:00
l = prefetch_strlen ();
assert (l > 0);
M->encr_video.key = talloc0 (32);
2013-11-04 12:34:27 -05:00
if (l <= 32) {
memcpy (M->encr_video.key + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_video.key, fetch_str (l) + (l - 32), 32);
}
M->encr_video.iv = talloc0 (32);
2013-11-04 12:34:27 -05:00
l = prefetch_strlen ();
assert (l > 0);
if (l <= 32) {
memcpy (M->encr_video.iv + (32 - l), fetch_str (l), l);
} else {
memcpy (M->encr_video.iv, fetch_str (l) + (l - 32), 32);
}
break;
/* case CODE_decrypted_message_media_file:
M->type = x;
M->encr_file.filename = fetch_str_dup ();
l = prefetch_strlen ();
fetch_str (l); // thumb
l = fetch_int ();
assert (l > 0);
M->encr_file.key = talloc (l);
memcpy (M->encr_file.key, fetch_str (l), l);
l = fetch_int ();
assert (l > 0);
M->encr_file.iv = talloc (l);
memcpy (M->encr_file.iv, fetch_str (l), l);
break;
*/
case CODE_decrypted_message_media_geo_point:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_geo;
M->geo.longitude = fetch_double ();
M->geo.latitude = fetch_double ();
break;
case CODE_decrypted_message_media_contact:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_media_contact;
M->phone = fetch_str_dup ();
M->first_name = fetch_str_dup ();
M->last_name = fetch_str_dup ();
M->user_id = fetch_int ();
break;
default:
2014-08-13 08:56:55 -04:00
vlogprintf (E_ERROR, "type = 0x%08x\n", x);
assert (0);
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message_action_encrypted (struct tgl_message_action *M) {
unsigned x = fetch_int ();
switch (x) {
case CODE_decrypted_message_action_set_message_t_t_l:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_set_message_ttl;
M->ttl = fetch_int ();
break;
2014-08-12 21:22:15 -04:00
case CODE_decrypted_message_action_read_messages:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_read_messages;
2014-08-12 21:22:15 -04:00
{
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
M->read_cnt = n;
while (n -- > 0) {
long long id = fetch_long ();
2014-08-13 11:55:16 -04:00
struct tgl_message *N = tgl_message_get (id);
2014-08-12 21:22:15 -04:00
if (N) {
N->unread = 0;
}
}
}
break;
case CODE_decrypted_message_action_delete_messages:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_delete_messages;
2014-08-12 21:22:15 -04:00
{
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
M->delete_cnt = n;
while (n -- > 0) {
fetch_long ();
}
}
break;
case CODE_decrypted_message_action_screenshot_messages:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_screenshot_messages;
2014-08-12 21:22:15 -04:00
{
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
M->screenshot_cnt = n;
while (n -- > 0) {
fetch_long ();
}
}
break;
case CODE_decrypted_message_action_notify_layer:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_notify_layer;
2014-08-12 21:22:15 -04:00
M->layer = fetch_int ();
break;
case CODE_decrypted_message_action_flush_history:
2014-08-18 12:39:04 -04:00
M->type = tgl_message_action_flush_history;
2014-08-12 21:22:15 -04:00
break;
default:
2014-08-13 08:56:55 -04:00
vlogprintf (E_ERROR, "x = 0x%08x\n", x);
assert (0);
}
}
2014-08-13 11:55:16 -04:00
tgl_peer_id_t tglf_fetch_peer_id (void) {
unsigned x =fetch_int ();
if (x == CODE_peer_user) {
2014-08-13 11:55:16 -04:00
return TGL_MK_USER (fetch_int ());
} else {
assert (CODE_peer_chat);
2014-08-13 11:55:16 -04:00
return TGL_MK_CHAT (fetch_int ());
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_message (struct tgl_message *M) {
unsigned x = fetch_int ();
assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service);
int id = fetch_int ();
assert (M->id == id);
if (x == CODE_message_empty) {
return;
}
int fwd_from_id = 0;
int fwd_date = 0;
if (x == CODE_message_forwarded) {
fwd_from_id = fetch_int ();
fwd_date = fetch_int ();
}
int from_id = fetch_int ();
2014-08-13 11:55:16 -04:00
tgl_peer_id_t to_id = tglf_fetch_peer_id ();
fetch_bool (); // out.
int unread = fetch_bool ();
int date = fetch_int ();
int new = !(M->flags & FLAG_CREATED);
if (x == CODE_message_service) {
int *start = in_ptr;
2014-08-12 11:15:04 -04:00
2014-08-12 17:32:11 -04:00
assert (skip_type_any (TYPE_TO_PARAM (message_action)) >= 0);
2014-08-12 11:15:04 -04:00
if (new) {
if (fwd_from_id) {
2014-08-21 16:35:27 -04:00
bl_do_create_message_service_fwd (id, from_id, tgl_get_peer_type (to_id), tgl_get_peer_id (to_id), date, fwd_from_id, fwd_date, unread, start, (in_ptr - start));
} else {
2014-08-21 16:35:27 -04:00
bl_do_create_message_service (id, from_id, tgl_get_peer_type (to_id), tgl_get_peer_id (to_id), date, unread, start, (in_ptr - start));
}
}
} else {
int l = prefetch_strlen ();
char *s = fetch_str (l);
int *start = in_ptr;
2014-08-12 11:15:04 -04:00
2014-08-12 17:32:11 -04:00
assert (skip_type_any (TYPE_TO_PARAM (message_media)) >= 0);
2014-08-12 11:15:04 -04:00
if (new) {
if (fwd_from_id) {
2014-08-21 16:35:27 -04:00
bl_do_create_message_media_fwd (id, from_id, tgl_get_peer_type (to_id), tgl_get_peer_id (to_id), date, fwd_from_id, fwd_date, unread, l, s, start, in_ptr - start);
} else {
2014-08-21 16:35:27 -04:00
bl_do_create_message_media (id, from_id, tgl_get_peer_type (to_id), tgl_get_peer_id (to_id), date, unread, l, s, start, in_ptr - start);
}
}
}
bl_do_set_unread (M, unread);
}
2014-08-14 14:03:33 -04:00
void tglf_tglf_fetch_geo_message (struct tgl_message *M) {
2013-11-01 15:57:57 -04:00
memset (M, 0, sizeof (*M));
unsigned x = fetch_int ();
assert (x == CODE_geo_chat_message_empty || x == CODE_geo_chat_message || x == CODE_geo_chat_message_service);
2014-08-13 11:55:16 -04:00
M->to_id = TGL_MK_GEO_CHAT (fetch_int ());
2013-11-01 15:57:57 -04:00
M->id = fetch_int ();
if (x == CODE_geo_chat_message_empty) {
M->flags |= 1;
return;
}
2014-08-13 11:55:16 -04:00
M->from_id = TGL_MK_USER (fetch_int ());
2013-11-01 15:57:57 -04:00
M->date = fetch_int ();
if (x == CODE_geo_chat_message_service) {
M->service = 1;
2014-08-13 08:56:55 -04:00
tglf_fetch_message_action (&M->action);
2013-11-01 15:57:57 -04:00
} else {
M->message = fetch_str_dup ();
M->message_len = strlen (M->message);
2014-08-13 08:56:55 -04:00
tglf_fetch_message_media (&M->media);
2013-11-01 15:57:57 -04:00
}
}
2013-11-25 11:13:36 -05:00
static int *decr_ptr;
static int *decr_end;
2014-08-13 11:55:16 -04:00
static int decrypt_encrypted_message (struct tgl_secret_chat *E) {
int *msg_key = decr_ptr;
decr_ptr += 4;
assert (decr_ptr < decr_end);
static unsigned char sha1a_buffer[20];
static unsigned char sha1b_buffer[20];
static unsigned char sha1c_buffer[20];
static unsigned char sha1d_buffer[20];
static unsigned char buf[64];
memcpy (buf, msg_key, 16);
memcpy (buf + 16, E->key, 32);
sha1 (buf, 48, sha1a_buffer);
memcpy (buf, E->key + 8, 16);
memcpy (buf + 16, msg_key, 16);
memcpy (buf + 32, E->key + 12, 16);
sha1 (buf, 48, sha1b_buffer);
memcpy (buf, E->key + 16, 32);
memcpy (buf + 32, msg_key, 16);
sha1 (buf, 48, sha1c_buffer);
memcpy (buf, msg_key, 16);
memcpy (buf + 16, E->key + 24, 32);
sha1 (buf, 48, sha1d_buffer);
static unsigned char key[32];
2013-11-04 12:34:27 -05:00
memcpy (key, sha1a_buffer + 0, 8);
memcpy (key + 8, sha1b_buffer + 8, 12);
memcpy (key + 20, sha1c_buffer + 4, 12);
static unsigned char iv[32];
memcpy (iv, sha1a_buffer + 8, 12);
memcpy (iv + 12, sha1b_buffer + 0, 8);
memcpy (iv + 20, sha1c_buffer + 16, 4);
memcpy (iv + 24, sha1d_buffer + 0, 8);
AES_KEY aes_key;
AES_set_decrypt_key (key, 256, &aes_key);
AES_ige_encrypt ((void *)decr_ptr, (void *)decr_ptr, 4 * (decr_end - decr_ptr), &aes_key, iv, 0);
2014-01-21 11:02:34 -05:00
memset (&aes_key, 0, sizeof (aes_key));
2013-11-04 12:34:27 -05:00
int x = *(decr_ptr);
2013-11-05 17:24:26 -05:00
if (x < 0 || (x & 3)) {
return -1;
}
2013-11-04 12:34:27 -05:00
assert (x >= 0 && !(x & 3));
sha1 ((void *)decr_ptr, 4 + x, sha1a_buffer);
2013-11-04 12:34:27 -05:00
if (memcmp (sha1a_buffer + 4, msg_key, 16)) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Sha1 mismatch\n");
return -1;
}
return 0;
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_encrypted_message (struct tgl_message *M) {
unsigned x = fetch_int ();
assert (x == CODE_encrypted_message || x == CODE_encrypted_message_service);
2013-11-04 12:34:27 -05:00
unsigned sx = x;
int new = !(M->flags & FLAG_CREATED);
long long id = fetch_long ();
int to_id = fetch_int ();
2014-08-13 11:55:16 -04:00
tgl_peer_id_t chat = TGL_MK_ENCR_CHAT (to_id);
int date = fetch_int ();
2014-08-13 11:55:16 -04:00
tgl_peer_t *P = tgl_peer_get (chat);
if (!P) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Encrypted message to unknown chat. Dropping\n");
2013-11-21 14:35:49 -05:00
M->flags |= FLAG_MESSAGE_EMPTY;
}
2013-11-04 12:34:27 -05:00
int len = prefetch_strlen ();
2013-11-04 12:34:27 -05:00
assert ((len & 15) == 8);
decr_ptr = (void *)fetch_str (len);
2013-11-04 12:34:27 -05:00
decr_end = decr_ptr + (len / 4);
int ok = 0;
if (P) {
if (*(long long *)decr_ptr != P->encr_chat.key_fingerprint) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_WARNING, "Encrypted message with bad fingerprint to chat %s\n", P->print_name);
2013-11-04 12:34:27 -05:00
P = 0;
}
decr_ptr += 2;
}
int l = 0;
char *s = 0;
int *start = 0;
int *end = 0;
x = 0;
if (P && decrypt_encrypted_message (&P->encr_chat) >= 0 && new) {
2013-11-04 12:34:27 -05:00
ok = 1;
int *save_in_ptr = in_ptr;
int *save_in_end = in_end;
in_ptr = decr_ptr;
int ll = fetch_int ();
in_end = in_ptr + ll;
x = fetch_int ();
if (x == CODE_decrypted_message_layer) {
int layer = fetch_int ();
assert (layer >= 0);
x = fetch_int ();
}
2013-11-04 12:34:27 -05:00
assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service);
//assert (id == fetch_long ());
fetch_long ();
ll = prefetch_strlen ();
fetch_str (ll); // random_bytes
if (x == CODE_decrypted_message) {
l = prefetch_strlen ();
s = fetch_str (l);
start = in_ptr;
2014-08-12 17:32:11 -04:00
assert (skip_type_any (TYPE_TO_PARAM (decrypted_message_media)) >= 0);
end = in_ptr;
} else {
start = in_ptr;
2014-08-26 12:06:30 -04:00
if (skip_type_any (TYPE_TO_PARAM (decrypted_message_action)) < 0) {
2014-08-31 13:19:56 -04:00
vlogprintf (E_ERROR, "Skipped %ld int out of %ld. Magic = 0x%08x\n", (long)(in_ptr - start), (long)(in_end - start), *start);
2014-08-26 12:06:30 -04:00
assert (0);
}
end = in_ptr;
}
2013-11-04 12:34:27 -05:00
in_ptr = save_in_ptr;
in_end = save_in_end;
2014-08-13 08:56:55 -04:00
}
2013-11-04 12:34:27 -05:00
if (sx == CODE_encrypted_message) {
if (ok) {
int *start_file = in_ptr;
2014-08-12 17:32:11 -04:00
assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0);
if (x == CODE_decrypted_message) {
2014-08-13 11:55:16 -04:00
bl_do_create_message_media_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, in_ptr - start_file);
2014-08-12 21:22:15 -04:00
} else if (x == CODE_decrypted_message_service) {
2014-08-13 11:55:16 -04:00
bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start);
}
2013-11-04 12:34:27 -05:00
} else {
2014-08-12 21:22:15 -04:00
assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0);
2013-11-04 12:34:27 -05:00
M->media.type = CODE_message_media_empty;
}
} else {
if (ok && x == CODE_decrypted_message_service) {
2014-08-13 11:55:16 -04:00
bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start);
}
}
}
2014-08-13 11:55:16 -04:00
void tglf_fetch_encrypted_message_file (struct tgl_message_media *M) {
unsigned x = fetch_int ();
assert (x == CODE_encrypted_file || x == CODE_encrypted_file_empty);
if (x == CODE_encrypted_file_empty) {
2014-08-18 12:39:04 -04:00
assert (M->type != tgl_message_media_photo_encr && M->type != tgl_message_media_video_encr);
} else {
2014-08-18 12:39:04 -04:00
assert (M->type == tgl_message_media_document_encr || M->type == tgl_message_media_photo_encr || M->type == tgl_message_media_video_encr || M->type == tgl_message_media_audio_encr);
2014-03-06 17:43:15 -05:00
M->encr_photo.id = fetch_long();
M->encr_photo.access_hash = fetch_long();
2014-03-06 17:44:41 -05:00
if (!M->encr_photo.size) {
M->encr_photo.size = fetch_int ();
} else {
fetch_int ();
}
2014-03-06 17:43:15 -05:00
M->encr_photo.dc_id = fetch_int();
M->encr_photo.key_fingerprint = fetch_int();
}
}
2014-08-13 11:55:16 -04:00
static int id_cmp (struct tgl_message *M1, struct tgl_message *M2) {
if (M1->id < M2->id) { return -1; }
else if (M1->id > M2->id) { return 1; }
else { return 0; }
}
2014-08-13 11:55:16 -04:00
struct tgl_user *tglf_fetch_alloc_user (void) {
2013-10-24 13:04:44 -04:00
int data[2];
prefetch_data (data, 8);
2014-08-13 11:55:16 -04:00
tgl_peer_t *U = tgl_peer_get (TGL_MK_USER (data[1]));
2013-11-21 14:35:49 -05:00
if (!U) {
2013-10-24 13:04:44 -04:00
users_allocated ++;
U = talloc0 (sizeof (*U));
2014-08-13 11:55:16 -04:00
U->id = TGL_MK_USER (data[1]);
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, U, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
2013-11-04 12:34:27 -05:00
Peers[peer_num ++] = U;
}
2014-08-13 08:56:55 -04:00
tglf_fetch_user (&U->user);
2013-11-21 14:35:49 -05:00
return &U->user;
}
2014-08-13 11:55:16 -04:00
struct tgl_secret_chat *tglf_fetch_alloc_encrypted_chat (void) {
int data[2];
prefetch_data (data, 8);
2014-08-13 11:55:16 -04:00
tgl_peer_t *U = tgl_peer_get (TGL_MK_ENCR_CHAT (data[1]));
2013-11-21 14:35:49 -05:00
if (!U) {
U = talloc0 (sizeof (*U));
2014-08-13 11:55:16 -04:00
U->id = TGL_MK_ENCR_CHAT (data[1]);
2013-11-21 14:35:49 -05:00
encr_chats_allocated ++;
2014-08-13 11:55:16 -04:00
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, U, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
2013-11-04 12:34:27 -05:00
Peers[peer_num ++] = U;
}
2014-08-13 08:56:55 -04:00
tglf_fetch_encrypted_chat (&U->encr_chat);
2013-11-21 14:35:49 -05:00
return &U->encr_chat;
}
2014-08-13 11:55:16 -04:00
struct tgl_user *tglf_fetch_alloc_user_full (void) {
int data[3];
prefetch_data (data, 12);
tgl_peer_t *U = tgl_peer_get (TGL_MK_USER (data[2]));
if (U) {
tglf_fetch_user_full (&U->user);
return &U->user;
} else {
users_allocated ++;
U = talloc0 (sizeof (*U));
U->id = TGL_MK_USER (data[2]);
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, U, lrand48 ());
tglf_fetch_user_full (&U->user);
assert (peer_num < TGL_MAX_PEER_NUM);
Peers[peer_num ++] = U;
return &U->user;
}
2013-11-04 12:34:27 -05:00
}
2014-08-13 11:55:16 -04:00
struct tgl_message *tglf_fetch_alloc_message (void) {
int data[2];
prefetch_data (data, 8);
struct tgl_message *M = tgl_message_get (data[1]);
if (!M) {
M = tglm_message_alloc (data[1]);
}
tglf_fetch_message (M);
return M;
2013-11-21 14:35:49 -05:00
}
2014-08-13 11:55:16 -04:00
struct tgl_message *tglf_fetch_alloc_geo_message (void) {
struct tgl_message *M = talloc (sizeof (*M));
2014-08-14 14:03:33 -04:00
tglf_tglf_fetch_geo_message (M);
2014-08-13 11:55:16 -04:00
struct tgl_message *M1 = tree_lookup_message (message_tree, M);
messages_allocated ++;
if (M1) {
tglm_message_del_use (M1);
tglm_message_del_peer (M1);
tgls_clear_message (M1);
2014-08-13 11:55:16 -04:00
memcpy (M1, M, sizeof (*M));
tfree (M, sizeof (*M));
tglm_message_add_use (M1);
tglm_message_add_peer (M1);
messages_allocated --;
return M1;
} else {
tglm_message_add_use (M);
tglm_message_add_peer (M);
message_tree = tree_insert_message (message_tree, M, lrand48 ());
return M;
}
2013-11-22 18:26:35 -05:00
}
2014-08-13 11:55:16 -04:00
struct tgl_message *tglf_fetch_alloc_encrypted_message (void) {
2013-10-25 13:29:02 -04:00
int data[3];
prefetch_data (data, 12);
2014-08-13 11:55:16 -04:00
struct tgl_message *M = tgl_message_get (*(long long *)(data + 1));
if (!M) {
M = talloc0 (sizeof (*M));
M->id = *(long long *)(data + 1);
tglm_message_insert_tree (M);
messages_allocated ++;
assert (tgl_message_get (M->id) == M);
}
tglf_fetch_encrypted_message (M);
return M;
}
struct tgl_message *tglf_fetch_alloc_message_short (void) {
int data[1];
prefetch_data (data, 4);
struct tgl_message *M = tgl_message_get (data[0]);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = data[0];
tglm_message_insert_tree (M);
messages_allocated ++;
}
tglf_fetch_message_short (M);
return M;
}
struct tgl_message *tglf_fetch_alloc_message_short_chat (void) {
int data[1];
prefetch_data (data, 4);
struct tgl_message *M = tgl_message_get (data[0]);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = data[0];
tglm_message_insert_tree (M);
messages_allocated ++;
}
tglf_fetch_message_short_chat (M);
return M;
}
struct tgl_chat *tglf_fetch_alloc_chat (void) {
int data[2];
prefetch_data (data, 8);
tgl_peer_t *U = tgl_peer_get (TGL_MK_CHAT (data[1]));
if (!U) {
chats_allocated ++;
U = talloc0 (sizeof (*U));
U->id = TGL_MK_CHAT (data[1]);
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, U, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
Peers[peer_num ++] = U;
}
tglf_fetch_chat (&U->chat);
return &U->chat;
}
struct tgl_chat *tglf_fetch_alloc_chat_full (void) {
int data[3];
prefetch_data (data, 12);
tgl_peer_t *U = tgl_peer_get (TGL_MK_CHAT (data[2]));
2013-10-25 13:29:02 -04:00
if (U) {
2014-08-13 11:55:16 -04:00
tglf_fetch_chat_full (&U->chat);
return &U->chat;
2013-10-25 13:29:02 -04:00
} else {
2014-08-13 11:55:16 -04:00
chats_allocated ++;
U = talloc0 (sizeof (*U));
2014-08-13 11:55:16 -04:00
U->id = TGL_MK_CHAT (data[2]);
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, U, lrand48 ());
tglf_fetch_chat_full (&U->chat);
assert (peer_num < TGL_MAX_PEER_NUM);
2013-11-04 12:34:27 -05:00
Peers[peer_num ++] = U;
2014-08-13 11:55:16 -04:00
return &U->chat;
2013-10-25 13:29:02 -04:00
}
}
2014-08-13 11:55:16 -04:00
/* }}} */
void tglp_insert_encrypted_chat (tgl_peer_t *P) {
encr_chats_allocated ++;
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, P, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
Peers[peer_num ++] = P;
}
void tglp_insert_user (tgl_peer_t *P) {
users_allocated ++;
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, P, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
Peers[peer_num ++] = P;
}
void tglp_insert_chat (tgl_peer_t *P) {
chats_allocated ++;
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, P, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
Peers[peer_num ++] = P;
}
2013-10-25 13:29:02 -04:00
void tgl_insert_empty_user (int uid) {
tgl_peer_id_t id = TGL_MK_USER (uid);
if (tgl_peer_get (id)) { return; }
tgl_peer_t *P = talloc0 (sizeof (*P));
P->id = id;
tglp_insert_user (P);
}
void tgl_insert_empty_chat (int cid) {
tgl_peer_id_t id = TGL_MK_CHAT (cid);
if (tgl_peer_get (id)) { return; }
tgl_peer_t *P = talloc0 (sizeof (*P));
P->id = id;
tglp_insert_chat (P);
}
2014-08-13 11:55:16 -04:00
/* {{{ Free */
2014-08-13 11:55:16 -04:00
void tgls_free_photo_size (struct tgl_photo_size *S) {
tfree_str (S->type);
if (S->data) {
tfree (S->data, S->size);
}
}
2014-08-13 11:55:16 -04:00
void tgls_free_photo (struct tgl_photo *P) {
if (P->caption) { tfree_str (P->caption); }
if (P->sizes) {
int i;
for (i = 0; i < P->sizes_num; i++) {
2014-08-13 11:55:16 -04:00
tgls_free_photo_size (&P->sizes[i]);
}
2014-08-13 11:55:16 -04:00
tfree (P->sizes, sizeof (struct tgl_photo_size) * P->sizes_num);
}
}
2014-08-13 11:55:16 -04:00
void tgls_free_video (struct tgl_video *V) {
2014-09-18 06:11:23 -04:00
tfree_str (V->mime_type);
if (!V->access_hash) { return; }
tfree_str (V->caption);
2014-08-13 11:55:16 -04:00
tgls_free_photo_size (&V->thumb);
}
2014-09-18 06:11:23 -04:00
void tgls_free_audio (struct tgl_audio *A) {
tfree_str (A->mime_type);
}
2014-08-13 11:55:16 -04:00
void tgls_free_document (struct tgl_document *D) {
2013-11-15 05:37:14 -05:00
if (!D->access_hash) { return; }
if (D->mime_type) { tfree_str (D->mime_type);}
if (D->caption) {tfree_str (D->caption);}
2014-08-13 11:55:16 -04:00
tgls_free_photo_size (&D->thumb);
2013-11-15 05:37:14 -05:00
}
2014-08-13 11:55:16 -04:00
void tgls_free_message_media (struct tgl_message_media *M) {
switch (M->type) {
2014-08-18 12:39:04 -04:00
case tgl_message_media_none:
case tgl_message_media_geo:
2014-09-18 06:11:23 -04:00
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_audio:
2014-09-18 06:11:23 -04:00
tgls_free_audio (&M->audio);
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_photo:
2014-08-13 11:55:16 -04:00
tgls_free_photo (&M->photo);
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_video:
2014-08-13 11:55:16 -04:00
tgls_free_video (&M->video);
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_contact:
tfree_str (M->phone);
tfree_str (M->first_name);
tfree_str (M->last_name);
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_document:
2014-08-13 11:55:16 -04:00
tgls_free_document (&M->document);
2013-11-15 05:37:14 -05:00
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_unsupported:
tfree (M->data, M->data_size);
return;
2014-08-18 12:39:04 -04:00
case tgl_message_media_photo_encr:
case tgl_message_media_video_encr:
case tgl_message_media_audio_encr:
case tgl_message_media_document_encr:
tfree_secure (M->encr_photo.key, 32);
tfree_secure (M->encr_photo.iv, 32);
return;
default:
2014-08-13 08:56:55 -04:00
vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
assert (0);
}
}
2014-08-13 11:55:16 -04:00
void tgls_free_message_action (struct tgl_message_action *M) {
switch (M->type) {
2014-08-18 12:39:04 -04:00
case tgl_message_action_none:
break;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_create:
tfree_str (M->title);
tfree (M->users, M->user_num * 4);
break;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_edit_title:
tfree_str (M->new_title);
break;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_edit_photo:
2014-08-13 11:55:16 -04:00
tgls_free_photo (&M->photo);
break;
2014-08-18 12:39:04 -04:00
case tgl_message_action_chat_delete_photo:
case tgl_message_action_chat_add_user:
case tgl_message_action_chat_delete_user:
case tgl_message_action_geo_chat_create:
case tgl_message_action_geo_chat_checkin:
case tgl_message_action_set_message_ttl:
case tgl_message_action_read_messages:
case tgl_message_action_delete_messages:
case tgl_message_action_screenshot_messages:
case tgl_message_action_flush_history:
case tgl_message_action_notify_layer:
2013-11-04 12:34:27 -05:00
break;
default:
vlogprintf (E_ERROR, "type = 0x%08x\n", M->type);
assert (0);
}
}
void tgls_clear_message (struct tgl_message *M) {
if (!M->service) {
if (M->message) { tfree (M->message, M->message_len + 1); }
2014-08-13 11:55:16 -04:00
tgls_free_message_media (&M->media);
} else {
2014-08-13 11:55:16 -04:00
tgls_free_message_action (&M->action);
}
}
void tgls_free_message (struct tgl_message *M) {
tgls_clear_message (M);
tfree (M, sizeof (*M));
}
2014-08-13 11:55:16 -04:00
void tgls_free_chat (struct tgl_chat *U) {
if (U->title) { tfree_str (U->title); }
if (U->print_title) { tfree_str (U->print_title); }
if (U->user_list) {
tfree (U->user_list, U->user_list_size * 12);
}
tgls_free_photo (&U->photo);
tfree (U, sizeof (*U));
}
void tgls_free_user (struct tgl_user *U) {
if (U->first_name) { tfree_str (U->first_name); }
if (U->last_name) { tfree_str (U->last_name); }
if (U->print_name) { tfree_str (U->print_name); }
if (U->phone) { tfree_str (U->phone); }
if (U->real_first_name) { tfree_str (U->real_first_name); }
if (U->real_last_name) { tfree_str (U->real_last_name); }
tgls_free_photo (&U->photo);
tfree (U, sizeof (*U));
}
void tgls_free_encr_chat (struct tgl_secret_chat *U) {
if (U->print_name) { tfree_str (U->print_name); }
if (U->g_key) { tfree (U->g_key, 256); }
if (U->nonce) { tfree (U->nonce, 256); }
tfree (U, sizeof (*U));
}
void tgls_free_peer (tgl_peer_t *P) {
if (tgl_get_peer_type (P->id) == TGL_PEER_USER) {
tgls_free_user ((void *)P);
} else if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT) {
tgls_free_chat ((void *)P);
} else if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT) {
tgls_free_encr_chat ((void *)P);
} else {
assert (0);
}
2014-08-13 11:55:16 -04:00
}
/* }}} */
/* Messages {{{ */
void tglm_message_del_use (struct tgl_message *M) {
M->next_use->prev_use = M->prev_use;
M->prev_use->next_use = M->next_use;
}
2014-08-13 11:55:16 -04:00
void tglm_message_add_use (struct tgl_message *M) {
M->next_use = message_list.next_use;
M->prev_use = &message_list;
M->next_use->prev_use = M;
M->prev_use->next_use = M;
}
2014-08-13 11:55:16 -04:00
void tglm_message_add_peer (struct tgl_message *M) {
tgl_peer_id_t id;
if (!tgl_cmp_peer_id (M->to_id, TGL_MK_USER (tgl_state.our_id))) {
2013-11-04 12:34:27 -05:00
id = M->from_id;
} else {
id = M->to_id;
}
2014-08-13 11:55:16 -04:00
tgl_peer_t *P = tgl_peer_get (id);
2013-11-04 12:34:27 -05:00
if (!P) {
P = talloc0 (sizeof (*P));
2013-11-04 12:34:27 -05:00
P->id = id;
2014-08-13 11:55:16 -04:00
switch (tgl_get_peer_type (id)) {
case TGL_PEER_USER:
2013-11-04 12:34:27 -05:00
users_allocated ++;
break;
2014-08-13 11:55:16 -04:00
case TGL_PEER_CHAT:
2013-11-04 12:34:27 -05:00
chats_allocated ++;
break;
2014-08-13 11:55:16 -04:00
case TGL_PEER_GEO_CHAT:
2013-11-04 12:34:27 -05:00
geo_chats_allocated ++;
break;
2014-08-13 11:55:16 -04:00
case TGL_PEER_ENCR_CHAT:
2013-11-04 12:34:27 -05:00
encr_chats_allocated ++;
break;
}
2014-08-13 11:55:16 -04:00
tgl_peer_tree = tree_insert_peer (tgl_peer_tree, P, lrand48 ());
assert (peer_num < TGL_MAX_PEER_NUM);
2013-11-04 12:34:27 -05:00
Peers[peer_num ++] = P;
}
if (!P->last) {
P->last = M;
M->prev = M->next = 0;
} else {
2014-08-13 11:55:16 -04:00
if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) {
struct tgl_message *N = P->last;
struct tgl_message *NP = 0;
while (N && N->id > M->id) {
NP = N;
N = N->next;
}
if (N) { assert (N->id < M->id); }
M->next = N;
M->prev = NP;
if (N) { N->prev = M; }
if (NP) { NP->next = M; }
else { P->last = M; }
} else {
2014-08-13 11:55:16 -04:00
struct tgl_message *N = P->last;
struct tgl_message *NP = 0;
M->next = N;
M->prev = NP;
if (N) { N->prev = M; }
if (NP) { NP->next = M; }
else { P->last = M; }
}
}
2013-11-04 12:34:27 -05:00
}
2014-08-13 11:55:16 -04:00
void tglm_message_del_peer (struct tgl_message *M) {
tgl_peer_id_t id;
if (!tgl_cmp_peer_id (M->to_id, TGL_MK_USER (tgl_state.our_id))) {
2013-11-04 12:34:27 -05:00
id = M->from_id;
} else {
id = M->to_id;
}
2014-08-13 11:55:16 -04:00
tgl_peer_t *P = tgl_peer_get (id);
2013-11-04 12:34:27 -05:00
if (M->prev) {
M->prev->next = M->next;
}
if (M->next) {
M->next->prev = M->prev;
}
if (P && P->last == M) {
P->last = M->next;
}
}
2014-08-13 11:55:16 -04:00
struct tgl_message *tglm_message_alloc (long long id) {
struct tgl_message *M = talloc0 (sizeof (*M));
2014-08-13 08:56:55 -04:00
M->id = id;
2014-08-13 11:55:16 -04:00
tglm_message_insert_tree (M);
2013-11-01 15:57:57 -04:00
messages_allocated ++;
return M;
}
2014-08-13 11:55:16 -04:00
void tglm_update_message_id (struct tgl_message *M, long long id) {
2013-10-16 15:19:39 -04:00
message_tree = tree_delete_message (message_tree, M);
M->id = id;
message_tree = tree_insert_message (message_tree, M, lrand48 ());
}
2013-10-18 15:30:24 -04:00
2014-08-13 11:55:16 -04:00
void tglm_message_insert_tree (struct tgl_message *M) {
assert (M->id);
message_tree = tree_insert_message (message_tree, M, lrand48 ());
}
2014-08-13 11:55:16 -04:00
void tglm_message_remove_tree (struct tgl_message *M) {
assert (M->id);
message_tree = tree_delete_message (message_tree, M);
}
2014-08-13 11:55:16 -04:00
void tglm_message_insert (struct tgl_message *M) {
tglm_message_add_use (M);
tglm_message_add_peer (M);
}
2014-08-13 11:55:16 -04:00
void tglm_message_insert_unsent (struct tgl_message *M) {
message_unsent_tree = tree_insert_message (message_unsent_tree, M, lrand48 ());
}
2014-08-13 11:55:16 -04:00
void tglm_message_remove_unsent (struct tgl_message *M) {
message_unsent_tree = tree_delete_message (message_unsent_tree, M);
}
2014-08-13 11:55:16 -04:00
static void __send_msg (struct tgl_message *M) {
2014-08-13 08:56:55 -04:00
vlogprintf (E_NOTICE, "Resending message...\n");
2014-08-13 21:31:24 -04:00
//print_message (M);
2014-09-11 16:57:59 -04:00
if (M->media.type != tgl_message_media_none) {
assert (M->flags & FLAG_ENCRYPTED);
bl_do_delete_msg (M);
} else {
tgl_do_send_msg (M, 0, 0);
}
}
2014-08-13 11:55:16 -04:00
void tglm_send_all_unsent (void ) {
tree_act_message (message_unsent_tree, __send_msg);
2013-10-18 15:30:24 -04:00
}
2014-08-13 11:55:16 -04:00
/* }}} */
2014-01-31 11:03:40 -05:00
2014-08-13 11:55:16 -04:00
void tglp_peer_insert_name (tgl_peer_t *P) {
2014-01-31 11:03:40 -05:00
peer_by_name_tree = tree_insert_peer_by_name (peer_by_name_tree, P, lrand48 ());
}
2014-08-13 11:55:16 -04:00
void tglp_peer_delete_name (tgl_peer_t *P) {
2014-01-31 11:03:40 -05:00
peer_by_name_tree = tree_delete_peer_by_name (peer_by_name_tree, P);
}
2014-08-13 11:55:16 -04:00
tgl_peer_t *tgl_peer_get (tgl_peer_id_t id) {
static tgl_peer_t U;
U.id = id;
return tree_lookup_peer (tgl_peer_tree, &U);
}
struct tgl_message *tgl_message_get (long long id) {
struct tgl_message M;
M.id = id;
return tree_lookup_message (message_tree, &M);
}
tgl_peer_t *tgl_peer_get_by_name (const char *s) {
static tgl_peer_t P;
2014-01-31 11:03:40 -05:00
P.print_name = (void *)s;
2014-08-13 11:55:16 -04:00
tgl_peer_t *R = tree_lookup_peer_by_name (peer_by_name_tree, &P);
2014-01-31 11:03:40 -05:00
return R;
}
2014-08-13 08:56:55 -04:00
2014-08-13 11:55:16 -04:00
void tgl_peer_iterator_ex (void (*it)(tgl_peer_t *P, void *extra), void *extra) {
tree_act_ex_peer (tgl_peer_tree, it, extra);
2014-08-13 08:56:55 -04:00
}
2014-08-13 11:55:16 -04:00
int tgl_complete_user_list (int index, const char *text, int len, char **R) {
2014-08-13 08:56:55 -04:00
index ++;
2014-08-13 11:55:16 -04:00
while (index < peer_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || tgl_get_peer_type (Peers[index]->id) != TGL_PEER_USER)) {
2014-08-13 08:56:55 -04:00
index ++;
}
if (index < peer_num) {
*R = strdup (Peers[index]->print_name);
assert (*R);
2014-08-13 08:56:55 -04:00
return index;
} else {
return -1;
}
}
2014-08-13 11:55:16 -04:00
int tgl_complete_chat_list (int index, const char *text, int len, char **R) {
2014-08-13 08:56:55 -04:00
index ++;
2014-08-13 11:55:16 -04:00
while (index < peer_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || tgl_get_peer_type (Peers[index]->id) != TGL_PEER_CHAT)) {
2014-08-13 08:56:55 -04:00
index ++;
}
if (index < peer_num) {
*R = strdup (Peers[index]->print_name);
assert (*R);
2014-08-13 08:56:55 -04:00
return index;
} else {
return -1;
}
}
2014-08-13 11:55:16 -04:00
int tgl_complete_encr_chat_list (int index, const char *text, int len, char **R) {
2014-08-13 08:56:55 -04:00
index ++;
2014-08-13 11:55:16 -04:00
while (index < peer_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || tgl_get_peer_type (Peers[index]->id) != TGL_PEER_ENCR_CHAT)) {
2014-08-13 08:56:55 -04:00
index ++;
}
if (index < peer_num) {
*R = strdup (Peers[index]->print_name);
assert (*R);
2014-08-13 08:56:55 -04:00
return index;
} else {
return -1;
}
}
2014-08-13 11:55:16 -04:00
int tgl_complete_peer_list (int index, const char *text, int len, char **R) {
2014-08-13 08:56:55 -04:00
index ++;
while (index < peer_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len))) {
index ++;
}
if (index < peer_num) {
*R = strdup (Peers[index]->print_name);
assert (*R);
2014-08-13 08:56:55 -04:00
return index;
} else {
return -1;
}
}
2014-08-13 11:55:16 -04:00
void tgl_free_all (void) {
tree_act_peer (tgl_peer_tree, tgls_free_peer);
tgl_peer_tree = tree_clear_peer (tgl_peer_tree);
peer_by_name_tree = tree_clear_peer_by_name (peer_by_name_tree);
tree_act_message (message_tree, tgls_free_message);
message_tree = tree_clear_message (message_tree);
tree_act_message (message_unsent_tree, tgls_free_message);
message_unsent_tree = tree_clear_message (message_unsent_tree);
if (tgl_state.encr_prime) { tfree (tgl_state.encr_prime, 256); }
if (tgl_state.binlog_name) { tfree_str (tgl_state.binlog_name); }
if (tgl_state.auth_file) { tfree_str (tgl_state.auth_file); }
if (tgl_state.downloads_directory) { tfree_str (tgl_state.downloads_directory); }
int i;
for (i = 0; i < tgl_state.rsa_key_num; i++) {
tfree_str (tgl_state.rsa_key_list[i]);
}
for (i = 0; i <= tgl_state.max_dc_num; i++) if (tgl_state.DC_list[i]) {
tgls_free_dc (tgl_state.DC_list[i]);
}
}
2014-08-13 11:55:16 -04:00
int tgl_print_stat (char *s, int len) {
return tsnprintf (s, len,
"users_allocated\t%d\n"
"chats_allocated\t%d\n"
"secret_chats_allocated\t%d\n"
"peer_num\t%d\n"
"messages_allocated\t%d\n",
users_allocated,
chats_allocated,
encr_chats_allocated,
peer_num,
messages_allocated
);
}