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
|
||||
|
||||
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}
|
||||
|
||||
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
|
||||
|
||||
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}
|
||||
|
||||
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 "mtproto-common.h"
|
||||
#include "net.h"
|
||||
|
||||
#define LOG_START 0x8948329a
|
||||
#define LOG_AUTH_KEY 0x984932aa
|
||||
#define LOG_DEFAULT_DC 0x95382908
|
||||
#include "include.h"
|
||||
|
||||
#define BINLOG_BUFFER_SIZE (1 << 20)
|
||||
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_working;
|
||||
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) {
|
||||
assert (rptr < wptr);
|
||||
@ -41,6 +46,7 @@ void replay_log_event (void) {
|
||||
return;
|
||||
case CODE_dc_option:
|
||||
fetch_dc_option ();
|
||||
rptr = in_ptr;
|
||||
return;
|
||||
case LOG_AUTH_KEY:
|
||||
rptr ++;
|
||||
@ -52,6 +58,7 @@ void replay_log_event (void) {
|
||||
rptr += 2;
|
||||
memcpy (DC_list[num]->auth_key, rptr, 256);
|
||||
rptr += 64;
|
||||
DC_list[num]->flags |= 1;
|
||||
};
|
||||
return;
|
||||
case LOG_DEFAULT_DC:
|
||||
@ -63,6 +70,180 @@ void replay_log_event (void) {
|
||||
dc_working_num = num;
|
||||
}
|
||||
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;
|
||||
out_int (LOG_START);
|
||||
out_int (CODE_dc_option);
|
||||
out_int (0);
|
||||
out_int (1);
|
||||
out_string ("");
|
||||
out_string (test_dc ? TG_SERVER_TEST : TG_SERVER);
|
||||
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);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
|
||||
void replay_log (void) {
|
||||
in_replay_log = 1;
|
||||
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 ();
|
||||
}
|
||||
int fd = open (get_binlog_file_name (), O_RDONLY);
|
||||
@ -92,7 +280,7 @@ void replay_log (void) {
|
||||
perror ("binlog open");
|
||||
exit (2);
|
||||
}
|
||||
int end;
|
||||
int end = 0;
|
||||
while (1) {
|
||||
if (!end && wptr - rptr < MAX_LOG_EVENT_SIZE / 4) {
|
||||
if (wptr == rptr) {
|
||||
@ -119,4 +307,20 @@ void replay_log (void) {
|
||||
replay_log_event ();
|
||||
}
|
||||
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__
|
||||
#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 replay_log (void);
|
||||
void add_log_event (const int *data, int l);
|
||||
void write_binlog (void);
|
||||
#endif
|
||||
|
19
loop.c
19
loop.c
@ -160,6 +160,7 @@ void write_dc (int auth_file_fd, struct dc *DC) {
|
||||
|
||||
int our_id;
|
||||
void write_auth_file (void) {
|
||||
if (binlog_enabled) { return; }
|
||||
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
||||
assert (auth_file_fd >= 0);
|
||||
int x = DC_SERIALIZED_MAGIC_V2;
|
||||
@ -216,6 +217,7 @@ void empty_auth_file (void) {
|
||||
|
||||
int need_dc_list_update;
|
||||
void read_auth_file (void) {
|
||||
if (binlog_enabled) { return; }
|
||||
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
|
||||
if (auth_file_fd < 0) {
|
||||
empty_auth_file ();
|
||||
@ -308,6 +310,7 @@ extern unsigned char *encr_prime;
|
||||
extern int encr_param_version;
|
||||
|
||||
void read_secret_chat_file (void) {
|
||||
if (binlog_enabled) { return; }
|
||||
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
@ -364,6 +367,7 @@ void read_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);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
@ -430,12 +434,15 @@ int loop (void) {
|
||||
on_start ();
|
||||
if (binlog_enabled) {
|
||||
replay_log ();
|
||||
write_binlog ();
|
||||
} else {
|
||||
read_auth_file ();
|
||||
}
|
||||
read_auth_file ();
|
||||
update_prompt ();
|
||||
|
||||
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];
|
||||
assert (!DC_working->auth_key_id);
|
||||
dc_authorize (DC_working);
|
||||
@ -459,7 +466,7 @@ int loop (void) {
|
||||
write_auth_file ();
|
||||
}
|
||||
|
||||
if (auth_state == 100) {
|
||||
if (auth_state == 100 || !(DC_working->has_auth)) {
|
||||
if (!default_username) {
|
||||
size_t size = 0;
|
||||
char *user = 0;
|
||||
@ -546,6 +553,12 @@ int loop (void) {
|
||||
do_export_auth (i);
|
||||
do_import_auth (i);
|
||||
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 ();
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "loop.h"
|
||||
#include "interface.h"
|
||||
#include "structures.h"
|
||||
#include "binlog.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
@ -57,6 +58,7 @@ enum dc_state c_state;
|
||||
char nonce[256];
|
||||
char new_nonce[256];
|
||||
char server_nonce[256];
|
||||
extern int binlog_enabled;
|
||||
|
||||
int rpc_execute (struct connection *c, int op, int len);
|
||||
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);
|
||||
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
|
||||
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) {
|
||||
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 ++;
|
||||
GET_DC(c)->flags |= 1;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -559,7 +577,7 @@ void init_enc_msg (struct session *S, int useful) {
|
||||
struct dc *DC = S->dc;
|
||||
assert (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;
|
||||
if (!S->session_id) {
|
||||
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 ();
|
||||
fetch_long (); // unique_id
|
||||
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) {
|
||||
@ -1294,6 +1320,13 @@ void work_bad_server_salt (struct connection *c UU, long long msg_id UU) {
|
||||
fetch_int (); // error_code
|
||||
long long new_server_salt = fetch_long ();
|
||||
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) {
|
||||
@ -1389,6 +1422,13 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
|
||||
if (DC->server_salt != enc->server_salt) {
|
||||
DC->server_salt = enc->server_salt;
|
||||
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;
|
||||
@ -1475,7 +1515,11 @@ int rpc_execute (struct connection *c, int op, int len) {
|
||||
#endif
|
||||
return 0;
|
||||
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__
|
||||
setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
||||
#endif
|
||||
|
@ -307,6 +307,53 @@ static inline char *fetch_str_dup (void) {
|
||||
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) {
|
||||
in_ptr += n;
|
||||
}
|
||||
|
111
queries.c
111
queries.c
@ -44,6 +44,7 @@
|
||||
#include <openssl/md5.h>
|
||||
|
||||
#include "no-preview.h"
|
||||
#include "binlog.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
@ -55,6 +56,8 @@ long long cur_uploaded_bytes;
|
||||
long long cur_downloading_bytes;
|
||||
long long cur_downloaded_bytes;
|
||||
|
||||
extern int binlog_enabled;
|
||||
|
||||
void out_peer_id (peer_id_t id);
|
||||
#define QUERY_TIMEOUT 6.0
|
||||
|
||||
@ -303,6 +306,7 @@ void out_random (int n) {
|
||||
/* {{{ Get config */
|
||||
|
||||
void fetch_dc_option (void) {
|
||||
int *start = in_ptr;
|
||||
assert (fetch_int () == CODE_dc_option);
|
||||
int id = fetch_int ();
|
||||
int l1 = prefetch_strlen ();
|
||||
@ -316,6 +320,9 @@ void fetch_dc_option (void) {
|
||||
if (!DC_list[id]) {
|
||||
alloc_dc (id, strndup (ip, l2), port);
|
||||
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_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);
|
||||
want_dc_num = 0;
|
||||
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 = DC_list[i];
|
||||
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;
|
||||
} else if (l >= s2 && !memcmp (error, "NETWORK_MIGRATE_", s2)) {
|
||||
int i = error[s2] - '0';
|
||||
assert (DC_list[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];
|
||||
write_auth_file ();
|
||||
check_phone_result = 1;
|
||||
@ -536,6 +566,7 @@ int do_get_nearest_dc (void) {
|
||||
|
||||
/* {{{ Sign in / Sign up */
|
||||
int sign_in_ok;
|
||||
int our_id;
|
||||
int sign_in_is_ok (void) {
|
||||
return sign_in_ok;
|
||||
}
|
||||
@ -546,11 +577,28 @@ int sign_in_on_answer (struct query *q UU) {
|
||||
assert (fetch_int () == (int)CODE_auth_authorization);
|
||||
int expires = fetch_int ();
|
||||
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;
|
||||
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 ()));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -734,7 +782,7 @@ void encr_finish (struct secret_chat *E) {
|
||||
/* {{{ Seng msg (plain text) */
|
||||
int msg_send_encr_on_answer (struct query *q UU) {
|
||||
assert (fetch_int () == CODE_messages_sent_encrypted_message);
|
||||
logprintf ("Sent\n");
|
||||
rprintf ("Sent\n");
|
||||
struct message *M = q->extra;
|
||||
M->date = fetch_int ();
|
||||
message_insert (M);
|
||||
@ -790,7 +838,7 @@ int msg_send_on_answer (struct query *q UU) {
|
||||
print_end ();
|
||||
}
|
||||
}
|
||||
logprintf ("Sent: id = %d\n", id);
|
||||
rprintf ("Sent: id = %d\n", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2113,6 +2161,8 @@ int send_encr_request_on_answer (struct query *q UU) {
|
||||
printf ("\n");
|
||||
pop_color ();
|
||||
print_end ();
|
||||
|
||||
assert (E->state == sc_waiting);
|
||||
}
|
||||
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);
|
||||
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 ();
|
||||
out_int (CODE_messages_accept_encryption);
|
||||
out_int (CODE_input_encrypted_chat);
|
||||
logprintf ("id = %d\n", get_peer_id (E->id));
|
||||
out_int (get_peer_id (E->id));
|
||||
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 (p);
|
||||
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);
|
||||
}
|
||||
|
||||
void do_create_keys_end (struct secret_chat *U) {
|
||||
if (!encr_prime) {
|
||||
rprintf (COLOR_YELLOW "Something failed in bad moment. Did not fail\n"COLOR_NORMAL);
|
||||
return;
|
||||
}
|
||||
assert (encr_prime);
|
||||
BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0);
|
||||
assert (g_b);
|
||||
if (!ctx) {
|
||||
@ -2212,6 +2277,15 @@ void do_create_keys_end (struct secret_chat *U) {
|
||||
BN_clear_free (g_b);
|
||||
BN_clear_free (r);
|
||||
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) {
|
||||
@ -2264,20 +2338,36 @@ void do_send_create_encr_chat (struct secret_chat *E, unsigned char *random) {
|
||||
BN_clear_free (p);
|
||||
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);
|
||||
}
|
||||
|
||||
int get_dh_config_on_answer (struct query *q UU) {
|
||||
int *start = in_ptr;
|
||||
unsigned x = fetch_int ();
|
||||
assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified);
|
||||
if (x == CODE_messages_dh_config) {
|
||||
assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified || LOG_DH_CONFIG);
|
||||
if (x == CODE_messages_dh_config || x == LOG_DH_CONFIG) {
|
||||
encr_root = fetch_int ();
|
||||
if (encr_prime) { free (encr_prime); }
|
||||
int l = prefetch_strlen ();
|
||||
assert (l == 256);
|
||||
encr_prime = (void *)fetch_str_dup ();
|
||||
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 ();
|
||||
assert (l == 256);
|
||||
unsigned char *random = (void *)fetch_str_dup ();
|
||||
@ -2411,7 +2501,7 @@ struct query_methods get_difference_methods = {
|
||||
void do_get_difference (void) {
|
||||
difference_got = 0;
|
||||
clear_packet ();
|
||||
out_int (CODE_invoke_with_layer10);
|
||||
out_int (CODE_invoke_with_layer9);
|
||||
out_int (CODE_init_connection);
|
||||
out_int (TG_APP_ID);
|
||||
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);
|
||||
if (!U) {
|
||||
rprintf ("Can not create chat with unknown user\n");
|
||||
return;
|
||||
}
|
||||
|
||||
peer_t *P = malloc (sizeof (*P));
|
||||
|
@ -111,5 +111,6 @@ void do_contacts_search (int limit, const char *s);
|
||||
|
||||
// For binlog
|
||||
|
||||
int get_dh_config_on_answer (struct query *q);
|
||||
void fetch_dc_option (void);
|
||||
#endif
|
||||
|
205
structures.c
205
structures.c
@ -30,6 +30,7 @@
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "queries.h"
|
||||
#include "binlog.h"
|
||||
|
||||
#define sha1 SHA1
|
||||
|
||||
@ -40,24 +41,37 @@ int peer_num;
|
||||
int encr_chats_allocated;
|
||||
int geo_chats_allocated;
|
||||
|
||||
void fetch_file_location (struct file_location *loc) {
|
||||
int x = fetch_int ();
|
||||
if (x == CODE_file_location_unavailable) {
|
||||
loc->dc = -1;
|
||||
loc->volume = fetch_long ();
|
||||
loc->local_id = fetch_int ();
|
||||
loc->secret = fetch_long ();
|
||||
} else {
|
||||
assert (x == CODE_file_location);
|
||||
loc->dc = fetch_int ();;
|
||||
loc->volume = fetch_long ();
|
||||
loc->local_id = fetch_int ();
|
||||
loc->secret = fetch_long ();
|
||||
extern int binlog_enabled;
|
||||
|
||||
void fetch_add_alloc_log_event (void *obj, int (*f)(void *)) {
|
||||
int *start = in_ptr;
|
||||
int r = f (obj);
|
||||
if (binlog_enabled && r) {
|
||||
add_log_event (start, 4 * (in_ptr - start));
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_user_status (struct user_status *S) {
|
||||
int fetch_file_location (struct file_location *loc) {
|
||||
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) {
|
||||
case CODE_user_status_empty:
|
||||
S->online = 0;
|
||||
@ -73,6 +87,7 @@ void fetch_user_status (struct user_status *S) {
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
return (old == S->online);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void fetch_user (struct user *U) {
|
||||
int fetch_user (struct user *U) {
|
||||
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);
|
||||
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) {
|
||||
U->flags |= FLAG_EMPTY;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
U->flags |= FLAG_CREATED;
|
||||
if (x == CODE_user_self) {
|
||||
assert (!our_id || (our_id == get_peer_id (U->id)));
|
||||
if (!our_id) {
|
||||
our_id = get_peer_id (U->id);
|
||||
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); }
|
||||
if (U->last_name) { free (U->last_name); }
|
||||
if (U->print_name) { free (U->print_name); }
|
||||
U->first_name = fetch_str_dup ();
|
||||
U->last_name = fetch_str_dup ();
|
||||
|
||||
U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0);
|
||||
int need_update = 0;
|
||||
need_update |= fetch_update_str (&U->first_name);
|
||||
need_update |= fetch_update_str (&U->last_name);
|
||||
if (need_update) {
|
||||
if (U->print_name) { free (U->print_name); }
|
||||
U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0);
|
||||
}
|
||||
if (x == CODE_user_deleted) {
|
||||
U->flags |= FLAG_DELETED;
|
||||
return;
|
||||
}
|
||||
if (x == CODE_user_self) {
|
||||
U->flags |= FLAG_USER_SELF;
|
||||
} else {
|
||||
U->access_hash = fetch_long ();
|
||||
}
|
||||
if (x == CODE_user_foreign) {
|
||||
U->flags |= FLAG_USER_FOREIGN;
|
||||
U->phone = 0;
|
||||
} else {
|
||||
if (U->phone) { free (U->phone); }
|
||||
U->phone = fetch_str_dup ();
|
||||
}
|
||||
//logprintf ("name = %s, surname = %s, phone = %s\n", U->first_name, U->last_name, U->phone);
|
||||
unsigned y = fetch_int ();
|
||||
//fprintf (stderr, "y = 0x%08x\n", y);
|
||||
if (y == CODE_user_profile_photo_empty) {
|
||||
U->photo_small.dc = -2;
|
||||
U->photo_big.dc = -2;
|
||||
} else {
|
||||
assert (y == CODE_user_profile_photo || y == 0x990d1493);
|
||||
if (y == CODE_user_profile_photo) {
|
||||
fetch_long ();
|
||||
if (x == CODE_user_self) {
|
||||
U->flags |= FLAG_USER_SELF;
|
||||
} else {
|
||||
need_update |= fetch_update_long (&U->access_hash);
|
||||
}
|
||||
if (x == CODE_user_foreign) {
|
||||
U->flags |= FLAG_USER_FOREIGN;
|
||||
} else {
|
||||
need_update |= fetch_update_str (&U->phone);
|
||||
}
|
||||
unsigned y = fetch_int ();
|
||||
if (y == CODE_user_profile_photo_empty) {
|
||||
need_update |= set_update_int (&U->photo_small.dc, -2);
|
||||
need_update |= set_update_int (&U->photo_big.dc, -2);
|
||||
} else {
|
||||
assert (y == CODE_user_profile_photo);
|
||||
fetch_long ();
|
||||
need_update |= fetch_file_location (&U->photo_small);
|
||||
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) {
|
||||
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);
|
||||
U->id = MK_ENCR_CHAT (fetch_int ());
|
||||
if ((U->flags & FLAG_CREATED) && x == CODE_encrypted_chat_empty) {
|
||||
return;
|
||||
}
|
||||
U->flags &= ~(FLAG_EMPTY | FLAG_DELETED);
|
||||
enum secret_chat_state old_state = U->state;
|
||||
if (x == CODE_encrypted_chat_empty) {
|
||||
@ -210,11 +236,18 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
U->flags |= FLAG_CREATED;
|
||||
if (x == CODE_encrypted_chat_discarded) {
|
||||
U->state = sc_deleted;
|
||||
U->flags |= FLAG_DELETED;
|
||||
if (U->state != old_state) {
|
||||
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;
|
||||
}
|
||||
@ -222,19 +255,31 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
||||
U->date = fetch_int ();
|
||||
U->admin_id = fetch_int ();
|
||||
U->user_id = fetch_int () + U->admin_id - our_id;
|
||||
if (U->print_name) { free (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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (x == CODE_encrypted_chat_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) {
|
||||
U->state = sc_request;
|
||||
if (!U->g_key) {
|
||||
@ -259,6 +304,18 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
||||
} else {
|
||||
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 {
|
||||
U->state = sc_ok;
|
||||
if (!U->g_key) {
|
||||
@ -291,6 +348,18 @@ void fetch_encrypted_chat (struct secret_chat *U) {
|
||||
if (old_state == sc_waiting) {
|
||||
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) {
|
||||
write_secret_chat_file ();
|
||||
@ -941,13 +1010,13 @@ struct user *fetch_alloc_user (void) {
|
||||
prefetch_data (data, 8);
|
||||
peer_t *U = user_chat_get (MK_USER (data[1]));
|
||||
if (U) {
|
||||
fetch_user (&U->user);
|
||||
fetch_add_alloc_log_event (&U->user, (void *)fetch_user);
|
||||
return &U->user;
|
||||
} else {
|
||||
users_allocated ++;
|
||||
U = malloc (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 ());
|
||||
Peers[peer_num ++] = U;
|
||||
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 U;
|
||||
static peer_t U;
|
||||
U.id = id;
|
||||
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_FORBIDDEN 4
|
||||
#define FLAG_HAS_PHOTO 8
|
||||
#define FLAG_CREATED 16
|
||||
|
||||
#define FLAG_USER_SELF 128
|
||||
#define FLAG_USER_FOREIGN 256
|
||||
@ -113,6 +114,7 @@ struct user {
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_name;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
@ -137,6 +139,7 @@ struct chat {
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_title;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
@ -161,6 +164,7 @@ struct secret_chat {
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_name;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
@ -183,6 +187,7 @@ typedef union peer {
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_name;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
@ -262,9 +267,9 @@ struct message {
|
||||
};
|
||||
};
|
||||
|
||||
void fetch_file_location (struct file_location *loc);
|
||||
void fetch_user_status (struct user_status *S);
|
||||
void fetch_user (struct user *U);
|
||||
int fetch_file_location (struct file_location *loc);
|
||||
int fetch_user_status (struct user_status *S);
|
||||
int fetch_user (struct user *U);
|
||||
struct user *fetch_alloc_user (void);
|
||||
struct user *fetch_alloc_user_full (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_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);
|
||||
peer_t *user_chat_get (peer_id_t id);
|
||||
struct message *message_get (long long id);
|
||||
|
Loading…
Reference in New Issue
Block a user