diff --git a/binlog.c b/binlog.c index 756e866..7ade286 100644 --- a/binlog.c +++ b/binlog.c @@ -1126,9 +1126,7 @@ static 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); - } + vlogprintf (E_DEBUG, "replay_log_event: log_pos=%lld, op=0x%08x\n", binlog_pos, op); in_ptr = rptr; in_end = wptr; @@ -1201,7 +1199,7 @@ static void replay_log_event (void) { FETCH_COMBINATOR_FUNCTION (binlog_set_msg_id) FETCH_COMBINATOR_FUNCTION (binlog_delete_msg) default: - logprintf ("Unknown op 0x%08x\n", op); + vlogprintf (E_ERROR, "Unknown op 0x%08x\n", op); assert (0); } assert (ok >= 0); @@ -1287,9 +1285,7 @@ void tgl_reopen_binlog_for_writing (void) { } static void add_log_event (const int *data, int len) { - if (verbosity) { - logprintf ("Add log event: magic = 0x%08x, len = %d\n", data[0], len); - } + vlogprintf (E_DEBUG, "Add log event: magic = 0x%08x, len = %d\n", data[0], len); assert (!(len & 3)); rptr = (void *)data; wptr = rptr + (len / 4); @@ -1297,7 +1293,7 @@ static void add_log_event (const int *data, int len) { int *end = in_end; replay_log_event (); if (rptr != wptr) { - logprintf ("Unread %lld ints. Len = %d\n", (long long)(wptr - rptr), len); + vlogprintf (E_ERROR, "Unread %lld ints. Len = %d\n", (long long)(wptr - rptr), len); assert (rptr == wptr); } if (tgl_state.binlog_enabled) { diff --git a/interface.h b/interface.h index df4906b..dd363ec 100644 --- a/interface.h +++ b/interface.h @@ -34,11 +34,6 @@ #define COLOR_INVERSE "\033[7m" -#define E_ERROR 0 -#define E_WARNING 1 -#define E_NOTICE 2 -#define E_DEBUG 3 - char *get_default_prompt (void); char *complete_none (const char *text, int state); char **complete_text (char *text, int start, int end); diff --git a/loop.c b/loop.c index ceec635..3d0ebe6 100644 --- a/loop.c +++ b/loop.c @@ -155,7 +155,7 @@ char *get_state_filename (void); char *get_secret_chat_filename (void); int zero[512]; - +/* void write_dc (int auth_file_fd, struct dc *DC) { assert (write (auth_file_fd, &DC->port, 4) == 4); int l = strlen (DC->ip); @@ -436,7 +436,7 @@ void write_secret_chat_file (void) { assert (write (fd, encr_prime, 256) == 256); } close (fd); -} +}*/ extern int max_chat_size; int mcs (void) { diff --git a/main.c b/main.c index 3ea11a2..6c5a1ca 100644 --- a/main.c +++ b/main.c @@ -49,7 +49,6 @@ #include "telegram.h" #include "loop.h" -#include "mtproto-client.h" #include "interface.h" #include "tools.h" @@ -59,8 +58,8 @@ #include "tgl.h" -#define PROGNAME "telegram-client" -#define VERSION "0.01" +#define PROGNAME "telegram-cli" +#define VERSION "0.07" #define CONFIG_DIRECTORY "." PROG_NAME #define CONFIG_FILE "config" @@ -319,13 +318,20 @@ void parse_config (void) { config_directory = make_full_path (config_directory); parse_config_val (&conf, &auth_file_name, "auth_file", AUTH_KEY_FILE, config_directory); - parse_config_val (&conf, &state_file_name, "state_file", STATE_FILE, config_directory); - parse_config_val (&conf, &secret_chat_file_name, "secret", SECRET_CHAT_FILE, config_directory); parse_config_val (&conf, &downloads_directory, "downloads", DOWNLOADS_DIRECTORY, config_directory); parse_config_val (&conf, &binlog_file_name, "binlog", BINLOG_FILE, config_directory); strcpy (buf + l, "binlog_enabled"); config_lookup_bool (&conf, buf, &binlog_enabled); + + if (binlog_enabled) { + tgl_set_binlog_mode (1); + tgl_set_binlog_path (binlog_file_name); + } else { + tgl_set_binlog_mode (0); + tgl_set_auth_file_path (auth_file_name); + } + tgl_set_download_directory (downloads_directory); if (!mkdir (config_directory, CONFIG_DIRECTORY_MODE)) { printf ("[%s] created\n", config_directory); @@ -338,10 +344,17 @@ void parse_config (void) { void parse_config (void) { printf ("libconfig not enabled\n"); tasprintf (&auth_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, AUTH_KEY_FILE); - tasprintf (&state_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, STATE_FILE); - tasprintf (&secret_chat_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, SECRET_CHAT_FILE); tasprintf (&downloads_directory, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, DOWNLOADS_DIRECTORY); tasprintf (&binlog_file_name, "%s/%s/%s", get_home_directory (), CONFIG_DIRECTORY, BINLOG_FILE); + + if (binlog_enabled) { + tgl_set_binlog_mode (1); + tgl_set_binlog_path (binlog_file_name); + } else { + tgl_set_binlog_mode (0); + tgl_set_auth_file_path (auth_file_name; + } + tgl_set_download_directory (downloads_directory); } #endif @@ -488,7 +501,7 @@ int main (int argc, char **argv) { args_parse (argc, argv); printf ( - "Telegram-client version " TG_VERSION ", Copyright (C) 2013 Vitaly Valtman\n" + "Telegram-client version " TGL_VERSION ", Copyright (C) 2013 Vitaly Valtman\n" "Telegram-client comes with ABSOLUTELY NO WARRANTY; for details type `show_license'.\n" "This is free software, and you are welcome to redistribute it\n" "under certain conditions; type `show_license' for details.\n" diff --git a/mtproto-client.c b/mtproto-client.c index de390c3..0f738ab 100644 --- a/mtproto-client.c +++ b/mtproto-client.c @@ -50,7 +50,6 @@ #include "include.h" #include "queries.h" #include "loop.h" -#include "interface.h" #include "structures.h" #include "binlog.h" #include "auto.h" @@ -142,18 +141,18 @@ static int rsa_load_public_key (const char *public_key_name) { pubKey = NULL; FILE *f = fopen (public_key_name, "r"); if (f == NULL) { - logprintf ( "Couldn't open public key file: %s\n", public_key_name); + vlogprintf (E_WARNING, "Couldn't open public key file: %s\n", public_key_name); return -1; } pubKey = PEM_read_RSAPublicKey (f, NULL, NULL, NULL); fclose (f); if (pubKey == NULL) { - logprintf ( "PEM_read_RSAPublicKey returns NULL.\n"); + vlogprintf (E_WARNING, "PEM_read_RSAPublicKey returns NULL.\n"); return -1; } if (verbosity) { - logprintf ( "public key '%s' loaded successfully\n", rsa_public_key_name); + vlogprintf (E_WARNING, "public key '%s' loaded successfully\n", rsa_public_key_name); } return 0; @@ -267,9 +266,7 @@ unsigned p1, p2; int process_respq_answer (struct connection *c, char *packet, int len) { int i; - if (verbosity) { - logprintf ( "process_respq_answer(), len=%d\n", len); - } + vlogprintf (E_DEBUG, "process_respq_answer(), len=%d\n", len); assert (len >= 76); assert (!*(long long *) packet); assert (*(int *) (packet + 16) == len - 20); @@ -289,10 +286,6 @@ int process_respq_answer (struct connection *c, char *packet, int len) { p1 = 0, p2 = 0; - if (verbosity >= 2) { - logprintf ( "%lld received\n", what); - } - int it = 0; unsigned long long g = 0; for (i = 0; i < 3 || it < 1000; i++) { @@ -337,10 +330,6 @@ int process_respq_answer (struct connection *c, char *packet, int len) { } - if (verbosity) { - logprintf ( "p1 = %d, p2 = %d, %d iterations\n", p1, p2, it); - } - /// ++p1; /// assert (*(int *) (from) == CODE_vector); @@ -354,7 +343,7 @@ int process_respq_answer (struct connection *c, char *packet, int len) { } } if (i == fingerprints_num) { - logprintf ( "fatal: don't have any matching keys (%016llx expected)\n", pk_fingerprint); + vlogprintf (E_ERROR, "fatal: don't have any matching keys (%016llx expected)\n", pk_fingerprint); exit (2); } // create inner part (P_Q_inner_data) @@ -519,7 +508,7 @@ int check_g (unsigned char p[256], BIGNUM *g) { ok = 1; break; } else if (s[i] > p[i]) { - logprintf ("i = %d (%d %d)\n", i, (int)s[i], (int)p[i]); + vlogprintf (E_WARNING, "i = %d (%d %d)\n", i, (int)s[i], (int)p[i]); return -1; } } @@ -536,11 +525,9 @@ int check_g_bn (BIGNUM *p, BIGNUM *g) { } int process_dh_answer (struct connection *c, char *packet, int len) { - if (verbosity) { - logprintf ( "process_dh_answer(), len=%d\n", len); - } + vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len); if (len < 116) { - logprintf ( "%u * %u = %llu", p1, p2, what); + vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what); } assert (len >= 116); assert (!*(long long *) packet); @@ -636,9 +623,7 @@ int process_dh_answer (struct connection *c, char *packet, int len) { int process_auth_complete (struct connection *c UU, char *packet, int len) { - if (verbosity) { - logprintf ( "process_dh_answer(), len=%d\n", len); - } + vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len); assert (len == 72); assert (!*(long long *) packet); assert (*(int *) (packet + 16) == len - 20); @@ -659,9 +644,6 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) { assert (!memcmp (packet + 56, sha1_buffer + 4, 16)); GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce; - if (verbosity >= 3) { - logprintf ( "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id); - } //kprintf ("OK\n"); //c->status = conn_error; @@ -669,9 +651,7 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) { c_state = st_authorized; //return 1; - if (verbosity) { - logprintf ( "Auth success\n"); - } + vlogprintf (E_DEBUG, "Auth success\n"); auth_success ++; GET_DC(c)->flags |= 1; write_auth_file (); @@ -735,9 +715,7 @@ int aes_encrypt_message (struct dc *DC, struct encrypted_message *enc) { assert (enc->msg_len >= 0 && enc->msg_len <= MAX_MESSAGE_INTS * 4 - 16 && !(enc->msg_len & 3)); sha1 ((unsigned char *) &enc->server_salt, enc_len, sha1_buffer); //printf ("enc_len is %d\n", enc_len); - if (verbosity >= 2) { - logprintf ( "sending message with sha1 %08x\n", *(int *)sha1_buffer); - } + vlogprintf (E_DEBUG, "sending message with sha1 %08x\n", *(int *)sha1_buffer); memcpy (enc->msg_key, sha1_buffer + 4, 16); init_aes_auth (DC->auth_key, enc->msg_key, AES_ENCRYPT); //hexdump ((char *)enc, (char *)enc + enc_len + 24); @@ -831,7 +809,7 @@ void fetch_date (void) { void fetch_seq (void) { int x = fetch_int (); if (x > seq + 1) { - logprintf ("Hole in seq: seq = %d, x = %d\n", seq, x); + vlogprintf (E_NOTICE, "Hole in seq: seq = %d, x = %d\n", seq, x); //tgl_do_get_difference (); //seq = x; } else if (x == seq + 1) { @@ -911,9 +889,11 @@ void work_update (struct connection *c UU, long long msg_id UU) { struct tgl_message *M = tglf_fetch_alloc_message (); assert (M); fetch_pts (); - unread_messages ++; - print_message (M); - update_prompt (); + + tgl_state.callback.new_msg (M); + //unread_messages ++; + //print_message (M); + //update_prompt (); break; }; case CODE_update_message_i_d: @@ -930,30 +910,38 @@ void work_update (struct connection *c UU, long long msg_id UU) { { assert (fetch_int () == (int)CODE_vector); int n = fetch_int (); + + struct tgl_message **ML = talloc (n * sizeof (void *)); + int p = 0; int i; for (i = 0; i < n; i++) { int id = fetch_int (); struct tgl_message *M = tgl_message_get (id); if (M) { bl_do_set_unread (M, 0); + ML[p ++] = M; } } fetch_pts (); - if (log_level >= 1) { + tgl_state.callback.marked_read (p, ML); + tfree (ML, sizeof (void *) * n); + /*if (log_level >= 1) { print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" %d messages marked as read\n", n); pop_color (); print_end (); - } + }*/ } break; case CODE_update_user_typing: { tgl_peer_id_t id = TGL_MK_USER (fetch_int ()); tgl_peer_t *U = tgl_peer_get (id); - if (log_level >= 2) { + + tgl_state.callback.type_notification (id, (void *)U); + /*if (log_level >= 2) { print_start (); push_color (COLOR_YELLOW); print_date (time (0)); @@ -962,7 +950,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { printf (" is typing....\n"); pop_color (); print_end (); - } + }*/ } break; case CODE_update_chat_user_typing: @@ -971,7 +959,9 @@ void work_update (struct connection *c UU, long long msg_id UU) { tgl_peer_id_t id = TGL_MK_USER (fetch_int ()); tgl_peer_t *C = tgl_peer_get (chat_id); tgl_peer_t *U = tgl_peer_get (id); - if (log_level >= 2) { + + tgl_state.callback.type_in_chat_notification (id, (void *)U, chat_id, (void *)C); + /*if (log_level >= 2) { print_start (); push_color (COLOR_YELLOW); print_date (time (0)); @@ -982,7 +972,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { printf ("....\n"); pop_color (); print_end (); - } + }*/ } break; case CODE_update_user_status: @@ -991,7 +981,8 @@ void work_update (struct connection *c UU, long long msg_id UU) { tgl_peer_t *U = tgl_peer_get (user_id); if (U) { tglf_fetch_user_status (&U->user.status); - if (log_level >= 3) { + tgl_state.callback.status_notification ((void *)U); + /*if (log_level >= 3) { print_start (); push_color (COLOR_YELLOW); print_date (time (0)); @@ -1001,7 +992,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { printf ("%s\n", (U->user.status.online > 0) ? "online" : "offline"); pop_color (); print_end (); - } + }*/ } else { struct tgl_user_status t; tglf_fetch_user_status (&t); @@ -1019,7 +1010,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { char *l = fetch_str (l2); struct tgl_user *U = &UC->user; bl_do_user_set_real_name (U, f, l1, l, l2); - print_start (); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" User "); @@ -1028,7 +1019,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { print_user_name (user_id, UC); printf ("\n"); pop_color (); - print_end (); + print_end ();*/ } else { fetch_skip_str (); fetch_skip_str (); @@ -1060,14 +1051,14 @@ void work_update (struct connection *c UU, long long msg_id UU) { } bl_do_set_user_profile_photo (U, photo_id, &big, &small); - print_start (); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" User "); print_user_name (user_id, UC); printf (" updated profile photo\n"); pop_color (); - print_end (); + print_end ();*/ } else { struct tgl_file_location t; unsigned y = fetch_int (); @@ -1086,12 +1077,12 @@ void work_update (struct connection *c UU, long long msg_id UU) { { assert (fetch_int () == CODE_vector); int n = fetch_int (); - print_start (); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" Restored %d messages\n", n); pop_color (); - print_end (); + print_end ();*/ fetch_skip (n); fetch_pts (); } @@ -1100,12 +1091,12 @@ void work_update (struct connection *c UU, long long msg_id UU) { { assert (fetch_int () == CODE_vector); int n = fetch_int (); - print_start (); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" Deleted %d messages\n", n); pop_color (); - print_end (); + print_end ();*/ fetch_skip (n); fetch_pts (); } @@ -1142,7 +1133,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { fetch_int (); // version } } - print_start (); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" Chat "); @@ -1153,7 +1144,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { printf (" changed list, but we are forbidden to know about it (Why this update even was sent to us?\n"); } pop_color (); - print_end (); + print_end ();*/ } break; case CODE_update_contact_registered: @@ -1161,28 +1152,29 @@ void work_update (struct connection *c UU, long long msg_id UU) { tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); tgl_peer_t *U = tgl_peer_get (user_id); fetch_int (); // date - print_start (); + tgl_state.callback.user_registered (U); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" User "); print_user_name (user_id, U); printf (" registered\n"); pop_color (); - print_end (); + print_end ();*/ } break; case CODE_update_contact_link: { tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); tgl_peer_t *U = tgl_peer_get (user_id); - print_start (); + /*print_start (); push_color (COLOR_YELLOW); print_date (time (0)); printf (" Updated link with user "); print_user_name (user_id, U); printf ("\n"); pop_color (); - print_end (); + print_end ();*/ unsigned t = fetch_int (); assert (t == CODE_contacts_my_link_empty || t == CODE_contacts_my_link_requested || t == CODE_contacts_my_link_contact); if (t == CODE_contacts_my_link_requested) { @@ -1246,9 +1238,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { case CODE_update_encryption: { struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (); - if (verbosity >= 2) { - logprintf ("Secret chat state = %d\n", E->state); - } + vlogprintf (E_DEBUG, "Secret chat state = %d\n", E->state); print_start (); push_color (COLOR_YELLOW); print_date (time (0)); @@ -1415,7 +1405,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { } break; default: - logprintf ("Unknown update type %08x\n", op); + vlogprintf (E_ERROR, "Unknown update type %08x\n", op); ; } } @@ -1476,9 +1466,7 @@ void work_update_short_chat_message (struct connection *c UU, long long msg_id U } void work_container (struct connection *c, long long msg_id UU) { - if (verbosity) { - logprintf ( "work_container: msg_id = %lld\n", msg_id); - } + vlogprintf (E_DEBUG, "work_container: msg_id = %lld\n", msg_id); assert (fetch_int () == CODE_msg_container); int n = fetch_int (); int i; @@ -1499,9 +1487,7 @@ void work_container (struct connection *c, long long msg_id UU) { } void work_new_session_created (struct connection *c, long long msg_id UU) { - if (verbosity) { - logprintf ( "work_new_session_created: msg_id = %lld\n", msg_id); - } + vlogprintf (E_DEBUG, "work_new_session_created: msg_id = %lld\n", msg_id); assert (fetch_int () == (int)CODE_new_session_created); fetch_long (); // first message id //DC->session_id = fetch_long (); @@ -1511,26 +1497,20 @@ void work_new_session_created (struct connection *c, long long msg_id UU) { } void work_msgs_ack (struct connection *c UU, long long msg_id UU) { - if (verbosity) { - logprintf ( "work_msgs_ack: msg_id = %lld\n", msg_id); - } + vlogprintf (E_DEBUG, "work_msgs_ack: msg_id = %lld\n", msg_id); assert (fetch_int () == CODE_msgs_ack); assert (fetch_int () == CODE_vector); int n = fetch_int (); int i; for (i = 0; i < n; i++) { long long id = fetch_long (); - if (verbosity) { - logprintf ("ack for %lld\n", id); - } + vlogprintf (E_DEBUG + 1, "ack for %lld\n", id); query_ack (id); } } void work_rpc_result (struct connection *c UU, long long msg_id UU) { - if (verbosity) { - logprintf ( "work_rpc_result: msg_id = %lld\n", msg_id); - } + vlogprintf (E_DEBUG, "work_rpc_result: msg_id = %lld\n", msg_id); assert (fetch_int () == (int)CODE_rpc_result); long long id = fetch_long (); int op = prefetch_int (); @@ -1558,10 +1538,6 @@ void work_packed (struct connection *c, long long msg_id) { //assert (total_out % 4 == 0); in_ptr = buf; in_end = in_ptr + total_out / 4; - if (verbosity >= 4) { - logprintf ( "Unzipped data: "); - hexdump_in (); - } rpc_execute_answer (c, msg_id); in_ptr = end; in_end = eend; @@ -1601,7 +1577,7 @@ void work_new_detailed_info (struct connection *c UU, long long msg_id UU) { void work_updates_to_long (struct connection *c UU, long long msg_id UU) { assert (fetch_int () == (int)CODE_updates_too_long); - logprintf ("updates to long... Getting difference\n"); + vlogprintf (E_NOTICE, "updates to long... Getting difference\n"); tgl_do_get_difference (); } @@ -1610,14 +1586,10 @@ void work_bad_msg_notification (struct connection *c UU, long long msg_id UU) { long long m1 = fetch_long (); int s = fetch_int (); int e = fetch_int (); - logprintf ("bad_msg_notification: msg_id = %lld, seq = %d, error = %d\n", m1, s, e); + vlogprintf (E_NOTICE, "bad_msg_notification: msg_id = %lld, seq = %d, error = %d\n", m1, s, e); } void rpc_execute_answer (struct connection *c, long long msg_id UU) { - if (verbosity >= 5) { - logprintf ("rpc_execute_answer: fd=%d\n", c->fd); - hexdump_in (); - } int op = prefetch_int (); switch (op) { case CODE_msg_container: @@ -1666,17 +1638,14 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { work_bad_msg_notification (c, msg_id); return; } - logprintf ( "Unknown message: \n"); - hexdump_in (); + vlogprintf (E_WARNING, "Unknown message: %08x\n", op); in_ptr = in_end; // Will not fail due to assertion in_ptr == in_end } int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, int len) { const int MINSZ = offsetof (struct encrypted_message, message); const int UNENCSZ = offsetof (struct encrypted_message, server_salt); - if (verbosity) { - logprintf ( "process_rpc_message(), len=%d\n", len); - } + vlogprintf (E_DEBUG, "process_rpc_message(), len=%d\n", len); assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15)); struct dc *DC = GET_DC(c); assert (enc->auth_key_id == DC->auth_key_id); @@ -1702,10 +1671,9 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, } double st = get_server_time (DC); if (this_server_time < st - 300 || this_server_time > st + 30) { - logprintf ("salt = %lld, session_id = %lld, msg_id = %lld, seq_no = %d, st = %lf, now = %lf\n", enc->server_salt, enc->session_id, enc->msg_id, enc->seq_no, st, get_utime (CLOCK_REALTIME)); + vlogprintf (E_WARNING, "salt = %lld, session_id = %lld, msg_id = %lld, seq_no = %d, st = %lf, now = %lf\n", enc->server_salt, enc->session_id, enc->msg_id, enc->seq_no, st, get_utime (CLOCK_REALTIME)); in_ptr = enc->message; in_end = in_ptr + (enc->msg_len / 4); - hexdump_in (); } assert (this_server_time >= st - 300 && this_server_time <= st + 30); diff --git a/mtproto-common.c b/mtproto-common.c index 9352a79..74650ae 100644 --- a/mtproto-common.c +++ b/mtproto-common.c @@ -39,7 +39,6 @@ #include #include "mtproto-common.h" -#include "interface.h" #include "include.h" #ifdef __MACH__ @@ -61,9 +60,7 @@ int get_random_bytes (unsigned char *buf, int n) { if (h >= 0) { r = read (h, buf, n); if (r > 0) { - if (verbosity >= 3) { - logprintf ( "added %d bytes of real entropy to secure random numbers seed\n", r); - } + vlogprintf (E_DEBUG, "added %d bytes of real entropy to secure random numbers seed\n", r); } else { r = 0; } @@ -143,16 +140,14 @@ void prng_seed (const char *password_filename, int password_length) { if (password_filename && password_length > 0) { int fd = open (password_filename, O_RDONLY); if (fd < 0) { - logprintf ( "Warning: fail to open password file - \"%s\", %m.\n", password_filename); + vlogprintf (E_WARNING, "Warning: fail to open password file - \"%s\", %m.\n", password_filename); } else { unsigned char *a = talloc0 (password_length); int l = read (fd, a, password_length); if (l < 0) { - logprintf ( "Warning: fail to read password file - \"%s\", %m.\n", password_filename); + vlogprintf (E_WARNING, "Warning: fail to read password file - \"%s\", %m.\n", password_filename); } else { - if (verbosity > 0) { - logprintf ( "read %d bytes from password file.\n", l); - } + vlogprintf (E_DEBUG, "read %d bytes from password file.\n", l); RAND_add (a, l, l); } close (fd); diff --git a/mtproto-common.h b/mtproto-common.h index dcec745..439860a 100644 --- a/mtproto-common.h +++ b/mtproto-common.h @@ -26,9 +26,11 @@ #include #include -#include "interface.h" +//#include "interface.h" #include "tools.h" #include "auto/constants.h" + +#include "tgl.h" /* DH key exchange protocol data structures */ #define CODE_req_pq 0x60469778 #define CODE_resPQ 0x05162463 @@ -178,9 +180,7 @@ static inline int prefetch_strlen (void) { extern int verbosity; static inline char *fetch_str (int len) { assert (len >= 0); - if (verbosity > 6) { - logprintf ("fetch_string: len = %d\n", len); - } + vlogprintf (E_DEBUG + 3, "fetch_string: len = %d\n", len); if (len < 254) { char *str = (char *) in_ptr + 1; in_ptr += 1 + (len >> 2); @@ -272,16 +272,12 @@ int fetch_bignum (BIGNUM *x); static inline int fetch_int (void) { assert (in_ptr + 1 <= in_end); - if (verbosity > 6) { - logprintf ("fetch_int: 0x%08x (%d)\n", *in_ptr, *in_ptr); - } + vlogprintf (E_DEBUG + 3, "fetch_int: 0x%08x (%d)\n", *in_ptr, *in_ptr); return *(in_ptr ++); } static inline int fetch_bool (void) { - if (verbosity > 6) { - logprintf ("fetch_bool: 0x%08x (%d)\n", *in_ptr, *in_ptr); - } + vlogprintf (E_DEBUG + 3, "fetch_bool: 0x%08x (%d)\n", *in_ptr, *in_ptr); assert (in_ptr + 1 <= in_end); assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false); return *(in_ptr ++) == (int)CODE_bool_true; @@ -349,14 +345,14 @@ void init_aes_unauth (const char server_nonce[16], const char hidden_client_nonc void init_aes_auth (char auth_key[192], char msg_key[16], int encrypt); int pad_aes_encrypt (char *from, int from_len, char *to, int size); int pad_aes_decrypt (char *from, int from_len, char *to, int size); - +/* static inline void hexdump_in (void) { hexdump (in_ptr, in_end); } static inline void hexdump_out (void) { hexdump (packet_buffer, packet_ptr); -} +}*/ #ifdef __MACH__ #define CLOCK_REALTIME 0 diff --git a/net.h b/net.h index d89029f..1a47574 100644 --- a/net.h +++ b/net.h @@ -26,9 +26,6 @@ struct dc; #define TG_SERVER_TEST "173.240.5.253" #define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74" #define TG_APP_ID 2899 -#define TG_BUILD "209" - -#define TG_VERSION "0.01-beta" #define ACK_TIMEOUT 1 #define MAX_DC_ID 10 diff --git a/queries.c b/queries.c index 23d0ee7..bcecd9b 100644 --- a/queries.c +++ b/queries.c @@ -43,7 +43,7 @@ #include "telegram.h" #include "loop.h" #include "structures.h" -#include "interface.h" +//#include "interface.h" #include "net.h" #include #include @@ -64,21 +64,21 @@ #define OPEN_BIN "xdg-open %s" #endif +int want_dc_num; char *get_downloads_directory (void); -int verbosity; -extern int offline_mode; +//extern int offline_mode; -long long cur_uploading_bytes; -long long cur_uploaded_bytes; -long long cur_downloading_bytes; -long long cur_downloaded_bytes; +//long long cur_uploading_bytes; +//long long cur_uploaded_bytes; +//long long cur_downloading_bytes; +//long long cur_downloaded_bytes; -extern int binlog_enabled; -extern int sync_from_start; +//extern int binlog_enabled; +//extern int sync_from_start; -int queries_num; +static int queries_num; -void out_peer_id (tgl_peer_id_t id); +static void out_peer_id (tgl_peer_id_t id); #define QUERY_TIMEOUT 6.0 #define memcmp8(a,b) memcmp ((a), (b), 8) @@ -97,9 +97,7 @@ struct query *query_get (long long id) { int alarm_query (struct query *q) { assert (q); - if (verbosity >= 1) { - logprintf ("Alarm query %lld\n", q->msg_id); - } + vlogprintf (E_DEBUG, "Alarm query %lld\n", q->msg_id); q->ev.timeout = get_double_time () + QUERY_TIMEOUT; insert_event_timer (&q->ev); @@ -127,15 +125,13 @@ void query_restart (long long id) { } } -struct query *send_query (struct dc *DC, int ints, void *data, struct query_methods *methods, void *extra) { +struct query *send_query (struct dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) { assert (DC); assert (DC->auth_key_id); if (!DC->sessions[0]) { dc_create_session (DC); } - if (verbosity) { - logprintf ( "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port); - } + vlogprintf (E_DEBUG, "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port); struct query *q = talloc0 (sizeof (*q)); q->data_len = ints; q->data = talloc (4 * ints); @@ -143,15 +139,11 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth q->msg_id = encrypt_send_message (DC->sessions[0]->c, data, ints, 1); q->session = DC->sessions[0]; q->seq_no = DC->sessions[0]->seq_no - 1; - if (verbosity) { - logprintf ( "Msg_id is %lld %p\n", q->msg_id, q); - } + vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q); q->methods = methods; q->DC = DC; if (queries_tree) { - if (verbosity >= 2) { - logprintf ( "%lld %lld\n", q->msg_id, queries_tree->x->msg_id); - } + vlogprintf (E_DEBUG + 2, "%lld %lld\n", q->msg_id, queries_tree->x->msg_id); } queries_tree = tree_insert_query (queries_tree, q, lrand48 ()); @@ -161,10 +153,18 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth insert_event_timer (&q->ev); q->extra = extra; + q->callback = callback; + q->callback_extra = callback_extra; queries_num ++; return q; } +static int fail_on_error (struct query *q UU, int error_code UU, int l UU, char *error UU) { + fprintf (stderr, "error #%d: %.*s\n", error_code, l, error); + assert (0); + return 0; +} + void query_ack (long long id) { struct query *q = query_get (id); if (q && !(q->flags & QUERY_ACK_RECEIVED)) { @@ -179,14 +179,10 @@ void query_error (long long id) { int error_code = fetch_int (); int error_len = prefetch_strlen (); char *error = fetch_str (error_len); - if (verbosity) { - logprintf ( "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); - } + vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); struct query *q = query_get (id); if (!q) { - if (verbosity) { - logprintf ( "No such query\n"); - } + vlogprintf (E_WARNING, "No such query\n"); } else { if (!(q->flags & QUERY_ACK_RECEIVED)) { remove_event_timer (&q->ev); @@ -195,7 +191,7 @@ void query_error (long long id) { if (q->methods && q->methods->on_error) { q->methods->on_error (q, error_code, error_len, error); } else { - logprintf ( "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); + vlogprintf ( E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); } tfree (q->data, q->data_len * 4); tfree (q, sizeof (*q)); @@ -207,13 +203,11 @@ void query_error (long long id) { static int packed_buffer[MAX_PACKED_SIZE / 4]; void query_result (long long id UU) { - if (verbosity) { - logprintf ( "result for query #%lld\n", id); - } - if (verbosity >= 4) { + vlogprintf (E_DEBUG, "result for query #%lld\n", id); + /*if (verbosity >= 4) { logprintf ( "result: "); hexdump_in (); - } + }*/ int op = prefetch_int (); int *end = 0; int *eend = 0; @@ -227,16 +221,17 @@ void query_result (long long id UU) { //assert (total_out % 4 == 0); in_ptr = packed_buffer; in_end = in_ptr + total_out / 4; - if (verbosity >= 4) { + /*if (verbosity >= 4) { logprintf ( "Unzipped data: "); hexdump_in (); - } + }*/ } struct query *q = query_get (id); if (!q) { - if (verbosity) { - logprintf ( "No such query\n"); - } + //if (verbosity) { + // logprintf ( "No such query\n"); + //} + vlogprintf (E_WARNING, "No such query\n"); in_ptr = in_end; } else { if (!(q->flags & QUERY_ACK_RECEIVED)) { @@ -247,7 +242,7 @@ void query_result (long long id UU) { if (q->methods->type) { int *save = in_ptr; if (skip_type_any (q->methods->type) < 0) { - logprintf ("Skipped %ld int out of %ld (type %s)\n", in_ptr - save, in_end - save, q->methods->type->type->id); + vlogprintf (E_ERROR, "Skipped %ld int out of %ld (type %s)\n", in_ptr - save, in_end - save, q->methods->type->type->id); assert (0); } @@ -272,16 +267,12 @@ DEFINE_TREE (timer, struct event_timer *, event_timer_cmp, 0) struct tree_timer *timer_tree; void insert_event_timer (struct event_timer *ev) { - if (verbosity > 2) { - logprintf ( "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); - } + vlogprintf (E_DEBUG + 2, "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); timer_tree = tree_insert_timer (timer_tree, ev, lrand48 ()); } void remove_event_timer (struct event_timer *ev) { - if (verbosity > 2) { - logprintf ( "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); - } + vlogprintf (E_DEBUG + 2, "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); timer_tree = tree_delete_timer (timer_tree, ev); } @@ -298,21 +289,19 @@ void work_timers (void) { if (ev->timeout > t) { break; } remove_event_timer (ev); assert (ev->alarm); - if (verbosity) { - logprintf ("Alarm\n"); - } + vlogprintf (E_DEBUG, "Alarm\n"); ev->alarm (ev->self); } } int max_chat_size; int max_bcast_size; -int want_dc_num; -int new_dc_num; +//int want_dc_num; +//int new_dc_num; extern struct dc *DC_list[]; extern struct dc *DC_working; -void out_random (int n) { +static void out_random (int n) { assert (n <= 32); static char buf[32]; secure_random (buf, n); @@ -331,19 +320,19 @@ void tgl_do_insert_header (void) { static char buf[4096]; tsnprintf (buf, sizeof (buf), "%.999s %.999s %.999s\n", st.sysname, st.release, st.version); out_string (buf); - out_string (TG_VERSION " (build " TG_BUILD ")"); + out_string (TGL_VERSION " (build " TGL_BUILD ")"); out_string ("En"); } else { out_string ("x86"); out_string ("Linux"); - out_string (TG_VERSION); + out_string (TGL_VERSION); out_string ("en"); } } /* {{{ Get config */ -void fetch_dc_option (void) { +static void fetch_dc_option (void) { assert (fetch_int () == CODE_dc_option); int id = fetch_int (); int l1 = prefetch_strlen (); @@ -351,14 +340,12 @@ void fetch_dc_option (void) { int l2 = prefetch_strlen (); char *ip = fetch_str (l2); int port = fetch_int (); - if (verbosity) { - logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port); - } + vlogprintf (E_DEBUG, "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port); bl_do_dc_option (id, l1, name, l2, ip, port); } -int help_get_config_on_answer (struct query *q UU) { +static int help_get_config_on_answer (struct query *q UU) { unsigned op = fetch_int (); assert (op == CODE_config || op == CODE_config_old); fetch_int (); @@ -367,9 +354,7 @@ int help_get_config_on_answer (struct query *q UU) { assert (test_mode == CODE_bool_true || test_mode == CODE_bool_false); assert (test_mode == CODE_bool_false || test_mode == CODE_bool_true); int this_dc = fetch_int (); - if (verbosity) { - logprintf ( "this_dc = %d\n", this_dc); - } + vlogprintf (E_DEBUG, "this_dc = %d\n", this_dc); assert (fetch_int () == CODE_vector); int n = fetch_int (); assert (n <= 10); @@ -381,30 +366,32 @@ int help_get_config_on_answer (struct query *q UU) { if (op == CODE_config) { max_bcast_size = fetch_int (); } - if (verbosity >= 2) { - logprintf ( "chat_size = %d\n", max_chat_size); + vlogprintf (E_DEBUG, "chat_size = %d\n", max_chat_size); + + if (q->callback) { + ((void (*)(void *, int))(q->callback))(q->callback_extra, 1); } return 0; } -struct query_methods help_get_config_methods = { +static struct query_methods help_get_config_methods = { .on_answer = help_get_config_on_answer, .type = TYPE_TO_PARAM(config) }; -void tgl_do_help_get_config (void) { +void tgl_do_help_get_config (void (*callback)(void *, int), void *callback_extra) { clear_packet (); tgl_do_insert_header (); out_int (CODE_help_get_config); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Send code */ -char *phone_code_hash; -int send_code_on_answer (struct query *q UU) { +static char *phone_code_hash; +static int send_code_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_auth_sent_code); - fetch_bool (); + int registered = fetch_bool (); int l = prefetch_strlen (); char *s = fetch_str (l); if (phone_code_hash) { @@ -414,10 +401,13 @@ int send_code_on_answer (struct query *q UU) { fetch_int (); fetch_bool (); want_dc_num = -1; + if (q->callback) { + ((void (*)(void *, int, int, const char *))(q->callback)) (q->callback_extra, 1, registered, phone_code_hash); + } return 0; } -int send_code_on_error (struct query *q UU, int error_code, int l, char *error) { +static int send_code_on_error (struct query *q UU, int error_code, int l, char *error) { int s = strlen ("PHONE_MIGRATE_"); int s2 = strlen ("NETWORK_MIGRATE_"); if (l >= s && !memcmp (error, "PHONE_MIGRATE_", s)) { @@ -427,31 +417,26 @@ int send_code_on_error (struct query *q UU, int error_code, int l, char *error) int i = error[s2] - '0'; want_dc_num = i; } else { - logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error); + vlogprintf (E_ERROR, "error_code = %d, error = %.*s\n", error_code, l, error); assert (0); } + if (q->callback) { + ((void (*)(void *, int, int, const char *))(q->callback)) (q->callback_extra, 0, 0, 0); + } return 0; } -struct query_methods send_code_methods = { +static struct query_methods send_code_methods = { .on_answer = send_code_on_answer, .on_error = send_code_on_error, .type = TYPE_TO_PARAM(auth_sent_code) }; -int code_is_sent (void) { - return want_dc_num; -} - -int config_got (void) { - return DC_list[want_dc_num] != 0; -} - -char *suser; +//char *suser; extern int dc_working_num; -void tgl_do_send_code (const char *user) { - logprintf ("sending code\n"); - suser = tstrdup (user); +void tgl_do_send_code (const char *user, void (*callback)(void *callback_extra, int success, int registered, const char *hash), void *callback_extra) { + vlogprintf (E_DEBUG, "sending code to dc %d\n", dc_working_num); + //suser = tstrdup (user); want_dc_num = 0; clear_packet (); tgl_do_insert_header (); @@ -462,56 +447,26 @@ void tgl_do_send_code (const char *user) { out_string (TG_APP_HASH); out_string ("en"); - logprintf ("send_code: dc_num = %d\n", dc_working_num); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0); - net_loop (0, code_is_sent); - if (want_dc_num == -1) { return; } - - DC_working = DC_list[want_dc_num]; - if (!DC_working->sessions[0]) { - dc_create_session (DC_working); - } - dc_working_num = want_dc_num; - - bl_do_set_working_dc (dc_working_num); - - logprintf ("send_code: dc_num = %d\n", dc_working_num); - want_dc_num = 0; - clear_packet (); - tgl_do_insert_header (); - out_int (CODE_auth_send_code); - out_string (user); - out_int (0); - out_int (TG_APP_ID); - out_string (TG_APP_HASH); - out_string ("en"); - - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0); - net_loop (0, code_is_sent); - assert (want_dc_num == -1); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0, callback, callback_extra); } -int phone_call_on_answer (struct query *q UU) { +static int phone_call_on_answer (struct query *q UU) { fetch_bool (); + if (q->callback) { + ((void (*)(void *, int))(q->callback))(q->callback_extra, 1); + } return 0; } -int phone_call_on_error (struct query *q UU, int error_code, int l, char *error) { - logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error); - assert (0); - return 0; -} - -struct query_methods phone_call_methods = { +static struct query_methods phone_call_methods = { .on_answer = phone_call_on_answer, - .on_error = phone_call_on_error, .type = TYPE_TO_PARAM(bool) }; -void tgl_do_phone_call (const char *user) { - logprintf ("calling user\n"); - suser = tstrdup (user); +void tgl_do_phone_call (const char *user, void (*callback)(void *callback_extra, int success), void *callback_extra) { + vlogprintf (E_DEBUG, "calling user\n"); + //suser = tstrdup (user); want_dc_num = 0; clear_packet (); tgl_do_insert_header (); @@ -519,13 +474,12 @@ void tgl_do_phone_call (const char *user) { out_string (user); out_string (phone_code_hash); - logprintf ("tgl_do_phone_call: dc_num = %d\n", dc_working_num); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Check phone */ -int check_phone_result; +/*int check_phone_result; int cr_f (void) { return check_phone_result >= 0; } @@ -586,11 +540,11 @@ int tgl_do_auth_check_phone (const char *user) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); net_loop (0, cr_f); return check_phone_result; -} +}*/ /* }}} */ /* {{{ Nearest DC */ -int nearest_dc_num; +/*int nearest_dc_num; int nr_f (void) { return nearest_dc_num >= 0; } @@ -607,12 +561,6 @@ int nearest_dc_on_answer (struct query *q UU) { return 0; } -int fail_on_error (struct query *q UU, int error_code UU, int l UU, char *error UU) { - fprintf (stderr, "error #%d: %.*s\n", error_code, l, error); - assert (0); - return 0; -} - struct query_methods nearest_dc_methods = { .on_answer = nearest_dc_on_answer, .on_error = fail_on_error, @@ -626,79 +574,58 @@ int tgl_do_get_nearest_dc (void) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &nearest_dc_methods, 0); net_loop (0, nr_f); return nearest_dc_num; -} +}*/ /* }}} */ /* {{{ Sign in / Sign up */ -int sign_in_ok; -int sign_in_is_ok (void) { - return sign_in_ok; -} - -struct tgl_user User; - -int sign_in_on_answer (struct query *q UU) { +static int sign_in_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_auth_authorization); int expires = fetch_int (); - tglf_fetch_user (&User); - if (!tgl_state.our_id) { - bl_do_set_our_id (tgl_get_peer_id (User.id)); - } - sign_in_ok = 1; - if (verbosity) { - logprintf ( "authorized successfully: name = '%s %s', phone = '%s', expires = %d\n", User.first_name, User.last_name, User.phone, (int)(expires - get_double_time ())); - } + vlogprintf (E_DEBUG, "Expires in %d\n", expires); + + struct tgl_user *U = tglf_fetch_alloc_user (); + DC_working->has_auth = 1; bl_do_dc_signed (DC_working->id); + if (q->callback) { + ((void (*)(void *, int, struct tgl_user *))q->callback) (q->callback_extra, 1, U); + } + return 0; } -int sign_in_on_error (struct query *q UU, int error_code, int l, char *error) { - logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error); - sign_in_ok = -1; - assert (0); - return 0; -} - -struct query_methods sign_in_methods = { +static struct query_methods sign_in_methods = { .on_answer = sign_in_on_answer, - .on_error = sign_in_on_error, .type = TYPE_TO_PARAM(auth_authorization) }; -int tgl_do_send_code_result (const char *code) { +int tgl_do_send_code_result (const char *user, const char *code, void (*callback)(void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) { clear_packet (); out_int (CODE_auth_sign_in); - out_string (suser); + out_string (user); out_string (phone_code_hash); out_string (code); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0); - sign_in_ok = 0; - net_loop (0, sign_in_is_ok); - return sign_in_ok; + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); + return 0; } -int tgl_do_send_code_result_auth (const char *code, const char *first_name, const char *last_name) { +int tgl_do_send_code_result_auth (const char *user, const char *code, const char *first_name, const char *last_name, void (*callback)(void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) { clear_packet (); out_int (CODE_auth_sign_up); - out_string (suser); + out_string (user); out_string (phone_code_hash); out_string (code); out_string (first_name); out_string (last_name); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0); - sign_in_ok = 0; - net_loop (0, sign_in_is_ok); - return sign_in_ok; + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); + return 0; } /* }}} */ /* {{{ Get contacts */ -extern char *user_list[]; - -int get_contacts_on_answer (struct query *q UU) { +static int get_contacts_on_answer (struct query *q UU) { int i; assert (fetch_int () == (int)CODE_contacts_contacts); @@ -711,7 +638,15 @@ int get_contacts_on_answer (struct query *q UU) { } assert (fetch_int () == CODE_vector); n = fetch_int (); + struct tgl_user **list = talloc (sizeof (void *) * n); for (i = 0; i < n; i++) { + list[i] = tglf_fetch_alloc_user (); + } + if (q->callback) { + ((void (*)(void *, int, int, struct tgl_user **))q->callback) (q->callback_extra, 1, n, list); + } + tfree (list, sizeof (void *) * n); +/* for (i = 0; i < n; i++) { struct tgl_user *U = tglf_fetch_alloc_user (); print_start (); push_color (COLOR_YELLOW); @@ -739,30 +674,30 @@ int get_contacts_on_answer (struct query *q UU) { } pop_color (); print_end (); - } + }*/ return 0; } -struct query_methods get_contacts_methods = { +static struct query_methods get_contacts_methods = { .on_answer = get_contacts_on_answer, .type = TYPE_TO_PARAM(contacts_contacts) }; -void tgl_do_update_contact_list (void) { +void tgl_do_update_contact_list (void (*callback) (void *callback_extra, int success, int size, struct tgl_user *contacts[]), void *callback_extra) { clear_packet (); out_int (CODE_contacts_get_contacts); out_string (""); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Encrypt decrypted */ -int *encr_extra; -int *encr_ptr; -int *encr_end; +static int *encr_extra; +static int *encr_ptr; +static int *encr_end; -char *encrypt_decrypted_message (struct tgl_secret_chat *E) { +static char *encrypt_decrypted_message (struct tgl_secret_chat *E) { static int msg_key[4]; static unsigned char sha1a_buffer[20]; static unsigned char sha1b_buffer[20]; @@ -848,22 +783,25 @@ void tgl_do_send_encr_chat_layer (struct tgl_secret_chat *E) { struct tgl_message *M = tgl_message_get (t); assert (M); - tgl_do_send_msg (M); - print_message (M); + tgl_do_send_msg (M, 0, 0); + //print_message (M); } /* {{{ Seng msg (plain text) */ -int msg_send_encr_on_answer (struct query *q UU) { +static int msg_send_encr_on_answer (struct query *q UU) { assert (fetch_int () == CODE_messages_sent_encrypted_message); - rprintf ("Sent\n"); struct tgl_message *M = q->extra; //M->date = fetch_int (); fetch_int (); bl_do_set_message_sent (M); + + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); + } return 0; } -int msg_send_on_answer (struct query *q UU) { +static 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 @@ -873,6 +811,9 @@ int msg_send_on_answer (struct query *q UU) { fetch_pts (); fetch_seq (); if (x == CODE_messages_sent_message_link) { + assert (skip_type_any (TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (contacts_link))) >= 0); + } + /*if (x == CODE_messages_sent_message_link) { assert (fetch_int () == CODE_vector); int n = fetch_int (); int i; @@ -910,35 +851,46 @@ int msg_send_on_answer (struct query *q UU) { pop_color (); print_end (); } - } - rprintf ("Sent: id = %d\n", id); + }*/ bl_do_set_message_sent (M); + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); + } return 0; } -int msg_send_on_error (struct query *q, int error_code, int error_len, char *error) { - logprintf ( "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error); +static int msg_send_on_error (struct query *q, int error_code, int error_len, char *error) { + vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error); struct tgl_message *M = q->extra; + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 0, M); + } bl_do_delete_msg (M); return 0; } -struct query_methods msg_send_methods = { +static struct query_methods msg_send_methods = { .on_answer = msg_send_on_answer, .on_error = msg_send_on_error, .type = TYPE_TO_PARAM(messages_sent_message) }; -struct query_methods msg_send_encr_methods = { +static struct query_methods msg_send_encr_methods = { .on_answer = msg_send_encr_on_answer, .type = TYPE_TO_PARAM(messages_sent_encrypted_message) }; -int out_message_num; +//int out_message_num; -void tgl_do_send_encr_msg_action (struct tgl_message *M) { +void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_peer_t *P = tgl_peer_get (M->to_id); - if (!P || P->encr_chat.state != sc_ok) { return; } + if (!P || P->encr_chat.state != sc_ok) { + vlogprintf (E_WARNING, "Unknown encrypted chat\n"); + if (callback) { + ((void (*)(void *, int, struct tgl_message *))callback) (callback_extra, 0, M); + } + return; + } clear_packet (); out_int (CODE_messages_send_encrypted_service); @@ -963,16 +915,22 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M) { } encr_finish (&P->encr_chat); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); } -void tgl_do_send_encr_msg (struct tgl_message *M) { +void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (M->service) { - tgl_do_send_encr_msg_action (M); + tgl_do_send_encr_msg_action (M, callback, callback_extra); return; } tgl_peer_t *P = tgl_peer_get (M->to_id); - if (!P || P->encr_chat.state != sc_ok) { return; } + if (!P || P->encr_chat.state != sc_ok) { + vlogprintf (E_WARNING, "Unknown encrypted chat\n"); + if (callback) { + ((void (*)(void *, int, struct tgl_message *))callback) (callback_extra, 0, M); + } + return; + } clear_packet (); out_int (CODE_messages_send_encrypted); @@ -990,12 +948,12 @@ void tgl_do_send_encr_msg (struct tgl_message *M) { out_int (CODE_decrypted_message_media_empty); encr_finish (&P->encr_chat); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); } -void tgl_do_send_msg (struct tgl_message *M) { +void tgl_do_send_msg (struct tgl_message *M, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT) { - tgl_do_send_encr_msg (M); + tgl_do_send_encr_msg (M, callback, callback_extra); return; } clear_packet (); @@ -1003,50 +961,60 @@ void tgl_do_send_msg (struct tgl_message *M) { 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); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, M, callback, callback_extra); } -void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len) { +void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { tgl_peer_t *P = tgl_peer_get (id); if (!P) { - logprintf ("Can not send to unknown encrypted chat\n"); + vlogprintf (E_WARNING, "Unknown encrypted chat\n"); + if (callback) { + ((void (*)(void *, int, struct tgl_message *))callback) (callback_extra, 0, 0); + } return; } if (P->encr_chat.state != sc_ok) { - logprintf ("Chat is not yet initialized\n"); + vlogprintf (E_WARNING, "Chat is not yet initialized\n"); + if (callback) { + ((void (*)(void *, int, struct tgl_message *))callback) (callback_extra, 0, 0); + } return; } } long long t; secure_random (&t, 8); - logprintf ("t = %lld, len = %d\n", t, len); + vlogprintf (E_DEBUG, "t = %lld, len = %d\n", t, len); bl_do_send_message_text (t, tgl_state.our_id, tgl_get_peer_type (id), tgl_get_peer_id (id), time (0), len, msg); struct tgl_message *M = tgl_message_get (t); assert (M); - tgl_do_send_msg (M); - print_message (M); + tgl_do_send_msg (M, callback, callback_extra); + //print_message (M); } /* }}} */ /* {{{ Send text file */ -void tgl_do_send_text (tgl_peer_id_t id, char *file_name) { +void tgl_do_send_text (tgl_peer_id_t id, char *file_name, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { int fd = open (file_name, O_RDONLY); if (fd < 0) { - rprintf ("No such file '%s'\n", file_name); - tfree_str (file_name); + vlogprintf (E_WARNING, "No such file '%s'\n", file_name); + if (callback) { + ((void (*)(void *, int, struct tgl_message *))callback) (callback_extra, 0, 0); + } return; } static char buf[(1 << 20) + 1]; int x = read (fd, buf, (1 << 20) + 1); assert (x >= 0); if (x == (1 << 20) + 1) { - rprintf ("Too big file '%s'\n", file_name); - tfree_str (file_name); + vlogprintf (E_WARNING, "Too big file '%s'\n", file_name); close (fd); + if (callback) { + ((void (*)(void *, int, struct tgl_message *))callback) (callback_extra, 0, 0); + } } else { buf[x] = 0; - tgl_do_send_message (id, buf, x); + tgl_do_send_message (id, buf, x, callback, callback_extra); tfree_str (file_name); close (fd); } @@ -1054,96 +1022,93 @@ void tgl_do_send_text (tgl_peer_id_t id, char *file_name) { /* }}} */ /* {{{ Mark read */ -int mark_read_on_receive (struct query *q UU) { +static int mark_read_on_receive (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_affected_history); fetch_pts (); fetch_seq (); fetch_int (); // offset + if (q->callback) { + ((void (*)(void *, int))q->callback)(q->callback_extra, 1); + } return 0; } -int mark_read_encr_on_receive (struct query *q UU) { +static int mark_read_encr_on_receive (struct query *q UU) { fetch_bool (); + if (q->callback) { + ((void (*)(void *, int))q->callback)(q->callback_extra, 1); + } return 0; } -struct query_methods mark_read_methods = { +static struct query_methods mark_read_methods = { .on_answer = mark_read_on_receive, .type = TYPE_TO_PARAM(messages_affected_history) }; -struct query_methods mark_read_encr_methods = { +static struct query_methods mark_read_encr_methods = { .on_answer = mark_read_encr_on_receive, .type = TYPE_TO_PARAM(bool) }; -void tgl_do_messages_mark_read (tgl_peer_id_t id, int max_id) { +void tgl_do_messages_mark_read (tgl_peer_id_t id, int max_id, void (*callback)(void *callback_extra, int), void *callback_extra) { clear_packet (); out_int (CODE_messages_read_history); out_peer_id (id); out_int (max_id); out_int (0); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, 0, callback, callback_extra); } -void tgl_do_messages_mark_read_encr (tgl_peer_id_t id, long long access_hash, int last_time) { +void tgl_do_messages_mark_read_encr (tgl_peer_id_t id, long long access_hash, int last_time, void (*callback)(void *callback_extra, int), void *callback_extra) { clear_packet (); out_int (CODE_messages_read_encrypted_history); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (id)); out_long (access_hash); out_int (last_time); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, 0, callback, callback_extra); } -void tgl_do_mark_read (tgl_peer_id_t id) { +void tgl_do_mark_read (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success), void *callback_extra) { tgl_peer_t *P = tgl_peer_get (id); if (!P) { - rprintf ("Unknown peer\n"); + vlogprintf (E_WARNING, "Unknown peer\n"); + callback (callback_extra, 0); return; } if (tgl_get_peer_type (id) == TGL_PEER_USER || tgl_get_peer_type (id) == TGL_PEER_CHAT) { if (!P->last) { - rprintf ("Unknown last peer message\n"); + vlogprintf (E_WARNING, "Unknown last peer message\n"); + callback (callback_extra, 0); return; } - tgl_do_messages_mark_read (id, P->last->id); + tgl_do_messages_mark_read (id, P->last->id, callback, callback_extra); return; } assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT); if (P->last) { - tgl_do_messages_mark_read_encr (id, P->encr_chat.access_hash, P->last->date); + tgl_do_messages_mark_read_encr (id, P->encr_chat.access_hash, P->last->date, callback, callback_extra); } else { - tgl_do_messages_mark_read_encr (id, P->encr_chat.access_hash, time (0) - 10); + tgl_do_messages_mark_read_encr (id, P->encr_chat.access_hash, time (0) - 10, callback, callback_extra); } } /* }}} */ /* {{{ Get history */ -int get_history_on_answer (struct query *q UU) { - static struct tgl_message *ML[10000]; +static int get_history_on_answer (struct query *q UU) { int i; int x = fetch_int (); - if (x == (int)CODE_messages_messages_slice) { - fetch_int (); - rprintf ("...\n"); - } else { - assert (x == (int)CODE_messages_messages); - } + assert (x == (int)CODE_messages_messages_slice || x == (int)CODE_messages_messages); assert (fetch_int () == CODE_vector); int n = fetch_int (); + struct tgl_message **ML = talloc (sizeof (void *) * n); for (i = 0; i < n; i++) { - struct tgl_message *M = tglf_fetch_alloc_message (); - if (i <= 9999) { - ML[i] = M; - } + ML[i] = tglf_fetch_alloc_message (); } - if (n > 10000) { n = 10000; } int sn = n; - for (i = n - 1; i >= 0; i--) { - print_message (ML[i]); - } + assert (fetch_int () == CODE_vector); n = fetch_int (); for (i = 0; i < n; i++) { @@ -1154,20 +1119,32 @@ int get_history_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { tglf_fetch_alloc_user (); } + + if (q->callback) { + ((void (*)(void *, int, int, struct tgl_message **))q->callback) (q->callback_extra, 1, sn, ML); + } + tfree (ML, sizeof (void *) * n); + + /*for (i = n - 1; i >= 0; i--) { + print_message (ML[i]); + }*/ if (sn > 0 && q->extra) { - tgl_do_messages_mark_read (*(tgl_peer_id_t *)&(q->extra), ML[0]->id); + tgl_do_messages_mark_read (*(tgl_peer_id_t *)&(q->extra), ML[0]->id, 0, 0); } return 0; } -struct query_methods get_history_methods = { +static struct query_methods get_history_methods = { .on_answer = get_history_on_answer, .type = TYPE_TO_PARAM(messages_messages) }; -void tgl_do_get_local_history (tgl_peer_id_t id, int limit) { +void tgl_do_get_local_history (tgl_peer_id_t id, int limit, void (*callback)(void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { tgl_peer_t *P = tgl_peer_get (id); - if (!P || !P->last) { return; } + if (!P || !P->last) { + callback (callback_extra, 0, 0, 0); + return; + } struct tgl_message *M = P->last; int count = 1; assert (!M->prev); @@ -1175,16 +1152,23 @@ void tgl_do_get_local_history (tgl_peer_id_t id, int limit) { M = M->next; count ++; } - while (M) { - print_message (M); - M = M->prev; + struct tgl_message **ML = talloc (sizeof (void *) * count); + M = P->last; + ML[0] = M; + count = 1; + while (count < limit && M->next) { + M = M->next; + ML[count ++] = M->next; } + + callback (callback_extra, 1, count, ML); + tfree (ML, sizeof (void *) * count); } -void tgl_do_get_history (tgl_peer_id_t id, int limit) { +void tgl_do_get_history (tgl_peer_id_t id, int limit, int offline_mode, void (*callback)(void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT || offline_mode) { - tgl_do_get_local_history (id, limit); - tgl_do_mark_read (id); + tgl_do_get_local_history (id, limit, callback, callback_extra); + tgl_do_mark_read (id, 0, 0); return; } clear_packet (); @@ -1193,13 +1177,12 @@ void tgl_do_get_history (tgl_peer_id_t id, int limit) { 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, callback, callback_extra); } /* }}} */ /* {{{ Get dialogs */ -int dialog_list_got; -int get_dialogs_on_answer (struct query *q UU) { +static int get_dialogs_on_answer (struct query *q UU) { unsigned x = fetch_int (); assert (x == CODE_messages_dialogs || x == CODE_messages_dialogs_slice); if (x == CODE_messages_dialogs_slice) { @@ -1208,20 +1191,16 @@ int get_dialogs_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); int n, i; n = fetch_int (); - static int dlist[2 * 100]; - static tgl_peer_id_t plist[100]; int dl_size = n; + + tgl_peer_id_t *PL = talloc0 (sizeof (tgl_peer_id_t) * n); + int *UC = talloc0 (4 * n); + int *LM = talloc0 (4 * n); for (i = 0; i < n; i++) { assert (fetch_int () == (int)CODE_dialog); - if (i < 100) { - plist[i] = tglf_fetch_peer_id (); - dlist[2 * i + 0] = fetch_int (); - dlist[2 * i + 1] = fetch_int (); - } else { - tglf_fetch_peer_id (); - fetch_int (); - fetch_int (); - } + PL[i] = tglf_fetch_peer_id (); + LM[i] = fetch_int (); + UC[i] = fetch_int (); assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0); } assert (fetch_int () == CODE_vector); @@ -1239,7 +1218,7 @@ int get_dialogs_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { tglf_fetch_alloc_user (); } - print_start (); + /*print_start (); push_color (COLOR_YELLOW); for (i = dl_size - 1; i >= 0; i--) { tgl_peer_t *UC; @@ -1261,23 +1240,31 @@ int get_dialogs_on_answer (struct query *q UU) { pop_color (); print_end (); - dialog_list_got = 1; + dialog_list_got = 1;*/ + + if (q->callback) { + ((void (*)(void *, int, int, tgl_peer_id_t *, int *, int *))q->callback) (q->callback_extra, 1, dl_size, PL, LM, UC); + } + tfree (PL, sizeof (tgl_peer_id_t) * dl_size); + tfree (UC, 4 * dl_size); + tfree (LM, 4 * dl_size); + return 0; } -struct query_methods get_dialogs_methods = { +static struct query_methods get_dialogs_methods = { .on_answer = get_dialogs_on_answer, .type = TYPE_TO_PARAM(messages_dialogs) }; -void tgl_do_get_dialog_list (void) { +void tgl_do_get_dialog_list (void (*callback)(void *callback_extra, int success, int size, tgl_peer_id_t peers[], int last_msg_id[], int unread_count[]), void *callback_extra) { clear_packet (); out_int (CODE_messages_get_dialogs); out_int (0); out_int (0); out_int (1000); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0, callback, callback_extra); } /* }}} */ @@ -1301,7 +1288,7 @@ struct send_file { unsigned char *key; }; -void out_peer_id (tgl_peer_id_t id) { +static void out_peer_id (tgl_peer_id_t id) { tgl_peer_t *U; switch (tgl_get_peer_type (id)) { case TGL_PEER_CHAT: @@ -1324,14 +1311,14 @@ void out_peer_id (tgl_peer_id_t id) { } } -void send_part (struct send_file *f); -int send_file_part_on_answer (struct query *q) { +static void send_part (struct send_file *f, void *callback, void *callback_extra); +static int send_file_part_on_answer (struct query *q) { assert (fetch_int () == (int)CODE_bool_true); - send_part (q->extra); + send_part (q->extra, q->callback, q->callback_extra); return 0; } -int send_file_on_answer (struct query *q UU) { +static int send_file_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_stated_message); struct tgl_message *M = tglf_fetch_alloc_message (); assert (fetch_int () == CODE_vector); @@ -1347,14 +1334,15 @@ int send_file_on_answer (struct query *q UU) { } fetch_pts (); fetch_seq (); - print_message (M); + + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback)(q->callback_extra, 1, M); + } + //print_message (M); return 0; } -int send_encr_file_on_answer (struct query *q UU) { - if (prefetch_int () != (int)CODE_messages_sent_encrypted_file) { - hexdump_in (); - } +static int send_encr_file_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_sent_encrypted_file); struct tgl_message *M = q->extra; M->date = fetch_int (); @@ -1365,30 +1353,34 @@ int send_encr_file_on_answer (struct query *q UU) { fetch_int (); M->media.encr_photo.dc_id = fetch_int (); assert (fetch_int () == M->media.encr_photo.key_fingerprint); - print_message (M); + //print_message (M); tglm_message_insert (M); + + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback)(q->callback_extra, 1, M); + } return 0; } -struct query_methods send_file_part_methods = { +static struct query_methods send_file_part_methods = { .on_answer = send_file_part_on_answer, .type = TYPE_TO_PARAM(bool) }; -struct query_methods send_file_methods = { +static struct query_methods send_file_methods = { .on_answer = send_file_on_answer, .type = TYPE_TO_PARAM(messages_stated_message) }; -struct query_methods send_encr_file_methods = { +static struct query_methods send_encr_file_methods = { .on_answer = send_encr_file_on_answer, .type = TYPE_TO_PARAM(messages_sent_encrypted_message) }; -void send_part (struct send_file *f) { +static void send_part (struct send_file *f, void *callback, void *callback_extra) { if (f->fd >= 0) { if (!f->part_num) { - cur_uploading_bytes += f->size; + tgl_state.cur_uploading_bytes += f->size; } clear_packet (); if (f->size < (16 << 20)) { @@ -1405,7 +1397,7 @@ void send_part (struct send_file *f) { int x = read (f->fd, buf, f->part_size); assert (x > 0); f->offset += x; - cur_uploaded_bytes += x; + tgl_state.cur_uploaded_bytes += x; if (f->encr) { if (x & 15) { @@ -1420,21 +1412,19 @@ void send_part (struct send_file *f) { memset (&aes_key, 0, sizeof (aes_key)); } out_cstring (buf, x); - if (verbosity >= 2) { - logprintf ("offset=%lld size=%lld\n", f->offset, f->size); - } + vlogprintf (E_DEBUG, "offset=%lld size=%lld\n", f->offset, f->size); if (f->offset == f->size) { close (f->fd); f->fd = -1; } else { assert (f->part_size == x); } - update_prompt (); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f); + //update_prompt (); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra); } else { - cur_uploaded_bytes -= f->size; - cur_uploading_bytes -= f->size; - update_prompt (); + tgl_state.cur_uploaded_bytes -= f->size; + tgl_state.cur_uploading_bytes -= f->size; + //update_prompt (); clear_packet (); assert (f->media_type == CODE_input_media_uploaded_photo || f->media_type == CODE_input_media_uploaded_video || f->media_type == CODE_input_media_uploaded_thumb_video || f->media_type == CODE_input_media_uploaded_audio || f->media_type == CODE_input_media_uploaded_document || f->media_type == CODE_input_media_uploaded_thumb_document); if (!f->encr) { @@ -1477,7 +1467,7 @@ void send_part (struct send_file *f) { } out_long (-lrand48 () * (1ll << 32) - lrand48 ()); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0, callback, callback_extra); } else { struct tgl_message *M = talloc0 (sizeof (*M)); @@ -1568,38 +1558,37 @@ void send_part (struct send_file *f) { M->id = r; M->date = time (0); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M); - + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra); } tfree_str (f->file_name); tfree (f, sizeof (*f)); } } -void send_file_thumb (struct send_file *f) { +/*void send_file_thumb (struct send_file *f, void *callback, void *callback_extra) { clear_packet (); f->thumb_id = lrand48 () * (1ll << 32) + lrand48 (); out_int (CODE_upload_save_file_part); out_long (f->thumb_id); out_int (0); out_cstring ((void *)thumb_file, thumb_file_size); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f); -} + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra); +}*/ -void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name) { +void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { int fd = open (file_name, O_RDONLY); if (fd < 0) { - rprintf ("No such file '%s'\n", file_name); - tfree_str (file_name); + vlogprintf (E_WARNING, "No such file '%s'\n", file_name); + callback (callback_extra, 0, 0); return; } struct stat buf; fstat (fd, &buf); long long size = buf.st_size; if (size <= 0) { - rprintf ("File has zero length\n"); - tfree_str (file_name); + vlogprintf (E_WARNING, "File has zero length\n"); close (fd); + callback (callback_extra, 0, 0); return; } struct send_file *f = talloc0 (sizeof (*f)); @@ -1615,16 +1604,16 @@ void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name) { if (f->part_size > (512 << 10)) { close (fd); - rprintf ("Too big file. Maximal supported size is %d.\n", (512 << 10) * 1000); + vlogprintf (E_WARNING, "Too big file. Maximal supported size is %d.\n", (512 << 10) * 1000); tfree (f, sizeof (*f)); - tfree_str (file_name); + callback (callback_extra, 0, 0); return; } f->id = lrand48 () * (1ll << 32) + lrand48 (); f->to_id = to_id; f->media_type = type; - f->file_name = file_name; + f->file_name = tstrdup (file_name); if (tgl_get_peer_type (f->to_id) == TGL_PEER_ENCR_CHAT) { f->encr = 1; f->iv = talloc (32); @@ -1643,12 +1632,12 @@ void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name) { } else { send_part (f); }*/ - send_part (f); + send_part (f, callback, callback_extra); } /* }}} */ /* {{{ Forward */ -int fwd_msg_on_answer (struct query *q UU) { +static int fwd_msg_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_stated_message); struct tgl_message *M = tglf_fetch_alloc_message (); assert (fetch_int () == CODE_vector); @@ -1664,18 +1653,22 @@ int fwd_msg_on_answer (struct query *q UU) { } fetch_pts (); fetch_seq (); - print_message (M); + //print_message (M); + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); + } return 0; } -struct query_methods fwd_msg_methods = { +static struct query_methods fwd_msg_methods = { .on_answer = fwd_msg_on_answer, .type = TYPE_TO_PARAM(messages_stated_message) }; -void tgl_do_forward_message (tgl_peer_id_t id, int n) { +void tgl_do_forward_message (tgl_peer_id_t id, int n, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { - rprintf ("Can not forward messages from secret chat\n"); + vlogprintf (E_WARNING, "Can not forward messages from secret chat\n"); + callback (callback_extra, 0, 0); return; } clear_packet (); @@ -1683,12 +1676,12 @@ void tgl_do_forward_message (tgl_peer_id_t id, int n) { out_peer_id (id); out_int (n); out_long (lrand48 () * (1ll << 32) + lrand48 ()); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Rename chat */ -int rename_chat_on_answer (struct query *q UU) { +static int rename_chat_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_stated_message); struct tgl_message *M = tglf_fetch_alloc_message (); assert (fetch_int () == CODE_vector); @@ -1704,27 +1697,30 @@ int rename_chat_on_answer (struct query *q UU) { } fetch_pts (); fetch_seq (); - print_message (M); + //print_message (M); + if (q->callback) { + ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); + } return 0; } -struct query_methods rename_chat_methods = { +static struct query_methods rename_chat_methods = { .on_answer = rename_chat_on_answer, .type = TYPE_TO_PARAM(messages_stated_message) }; -void tgl_do_rename_chat (tgl_peer_id_t id, char *name UU) { +void tgl_do_rename_chat (tgl_peer_id_t id, char *name UU, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { clear_packet (); out_int (CODE_messages_edit_chat_title); assert (tgl_get_peer_type (id) == TGL_PEER_CHAT); out_int (tgl_get_peer_id (id)); out_string (name); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Chat info */ -void print_chat_info (struct tgl_chat *C) { +/*void print_chat_info (struct tgl_chat *C) { tgl_peer_t *U = (void *)C; print_start (); push_color (COLOR_YELLOW); @@ -1746,26 +1742,31 @@ void print_chat_info (struct tgl_chat *C) { } pop_color (); print_end (); -} +}*/ -int chat_info_on_answer (struct query *q UU) { +static int chat_info_on_answer (struct query *q UU) { struct tgl_chat *C = tglf_fetch_alloc_chat_full (); - print_chat_info (C); + //print_chat_info (C); + if (q->callback) { + ((void (*)(void *, int, struct tgl_chat *))q->callback) (q->callback_extra, 0, C); + } return 0; } -struct query_methods chat_info_methods = { +static struct query_methods chat_info_methods = { .on_answer = chat_info_on_answer, .type = TYPE_TO_PARAM(messages_chat_full) }; -void tgl_do_get_chat_info (tgl_peer_id_t id) { +void tgl_do_get_chat_info (tgl_peer_id_t id, int offline_mode, void (*callback)(void *callback_extra, int success, struct tgl_chat *C), void *callback_extra) { if (offline_mode) { tgl_peer_t *C = tgl_peer_get (id); if (!C) { - rprintf ("No such chat\n"); + vlogprintf (E_WARNING, "No such chat\n"); + callback (callback_extra, 0, 0); } else { - print_chat_info (&C->chat); + //print_chat_info (&C->chat); + callback (callback_extra, 1, &C->chat); } return; } @@ -1773,13 +1774,13 @@ void tgl_do_get_chat_info (tgl_peer_id_t id) { out_int (CODE_messages_get_full_chat); assert (tgl_get_peer_type (id) == TGL_PEER_CHAT); out_int (tgl_get_peer_id (id)); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ User info */ -void print_user_info (struct tgl_user *U) { +/*void print_user_info (struct tgl_user *U) { tgl_peer_t *C = (void *)U; print_start (); push_color (COLOR_YELLOW); @@ -1797,26 +1798,29 @@ void print_user_info (struct tgl_user *U) { } pop_color (); print_end (); -} +}*/ -int user_info_on_answer (struct query *q UU) { +static int user_info_on_answer (struct query *q UU) { struct tgl_user *U = tglf_fetch_alloc_user_full (); - print_user_info (U); + if (q->callback) { + ((void (*)(void *, int, struct tgl_user *))q->callback) (q->callback_extra, 0, U); + } return 0; } -struct query_methods user_info_methods = { +static struct query_methods user_info_methods = { .on_answer = user_info_on_answer, .type = TYPE_TO_PARAM(user_full) }; -void tgl_do_get_user_info (tgl_peer_id_t id) { +void tgl_do_get_user_info (tgl_peer_id_t id, int offline_mode, void (*callback)(void *callback_extra, int success, struct tgl_user *U), void *callback_extra) { if (offline_mode) { tgl_peer_t *C = tgl_peer_get (id); if (!C) { - rprintf ("No such user\n"); + vlogprintf (E_WARNING, "No such user\n"); + callback (callback_extra, 0, 0); } else { - print_user_info (&C->user); + callback (callback_extra, 1, &C->user); } return; } @@ -1832,12 +1836,12 @@ void tgl_do_get_user_info (tgl_peer_id_t id) { out_int (CODE_input_user_contact); out_int (tgl_get_peer_id (id)); } - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Get user info silently */ -int user_list_info_silent_on_answer (struct query *q UU) { +/*int user_list_info_silent_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); int n = fetch_int (); int i; @@ -1864,7 +1868,7 @@ void tgl_do_get_user_list_info_silent (int num, int *list) { //out_long (0); } send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0); -} +}*/ /* }}} */ /* {{{ Load photo/video */ @@ -1886,12 +1890,12 @@ struct download { }; -void end_load (struct download *D) { - cur_downloading_bytes -= D->size; - cur_downloaded_bytes -= D->size; - update_prompt (); +static void end_load (struct download *D, void *callback, void *callback_extra) { + tgl_state.cur_downloading_bytes -= D->size; + tgl_state.cur_downloaded_bytes -= D->size; + //update_prompt (); close (D->fd); - if (D->next == 1) { + /*if (D->next == 1) { logprintf ("Done: %s\n", D->name); } else if (D->next == 2) { static char buf[PATH_MAX]; @@ -1904,7 +1908,12 @@ void end_load (struct download *D) { logprintf ("Image is at %s\n", D->name); } } + }*/ + + if (callback) { + ((void (*)(void *, int, char *))callback) (callback_extra, 1, D->name); } + if (D->iv) { tfree_secure (D->iv, 32); } @@ -1912,8 +1921,8 @@ void end_load (struct download *D) { tfree (D, sizeof (*D)); } -void load_next_part (struct download *D); -int download_on_answer (struct query *q) { +static void load_next_part (struct download *D, void *callback, void *callback_extra); +static int download_on_answer (struct query *q) { assert (fetch_int () == (int)CODE_upload_file); unsigned x = fetch_int (); assert (x); @@ -1924,8 +1933,8 @@ int download_on_answer (struct query *q) { fetch_int (); // mtime int len = prefetch_strlen (); assert (len >= 0); - cur_downloaded_bytes += len; - update_prompt (); + tgl_state.cur_downloaded_bytes += len; + //update_prompt (); if (D->iv) { unsigned char *ptr = (void *)fetch_str (len); assert (!(len & 15)); @@ -1942,20 +1951,20 @@ int download_on_answer (struct query *q) { } D->offset += len; if (D->offset < D->size) { - load_next_part (D); + load_next_part (D, q->callback, q->callback_extra); return 0; } else { - end_load (D); + end_load (D, q->callback, q->callback_extra); return 0; } } -struct query_methods download_methods = { +static struct query_methods download_methods = { .on_answer = download_on_answer, .type = TYPE_TO_PARAM(upload_file) }; -void load_next_part (struct download *D) { +static void load_next_part (struct download *D, void *callback, void *callback_extra) { if (!D->offset) { static char buf[PATH_MAX]; int l; @@ -1965,7 +1974,7 @@ void load_next_part (struct download *D) { l = tsnprintf (buf, sizeof (buf), "%s/download_%lld", get_downloads_directory (), D->id); } if (l >= (int) sizeof (buf)) { - logprintf ("Download filename is too long"); + vlogprintf (E_ERROR, "Download filename is too long"); exit (1); } D->name = tstrdup (buf); @@ -1973,17 +1982,17 @@ void load_next_part (struct download *D) { if (stat (buf, &st) >= 0) { D->offset = st.st_size; if (D->offset >= D->size) { - cur_downloading_bytes += D->size; - cur_downloaded_bytes += D->offset; - rprintf ("Already downloaded\n"); - end_load (D); + tgl_state.cur_downloading_bytes += D->size; + tgl_state.cur_downloaded_bytes += D->offset; + vlogprintf (E_NOTICE, "Already downloaded\n"); + end_load (D, callback, callback_extra); return; } } - cur_downloading_bytes += D->size; - cur_downloaded_bytes += D->offset; - update_prompt (); + tgl_state.cur_downloading_bytes += D->size; + tgl_state.cur_downloaded_bytes += D->offset; + //update_prompt (); } clear_packet (); out_int (CODE_upload_get_file); @@ -2003,18 +2012,18 @@ void load_next_part (struct download *D) { } out_int (D->offset); out_int (1 << 14); - send_query (DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D); + send_query (DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D, callback, callback_extra); //send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D); } -void tgl_do_load_photo_size (struct tgl_photo_size *P, int next) { +void tgl_do_load_photo_size (struct tgl_photo_size *P, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { if (!P->loc.dc) { - rprintf ("Bad video thumb\n"); + vlogprintf (E_WARNING, "Bad video thumb\n"); + callback (callback_extra, 0, 0); return; } assert (P); - assert (next); struct download *D = talloc0 (sizeof (*D)); D->id = 0; D->offset = 0; @@ -2023,14 +2032,17 @@ void tgl_do_load_photo_size (struct tgl_photo_size *P, int next) { D->dc = P->loc.dc; D->local_id = P->loc.local_id; D->secret = P->loc.secret; - D->next = next; D->name = 0; D->fd = -1; - load_next_part (D); + load_next_part (D, callback, callback_extra); } -void tgl_do_load_photo (struct tgl_photo *photo, int next) { - if (!photo->sizes_num) { return; } +void tgl_do_load_photo (struct tgl_photo *photo, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { + if (!photo->sizes_num) { + vlogprintf (E_WARNING, "No sizes\n"); + callback (callback_extra, 0, 0); + return; + } int max = -1; int maxi = 0; int i; @@ -2040,81 +2052,73 @@ void tgl_do_load_photo (struct tgl_photo *photo, int next) { maxi = i; } } - tgl_do_load_photo_size (&photo->sizes[maxi], next); + tgl_do_load_photo_size (&photo->sizes[maxi], callback, callback_extra); } -void tgl_do_load_video_thumb (struct tgl_video *video, int next) { - tgl_do_load_photo_size (&video->thumb, next); +void tgl_do_load_video_thumb (struct tgl_video *video, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { + tgl_do_load_photo_size (&video->thumb, callback, callback_extra); } -void tgl_do_load_document_thumb (struct tgl_document *video, int next) { - tgl_do_load_photo_size (&video->thumb, next); +void tgl_do_load_document_thumb (struct tgl_document *video, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { + tgl_do_load_photo_size (&video->thumb, callback, callback_extra); } -void tgl_do_load_video (struct tgl_video *V, int next) { +void tgl_do_load_video (struct tgl_video *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { assert (V); - assert (next); struct download *D = talloc0 (sizeof (*D)); D->offset = 0; D->size = V->size; D->id = V->id; D->access_hash = V->access_hash; D->dc = V->dc_id; - D->next = next; D->name = 0; D->fd = -1; D->type = CODE_input_video_file_location; - load_next_part (D); + load_next_part (D, callback, callback_extra); } -void tgl_do_load_audio (struct tgl_video *V, int next) { +void tgl_do_load_audio (struct tgl_video *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { assert (V); - assert (next); struct download *D = talloc0 (sizeof (*D)); D->offset = 0; D->size = V->size; D->id = V->id; D->access_hash = V->access_hash; D->dc = V->dc_id; - D->next = next; D->name = 0; D->fd = -1; D->type = CODE_input_audio_file_location; - load_next_part (D); + load_next_part (D, callback, callback_extra); } -void tgl_do_load_document (struct tgl_document *V, int next) { +void tgl_do_load_document (struct tgl_document *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { assert (V); - assert (next); struct download *D = talloc0 (sizeof (*D)); D->offset = 0; D->size = V->size; D->id = V->id; D->access_hash = V->access_hash; D->dc = V->dc_id; - D->next = next; D->name = 0; D->fd = -1; D->type = CODE_input_document_file_location; - load_next_part (D); + load_next_part (D, callback, callback_extra); } -void tgl_do_load_encr_video (struct tgl_encr_video *V, int next) { +void tgl_do_load_encr_video (struct tgl_encr_video *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { assert (V); - assert (next); struct download *D = talloc0 (sizeof (*D)); D->offset = 0; D->size = V->size; D->id = V->id; D->access_hash = V->access_hash; D->dc = V->dc_id; - D->next = next; D->name = 0; D->fd = -1; D->key = V->key; D->iv = talloc (32); memcpy (D->iv, V->iv, 32); - load_next_part (D); + load_next_part (D, callback, callback_extra); unsigned char md5[16]; unsigned char str[64]; @@ -2126,78 +2130,64 @@ void tgl_do_load_encr_video (struct tgl_encr_video *V, int next) { /* }}} */ /* {{{ Export auth */ -char *export_auth_str; -int export_auth_str_len; -int is_export_auth_str (void) { - return export_auth_str != 0; -} -int isn_export_auth_str (void) { - return export_auth_str == 0; -} -int export_auth_on_answer (struct query *q UU) { - assert (fetch_int () == (int)CODE_auth_exported_authorization); - bl_do_set_our_id (fetch_int ()); - int l = prefetch_strlen (); - char *s = talloc (l); - memcpy (s, fetch_str (l), l); - export_auth_str_len = l; - export_auth_str = s; - return 0; -} - -struct query_methods export_auth_methods = { - .on_answer = export_auth_on_answer, - .on_error = fail_on_error, - .type = TYPE_TO_PARAM(auth_exported_authorization) -}; - -void tgl_do_export_auth (int num) { - export_auth_str = 0; - clear_packet (); - out_int (CODE_auth_export_authorization); - out_int (num); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, 0); - net_loop (0, is_export_auth_str); -} -/* }}} */ - -/* {{{ Import auth */ -int import_auth_on_answer (struct query *q UU) { +static int import_auth_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_auth_authorization); fetch_int (); // expires tglf_fetch_alloc_user (); - tfree (export_auth_str, export_auth_str_len); - export_auth_str = 0; + + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } return 0; } -struct query_methods import_auth_methods = { +static struct query_methods import_auth_methods = { .on_answer = import_auth_on_answer, .on_error = fail_on_error, .type = TYPE_TO_PARAM(auth_authorization) }; -void tgl_do_import_auth (int num) { +static int export_auth_on_answer (struct query *q UU) { + assert (fetch_int () == (int)CODE_auth_exported_authorization); + bl_do_set_our_id (fetch_int ()); + int l = prefetch_strlen (); + char *s = talloc (l); + memcpy (s, fetch_str (l), l); + clear_packet (); tgl_do_insert_header (); out_int (CODE_auth_import_authorization); out_int (tgl_state.our_id); - out_cstring (export_auth_str, export_auth_str_len); - send_query (DC_list[num], packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0); - net_loop (0, isn_export_auth_str); + out_cstring (s, l); + send_query (q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0, q->callback, q->callback_extra); + tfree (s, l); + return 0; +} + +static struct query_methods export_auth_methods = { + .on_answer = export_auth_on_answer, + .on_error = fail_on_error, + .type = TYPE_TO_PARAM(auth_exported_authorization) +}; + +void tgl_do_export_auth (int num, void (*callback) (void *callback_extra, int success), void *callback_extra) { + clear_packet (); + out_int (CODE_auth_export_authorization); + out_int (num); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, DC_list[num], callback, callback_extra); } /* }}} */ /* {{{ Add contact */ -int add_contact_on_answer (struct query *q UU) { +static int add_contact_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_contacts_imported_contacts); assert (fetch_int () == CODE_vector); int n = fetch_int (); if (n > 0) { - logprintf ("Added successfully"); + vlogprintf (E_DEBUG, "Added successfully"); } else { - logprintf ("Not added"); + vlogprintf (E_DEBUG, "Not added"); } int i; for (i = 0; i < n ; i++) { @@ -2209,11 +2199,16 @@ int add_contact_on_answer (struct query *q UU) { n = fetch_int (); for (i = 0; i < n; i++) { long long id = fetch_long (); - logprintf ("contact #%lld not added. Please retry\n", id); + vlogprintf (E_NOTICE, "contact #%lld not added. Please retry\n", id); } assert (fetch_int () == CODE_vector); n = fetch_int (); - for (i = 0; i < n ; i++) { + + struct tgl_user **UL = talloc (n * sizeof (void *)); + for (i = 0; i < n; i++) { + UL[i] = tglf_fetch_alloc_user (); + } + /*for (i = 0; i < n ; i++) { struct tgl_user *U = tglf_fetch_alloc_user (); print_start (); push_color (COLOR_YELLOW); @@ -2242,16 +2237,21 @@ int add_contact_on_answer (struct query *q UU) { pop_color (); print_end (); + }*/ + + if (q->callback) { + ((void (*)(void *, int, int, struct tgl_user **))q->callback) (q->callback_extra, 1, n, UL); } + tfree (UL, n * sizeof (void *)); return 0; } -struct query_methods add_contact_methods = { +static struct query_methods add_contact_methods = { .on_answer = add_contact_on_answer, .type = TYPE_TO_PARAM(contacts_imported_contacts) }; -void tgl_do_add_contact (const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force) { +void tgl_do_add_contact (const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force, void (*callback)(void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra) { clear_packet (); out_int (CODE_contacts_import_contacts); out_int (CODE_vector); @@ -2262,23 +2262,26 @@ void tgl_do_add_contact (const char *phone, int phone_len, const char *first_nam out_cstring (first_name, first_name_len); out_cstring (last_name, last_name_len); out_int (force ? CODE_bool_true : CODE_bool_false); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Msg search */ -int msg_search_on_answer (struct query *q UU) { +static int msg_search_on_answer (struct query *q UU) { return get_history_on_answer (q); } -struct query_methods msg_search_methods = { +static struct query_methods msg_search_methods = { .on_answer = msg_search_on_answer, .type = TYPE_TO_PARAM(messages_messages) }; -void tgl_do_msg_search (tgl_peer_id_t id, int from, int to, int limit, const char *s) { +void tgl_do_msg_search (tgl_peer_id_t id, int from, int to, int limit, const char *s, void (*callback)(void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) { if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) { - rprintf ("Can not search in secure chat\n"); + vlogprintf (E_WARNING, "Can not search in secure chat\n"); + if (callback) { + callback (callback_extra, 0, 0, 0); + } return; } clear_packet (); @@ -2295,12 +2298,12 @@ void tgl_do_msg_search (tgl_peer_id_t id, int from, int to, int limit, const cha out_int (0); // offset out_int (0); // max_id out_int (limit); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Contacts search */ -int contacts_search_on_answer (struct query *q UU) { +static int contacts_search_on_answer (struct query *q UU) { assert (fetch_int () == CODE_contacts_found); assert (fetch_int () == CODE_vector); int n = fetch_int (); @@ -2311,7 +2314,12 @@ int contacts_search_on_answer (struct query *q UU) { } assert (fetch_int () == CODE_vector); n = fetch_int (); - print_start (); + + struct tgl_user **UL = talloc (sizeof (void *) * n); + for (i = 0; i < n; i++) { + UL[i] = tglf_fetch_alloc_user (); + } + /*print_start (); push_color (COLOR_YELLOW); for (i = 0; i < n; i++) { struct tgl_user *U = tglf_fetch_alloc_user (); @@ -2322,29 +2330,33 @@ int contacts_search_on_answer (struct query *q UU) { printf (". Phone %s\n", U->phone); } pop_color (); - print_end (); + print_end ();*/ + if (q->callback) { + ((void (*)(void *, int, int, struct tgl_user **))q->callback) (q->callback_extra, 1, n, UL); + } + tfree (UL, sizeof (void *) * n); return 0; } -struct query_methods contacts_search_methods = { +static struct query_methods contacts_search_methods = { .on_answer = contacts_search_on_answer, .type = TYPE_TO_PARAM(contacts_found) }; -void tgl_do_contacts_search (int limit, const char *s) { +void tgl_do_contacts_search (int limit, const char *s, void (*callback) (void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra) { clear_packet (); out_int (CODE_contacts_search); out_string (s); out_int (limit); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &contacts_search_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &contacts_search_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Encr accept */ -int send_encr_accept_on_answer (struct query *q UU) { +static int send_encr_accept_on_answer (struct query *q UU) { struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (); - if (E->state == sc_ok) { + /*if (E->state == sc_ok) { print_start (); push_color (COLOR_YELLOW); printf ("Encrypted connection with "); @@ -2360,13 +2372,17 @@ int send_encr_accept_on_answer (struct query *q UU) { printf (" failed\n"); pop_color (); print_end (); + }*/ + + if (q->callback) { + ((void (*)(void *, int, struct tgl_secret_chat *))q->callback) (q->callback_extra, E->state == sc_ok, E); } return 0; } -int send_encr_request_on_answer (struct query *q UU) { +static int send_encr_request_on_answer (struct query *q UU) { struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (); - if (E->state == sc_deleted) { + /*if (E->state == sc_deleted) { print_start (); push_color (COLOR_YELLOW); printf ("Encrypted connection with "); @@ -2384,26 +2400,30 @@ int send_encr_request_on_answer (struct query *q UU) { print_end (); assert (E->state == sc_waiting); + }*/ + + if (q->callback) { + ((void (*)(void *, int, struct tgl_secret_chat *))q->callback) (q->callback_extra, E->state != sc_deleted, E); } return 0; } -struct query_methods send_encr_accept_methods = { +static struct query_methods send_encr_accept_methods = { .on_answer = send_encr_accept_on_answer, .type = TYPE_TO_PARAM(encrypted_chat) }; -struct query_methods send_encr_request_methods = { +static struct query_methods send_encr_request_methods = { .on_answer = send_encr_request_on_answer, .type = TYPE_TO_PARAM(encrypted_chat) }; -int encr_root; -unsigned char *encr_prime; -int encr_param_version; -BN_CTX *ctx; +//int encr_root; +//unsigned char *encr_prime; +//int encr_param_version; +static BN_CTX *ctx; -void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *random) { +void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *random, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { int i; int ok = 0; for (i = 0; i < 64; i++) { @@ -2412,7 +2432,10 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran break; } } - if (ok) { return; } // Already generated key for this chat + if (ok) { + callback (callback_extra, 1, E); + return; + } // Already generated key for this chat unsigned char random_here[256]; secure_random (random_here, 256); for (i = 0; i < 256; i++) { @@ -2422,12 +2445,12 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran ensure_ptr (b); BIGNUM *g_a = BN_bin2bn (E->g_key, 256, 0); ensure_ptr (g_a); - assert (check_g (encr_prime, g_a) >= 0); + assert (check_g (tgl_state.encr_prime, g_a) >= 0); if (!ctx) { ctx = BN_CTX_new (); ensure_ptr (ctx); } - BIGNUM *p = BN_bin2bn (encr_prime, 256, 0); + BIGNUM *p = BN_bin2bn (tgl_state.encr_prime, 256, 0); ensure_ptr (p); BIGNUM *r = BN_new (); ensure_ptr (r); @@ -2449,7 +2472,7 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran out_int (tgl_get_peer_id (E->id)); out_long (E->access_hash); - ensure (BN_set_word (g_a, encr_root)); + ensure (BN_set_word (g_a, tgl_state.encr_root)); ensure (BN_mod_exp (r, g_a, b, p, ctx)); static unsigned char buf[256]; memset (buf, 0, sizeof (buf)); @@ -2462,19 +2485,19 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran BN_clear_free (p); BN_clear_free (r); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E, callback, callback_extra); } void tgl_do_create_keys_end (struct tgl_secret_chat *U) { - assert (encr_prime); + assert (tgl_state.encr_prime); BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0); ensure_ptr (g_b); - assert (check_g (encr_prime, g_b) >= 0); + assert (check_g (tgl_state.encr_prime, g_b) >= 0); if (!ctx) { ctx = BN_CTX_new (); ensure_ptr (ctx); } - BIGNUM *p = BN_bin2bn (encr_prime, 256, 0); + BIGNUM *p = BN_bin2bn (tgl_state.encr_prime, 256, 0); ensure_ptr (p); BIGNUM *r = BN_new (); ensure_ptr (r); @@ -2496,13 +2519,7 @@ void tgl_do_create_keys_end (struct tgl_secret_chat *U) { sha1 ((void *)U->key, 256, sha_buffer); long long k = *(long long *)(sha_buffer + 12); 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)); - hexdump ((void *)sha_buffer, (void *)(sha_buffer + 20)); - logprintf ("!!Key fingerprint mismatch (my 0x%llx 0x%llx)\n", (unsigned long long)k, (unsigned long long)U->key_fingerprint); + vlogprintf (E_WARNING, "Key fingerprint mismatch (my 0x%llx 0x%llx)\n", (unsigned long long)k, (unsigned long long)U->key_fingerprint); U->state = sc_deleted; } @@ -2514,7 +2531,7 @@ void tgl_do_create_keys_end (struct tgl_secret_chat *U) { BN_clear_free (a); } -void tgl_do_send_create_encr_chat (void *x, unsigned char *random) { +void tgl_do_send_create_encr_chat (void *x, unsigned char *random, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { int user_id = (long)x; int i; unsigned char random_here[256]; @@ -2528,13 +2545,13 @@ void tgl_do_send_create_encr_chat (void *x, unsigned char *random) { } BIGNUM *a = BN_bin2bn (random, 256, 0); ensure_ptr (a); - BIGNUM *p = BN_bin2bn (encr_prime, 256, 0); + BIGNUM *p = BN_bin2bn (tgl_state.encr_prime, 256, 0); ensure_ptr (p); BIGNUM *g = BN_new (); ensure_ptr (g); - ensure (BN_set_word (g, encr_root)); + ensure (BN_set_word (g, tgl_state.encr_root)); BIGNUM *r = BN_new (); ensure_ptr (r); @@ -2578,10 +2595,10 @@ void tgl_do_send_create_encr_chat (void *x, unsigned char *random) { BN_clear_free (p); BN_clear_free (r); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra); } -int get_dh_config_on_answer (struct query *q UU) { +static int get_dh_config_on_answer (struct query *q UU) { unsigned x = fetch_int (); assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified); if (x == CODE_messages_dh_config) { @@ -2603,7 +2620,7 @@ int get_dh_config_on_answer (struct query *q UU) { memcpy (random, fetch_str (256), 256); if (q->extra) { void **x = q->extra; - ((void (*)(void *, void *))(*x))(x[1], random); + ((void (*)(void *, void *, void *, void *))(*x))(x[1], random, q->callback, q->callback_extra); tfree (x, 2 * sizeof (void *)); tfree_secure (random, 256); } else { @@ -2612,81 +2629,84 @@ int get_dh_config_on_answer (struct query *q UU) { return 0; } -struct query_methods get_dh_config_methods = { +static struct query_methods get_dh_config_methods = { .on_answer = get_dh_config_on_answer, .type = TYPE_TO_PARAM(messages_dh_config) }; -void tgl_do_accept_encr_chat_request (struct tgl_secret_chat *E) { +void tgl_do_accept_encr_chat_request (struct tgl_secret_chat *E, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { assert (E->state == sc_request); clear_packet (); out_int (CODE_messages_get_dh_config); - out_int (encr_param_version); + out_int (tgl_state.encr_param_version); out_int (256); void **x = talloc (2 * sizeof (void *)); x[0] = tgl_do_send_accept_encr_chat; x[1] = E; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra); } -void tgl_do_create_encr_chat_request (int user_id) { +void tgl_do_create_encr_chat_request (int user_id, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { clear_packet (); out_int (CODE_messages_get_dh_config); - out_int (encr_param_version); + out_int (tgl_state.encr_param_version); out_int (256); void **x = talloc (2 * sizeof (void *)); x[0] = tgl_do_send_create_encr_chat; x[1] = (void *)(long)(user_id); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra); } /* }}} */ /* {{{ Get difference */ -int unread_messages; -int difference_got; -int seq, pts, qts, last_date; -int get_state_on_answer (struct query *q UU) { +//int unread_messages; +//int difference_got; +//int seq, pts, qts, last_date; +static int get_state_on_answer (struct query *q UU) { assert (fetch_int () == (int)CODE_updates_state); bl_do_set_pts (fetch_int ()); bl_do_set_qts (fetch_int ()); bl_do_set_date (fetch_int ()); bl_do_set_seq (fetch_int ()); - unread_messages = fetch_int (); - write_state_file (); - difference_got = 1; + //unread_messages = fetch_int (); + fetch_int (); + //write_state_file (); + //difference_got = 1; + + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } return 0; } -int get_difference_active; -int get_difference_on_answer (struct query *q UU) { - get_difference_active = 0; +//int get_difference_active; +static int get_difference_on_answer (struct query *q UU) { + //get_difference_active = 0; unsigned x = fetch_int (); if (x == CODE_updates_difference_empty) { bl_do_set_date (fetch_int ()); bl_do_set_seq (fetch_int ()); - difference_got = 1; + //difference_got = 1; + + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } } else if (x == CODE_updates_difference || x == CODE_updates_difference_slice) { int n, i; assert (fetch_int () == CODE_vector); n = fetch_int (); - static struct tgl_message *ML[10000]; + struct tgl_message **ML = talloc (n * sizeof (void *)); int ml_pos = 0; for (i = 0; i < n; i++) { - if (ml_pos < 10000) { - ML[ml_pos ++] = tglf_fetch_alloc_message (); - } else { - tglf_fetch_alloc_message (); - } + ML[ml_pos ++] = tglf_fetch_alloc_message (); } assert (fetch_int () == CODE_vector); n = fetch_int (); + struct tgl_message **EL = talloc (n * sizeof (void *)); + int el_pos = 0; for (i = 0; i < n; i++) { - if (ml_pos < 10000) { - ML[ml_pos ++] = tglf_fetch_alloc_encrypted_message (); - } else { - tglf_fetch_alloc_encrypted_message (); - } + EL[el_pos ++] = tglf_fetch_alloc_encrypted_message (); } assert (fetch_int () == CODE_vector); n = fetch_int (); @@ -2708,15 +2728,28 @@ int get_difference_on_answer (struct query *q UU) { bl_do_set_qts (fetch_int ()); bl_do_set_date (fetch_int ()); bl_do_set_seq (fetch_int ()); - unread_messages = fetch_int (); - write_state_file (); - for (i = 0; i < ml_pos; i++) { + //unread_messages = fetch_int (); + fetch_int (); + //write_state_file (); + /*for (i = 0; i < ml_pos; i++) { print_message (ML[i]); + }*/ + for (i = 0; i < ml_pos; i++) { + tgl_state.callback.new_msg (ML[i]); } + for (i = 0; i < el_pos; i++) { + tgl_state.callback.new_msg (EL[i]); + } + tfree (ML, ml_pos * sizeof (void *)); + tfree (EL, el_pos * sizeof (void *)); + if (x == CODE_updates_difference_slice) { - tgl_do_get_difference (); + tgl_do_get_difference (0, q->callback, q->callback_extra); } else { - difference_got = 1; + //difference_got = 1; + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } } } else { assert (0); @@ -2724,39 +2757,39 @@ int get_difference_on_answer (struct query *q UU) { return 0; } -struct query_methods get_state_methods = { +static struct query_methods get_state_methods = { .on_answer = get_state_on_answer, .type = TYPE_TO_PARAM(updates_state) }; -struct query_methods get_difference_methods = { +static struct query_methods get_difference_methods = { .on_answer = get_difference_on_answer, .type = TYPE_TO_PARAM(updates_difference) }; -void tgl_do_get_difference (void) { - get_difference_active = 1; - difference_got = 0; +void tgl_do_get_difference (int sync_from_start, void (*callback)(void *callback_extra, int success), void *callback_extra) { + //get_difference_active = 1; + //difference_got = 0; clear_packet (); tgl_do_insert_header (); - if (seq > 0 || sync_from_start) { - if (pts == 0) { pts = 1; } - if (qts == 0) { qts = 1; } - if (last_date == 0) { last_date = 1; } + if (tgl_state.seq > 0 || sync_from_start) { + if (tgl_state.pts == 0) { tgl_state.pts = 1; } + if (tgl_state.qts == 0) { tgl_state.qts = 1; } + if (tgl_state.date == 0) { tgl_state.date = 1; } out_int (CODE_updates_get_difference); - out_int (pts); - out_int (last_date); - out_int (qts); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0); + out_int (tgl_state.pts); + out_int (tgl_state.date); + out_int (tgl_state.qts); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0, callback, callback_extra); } else { out_int (CODE_updates_get_state); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0, callback, callback_extra); } } /* }}} */ /* {{{ Visualize key */ -char *colors[4] = {COLOR_GREY, COLOR_CYAN, COLOR_BLUE, COLOR_GREEN}; +/*char *colors[4] = {COLOR_GREY, COLOR_CYAN, COLOR_BLUE, COLOR_GREEN}; void tgl_do_visualize_key (tgl_peer_id_t id) { assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT); @@ -2784,11 +2817,24 @@ void tgl_do_visualize_key (tgl_peer_id_t id) { if (i & 1) { printf ("\n"); } } print_end (); +}*/ + +void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]) { + assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT); + tgl_peer_t *P = tgl_peer_get (id); + assert (P); + if (P->encr_chat.state != sc_ok) { + vlogprintf (E_WARNING, "Chat is not initialized yet\n"); + return; + } + unsigned char res[20]; + SHA1 ((void *)P->encr_chat.key, 256, res); + memcpy (buf, res, 16); } /* }}} */ /* {{{ Get suggested */ -int get_suggested_on_answer (struct query *q UU) { +/*int get_suggested_on_answer (struct query *q UU) { assert (fetch_int () == CODE_contacts_suggested); assert (fetch_int () == CODE_vector); int n = fetch_int (); @@ -2827,17 +2873,17 @@ void tgl_do_get_suggested (void) { out_int (CODE_contacts_get_suggested); out_int (100); send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_suggested_methods, 0); -} +}*/ /* }}} */ /* {{{ Add user to chat */ -struct query_methods add_user_to_chat_methods = { +static struct query_methods add_user_to_chat_methods = { .on_answer = fwd_msg_on_answer, .type = TYPE_TO_PARAM(message_action) }; -void tgl_do_add_user_to_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit) { +void tgl_do_add_user_to_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { clear_packet (); out_int (CODE_messages_add_chat_user); out_int (tgl_get_peer_id (chat_id)); @@ -2853,10 +2899,10 @@ void tgl_do_add_user_to_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit out_int (tgl_get_peer_id (id)); } out_int (limit); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra); } -void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id) { +void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { clear_packet (); out_int (CODE_messages_delete_chat_user); out_int (tgl_get_peer_id (chat_id)); @@ -2871,36 +2917,36 @@ void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id) { out_int (CODE_input_user_contact); out_int (tgl_get_peer_id (id)); } - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Create secret chat */ -char *create_print_name (tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); +//char *create_print_name (tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); -void tgl_do_create_secret_chat (tgl_peer_id_t id) { +void tgl_do_create_secret_chat (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { assert (tgl_get_peer_type (id) == TGL_PEER_USER); tgl_peer_t *U = tgl_peer_get (id); if (!U) { - rprintf ("Can not create chat with unknown user\n"); + vlogprintf (E_WARNING, "Can not create chat with unknown user\n"); return; } - tgl_do_create_encr_chat_request (tgl_get_peer_id (id)); + tgl_do_create_encr_chat_request (tgl_get_peer_id (id), callback, callback_extra); } /* }}} */ /* {{{ Create group chat */ -struct query_methods create_group_chat_methods = { +static struct query_methods create_group_chat_methods = { .on_answer = fwd_msg_on_answer, .type = TYPE_TO_PARAM(message_action) }; -void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic) { +void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { assert (tgl_get_peer_type (id) == TGL_PEER_USER); tgl_peer_t *U = tgl_peer_get (id); if (!U) { - rprintf ("Can not create chat with unknown user\n"); + vlogprintf (E_WARNING, "Can not create chat with unknown user\n"); return; } clear_packet (); @@ -2916,62 +2962,74 @@ void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic) { out_int (tgl_get_peer_id (id)); } out_string (chat_topic); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Delete msg */ -int delete_msg_on_answer (struct query *q UU) { +static int delete_msg_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); int n = fetch_int (); fetch_skip (n); - logprintf ("Deleted %d messages\n", n); + + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } return 0; } -struct query_methods delete_msg_methods = { +static struct query_methods delete_msg_methods = { .on_answer = delete_msg_on_answer, .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM (bare_int)) }; -void tgl_do_delete_msg (long long id) { +void tgl_do_delete_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_delete_messages); out_int (CODE_vector); out_int (1); out_int (id); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0, callback, callback_extra); } /* }}} */ /* {{{ Restore msg */ -int restore_msg_on_answer (struct query *q UU) { +static int restore_msg_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); int n = fetch_int (); fetch_skip (n); - logprintf ("Restored %d messages\n", n); + //logprintf ("Restored %d messages\n", n); + + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } return 0; } -struct query_methods restore_msg_methods = { +static struct query_methods restore_msg_methods = { .on_answer = restore_msg_on_answer, .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM (bare_int)) }; -void tgl_do_restore_msg (long long id) { +void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_messages_restore_messages); out_int (CODE_vector); out_int (1); out_int (id); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &restore_msg_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &restore_msg_methods, 0, callback, callback_extra); } /* }}} */ + int update_status_on_answer (struct query *q UU) { fetch_bool (); + + if (q->callback) { + ((void (*)(void *, int))q->callback) (q->callback_extra, 1); + } return 0; } @@ -2980,9 +3038,9 @@ struct query_methods update_status_methods = { .type = TYPE_TO_PARAM(bool) }; -void tgl_do_update_status (int online UU) { +void tgl_do_update_status (int online UU, void (*callback)(void *callback_extra, int success), void *callback_extra) { clear_packet (); out_int (CODE_account_update_status); out_int (online ? CODE_bool_false : CODE_bool_true); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0, callback, callback_extra); } diff --git a/queries.h b/queries.h index db45111..257056b 100644 --- a/queries.h +++ b/queries.h @@ -50,10 +50,12 @@ struct query { struct dc *DC; struct session *session; void *extra; + void *callback; + void *callback_extra; }; -struct query *send_query (struct dc *DC, int len, void *data, struct query_methods *methods, void *extra); +struct query *send_query (struct dc *DC, int len, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra); void query_ack (long long id); void query_error (long long id); void query_result (long long id); @@ -64,13 +66,13 @@ void remove_event_timer (struct event_timer *ev); double next_timer_in (void); void work_timers (void); -extern struct query_methods help_get_config_methods; +//extern struct query_methods help_get_config_methods; double get_double_time (void); // For binlog -int get_dh_config_on_answer (struct query *q); -void fetch_dc_option (void); +//int get_dh_config_on_answer (struct query *q); +//void fetch_dc_option (void); #endif diff --git a/structures.c b/structures.c index 921ff5b..2ee8dcf 100644 --- a/structures.c +++ b/structures.c @@ -1628,9 +1628,9 @@ void tglm_message_remove_unsent (struct tgl_message *M) { static void __send_msg (struct tgl_message *M) { vlogprintf (E_NOTICE, "Resending message...\n"); - print_message (M); + //print_message (M); - tgl_do_send_msg (M); + tgl_do_send_msg (M, 0, 0); } void tglm_send_all_unsent (void ) { diff --git a/tgl.c b/tgl.c index 6412a21..5fc5a76 100644 --- a/tgl.c +++ b/tgl.c @@ -5,3 +5,19 @@ #include "tgl.h" struct tgl_state tgl_state; + +void tgl_set_binlog_mode (int mode) { + tgl_state.binlog_enabled = mode; +} + +void tgl_set_binlog_path (const char *path) { + tgl_state.binlog_name = tstrdup (path); +} + +void tgl_set_auth_file_path (const char *path) { + tgl_state.auth_file = tstrdup (path); +} + +void tgl_set_download_directory (const char *path) { + tgl_state.downloads_directory = tstrdup (path); +} diff --git a/tgl.h b/tgl.h index e821493..a126675 100644 --- a/tgl.h +++ b/tgl.h @@ -6,7 +6,33 @@ #define TGL_MAX_DC_NUM 100 +#define TGL_BUILD "1828" +#define TGL_VERSION "0.9-beta" + // Do not modify this structure, unless you know what you do +struct tgl_update_callback { + void (*new_msg)(struct tgl_message *M); + void (*marked_read)(int num, struct tgl_message *list[]); + void (*logprintf)(const char *format, ...) __attribute__ ((format (printf, 1, 2))); + void (*type_notification)(tgl_peer_id_t id, struct tgl_user *U); + void (*type_in_chat_notification)(tgl_peer_id_t id, struct tgl_user *U, tgl_peer_id_t chat_id, struct tgl_chat *C); + void (*status_notification)(struct tgl_user *U); + void (*user_registered)(struct tgl_user *U); +}; + +#define vlogprintf(verbosity_level,...) \ + do { \ + if (tgl_state.verbosity >= verbosity_level) { \ + tgl_state.callback.logprintf (__VA_ARGS__); \ + } \ + } while (0) + + +#define E_ERROR 0 +#define E_WARNING 1 +#define E_NOTICE 2 +#define E_DEBUG 3 + struct tgl_state { int our_id; // ID of logged in user int encr_root; @@ -29,6 +55,12 @@ struct tgl_state { long long cur_uploaded_bytes; long long cur_downloading_bytes; long long cur_downloaded_bytes; + + char *binlog_name; + char *auth_file; + char *downloads_directory; + + struct tgl_update_callback callback; }; extern struct tgl_state tgl_state; @@ -57,6 +89,12 @@ int tgl_complete_peer_list (int index, const char *text, int len, char **R); #define TGL_MK_CHAT(id) tgl_set_peer_id (TGL_PEER_CHAT,id) #define TGL_MK_GEO_CHAT(id) tgl_set_peer_id (TGL_PEER_GEO_CHAT,id) #define TGL_MK_ENCR_CHAT(id) tgl_set_peer_id (TGL_PEER_ENCR_CHAT,id) + +void tgl_set_binlog_mode (int mode); +void tgl_set_binlog_path (const char *path); +void tgl_set_auth_file_path (const char *path); +void tgl_set_download_directory (const char *path); + static inline int tgl_get_peer_type (tgl_peer_id_t id) { return id.type; @@ -89,52 +127,49 @@ static inline void tgl_set_test_mode (void) { tgl_state.test_mode ++; } -void tgl_do_send_code (const char *user); -void tgl_do_phone_call (const char *user); -int tgl_do_send_code_result (const char *code); -void tgl_do_update_contact_list (void); -void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len); -void tgl_do_send_text (tgl_peer_id_t id, char *file); -void tgl_do_get_history (tgl_peer_id_t id, int limit); -void tgl_do_get_dialog_list (void); -void tgl_do_get_dialog_list_ex (void); -void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name); -void tgl_do_get_chat_info (tgl_peer_id_t id); -void tgl_do_get_user_list_info_silent (int num, int *list); -void tgl_do_get_user_info (tgl_peer_id_t id); -void tgl_do_forward_message (tgl_peer_id_t id, int n); -void tgl_do_rename_chat (tgl_peer_id_t id, char *name); -void tgl_do_load_encr_video (struct tgl_encr_video *V, int next); -void tgl_do_create_encr_chat_request (int user_id); -void tgl_do_create_secret_chat (tgl_peer_id_t id); -void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic); -void tgl_do_get_suggested (void); +void tgl_do_help_get_config (void (*callback)(void *callback_extra, int success), void *callback_extra); +void tgl_do_send_code (const char *user, void (*callback)(void *callback_extra, int success, int registered, const char *hash), void *callback_extra); +void tgl_do_phone_call (const char *user, void (*callback)(void *callback_extra, int success), void *callback_extra); +int tgl_do_send_code_result (const char *user, const char *code, void (*callback)(void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) ; +int tgl_do_send_code_result_auth (const char *user, const char *code, const char *first_name, const char *last_name, void (*callback)(void *callback_extra, int success, struct tgl_user *Self), void *callback_extra); +void tgl_do_update_contact_list (void (*callback) (void *callback_extra, int success, int size, struct tgl_user *contacts[]), void *callback_extra); +void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_send_msg (struct tgl_message *M, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_send_text (tgl_peer_id_t id, char *file, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_mark_read (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success), void *callback_extra); +void tgl_do_get_history (tgl_peer_id_t id, int limit, int offline_mode, void (*callback)(void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra); +void tgl_do_get_dialog_list (void (*callback)(void *callback_extra, int success, int size, tgl_peer_id_t peers[], int last_msg_id[], int unread_count[]), void *callback_extra); +void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_forward_message (tgl_peer_id_t id, int n, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_rename_chat (tgl_peer_id_t id, char *name, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_get_chat_info (tgl_peer_id_t id, int offline_mode, void (*callback)(void *callback_extra, int success, struct tgl_chat *C), void *callback_extra); +void tgl_do_get_user_info (tgl_peer_id_t id, int offline_mode, void (*callback)(void *callback_extra, int success, struct tgl_user *U), void *callback_extra); +void tgl_do_load_photo (struct tgl_photo *photo, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_load_video_thumb (struct tgl_video *video, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_load_audio (struct tgl_video *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_load_video (struct tgl_video *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_load_document (struct tgl_document *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_load_document_thumb (struct tgl_document *video, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_load_encr_video (struct tgl_encr_video *V, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra); +void tgl_do_export_auth (int num, void (*callback) (void *callback_extra, int success), void *callback_extra); +void tgl_do_add_contact (const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force, void (*callback)(void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra); +void tgl_do_msg_search (tgl_peer_id_t id, int from, int to, int limit, const char *s, void (*callback)(void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra); +void tgl_do_contacts_search (int limit, const char *s, void (*callback) (void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra); +void tgl_do_create_encr_chat_request (int user_id, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); +void tgl_do_create_secret_chat (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); +void tgl_do_accept_encr_chat_request (struct tgl_secret_chat *E, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra); +void tgl_do_get_difference (int sync_from_start, void (*callback)(void *callback_extra, int success), void *callback_extra); +void tgl_do_add_user_to_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra); +void tgl_do_delete_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra); +void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra); +void tgl_do_update_status (int online, void (*callback)(void *callback_extra, int success), void *callback_extra); + +void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]); + +//void tgl_do_get_suggested (void); -void tgl_do_load_photo (struct tgl_photo *photo, int next); -void tgl_do_load_video_thumb (struct tgl_video *video, int next); -void tgl_do_load_audio (struct tgl_video *V, int next); -void tgl_do_load_video (struct tgl_video *V, int next); -void tgl_do_load_document (struct tgl_document *V, int next); -void tgl_do_load_document_thumb (struct tgl_document *video, int next); -void tgl_do_help_get_config (void); -int tgl_do_auth_check_phone (const char *user); -int tgl_do_get_nearest_dc (void); -int tgl_do_send_code_result_auth (const char *code, const char *first_name, const char *last_name); -void tgl_do_import_auth (int num); -void tgl_do_export_auth (int num); -void tgl_do_add_contact (const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force); -void tgl_do_msg_search (tgl_peer_id_t id, int from, int to, int limit, const char *s); -void tgl_do_accept_encr_chat_request (struct tgl_secret_chat *E); -void tgl_do_get_difference (void); -void tgl_do_mark_read (tgl_peer_id_t id); -void tgl_do_visualize_key (tgl_peer_id_t id); void tgl_do_create_keys_end (struct tgl_secret_chat *U); -void tgl_do_add_user_to_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit); -void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id); -void tgl_do_update_status (int online); -void tgl_do_contacts_search (int limit, const char *s); -void tgl_do_send_msg (struct tgl_message *M); -void tgl_do_delete_msg (long long id); -void tgl_do_restore_msg (long long id); void tgl_do_send_encr_chat_layer (struct tgl_secret_chat *E); #endif