diff --git a/interface.c b/interface.c index a0fc830..e582688 100644 --- a/interface.c +++ b/interface.c @@ -50,7 +50,7 @@ long long cur_downloaded_bytes; char *line_ptr; extern int user_num; extern int chat_num; -extern union user_chat *Peers[]; +extern peer_t *Peers[]; int is_same_word (const char *s, size_t l, const char *word) { return s && word && strlen (word) == l && !memcmp (s, word, l); @@ -77,6 +77,8 @@ char *next_token (int *l) { } #define NOT_FOUND (int)0x80000000 +peer_id_t PEER_NOT_FOUND = {.id = NOT_FOUND}; + int next_token_int (void) { int l; char *s = next_token (&l); @@ -90,84 +92,82 @@ int next_token_int (void) { } } -int next_token_user (void) { +peer_id_t next_token_user (void) { int l; char *s = next_token (&l); - if (!s) { return NOT_FOUND; } + if (!s) { return PEER_NOT_FOUND; } - if (*s == '#') { - s ++; - l --; - if (l > 0) { - int r = atoi (s); - if (r < 0) { return r; } - else { return NOT_FOUND; } - } else { - return NOT_FOUND; - } + if (l >= 6 && !memcmp (s, "user#", 5)) { + s += 5; + l -= 5; + int r = atoi (s); + if (r >= 0) { return set_peer_id (PEER_USER, r); } + else { return PEER_NOT_FOUND; } } + int index = 0; - while (index < user_num + chat_num && (!is_same_word (s, l, Peers[index]->print_name) || Peers[index]->id < 0)) { + while (index < user_num + chat_num && (!is_same_word (s, l, Peers[index]->print_name) || get_peer_type (Peers[index]->id) != PEER_USER)) { index ++; } if (index < user_num + chat_num) { return Peers[index]->id; } else { - return NOT_FOUND; + return PEER_NOT_FOUND; } } -int next_token_chat (void) { +peer_id_t next_token_chat (void) { int l; char *s = next_token (&l); - if (!s) { return NOT_FOUND; } - - if (*s == '#') { - s ++; - l --; - if (l > 0) { - int r = atoi (s); - if (r < 0) { return r; } - else { return NOT_FOUND; } - } else { - return NOT_FOUND; - } + if (!s) { return PEER_NOT_FOUND; } + + if (l >= 6 && !memcmp (s, "chat#", 5)) { + s += 5; + l -= 5; + int r = atoi (s); + if (r >= 0) { return set_peer_id (PEER_CHAT, r); } + else { return PEER_NOT_FOUND; } } + int index = 0; - while (index < user_num + chat_num && (!is_same_word (s, l, Peers[index]->print_name) || Peers[index]->id > 0)) { + while (index < user_num + chat_num && (!is_same_word (s, l, Peers[index]->print_name) || get_peer_type (Peers[index]->id) != PEER_CHAT)) { index ++; } if (index < user_num + chat_num) { return Peers[index]->id; } else { - return NOT_FOUND; + return PEER_NOT_FOUND; } } -int next_token_user_chat (void) { +peer_id_t next_token_peer (void) { int l; char *s = next_token (&l); - if (!s) { return NOT_FOUND; } - - if (*s == '#') { - s ++; - l --; - if (l > 0) { - int r = atoi (s); - if (r != 0) { return r; } - else { return NOT_FOUND; } - } else { - return NOT_FOUND; - } + if (!s) { return PEER_NOT_FOUND; } + + if (l >= 6 && !memcmp (s, "user#", 5)) { + s += 5; + l -= 5; + int r = atoi (s); + if (r >= 0) { return set_peer_id (PEER_USER, r); } + else { return PEER_NOT_FOUND; } } + if (l >= 6 && !memcmp (s, "chat#", 5)) { + s += 5; + l -= 5; + int r = atoi (s); + if (r >= 0) { return set_peer_id (PEER_CHAT, r); } + else { return PEER_NOT_FOUND; } + } + int index = 0; - while (index < user_num + chat_num && (!is_same_word (s, l, Peers[index]->print_name) || !Peers[index]->id)) { + while (index < user_num + chat_num && (!is_same_word (s, l, Peers[index]->print_name))) { index ++; } if (index < user_num + chat_num) { return Peers[index]->id; } else { - return NOT_FOUND; + return PEER_NOT_FOUND; } } @@ -295,7 +295,7 @@ int get_complete_mode (void) { int complete_user_list (int index, const char *text, int len, char **R) { index ++; - while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || Peers[index]->id < 0)) { + while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || get_peer_type (Peers[index]->id) != PEER_USER)) { index ++; } if (index < user_num + chat_num) { @@ -308,7 +308,7 @@ int complete_user_list (int index, const char *text, int len, char **R) { int complete_chat_list (int index, const char *text, int len, char **R) { index ++; - while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || Peers[index]->id > 0)) { + while (index < user_num + chat_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || get_peer_type (Peers[index]->id) != PEER_CHAT)) { index ++; } if (index < user_num + chat_num) { @@ -426,6 +426,27 @@ void interpreter (char *line UU) { #define IS_WORD(s) is_same_word (command, l, (s)) #define RET in_readline = 0; return; + + peer_id_t id; +#define GET_PEER \ + id = next_token_peer (); \ + if (!cmp_peer_id (id, PEER_NOT_FOUND)) { \ + printf ("Bad user/char id\n"); \ + RET; \ + } +#define GET_PEER_USER \ + id = next_token_user (); \ + if (!cmp_peer_id (id, PEER_NOT_FOUND)) { \ + printf ("Bad user id\n"); \ + RET; \ + } +#define GET_PEER_CHAT \ + id = next_token_chat (); \ + if (!cmp_peer_id (id, PEER_NOT_FOUND)) { \ + printf ("Bad char id\n"); \ + RET; \ + } + if (IS_WORD ("contact_list")) { do_update_contact_list (); } else if (IS_WORD ("dialog_list")) { @@ -435,11 +456,7 @@ void interpreter (char *line UU) { print_stat (stat_buf, (1 << 15) - 1); printf ("%s\n", stat_buf); } else if (IS_WORD ("msg")) { - int id = next_token_user_chat (); - if (id == NOT_FOUND) { - printf ("Bad user/chat id\n"); - RET; - } + GET_PEER; int t; char *s = next_token (&t); if (!s) { @@ -448,11 +465,7 @@ void interpreter (char *line UU) { } do_send_message (id, s, strlen (s)); } else if (IS_WORD ("rename_chat")) { - int id = next_token_chat (); - if (id == NOT_FOUND) { - printf ("Bad chat id\n"); - RET; - } + GET_PEER_CHAT; int t; char *s = next_token (&t); if (!s) { @@ -461,11 +474,7 @@ void interpreter (char *line UU) { } do_rename_chat (id, s); } else if (IS_WORD ("send_photo")) { - int id = next_token_user_chat (); - if (id == NOT_FOUND) { - printf ("Bad user/chat id\n"); - RET; - } + GET_PEER; int t; char *s = next_token (&t); if (!s) { @@ -474,11 +483,7 @@ void interpreter (char *line UU) { } do_send_photo (CODE_input_media_uploaded_photo, id, strndup (s, t)); } else if (IS_WORD("send_video")) { - int id = next_token_user_chat (); - if (id == NOT_FOUND) { - printf ("Bad user/chat id\n"); - RET; - } + GET_PEER; int t; char *s = next_token (&t); if (!s) { @@ -487,11 +492,7 @@ void interpreter (char *line UU) { } do_send_photo (CODE_input_media_uploaded_video, id, strndup (s, t)); } else if (IS_WORD ("send_text")) { - int id = next_token_user_chat (); - if (id == NOT_FOUND) { - printf ("Bad user/chat id\n"); - RET; - } + GET_PEER; int t; char *s = next_token (&t); if (!s) { @@ -500,11 +501,7 @@ void interpreter (char *line UU) { } do_send_text (id, strndup (s, t)); } else if (IS_WORD ("fwd")) { - int id = next_token_user_chat (); - if (id == NOT_FOUND) { - printf ("Bad user/chat id\n"); - RET; - } + GET_PEER; int num = next_token_int (); if (num == NOT_FOUND || num <= 0) { printf ("Bad msg id\n"); @@ -590,25 +587,13 @@ void interpreter (char *line UU) { RET; } } else if (IS_WORD ("chat_info")) { - int id = next_token_chat (); - if (id == NOT_FOUND) { - printf ("Bad chat id\n"); - RET; - } + GET_PEER_CHAT; do_get_chat_info (id); } else if (IS_WORD ("user_info")) { - int id = next_token_user (); - if (id == NOT_FOUND) { - printf ("Bad user id\n"); - RET; - } + GET_PEER_USER; do_get_user_info (id); } else if (IS_WORD ("history")) { - int id = next_token_user_chat (); - if (id == NOT_FOUND) { - printf ("Bad user/chat id\n"); - RET; - } + GET_PEER; int limit = next_token_int (); do_get_history (id, limit > 0 ? limit : 40); } else if (IS_WORD ("add_contact")) { @@ -631,12 +616,8 @@ void interpreter (char *line UU) { } do_add_contact (phone, phone_len, first_name, first_name_len, last_name, last_name_len, 0); } else if (IS_WORD ("rename_contact")) { - int id = next_token_user (); - if (id == NOT_FOUND) { - printf ("Bad user\n"); - RET; - } - union user_chat *U = user_chat_get (id); + GET_PEER_USER; + peer_t *U = user_chat_get (id); if (!U) { printf ("No such user\n"); RET; @@ -879,20 +860,22 @@ void print_media (struct message_media *M) { int unknown_user_list_pos; int unknown_user_list[1000]; -void print_user_name (int id, union user_chat *U) { +void print_user_name (peer_id_t id, peer_t *U) { + assert (get_peer_type (id) == PEER_USER); push_color (COLOR_RED); if (!U) { - printf ("user#%d", id); + printf ("user#%d", get_peer_id (id)); int i; + int ok = 1; for (i = 0; i < unknown_user_list_pos; i++) { - if (unknown_user_list[i] == id) { - id = 0; + if (unknown_user_list[i] == get_peer_id (id)) { + ok = 0; break; } } - if (id) { + if (ok) { assert (unknown_user_list_pos < 1000); - unknown_user_list[unknown_user_list_pos ++] = id; + unknown_user_list[unknown_user_list_pos ++] = get_peer_id (id); } } else { if (U->flags & (FLAG_USER_SELF | FLAG_USER_CONTACT)) { @@ -912,10 +895,10 @@ void print_user_name (int id, union user_chat *U) { pop_color (); } -void print_chat_name (int id, union user_chat *C) { +void print_chat_name (peer_id_t id, peer_t *C) { push_color (COLOR_MAGENTA); if (!C) { - printf ("chat#%d", -id); + printf ("chat#%d", get_peer_id (id)); } else { printf ("%s", C->chat.title); } @@ -973,12 +956,12 @@ void print_service_message (struct message *M) { break; case CODE_message_action_chat_add_user: printf (" added user "); - print_user_name (M->action.user, user_chat_get (M->action.user)); + print_user_name (set_peer_id (PEER_USER, M->action.user), user_chat_get (set_peer_id (PEER_USER, M->action.user))); printf ("\n"); break; case CODE_message_action_chat_delete_user: printf (" deleted user "); - print_user_name (M->action.user, user_chat_get (M->action.user)); + print_user_name (set_peer_id (PEER_USER, M->action.user), user_chat_get (set_peer_id (PEER_USER, M->action.user))); printf ("\n"); break; default: @@ -988,15 +971,20 @@ void print_service_message (struct message *M) { print_end (); } +peer_id_t last_from_id; +peer_id_t last_to_id; + void print_message (struct message *M) { if (M->service) { print_service_message (M); return; } + last_from_id = M->from_id; + last_to_id = M->to_id; print_start (); - if (M->to_id >= 0) { + if (get_peer_type (M->to_id) == PEER_USER) { if (M->out) { push_color (COLOR_GREEN); if (msg_num_mode) { @@ -1039,7 +1027,7 @@ void print_message (struct message *M) { print_chat_name (M->to_id, user_chat_get (M->to_id)); printf (" "); print_user_name (M->from_id, user_chat_get (M->from_id)); - if (M->from_id == our_id) { + if ((get_peer_type (M->from_id) == PEER_USER) && (get_peer_id (M->from_id) == our_id)) { push_color (COLOR_GREEN); } else { push_color (COLOR_BLUE); @@ -1050,7 +1038,7 @@ void print_message (struct message *M) { printf (" »»» "); } } - if (M->fwd_from_id) { + if (get_peer_type (M->fwd_from_id) == PEER_USER) { printf ("[fwd from "); print_user_name (M->fwd_from_id, user_chat_get (M->fwd_from_id)); printf ("] "); diff --git a/interface.h b/interface.h index 51463a8..6a59bbc 100644 --- a/interface.h +++ b/interface.h @@ -18,6 +18,7 @@ */ #ifndef __INTERFACE_H__ #define __INTERFACE_H__ +#include "structures.h" #define COLOR_RED "\033[0;31m" #define COLOR_REDB "\033[1;31m" @@ -40,10 +41,10 @@ void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))) void hexdump (int *in_ptr, int *in_end); struct message; -union user_chat; +union peer; void print_message (struct message *M); -void print_chat_name (int id, union user_chat *C); -void print_user_name (int id, union user_chat *U); +void print_chat_name (peer_id_t id, union peer *C); +void print_user_name (peer_id_t id, union peer *U); //void print_media (struct message_media *M); void pop_color (void); void push_color (const char *color); diff --git a/mtproto-client.c b/mtproto-client.c index 0b5be0b..0752a5c 100644 --- a/mtproto-client.c +++ b/mtproto-client.c @@ -635,13 +635,45 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU); int unread_messages; int our_id; +int pts; +int qts; + +void fetch_pts (void) { + int p = fetch_int (); + if (p != pts + 1) { + if (pts) { + logprintf ("Hole in pts p = %d, pts = %d\n", p, pts); + + // get difference should be here + } else { + pts = p; + } + } else { + pts ++; + } +} + +void fetch_qts (void) { + int p = fetch_int (); + if (p != qts + 1) { + if (qts) { + logprintf ("Hole in qts\n"); + // get difference should be here + } else { + qts = p; + } + } else { + qts ++; + } +} + void work_update (struct connection *c UU, long long msg_id UU) { unsigned op = fetch_int (); switch (op) { case CODE_update_new_message: { struct message *M = fetch_alloc_message (); - fetch_int (); //pts + fetch_pts (); unread_messages ++; print_message (M); update_prompt (); @@ -667,7 +699,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { M->unread = 0; } } - fetch_int (); //pts + fetch_pts (); print_start (); push_color (COLOR_YELLOW); printf ("%d messages marked as read\n", n); @@ -677,8 +709,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_user_typing: { - int id = fetch_int (); - union user_chat *U = user_chat_get (id); + peer_id_t id = MK_USER (fetch_int ()); + peer_t *U = user_chat_get (id); print_start (); push_color (COLOR_YELLOW); printf ("User "); @@ -690,16 +722,16 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_chat_user_typing: { - int chat_id = fetch_int (); - int id = fetch_int (); - union user_chat *C = user_chat_get (-chat_id); - union user_chat *U = user_chat_get (id); + peer_id_t chat_id = MK_CHAT (fetch_int ()); + peer_id_t id = MK_USER (fetch_int ()); + peer_t *C = user_chat_get (chat_id); + peer_t *U = user_chat_get (id); print_start (); push_color (COLOR_YELLOW); printf ("User "); print_user_name (id, U); printf (" is typing in chat "); - print_chat_name (-chat_id, C); + print_chat_name (chat_id, C); printf ("....\n"); pop_color (); print_end (); @@ -707,8 +739,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_user_status: { - int user_id = fetch_int (); - union user_chat *U = user_chat_get (user_id); + peer_id_t user_id = MK_USER (fetch_int ()); + peer_t *U = user_chat_get (user_id); if (U) { fetch_user_status (&U->user.status); print_start (); @@ -727,8 +759,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_user_name: { - int user_id = fetch_int (); - union user_chat *UC = user_chat_get (user_id); + peer_id_t user_id = MK_USER (fetch_int ()); + peer_t *UC = user_chat_get (user_id); if (UC) { struct user *U = &UC->user; print_start (); @@ -770,8 +802,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_user_photo: { - int user_id = fetch_int (); - union user_chat *UC = user_chat_get (user_id); + peer_id_t user_id = MK_USER (fetch_int ()); + peer_t *UC = user_chat_get (user_id); if (UC) { struct user *U = &UC->user; @@ -813,23 +845,36 @@ void work_update (struct connection *c UU, long long msg_id UU) { pop_color (); print_end (); fetch_skip (n); - fetch_int (); // pts + fetch_pts (); + } + break; + case CODE_update_delete_messages: + { + assert (fetch_int () == CODE_vector); + int n = fetch_int (); + print_start (); + push_color (COLOR_YELLOW); + printf ("Deleted %d messages\n", n); + pop_color (); + print_end (); + fetch_skip (n); + fetch_pts (); } break; case CODE_update_chat_participants: { assert (fetch_int () == CODE_chat_participants); - int chat_id = fetch_int (); + peer_id_t chat_id = MK_CHAT (fetch_int ()); fetch_int (); // admin_id assert (fetch_int () == CODE_vector); int n = fetch_int (); fetch_skip (n * 4); fetch_int (); // version - union user_chat *C = user_chat_get (-chat_id); + peer_t *C = user_chat_get (chat_id); print_start (); push_color (COLOR_YELLOW); printf ("Chat "); - print_chat_name (-chat_id, C); + print_chat_name (chat_id, C); printf (" changed list: now %d members\n", n); pop_color (); print_end (); @@ -837,8 +882,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_contact_registered: { - int user_id = fetch_int (); - union user_chat *U = user_chat_get (user_id); + peer_id_t user_id = MK_USER (fetch_int ()); + peer_t *U = user_chat_get (user_id); fetch_int (); // date print_start (); push_color (COLOR_YELLOW); @@ -851,8 +896,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_contact_link: { - int user_id = fetch_int (); - union user_chat *U = user_chat_get (user_id); + peer_id_t user_id = MK_USER (fetch_int ()); + peer_t *U = user_chat_get (user_id); print_start (); push_color (COLOR_YELLOW); printf ("Updated link with user "); @@ -874,8 +919,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { break; case CODE_update_activation: { - int user_id = fetch_int (); - union user_chat *U = user_chat_get (user_id); + peer_id_t user_id = MK_USER (fetch_int ()); + peer_t *U = user_chat_get (user_id); print_start (); push_color (COLOR_YELLOW); printf ("User "); diff --git a/queries.c b/queries.c index ffd2153..0e157bd 100644 --- a/queries.c +++ b/queries.c @@ -562,8 +562,8 @@ int get_contacts_on_answer (struct query *q UU) { struct user *U = fetch_alloc_user (); print_start (); push_color (COLOR_YELLOW); - printf ("User #%d: ", U->id); - print_user_name (U->id, (union user_chat *)U); + printf ("User #%d: ", get_peer_id (U->id)); + print_user_name (U->id, (peer_t *)U); push_color (COLOR_GREEN); printf (" ("); printf ("%s", U->print_name); @@ -622,8 +622,8 @@ struct query_methods msg_send_methods = { int out_message_num; int our_id; -void out_peer_id (int id); -void do_send_message (int id, const char *msg, int len) { +void out_peer_id (peer_id_t id); +void do_send_message (peer_id_t id, const char *msg, int len) { if (!out_message_num) { out_message_num = -lrand48 (); } @@ -631,7 +631,7 @@ void do_send_message (int id, const char *msg, int len) { out_int (CODE_messages_send_message); struct message *M = malloc (sizeof (*M)); memset (M, 0, sizeof (*M)); - M->from_id = our_id; + M->from_id = MK_USER (our_id); M->to_id = id; M->unread = 1; out_peer_id (id); @@ -649,7 +649,7 @@ void do_send_message (int id, const char *msg, int len) { print_message (M); } -void do_send_text (int id, char *file_name) { +void do_send_text (peer_id_t id, char *file_name) { int fd = open (file_name, O_RDONLY); if (fd < 0) { rprintf ("No such file '%s'\n", file_name); @@ -683,7 +683,7 @@ struct query_methods mark_read_methods = { .on_answer = mark_read_on_receive }; -void do_messages_mark_read (int id, int max_id) { +void do_messages_mark_read (peer_id_t id, int max_id) { clear_packet (); out_int (CODE_messages_read_history); out_peer_id (id); @@ -726,7 +726,7 @@ int get_history_on_answer (struct query *q UU) { fetch_alloc_user (); } if (sn > 0) { - do_messages_mark_read ((long)(q->extra), ML[0]->id); + do_messages_mark_read (*(peer_id_t *)&(q->extra), ML[0]->id); } return 0; } @@ -736,14 +736,14 @@ struct query_methods get_history_methods = { }; -void do_get_history (int id, int limit) { +void do_get_history (peer_id_t id, int limit) { clear_packet (); out_int (CODE_messages_get_history); out_peer_id (id); out_int (0); out_int (0); out_int (limit); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, (void *)(long)id); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, (void *)*(long *)&id); } int get_dialogs_on_answer (struct query *q UU) { @@ -755,14 +755,15 @@ int get_dialogs_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); int n, i; n = fetch_int (); - static int dlist[3 * 100]; + static int dlist[2 * 100]; + static peer_id_t plist[100]; int dl_size = n; for (i = 0; i < n; i++) { assert (fetch_int () == CODE_dialog); if (i < 100) { - dlist[3 * i + 0] = fetch_peer_id (); - dlist[3 * i + 1] = fetch_int (); - dlist[3 * i + 2] = fetch_int (); + plist[i] = fetch_peer_id (); + dlist[2 * i + 0] = fetch_int (); + dlist[2 * i + 1] = fetch_int (); } else { fetch_peer_id (); fetch_int (); @@ -787,16 +788,20 @@ int get_dialogs_on_answer (struct query *q UU) { print_start (); push_color (COLOR_YELLOW); for (i = dl_size - 1; i >= 0; i--) { - if (dlist[3 * i] < 0) { - union user_chat *UC = user_chat_get (dlist[3 * i]); - printf ("Chat "); - print_chat_name (dlist[3 * i], UC); - printf (": %d unread\n", dlist[3 * i + 2]); - } else { - union user_chat *UC = user_chat_get (dlist[3 * i]); + peer_t *UC; + switch (get_peer_type (plist[i])) { + case PEER_USER: + UC = user_chat_get (plist[i]); printf ("User "); - print_user_name (dlist[3 * i], UC); - printf (": %d unread\n", dlist[3 * i + 2]); + print_user_name (plist[i], UC); + printf (": %d unread\n", dlist[2 * i + 1]); + break; + case PEER_CHAT: + UC = user_chat_get (plist[i]); + printf ("Chat "); + print_chat_name (plist[i], UC); + printf (": %d unread\n", dlist[2 * i + 1]); + break; } } pop_color (); @@ -825,25 +830,31 @@ struct send_file { int part_num; int part_size; long long id; - int to_id; + peer_id_t to_id; int media_type; char *file_name; }; -void out_peer_id (int id) { - union user_chat *U = user_chat_get (id); - if (id < 0) { +void out_peer_id (peer_id_t id) { + peer_t *U; + switch (get_peer_type (id)) { + case PEER_CHAT: out_int (CODE_input_peer_chat); - out_int (-id); - } else { + out_int (get_peer_id (id)); + break; + case PEER_USER: + U = user_chat_get (id); if (U && U->user.access_hash) { out_int (CODE_input_peer_foreign); - out_int (id); + out_int (get_peer_id (id)); out_long (U->user.access_hash); } else { out_int (CODE_input_peer_contact); - out_int (id); + out_int (get_peer_id (id)); } + break; + default: + assert (0); } } @@ -932,7 +943,7 @@ void send_part (struct send_file *f) { } } -void do_send_photo (int type, int to_id, char *file_name) { +void do_send_photo (int type, peer_id_t to_id, char *file_name) { int fd = open (file_name, O_RDONLY); if (fd < 0) { rprintf ("No such file '%s'\n", file_name); @@ -988,7 +999,7 @@ struct query_methods fwd_msg_methods = { .on_answer = fwd_msg_on_answer }; -void do_forward_message (int id, int n) { +void do_forward_message (peer_id_t id, int n) { clear_packet (); out_int (CODE_invoke_with_layer3); out_int (CODE_messages_forward_message); @@ -1022,17 +1033,18 @@ struct query_methods rename_chat_methods = { .on_answer = rename_chat_on_answer }; -void do_rename_chat (int id, char *name) { +void do_rename_chat (peer_id_t id, char *name) { clear_packet (); out_int (CODE_messages_edit_chat_title); - out_int (-id); + assert (get_peer_type (id) == PEER_CHAT); + out_int (get_peer_id (id)); out_string (name); send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0); } int chat_info_on_answer (struct query *q UU) { struct chat *C = fetch_alloc_chat_full (); - union user_chat *U = (void *)C; + peer_t *U = (void *)C; print_start (); push_color (COLOR_YELLOW); printf ("Chat "); @@ -1041,9 +1053,9 @@ int chat_info_on_answer (struct query *q UU) { int i; for (i = 0; i < C->users_num; i++) { printf ("\t\t"); - print_user_name (C->users[i].user_id, user_chat_get (C->users[i].user_id)); + print_user_name (MK_USER (C->users[i].user_id), user_chat_get (MK_USER (C->users[i].user_id))); printf (" invited by "); - print_user_name (C->users[i].inviter_id, user_chat_get (C->users[i].inviter_id)); + print_user_name (MK_USER (C->users[i].inviter_id), user_chat_get (MK_USER (C->users[i].inviter_id))); printf (" at "); print_date_full (C->users[i].date); if (C->users[i].user_id == C->admin_id) { @@ -1060,16 +1072,17 @@ struct query_methods chat_info_methods = { .on_answer = chat_info_on_answer }; -void do_get_chat_info (int id) { +void do_get_chat_info (peer_id_t id) { clear_packet (); out_int (CODE_messages_get_full_chat); - out_int (-id); + assert (get_peer_type (id) == PEER_CHAT); + out_int (get_peer_id (id)); send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0); } int user_info_on_answer (struct query *q UU) { struct user *U = fetch_alloc_user_full (); - union user_chat *C = (void *)U; + peer_t *C = (void *)U; print_start (); push_color (COLOR_YELLOW); printf ("User "); @@ -1093,17 +1106,18 @@ struct query_methods user_info_methods = { .on_answer = user_info_on_answer }; -void do_get_user_info (int id) { +void do_get_user_info (peer_id_t id) { clear_packet (); out_int (CODE_users_get_full_user); - union user_chat *U = user_chat_get (id); + assert (get_peer_type (id) == PEER_USER); + peer_t *U = user_chat_get (id); if (U && U->user.access_hash) { out_int (CODE_input_user_foreign); - out_int (id); + out_int (get_peer_id (id)); out_long (U->user.access_hash); } else { out_int (CODE_input_user_contact); - out_int (id); + out_int (get_peer_id (id)); } send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0); } @@ -1387,8 +1401,8 @@ int add_contact_on_answer (struct query *q UU) { struct user *U = fetch_alloc_user (); print_start (); push_color (COLOR_YELLOW); - printf ("User #%d: ", U->id); - print_user_name (U->id, (union user_chat *)U); + printf ("User #%d: ", get_peer_id (U->id)); + print_user_name (U->id, (peer_t *)U); push_color (COLOR_GREEN); printf (" ("); printf ("%s", U->print_name); diff --git a/queries.h b/queries.h index c5192ba..34e3838 100644 --- a/queries.h +++ b/queries.h @@ -19,6 +19,7 @@ #include "net.h" #ifndef __QUERIES_H__ #define __QUERIES_H__ +#include "structures.h" #define QUERY_ACK_RECEIVED 1 @@ -68,16 +69,16 @@ double get_double_time (void); void do_update_contact_list (void); union user_chat; -void do_send_message (int id, const char *msg, int len); -void do_send_text (int id, char *file); -void do_get_history (int id, int limit); +void do_send_message (peer_id_t id, const char *msg, int len); +void do_send_text (peer_id_t id, char *file); +void do_get_history (peer_id_t id, int limit); void do_get_dialog_list (void); -void do_send_photo (int type, int to_id, char *file_name); -void do_get_chat_info (int id); +void do_send_photo (int type, peer_id_t to_id, char *file_name); +void do_get_chat_info (peer_id_t id); void do_get_user_list_info_silent (int num, int *list); -void do_get_user_info (int id); -void do_forward_message (int id, int n); -void do_rename_chat (int id, char *name); +void do_get_user_info (peer_id_t id); +void do_forward_message (peer_id_t id, int n); +void do_rename_chat (peer_id_t id, char *name); struct photo; struct video; diff --git a/structures.c b/structures.c index 999f361..366603c 100644 --- a/structures.c +++ b/structures.c @@ -17,13 +17,14 @@ Copyright Vitaly Valtman 2013 */ #include +#include #include "structures.h" #include "mtproto-common.h" #include "telegram.h" #include "tree.h" #include "loop.h" int verbosity; -union user_chat *Peers[MAX_USER_NUM]; +peer_t *Peers[MAX_USER_NUM]; void fetch_file_location (struct file_location *loc) { int x = fetch_int (); @@ -67,16 +68,16 @@ int chat_num; void fetch_user (struct user *U) { unsigned x = fetch_int (); assert (x == CODE_user_empty || x == CODE_user_self || x == CODE_user_contact || x == CODE_user_request || x == CODE_user_foreign || x == CODE_user_deleted); - U->id = fetch_int (); + U->id = MK_USER (fetch_int ()); U->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_USER_SELF | FLAG_USER_FOREIGN | FLAG_USER_CONTACT); if (x == CODE_user_empty) { U->flags |= FLAG_EMPTY; return; } if (x == CODE_user_self) { - assert (!our_id || (our_id == U->id)); + assert (!our_id || (our_id == get_peer_id (U->id))); if (!our_id) { - our_id = U->id; + our_id = get_peer_id (U->id); write_auth_file (); } } @@ -226,7 +227,7 @@ void fetch_user_full (struct user *U) { void fetch_chat (struct chat *C) { unsigned x = fetch_int (); assert (x == CODE_chat_empty || x == CODE_chat || x == CODE_chat_forbidden); - C->id = -fetch_int (); + C->id = MK_CHAT (fetch_int ()); C->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_FORBIDDEN | FLAG_CHAT_IN_CHAT); if (x == CODE_chat_empty) { C->flags |= FLAG_EMPTY; @@ -292,11 +293,11 @@ void fetch_chat_full (struct chat *C) { unsigned x = fetch_int (); assert (x == CODE_messages_chat_full); assert (fetch_int () == CODE_chat_full); - C->id = -fetch_int (); + C->id = MK_CHAT (fetch_int ()); C->flags &= ~(FLAG_EMPTY | FLAG_DELETED | FLAG_FORBIDDEN | FLAG_CHAT_IN_CHAT); x = fetch_int (); if (x == CODE_chat_participants) { - assert (fetch_int () == -C->id); + assert (fetch_int () == get_peer_id (C->id)); C->admin_id = fetch_int (); assert (fetch_int () == CODE_vector); if (C->users) { @@ -440,7 +441,8 @@ void fetch_message_action (struct message_action *M) { void fetch_message_short (struct message *M) { memset (M, 0, sizeof (*M)); M->id = fetch_int (); - M->from_id = fetch_int (); + M->to_id = MK_USER (our_id); + M->from_id = MK_USER (fetch_int ()); M->message = fetch_str_dup (); fetch_int (); // pts M->date = fetch_int (); @@ -452,8 +454,8 @@ void fetch_message_short (struct message *M) { void fetch_message_short_chat (struct message *M) { memset (M, 0, sizeof (*M)); M->id = fetch_int (); - M->from_id = fetch_int (); - M->to_id = -fetch_int (); + M->from_id = MK_USER (fetch_int ()); + M->to_id = MK_CHAT (fetch_int ()); M->message = fetch_str_dup (); fetch_int (); // pts M->date = fetch_int (); @@ -493,13 +495,13 @@ void fetch_message_media (struct message_media *M) { } } -int fetch_peer_id (void) { +peer_id_t fetch_peer_id (void) { unsigned x =fetch_int (); if (x == CODE_peer_user) { - return fetch_int (); + return MK_USER (fetch_int ()); } else { assert (CODE_peer_chat); - return -fetch_int (); + return MK_CHAT (fetch_int ()); } } @@ -513,10 +515,10 @@ void fetch_message (struct message *M) { return; } if (x == CODE_message_forwarded) { - M->fwd_from_id = fetch_int (); + M->fwd_from_id = MK_USER (fetch_int ()); M->fwd_date = fetch_int (); } - M->from_id = fetch_int (); + M->from_id = MK_USER (fetch_int ()); M->to_id = fetch_peer_id (); M->out = fetch_bool (); M->unread = fetch_bool (); @@ -530,10 +532,11 @@ void fetch_message (struct message *M) { } } -#define user_cmp(a,b) ((a)->id - (b)->id) +#define id_cmp(a,b) ((a)->id - (b)->id) +#define peer_cmp(a,b) (cmp_peer_id (a->id, b->id)) -DEFINE_TREE(peer,union user_chat *,user_cmp,0) -DEFINE_TREE(message,struct message *,user_cmp,0) +DEFINE_TREE(peer,peer_t *,peer_cmp,0) +DEFINE_TREE(message,struct message *,id_cmp,0) struct tree_peer *peer_tree; struct tree_message *message_tree; @@ -551,7 +554,7 @@ struct message message_list = { struct user *fetch_alloc_user (void) { int data[2]; prefetch_data (data, 8); - union user_chat *U = user_chat_get (data[1]); + peer_t *U = user_chat_get (MK_USER (data[1])); if (U) { fetch_user (&U->user); return &U->user; @@ -569,7 +572,7 @@ struct user *fetch_alloc_user (void) { struct user *fetch_alloc_user_full (void) { int data[3]; prefetch_data (data, 12); - union user_chat *U = user_chat_get (data[2]); + peer_t *U = user_chat_get (MK_USER (data[2])); if (U) { fetch_user_full (&U->user); return &U->user; @@ -577,7 +580,7 @@ struct user *fetch_alloc_user_full (void) { users_allocated ++; U = malloc (sizeof (*U)); memset (U, 0, sizeof (*U)); - U->id = data[2]; + U->id = MK_USER (data[2]); peer_tree = tree_insert_peer (peer_tree, U, lrand48 ()); fetch_user_full (&U->user); Peers[chat_num + (user_num ++ )] = U; @@ -754,7 +757,7 @@ struct message *fetch_alloc_message_short_chat (void) { struct chat *fetch_alloc_chat (void) { int data[2]; prefetch_data (data, 8); - union user_chat *U = user_chat_get (-data[1]); + peer_t *U = user_chat_get (MK_CHAT (data[1])); if (U) { fetch_chat (&U->chat); return &U->chat; @@ -772,7 +775,7 @@ struct chat *fetch_alloc_chat (void) { struct chat *fetch_alloc_chat_full (void) { int data[3]; prefetch_data (data, 12); - union user_chat *U = user_chat_get (-data[2]); + peer_t *U = user_chat_get (MK_CHAT (data[2])); if (U) { fetch_chat_full (&U->chat); return &U->chat; @@ -780,7 +783,7 @@ struct chat *fetch_alloc_chat_full (void) { chats_allocated ++; U = malloc (sizeof (*U)); memset (U, 0, sizeof (*U)); - U->id = -data[2]; + U->id = MK_CHAT (data[2]); peer_tree = tree_insert_peer (peer_tree, U, lrand48 ()); fetch_chat_full (&U->chat); Peers[(chat_num ++) + user_num] = U; @@ -804,8 +807,8 @@ int print_stat (char *s, int len) { ); } -union user_chat *user_chat_get (int id) { - union user_chat U; +peer_t *user_chat_get (peer_id_t id) { + peer_t U; U.id = id; return tree_lookup_peer (peer_tree, &U); } diff --git a/structures.h b/structures.h index e08c1f1..20b36c9 100644 --- a/structures.h +++ b/structures.h @@ -19,6 +19,9 @@ #ifndef __STRUCTURES_H__ #define __STRUCTURES_H__ +#include +typedef struct { int id; } peer_id_t; + #define FLAG_EMPTY 1 #define FLAG_DELETED 2 #define FLAG_FORBIDDEN 4 @@ -32,6 +35,7 @@ #define FLAG_CHAT_IN_CHAT 128 + struct file_location { int dc; long long volume; @@ -70,7 +74,7 @@ struct user_status { }; struct user { - int id; + peer_id_t id; int flags; char *print_name; struct file_location photo_big; @@ -93,7 +97,7 @@ struct chat_user { }; struct chat { - int id; + peer_id_t id; int flags; char *print_title; struct file_location photo_big; @@ -107,9 +111,9 @@ struct chat { int admin_id; }; -union user_chat { +typedef union peer { struct { - int id; + peer_id_t id; int flags; char *print_name; struct file_location photo_big; @@ -118,7 +122,7 @@ union user_chat { }; struct user user; struct chat chat; -}; +} peer_t; struct video { long long id; @@ -168,10 +172,10 @@ struct message { struct message *next_use, *prev_use; int id; int flags; - int fwd_from_id; + peer_id_t fwd_from_id; int fwd_date; - int from_id; - int to_id; + peer_id_t from_id; + peer_id_t to_id; int out; int unread; int date; @@ -196,16 +200,64 @@ struct chat *fetch_alloc_chat_full (void); struct message *fetch_alloc_message (void); struct message *fetch_alloc_message_short (void); struct message *fetch_alloc_message_short_chat (void); -int fetch_peer_id (void); +peer_id_t fetch_peer_id (void); void free_user (struct user *U); void free_chat (struct chat *U); int print_stat (char *s, int len); -union user_chat *user_chat_get (int id); +peer_t *user_chat_get (peer_id_t id); struct message *message_get (int id); void update_message_id (struct message *M, int id); void message_insert (struct message *M); void free_photo (struct photo *P); void fetch_photo (struct photo *P); + +#define PEER_USER 1 +#define PEER_CHAT 2 +#define PEER_UNKNOWN 0 + +#define MK_USER(id) set_peer_id (PEER_USER,id) +#define MK_CHAT(id) set_peer_id (PEER_CHAT,id) + +static inline int get_peer_type (peer_id_t id) { + if (id.id > 0) { + return PEER_USER; + } + if (id.id < 0) { + return PEER_CHAT; + } + return PEER_UNKNOWN; +} + +static inline int get_peer_id (peer_id_t id) { + switch (get_peer_type (id)) { + case PEER_USER: + return id.id; + case PEER_CHAT: + return -id.id; + default: + return 0; + } +} + +static inline peer_id_t set_peer_id (int type, int id) { + peer_id_t ID; + switch (type) { + case PEER_USER: + ID.id = id; + return ID; + case PEER_CHAT: + ID.id = -id; + return ID; + default: + assert (0); + return ID; + } +} + +static inline int cmp_peer_id (peer_id_t a, peer_id_t b) { + return memcmp (&a, &b, sizeof (a)); +} + #endif