Partial support for binlog. It now can track user, secret chat and auth updates.
This commit is contained in:
parent
0d99482877
commit
8ad5053c66
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ DEFS=-DHAVE_CONFIG_H
|
|||||||
COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
|
COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
|
||||||
|
|
||||||
EXTRA_LIBS= -lreadline -lrt -lconfig
|
EXTRA_LIBS= -lreadline -lrt -lconfig
|
||||||
LOCAL_LDFLAGS=-lm -lcrypto -lz -lssl -rdynamic ${EXTRA_LIBS}
|
LOCAL_LDFLAGS=-lm -lcrypto -lz -lssl -rdynamic -ggdb ${EXTRA_LIBS}
|
||||||
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
|
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
|
||||||
|
|
||||||
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h
|
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h
|
||||||
|
@ -7,7 +7,7 @@ DEFS=@DEFS@
|
|||||||
COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
|
COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
|
||||||
|
|
||||||
EXTRA_LIBS=@EXTRA_LIBS@
|
EXTRA_LIBS=@EXTRA_LIBS@
|
||||||
LOCAL_LDFLAGS=-lm -lcrypto -lz -lssl -rdynamic ${EXTRA_LIBS}
|
LOCAL_LDFLAGS=-lm -lcrypto -lz -lssl -rdynamic -ggdb ${EXTRA_LIBS}
|
||||||
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
|
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
|
||||||
|
|
||||||
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h
|
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h
|
||||||
|
220
binlog.c
220
binlog.c
@ -11,10 +11,7 @@
|
|||||||
#include "binlog.h"
|
#include "binlog.h"
|
||||||
#include "mtproto-common.h"
|
#include "mtproto-common.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "include.h"
|
||||||
#define LOG_START 0x8948329a
|
|
||||||
#define LOG_AUTH_KEY 0x984932aa
|
|
||||||
#define LOG_DEFAULT_DC 0x95382908
|
|
||||||
|
|
||||||
#define BINLOG_BUFFER_SIZE (1 << 20)
|
#define BINLOG_BUFFER_SIZE (1 << 20)
|
||||||
int binlog_buffer[BINLOG_BUFFER_SIZE];
|
int binlog_buffer[BINLOG_BUFFER_SIZE];
|
||||||
@ -28,6 +25,14 @@ char *get_binlog_file_name (void);
|
|||||||
extern struct dc *DC_list[];
|
extern struct dc *DC_list[];
|
||||||
extern struct dc *DC_working;
|
extern struct dc *DC_working;
|
||||||
extern int dc_working_num;
|
extern int dc_working_num;
|
||||||
|
extern int our_id;
|
||||||
|
extern int binlog_enabled;
|
||||||
|
|
||||||
|
int in_replay_log;
|
||||||
|
|
||||||
|
void *alloc_log_event (int l UU) {
|
||||||
|
return binlog_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
void replay_log_event (void) {
|
void replay_log_event (void) {
|
||||||
assert (rptr < wptr);
|
assert (rptr < wptr);
|
||||||
@ -41,6 +46,7 @@ void replay_log_event (void) {
|
|||||||
return;
|
return;
|
||||||
case CODE_dc_option:
|
case CODE_dc_option:
|
||||||
fetch_dc_option ();
|
fetch_dc_option ();
|
||||||
|
rptr = in_ptr;
|
||||||
return;
|
return;
|
||||||
case LOG_AUTH_KEY:
|
case LOG_AUTH_KEY:
|
||||||
rptr ++;
|
rptr ++;
|
||||||
@ -52,6 +58,7 @@ void replay_log_event (void) {
|
|||||||
rptr += 2;
|
rptr += 2;
|
||||||
memcpy (DC_list[num]->auth_key, rptr, 256);
|
memcpy (DC_list[num]->auth_key, rptr, 256);
|
||||||
rptr += 64;
|
rptr += 64;
|
||||||
|
DC_list[num]->flags |= 1;
|
||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
case LOG_DEFAULT_DC:
|
case LOG_DEFAULT_DC:
|
||||||
@ -63,6 +70,180 @@ void replay_log_event (void) {
|
|||||||
dc_working_num = num;
|
dc_working_num = num;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
case LOG_OUR_ID:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
our_id = *(rptr ++);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOG_DC_SIGNED:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
int num = *(rptr ++);
|
||||||
|
assert (num >= 0 && num <= MAX_DC_ID);
|
||||||
|
assert (DC_list[num]);
|
||||||
|
DC_list[num]->has_auth = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOG_DC_SALT:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
int num = *(rptr ++);
|
||||||
|
assert (num >= 0 && num <= MAX_DC_ID);
|
||||||
|
assert (DC_list[num]);
|
||||||
|
DC_list[num]->server_salt = *(long long *)rptr;
|
||||||
|
rptr += 2;
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case CODE_user_empty:
|
||||||
|
case CODE_user_self:
|
||||||
|
case CODE_user_contact:
|
||||||
|
case CODE_user_request:
|
||||||
|
case CODE_user_foreign:
|
||||||
|
case CODE_user_deleted:
|
||||||
|
fetch_alloc_user ();
|
||||||
|
rptr = in_ptr;
|
||||||
|
return;
|
||||||
|
case LOG_DH_CONFIG:
|
||||||
|
get_dh_config_on_answer (0);
|
||||||
|
rptr = in_ptr;
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_KEY:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
assert (U);
|
||||||
|
U->key_fingerprint = *(long long *)rptr;
|
||||||
|
rptr += 2;
|
||||||
|
memcpy (U->key, rptr, 256);
|
||||||
|
rptr += 64;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_SEND_ACCEPT:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
assert (U);
|
||||||
|
U->key_fingerprint = *(long long *)rptr;
|
||||||
|
rptr += 2;
|
||||||
|
memcpy (U->key, rptr, 256);
|
||||||
|
rptr += 64;
|
||||||
|
if (!U->g_key) {
|
||||||
|
U->g_key = malloc (256);
|
||||||
|
}
|
||||||
|
memcpy (U->g_key, rptr, 256);
|
||||||
|
rptr += 64;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_SEND_CREATE:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
assert (!U || (U->flags & FLAG_EMPTY));
|
||||||
|
if (!U) {
|
||||||
|
U = malloc (sizeof (peer_t));
|
||||||
|
memset (U, 0, sizeof (peer_t));
|
||||||
|
U->id = id;
|
||||||
|
insert_encrypted_chat ((void *)U);
|
||||||
|
} else {
|
||||||
|
U->flags &= ~FLAG_EMPTY;
|
||||||
|
}
|
||||||
|
U->flags |= FLAG_CREATED;
|
||||||
|
U->user_id = *(rptr ++);
|
||||||
|
memcpy (U->key, rptr, 256);
|
||||||
|
rptr += 64;
|
||||||
|
if (!U->print_name) {
|
||||||
|
peer_t *P = user_chat_get (MK_USER (U->user_id));
|
||||||
|
if (P) {
|
||||||
|
U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0);
|
||||||
|
} else {
|
||||||
|
static char buf[100];
|
||||||
|
sprintf (buf, "user#%d", U->user_id);
|
||||||
|
U->print_name = create_print_name (U->id, "!", buf, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_DELETED:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
if (!U) {
|
||||||
|
U = malloc (sizeof (peer_t));
|
||||||
|
memset (U, 0, sizeof (peer_t));
|
||||||
|
U->id = id;
|
||||||
|
insert_encrypted_chat ((void *)U);
|
||||||
|
} else {
|
||||||
|
U->flags &= ~FLAG_EMPTY;
|
||||||
|
}
|
||||||
|
U->flags |= FLAG_CREATED;
|
||||||
|
U->state = sc_deleted;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_WAITING:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
assert (U);
|
||||||
|
U->state = sc_waiting;
|
||||||
|
U->date = *(rptr ++);
|
||||||
|
U->admin_id = *(rptr ++);
|
||||||
|
U->user_id = *(rptr ++);
|
||||||
|
U->access_hash = *(long long *)rptr;
|
||||||
|
rptr += 2;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_REQUESTED:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
if (!U) {
|
||||||
|
U = malloc (sizeof (peer_t));
|
||||||
|
memset (U, 0, sizeof (peer_t));
|
||||||
|
U->id = id;
|
||||||
|
insert_encrypted_chat ((void *)U);
|
||||||
|
} else {
|
||||||
|
U->flags &= ~FLAG_EMPTY;
|
||||||
|
}
|
||||||
|
U->flags |= FLAG_CREATED;
|
||||||
|
U->state = sc_request;
|
||||||
|
U->date = *(rptr ++);
|
||||||
|
U->admin_id = *(rptr ++);
|
||||||
|
U->user_id = *(rptr ++);
|
||||||
|
U->access_hash = *(long long *)rptr;
|
||||||
|
if (!U->print_name) {
|
||||||
|
peer_t *P = user_chat_get (MK_USER (U->user_id));
|
||||||
|
if (P) {
|
||||||
|
U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0);
|
||||||
|
} else {
|
||||||
|
static char buf[100];
|
||||||
|
sprintf (buf, "user#%d", U->user_id);
|
||||||
|
U->print_name = create_print_name (U->id, "!", buf, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rptr += 2;
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
case LOG_ENCR_CHAT_OK:
|
||||||
|
rptr ++;
|
||||||
|
{
|
||||||
|
peer_id_t id = MK_ENCR_CHAT (*(rptr ++));
|
||||||
|
struct secret_chat *U = (void *)user_chat_get (id);
|
||||||
|
assert (U);
|
||||||
|
U->state = sc_ok;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logprintf ("Unknown logevent [0x%08x] 0x%08x [0x%08x]\n", *(rptr - 1), op, *(rptr + 1));
|
||||||
|
|
||||||
|
assert (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,20 +252,27 @@ void create_new_binlog (void) {
|
|||||||
packet_ptr = s;
|
packet_ptr = s;
|
||||||
out_int (LOG_START);
|
out_int (LOG_START);
|
||||||
out_int (CODE_dc_option);
|
out_int (CODE_dc_option);
|
||||||
out_int (0);
|
out_int (1);
|
||||||
out_string ("");
|
out_string ("");
|
||||||
out_string (test_dc ? TG_SERVER_TEST : TG_SERVER);
|
out_string (test_dc ? TG_SERVER_TEST : TG_SERVER);
|
||||||
out_int (443);
|
out_int (443);
|
||||||
|
out_int (LOG_DEFAULT_DC);
|
||||||
|
out_int (1);
|
||||||
|
|
||||||
int fd = open (get_binlog_file_name (), O_WRONLY | O_EXCL);
|
int fd = open (get_binlog_file_name (), O_WRONLY | O_EXCL | O_CREAT, 0600);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror ("Write new binlog");
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
assert (write (fd, s, (packet_ptr - s) * 4) == (packet_ptr - s) * 4);
|
assert (write (fd, s, (packet_ptr - s) * 4) == (packet_ptr - s) * 4);
|
||||||
close (fd);
|
close (fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void replay_log (void) {
|
void replay_log (void) {
|
||||||
|
in_replay_log = 1;
|
||||||
if (access (get_binlog_file_name (), F_OK) < 0) {
|
if (access (get_binlog_file_name (), F_OK) < 0) {
|
||||||
printf ("No binlog found. Creating new one");
|
printf ("No binlog found. Creating new one\n");
|
||||||
create_new_binlog ();
|
create_new_binlog ();
|
||||||
}
|
}
|
||||||
int fd = open (get_binlog_file_name (), O_RDONLY);
|
int fd = open (get_binlog_file_name (), O_RDONLY);
|
||||||
@ -92,7 +280,7 @@ void replay_log (void) {
|
|||||||
perror ("binlog open");
|
perror ("binlog open");
|
||||||
exit (2);
|
exit (2);
|
||||||
}
|
}
|
||||||
int end;
|
int end = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!end && wptr - rptr < MAX_LOG_EVENT_SIZE / 4) {
|
if (!end && wptr - rptr < MAX_LOG_EVENT_SIZE / 4) {
|
||||||
if (wptr == rptr) {
|
if (wptr == rptr) {
|
||||||
@ -119,4 +307,20 @@ void replay_log (void) {
|
|||||||
replay_log_event ();
|
replay_log_event ();
|
||||||
}
|
}
|
||||||
close (fd);
|
close (fd);
|
||||||
|
in_replay_log = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int binlog_fd;
|
||||||
|
void write_binlog (void) {
|
||||||
|
binlog_fd = open (get_binlog_file_name (), O_WRONLY);
|
||||||
|
if (binlog_fd < 0) {
|
||||||
|
perror ("binlog open");
|
||||||
|
exit (2);
|
||||||
|
}
|
||||||
|
lseek (binlog_fd, 0, SEEK_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_log_event (const int *data, int len) {
|
||||||
|
if (in_replay_log) { return; }
|
||||||
|
assert (write (binlog_fd, data, len) == len);
|
||||||
}
|
}
|
||||||
|
17
binlog.h
17
binlog.h
@ -1,6 +1,23 @@
|
|||||||
#ifndef __BINLOG_H__
|
#ifndef __BINLOG_H__
|
||||||
#define __BINLOG_H__
|
#define __BINLOG_H__
|
||||||
|
|
||||||
|
#define LOG_START 0x8948329a
|
||||||
|
#define LOG_AUTH_KEY 0x984932aa
|
||||||
|
#define LOG_DEFAULT_DC 0x95382908
|
||||||
|
#define LOG_OUR_ID 0x8943211a
|
||||||
|
#define LOG_DC_SIGNED 0x234f9893
|
||||||
|
#define LOG_DC_SALT 0x92192ffa
|
||||||
|
#define LOG_DH_CONFIG 0x8983402b
|
||||||
|
#define LOG_ENCR_CHAT_KEY 0x894320aa
|
||||||
|
#define LOG_ENCR_CHAT_SEND_ACCEPT 0x12ab01c4
|
||||||
|
#define LOG_ENCR_CHAT_SEND_CREATE 0xab091e24
|
||||||
|
#define LOG_ENCR_CHAT_DELETED 0x99481230
|
||||||
|
#define LOG_ENCR_CHAT_WAITING 0x7102100a
|
||||||
|
#define LOG_ENCR_CHAT_REQUESTED 0x9011011a
|
||||||
|
#define LOG_ENCR_CHAT_OK 0x7612ce13
|
||||||
|
|
||||||
void *alloc_log_event (int l);
|
void *alloc_log_event (int l);
|
||||||
void replay_log (void);
|
void replay_log (void);
|
||||||
|
void add_log_event (const int *data, int l);
|
||||||
|
void write_binlog (void);
|
||||||
#endif
|
#endif
|
||||||
|
19
loop.c
19
loop.c
@ -160,6 +160,7 @@ void write_dc (int auth_file_fd, struct dc *DC) {
|
|||||||
|
|
||||||
int our_id;
|
int our_id;
|
||||||
void write_auth_file (void) {
|
void write_auth_file (void) {
|
||||||
|
if (binlog_enabled) { return; }
|
||||||
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
||||||
assert (auth_file_fd >= 0);
|
assert (auth_file_fd >= 0);
|
||||||
int x = DC_SERIALIZED_MAGIC_V2;
|
int x = DC_SERIALIZED_MAGIC_V2;
|
||||||
@ -216,6 +217,7 @@ void empty_auth_file (void) {
|
|||||||
|
|
||||||
int need_dc_list_update;
|
int need_dc_list_update;
|
||||||
void read_auth_file (void) {
|
void read_auth_file (void) {
|
||||||
|
if (binlog_enabled) { return; }
|
||||||
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
||||||
if (auth_file_fd < 0) {
|
if (auth_file_fd < 0) {
|
||||||
empty_auth_file ();
|
empty_auth_file ();
|
||||||
@ -308,6 +310,7 @@ extern unsigned char *encr_prime;
|
|||||||
extern int encr_param_version;
|
extern int encr_param_version;
|
||||||
|
|
||||||
void read_secret_chat_file (void) {
|
void read_secret_chat_file (void) {
|
||||||
|
if (binlog_enabled) { return; }
|
||||||
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
|
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return;
|
return;
|
||||||
@ -364,6 +367,7 @@ void read_secret_chat_file (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write_secret_chat_file (void) {
|
void write_secret_chat_file (void) {
|
||||||
|
if (binlog_enabled) { return; }
|
||||||
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
|
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return;
|
return;
|
||||||
@ -430,12 +434,15 @@ int loop (void) {
|
|||||||
on_start ();
|
on_start ();
|
||||||
if (binlog_enabled) {
|
if (binlog_enabled) {
|
||||||
replay_log ();
|
replay_log ();
|
||||||
|
write_binlog ();
|
||||||
|
} else {
|
||||||
|
read_auth_file ();
|
||||||
}
|
}
|
||||||
read_auth_file ();
|
|
||||||
update_prompt ();
|
update_prompt ();
|
||||||
|
|
||||||
assert (DC_list[dc_working_num]);
|
assert (DC_list[dc_working_num]);
|
||||||
if (auth_state == 0) {
|
if (!DC_working || !DC_working->auth_key_id) {
|
||||||
|
// if (auth_state == 0) {
|
||||||
DC_working = DC_list[dc_working_num];
|
DC_working = DC_list[dc_working_num];
|
||||||
assert (!DC_working->auth_key_id);
|
assert (!DC_working->auth_key_id);
|
||||||
dc_authorize (DC_working);
|
dc_authorize (DC_working);
|
||||||
@ -459,7 +466,7 @@ int loop (void) {
|
|||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auth_state == 100) {
|
if (auth_state == 100 || !(DC_working->has_auth)) {
|
||||||
if (!default_username) {
|
if (!default_username) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
char *user = 0;
|
char *user = 0;
|
||||||
@ -546,6 +553,12 @@ int loop (void) {
|
|||||||
do_export_auth (i);
|
do_export_auth (i);
|
||||||
do_import_auth (i);
|
do_import_auth (i);
|
||||||
DC_list[i]->has_auth = 1;
|
DC_list[i]->has_auth = 1;
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_DC_SIGNED;
|
||||||
|
ev[1] = i;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
}
|
}
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "structures.h"
|
#include "structures.h"
|
||||||
|
#include "binlog.h"
|
||||||
|
|
||||||
#define sha1 SHA1
|
#define sha1 SHA1
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ enum dc_state c_state;
|
|||||||
char nonce[256];
|
char nonce[256];
|
||||||
char new_nonce[256];
|
char new_nonce[256];
|
||||||
char server_nonce[256];
|
char server_nonce[256];
|
||||||
|
extern int binlog_enabled;
|
||||||
|
|
||||||
int rpc_execute (struct connection *c, int op, int len);
|
int rpc_execute (struct connection *c, int op, int len);
|
||||||
int rpc_becomes_ready (struct connection *c);
|
int rpc_becomes_ready (struct connection *c);
|
||||||
@ -509,6 +511,13 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
|
|||||||
sha1 (tmp, 41, sha1_buffer);
|
sha1 (tmp, 41, sha1_buffer);
|
||||||
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
|
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
|
||||||
GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce;
|
GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce;
|
||||||
|
/* if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (16);
|
||||||
|
ev[0] = LOG_DC_SALT;
|
||||||
|
ev[1] = GET_DC(c)->id;
|
||||||
|
*(long long *)(ev + 2) = GET_DC(c)->server_salt;
|
||||||
|
add_log_event (ev, 16);
|
||||||
|
}*/
|
||||||
if (verbosity >= 3) {
|
if (verbosity >= 3) {
|
||||||
logprintf ( "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id);
|
logprintf ( "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id);
|
||||||
}
|
}
|
||||||
@ -525,6 +534,15 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
|
|||||||
auth_success ++;
|
auth_success ++;
|
||||||
GET_DC(c)->flags |= 1;
|
GET_DC(c)->flags |= 1;
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8 + 8 + 256);
|
||||||
|
ev[0] = LOG_AUTH_KEY;
|
||||||
|
ev[1] = GET_DC(c)->id;
|
||||||
|
*(long long *)(ev + 2) = GET_DC(c)->auth_key_id;
|
||||||
|
memcpy (ev + 4, GET_DC(c)->auth_key, 256);
|
||||||
|
add_log_event (ev, 8 + 8 + 256);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -559,7 +577,7 @@ void init_enc_msg (struct session *S, int useful) {
|
|||||||
struct dc *DC = S->dc;
|
struct dc *DC = S->dc;
|
||||||
assert (DC->auth_key_id);
|
assert (DC->auth_key_id);
|
||||||
enc_msg.auth_key_id = DC->auth_key_id;
|
enc_msg.auth_key_id = DC->auth_key_id;
|
||||||
assert (DC->server_salt);
|
// assert (DC->server_salt);
|
||||||
enc_msg.server_salt = DC->server_salt;
|
enc_msg.server_salt = DC->server_salt;
|
||||||
if (!S->session_id) {
|
if (!S->session_id) {
|
||||||
assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0);
|
assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0);
|
||||||
@ -1213,6 +1231,14 @@ void work_new_session_created (struct connection *c, long long msg_id UU) {
|
|||||||
//DC->session_id = fetch_long ();
|
//DC->session_id = fetch_long ();
|
||||||
fetch_long (); // unique_id
|
fetch_long (); // unique_id
|
||||||
GET_DC(c)->server_salt = fetch_long ();
|
GET_DC(c)->server_salt = fetch_long ();
|
||||||
|
|
||||||
|
/* if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (16);
|
||||||
|
ev[0] = LOG_DC_SALT;
|
||||||
|
ev[1] = GET_DC(c)->id;
|
||||||
|
*(long long *)(ev + 2) = GET_DC(c)->server_salt;
|
||||||
|
add_log_event (ev, 16);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void work_msgs_ack (struct connection *c UU, long long msg_id UU) {
|
void work_msgs_ack (struct connection *c UU, long long msg_id UU) {
|
||||||
@ -1294,6 +1320,13 @@ void work_bad_server_salt (struct connection *c UU, long long msg_id UU) {
|
|||||||
fetch_int (); // error_code
|
fetch_int (); // error_code
|
||||||
long long new_server_salt = fetch_long ();
|
long long new_server_salt = fetch_long ();
|
||||||
GET_DC(c)->server_salt = new_server_salt;
|
GET_DC(c)->server_salt = new_server_salt;
|
||||||
|
/* if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (16);
|
||||||
|
ev[0] = LOG_DC_SALT;
|
||||||
|
ev[1] = GET_DC(c)->id;
|
||||||
|
*(long long *)(ev + 2) = GET_DC(c)->server_salt;
|
||||||
|
add_log_event (ev, 16);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void work_pong (struct connection *c UU, long long msg_id UU) {
|
void work_pong (struct connection *c UU, long long msg_id UU) {
|
||||||
@ -1389,6 +1422,13 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
|
|||||||
if (DC->server_salt != enc->server_salt) {
|
if (DC->server_salt != enc->server_salt) {
|
||||||
DC->server_salt = enc->server_salt;
|
DC->server_salt = enc->server_salt;
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
|
/* if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (16);
|
||||||
|
ev[0] = LOG_DC_SALT;
|
||||||
|
ev[1] = DC->id;
|
||||||
|
*(long long *)(ev + 2) = DC->server_salt;
|
||||||
|
add_log_event (ev, 16);
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int this_server_time = enc->msg_id >> 32LL;
|
int this_server_time = enc->msg_id >> 32LL;
|
||||||
@ -1475,7 +1515,11 @@ int rpc_execute (struct connection *c, int op, int len) {
|
|||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
case st_authorized:
|
case st_authorized:
|
||||||
process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/);
|
if (op < 0 && op >= -999) {
|
||||||
|
logprintf ("Server error %d\n", op);
|
||||||
|
} else {
|
||||||
|
process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/);
|
||||||
|
}
|
||||||
#ifndef __MACH__
|
#ifndef __MACH__
|
||||||
setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
||||||
#endif
|
#endif
|
||||||
|
@ -307,6 +307,53 @@ static inline char *fetch_str_dup (void) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int fetch_update_str (char **s) {
|
||||||
|
if (!*s) {
|
||||||
|
*s = fetch_str_dup ();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int l = prefetch_strlen ();
|
||||||
|
char *r = fetch_str (l);
|
||||||
|
if (memcmp (*s, r, l) || (*s)[l]) {
|
||||||
|
free (*s);
|
||||||
|
*s = malloc (l + 1);
|
||||||
|
memcpy (*s, r, l);
|
||||||
|
(*s)[l] = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fetch_update_int (int *value) {
|
||||||
|
if (*value == *in_ptr) {
|
||||||
|
in_ptr ++;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
*value = *(in_ptr ++);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fetch_update_long (long long *value) {
|
||||||
|
if (*value == *(long long *)in_ptr) {
|
||||||
|
in_ptr += 2;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
*value = *(long long *)(in_ptr);
|
||||||
|
in_ptr += 2;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int set_update_int (int *value, int new_value) {
|
||||||
|
if (*value == new_value) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
*value = new_value;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void fetch_skip (int n) {
|
static inline void fetch_skip (int n) {
|
||||||
in_ptr += n;
|
in_ptr += n;
|
||||||
}
|
}
|
||||||
|
111
queries.c
111
queries.c
@ -44,6 +44,7 @@
|
|||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
|
||||||
#include "no-preview.h"
|
#include "no-preview.h"
|
||||||
|
#include "binlog.h"
|
||||||
|
|
||||||
#define sha1 SHA1
|
#define sha1 SHA1
|
||||||
|
|
||||||
@ -55,6 +56,8 @@ long long cur_uploaded_bytes;
|
|||||||
long long cur_downloading_bytes;
|
long long cur_downloading_bytes;
|
||||||
long long cur_downloaded_bytes;
|
long long cur_downloaded_bytes;
|
||||||
|
|
||||||
|
extern int binlog_enabled;
|
||||||
|
|
||||||
void out_peer_id (peer_id_t id);
|
void out_peer_id (peer_id_t id);
|
||||||
#define QUERY_TIMEOUT 6.0
|
#define QUERY_TIMEOUT 6.0
|
||||||
|
|
||||||
@ -303,6 +306,7 @@ void out_random (int n) {
|
|||||||
/* {{{ Get config */
|
/* {{{ Get config */
|
||||||
|
|
||||||
void fetch_dc_option (void) {
|
void fetch_dc_option (void) {
|
||||||
|
int *start = in_ptr;
|
||||||
assert (fetch_int () == CODE_dc_option);
|
assert (fetch_int () == CODE_dc_option);
|
||||||
int id = fetch_int ();
|
int id = fetch_int ();
|
||||||
int l1 = prefetch_strlen ();
|
int l1 = prefetch_strlen ();
|
||||||
@ -316,6 +320,9 @@ void fetch_dc_option (void) {
|
|||||||
if (!DC_list[id]) {
|
if (!DC_list[id]) {
|
||||||
alloc_dc (id, strndup (ip, l2), port);
|
alloc_dc (id, strndup (ip, l2), port);
|
||||||
new_dc_num ++;
|
new_dc_num ++;
|
||||||
|
if (binlog_enabled) {
|
||||||
|
add_log_event (start, 4 * (in_ptr - start));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,6 +431,13 @@ void do_send_code (const char *user) {
|
|||||||
dc_create_session (DC_working);
|
dc_create_session (DC_working);
|
||||||
}
|
}
|
||||||
dc_working_num = want_dc_num;
|
dc_working_num = want_dc_num;
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_DEFAULT_DC;
|
||||||
|
ev[1] = dc_working_num;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
|
|
||||||
logprintf ("send_code: dc_num = %d\n", dc_working_num);
|
logprintf ("send_code: dc_num = %d\n", dc_working_num);
|
||||||
want_dc_num = 0;
|
want_dc_num = 0;
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
@ -463,11 +477,27 @@ int check_phone_on_error (struct query *q UU, int error_code, int l, char *error
|
|||||||
dc_working_num = i;
|
dc_working_num = i;
|
||||||
DC_working = DC_list[i];
|
DC_working = DC_list[i];
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_DEFAULT_DC;
|
||||||
|
ev[1] = i;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
|
|
||||||
check_phone_result = 1;
|
check_phone_result = 1;
|
||||||
} else if (l >= s2 && !memcmp (error, "NETWORK_MIGRATE_", s2)) {
|
} else if (l >= s2 && !memcmp (error, "NETWORK_MIGRATE_", s2)) {
|
||||||
int i = error[s2] - '0';
|
int i = error[s2] - '0';
|
||||||
assert (DC_list[i]);
|
assert (DC_list[i]);
|
||||||
dc_working_num = i;
|
dc_working_num = i;
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_DEFAULT_DC;
|
||||||
|
ev[1] = i;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
|
|
||||||
DC_working = DC_list[i];
|
DC_working = DC_list[i];
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
check_phone_result = 1;
|
check_phone_result = 1;
|
||||||
@ -536,6 +566,7 @@ int do_get_nearest_dc (void) {
|
|||||||
|
|
||||||
/* {{{ Sign in / Sign up */
|
/* {{{ Sign in / Sign up */
|
||||||
int sign_in_ok;
|
int sign_in_ok;
|
||||||
|
int our_id;
|
||||||
int sign_in_is_ok (void) {
|
int sign_in_is_ok (void) {
|
||||||
return sign_in_ok;
|
return sign_in_ok;
|
||||||
}
|
}
|
||||||
@ -546,11 +577,28 @@ int sign_in_on_answer (struct query *q UU) {
|
|||||||
assert (fetch_int () == (int)CODE_auth_authorization);
|
assert (fetch_int () == (int)CODE_auth_authorization);
|
||||||
int expires = fetch_int ();
|
int expires = fetch_int ();
|
||||||
fetch_user (&User);
|
fetch_user (&User);
|
||||||
|
if (!our_id) {
|
||||||
|
our_id = get_peer_id (User.id);
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_OUR_ID;
|
||||||
|
ev[1] = our_id;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
sign_in_ok = 1;
|
sign_in_ok = 1;
|
||||||
if (verbosity) {
|
if (verbosity) {
|
||||||
logprintf ( "authorized successfully: name = '%s %s', phone = '%s', expires = %d\n", User.first_name, User.last_name, User.phone, (int)(expires - get_double_time ()));
|
logprintf ( "authorized successfully: name = '%s %s', phone = '%s', expires = %d\n", User.first_name, User.last_name, User.phone, (int)(expires - get_double_time ()));
|
||||||
}
|
}
|
||||||
DC_working->has_auth = 1;
|
DC_working->has_auth = 1;
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_DC_SIGNED;
|
||||||
|
ev[1] = DC_working->id;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,7 +782,7 @@ void encr_finish (struct secret_chat *E) {
|
|||||||
/* {{{ Seng msg (plain text) */
|
/* {{{ Seng msg (plain text) */
|
||||||
int msg_send_encr_on_answer (struct query *q UU) {
|
int msg_send_encr_on_answer (struct query *q UU) {
|
||||||
assert (fetch_int () == CODE_messages_sent_encrypted_message);
|
assert (fetch_int () == CODE_messages_sent_encrypted_message);
|
||||||
logprintf ("Sent\n");
|
rprintf ("Sent\n");
|
||||||
struct message *M = q->extra;
|
struct message *M = q->extra;
|
||||||
M->date = fetch_int ();
|
M->date = fetch_int ();
|
||||||
message_insert (M);
|
message_insert (M);
|
||||||
@ -790,7 +838,7 @@ int msg_send_on_answer (struct query *q UU) {
|
|||||||
print_end ();
|
print_end ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logprintf ("Sent: id = %d\n", id);
|
rprintf ("Sent: id = %d\n", id);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2113,6 +2161,8 @@ int send_encr_request_on_answer (struct query *q UU) {
|
|||||||
printf ("\n");
|
printf ("\n");
|
||||||
pop_color ();
|
pop_color ();
|
||||||
print_end ();
|
print_end ();
|
||||||
|
|
||||||
|
assert (E->state == sc_waiting);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2156,10 +2206,18 @@ void do_send_accept_encr_chat (struct secret_chat *E, unsigned char *random) {
|
|||||||
sha1 ((void *)E->key, 256, sha_buffer);
|
sha1 ((void *)E->key, 256, sha_buffer);
|
||||||
E->key_fingerprint = *(long long *)(sha_buffer + 12);
|
E->key_fingerprint = *(long long *)(sha_buffer + 12);
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8 + 8 + 256);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_KEY;
|
||||||
|
ev[1] = get_peer_id (E->id);
|
||||||
|
*(long long *)(ev + 2) = E->key_fingerprint;
|
||||||
|
memcpy (ev + 4, E->key, 256);
|
||||||
|
add_log_event (ev, 8 + 8 + 256);
|
||||||
|
}
|
||||||
|
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
out_int (CODE_messages_accept_encryption);
|
out_int (CODE_messages_accept_encryption);
|
||||||
out_int (CODE_input_encrypted_chat);
|
out_int (CODE_input_encrypted_chat);
|
||||||
logprintf ("id = %d\n", get_peer_id (E->id));
|
|
||||||
out_int (get_peer_id (E->id));
|
out_int (get_peer_id (E->id));
|
||||||
out_long (E->access_hash);
|
out_long (E->access_hash);
|
||||||
|
|
||||||
@ -2175,15 +2233,22 @@ void do_send_accept_encr_chat (struct secret_chat *E, unsigned char *random) {
|
|||||||
BN_clear_free (g_a);
|
BN_clear_free (g_a);
|
||||||
BN_clear_free (p);
|
BN_clear_free (p);
|
||||||
BN_clear_free (r);
|
BN_clear_free (r);
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (16 + 512);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_SEND_ACCEPT;
|
||||||
|
ev[1] = get_peer_id (E->id);
|
||||||
|
*(long long *)(ev + 2) = E->key_fingerprint;
|
||||||
|
memcpy (ev + 4, E->key, 256);
|
||||||
|
memcpy (ev + 68, buf, 256);
|
||||||
|
add_log_event (ev, 16 + 512);
|
||||||
|
}
|
||||||
|
|
||||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E);
|
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E);
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_create_keys_end (struct secret_chat *U) {
|
void do_create_keys_end (struct secret_chat *U) {
|
||||||
if (!encr_prime) {
|
assert (encr_prime);
|
||||||
rprintf (COLOR_YELLOW "Something failed in bad moment. Did not fail\n"COLOR_NORMAL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0);
|
BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0);
|
||||||
assert (g_b);
|
assert (g_b);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -2212,6 +2277,15 @@ void do_create_keys_end (struct secret_chat *U) {
|
|||||||
BN_clear_free (g_b);
|
BN_clear_free (g_b);
|
||||||
BN_clear_free (r);
|
BN_clear_free (r);
|
||||||
BN_clear_free (a);
|
BN_clear_free (a);
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8 + 8 + 256);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_KEY;
|
||||||
|
ev[1] = get_peer_id (U->id);
|
||||||
|
*(long long *)(ev + 2) = U->key_fingerprint;
|
||||||
|
memcpy (ev + 4, U->key, 256);
|
||||||
|
add_log_event (ev, 8 + 8 + 256);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_send_create_encr_chat (struct secret_chat *E, unsigned char *random) {
|
void do_send_create_encr_chat (struct secret_chat *E, unsigned char *random) {
|
||||||
@ -2264,20 +2338,36 @@ void do_send_create_encr_chat (struct secret_chat *E, unsigned char *random) {
|
|||||||
BN_clear_free (p);
|
BN_clear_free (p);
|
||||||
BN_clear_free (r);
|
BN_clear_free (r);
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (12 + 256);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_SEND_CREATE;
|
||||||
|
ev[1] = get_peer_id (E->id);
|
||||||
|
ev[2] = E->user_id;
|
||||||
|
memcpy (ev + 3, E->key, 256);
|
||||||
|
add_log_event (ev, 12 + 256);
|
||||||
|
}
|
||||||
|
|
||||||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E);
|
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_dh_config_on_answer (struct query *q UU) {
|
int get_dh_config_on_answer (struct query *q UU) {
|
||||||
|
int *start = in_ptr;
|
||||||
unsigned x = fetch_int ();
|
unsigned x = fetch_int ();
|
||||||
assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified);
|
assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified || LOG_DH_CONFIG);
|
||||||
if (x == CODE_messages_dh_config) {
|
if (x == CODE_messages_dh_config || x == LOG_DH_CONFIG) {
|
||||||
encr_root = fetch_int ();
|
encr_root = fetch_int ();
|
||||||
if (encr_prime) { free (encr_prime); }
|
if (encr_prime) { free (encr_prime); }
|
||||||
int l = prefetch_strlen ();
|
int l = prefetch_strlen ();
|
||||||
assert (l == 256);
|
assert (l == 256);
|
||||||
encr_prime = (void *)fetch_str_dup ();
|
encr_prime = (void *)fetch_str_dup ();
|
||||||
encr_param_version = fetch_int ();
|
encr_param_version = fetch_int ();
|
||||||
|
if (binlog_enabled) {
|
||||||
|
*start = LOG_DH_CONFIG;
|
||||||
|
add_log_event (start, 4 * (in_ptr - start));
|
||||||
|
*start = CODE_messages_dh_config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (x == LOG_DH_CONFIG) { return 0; }
|
||||||
int l = prefetch_strlen ();
|
int l = prefetch_strlen ();
|
||||||
assert (l == 256);
|
assert (l == 256);
|
||||||
unsigned char *random = (void *)fetch_str_dup ();
|
unsigned char *random = (void *)fetch_str_dup ();
|
||||||
@ -2411,7 +2501,7 @@ struct query_methods get_difference_methods = {
|
|||||||
void do_get_difference (void) {
|
void do_get_difference (void) {
|
||||||
difference_got = 0;
|
difference_got = 0;
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
out_int (CODE_invoke_with_layer10);
|
out_int (CODE_invoke_with_layer9);
|
||||||
out_int (CODE_init_connection);
|
out_int (CODE_init_connection);
|
||||||
out_int (TG_APP_ID);
|
out_int (TG_APP_ID);
|
||||||
if (allow_send_linux_version) {
|
if (allow_send_linux_version) {
|
||||||
@ -2568,6 +2658,7 @@ void do_create_secret_chat (peer_id_t id) {
|
|||||||
peer_t *U = user_chat_get (id);
|
peer_t *U = user_chat_get (id);
|
||||||
if (!U) {
|
if (!U) {
|
||||||
rprintf ("Can not create chat with unknown user\n");
|
rprintf ("Can not create chat with unknown user\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
peer_t *P = malloc (sizeof (*P));
|
peer_t *P = malloc (sizeof (*P));
|
||||||
|
@ -111,5 +111,6 @@ void do_contacts_search (int limit, const char *s);
|
|||||||
|
|
||||||
// For binlog
|
// For binlog
|
||||||
|
|
||||||
|
int get_dh_config_on_answer (struct query *q);
|
||||||
void fetch_dc_option (void);
|
void fetch_dc_option (void);
|
||||||
#endif
|
#endif
|
||||||
|
205
structures.c
205
structures.c
@ -30,6 +30,7 @@
|
|||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include "queries.h"
|
#include "queries.h"
|
||||||
|
#include "binlog.h"
|
||||||
|
|
||||||
#define sha1 SHA1
|
#define sha1 SHA1
|
||||||
|
|
||||||
@ -40,24 +41,37 @@ int peer_num;
|
|||||||
int encr_chats_allocated;
|
int encr_chats_allocated;
|
||||||
int geo_chats_allocated;
|
int geo_chats_allocated;
|
||||||
|
|
||||||
void fetch_file_location (struct file_location *loc) {
|
extern int binlog_enabled;
|
||||||
int x = fetch_int ();
|
|
||||||
if (x == CODE_file_location_unavailable) {
|
void fetch_add_alloc_log_event (void *obj, int (*f)(void *)) {
|
||||||
loc->dc = -1;
|
int *start = in_ptr;
|
||||||
loc->volume = fetch_long ();
|
int r = f (obj);
|
||||||
loc->local_id = fetch_int ();
|
if (binlog_enabled && r) {
|
||||||
loc->secret = fetch_long ();
|
add_log_event (start, 4 * (in_ptr - start));
|
||||||
} else {
|
|
||||||
assert (x == CODE_file_location);
|
|
||||||
loc->dc = fetch_int ();;
|
|
||||||
loc->volume = fetch_long ();
|
|
||||||
loc->local_id = fetch_int ();
|
|
||||||
loc->secret = fetch_long ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetch_user_status (struct user_status *S) {
|
int fetch_file_location (struct file_location *loc) {
|
||||||
int x = fetch_int ();
|
int x = fetch_int ();
|
||||||
|
int new = 0;
|
||||||
|
if (x == CODE_file_location_unavailable) {
|
||||||
|
new |= set_update_int (&loc->dc, -1);
|
||||||
|
new |= fetch_update_long (&loc->volume);
|
||||||
|
new |= fetch_update_int (&loc->local_id);
|
||||||
|
new |= fetch_update_long (&loc->secret);
|
||||||
|
} else {
|
||||||
|
assert (x == CODE_file_location);
|
||||||
|
new |= fetch_update_int (&loc->dc);
|
||||||
|
new |= fetch_update_long (&loc->volume);
|
||||||
|
new |= fetch_update_int (&loc->local_id);
|
||||||
|
new |= fetch_update_long (&loc->secret);
|
||||||
|
}
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fetch_user_status (struct user_status *S) {
|
||||||
|
int x = fetch_int ();
|
||||||
|
int old = S->online;
|
||||||
switch (x) {
|
switch (x) {
|
||||||
case CODE_user_status_empty:
|
case CODE_user_status_empty:
|
||||||
S->online = 0;
|
S->online = 0;
|
||||||
@ -73,6 +87,7 @@ void fetch_user_status (struct user_status *S) {
|
|||||||
default:
|
default:
|
||||||
assert (0);
|
assert (0);
|
||||||
}
|
}
|
||||||
|
return (old == S->online);
|
||||||
}
|
}
|
||||||
|
|
||||||
int our_id;
|
int our_id;
|
||||||
@ -134,72 +149,83 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha
|
|||||||
return strdup (s);
|
return strdup (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetch_user (struct user *U) {
|
int fetch_user (struct user *U) {
|
||||||
unsigned x = fetch_int ();
|
unsigned x = fetch_int ();
|
||||||
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);
|
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);
|
||||||
U->id = MK_USER (fetch_int ());
|
U->id = MK_USER (fetch_int ());
|
||||||
U->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_USER_SELF | FLAG_USER_FOREIGN | FLAG_USER_CONTACT);
|
if ((U->flags & FLAG_CREATED) && x == CODE_user_empty) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int old_flags = U->flags;
|
||||||
|
U->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_USER_SELF | FLAG_USER_FOREIGN | FLAG_USER_CONTACT | FLAG_CREATED);
|
||||||
if (x == CODE_user_empty) {
|
if (x == CODE_user_empty) {
|
||||||
U->flags |= FLAG_EMPTY;
|
U->flags |= FLAG_EMPTY;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
U->flags |= FLAG_CREATED;
|
||||||
if (x == CODE_user_self) {
|
if (x == CODE_user_self) {
|
||||||
assert (!our_id || (our_id == get_peer_id (U->id)));
|
assert (!our_id || (our_id == get_peer_id (U->id)));
|
||||||
if (!our_id) {
|
if (!our_id) {
|
||||||
our_id = get_peer_id (U->id);
|
our_id = get_peer_id (U->id);
|
||||||
write_auth_file ();
|
write_auth_file ();
|
||||||
|
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_OUR_ID;
|
||||||
|
ev[1] = our_id;
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (U->first_name) { free (U->first_name); }
|
int need_update = 0;
|
||||||
if (U->last_name) { free (U->last_name); }
|
need_update |= fetch_update_str (&U->first_name);
|
||||||
if (U->print_name) { free (U->print_name); }
|
need_update |= fetch_update_str (&U->last_name);
|
||||||
U->first_name = fetch_str_dup ();
|
if (need_update) {
|
||||||
U->last_name = fetch_str_dup ();
|
if (U->print_name) { free (U->print_name); }
|
||||||
|
U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0);
|
||||||
U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0);
|
}
|
||||||
if (x == CODE_user_deleted) {
|
if (x == CODE_user_deleted) {
|
||||||
U->flags |= FLAG_DELETED;
|
U->flags |= FLAG_DELETED;
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (x == CODE_user_self) {
|
|
||||||
U->flags |= FLAG_USER_SELF;
|
|
||||||
} else {
|
} else {
|
||||||
U->access_hash = fetch_long ();
|
if (x == CODE_user_self) {
|
||||||
}
|
U->flags |= FLAG_USER_SELF;
|
||||||
if (x == CODE_user_foreign) {
|
} else {
|
||||||
U->flags |= FLAG_USER_FOREIGN;
|
need_update |= fetch_update_long (&U->access_hash);
|
||||||
U->phone = 0;
|
}
|
||||||
} else {
|
if (x == CODE_user_foreign) {
|
||||||
if (U->phone) { free (U->phone); }
|
U->flags |= FLAG_USER_FOREIGN;
|
||||||
U->phone = fetch_str_dup ();
|
} else {
|
||||||
}
|
need_update |= fetch_update_str (&U->phone);
|
||||||
//logprintf ("name = %s, surname = %s, phone = %s\n", U->first_name, U->last_name, U->phone);
|
}
|
||||||
unsigned y = fetch_int ();
|
unsigned y = fetch_int ();
|
||||||
//fprintf (stderr, "y = 0x%08x\n", y);
|
if (y == CODE_user_profile_photo_empty) {
|
||||||
if (y == CODE_user_profile_photo_empty) {
|
need_update |= set_update_int (&U->photo_small.dc, -2);
|
||||||
U->photo_small.dc = -2;
|
need_update |= set_update_int (&U->photo_big.dc, -2);
|
||||||
U->photo_big.dc = -2;
|
} else {
|
||||||
} else {
|
assert (y == CODE_user_profile_photo);
|
||||||
assert (y == CODE_user_profile_photo || y == 0x990d1493);
|
fetch_long ();
|
||||||
if (y == CODE_user_profile_photo) {
|
need_update |= fetch_file_location (&U->photo_small);
|
||||||
fetch_long ();
|
need_update |= fetch_file_location (&U->photo_big);
|
||||||
|
}
|
||||||
|
fetch_user_status (&U->status);
|
||||||
|
if (x == CODE_user_self) {
|
||||||
|
fetch_bool ();
|
||||||
|
}
|
||||||
|
if (x == CODE_user_contact) {
|
||||||
|
U->flags |= FLAG_USER_CONTACT;
|
||||||
}
|
}
|
||||||
fetch_file_location (&U->photo_small);
|
|
||||||
fetch_file_location (&U->photo_big);
|
|
||||||
}
|
|
||||||
fetch_user_status (&U->status);
|
|
||||||
if (x == CODE_user_self) {
|
|
||||||
fetch_bool ();
|
|
||||||
}
|
|
||||||
if (x == CODE_user_contact) {
|
|
||||||
U->flags |= FLAG_USER_CONTACT;
|
|
||||||
}
|
}
|
||||||
|
need_update |= (old_flags != U->flags);
|
||||||
|
return need_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetch_encrypted_chat (struct secret_chat *U) {
|
void fetch_encrypted_chat (struct secret_chat *U) {
|
||||||
unsigned x = fetch_int ();
|
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);
|
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);
|
||||||
U->id = MK_ENCR_CHAT (fetch_int ());
|
U->id = MK_ENCR_CHAT (fetch_int ());
|
||||||
|
if ((U->flags & FLAG_CREATED) && x == CODE_encrypted_chat_empty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
U->flags &= ~(FLAG_EMPTY | FLAG_DELETED);
|
U->flags &= ~(FLAG_EMPTY | FLAG_DELETED);
|
||||||
enum secret_chat_state old_state = U->state;
|
enum secret_chat_state old_state = U->state;
|
||||||
if (x == CODE_encrypted_chat_empty) {
|
if (x == CODE_encrypted_chat_empty) {
|
||||||
@ -210,11 +236,18 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
U->flags |= FLAG_CREATED;
|
||||||
if (x == CODE_encrypted_chat_discarded) {
|
if (x == CODE_encrypted_chat_discarded) {
|
||||||
U->state = sc_deleted;
|
U->state = sc_deleted;
|
||||||
U->flags |= FLAG_DELETED;
|
U->flags |= FLAG_DELETED;
|
||||||
if (U->state != old_state) {
|
if (U->state != old_state) {
|
||||||
write_secret_chat_file ();
|
write_secret_chat_file ();
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_DELETED;
|
||||||
|
ev[1] = get_peer_id (U->id);
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -222,19 +255,31 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
|||||||
U->date = fetch_int ();
|
U->date = fetch_int ();
|
||||||
U->admin_id = fetch_int ();
|
U->admin_id = fetch_int ();
|
||||||
U->user_id = fetch_int () + U->admin_id - our_id;
|
U->user_id = fetch_int () + U->admin_id - our_id;
|
||||||
if (U->print_name) { free (U->print_name); }
|
if (!U->print_name) {
|
||||||
|
peer_t *P = user_chat_get (MK_USER (U->user_id));
|
||||||
peer_t *P = user_chat_get (MK_USER (U->user_id));
|
if (P) {
|
||||||
if (P) {
|
U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0);
|
||||||
U->print_name = create_print_name (U->id, "!", P->user.first_name, P->user.last_name, 0);
|
} else {
|
||||||
} else {
|
static char buf[100];
|
||||||
static char buf[100];
|
sprintf (buf, "user#%d", U->user_id);
|
||||||
sprintf (buf, "user#%d", U->user_id);
|
U->print_name = create_print_name (U->id, "!", buf, 0, 0);
|
||||||
U->print_name = create_print_name (U->id, "!", buf, 0, 0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x == CODE_encrypted_chat_waiting) {
|
if (x == CODE_encrypted_chat_waiting) {
|
||||||
U->state = sc_waiting;
|
U->state = sc_waiting;
|
||||||
|
if (old_state != sc_waiting) {
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (28);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_WAITING;
|
||||||
|
ev[1] = get_peer_id (U->id);
|
||||||
|
ev[2] = U->date;
|
||||||
|
ev[3] = U->admin_id;
|
||||||
|
ev[4] = U->user_id;
|
||||||
|
*(long long *)(ev + 5) = U->access_hash;
|
||||||
|
add_log_event (ev, 28);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (x == CODE_encrypted_chat_requested) {
|
} else if (x == CODE_encrypted_chat_requested) {
|
||||||
U->state = sc_request;
|
U->state = sc_request;
|
||||||
if (!U->g_key) {
|
if (!U->g_key) {
|
||||||
@ -259,6 +304,18 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
|||||||
} else {
|
} else {
|
||||||
memcpy (U->nonce, s + (l - 256), 256);
|
memcpy (U->nonce, s + (l - 256), 256);
|
||||||
}
|
}
|
||||||
|
if (old_state != sc_request) {
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (28);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_REQUESTED;
|
||||||
|
ev[1] = get_peer_id (U->id);
|
||||||
|
ev[2] = U->date;
|
||||||
|
ev[3] = U->admin_id;
|
||||||
|
ev[4] = U->user_id;
|
||||||
|
*(long long *)(ev + 5) = U->access_hash;
|
||||||
|
add_log_event (ev, 28);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
U->state = sc_ok;
|
U->state = sc_ok;
|
||||||
if (!U->g_key) {
|
if (!U->g_key) {
|
||||||
@ -291,6 +348,18 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
|||||||
if (old_state == sc_waiting) {
|
if (old_state == sc_waiting) {
|
||||||
do_create_keys_end (U);
|
do_create_keys_end (U);
|
||||||
}
|
}
|
||||||
|
free (U->g_key);
|
||||||
|
U->g_key = 0;
|
||||||
|
free (U->nonce);
|
||||||
|
U->nonce = 0;
|
||||||
|
if (old_state != sc_ok) {
|
||||||
|
if (binlog_enabled) {
|
||||||
|
int *ev = alloc_log_event (8);
|
||||||
|
ev[0] = LOG_ENCR_CHAT_OK;
|
||||||
|
ev[1] = get_peer_id (U->id);
|
||||||
|
add_log_event (ev, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (U->state != old_state) {
|
if (U->state != old_state) {
|
||||||
write_secret_chat_file ();
|
write_secret_chat_file ();
|
||||||
@ -941,13 +1010,13 @@ struct user *fetch_alloc_user (void) {
|
|||||||
prefetch_data (data, 8);
|
prefetch_data (data, 8);
|
||||||
peer_t *U = user_chat_get (MK_USER (data[1]));
|
peer_t *U = user_chat_get (MK_USER (data[1]));
|
||||||
if (U) {
|
if (U) {
|
||||||
fetch_user (&U->user);
|
fetch_add_alloc_log_event (&U->user, (void *)fetch_user);
|
||||||
return &U->user;
|
return &U->user;
|
||||||
} else {
|
} else {
|
||||||
users_allocated ++;
|
users_allocated ++;
|
||||||
U = malloc (sizeof (*U));
|
U = malloc (sizeof (*U));
|
||||||
memset (U, 0, sizeof (*U));
|
memset (U, 0, sizeof (*U));
|
||||||
fetch_user (&U->user);
|
fetch_add_alloc_log_event (&U->user, (void *)fetch_user);
|
||||||
peer_tree = tree_insert_peer (peer_tree, U, lrand48 ());
|
peer_tree = tree_insert_peer (peer_tree, U, lrand48 ());
|
||||||
Peers[peer_num ++] = U;
|
Peers[peer_num ++] = U;
|
||||||
return &U->user;
|
return &U->user;
|
||||||
@ -1343,7 +1412,7 @@ int print_stat (char *s, int len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
peer_t *user_chat_get (peer_id_t id) {
|
peer_t *user_chat_get (peer_id_t id) {
|
||||||
peer_t U;
|
static peer_t U;
|
||||||
U.id = id;
|
U.id = id;
|
||||||
return tree_lookup_peer (peer_tree, &U);
|
return tree_lookup_peer (peer_tree, &U);
|
||||||
}
|
}
|
||||||
|
13
structures.h
13
structures.h
@ -26,6 +26,7 @@ typedef struct { int type; int id; } peer_id_t;
|
|||||||
#define FLAG_DELETED 2
|
#define FLAG_DELETED 2
|
||||||
#define FLAG_FORBIDDEN 4
|
#define FLAG_FORBIDDEN 4
|
||||||
#define FLAG_HAS_PHOTO 8
|
#define FLAG_HAS_PHOTO 8
|
||||||
|
#define FLAG_CREATED 16
|
||||||
|
|
||||||
#define FLAG_USER_SELF 128
|
#define FLAG_USER_SELF 128
|
||||||
#define FLAG_USER_FOREIGN 256
|
#define FLAG_USER_FOREIGN 256
|
||||||
@ -113,6 +114,7 @@ struct user {
|
|||||||
int flags;
|
int flags;
|
||||||
struct message *last;
|
struct message *last;
|
||||||
char *print_name;
|
char *print_name;
|
||||||
|
int structure_version;
|
||||||
struct file_location photo_big;
|
struct file_location photo_big;
|
||||||
struct file_location photo_small;
|
struct file_location photo_small;
|
||||||
struct photo photo;
|
struct photo photo;
|
||||||
@ -137,6 +139,7 @@ struct chat {
|
|||||||
int flags;
|
int flags;
|
||||||
struct message *last;
|
struct message *last;
|
||||||
char *print_title;
|
char *print_title;
|
||||||
|
int structure_version;
|
||||||
struct file_location photo_big;
|
struct file_location photo_big;
|
||||||
struct file_location photo_small;
|
struct file_location photo_small;
|
||||||
struct photo photo;
|
struct photo photo;
|
||||||
@ -161,6 +164,7 @@ struct secret_chat {
|
|||||||
int flags;
|
int flags;
|
||||||
struct message *last;
|
struct message *last;
|
||||||
char *print_name;
|
char *print_name;
|
||||||
|
int structure_version;
|
||||||
struct file_location photo_big;
|
struct file_location photo_big;
|
||||||
struct file_location photo_small;
|
struct file_location photo_small;
|
||||||
struct photo photo;
|
struct photo photo;
|
||||||
@ -183,6 +187,7 @@ typedef union peer {
|
|||||||
int flags;
|
int flags;
|
||||||
struct message *last;
|
struct message *last;
|
||||||
char *print_name;
|
char *print_name;
|
||||||
|
int structure_version;
|
||||||
struct file_location photo_big;
|
struct file_location photo_big;
|
||||||
struct file_location photo_small;
|
struct file_location photo_small;
|
||||||
struct photo photo;
|
struct photo photo;
|
||||||
@ -262,9 +267,9 @@ struct message {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
void fetch_file_location (struct file_location *loc);
|
int fetch_file_location (struct file_location *loc);
|
||||||
void fetch_user_status (struct user_status *S);
|
int fetch_user_status (struct user_status *S);
|
||||||
void fetch_user (struct user *U);
|
int fetch_user (struct user *U);
|
||||||
struct user *fetch_alloc_user (void);
|
struct user *fetch_alloc_user (void);
|
||||||
struct user *fetch_alloc_user_full (void);
|
struct user *fetch_alloc_user_full (void);
|
||||||
struct chat *fetch_alloc_chat (void);
|
struct chat *fetch_alloc_chat (void);
|
||||||
@ -281,6 +286,8 @@ peer_id_t fetch_peer_id (void);
|
|||||||
void free_user (struct user *U);
|
void free_user (struct user *U);
|
||||||
void free_chat (struct chat *U);
|
void free_chat (struct chat *U);
|
||||||
|
|
||||||
|
char *create_print_name (peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4);
|
||||||
|
|
||||||
int print_stat (char *s, int len);
|
int print_stat (char *s, int len);
|
||||||
peer_t *user_chat_get (peer_id_t id);
|
peer_t *user_chat_get (peer_id_t id);
|
||||||
struct message *message_get (long long id);
|
struct message *message_get (long long id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user