diff --git a/binlog.c b/binlog.c index 75aeaa9..0fadb63 100644 --- a/binlog.c +++ b/binlog.c @@ -1193,6 +1193,28 @@ static int fetch_comb_binlog_delete_msg (void *extra) { return 0; } + +static int fetch_comb_binlog_msg_seq_update (void *extra) { + struct tgl_message *M = tgl_message_get (fetch_long ()); + assert (M); + tgl_state.seq ++; + + if (tgl_state.callback.msg_receive) { + tgl_state.callback.msg_receive (M); + } + return 0; +} + +static int fetch_comb_binlog_msg_update (void *extra) { + struct tgl_message *M = tgl_message_get (fetch_long ()); + assert (M); + + if (tgl_state.callback.msg_receive) { + tgl_state.callback.msg_receive (M); + } + return 0; +} + #define FETCH_COMBINATOR_FUNCTION(NAME) \ case CODE_ ## NAME:\ ok = fetch_comb_ ## NAME (0); \ @@ -1275,6 +1297,8 @@ static void replay_log_event (void) { FETCH_COMBINATOR_FUNCTION (binlog_set_message_sent) FETCH_COMBINATOR_FUNCTION (binlog_set_msg_id) FETCH_COMBINATOR_FUNCTION (binlog_delete_msg) + FETCH_COMBINATOR_FUNCTION (binlog_msg_seq_update) + FETCH_COMBINATOR_FUNCTION (binlog_msg_update) default: vlogprintf (E_ERROR, "Unknown op 0x%08x\n", op); assert (0); @@ -1989,3 +2013,17 @@ void bl_do_delete_msg (struct tgl_message *M) { out_long (M->id); add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); } + +void bl_do_msg_seq_update (long long id) { + clear_packet (); + out_int (CODE_binlog_msg_seq_update); + out_long (id); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_msg_update (long long id) { + clear_packet (); + out_int (CODE_binlog_msg_update); + out_long (id); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} diff --git a/binlog.h b/binlog.h index c059303..cdaaa29 100644 --- a/binlog.h +++ b/binlog.h @@ -83,4 +83,7 @@ void bl_do_set_unread (struct tgl_message *M, int unread); void bl_do_set_message_sent (struct tgl_message *M); void bl_do_set_msg_id (struct tgl_message *M, int id); void bl_do_delete_msg (struct tgl_message *M); + +void bl_do_msg_seq_update (long long id); +void bl_do_msg_update (long long id); #endif diff --git a/binlog.tl b/binlog.tl index 74290ae..4cc334a 100644 --- a/binlog.tl +++ b/binlog.tl @@ -64,3 +64,6 @@ binlog.messageSetUnread id:int = binlog.Update; binlog.setMessageSent id:long = binlog.Update; binlog.setMsgId old_id:long new_id:int = binlog.Update; binlog.deleteMsg id:long = binlog.Update; + +binlog.msgSeqUpdate id:long = binlog.Update; +binlog.msgUpdate id:long = binlog.Update; diff --git a/interface.c b/interface.c index a819b3d..2856fef 100644 --- a/interface.c +++ b/interface.c @@ -681,7 +681,7 @@ void interpreter_chat_mode (char *line) { return; } if (strlen (line)>0) { - tgl_do_send_message (chat_mode_id, line, strlen (line), print_msg_gw, 0); + tgl_do_send_message (chat_mode_id, line, strlen (line), 0, 0); } } @@ -740,7 +740,8 @@ struct tgl_update_callback upd_cb = { .secret_chat_request = 0, .secret_chat_established = 0, .secret_chat_deleted = 0, - .secret_chat_accepted = 0 + .secret_chat_accepted = 0, + .msg_receive = print_message_gw }; @@ -829,7 +830,7 @@ void interpreter (char *line UU) { printf ("Empty message\n"); RET; } - tgl_do_send_message (id, s, strlen (s), print_msg_gw, 0); + tgl_do_send_message (id, s, strlen (s), 0, 0); } else if (IS_WORD ("rename_chat")) { GET_PEER_CHAT; int t; @@ -838,7 +839,7 @@ void interpreter (char *line UU) { printf ("Empty new name\n"); RET; } - tgl_do_rename_chat (id, s, print_msg_gw, 0); + tgl_do_rename_chat (id, s, 0, 0); } else if (IS_WORD ("send_photo")) { GET_PEER; int t; @@ -847,7 +848,7 @@ void interpreter (char *line UU) { printf ("Empty file name\n"); RET; } - tgl_do_send_photo (tgl_message_media_photo, id, strndup (s, t), print_msg_gw, 0); + tgl_do_send_photo (tgl_message_media_photo, id, strndup (s, t), 0, 0); } else if (IS_WORD("send_video")) { GET_PEER; int t; @@ -856,7 +857,7 @@ void interpreter (char *line UU) { printf ("Empty file name\n"); RET; } - tgl_do_send_photo (tgl_message_media_video, id, strndup (s, t), print_msg_gw, 0); + tgl_do_send_photo (tgl_message_media_video, id, strndup (s, t), 0, 0); } else if (IS_WORD ("send_text")) { GET_PEER; int t; @@ -865,7 +866,7 @@ void interpreter (char *line UU) { printf ("Empty file name\n"); RET; } - tgl_do_send_text (id, strndup (s, t), print_msg_gw, 0); + tgl_do_send_text (id, strndup (s, t), 0, 0); } else if (IS_WORD ("fwd")) { GET_PEER; int num = next_token_int (); @@ -873,7 +874,7 @@ void interpreter (char *line UU) { printf ("Bad msg id\n"); RET; } - tgl_do_forward_message (id, num, print_msg_gw, 0); + tgl_do_forward_message (id, num, 0, 0); } else if (IS_WORD ("load_photo")) { long long num = next_token_int (); if (num == NOT_FOUND) { @@ -974,12 +975,12 @@ void interpreter (char *line UU) { GET_PEER_CHAT; tgl_peer_id_t chat_id = id; GET_PEER_USER; - tgl_do_add_user_to_chat (chat_id, id, 100, print_msg_gw, 0); + tgl_do_add_user_to_chat (chat_id, id, 100, 0, 0); } else if (IS_WORD ("chat_del_user")) { GET_PEER_CHAT; tgl_peer_id_t chat_id = id; GET_PEER_USER; - tgl_do_del_user_from_chat (chat_id, id, print_msg_gw, 0); + tgl_do_del_user_from_chat (chat_id, id, 0, 0); } else if (IS_WORD ("add_contact")) { int phone_len, first_name_len, last_name_len; char *phone, *first_name, *last_name; @@ -1129,7 +1130,7 @@ void interpreter (char *line UU) { printf ("Empty chat topic\n"); RET; } - tgl_do_create_group_chat (id, s, print_msg_gw, 0); + tgl_do_create_group_chat (id, s, 0, 0); //} else if (IS_WORD ("suggested_contacts")) { // tgl_do_get_suggested (); } else if (IS_WORD ("status_online")) { @@ -1152,7 +1153,7 @@ void interpreter (char *line UU) { printf ("Empty file name\n"); RET; } - tgl_do_send_photo (tgl_message_media_audio, id, strndup (s, t), print_msg_gw, 0); + tgl_do_send_photo (tgl_message_media_audio, id, strndup (s, t), 0, 0); } else if (IS_WORD("send_document")) { GET_PEER; int t; @@ -1161,7 +1162,7 @@ void interpreter (char *line UU) { printf ("Empty file name\n"); RET; } - tgl_do_send_photo (tgl_message_media_document, id, strndup (s, t), print_msg_gw, 0); + tgl_do_send_photo (tgl_message_media_document, id, strndup (s, t), 0, 0); } else if (IS_WORD ("load_audio")) { long long num = next_token_int (); if (num == NOT_FOUND) { diff --git a/loop.c b/loop.c index c186b5b..ae865ce 100644 --- a/loop.c +++ b/loop.c @@ -63,6 +63,7 @@ extern int unknown_user_list[]; int register_mode; extern int safe_quit; int queries_num; +extern int sync_from_start; void got_it (char *line, int len); @@ -366,7 +367,7 @@ int loop (void) { set_interface_callbacks (); - tgl_do_get_difference (0, get_difference_callback, 0); + tgl_do_get_difference (sync_from_start, get_difference_callback, 0); net_loop (0, dgot); #ifdef USE_LUA lua_diff_end (); diff --git a/queries.c b/queries.c index 63aeb6b..567f746 100644 --- a/queries.c +++ b/queries.c @@ -774,6 +774,7 @@ static int msg_send_encr_on_answer (struct query *q UU) { //M->date = fetch_int (); fetch_int (); bl_do_set_message_sent (M); + bl_do_msg_update (M->id); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); @@ -789,7 +790,14 @@ static int msg_send_on_answer (struct query *q UU) { bl_do_set_msg_id (M, id); tglu_fetch_date (); tglu_fetch_pts (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + //bl_do_ + int seq = fetch_int (); + if (seq == tgl_state.seq + 1) { + bl_do_msg_seq_update (id); + } else { + tgl_do_get_difference (0, 0, 0); + } if (x == CODE_messages_sent_message_link) { assert (skip_type_any (TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (contacts_link))) >= 0); } @@ -1005,7 +1013,8 @@ void tgl_do_send_text (tgl_peer_id_t id, char *file_name, void (*callback)(void static int mark_read_on_receive (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_affected_history); tglu_fetch_pts (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + fetch_int (); // seq fetch_int (); // offset if (q->callback) { ((void (*)(void *, int))q->callback)(q->callback_extra, 1); @@ -1316,7 +1325,14 @@ static int send_file_on_answer (struct query *q UU) { tglf_fetch_alloc_user (); } tglu_fetch_pts (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + + int seq = fetch_int (); + if (seq == tgl_state.seq + 1) { + bl_do_msg_seq_update (M->id); + } else { + tgl_do_get_difference (0, 0, 0); + } if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback)(q->callback_extra, 1, M); @@ -1338,6 +1354,7 @@ static int send_encr_file_on_answer (struct query *q UU) { assert (fetch_int () == M->media.encr_photo.key_fingerprint); //print_message (M); tglm_message_insert (M); + bl_do_msg_update (M->id); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback)(q->callback_extra, 1, M); @@ -1654,7 +1671,13 @@ static int fwd_msg_on_answer (struct query *q UU) { tglf_fetch_alloc_user (); } tglu_fetch_pts (); - tglu_fetch_seq (); + + int seq = fetch_int (); + if (seq == tgl_state.seq + 1) { + bl_do_msg_seq_update (M->id); + } else { + tgl_do_get_difference (0, 0, 0); + } //print_message (M); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); @@ -1698,7 +1721,12 @@ static int rename_chat_on_answer (struct query *q UU) { tglf_fetch_alloc_user (); } tglu_fetch_pts (); - tglu_fetch_seq (); + int seq = fetch_int (); + if (seq == tgl_state.seq + 1) { + bl_do_msg_seq_update (M->id); + } else { + tgl_do_get_difference (0, 0, 0); + } //print_message (M); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); @@ -2739,15 +2767,20 @@ static int get_difference_on_answer (struct query *q UU) { print_message (ML[i]); }*/ for (i = 0; i < ml_pos; i++) { - tgl_state.callback.new_msg (ML[i]); + //tgl_state.callback.new_msg (ML[i]); + bl_do_msg_update (ML[i]->id); } for (i = 0; i < el_pos; i++) { - tgl_state.callback.new_msg (EL[i]); + //tgl_state.callback.new_msg (EL[i]); + bl_do_msg_update (EL[i]->id); } tfree (ML, ml_pos * sizeof (void *)); tfree (EL, el_pos * sizeof (void *)); if (x == CODE_updates_difference_slice) { + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } tgl_do_get_difference (0, q->callback, q->callback_extra); } else { //difference_got = 1; diff --git a/structures.c b/structures.c index 1bd37b6..ab4bea2 100644 --- a/structures.c +++ b/structures.c @@ -642,7 +642,8 @@ void tglf_fetch_message_short (struct tgl_message *M) { tglu_fetch_pts (); int date = fetch_int (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + fetch_int (); bl_do_create_message_text (id, from_id, TGL_PEER_USER, to_id, date, l, s); } else { @@ -653,7 +654,8 @@ void tglf_fetch_message_short (struct tgl_message *M) { tglu_fetch_pts (); fetch_int (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + fetch_int (); } } @@ -670,8 +672,9 @@ void tglf_fetch_message_short_chat (struct tgl_message *M) { tglu_fetch_pts (); int date = fetch_int (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + fetch_int (); bl_do_create_message_text (id, from_id, TGL_PEER_CHAT, to_id, date, l, s); } else { fetch_int (); // id @@ -682,7 +685,8 @@ void tglf_fetch_message_short_chat (struct tgl_message *M) { tglu_fetch_pts (); fetch_int (); - tglu_fetch_seq (); + //tglu_fetch_seq (); + fetch_int (); } } diff --git a/tgl.h b/tgl.h index 6a66ec4..d2cc672 100644 --- a/tgl.h +++ b/tgl.h @@ -39,6 +39,7 @@ struct tgl_update_callback { //void (*secret_chat_created)(struct tgl_secret_chat *U); void (*chat_created)(struct tgl_chat *C); void (*chat_update)(struct tgl_chat *C); + void (*msg_receive)(struct tgl_message *M); }; struct tgl_net_methods { diff --git a/updates.c b/updates.c index 1da3cf3..1397be4 100644 --- a/updates.c +++ b/updates.c @@ -657,10 +657,30 @@ void tglu_work_update_short (struct connection *c, long long msg_id) { assert (save_end == in_ptr); } + +static int do_skip_seq (int seq) { + if (tgl_state.seq) { + if (seq <= tgl_state.seq) { + vlogprintf (E_NOTICE, "Duplicate message with seq=%d\n", seq); + return -1; + } + if (seq > tgl_state.seq + 1) { + vlogprintf (E_NOTICE, "Hole in seq (seq = %d, cur_seq = %d)\n", seq, tgl_state.seq); + tgl_do_get_difference (0, 0, 0); + return -1; + } + return 0; + } else { + return -1; + } +} void tglu_work_updates (struct connection *c, long long msg_id) { int *save = in_ptr; assert (!skip_type_any (TYPE_TO_PARAM (updates))); + if (do_skip_seq (*(in_ptr - 1)) < 0) { + return; + } int *save_end = in_ptr; in_ptr = save; assert (fetch_int () == CODE_updates); @@ -681,13 +701,17 @@ void tglu_work_updates (struct connection *c, long long msg_id) { tglf_fetch_alloc_chat (); } bl_do_set_date (fetch_int ()); - bl_do_set_seq (fetch_int ()); + //bl_do_set_seq (fetch_int ()); + fetch_int (); assert (save_end == in_ptr); } void tglu_work_update_short_message (struct connection *c, long long msg_id) { int *save = in_ptr; assert (!skip_type_any (TYPE_TO_PARAM (updates))); + if (do_skip_seq (*(in_ptr - 1)) < 0) { + return; + } int *save_end = in_ptr; in_ptr = save; @@ -707,6 +731,9 @@ void tglu_work_update_short_message (struct connection *c, long long msg_id) { void tglu_work_update_short_chat_message (struct connection *c, long long msg_id) { int *save = in_ptr; assert (!skip_type_any (TYPE_TO_PARAM (updates))); + if (do_skip_seq (*(in_ptr - 1)) < 0) { + return; + } int *save_end = in_ptr; in_ptr = save; @@ -720,6 +747,8 @@ void tglu_work_update_short_chat_message (struct connection *c, long long msg_id last_date = M->date; }*/ assert (save_end == in_ptr); + + bl_do_msg_seq_update (M->id); } void tglu_work_updates_to_long (struct connection *c, long long msg_id) {