Commit 8ad5053c authored by Vysheng's avatar Vysheng

Partial support for binlog. It now can track user, secret chat and auth updates.

parent 0d994828
...@@ -7,7 +7,7 @@ DEFS=-DHAVE_CONFIG_H ...@@ -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@ ...@@ -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
......
...@@ -11,10 +11,7 @@ ...@@ -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); ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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);
} }
#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
...@@ -160,6 +160,7 @@ void write_dc (int auth_file_fd, struct dc *DC) { ...@@ -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) { ...@@ -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; ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 @@ ...@@ -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; ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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, ...@@ -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) { ...@@ -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) { ...@@ -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;
} }
......
...@@ -44,6 +44,7 @@ ...@@ -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; ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 = { ...@@ -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) { ...@@ -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); ...@@ -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
...@@ -30,6 +30,7 @@ ...@@ -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; ...@@ -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;
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));
}
}
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) { if (x == CODE_file_location_unavailable) {
loc->dc = -1; new |= set_update_int (&loc->dc, -1);
loc->volume = fetch_long (); new |= fetch_update_long (&loc->volume);
loc->local_id = fetch_int (); new |= fetch_update_int (&loc->local_id);
loc->secret = fetch_long (); new |= fetch_update_long (&loc->secret);
} else { } else {
assert (x == CODE_file_location); assert (x == CODE_file_location);
loc->dc = fetch_int ();; new |= fetch_update_int (&loc->dc);
loc->volume = fetch_long (); new |= fetch_update_long (&loc->volume);
loc->local_id = fetch_int (); new |= fetch_update_int (&loc->local_id);
loc->secret = fetch_long (); new |= fetch_update_long (&loc->secret);
} }
return new;
} }
void fetch_user_status (struct user_status *S) { int fetch_user_status (struct user_status *S) {
int x = fetch_int (); 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) { ...@@ -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 ...@@ -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 {
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 { } else {
assert (y == CODE_user_profile_photo || y == 0x990d1493); if (x == CODE_user_self) {
if (y == CODE_user_profile_photo) { 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 (); 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) { 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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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);
} }
......
...@@ -26,6 +26,7 @@ typedef struct { int type; int id; } peer_id_t; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment