telegram-purple/binlog.c

1687 lines
54 KiB
C
Raw Permalink Normal View History

2013-11-30 14:12:51 +04:00
/*
This file is part of telegram-client.
Telegram-client is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Telegram-client is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this telegram-client. If not, see <http://www.gnu.org/licenses/>.
Copyright Vitaly Valtman 2013
*/
2013-11-13 04:11:25 +04:00
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
2013-11-13 04:11:25 +04:00
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
2013-12-23 15:10:53 +04:00
#include <openssl/bn.h>
2013-11-13 04:11:25 +04:00
#include "binlog.h"
#include "net.h"
#include "include.h"
2013-11-21 23:35:49 +04:00
#include "mtproto-client.h"
2014-07-26 11:55:45 +02:00
#include "telegram.h"
2013-11-21 23:35:49 +04:00
#include <openssl/sha.h>
2013-11-13 04:11:25 +04:00
#define MAX_LOG_EVENT_SIZE (1 << 17)
2014-07-26 11:55:45 +02:00
int binlog_enabled = 0;
2014-08-22 17:05:29 +02:00
void *alloc_log_event (struct binlog *bl, int l UU) {
return bl->binlog_buffer;
}
2013-11-13 04:11:25 +04:00
2014-07-26 11:55:45 +02:00
void replay_log_event (struct telegram *instance) {
2014-08-06 19:45:46 +02:00
struct mtproto_connection *self = instance->connection;
2014-08-22 17:05:29 +02:00
struct binlog *bl = instance->bl;
2014-07-26 11:55:45 +02:00
2014-08-22 17:05:29 +02:00
int *start = bl->rptr;
bl->in_replay_log = 1;
assert (bl->rptr < bl->wptr);
int op = *bl->rptr;
2013-11-13 04:11:25 +04:00
2013-11-21 23:35:49 +04:00
if (verbosity >= 2) {
2014-10-03 14:23:15 +02:00
debug ("log_pos %lld, op 0x%08x\n", bl->binlog_pos, op);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
self->in_ptr = bl->rptr;
self->in_end = bl->wptr;
2013-11-13 04:11:25 +04:00
switch (op) {
case LOG_START:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
break;
case CODE_binlog_dc_option:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-06 19:45:46 +02:00
int id = fetch_int (self);
int l1 = prefetch_strlen (self);
char *name = fetch_str (self, l1);
int l2 = prefetch_strlen (self);
char *ip = fetch_str (self, l2);
int port = fetch_int (self);
2014-10-03 14:23:15 +02:00
debug ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
2014-07-26 11:55:45 +02:00
alloc_dc (instance->auth.DC_list, id, tstrndup (ip, l2), port);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
2013-11-13 04:11:25 +04:00
case LOG_AUTH_KEY:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-13 04:11:25 +04:00
{
2014-08-22 17:05:29 +02:00
int num = *(bl->rptr ++);
2013-11-13 04:11:25 +04:00
assert (num >= 0 && num <= MAX_DC_ID);
2014-07-26 11:55:45 +02:00
assert (instance->auth.DC_list[num]);
2014-08-22 17:05:29 +02:00
instance->auth.DC_list[num]->auth_key_id = *(long long *)bl->rptr;
bl->rptr += 2;
memcpy (instance->auth.DC_list[num]->auth_key, bl->rptr, 256);
bl->rptr += 64;
2014-07-26 11:55:45 +02:00
instance->auth.DC_list[num]->flags |= 1;
2013-11-13 04:11:25 +04:00
};
2013-11-21 23:35:49 +04:00
break;
2013-11-13 04:11:25 +04:00
case LOG_DEFAULT_DC:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-13 04:11:25 +04:00
{
2014-08-22 17:05:29 +02:00
int num = *(bl->rptr ++);
2013-11-13 04:11:25 +04:00
assert (num >= 0 && num <= MAX_DC_ID);
2014-07-26 11:55:45 +02:00
instance->auth.dc_working_num = num;
2013-11-13 04:11:25 +04:00
}
2013-11-21 23:35:49 +04:00
break;
case LOG_OUR_ID:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-09-01 21:25:41 +02:00
instance->our_id = *(bl->rptr ++);
}
break;
case LOG_DC_SIGNED:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
int num = *(bl->rptr ++);
assert (num >= 0 && num <= MAX_DC_ID);
2014-07-26 11:55:45 +02:00
assert (instance->auth.DC_list[num]);
instance->auth.DC_list[num]->has_auth = 1;
}
break;
case LOG_DC_SALT:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
int num = *(bl->rptr ++);
assert (num >= 0 && num <= MAX_DC_ID);
2014-07-26 11:55:45 +02:00
assert (instance->auth.DC_list[num]);
2014-08-22 17:05:29 +02:00
instance->auth.DC_list[num]->server_salt = *(long long *)bl->rptr;
bl->rptr += 2;
};
break;
2014-07-26 11:55:45 +02:00
// case CODE_user_empty:
// case CODE_user_self:
// case CODE_user_contact:
// case CODE_user_request:
// case CODE_user_foreign:
case CODE_user_deleted:
2014-08-06 19:45:46 +02:00
fetch_alloc_user (self);
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2014-07-26 11:55:45 +02:00
break;
case LOG_DH_CONFIG:
get_dh_config_on_answer (0);
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_KEY:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
assert (U);
2014-08-22 17:05:29 +02:00
U->key_fingerprint = *(long long *)bl->rptr;
bl->rptr += 2;
memcpy (U->key, bl->rptr, 256);
bl->rptr += 64;
};
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_SEND_ACCEPT:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
assert (U);
2014-08-22 17:05:29 +02:00
U->key_fingerprint = *(long long *)bl->rptr;
bl->rptr += 2;
memcpy (U->key, bl->rptr, 256);
bl->rptr += 64;
if (!U->g_key) {
U->g_key = talloc (256);
}
2014-08-22 17:05:29 +02:00
memcpy (U->g_key, bl->rptr, 256);
bl->rptr += 64;
};
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_SEND_CREATE:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (!U || !(U->flags & FLAG_CREATED));
if (!U) {
U = talloc0 (sizeof (peer_t));
U->id = id;
2014-09-01 21:25:41 +02:00
insert_encrypted_chat (bl, (void *)U);
}
U->flags |= FLAG_CREATED;
2014-08-22 17:05:29 +02:00
U->user_id = *(bl->rptr ++);
memcpy (U->key, bl->rptr, 256);
bl->rptr += 64;
if (!U->print_name) {
2014-09-01 21:25:41 +02:00
peer_t *P = user_chat_get (bl, MK_USER (U->user_id));
if (P) {
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, U->id, "!", P->user.first_name, P->user.last_name, 0);
} else {
static char buf[100];
tsnprintf (buf, 99, "user#%d", U->user_id);
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, U->id, "!", buf, 0, 0);
}
2014-09-01 21:25:41 +02:00
peer_insert_name (bl, (void *)U);
}
};
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_DELETED:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
if (!U) {
U = talloc0 (sizeof (peer_t));
U->id = id;
2014-09-01 21:25:41 +02:00
insert_encrypted_chat (bl, (void *)U);
}
U->flags |= FLAG_CREATED;
U->state = sc_deleted;
};
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_WAITING:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
assert (U);
U->state = sc_waiting;
2014-08-22 17:05:29 +02:00
U->date = *(bl->rptr ++);
U->admin_id = *(bl->rptr ++);
U->user_id = *(bl->rptr ++);
U->access_hash = *(long long *)bl->rptr;
bl->rptr += 2;
};
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_REQUESTED:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
if (!U) {
U = talloc0 (sizeof (peer_t));
U->id = id;
2014-09-01 21:25:41 +02:00
insert_encrypted_chat (bl, (void *)U);
}
U->flags |= FLAG_CREATED;
U->state = sc_request;
2014-08-22 17:05:29 +02:00
U->date = *(bl->rptr ++);
U->admin_id = *(bl->rptr ++);
U->user_id = *(bl->rptr ++);
U->access_hash = *(long long *)bl->rptr;
if (!U->print_name) {
2014-09-01 21:25:41 +02:00
peer_t *P = user_chat_get (bl, MK_USER (U->user_id));
if (P) {
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, U->id, "!", P->user.first_name, P->user.last_name, 0);
} else {
static char buf[100];
tsnprintf (buf, 99, "user#%d", U->user_id);
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, U->id, "!", buf, 0, 0);
}
2014-09-01 21:25:41 +02:00
peer_insert_name (bl, (void *)U);
}
2014-08-22 17:05:29 +02:00
bl->rptr += 2;
};
2013-11-21 23:35:49 +04:00
break;
case LOG_ENCR_CHAT_OK:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
struct secret_chat *U = (void *)user_chat_get (bl, id);
assert (U);
U->state = sc_ok;
}
2013-11-21 23:35:49 +04:00
break;
case CODE_binlog_new_user:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-06 19:45:46 +02:00
peer_id_t id = MK_USER (fetch_int (self));
2014-09-01 21:25:41 +02:00
peer_t *_U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
if (!_U) {
_U = talloc0 (sizeof (*_U));
2013-11-21 23:35:49 +04:00
_U->id = id;
2014-09-01 21:25:41 +02:00
insert_user (bl, _U);
2013-11-21 23:35:49 +04:00
} else {
assert (!(_U->flags & FLAG_CREATED));
}
struct user *U = (void *)_U;
U->flags |= FLAG_CREATED;
2014-09-01 21:25:41 +02:00
if (get_peer_id (id) == instance->our_id) {
2013-11-21 23:35:49 +04:00
U->flags |= FLAG_USER_SELF;
}
2014-08-06 19:45:46 +02:00
U->first_name = fetch_str_dup (self);
U->last_name = fetch_str_dup (self);
2014-01-31 20:03:40 +04:00
assert (!U->print_name);
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, U->id, U->first_name, U->last_name, 0, 0);
peer_insert_name (bl, (void *)U);
2014-08-06 19:45:46 +02:00
U->access_hash = fetch_long (self);
U->phone = fetch_str_dup (self);
if (fetch_int (self)) {
2013-11-21 23:35:49 +04:00
U->flags |= FLAG_USER_CONTACT;
}
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
case CODE_binlog_user_delete:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_USER (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
U->flags |= FLAG_DELETED;
}
break;
case CODE_binlog_set_user_access_token:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_USER (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
2014-08-22 17:05:29 +02:00
U->user.access_hash = *(long long *)bl->rptr;
bl->rptr += 2;
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_set_user_phone:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-06 19:45:46 +02:00
peer_id_t id = MK_USER (fetch_int (self));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
if (U->user.phone) { tfree_str (U->user.phone); }
2014-08-06 19:45:46 +02:00
U->user.phone = fetch_str_dup (self);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
case CODE_binlog_set_user_friend:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_USER (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
2014-08-22 17:05:29 +02:00
int friend = *(bl->rptr ++);
2013-11-21 23:35:49 +04:00
if (friend) { U->flags |= FLAG_USER_CONTACT; }
else { U->flags &= ~FLAG_USER_CONTACT; }
}
break;
case CODE_binlog_user_full_photo:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-06 19:45:46 +02:00
peer_id_t id = MK_USER (fetch_int (self));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
if (U->flags & FLAG_HAS_PHOTO) {
free_photo (&U->user.photo);
}
2014-08-06 19:45:46 +02:00
fetch_photo (self, &U->user.photo);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
case CODE_binlog_user_blocked:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_USER (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
2014-08-22 17:05:29 +02:00
U->user.blocked = *(bl->rptr ++);
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_set_user_full_name:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-06 19:45:46 +02:00
peer_id_t id = MK_USER (fetch_int (self));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
if (U->user.real_first_name) { tfree_str (U->user.real_first_name); }
if (U->user.real_last_name) { tfree_str (U->user.real_last_name); }
2014-08-06 19:45:46 +02:00
U->user.real_first_name = fetch_str_dup (self);
U->user.real_last_name = fetch_str_dup (self);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
case CODE_binlog_encr_chat_delete:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *_U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (_U);
struct secret_chat *U = &_U->encr_chat;
memset (U->key, 0, sizeof (U->key));
U->flags |= FLAG_DELETED;
U->state = sc_deleted;
if (U->nonce) {
tfree_secure (U->nonce, 256);
2013-11-21 23:35:49 +04:00
U->nonce = 0;
}
if (U->g_key) {
tfree_secure (U->g_key, 256);
2013-11-21 23:35:49 +04:00
U->g_key = 0;
}
}
break;
case CODE_binlog_encr_chat_requested:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *_U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
if (!_U) {
_U = talloc0 (sizeof (*_U));
2013-11-21 23:35:49 +04:00
_U->id = id;
2014-09-01 21:25:41 +02:00
insert_encrypted_chat (bl, _U);
2013-11-21 23:35:49 +04:00
} else {
assert (!(_U->flags & FLAG_CREATED));
}
struct secret_chat *U = (void *)_U;
2014-08-22 17:05:29 +02:00
U->access_hash = *(long long *)bl->rptr;
bl->rptr += 2;
U->date = *(bl->rptr ++);
U->admin_id = *(bl->rptr ++);
U->user_id = *(bl->rptr ++);
2014-09-01 21:25:41 +02:00
peer_t *Us = user_chat_get (bl, MK_USER (U->user_id));
2014-01-31 20:03:40 +04:00
assert (!U->print_name);
2013-11-21 23:35:49 +04:00
if (Us) {
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, id, "!", Us->user.first_name, Us->user.last_name, 0);
2013-11-21 23:35:49 +04:00
} else {
static char buf[100];
tsnprintf (buf, 99, "user#%d", U->user_id);
2014-09-01 21:25:41 +02:00
U->print_name = create_print_name (bl, id, "!", buf, 0, 0);
2013-11-21 23:35:49 +04:00
}
2014-09-01 21:25:41 +02:00
peer_insert_name (bl, (void *)U);
U->g_key = talloc (256);
U->nonce = talloc (256);
2014-08-22 17:05:29 +02:00
memcpy (U->g_key, bl->rptr, 256);
bl->rptr += 64;
memcpy (U->nonce, bl->rptr, 256);
bl->rptr += 64;
2013-11-21 23:35:49 +04:00
U->flags |= FLAG_CREATED;
U->state = sc_request;
}
break;
case CODE_binlog_set_encr_chat_access_hash:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
2014-08-22 17:05:29 +02:00
U->encr_chat.access_hash = *(long long *)bl->rptr;
bl->rptr += 2;
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_set_encr_chat_date:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
2014-08-22 17:05:29 +02:00
U->encr_chat.date = *(bl->rptr ++);
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_set_encr_chat_state:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (U);
2014-08-22 17:05:29 +02:00
U->encr_chat.state = *(bl->rptr ++);
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_encr_chat_accepted:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *_U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (_U);
struct secret_chat *U = &_U->encr_chat;
if (!U->g_key) {
U->g_key = talloc (256);
2013-11-21 23:35:49 +04:00
}
if (!U->nonce) {
U->nonce = talloc (256);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
memcpy (U->g_key, bl->rptr, 256);
bl->rptr += 64;
memcpy (U->nonce, bl->rptr, 256);
bl->rptr += 64;
U->key_fingerprint = *(long long *)bl->rptr;
bl->rptr += 2;
2013-11-21 23:35:49 +04:00
if (U->state == sc_waiting) {
2014-09-01 21:25:41 +02:00
do_create_keys_end (instance, U);
2013-11-21 23:35:49 +04:00
}
U->state = sc_ok;
}
break;
case CODE_binlog_set_encr_chat_key:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *_U = user_chat_get (bl, id);
2013-11-21 23:35:49 +04:00
assert (_U);
struct secret_chat *U = &_U->encr_chat;
2014-08-22 17:05:29 +02:00
memcpy (U->key, bl->rptr, 256);
bl->rptr += 64;
U->key_fingerprint = *(long long *)bl->rptr;
bl->rptr += 2;
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_set_dh_params:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
2014-09-01 21:25:41 +02:00
if (instance->encr_prime) { tfree (instance->encr_prime, 256); }
instance->encr_root = *(bl->rptr ++);
instance->encr_prime = talloc (256);
memcpy (instance->encr_prime, bl->rptr, 256);
2014-08-22 17:05:29 +02:00
bl->rptr += 64;
2014-09-01 21:25:41 +02:00
instance->encr_param_version = *(bl->rptr ++);
2013-11-21 23:35:49 +04:00
}
break;
case CODE_binlog_encr_chat_init:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-21 23:35:49 +04:00
{
peer_t *P = talloc0 (sizeof (*P));
2014-08-22 17:05:29 +02:00
P->id = MK_ENCR_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
assert (!user_chat_get (bl, P->id));
2014-08-22 17:05:29 +02:00
P->encr_chat.user_id = *(bl->rptr ++);
2014-09-01 21:25:41 +02:00
P->encr_chat.admin_id = instance->our_id;
insert_encrypted_chat (bl, P);
peer_t *Us = user_chat_get (bl, MK_USER (P->encr_chat.user_id));
2013-11-21 23:35:49 +04:00
assert (Us);
2014-09-01 21:25:41 +02:00
P->print_name = create_print_name (bl, P->id, "!", Us->user.first_name, Us->user.last_name, 0);
peer_insert_name (bl, P);
2014-08-22 17:05:29 +02:00
memcpy (P->encr_chat.key, bl->rptr, 256);
bl->rptr += 64;
P->encr_chat.g_key = talloc (256);
2014-08-22 17:05:29 +02:00
memcpy (P->encr_chat.g_key, bl->rptr, 256);
bl->rptr += 64;
2013-11-21 23:35:49 +04:00
P->flags |= FLAG_CREATED;
}
break;
case CODE_binlog_set_pts:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2014-09-01 21:25:41 +02:00
instance->proto.pts = *(bl->rptr ++);
break;
case CODE_binlog_set_qts:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2014-09-01 21:25:41 +02:00
instance->proto.qts = *(bl->rptr ++);
break;
case CODE_binlog_set_date:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2014-09-01 21:25:41 +02:00
instance->proto.last_date = *(bl->rptr ++);
break;
case CODE_binlog_set_seq:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2014-09-01 21:25:41 +02:00
instance->proto.seq = *(bl->rptr ++);
break;
2013-11-23 03:26:35 +04:00
case CODE_binlog_chat_create:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-23 03:26:35 +04:00
{
2014-08-06 19:45:46 +02:00
peer_id_t id = MK_CHAT (fetch_int (self));
2014-09-01 21:25:41 +02:00
peer_t *_C = user_chat_get (bl, id);
2013-11-23 03:26:35 +04:00
if (!_C) {
_C = talloc0 (sizeof (*_C));
2013-11-23 03:26:35 +04:00
_C->id = id;
2014-09-01 21:25:41 +02:00
insert_chat (bl, _C);
2013-11-23 03:26:35 +04:00
} else {
assert (!(_C->flags & FLAG_CREATED));
}
struct chat *C = &_C->chat;
2014-08-06 19:45:46 +02:00
C->flags = FLAG_CREATED | fetch_int (self);
C->title = fetch_str_dup (self);
2014-01-31 20:03:40 +04:00
assert (!C->print_title);
2014-09-01 21:25:41 +02:00
C->print_title = create_print_name (bl, id, C->title, 0, 0, 0);
peer_insert_name (bl, (void *)C);
2014-08-06 19:45:46 +02:00
C->users_num = fetch_int (self);
C->date = fetch_int (self);
C->version = fetch_int (self);
fetch_data (self, &C->photo_big, sizeof (struct file_location));
fetch_data (self, &C->photo_small, sizeof (struct file_location));
2013-11-23 03:26:35 +04:00
};
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-23 03:26:35 +04:00
break;
case CODE_binlog_chat_change_flags:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-23 03:26:35 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *C = user_chat_get (bl, MK_CHAT (*(bl->rptr ++)));
2013-11-23 03:26:35 +04:00
assert (C && (C->flags & FLAG_CREATED));
2014-08-22 17:05:29 +02:00
C->flags |= *(bl->rptr ++);
C->flags &= ~*(bl->rptr ++);
2013-11-23 03:26:35 +04:00
};
break;
case CODE_binlog_set_chat_title:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-23 03:26:35 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *_C = user_chat_get (bl, MK_CHAT (fetch_int (self)));
2013-11-23 03:26:35 +04:00
assert (_C && (_C->flags & FLAG_CREATED));
struct chat *C = &_C->chat;
if (C->title) { tfree_str (C->title); }
2014-08-06 19:45:46 +02:00
C->title = fetch_str_dup (self);
2014-01-31 20:03:40 +04:00
if (C->print_title) {
2014-09-01 21:25:41 +02:00
peer_delete_name (bl, (void *)C);
2014-01-31 20:03:40 +04:00
tfree_str (C->print_title);
}
2014-09-01 21:25:41 +02:00
C->print_title = create_print_name (bl, C->id, C->title, 0, 0, 0);
peer_insert_name (bl, (void *)C);
2013-11-23 03:26:35 +04:00
};
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-23 03:26:35 +04:00
break;
case CODE_binlog_set_chat_photo:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-23 03:26:35 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *C = user_chat_get (bl, MK_CHAT (fetch_int (self)));
2013-11-23 03:26:35 +04:00
assert (C && (C->flags & FLAG_CREATED));
2014-08-06 19:45:46 +02:00
fetch_data (self, &C->photo_big, sizeof (struct file_location));
fetch_data (self, &C->photo_small, sizeof (struct file_location));
2013-11-23 03:26:35 +04:00
};
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-23 03:26:35 +04:00
break;
case CODE_binlog_set_chat_date:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-23 03:26:35 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *C = user_chat_get (bl, MK_CHAT (*(bl->rptr ++)));
2013-11-23 03:26:35 +04:00
assert (C && (C->flags & FLAG_CREATED));
2014-08-22 17:05:29 +02:00
C->chat.date = *(bl->rptr ++);
2013-11-23 03:26:35 +04:00
};
break;
case CODE_binlog_set_chat_version:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-23 03:26:35 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *C = user_chat_get (bl, MK_CHAT (*(bl->rptr ++)));
2013-11-23 03:26:35 +04:00
assert (C && (C->flags & FLAG_CREATED));
2014-08-22 17:05:29 +02:00
C->chat.version = *(bl->rptr ++);
C->chat.users_num = *(bl->rptr ++);
2013-11-23 03:26:35 +04:00
};
break;
2013-11-25 20:13:36 +04:00
case CODE_binlog_set_chat_admin:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-25 20:13:36 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *C = user_chat_get (bl, MK_CHAT (*(bl->rptr ++)));
2013-11-25 20:13:36 +04:00
assert (C && (C->flags & FLAG_CREATED));
2014-08-22 17:05:29 +02:00
C->chat.admin_id = *(bl->rptr ++);
2013-11-25 20:13:36 +04:00
};
break;
case CODE_binlog_set_chat_participants:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-25 20:13:36 +04:00
{
2014-09-01 21:25:41 +02:00
peer_t *C = user_chat_get (bl, MK_CHAT (*(bl->rptr ++)));
2013-11-25 20:13:36 +04:00
assert (C && (C->flags & FLAG_CREATED));
2014-08-22 17:05:29 +02:00
C->chat.user_list_version = *(bl->rptr ++);
if (C->chat.user_list) { tfree (C->chat.user_list, 12 * C->chat.user_list_size); }
2014-08-22 17:05:29 +02:00
C->chat.user_list_size = *(bl->rptr ++);
C->chat.user_list = talloc (12 * C->chat.user_list_size);
2014-08-22 17:05:29 +02:00
memcpy (C->chat.user_list, bl->rptr, 12 * C->chat.user_list_size);
bl->rptr += 3 * C->chat.user_list_size;
2013-11-25 20:13:36 +04:00
};
break;
case CODE_binlog_chat_full_photo:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
2013-11-25 20:13:36 +04:00
{
2014-08-06 19:45:46 +02:00
peer_id_t id = MK_CHAT (fetch_int (self));
2014-09-01 21:25:41 +02:00
peer_t *U = user_chat_get (bl, id);
2013-11-25 20:13:36 +04:00
assert (U && (U->flags & FLAG_CREATED));
if (U->flags & FLAG_HAS_PHOTO) {
free_photo (&U->chat.photo);
}
2014-08-06 19:45:46 +02:00
fetch_photo (self, &U->chat.photo);
2013-11-25 20:13:36 +04:00
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-25 20:13:36 +04:00
break;
case CODE_binlog_add_chat_participant:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-25 20:13:36 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *_C = user_chat_get (bl, id);
2013-11-25 20:13:36 +04:00
assert (_C && (_C->flags & FLAG_CREATED));
struct chat *C = &_C->chat;
2014-08-22 17:05:29 +02:00
int version = *(bl->rptr ++);
int user = *(bl->rptr ++);
int inviter = *(bl->rptr ++);
int date = *(bl->rptr ++);
2013-11-25 20:13:36 +04:00
assert (C->user_list_version < version);
int i;
for (i = 0; i < C->user_list_size; i++) {
assert (C->user_list[i].user_id != user);
}
C->user_list_size ++;
C->user_list = trealloc (C->user_list, 12 * C->user_list_size - 12, 12 * C->user_list_size);
2013-11-25 20:13:36 +04:00
C->user_list[C->user_list_size - 1].user_id = user;
C->user_list[C->user_list_size - 1].inviter_id = inviter;
C->user_list[C->user_list_size - 1].date = date;
C->user_list_version = version;
}
break;
case CODE_binlog_del_chat_participant:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-11-25 20:13:36 +04:00
{
2014-08-22 17:05:29 +02:00
peer_id_t id = MK_CHAT (*(bl->rptr ++));
2014-09-01 21:25:41 +02:00
peer_t *_C = user_chat_get (bl, id);
2013-11-25 20:13:36 +04:00
assert (_C && (_C->flags & FLAG_CREATED));
struct chat *C = &_C->chat;
2014-08-22 17:05:29 +02:00
int version = *(bl->rptr ++);
int user = *(bl->rptr ++);
2013-11-25 20:13:36 +04:00
assert (C->user_list_version < version);
int i;
for (i = 0; i < C->user_list_size; i++) {
if (C->user_list[i].user_id == user) {
struct chat_user t;
t = C->user_list[i];
C->user_list[i] = C->user_list[C->user_list_size - 1];
C->user_list[C->user_list_size - 1] = t;
}
}
assert (C->user_list[C->user_list_size - 1].user_id == user);
C->user_list_size --;
C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size);
2013-11-25 20:13:36 +04:00
C->user_list_version = version;
}
break;
case CODE_binlog_create_message_text:
case CODE_binlog_send_message_text:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
long long id;
if (op == CODE_binlog_create_message_text) {
2014-08-06 19:45:46 +02:00
id = fetch_int (self);
} else {
2014-08-06 19:45:46 +02:00
id = fetch_long (self);
}
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
2014-09-01 21:25:41 +02:00
M->instance = instance;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
2014-09-08 23:09:20 +02:00
event_update_new_message (instance, M);
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
if (t == PEER_ENCR_CHAT) {
M->flags |= FLAG_ENCRYPTED;
}
2014-08-06 19:45:46 +02:00
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
2014-08-06 19:45:46 +02:00
int l = prefetch_strlen (self);
M->message = talloc (l + 1);
2014-08-06 19:45:46 +02:00
memcpy (M->message, fetch_str (self, l), l);
M->message[l] = 0;
M->message_len = l;
if (t == PEER_ENCR_CHAT) {
M->media.type = CODE_decrypted_message_media_empty;
} else {
M->media.type = CODE_message_media_empty;
}
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
message_insert (M);
if (op == CODE_binlog_send_message_text) {
message_insert_unsent (M);
M->flags |= FLAG_PENDING;
}
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_text_fwd:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
int id = fetch_int (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
M->fwd_from_id = MK_USER (fetch_int (self));
M->fwd_date = fetch_int (self);
2014-08-06 19:45:46 +02:00
int l = prefetch_strlen (self);
M->message = talloc (l + 1);
2014-08-06 19:45:46 +02:00
memcpy (M->message, fetch_str (self, l), l);
M->message[l] = 0;
M->message_len = l;
M->media.type = CODE_message_media_empty;
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_media:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
int id = fetch_int (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
2014-08-06 19:45:46 +02:00
int l = prefetch_strlen (self);
M->message = talloc (l + 1);
2014-08-06 19:45:46 +02:00
memcpy (M->message, fetch_str (self, l), l);
M->message[l] = 0;
M->message_len = l;
2014-08-06 19:45:46 +02:00
fetch_message_media (self, &M->media);
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_media_encr:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
long long id = fetch_long (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED | FLAG_ENCRYPTED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
2014-08-06 19:45:46 +02:00
int l = prefetch_strlen (self);
M->message = talloc (l + 1);
2014-08-06 19:45:46 +02:00
memcpy (M->message, fetch_str (self, l), l);
M->message[l] = 0;
M->message_len = l;
2014-08-06 19:45:46 +02:00
fetch_message_media_encrypted (self, &M->media);
fetch_encrypted_message_file (self, &M->media);
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_media_fwd:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
int id = fetch_int (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
M->fwd_from_id = MK_USER (fetch_int (self));
M->fwd_date = fetch_int (self);
2014-08-06 19:45:46 +02:00
int l = prefetch_strlen (self);
M->message = talloc (l + 1);
2014-08-06 19:45:46 +02:00
memcpy (M->message, fetch_str (self, l), l);
M->message[l] = 0;
M->message_len = l;
2014-08-06 19:45:46 +02:00
fetch_message_media (self, &M->media);
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_service:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
int id = fetch_int (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
2014-08-06 19:45:46 +02:00
fetch_message_action (self, &M->action);
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
M->service = 1;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_service_encr:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
long long id = fetch_long (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED | FLAG_ENCRYPTED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
2014-08-06 19:45:46 +02:00
fetch_message_action_encrypted (self, &M->action);
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
M->service = 1;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_create_message_service_fwd:
2014-08-06 19:45:46 +02:00
self->in_ptr ++;
{
2014-08-06 19:45:46 +02:00
int id = fetch_int (self);
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, id);
if (!M) {
M = talloc0 (sizeof (*M));
M->id = id;
message_insert_tree (M);
2014-09-01 21:25:41 +02:00
bl->messages_allocated ++;
} else {
assert (!(M->flags & FLAG_CREATED));
}
M->flags |= FLAG_CREATED;
2014-08-06 19:45:46 +02:00
M->from_id = MK_USER (fetch_int (self));
int t = fetch_int (self);
M->to_id = set_peer_id (t, fetch_int (self));
M->date = fetch_int (self);
M->fwd_from_id = MK_USER (fetch_int (self));
M->fwd_date = fetch_int (self);
fetch_message_action (self, &M->action);
M->unread = 1;
2014-09-01 21:25:41 +02:00
M->out = get_peer_id (M->from_id) == instance->our_id;
M->service = 1;
message_insert (M);
}
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
break;
case CODE_binlog_set_unread:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, *(bl->rptr ++));
assert (M);
M->unread = 0;
}
break;
case CODE_binlog_set_message_sent:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, *(long long *)bl->rptr);
2014-08-22 17:05:29 +02:00
bl->rptr += 2;
assert (M);
message_remove_unsent (M);
M->flags &= ~FLAG_PENDING;
}
break;
case CODE_binlog_set_msg_id:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
{
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, *(long long *)bl->rptr);
2014-08-22 17:05:29 +02:00
bl->rptr += 2;
assert (M);
2013-12-06 20:40:52 +04:00
if (M->flags & FLAG_PENDING) {
message_remove_unsent (M);
M->flags &= ~FLAG_PENDING;
}
message_remove_tree (M);
message_del_peer (M);
2014-08-22 17:05:29 +02:00
M->id = *(bl->rptr ++);
2014-09-01 21:25:41 +02:00
if (message_get(bl, M->id)) {
2013-12-02 21:19:08 +04:00
free_message (M);
tfree (M, sizeof (*M));
2013-12-02 21:19:08 +04:00
} else {
message_insert_tree (M);
message_add_peer (M);
}
}
break;
2013-12-06 21:14:41 +04:00
case CODE_binlog_delete_msg:
2014-08-22 17:05:29 +02:00
bl->rptr ++;
2013-12-06 21:14:41 +04:00
{
2014-09-01 21:25:41 +02:00
struct message *M = message_get(bl, *(long long *)bl->rptr);
2014-08-22 17:05:29 +02:00
bl->rptr += 2;
2013-12-06 21:14:41 +04:00
assert (M);
if (M->flags & FLAG_PENDING) {
message_remove_unsent (M);
M->flags &= ~FLAG_PENDING;
}
message_remove_tree (M);
message_del_peer (M);
2014-01-12 04:43:29 +04:00
message_del_use (M);
2013-12-06 21:14:41 +04:00
free_message (M);
tfree (M, sizeof (*M));
2013-12-06 21:14:41 +04:00
}
break;
2013-11-21 23:35:49 +04:00
case CODE_update_user_photo:
case CODE_update_user_name:
2014-08-06 19:45:46 +02:00
work_update_binlog (self);
2014-08-22 17:05:29 +02:00
bl->rptr = self->in_ptr;
2013-11-21 23:35:49 +04:00
break;
default:
2014-10-03 14:23:15 +02:00
debug ("Unknown logevent [0x%08x] 0x%08x [0x%08x] at %lld\n", *(bl->rptr - 1), op, *(bl->rptr + 1), bl->binlog_pos);
assert (0);
2013-11-13 04:11:25 +04:00
}
2013-11-21 23:35:49 +04:00
if (verbosity >= 2) {
2014-10-03 14:23:15 +02:00
debug ("Event end\n");
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
bl->in_replay_log = 0;
bl->binlog_pos += (bl->rptr - start) * 4;
2013-11-13 04:11:25 +04:00
}
2014-08-22 17:05:29 +02:00
void add_log_event (struct binlog *bl, struct mtproto_connection *self, const int *data, int len) {
2014-10-03 14:23:15 +02:00
debug ("Add log event: magic = 0x%08x, len = %d\n", data[0], len);
2014-07-29 15:28:04 +02:00
assert (!(len & 3));
2014-08-22 17:05:29 +02:00
if (bl->in_replay_log) { return; }
bl->rptr = (void *)data;
bl->wptr = bl->rptr + (len / 4);
2014-08-06 19:45:46 +02:00
int *in = self->in_ptr;
int *end = self->in_end;
2014-08-08 08:44:56 +02:00
replay_log_event (self->connection->instance);
2014-08-22 17:05:29 +02:00
if (bl->rptr != bl->wptr) {
2014-10-03 14:23:15 +02:00
debug ("Unread %lld ints. Len = %d\n", (long long)(bl->wptr - bl->rptr), len);
2014-08-22 17:05:29 +02:00
assert (bl->rptr == bl->wptr);
2014-07-29 15:28:04 +02:00
}
2014-08-22 17:05:29 +02:00
if (bl->binlog_enabled) {
assert (bl->binlog_fd > 0);
assert (write (bl->binlog_fd, data, len) == len);
2014-07-29 15:28:04 +02:00
}
2014-08-06 19:45:46 +02:00
self->in_ptr = in;
self->in_end = end;
2014-07-29 15:28:04 +02:00
}
void bl_do_set_auth_key_id (struct telegram *instance, int num, unsigned char *buf) {
2014-08-06 19:45:46 +02:00
struct mtproto_connection *self = instance->connection;
2014-08-22 17:05:29 +02:00
struct binlog *bl = instance->bl;
2014-08-06 19:45:46 +02:00
2013-11-21 23:35:49 +04:00
static unsigned char sha1_buffer[20];
SHA1 (buf, 256, sha1_buffer);
long long fingerprint = *(long long *)(sha1_buffer + 12);
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 8 + 8 + 256);
2013-11-21 23:35:49 +04:00
ev[0] = LOG_AUTH_KEY;
ev[1] = num;
*(long long *)(ev + 2) = fingerprint;
memcpy (ev + 4, buf, 256);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8 + 8 + 256);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_our_id (struct binlog *bl, struct mtproto_connection *self, int id) {
int *ev = alloc_log_event (bl, 8);
2013-11-21 23:35:49 +04:00
ev[0] = LOG_OUR_ID;
ev[1] = id;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_new_user (struct binlog *bl, struct mtproto_connection *self, int id, const char *f, int fl, const char *l, int ll,
2014-08-06 19:45:46 +02:00
long long access_token, const char *p, int pl, int contact) {
clear_packet (self);
out_int (self, CODE_binlog_new_user);
out_int (self, id);
out_cstring (self, f ? f : "", fl);
out_cstring (self, l ? l : "", ll);
out_long (self, access_token);
out_cstring (self, p ? p : "", pl);
out_int (self, contact);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_user_delete (struct binlog *bl, struct mtproto_connection *self, struct user *U) {
2013-11-21 23:35:49 +04:00
if (U->flags & FLAG_DELETED) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 8);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_user_delete;
ev[1] = get_peer_id (U->id);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_profile_photo (struct binlog *bl, struct mtproto_connection *self, struct user *U,
2014-08-06 19:45:46 +02:00
long long photo_id, struct file_location *big, struct file_location *small) {
2013-11-21 23:35:49 +04:00
if (photo_id == U->photo_id) { return; }
if (!photo_id) {
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 20);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_update_user_photo;
ev[1] = get_peer_id (U->id);
2014-09-01 21:25:41 +02:00
ev[2] = self->connection->instance->proto.last_date;
2013-11-21 23:35:49 +04:00
ev[3] = CODE_user_profile_photo_empty;
ev[4] = CODE_bool_false;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 20);
2013-11-21 23:35:49 +04:00
} else {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_update_user_photo);
out_int (self, get_peer_id (U->id));
2014-09-01 21:25:41 +02:00
out_int (self, self->connection->instance->proto.last_date);
2014-08-06 19:45:46 +02:00
out_int (self, CODE_user_profile_photo);
out_long (self, photo_id);
2013-11-21 23:35:49 +04:00
if (small->dc >= 0) {
2014-08-06 19:45:46 +02:00
out_int (self, CODE_file_location);
out_int (self, small->dc);
out_long (self, small->volume);
out_int (self, small->local_id);
out_long (self, small->secret);
2013-11-21 23:35:49 +04:00
} else {
2014-08-06 19:45:46 +02:00
out_int (self, CODE_file_location_unavailable);
out_long (self, small->volume);
out_int (self, small->local_id);
out_long (self, small->secret);
2013-11-21 23:35:49 +04:00
}
if (big->dc >= 0) {
2014-08-06 19:45:46 +02:00
out_int (self, CODE_file_location);
out_int (self, big->dc);
out_long (self, big->volume);
out_int (self, big->local_id);
out_long (self, big->secret);
2013-11-21 23:35:49 +04:00
} else {
2014-08-06 19:45:46 +02:00
out_int (self, CODE_file_location_unavailable);
out_long (self, big->volume);
out_int (self, big->local_id);
out_long (self, big->secret);
2013-11-21 23:35:49 +04:00
}
2014-08-06 19:45:46 +02:00
out_int (self, CODE_bool_false);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-21 23:35:49 +04:00
}
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_name (struct binlog *bl, struct mtproto_connection *self, struct user *U, const char *f,
2014-08-06 19:45:46 +02:00
int fl, const char *l, int ll) {
2013-11-21 23:35:49 +04:00
if ((U->first_name && (int)strlen (U->first_name) == fl && !strncmp (U->first_name, f, fl)) &&
(U->last_name && (int)strlen (U->last_name) == ll && !strncmp (U->last_name, l, ll))) {
return;
}
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_update_user_name);
out_int (self, get_peer_id (U->id));
out_cstring (self, f, fl);
out_cstring (self, l, ll);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_access_token (struct binlog *bl, struct mtproto_connection *self, struct user *U, long long access_token) {
2013-11-21 23:35:49 +04:00
if (U->access_hash == access_token) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_user_access_token;
ev[1] = get_peer_id (U->id);
*(long long *)(ev + 2) = access_token;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_phone (struct binlog *bl, struct mtproto_connection *self, struct user *U,
2014-08-06 19:45:46 +02:00
const char *p, int pl) {
2013-11-21 23:35:49 +04:00
if (U->phone && (int)strlen (U->phone) == pl && !strncmp (U->phone, p, pl)) {
return;
}
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_user_phone);
out_int (self, get_peer_id (U->id));
out_cstring (self, p, pl);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_friend (struct binlog *bl, struct mtproto_connection *self, struct user *U, int friend) {
2013-11-21 23:35:49 +04:00
if (friend == ((U->flags & FLAG_USER_CONTACT) != 0)) { return ; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_user_friend;
ev[1] = get_peer_id (U->id);
ev[2] = friend;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_dc_option (struct binlog *bl, struct mtproto_connection *self, int id, int l1, const char *name,
2014-08-06 19:45:46 +02:00
int l2, const char *ip, int port, struct telegram *instance) {
2014-07-26 11:55:45 +02:00
struct dc *DC = instance->auth.DC_list[id];
2013-11-21 23:35:49 +04:00
if (DC) { return; }
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_dc_option);
out_int (self, id);
out_cstring (self, name, l1);
out_cstring (self, ip, l2);
out_int (self, port);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_dc_signed (struct binlog *bl, struct mtproto_connection *self, int id) {
int *ev = alloc_log_event (bl, 8);
2013-11-21 23:35:49 +04:00
ev[0] = LOG_DC_SIGNED;
ev[1] = id;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_working_dc (struct binlog *bl, struct mtproto_connection *self, int num) {
int *ev = alloc_log_event (bl, 8);
2013-11-21 23:35:49 +04:00
ev[0] = LOG_DEFAULT_DC;
ev[1] = num;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_full_photo (struct binlog *bl, struct mtproto_connection *self, struct user *U, const int *start, int len) {
2013-11-21 23:35:49 +04:00
if (U->photo.id == *(long long *)(start + 1)) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, len + 8);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_user_full_photo;
ev[1] = get_peer_id (U->id);
memcpy (ev + 2, start, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, len + 8);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_blocked (struct binlog *bl, struct mtproto_connection *self, struct user *U, int blocked) {
2013-11-21 23:35:49 +04:00
if (U->blocked == blocked) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_user_blocked;
ev[1] = get_peer_id (U->id);
ev[2] = blocked;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_user_real_name (struct binlog *bl, struct mtproto_connection *self, struct user *U, const char *f, int fl, const char *l, int ll) {
2013-11-21 23:35:49 +04:00
if ((U->real_first_name && (int)strlen (U->real_first_name) == fl && !strncmp (U->real_first_name, f, fl)) &&
(U->real_last_name && (int)strlen (U->real_last_name) == ll && !strncmp (U->real_last_name, l, ll))) {
return;
}
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_user_full_name);
out_int (self, get_peer_id (U->id));
out_cstring (self, f, fl);
out_cstring (self, l, ll);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_encr_chat_delete (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U) {
2013-11-21 23:35:49 +04:00
if (!(U->flags & FLAG_CREATED) || U->state == sc_deleted || U->state == sc_none) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 8);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_encr_chat_delete;
ev[1] = get_peer_id (U->id);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_encr_chat_requested (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U,
2014-08-06 19:45:46 +02:00
long long access_hash, int date, int admin_id, int user_id, unsigned char g_key[],
unsigned char nonce[]) {
if (U->state != sc_none) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 540);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_encr_chat_requested;
ev[1] = get_peer_id (U->id);
*(long long *)(ev + 2) = access_hash;
ev[4] = date;
ev[5] = admin_id;
ev[6] = user_id;
memcpy (ev + 7, g_key, 256);
memcpy (ev + 7 + 64, nonce, 256);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 540);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_encr_chat_access_hash (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U,
2014-08-06 19:45:46 +02:00
long long access_hash) {
2013-11-21 23:35:49 +04:00
if (U->access_hash == access_hash) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_encr_chat_access_hash;
ev[1] = get_peer_id (U->id);
*(long long *)(ev + 2) = access_hash;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_encr_chat_date (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, int date) {
2013-11-21 23:35:49 +04:00
if (U->date == date) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_encr_chat_date;
ev[1] = get_peer_id (U->id);
ev[2] = date;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_encr_chat_state (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, enum secret_chat_state state) {
2013-11-21 23:35:49 +04:00
if (U->state == state) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_encr_chat_state;
ev[1] = get_peer_id (U->id);
ev[2] = state;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_encr_chat_accepted (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, const unsigned char g_key[], const unsigned char nonce[], long long key_fingerprint) {
2013-11-21 23:35:49 +04:00
if (U->state != sc_waiting && U->state != sc_request) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 528);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_encr_chat_accepted;
ev[1] = get_peer_id (U->id);
memcpy (ev + 2, g_key, 256);
memcpy (ev + 66, nonce, 256);
*(long long *)(ev + 130) = key_fingerprint;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 528);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_encr_chat_key (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *E, unsigned char key[], long long key_fingerprint) {
int *ev = alloc_log_event (bl, 272);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_encr_chat_key;
ev[1] = get_peer_id (E->id);
memcpy (ev + 2, key, 256);
*(long long *)(ev + 66) = key_fingerprint;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 272);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_dh_params (struct binlog *bl, struct mtproto_connection *self, int root, unsigned char prime[], int version) {
int *ev = alloc_log_event (bl, 268);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_set_dh_params;
ev[1] = root;
memcpy (ev + 2, prime, 256);
ev[66] = version;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 268);
2013-11-21 23:35:49 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_encr_chat_init (struct binlog *bl, struct mtproto_connection *self, int id, int user_id, unsigned char random[], unsigned char g_a[]) {
int *ev = alloc_log_event (bl, 524);
2013-11-21 23:35:49 +04:00
ev[0] = CODE_binlog_encr_chat_init;
ev[1] = id;
ev[2] = user_id;
memcpy (ev + 3, random, 256);
memcpy (ev + 67, g_a, 256);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 524);
2013-11-13 04:11:25 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_pts (struct binlog *bl, struct mtproto_connection *self, int pts) {
int *ev = alloc_log_event (bl, 8);
ev[0] = CODE_binlog_set_pts;
ev[1] = pts;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
}
2014-08-22 17:05:29 +02:00
void bl_do_set_qts (struct binlog *bl, struct mtproto_connection *self, int qts) {
int *ev = alloc_log_event (bl, 8);
ev[0] = CODE_binlog_set_qts;
ev[1] = qts;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
}
2014-08-22 17:05:29 +02:00
void bl_do_set_date (struct binlog *bl, struct mtproto_connection *self, int date) {
int *ev = alloc_log_event (bl, 8);
ev[0] = CODE_binlog_set_date;
ev[1] = date;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
}
2014-08-22 17:05:29 +02:00
void bl_do_set_seq (struct binlog *bl, struct mtproto_connection *self, int seq) {
int *ev = alloc_log_event (bl, 8);
ev[0] = CODE_binlog_set_seq;
ev[1] = seq;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 8);
}
2013-11-23 03:26:35 +04:00
2014-08-22 17:05:29 +02:00
void bl_do_create_chat (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int y, const char *s, int l, int users_num, int date, int version, struct file_location *big, struct file_location *small) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_chat_create);
out_int (self, get_peer_id (C->id));
out_int (self, y);
out_cstring (self, s, l);
out_int (self, users_num);
out_int (self, date);
out_int (self, version);
out_data (self, big, sizeof (struct file_location));
out_data (self, small, sizeof (struct file_location));
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-23 03:26:35 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_chat_forbid (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int on) {
2013-11-23 03:26:35 +04:00
if (on) {
if (C->flags & FLAG_FORBIDDEN) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-23 03:26:35 +04:00
ev[0] = CODE_binlog_chat_change_flags;
ev[1] = get_peer_id (C->id);
ev[2] = FLAG_FORBIDDEN;
ev[3] = 0;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-23 03:26:35 +04:00
} else {
if (!(C->flags & FLAG_FORBIDDEN)) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-23 03:26:35 +04:00
ev[0] = CODE_binlog_chat_change_flags;
ev[1] = get_peer_id (C->id);
ev[2] = 0;
ev[3] = FLAG_FORBIDDEN;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-23 03:26:35 +04:00
}
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_title (struct binlog *bl, struct mtproto_connection *self, struct chat *C, const char *s, int l) {
2013-11-23 03:26:35 +04:00
if (C->title && (int)strlen (C->title) == l && !strncmp (C->title, s, l)) { return; }
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_chat_title);
out_int (self, get_peer_id (C->id));
out_cstring (self, s, l);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-23 03:26:35 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_photo (struct binlog *bl, struct mtproto_connection *self, struct chat *C, struct file_location *big, struct file_location *small) {
2013-11-23 03:26:35 +04:00
if (!memcmp (&C->photo_small, small, sizeof (struct file_location)) &&
!memcmp (&C->photo_big, big, sizeof (struct file_location))) { return; }
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_chat_photo);
out_int (self, get_peer_id (C->id));
out_data (self, big, sizeof (struct file_location));
out_data (self, small, sizeof (struct file_location));
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-11-23 03:26:35 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_date (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int date) {
2013-11-23 03:26:35 +04:00
if (C->date == date) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12);
2013-11-23 03:26:35 +04:00
ev[0] = CODE_binlog_set_chat_date;
ev[1] = get_peer_id (C->id);
ev[2] = date;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12);
2013-11-23 03:26:35 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_set_in_chat (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int on) {
2013-11-23 03:26:35 +04:00
if (on) {
if (C->flags & FLAG_CHAT_IN_CHAT) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-23 03:26:35 +04:00
ev[0] = CODE_binlog_chat_change_flags;
ev[1] = get_peer_id (C->id);
ev[2] = FLAG_CHAT_IN_CHAT;
ev[3] = 0;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-23 03:26:35 +04:00
} else {
if (!(C->flags & FLAG_CHAT_IN_CHAT)) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-23 03:26:35 +04:00
ev[0] = CODE_binlog_chat_change_flags;
ev[1] = get_peer_id (C->id);
ev[2] = 0;
ev[3] = FLAG_CHAT_IN_CHAT;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-23 03:26:35 +04:00
}
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_version (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user_num) {
2013-11-23 03:26:35 +04:00
if (C->version >= version) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-23 03:26:35 +04:00
ev[0] = CODE_binlog_set_chat_version;
ev[1] = get_peer_id (C->id);
ev[2] = version;
ev[3] = user_num;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-23 03:26:35 +04:00
}
2013-11-25 20:13:36 +04:00
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_admin (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int admin) {
2013-11-25 20:13:36 +04:00
if (C->admin_id == admin) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12);
2013-11-25 20:13:36 +04:00
ev[0] = CODE_binlog_set_chat_admin;
ev[1] = get_peer_id (C->id);
ev[2] = admin;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12);
2013-11-25 20:13:36 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_participants (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user_num, struct chat_user *users) {
2013-11-25 20:13:36 +04:00
if (C->user_list_version >= version) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 12 * user_num + 16);
2013-11-25 20:13:36 +04:00
ev[0] = CODE_binlog_set_chat_participants;
ev[1] = get_peer_id (C->id);
ev[2] = version;
ev[3] = user_num;
memcpy (ev + 4, users, 12 * user_num);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 12 * user_num + 16);
2013-11-25 20:13:36 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_set_chat_full_photo (struct binlog *bl, struct mtproto_connection *self, struct chat *U, const int *start, int len) {
2013-11-25 20:13:36 +04:00
if (U->photo.id == *(long long *)(start + 1)) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, len + 8);
2013-11-25 20:13:36 +04:00
ev[0] = CODE_binlog_chat_full_photo;
ev[1] = get_peer_id (U->id);
memcpy (ev + 2, start, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, len + 8);
2013-11-25 20:13:36 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_chat_add_user (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user, int inviter, int date) {
2013-11-25 20:13:36 +04:00
if (C->user_list_version >= version || !C->user_list_version) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 24);
2013-11-25 20:13:36 +04:00
ev[0] = CODE_binlog_add_chat_participant;
ev[1] = get_peer_id (C->id);
ev[2] = version;
ev[3] = user;
ev[4] = inviter;
ev[5] = date;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 24);
2013-11-25 20:13:36 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_chat_del_user (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user) {
2013-11-25 20:13:36 +04:00
if (C->user_list_version >= version || !C->user_list_version) { return; }
2014-08-22 17:05:29 +02:00
int *ev = alloc_log_event (bl, 16);
2013-11-25 20:13:36 +04:00
ev[0] = CODE_binlog_add_chat_participant;
ev[1] = get_peer_id (C->id);
ev[2] = version;
ev[3] = user;
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, ev, 16);
2013-11-25 20:13:36 +04:00
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_text (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_text);
out_int (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_cstring (self, s, l);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_send_message_text (struct binlog *bl, struct mtproto_connection *self, long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_send_message_text);
out_long (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_cstring (self, s, l);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_text_fwd (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_text_fwd);
out_int (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_int (self, fwd);
out_int (self, fwd_date);
out_cstring (self, s, l);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_media (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_media);
out_int (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_cstring (self, s, l);
out_ints (self, data, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_media_encr (struct binlog *bl, struct mtproto_connection *self, long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len, const int *data2, int len2) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_media_encr);
out_long (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_cstring (self, s, l);
out_ints (self, data, len);
out_ints (self, data2, len2);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_media_fwd (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s, const int *data, int len) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_media_fwd);
out_int (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_int (self, fwd);
out_int (self, fwd_date);
out_cstring (self, s, l);
out_ints (self, data, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_service (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_service);
out_int (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_ints (self, data, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_service_encr (struct binlog *bl, struct mtproto_connection *self, long long msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_service_encr);
out_long (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_ints (self, data, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_create_message_service_fwd (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, const int *data, int len) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_create_message_service_fwd);
out_int (self, msg_id);
out_int (self, from_id);
out_int (self, to_type);
out_int (self, to_id);
out_int (self, date);
out_int (self, fwd);
out_int (self, fwd_date);
out_ints (self, data, len);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_set_unread (struct binlog *bl, struct mtproto_connection *self, struct message *M, int unread) {
if (unread || !M->unread) { return; }
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_unread);
out_int (self, M->id);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_set_message_sent (struct binlog *bl, struct mtproto_connection *self, struct message *M) {
if (!(M->flags & FLAG_PENDING)) { return; }
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_message_sent);
out_long (self, M->id);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2014-08-22 17:05:29 +02:00
void bl_do_set_msg_id (struct binlog *bl, struct mtproto_connection *self, struct message *M, int id) {
if (M->id == id) { return; }
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_set_msg_id);
out_long (self, M->id);
out_int (self, id);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
}
2013-12-06 21:14:41 +04:00
2014-08-22 17:05:29 +02:00
void bl_do_delete_msg (struct binlog *bl, struct mtproto_connection *self, struct message *M) {
2014-08-06 19:45:46 +02:00
clear_packet (self);
out_int (self, CODE_binlog_delete_msg);
out_long (self, M->id);
2014-08-22 17:05:29 +02:00
add_log_event (bl, self, self->packet_buffer, 4 * (self->packet_ptr - self->packet_buffer));
2013-12-06 21:14:41 +04:00
}