From 725c6669a7d84d2293b00acc8d9b3cb81807d2d6 Mon Sep 17 00:00:00 2001 From: Vysheng Date: Sat, 30 Nov 2013 01:43:56 +0400 Subject: [PATCH] Manty fixes. Mostly binlog for messages --- binlog.c | 466 +++++++++++++++++++++++++++++++++- binlog.h | 25 ++ interface.c | 3 +- loop.c | 5 + mtproto-client.c | 6 +- mtproto-common.h | 2 +- queries.c | 119 ++++----- queries.h | 1 + structures.c | 631 +++++++++++++++++++++++++++++++++++------------ structures.h | 15 ++ telegram.h | 4 +- 11 files changed, 1040 insertions(+), 237 deletions(-) diff --git a/binlog.c b/binlog.c index 2860157..3e69207 100644 --- a/binlog.c +++ b/binlog.c @@ -38,6 +38,7 @@ extern int binlog_enabled; extern int encr_root; extern unsigned char *encr_prime; extern int encr_param_version; +extern int messages_allocated; int in_replay_log; @@ -53,11 +54,12 @@ void replay_log_event (void) { assert (rptr < wptr); int op = *rptr; + if (verbosity >= 2) { + logprintf ("log_pos %lld, op 0x%08x\n", binlog_pos, op); + } + in_ptr = rptr; in_end = wptr; - if (verbosity >= 2) { - logprintf ("event = 0x%08x. pos = %lld\n", op, binlog_pos); - } switch (op) { case LOG_START: rptr ++; @@ -703,6 +705,319 @@ void replay_log_event (void) { C->user_list_version = version; } break; + case CODE_binlog_create_message_text: + case CODE_binlog_send_message_text: + in_ptr ++; + { + long long id; + if (op == CODE_binlog_create_message_text) { + id = fetch_int (); + } else { + id = fetch_long (); + } + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + if (t == PEER_ENCR_CHAT) { + M->flags |= FLAG_ENCRYPTED; + } + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + + int l = prefetch_strlen (); + M->message = malloc (l + 1); + memcpy (M->message, fetch_str (l), l); + M->message[l] = 0; + M->message_len = l; + + if (t == PEER_ENCR_CHAT) { + M->media.type = CODE_decrypted_message_media_empty; + } else { + M->media.type = CODE_message_media_empty; + } + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + + message_insert (M); + if (op == CODE_binlog_send_message_text) { + message_insert_unsent (M); + M->flags |= FLAG_PENDING; + } + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_text_fwd: + in_ptr ++; + { + int id = fetch_int (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + M->fwd_from_id = MK_USER (fetch_int ()); + M->fwd_date = fetch_int (); + + int l = prefetch_strlen (); + M->message = malloc (l + 1); + memcpy (M->message, fetch_str (l), l); + M->message[l] = 0; + M->message_len = l; + + M->media.type = CODE_message_media_empty; + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_media: + in_ptr ++; + { + int id = fetch_int (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + + int l = prefetch_strlen (); + M->message = malloc (l + 1); + memcpy (M->message, fetch_str (l), l); + M->message[l] = 0; + M->message_len = l; + + fetch_message_media (&M->media); + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_media_encr: + in_ptr ++; + { + long long id = fetch_long (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED | FLAG_ENCRYPTED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + + int l = prefetch_strlen (); + M->message = malloc (l + 1); + memcpy (M->message, fetch_str (l), l); + M->message[l] = 0; + M->message_len = l; + + fetch_message_media_encrypted (&M->media); + fetch_encrypted_message_file (&M->media); + + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_media_fwd: + in_ptr ++; + { + int id = fetch_int (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + M->fwd_from_id = MK_USER (fetch_int ()); + M->fwd_date = fetch_int (); + + int l = prefetch_strlen (); + M->message = malloc (l + 1); + memcpy (M->message, fetch_str (l), l); + M->message[l] = 0; + M->message_len = l; + + fetch_message_media (&M->media); + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_service: + in_ptr ++; + { + int id = fetch_int (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + + fetch_message_action (&M->action); + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + M->service = 1; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_service_encr: + in_ptr ++; + { + long long id = fetch_long (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED | FLAG_ENCRYPTED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + + fetch_message_action_encrypted (&M->action); + + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + M->service = 1; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_create_message_service_fwd: + in_ptr ++; + { + int id = fetch_int (); + struct message *M = message_get (id); + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = id; + message_insert_tree (M); + messages_allocated ++; + } else { + assert (!(M->flags & FLAG_CREATED)); + } + M->flags |= FLAG_CREATED; + M->from_id = MK_USER (fetch_int ()); + int t = fetch_int (); + M->to_id = set_peer_id (t, fetch_int ()); + M->date = fetch_int (); + M->fwd_from_id = MK_USER (fetch_int ()); + M->fwd_date = fetch_int (); + fetch_message_action (&M->action); + M->unread = 1; + M->out = get_peer_id (M->from_id) == our_id; + M->service = 1; + + message_insert (M); + } + rptr = in_ptr; + break; + case CODE_binlog_set_unread: + rptr ++; + { + struct message *M = message_get (*(rptr ++)); + assert (M); + M->unread = 0; + } + break; + case CODE_binlog_set_message_sent: + rptr ++; + { + struct message *M = message_get (*(long long *)rptr); + rptr += 2; + assert (M); + message_remove_unsent (M); + M->flags &= ~FLAG_PENDING; + } + break; + case CODE_binlog_set_msg_id: + rptr ++; + { + struct message *M = message_get (*(long long *)rptr); + rptr += 2; + assert (M); + message_remove_tree (M); + message_del_peer (M); + M->id = *(rptr ++); + message_insert_tree (M); + message_add_peer (M); + } + break; case CODE_update_user_photo: case CODE_update_user_name: work_update_binlog (); @@ -807,6 +1122,7 @@ void add_log_event (const int *data, int len) { assert (rptr == wptr); } if (binlog_enabled) { + assert (binlog_fd > 0); assert (write (binlog_fd, data, len) == len); } in_ptr = in; @@ -1009,6 +1325,7 @@ void bl_do_encr_chat_delete (struct secret_chat *U) { } void bl_do_encr_chat_requested (struct secret_chat *U, long long access_hash, int date, int admin_id, int user_id, unsigned char g_key[], unsigned char nonce[]) { + if (U->state != sc_none) { return; } int *ev = alloc_log_event (540); ev[0] = CODE_binlog_encr_chat_requested; ev[1] = get_peer_id (U->id); @@ -1258,3 +1575,146 @@ void bl_do_chat_del_user (struct chat *C, int version, int user) { ev[3] = user; add_log_event (ev, 16); } + +void bl_do_create_message_text (int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s) { + clear_packet (); + out_int (CODE_binlog_create_message_text); + out_int (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_cstring (s, l); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_send_message_text (long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s) { + clear_packet (); + out_int (CODE_binlog_send_message_text); + out_long (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_cstring (s, l); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_text_fwd (int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s) { + clear_packet (); + out_int (CODE_binlog_create_message_text_fwd); + out_int (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_int (fwd); + out_int (fwd_date); + out_cstring (s, l); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_media (int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len) { + clear_packet (); + out_int (CODE_binlog_create_message_media); + out_int (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_cstring (s, l); + out_ints (data, len); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_media_encr (long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len, const int *data2, int len2) { + clear_packet (); + out_int (CODE_binlog_create_message_media_encr); + out_long (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_cstring (s, l); + out_ints (data, len); + out_ints (data2, len2); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_media_fwd (int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s, const int *data, int len) { + clear_packet (); + out_int (CODE_binlog_create_message_media_fwd); + out_int (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_int (fwd); + out_int (fwd_date); + out_cstring (s, l); + out_ints (data, len); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_service (int msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len) { + clear_packet (); + out_int (CODE_binlog_create_message_service); + out_int (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_ints (data, len); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_service_encr (long long msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len) { + clear_packet (); + out_int (CODE_binlog_create_message_service_encr); + out_long (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_ints (data, len); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_create_message_service_fwd (int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, const int *data, int len) { + clear_packet (); + out_int (CODE_binlog_create_message_service_fwd); + out_int (msg_id); + out_int (from_id); + out_int (to_type); + out_int (to_id); + out_int (date); + out_int (fwd); + out_int (fwd_date); + out_ints (data, len); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_set_unread (struct message *M, int unread) { + if (unread || !M->unread) { return; } + clear_packet (); + out_int (CODE_binlog_set_unread); + out_int (M->id); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_set_message_sent (struct message *M) { + if (!(M->flags & FLAG_PENDING)) { return; } + clear_packet (); + out_int (CODE_binlog_set_message_sent); + out_long (M->id); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} + +void bl_do_set_msg_id (struct message *M, int id) { + if (M->id == id) { return; } + clear_packet (); + out_int (CODE_binlog_set_msg_id); + out_long (M->id); + out_int (id); + add_log_event (packet_buffer, 4 * (packet_ptr - packet_buffer)); +} diff --git a/binlog.h b/binlog.h index 02c7af5..a3e231a 100644 --- a/binlog.h +++ b/binlog.h @@ -51,6 +51,18 @@ #define CODE_binlog_chat_full_photo 0x6cca6629 #define CODE_binlog_add_chat_participant 0x63345108 #define CODE_binlog_del_chat_participant 0x82d1f0ee +#define CODE_binlog_create_message_text 0x269acd5b +#define CODE_binlog_create_message_text_fwd 0xa3d864cd +#define CODE_binlog_create_message_service 0xbbe5e94b +#define CODE_binlog_create_message_service_fwd 0xea9c57ae +#define CODE_binlog_create_message_media 0x62a92d19 +#define CODE_binlog_create_message_media_fwd 0xbefdc462 +#define CODE_binlog_send_message_text 0x31cfd652 +#define CODE_binlog_set_unread 0x21d4c909 +#define CODE_binlog_set_message_sent 0xc335282b +#define CODE_binlog_set_msg_id 0xf3285b6a +#define CODE_binlog_create_message_media_encr 0x19cd7c9d +#define CODE_binlog_create_message_service_encr 0x8b4b9395 void *alloc_log_event (int l); void replay_log (void); @@ -102,4 +114,17 @@ void bl_do_set_chat_participants (struct chat *C, int version, int user_num, str void bl_do_set_chat_full_photo (struct chat *U, const int *start, int len); void bl_do_chat_add_user (struct chat *C, int version, int user, int inviter, int date); void bl_do_chat_del_user (struct chat *C, int version, int user); + +void bl_do_create_message_text (int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s); +void bl_do_create_message_text_fwd (int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s); +void bl_do_create_message_service (int msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len); +void bl_do_create_message_service_fwd (int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, const int *data, int len); +void bl_do_create_message_media (int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len); +void bl_do_create_message_media_fwd (int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s, const int *data, int len); +void bl_do_create_message_media_encr (long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len, const int *data2, int len2); +void bl_do_create_message_service_encr (long long msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len); +void bl_do_send_message_text (long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s); +void bl_do_set_unread (struct message *M, int unread); +void bl_do_set_message_sent (struct message *M); +void bl_do_set_msg_id (struct message *M, int id); #endif diff --git a/interface.c b/interface.c index 2001df1..6460ba0 100644 --- a/interface.c +++ b/interface.c @@ -43,7 +43,7 @@ #include "mtproto-common.h" -//#define ALLOW_MULT 1 +#define ALLOW_MULT 1 char *default_prompt = "> "; int unread_messages; @@ -1096,6 +1096,7 @@ void pop_color (void) { void print_media (struct message_media *M) { switch (M->type) { case CODE_message_media_empty: + case CODE_decrypted_message_media_empty: return; case CODE_message_media_photo: if (M->photo.caption && strlen (M->photo.caption)) { diff --git a/loop.c b/loop.c index 4ac7a54..d9f3bf3 100644 --- a/loop.c +++ b/loop.c @@ -436,7 +436,10 @@ int new_dc_num; int loop (void) { on_start (); if (binlog_enabled) { + double t = get_double_time (); + logprintf ("replay log start\n"); replay_log (); + logprintf ("replay log end in %lf seconds\n", get_double_time () - t); write_binlog (); } else { read_auth_file (); @@ -571,6 +574,8 @@ int loop (void) { do_get_difference (); net_loop (0, dgot); + send_all_unsent (); + do_get_dialog_list (); return main_loop (); diff --git a/mtproto-client.c b/mtproto-client.c index 7b8836a..83e43f6 100644 --- a/mtproto-client.c +++ b/mtproto-client.c @@ -789,7 +789,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { int new = fetch_long (); // random_id struct message *M = message_get (new); if (M) { - update_message_id (M, id); + bl_do_set_msg_id (M, id); } } break; @@ -802,7 +802,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { int id = fetch_int (); struct message *M = message_get (id); if (M) { - M->unread = 0; + bl_do_set_unread (M, 0); } } fetch_pts (); @@ -885,7 +885,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { int l2 = prefetch_strlen (); char *l = fetch_str (l2); struct user *U = &UC->user; - bl_do_set_user_name (U, f, l1, l, l2); + bl_do_set_user_real_name (U, f, l1, l, l2); print_start (); push_color (COLOR_YELLOW); print_date (time (0)); diff --git a/mtproto-common.h b/mtproto-common.h index 79d4f3b..43efac1 100644 --- a/mtproto-common.h +++ b/mtproto-common.h @@ -226,7 +226,7 @@ long long compute_rsa_key_fingerprint (RSA *key); extern int *packet_buffer; extern int *packet_ptr; -static inline void out_ints (int *what, int len) { +static inline void out_ints (const int *what, int len) { assert (packet_ptr + len <= packet_buffer + PACKET_BUFFER_SIZE); memcpy (packet_ptr, what, len * 4); packet_ptr += len; diff --git a/queries.c b/queries.c index 85cec4a..e841793 100644 --- a/queries.c +++ b/queries.c @@ -779,8 +779,9 @@ int msg_send_encr_on_answer (struct query *q UU) { assert (fetch_int () == CODE_messages_sent_encrypted_message); rprintf ("Sent\n"); struct message *M = q->extra; - M->date = fetch_int (); - message_insert (M); + //M->date = fetch_int (); + fetch_int (); + bl_do_set_message_sent (M); return 0; } @@ -788,12 +789,11 @@ int msg_send_on_answer (struct query *q UU) { unsigned x = fetch_int (); assert (x == CODE_messages_sent_message || x == CODE_messages_sent_message_link); int id = fetch_int (); // id + struct message *M = q->extra; + bl_do_set_msg_id (M, id); fetch_date (); fetch_pts (); fetch_seq (); - struct message *M = q->extra; - M->id = id; - message_insert (M); if (x == CODE_messages_sent_message_link) { assert (fetch_int () == CODE_vector); int n = fetch_int (); @@ -834,6 +834,7 @@ int msg_send_on_answer (struct query *q UU) { } } rprintf ("Sent: id = %d\n", id); + bl_do_set_message_sent (M); return 0; } @@ -848,86 +849,62 @@ struct query_methods msg_send_encr_methods = { int out_message_num; int our_id; -void do_send_encr_message (peer_id_t id, const char *msg, int len) { - peer_t *P = user_chat_get (id); - if (!P) { - logprintf ("Can not send to unknown encrypted chat\n"); - return; - } - if (P->encr_chat.state != sc_ok) { - logprintf ("Chat is not yet initialized\n"); - return; - } +void do_send_encr_msg (struct message *M) { + peer_t *P = user_chat_get (M->to_id); + if (!P || P->encr_chat.state != sc_ok) { return; } + clear_packet (); out_int (CODE_messages_send_encrypted); out_int (CODE_input_encrypted_chat); - out_int (get_peer_id (id)); + out_int (get_peer_id (M->to_id)); out_long (P->encr_chat.access_hash); - if (!out_message_num) { - out_message_num = -lrand48 (); - } - out_long ((--out_message_num) - (4ll << 32)); + out_long (M->id); encr_start (); - //out_int (CODE_decrypted_message_layer); - //out_int (8); out_int (CODE_decrypted_message); - out_long ((out_message_num) - (4ll << 32)); + out_long (M->id); static int buf[4]; int i; for (i = 0; i < 3; i++) { buf[i] = mrand48 (); } out_cstring ((void *)buf, 16); - out_cstring ((void *)msg, len); + out_cstring ((void *)M->message, M->message_len); out_int (CODE_decrypted_message_media_empty); encr_finish (&P->encr_chat); - struct message *M = malloc (sizeof (*M)); - memset (M, 0, sizeof (*M)); - M->flags = FLAG_ENCRYPTED; - M->from_id = MK_USER (our_id); - M->to_id = id; - M->unread = 1; - M->message = malloc (len + 1); - memcpy (M->message, msg, len); - M->message[len] = 0; - M->message_len = len; - M->out = 1; - M->media.type = CODE_message_media_empty; - M->id = (out_message_num) - (4ll << 32); - M->date = time (0); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M); - print_message (M); +} + +void do_send_msg (struct message *M) { + if (get_peer_type (M->to_id) == PEER_ENCR_CHAT) { + do_send_encr_msg (M); + return; + } + clear_packet (); + out_int (CODE_messages_send_message); + out_peer_id (M->to_id); + out_cstring (M->message, M->message_len); + out_long (M->id); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, M); } void do_send_message (peer_id_t id, const char *msg, int len) { if (get_peer_type (id) == PEER_ENCR_CHAT) { - do_send_encr_message (id, msg, len); - return; + peer_t *P = user_chat_get (id); + if (!P) { + logprintf ("Can not send to unknown encrypted chat\n"); + return; + } + if (P->encr_chat.state != sc_ok) { + logprintf ("Chat is not yet initialized\n"); + return; + } } - if (!out_message_num) { - out_message_num = -lrand48 (); - } - clear_packet (); - out_int (CODE_messages_send_message); - struct message *M = malloc (sizeof (*M)); - memset (M, 0, sizeof (*M)); - M->from_id = MK_USER (our_id); - M->to_id = id; - M->unread = 1; - out_peer_id (id); - M->message = malloc (len + 1); - memcpy (M->message, msg, len); - M->message[len] = 0; - M->message_len = len; - M->out = 1; - M->media.type = CODE_message_media_empty; - M->id = out_message_num; - M->date = time (0); - out_cstring (msg, len); - out_long ((--out_message_num) - (1ll << 32)); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, M); + long long t = -lrand48 () * (1ll << 32) - lrand48 (); + bl_do_send_message_text (t, our_id, get_peer_type (id), get_peer_id (id), time (0), len, msg); + struct message *M = message_get (t); + assert (M); + do_send_msg (M); print_message (M); } /* }}} */ @@ -1070,6 +1047,7 @@ void do_get_local_history (peer_id_t id, int limit) { if (!P || !P->last) { return; } struct message *M = P->last; int count = 1; + assert (!M->prev); while (count < limit && M->next) { M = M->next; count ++; @@ -2295,6 +2273,9 @@ void do_create_keys_end (struct secret_chat *U) { BIGNUM *a = BN_bin2bn ((void *)U->key, 256, 0); BN_init (r); BN_mod_exp (r, g_b, a, p, ctx); + + void *t = malloc (256); + memcpy (t, U->key, 256); memset (U->key, 0, sizeof (U->key)); BN_bn2bin (r, (void *)U->key); @@ -2306,7 +2287,15 @@ void do_create_keys_end (struct secret_chat *U) { static unsigned char sha_buffer[20]; sha1 ((void *)U->key, 256, sha_buffer); long long k = *(long long *)(sha_buffer + 12); - assert (k == U->key_fingerprint); + if (k != U->key_fingerprint) { + logprintf ("version = %d\n", encr_param_version); + hexdump ((void *)U->nonce, (void *)(U->nonce + 256)); + hexdump ((void *)U->g_key, (void *)(U->g_key + 256)); + hexdump ((void *)U->key, (void *)(U->key + 64)); + hexdump ((void *)t, (void *)(t + 256)); + logprintf ("!!Key fingerprint mismatch\n"); + U->state = sc_deleted; + } BN_clear_free (p); BN_clear_free (g_b); diff --git a/queries.h b/queries.h index e377a0a..3259b33 100644 --- a/queries.h +++ b/queries.h @@ -107,6 +107,7 @@ void do_add_user_to_chat (peer_id_t chat_id, peer_id_t id, int limit); void do_del_user_from_chat (peer_id_t chat_id, peer_id_t id); void do_update_status (int online); void do_contacts_search (int limit, const char *s); +void do_send_msg (struct message *M); // For binlog diff --git a/structures.c b/structures.c index 56ff4ba..6356ed6 100644 --- a/structures.c +++ b/structures.c @@ -47,6 +47,7 @@ struct message message_list = { struct tree_peer *peer_tree; struct tree_message *message_tree; +struct tree_message *message_unsent_tree; int users_allocated; int chats_allocated; @@ -121,6 +122,7 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha const char *d[4]; d[0] = a1; d[1] = a2; d[2] = a3; d[3] = a4; static char buf[10000]; + buf[0] = 0; int i; int p = 0; for (i = 0; i < 4; i++) { @@ -141,6 +143,7 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha int ok = 1; int i; for (i = 0; i < peer_num; i++) { + assert (Peers[i]); if (cmp_peer_id (Peers[i]->id, id) && Peers[i]->print_name && !strcmp (Peers[i]->print_name, s)) { ok = 0; break; @@ -151,24 +154,7 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha } cc ++; assert (cc <= 9999); - if (cc == 1) { - int l = strlen (s); - s[l + 2] = 0; - s[l] = '#'; - s[l + 1] = '1'; - } else if (cc == 10 || cc == 100 || cc == 1000) { -// int l = strlen (s); - sprintf (s + fl, "#%d", cc); - } else { - int l = strlen (s); - s[l - 1] ++; - int cc = l - 1; - while (s[cc] > '9') { - s[cc] = '0'; - s[cc - 1] ++; - cc --; - } - } + sprintf (s + fl, "#%d", cc); } return strdup (s); } @@ -320,6 +306,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { int l = prefetch_strlen (); char *s = fetch_str (l); + if (l != 256) { logprintf ("l = %d\n", l); } if (l < 256) { memcpy (g_key + 256 - l, s, l); } else { @@ -328,6 +315,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { l = prefetch_strlen (); s = fetch_str (l); + if (l != 256) { logprintf ("l = %d\n", l); } if (l < 256) { memcpy (nonce + 256 - l, s, l); } else { @@ -369,6 +357,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { int l = prefetch_strlen (); char *s = fetch_str (l); + if (l != 256) { logprintf ("l = %d\n", l); } if (l < 256) { memcpy (g_key + 256 - l, s, l); } else { @@ -377,6 +366,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { l = prefetch_strlen (); s = fetch_str (l); + if (l != 256) { logprintf ("l = %d\n", l); } if (l < 256) { memcpy (nonce + 256 - l, s, l); } else { @@ -635,7 +625,7 @@ void fetch_skip_geo (void) { unsigned x = fetch_int (); assert (x == CODE_geo_point || x == CODE_geo_point_empty); if (x == CODE_geo_point) { - in_ptr += 2; + in_ptr += 4; } } @@ -693,6 +683,18 @@ void fetch_video (struct video *V) { V->h = fetch_int (); } +void fetch_skip_video (void) { + unsigned x = fetch_int (); + fetch_long (); + if (x == CODE_video_empty) { return; } + fetch_skip (4); + int l = prefetch_strlen (); + fetch_str (l); + fetch_skip (2); + fetch_skip_photo_size (); + fetch_skip (3); +} + void fetch_audio (struct audio *V) { memset (V, 0, sizeof (*V)); unsigned x = fetch_int (); @@ -706,6 +708,13 @@ void fetch_audio (struct audio *V) { V->dc_id = fetch_int (); } +void fetch_skip_audio (void) { + unsigned x = fetch_int (); + fetch_skip (2); + if (x == CODE_audio_empty) { return; } + fetch_skip (7); +} + void fetch_document (struct document *V) { memset (V, 0, sizeof (*V)); unsigned x = fetch_int (); @@ -721,6 +730,20 @@ void fetch_document (struct document *V) { V->dc_id = fetch_int (); } +void fetch_skip_document (void) { + unsigned x = fetch_int (); + fetch_skip (2); + if (x == CODE_document_empty) { return; } + fetch_skip (4); + int l = prefetch_strlen (); + fetch_str (l); + l = prefetch_strlen (); + fetch_str (l); + fetch_skip (1); + fetch_skip_photo_size (); + fetch_skip (1); +} + void fetch_message_action (struct message_action *M) { memset (M, 0, sizeof (*M)); unsigned x = fetch_int (); @@ -765,30 +788,104 @@ void fetch_message_action (struct message_action *M) { } } +void fetch_skip_message_action (void) { + unsigned x = fetch_int (); + int l; + switch (x) { + case CODE_message_action_empty: + break; + case CODE_message_action_geo_chat_create: + { + l = prefetch_strlen (); + fetch_str (l); + l = prefetch_strlen (); + fetch_str (l); + } + break; + case CODE_message_action_geo_chat_checkin: + break; + case CODE_message_action_chat_create: + l = prefetch_strlen (); + fetch_str (l); + assert (fetch_int () == (int)CODE_vector); + l = fetch_int (); + fetch_skip (l); + break; + case CODE_message_action_chat_edit_title: + l = prefetch_strlen (); + fetch_str (l); + break; + case CODE_message_action_chat_edit_photo: + fetch_skip_photo (); + break; + case CODE_message_action_chat_delete_photo: + break; + case CODE_message_action_chat_add_user: + fetch_int (); + break; + case CODE_message_action_chat_delete_user: + fetch_int (); + break; + default: + assert (0); + } +} + void fetch_message_short (struct message *M) { - memset (M, 0, sizeof (*M)); - M->id = fetch_int (); - M->to_id = MK_USER (our_id); - M->from_id = MK_USER (fetch_int ()); - M->message = fetch_str_dup (); - fetch_pts (); - M->date = fetch_int (); - fetch_seq (); - M->media.type = CODE_message_media_empty; - M->unread = 1; + int new = !(M->flags & FLAG_CREATED); + + if (new) { + int id = fetch_int (); + int from_id = fetch_int (); + int to_id = our_id; + int l = prefetch_strlen (); + char *s = fetch_str (l); + + fetch_pts (); + + int date = fetch_int (); + fetch_seq (); + + bl_do_create_message_text (id, from_id, PEER_USER, to_id, date, l, s); + } else { + fetch_int (); // id + fetch_int (); // from_id + int l = prefetch_strlen (); + fetch_str (l); // text + + fetch_pts (); + fetch_int (); + fetch_seq (); + } } void fetch_message_short_chat (struct message *M) { - memset (M, 0, sizeof (*M)); - M->id = fetch_int (); - M->from_id = MK_USER (fetch_int ()); - M->to_id = MK_CHAT (fetch_int ()); - M->message = fetch_str_dup (); - fetch_pts (); - M->date = fetch_int (); - fetch_seq (); - M->media.type = CODE_message_media_empty; - M->unread = 1; + int new = !(M->flags & FLAG_CREATED); + + if (new) { + int id = fetch_int (); + int from_id = fetch_int (); + int to_id = fetch_int (); + int l = prefetch_strlen (); + char *s = fetch_str (l); + + fetch_pts (); + + int date = fetch_int (); + fetch_seq (); + + bl_do_create_message_text (id, from_id, PEER_CHAT, to_id, date, l, s); + } else { + fetch_int (); // id + fetch_int (); // from_id + fetch_int (); // to_id + int l = prefetch_strlen (); + fetch_str (l); // text + + fetch_pts (); + fetch_int (); + fetch_seq (); + } } @@ -828,6 +925,124 @@ void fetch_message_media (struct message_media *M) { } } +void fetch_skip_message_media (void) { + unsigned x = fetch_int (); + switch (x) { + case CODE_message_media_empty: + break; + case CODE_message_media_photo: + fetch_skip_photo (); + break; + case CODE_message_media_video: + fetch_skip_video (); + break; + case CODE_message_media_audio: + fetch_skip_audio (); + break; + case CODE_message_media_document: + fetch_skip_document (); + break; + case CODE_message_media_geo: + fetch_skip_geo (); + break; + case CODE_message_media_contact: + { + int l; + l = prefetch_strlen (); + fetch_str (l); + l = prefetch_strlen (); + fetch_str (l); + l = prefetch_strlen (); + fetch_str (l); + fetch_int (); + } + break; + case CODE_message_media_unsupported: + { + int l = prefetch_strlen (); + fetch_str (l); + } + break; + default: + logprintf ("type = 0x%08x\n", x); + assert (0); + } +} + +void fetch_skip_message_media_encrypted (void) { + unsigned x = fetch_int (); + int l; + switch (x) { + case CODE_decrypted_message_media_empty: + break; + case CODE_decrypted_message_media_photo: + l = prefetch_strlen (); + fetch_str (l); // thumb + fetch_skip (5); + + l = prefetch_strlen (); + fetch_str (l); + + l = prefetch_strlen (); + fetch_str (l); + break; + case CODE_decrypted_message_media_video: + l = prefetch_strlen (); + fetch_str (l); // thumb + + fetch_skip (6); + + l = prefetch_strlen (); + fetch_str (l); + + l = prefetch_strlen (); + fetch_str (l); + break; + case CODE_decrypted_message_media_audio: + fetch_skip (2); + + l = prefetch_strlen (); + fetch_str (l); + + l = prefetch_strlen (); + fetch_str (l); + break; + case CODE_decrypted_message_media_document: + l = prefetch_strlen (); + fetch_str (l); // thumb + + fetch_skip (2); + + l = prefetch_strlen (); + fetch_str (l); // thumb + l = prefetch_strlen (); + fetch_str (l); // thumb + fetch_skip (1); + + l = prefetch_strlen (); + fetch_str (l); + + l = prefetch_strlen (); + fetch_str (l); + break; + case CODE_decrypted_message_media_geo_point: + fetch_skip (4); + break; + case CODE_decrypted_message_media_contact: + l = prefetch_strlen (); + fetch_str (l); // thumb + l = prefetch_strlen (); + fetch_str (l); // thumb + l = prefetch_strlen (); + fetch_str (l); // thumb + fetch_skip (1); + break; + default: + logprintf ("type = 0x%08x\n", x); + assert (0); + } +} + void fetch_message_media_encrypted (struct message_media *M) { memset (M, 0, sizeof (*M)); unsigned x = fetch_int (); @@ -977,7 +1192,32 @@ void fetch_message_media_encrypted (struct message_media *M) { M->user_id = fetch_int (); break; default: - logprintf ("type = 0x%08x\n", M->type); + logprintf ("type = 0x%08x\n", x); + assert (0); + } +} + +void fetch_skip_message_action_encrypted (void) { + unsigned x = fetch_int (); + switch (x) { + case CODE_decrypted_message_action_set_message_t_t_l: + fetch_skip (1); + break; + default: + logprintf ("x = 0x%08x\n", x); + assert (0); + } +} + +void fetch_message_action_encrypted (struct message_action *M) { + unsigned x = fetch_int (); + switch (x) { + case CODE_decrypted_message_action_set_message_t_t_l: + M->type = x; + M->ttl = fetch_int (); + break; + default: + logprintf ("x = 0x%08x\n", x); assert (0); } } @@ -993,30 +1233,54 @@ peer_id_t fetch_peer_id (void) { } void fetch_message (struct message *M) { - memset (M, 0, sizeof (*M)); unsigned x = fetch_int (); assert (x == CODE_message_empty || x == CODE_message || x == CODE_message_forwarded || x == CODE_message_service); - M->id = fetch_int (); + int id = fetch_int (); + assert (M->id == id); if (x == CODE_message_empty) { - M->flags |= 1; return; } + int fwd_from_id = 0; + int fwd_date = 0; + if (x == CODE_message_forwarded) { - M->fwd_from_id = MK_USER (fetch_int ()); - M->fwd_date = fetch_int (); + fwd_from_id = fetch_int (); + fwd_date = fetch_int (); } - M->from_id = MK_USER (fetch_int ()); - M->to_id = fetch_peer_id (); - M->out = fetch_bool (); - M->unread = fetch_bool (); - M->date = fetch_int (); + int from_id = fetch_int (); + peer_id_t to_id = fetch_peer_id (); + + fetch_bool (); // out. + + int unread = fetch_bool (); + int date = fetch_int (); + + int new = !(M->flags & FLAG_CREATED); + if (x == CODE_message_service) { - M->service = 1; - fetch_message_action (&M->action); + int *start = in_ptr; + fetch_skip_message_action (); + if (new) { + if (fwd_from_id) { + bl_do_create_message_service_fwd (id, from_id, get_peer_type (to_id), get_peer_id (to_id), date, fwd_from_id, fwd_date, start, (in_ptr - start)); + } else { + bl_do_create_message_service (id, from_id, get_peer_type (to_id), get_peer_id (to_id), date, start, (in_ptr - start)); + } + } } else { - M->message = fetch_str_dup (); - fetch_message_media (&M->media); + int l = prefetch_strlen (); + char *s = fetch_str (l); + int *start = in_ptr; + fetch_skip_message_media (); + if (new) { + if (fwd_from_id) { + bl_do_create_message_media_fwd (id, from_id, get_peer_type (to_id), get_peer_id (to_id), date, fwd_from_id, fwd_date, l, s, start, in_ptr - start); + } else { + bl_do_create_message_media (id, from_id, get_peer_type (to_id), get_peer_id (to_id), date, l, s, start, in_ptr - start); + } + } } + bl_do_set_unread (M, unread); } void fetch_geo_message (struct message *M) { @@ -1100,29 +1364,26 @@ int decrypt_encrypted_message (struct secret_chat *E) { } void fetch_encrypted_message (struct message *M) { - memset (M, 0, sizeof (*M)); unsigned x = fetch_int (); assert (x == CODE_encrypted_message || x == CODE_encrypted_message_service); unsigned sx = x; - M->id = fetch_long (); - peer_id_t chat = MK_ENCR_CHAT (fetch_int ()); - M->from_id = MK_USER (our_id); - M->to_id = chat; + int new = !(M->flags & FLAG_CREATED); + long long id = fetch_long (); + int to_id = fetch_int (); + peer_id_t chat = MK_ENCR_CHAT (to_id); + int date = fetch_int (); + peer_t *P = user_chat_get (chat); - M->flags &= ~(FLAG_MESSAGE_EMPTY | FLAG_DELETED); - M->flags |= FLAG_ENCRYPTED; if (!P) { logprintf ("Encrypted message to unknown chat. Dropping\n"); M->flags |= FLAG_MESSAGE_EMPTY; } - M->date = fetch_int (); int len = prefetch_strlen (); assert ((len & 15) == 8); decr_ptr = (void *)fetch_str (len); decr_end = decr_ptr + (len / 4); - M->flags |= FLAG_ENCRYPTED; int ok = 0; if (P) { if (*(long long *)decr_ptr != P->encr_chat.key_fingerprint) { @@ -1131,32 +1392,39 @@ void fetch_encrypted_message (struct message *M) { } decr_ptr += 2; } - if (P && decrypt_encrypted_message (&P->encr_chat) >= 0) { + int l = 0; + char *s = 0; + int *start = 0; + int *end = 0; + x = 0; + if (P && decrypt_encrypted_message (&P->encr_chat) >= 0 && new) { ok = 1; int *save_in_ptr = in_ptr; int *save_in_end = in_end; in_ptr = decr_ptr; - int l = fetch_int (); - in_end = in_ptr + l; - unsigned x = fetch_int (); + int ll = fetch_int (); + in_end = in_ptr + ll; + x = fetch_int (); if (x == CODE_decrypted_message_layer) { int layer = fetch_int (); assert (layer >= 0); x = fetch_int (); } assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service); - assert (M->id = fetch_long ()); - l = prefetch_strlen (); - fetch_str (l); // random_bytes + //assert (id == fetch_long ()); + fetch_long (); + ll = prefetch_strlen (); + fetch_str (ll); // random_bytes if (x == CODE_decrypted_message) { - M->message = fetch_str_dup (); - fetch_message_media_encrypted (&M->media); + l = prefetch_strlen (); + s = fetch_str (l); + start = in_ptr; + fetch_skip_message_media_encrypted (); + end = in_ptr; } else { - assert (fetch_int () == (int)CODE_decrypted_message_action_set_message_t_t_l); - M->action.type = CODE_decrypted_message_action_set_message_t_t_l; - P->encr_chat.ttl = fetch_int (); - M->action.ttl = P->encr_chat.ttl; - M->service = 1; + start = in_ptr; + fetch_skip_message_action_encrypted (); + end = in_ptr; } in_ptr = save_in_ptr; in_end = save_in_end; @@ -1164,7 +1432,11 @@ void fetch_encrypted_message (struct message *M) { if (sx == CODE_encrypted_message) { if (ok) { - fetch_encrypted_message_file (&M->media); + int *start_file = in_ptr; + fetch_skip_encrypted_message_file (); + if (x == CODE_decrypted_message) { + bl_do_create_message_media_encr (id, P->encr_chat.user_id, PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, in_ptr - start_file); + } } else { x = fetch_int (); if (x == CODE_encrypted_file) { @@ -1174,6 +1446,10 @@ void fetch_encrypted_message (struct message *M) { } M->media.type = CODE_message_media_empty; } + } else { + if (ok && x == CODE_decrypted_message_service) { + bl_do_create_message_service_encr (id, P->encr_chat.user_id, PEER_ENCR_CHAT, to_id, date, start, end - start); + } } } @@ -1195,6 +1471,15 @@ void fetch_encrypted_message_file (struct message_media *M) { } } +void fetch_skip_encrypted_message_file (void) { + unsigned x = fetch_int (); + assert (x == CODE_encrypted_file || x == CODE_encrypted_file_empty); + if (x == CODE_encrypted_file_empty) { + } else { + fetch_skip (7); + } +} + static int id_cmp (struct message *M1, struct message *M2) { if (M1->id < M2->id) { return -1; } else if (M1->id > M2->id) { return 1; } @@ -1424,10 +1709,33 @@ void message_add_peer (struct message *M) { peer_tree = tree_insert_peer (peer_tree, P, lrand48 ()); Peers[peer_num ++] = P; } - M->next = P->last; - if (M->next) { M->next->prev = M; } - M->prev = 0; - P->last = M; + if (!P->last) { + P->last = M; + M->prev = M->next = 0; + } else { + if (get_peer_type (P->id) != PEER_ENCR_CHAT) { + struct message *N = P->last; + struct message *NP = 0; + while (N && N->id > M->id) { + NP = N; + N = N->next; + } + if (N) { assert (N->id < M->id); } + M->next = N; + M->prev = NP; + if (N) { N->prev = M; } + if (NP) { NP->next = M; } + else { P->last = M; } + } else { + struct message *N = P->last; + struct message *NP = 0; + M->next = N; + M->prev = NP; + if (N) { N->prev = M; } + if (NP) { NP->next = M; } + else { P->last = M; } + } + } } void message_del_peer (struct message *M) { @@ -1450,26 +1758,19 @@ void message_del_peer (struct message *M) { } struct message *fetch_alloc_message (void) { - struct message *M = malloc (sizeof (*M)); - fetch_message (M); - struct message *M1 = tree_lookup_message (message_tree, M); - messages_allocated ++; - if (M1) { - message_del_use (M1); - message_del_peer (M1); - free_message (M1); - memcpy (M1, M, sizeof (*M)); - free (M); - message_add_use (M1); - message_add_peer (M1); - messages_allocated --; - return M1; - } else { - message_add_use (M); - message_add_peer (M); - message_tree = tree_insert_message (message_tree, M, lrand48 ()); - return M; + int data[2]; + prefetch_data (data, 8); + struct message *M = message_get (data[1]); + + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = data[1]; + message_insert_tree (M); + messages_allocated ++; } + fetch_message (M); + return M; } struct message *fetch_alloc_geo_message (void) { @@ -1496,75 +1797,53 @@ struct message *fetch_alloc_geo_message (void) { } struct message *fetch_alloc_encrypted_message (void) { - struct message *M = malloc (sizeof (*M)); - fetch_encrypted_message (M); - struct message *M1 = tree_lookup_message (message_tree, M); - messages_allocated ++; - if (M1) { - message_del_use (M1); - message_del_peer (M1); - free_message (M1); - memcpy (M1, M, sizeof (*M)); - free (M); - message_add_use (M1); - message_add_peer (M1); - messages_allocated --; - return M1; - } else { - message_add_use (M); - message_add_peer (M); - message_tree = tree_insert_message (message_tree, M, lrand48 ()); - return M; + int data[3]; + prefetch_data (data, 12); + struct message *M = message_get (*(long long *)(data + 1)); + + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = *(long long *)(data + 1); + message_insert_tree (M); + messages_allocated ++; + assert (message_get (M->id) == M); + logprintf ("id = %lld\n", M->id); } + fetch_encrypted_message (M); + return M; } struct message *fetch_alloc_message_short (void) { - struct message *M = malloc (sizeof (*M)); - fetch_message_short (M); - struct message *M1 = tree_lookup_message (message_tree, M); - messages_allocated ++; - if (M1) { - message_del_use (M1); - message_del_peer (M1); - free_message (M1); - memcpy (M1, M, sizeof (*M)); - free (M); - message_add_use (M1); - message_add_peer (M1); - messages_allocated --; - return M1; - } else { - message_add_use (M); - message_add_peer (M); - message_tree = tree_insert_message (message_tree, M, lrand48 ()); - return M; + int data[1]; + prefetch_data (data, 4); + struct message *M = message_get (data[0]); + + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = data[0]; + message_insert_tree (M); + messages_allocated ++; } + fetch_message_short (M); + return M; } struct message *fetch_alloc_message_short_chat (void) { - struct message *M = malloc (sizeof (*M)); + int data[1]; + prefetch_data (data, 4); + struct message *M = message_get (data[0]); + + if (!M) { + M = malloc (sizeof (*M)); + memset (M, 0, sizeof (*M)); + M->id = data[0]; + message_insert_tree (M); + messages_allocated ++; + } fetch_message_short_chat (M); - if (verbosity >= 2) { - logprintf ("Read message with id %lld\n", M->id); - } - struct message *M1 = tree_lookup_message (message_tree, M); - messages_allocated ++; - if (M1) { - message_del_use (M1); - message_del_peer (M1); - free_message (M1); - memcpy (M1, M, sizeof (*M)); - free (M); - message_add_use (M1); - message_add_peer (M1); - messages_allocated --; - return M1; - } else { - message_add_use (M); - message_add_peer (M); - message_tree = tree_insert_message (message_tree, M, lrand48 ()); - return M; - } + return M; } struct chat *fetch_alloc_chat (void) { @@ -1640,8 +1919,36 @@ void update_message_id (struct message *M, long long id) { message_tree = tree_insert_message (message_tree, M, lrand48 ()); } +void message_insert_tree (struct message *M) { + assert (M->id); + message_tree = tree_insert_message (message_tree, M, lrand48 ()); +} + +void message_remove_tree (struct message *M) { + assert (M->id); + message_tree = tree_delete_message (message_tree, M); +} + void message_insert (struct message *M) { message_add_use (M); message_add_peer (M); - message_tree = tree_insert_message (message_tree, M, lrand48 ()); +} + +void message_insert_unsent (struct message *M) { + message_unsent_tree = tree_insert_message (message_unsent_tree, M, lrand48 ()); +} + +void message_remove_unsent (struct message *M) { + message_unsent_tree = tree_delete_message (message_unsent_tree, M); +} + +void __send_msg (struct message *M) { + logprintf ("Resending message...\n"); + print_message (M); + + do_send_msg (M); +} + +void send_all_unsent (void ) { + tree_act_message (message_unsent_tree, __send_msg); } diff --git a/structures.h b/structures.h index dc33ee2..202e522 100644 --- a/structures.h +++ b/structures.h @@ -38,6 +38,7 @@ typedef struct { int type; int id; } peer_id_t; #define FLAG_CHAT_IN_CHAT 128 #define FLAG_ENCRYPTED 4096 +#define FLAG_PENDING 8192 struct file_location { int dc; @@ -337,8 +338,16 @@ struct message *fetch_alloc_message_short (void); struct message *fetch_alloc_message_short_chat (void); struct message *fetch_alloc_encrypted_message (void); void fetch_encrypted_message_file (struct message_media *M); +void fetch_skip_encrypted_message_file (void); +void fetch_encrypted_message_file (struct message_media *M); +void fetch_message_action_encrypted (struct message_action *M); peer_id_t fetch_peer_id (void); +void fetch_message_media (struct message_media *M); +void fetch_message_media_encrypted (struct message_media *M); +void fetch_message_action (struct message_action *M); +void message_insert_tree (struct message *M); + void free_user (struct user *U); void free_chat (struct chat *U); @@ -356,6 +365,12 @@ void insert_user (peer_t *P); void insert_chat (peer_t *P); void fetch_photo (struct photo *P); void free_photo (struct photo *P); +void message_insert_unsent (struct message *M); +void message_remove_unsent (struct message *M); +void send_all_unsent (void); +void message_remove_tree (struct message *M); +void message_add_peer (struct message *M); +void message_del_peer (struct message *M); #define PEER_USER 1 #define PEER_CHAT 2 diff --git a/telegram.h b/telegram.h index b5ea029..0ec1fd5 100644 --- a/telegram.h +++ b/telegram.h @@ -17,5 +17,5 @@ Copyright Vitaly Valtman 2013 */ #define MAX_DC_NUM 9 -#define MAX_USER_NUM 1000 -#define MAX_CHAT_NUM 1000 +#define MAX_USER_NUM 100000 +#define MAX_CHAT_NUM 100000