diff --git a/binlog.c b/binlog.c index 30f536f..651957a 100644 --- a/binlog.c +++ b/binlog.c @@ -430,6 +430,22 @@ static int fetch_comb_binlog_encr_chat_set_date (void *extra) { return 0; } +static int fetch_comb_binlog_encr_chat_set_ttl (void *extra) { + tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); + tgl_peer_t *U = tgl_peer_get (id); + assert (U); + U->encr_chat.ttl = fetch_int (); + return 0; +} + +static int fetch_comb_binlog_encr_chat_set_layer (void *extra) { + tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); + tgl_peer_t *U = tgl_peer_get (id); + assert (U); + U->encr_chat.layer = fetch_int (); + return 0; +} + static int fetch_comb_binlog_encr_chat_set_state (void *extra) { tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); tgl_peer_t *U = tgl_peer_get (id); @@ -498,6 +514,24 @@ static int fetch_comb_binlog_encr_chat_init (void *extra) { return 0; } +static int fetch_comb_binlog_encr_chat_create (void *extra) { + tgl_peer_t *P = talloc0 (sizeof (*P)); + P->id = TGL_MK_ENCR_CHAT (fetch_int ()); + assert (!tgl_peer_get (P->id)); + P->encr_chat.user_id = fetch_int (); + P->encr_chat.admin_id = fetch_int (); + tglp_insert_encrypted_chat (P); + P->print_name = fetch_str_dup (); + tglp_peer_insert_name (P); + + P->flags |= FLAG_CREATED; + + if (tgl_state.callback.secret_chat_update) { + tgl_state.callback.secret_chat_update ((void *)P, TGL_UPDATE_CREATED); + } + return 0; +} + static int fetch_comb_binlog_chat_create (void *extra) { tgl_peer_id_t id = TGL_MK_CHAT (fetch_int ()); tgl_peer_t *_C = tgl_peer_get (id); @@ -1160,10 +1194,13 @@ static void replay_log_event (void) { FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_requested) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_access_hash) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_date) + FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_ttl) + FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_layer) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_state) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_accepted) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_key) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_init) + FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_create) FETCH_COMBINATOR_FUNCTION (binlog_chat_create) FETCH_COMBINATOR_FUNCTION (binlog_chat_change_flags) @@ -1530,6 +1567,24 @@ void bl_do_encr_chat_set_date (struct tgl_secret_chat *U, int date) { add_log_event (ev, 12); } +void bl_do_encr_chat_set_ttl (struct tgl_secret_chat *U, int ttl) { + if (U->ttl == ttl) { return; } + int *ev = alloc_log_event (12); + ev[0] = CODE_binlog_encr_chat_set_ttl; + ev[1] = tgl_get_peer_id (U->id); + ev[2] = ttl; + add_log_event (ev, 12); +} + +void bl_do_encr_chat_set_layer (struct tgl_secret_chat *U, int layer) { + if (U->layer == layer) { return; } + int *ev = alloc_log_event (12); + ev[0] = CODE_binlog_encr_chat_set_layer; + ev[1] = tgl_get_peer_id (U->id); + ev[2] = layer; + add_log_event (ev, 12); +} + void bl_do_encr_chat_set_state (struct tgl_secret_chat *U, enum tgl_secret_chat_state state) { if (U->state == state) { return; } int *ev = alloc_log_event (12); @@ -1550,6 +1605,16 @@ void bl_do_encr_chat_accepted (struct tgl_secret_chat *U, const unsigned char g_ add_log_event (ev, 528); } +void bl_do_encr_chat_create (int id, int user_id, int admin_id, char *name, int name_len) { + clear_packet (); + out_int (CODE_binlog_encr_chat_create); + out_int (id); + out_int (user_id); + out_int (admin_id); + out_cstring (name, name_len); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + void bl_do_encr_chat_set_key (struct tgl_secret_chat *E, unsigned char key[], long long key_fingerprint) { int *ev = alloc_log_event (272); ev[0] = CODE_binlog_encr_chat_set_key; diff --git a/binlog.h b/binlog.h index dc1e225..6f0732e 100644 --- a/binlog.h +++ b/binlog.h @@ -41,9 +41,12 @@ void bl_do_user_set_real_name (struct tgl_user *U, const char *f, int fl, const void bl_do_encr_chat_delete (struct tgl_secret_chat *U); void bl_do_encr_chat_requested (struct tgl_secret_chat *U, long long access_hash, int date, int admin_id, int user_id, unsigned char g_key[], unsigned char nonce[]); +void bl_do_encr_chat_create (int id, int user_id, int admin_id, char *name, int name_len); void bl_do_encr_chat_set_access_hash (struct tgl_secret_chat *U, long long access_hash); void bl_do_encr_chat_set_date (struct tgl_secret_chat *U, int date); void bl_do_encr_chat_set_state (struct tgl_secret_chat *U, enum tgl_secret_chat_state state); +void bl_do_encr_chat_set_ttl (struct tgl_secret_chat *U, int ttl); +void bl_do_encr_chat_set_layer (struct tgl_secret_chat *U, int layer); void bl_do_encr_chat_accepted (struct tgl_secret_chat *U, const unsigned char g_key[], const unsigned char nonce[], long long key_fingerprint); void bl_do_encr_chat_set_key (struct tgl_secret_chat *E, unsigned char key[], long long key_fingerprint); void bl_do_encr_chat_init (int id, int user_id, unsigned char random[], unsigned char g_a[]); diff --git a/binlog.tl b/binlog.tl index 56d2cad..0460133 100644 --- a/binlog.tl +++ b/binlog.tl @@ -32,9 +32,12 @@ binlog.encrChatDelete id:int = binlog.Update; binlog.encrChatRequested id:int hash:long date:int admin:int user:int key:64*[int] nonce:64*[int] = binlog.Update; binlog.encrChatAccepted id:int key:64*[int] nonce:64*[int] fingerprint:long = binlog.Update; binlog.encrChatInit id:int user:int key:64*[int] g_key:64*[int] = binlog.Update; +binlog.encrChatCreate id:int user_id:int admin_id:int name:string = binlog.Update; binlog.encrChatSetAccessHash id:int hash:long = binlog.Update; binlog.encrChatSetDate id:int date:int = binlog.Update; +binlog.encrChatSetTtl id:int ttl:int = binlog.Update; +binlog.encrChatSetLayer id:int layer:int = binlog.Update; binlog.encrChatSetState id:int state:int = binlog.Update; binlog.encrChatSetKey id:int key:64*[int] fingerprint:long = binlog.Update; diff --git a/interface.c b/interface.c index 685a7e7..d1f20ce 100644 --- a/interface.c +++ b/interface.c @@ -54,6 +54,7 @@ //#include "mtproto-common.h" #include "tgl.h" +#include "loop.h" #ifndef PATH_MAX #define PATH_MAX 4096 @@ -961,6 +962,9 @@ void secret_chat_update_gw (struct tgl_secret_chat *U, unsigned flags) { if (!binlog_read) { return; } + if ((flags & TGL_UPDATE_WORKING) || (flags & TGL_UPDATE_DELETED)) { + write_secret_chat_file (); + } if ((flags & TGL_UPDATE_REQUESTED) && !disable_auto_accept) { tgl_do_accept_encr_chat_request (U, 0, 0); } diff --git a/loop.c b/loop.c index a31cc2b..c1f4aa7 100644 --- a/loop.c +++ b/loop.c @@ -313,9 +313,11 @@ extern struct tgl_update_callback upd_cb; #define DC_SERIALIZED_MAGIC 0x868aa81d #define STATE_FILE_MAGIC 0x28949a93 -#define SECRET_FILE_MAGIX 0x37a1988a +#define SECRET_CHAT_FILE_MAGIC 0x37a1988a + char *get_auth_key_filename (void); char *get_state_filename (void); +char *get_secret_chat_filename (void); void read_state_file (void) { if (binlog_enabled) { return; } @@ -405,6 +407,52 @@ void write_auth_file (void) { close (auth_file_fd); } +void write_secret_chat (tgl_peer_t *_P, void *extra) { + struct tgl_secret_chat *P = (void *)_P; + if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) { return; } + if (P->state != sc_ok) { return; } + int *a = extra; + int fd = a[0]; + a[1] ++; + + int id = tgl_get_peer_id (P->id); + assert (write (fd, &id, 4) == 4); + //assert (write (fd, &P->flags, 4) == 4); + int l = strlen (P->print_name); + assert (write (fd, &l, 4) == 4); + assert (write (fd, P->print_name, l) == l); + assert (write (fd, &P->user_id, 4) == 4); + assert (write (fd, &P->admin_id, 4) == 4); + assert (write (fd, &P->date, 4) == 4); + assert (write (fd, &P->ttl, 4) == 4); + assert (write (fd, &P->layer, 4) == 4); + assert (write (fd, &P->access_hash, 8) == 8); + assert (write (fd, &P->state, 4) == 4); + assert (write (fd, &P->key_fingerprint, 8) == 8); + assert (write (fd, &P->key, 256) == 256); +} + +void write_secret_chat_file (void) { + if (binlog_enabled) { return; } + int secret_chat_fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); + assert (secret_chat_fd >= 0); + int x = SECRET_CHAT_FILE_MAGIC; + assert (write (secret_chat_fd, &x, 4) == 4); + x = 0; + assert (write (secret_chat_fd, &x, 4) == 4); // version + assert (write (secret_chat_fd, &x, 4) == 4); // num + + int y[2]; + y[0] = secret_chat_fd; + y[1] = 0; + + tgl_peer_iterator_ex (write_secret_chat, y); + + lseek (secret_chat_fd, 8, SEEK_SET); + assert (write (secret_chat_fd, &y[1], 4) == 4); + close (secret_chat_fd); +} + void read_dc (int auth_file_fd, int id, unsigned ver) { int port = 0; assert (read (auth_file_fd, &port, 4) == 4); @@ -473,6 +521,54 @@ void read_auth_file (void) { close (auth_file_fd); } +void read_secret_chat (int fd) { + int id, l, user_id, admin_id, date, ttl, layer, state; + long long access_hash, key_fingerprint; + static char s[1000]; + static unsigned char key[256]; + assert (read (fd, &id, 4) == 4); + //assert (read (fd, &flags, 4) == 4); + assert (read (fd, &l, 4) == 4); + assert (l > 0 && l < 1000); + assert (read (fd, s, l) == l); + assert (read (fd, &user_id, 4) == 4); + assert (read (fd, &admin_id, 4) == 4); + assert (read (fd, &date, 4) == 4); + assert (read (fd, &ttl, 4) == 4); + assert (read (fd, &layer, 4) == 4); + assert (read (fd, &access_hash, 8) == 8); + assert (read (fd, &state, 4) == 4); + assert (read (fd, &key_fingerprint, 8) == 8); + assert (read (fd, &key, 256) == 256); + + bl_do_encr_chat_create (id, user_id, admin_id, s, l); + struct tgl_secret_chat *P = (void *)tgl_peer_get (TGL_MK_ENCR_CHAT (id)); + assert (P && (P->flags & FLAG_CREATED)); + bl_do_encr_chat_set_date (P, date); + bl_do_encr_chat_set_ttl (P, ttl); + bl_do_encr_chat_set_layer (P, layer); + bl_do_encr_chat_set_access_hash (P, access_hash); + bl_do_encr_chat_set_state (P, state); + bl_do_encr_chat_set_key (P, key, key_fingerprint); +} + +void read_secret_chat_file (void) { + if (binlog_enabled) { return; } + int secret_chat_fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); + assert (secret_chat_fd >= 0); + int x; + assert (read (secret_chat_fd, &x, 4) == 4); + assert (x == SECRET_CHAT_FILE_MAGIC); + assert (read (secret_chat_fd, &x, 4) == 4); + assert (!x); // version + assert (read (secret_chat_fd, &x, 4) == 4); + assert (x >= 0); + while (x --> 0) { + read_secret_chat (secret_chat_fd); + } + close (secret_chat_fd); +} + void dlist_cb (void *callback_extra, int success, int size, tgl_peer_id_t peers[], int last_msg_id[], int unread_count[]) { d_got_ok = 1; } @@ -495,6 +591,7 @@ int loop (void) { } else { read_auth_file (); read_state_file (); + read_secret_chat_file (); } binlog_read = 1; #ifdef USE_LUA