diff --git a/Makefile.in b/Makefile.in index 7dd4653..8feda4c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -18,7 +18,7 @@ DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${DEP}/auto ${OBJ}/auto EXE_LIST=${EXE}/generate ${EXE}/tlc ${EXE}/telegram-cli -TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/net.o ${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/lua-tg.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o +TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/net.o ${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/lua-tg.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o ${OBJ}/updates.o TLC_OBJECTS=${OBJ}/tlc.o ${OBJ}/tl-parser.o ${OBJ}/crc32.o GENERATE_OBJECTS=${OBJ}/generate.o COMMON_OBJECTS=${OBJ}/tools.o @@ -60,6 +60,7 @@ ${EXE}/generate: ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${CC} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${LINK_FLAGS} -o $@ ${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tlc + ${EXE}/tlc -e $@ ${AUTO}/scheme.tl ${AUTO}/scheme.tl: ${srcdir}/scheme.tl ${srcdir}/binlog.tl ${srcdir}/append.tl diff --git a/binlog.c b/binlog.c index 7ade286..1b16644 100644 --- a/binlog.c +++ b/binlog.c @@ -44,6 +44,7 @@ #include "loop.h" #include "tgl.h" +#include "auto.h" #include @@ -80,7 +81,7 @@ static int fetch_comb_binlog_dc_option (void *extra) { vlogprintf (E_NOTICE, "DC%d '%.*s' update: %.*s:%d\n", id, l1, name, l2, ip, port); - alloc_dc (id, tstrndup (ip, l2), port); + tglmp_alloc_dc (id, tstrndup (ip, l2), port); return 0; } diff --git a/loop.c b/loop.c index 3d0ebe6..b266e2c 100644 --- a/loop.c +++ b/loop.c @@ -44,20 +44,11 @@ #include #include "interface.h" -#include "net.h" -#include "mtproto-client.h" -#include "mtproto-common.h" -#include "queries.h" #include "telegram.h" #include "loop.h" -#include "binlog.h" #include "lua-tg.h" -#include "structures.h" - #include "tgl.h" -#include "auto.h" - extern char *default_username; extern char *auth_token; void set_default_username (const char *s); @@ -80,7 +71,7 @@ void net_loop (int flags, int (*is_end)(void)) { cc ++; } - write_state_file (); + //write_state_file (); int x = connections_make_poll_array (fds + cc, 101 - cc) + cc; double timer = next_timer_in (); if (timer > 1000) { timer = 1000; } @@ -155,289 +146,6 @@ 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); - assert (write (auth_file_fd, &l, 4) == 4); - assert (write (auth_file_fd, DC->ip, l) == l); - if (DC->flags & 1) { - assert (write (auth_file_fd, &DC->auth_key_id, 8) == 8); - assert (write (auth_file_fd, DC->auth_key, 256) == 256); - } else { - assert (write (auth_file_fd, zero, 256 + 8) == 256 + 8); - } - - assert (write (auth_file_fd, &DC->server_salt, 8) == 8); - assert (write (auth_file_fd, &DC->has_auth, 4) == 4); -} - -void write_auth_file (void) { - if (binlog_enabled) { return; } - int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); - assert (auth_file_fd >= 0); - int x = DC_SERIALIZED_MAGIC_V2; - assert (write (auth_file_fd, &x, 4) == 4); - x = MAX_DC_ID; - assert (write (auth_file_fd, &x, 4) == 4); - assert (write (auth_file_fd, &dc_working_num, 4) == 4); - assert (write (auth_file_fd, &auth_state, 4) == 4); - int i; - for (i = 0; i <= MAX_DC_ID; i++) { - if (DC_list[i]) { - x = 1; - assert (write (auth_file_fd, &x, 4) == 4); - write_dc (auth_file_fd, DC_list[i]); - } else { - x = 0; - assert (write (auth_file_fd, &x, 4) == 4); - } - } - assert (write (auth_file_fd, &tgl_state.our_id, 4) == 4); - close (auth_file_fd); -} - -void read_dc (int auth_file_fd, int id, unsigned ver) { - int port = 0; - assert (read (auth_file_fd, &port, 4) == 4); - int l = 0; - assert (read (auth_file_fd, &l, 4) == 4); - assert (l >= 0); - char *ip = talloc (l + 1); - assert (read (auth_file_fd, ip, l) == l); - ip[l] = 0; - struct dc *DC = alloc_dc (id, ip, port); - assert (read (auth_file_fd, &DC->auth_key_id, 8) == 8); - assert (read (auth_file_fd, &DC->auth_key, 256) == 256); - assert (read (auth_file_fd, &DC->server_salt, 8) == 8); - if (DC->auth_key_id) { - DC->flags |= 1; - } - if (ver != DC_SERIALIZED_MAGIC) { - assert (read (auth_file_fd, &DC->has_auth, 4) == 4); - } else { - DC->has_auth = 0; - } -} - -void empty_auth_file (void) { - alloc_dc (1, tstrdup (tgl_state.test_mode ? TG_SERVER_TEST : TG_SERVER), 443); - dc_working_num = 1; - auth_state = 0; - write_auth_file (); -} - -int need_dc_list_update; -void read_auth_file (void) { - if (binlog_enabled) { return; } - int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); - if (auth_file_fd < 0) { - empty_auth_file (); - } - assert (auth_file_fd >= 0); - unsigned x; - unsigned m; - if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC && m != DC_SERIALIZED_MAGIC_V2)) { - close (auth_file_fd); - empty_auth_file (); - return; - } - assert (read (auth_file_fd, &x, 4) == 4); - assert (x <= MAX_DC_ID); - assert (read (auth_file_fd, &dc_working_num, 4) == 4); - assert (read (auth_file_fd, &auth_state, 4) == 4); - if (m == DC_SERIALIZED_MAGIC) { - auth_state = 700; - } - int i; - for (i = 0; i <= (int)x; i++) { - int y; - assert (read (auth_file_fd, &y, 4) == 4); - if (y) { - read_dc (auth_file_fd, i, m); - } - } - int l = read (auth_file_fd, &tgl_state.our_id, 4); - if (l < 4) { - assert (!l); - } - close (auth_file_fd); - DC_working = DC_list[dc_working_num]; - if (m == DC_SERIALIZED_MAGIC) { - DC_working->has_auth = 1; - } -} - -int pts, qts, seq, last_date; - -void read_state_file (void) { - if (binlog_enabled) { return; } - int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); - if (state_file_fd < 0) { - return; - } - int version, magic; - if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return; } - if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return; } - if (read (state_file_fd, &version, 4) < 4) { close (state_file_fd); return; } - assert (version >= 0); - int x[4]; - if (read (state_file_fd, x, 16) < 16) { - close (state_file_fd); - return; - } - pts = x[0]; - qts = x[1]; - seq = x[2]; - last_date = x[3]; - close (state_file_fd); -} - -void write_state_file (void) { - if (binlog_enabled) { return; } - static int wseq; - static int wpts; - static int wqts; - static int wdate; - if (wseq >= seq && wpts >= pts && wqts >= qts && wdate >= last_date) { return; } - int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); - if (state_file_fd < 0) { - return; - } - int x[6]; - x[0] = STATE_FILE_MAGIC; - x[1] = 0; - x[2] = pts; - x[3] = qts; - x[4] = seq; - x[5] = last_date; - assert (write (state_file_fd, x, 24) == 24); - close (state_file_fd); - wseq = seq; wpts = pts; wqts = qts; wdate = last_date; -} - -extern tgl_peer_t *Peers[]; -extern int peer_num; - -extern int encr_root; -extern unsigned char *encr_prime; -extern int encr_param_version; -extern int dialog_list_got; - -void read_secret_chat_file (void) { - if (binlog_enabled) { return; } - int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); - if (fd < 0) { - return; - } - int x[2]; - if (read (fd, x, 8) < 8) { - close (fd); return; - } - if (x[0] != (int)SECRET_CHAT_FILE_MAGIC) { close (fd); return; } - int version = x[1]; - assert (version >= 0); - int cc; - assert (read (fd, &cc, 4) == 4); - int i; - for (i = 0; i < cc; i++) { - tgl_peer_t *P = talloc0 (sizeof (*P)); - struct tgl_secret_chat *E = &P->encr_chat; - int t; - assert (read (fd, &t, 4) == 4); - P->id = TGL_MK_ENCR_CHAT (t); - assert (read (fd, &P->flags, 4) == 4); - assert (read (fd, &t, 4) == 4); - assert (t > 0); - P->print_name = talloc (t + 1); - assert (read (fd, P->print_name, t) == t); - P->print_name[t] = 0; - tglp_peer_insert_name (P); - - assert (read (fd, &E->state, 4) == 4); - assert (read (fd, &E->user_id, 4) == 4); - assert (read (fd, &E->admin_id, 4) == 4); - assert (read (fd, &E->ttl, 4) == 4); - assert (read (fd, &E->access_hash, 8) == 8); - - if (E->state != sc_waiting) { - E->g_key = talloc (256); - assert (read (fd, E->g_key, 256) == 256); - E->nonce = talloc (256); - assert (read (fd, E->nonce, 256) == 256); - } - assert (read (fd, E->key, 256) == 256); - assert (read (fd, &E->key_fingerprint, 8) == 8); - tglp_insert_encrypted_chat (P); - } - if (version >= 1) { - assert (read (fd, &encr_root, 4) == 4); - if (encr_root) { - assert (read (fd, &encr_param_version, 4) == 4); - encr_prime = talloc (256); - assert (read (fd, encr_prime, 256) == 256); - } - } - close (fd); -} - -void count_encr_peer (tgl_peer_t *P, void *cc) { - if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && P->encr_chat.state != sc_none && P->encr_chat.state != sc_deleted) { - (*(int *)cc) ++; - } -} - -void write_encr_peer (tgl_peer_t *P, void *pfd) { - int fd = *(int *)pfd; - if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && P->encr_chat.state != sc_none && P->encr_chat.state != sc_deleted) { - int t = tgl_get_peer_id (P->id); - assert (write (fd, &t, 4) == 4); - t = P->flags; - assert (write (fd, &t, 4) == 4); - t = strlen (P->print_name); - assert (write (fd, &t, 4) == 4); - assert (write (fd, P->print_name, t) == t); - - assert (write (fd, &P->encr_chat.state, 4) == 4); - - assert (write (fd, &P->encr_chat.user_id, 4) == 4); - assert (write (fd, &P->encr_chat.admin_id, 4) == 4); - assert (write (fd, &P->encr_chat.ttl, 4) == 4); - assert (write (fd, &P->encr_chat.access_hash, 8) == 8); - if (P->encr_chat.state != sc_waiting) { - assert (write (fd, P->encr_chat.g_key, 256) == 256); - } - if (P->encr_chat.state != sc_waiting) { - assert (write (fd, P->encr_chat.nonce, 256) == 256); - } - assert (write (fd, P->encr_chat.key, 256) == 256); - assert (write (fd, &P->encr_chat.key_fingerprint, 8) == 8); - } -} - -void write_secret_chat_file (void) { - if (binlog_enabled) { return; } - int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); - if (fd < 0) { - return; - } - int x[2]; - x[0] = SECRET_CHAT_FILE_MAGIC; - x[1] = 1; - assert (write (fd, x, 8) == 8); - - int cc = 0; - tgl_peer_iterator_ex (count_encr_peer, &cc); - tgl_peer_iterator_ex (write_encr_peer, &fd); - - assert (write (fd, &encr_root, 4) == 4); - if (encr_root) { - assert (write (fd, &encr_param_version, 4) == 4); - assert (write (fd, encr_prime, 256) == 256); - } - close (fd); -}*/ - extern int max_chat_size; int mcs (void) { return max_chat_size; @@ -456,19 +164,17 @@ int new_dc_num; int wait_dialog_list; int loop (void) { - on_start (); - if (binlog_enabled) { - double t = get_double_time (); - logprintf ("replay log start\n"); - tgl_replay_log (); - logprintf ("replay log end in %lf seconds\n", get_double_time () - t); - tgl_reopen_binlog_for_writing (); - #ifdef USE_LUA - lua_binlog_end (); - #endif - } else { - read_auth_file (); - } + //on_start (); + tgl_init (); + + double t = get_double_time (); + logprintf ("replay log start\n"); + tgl_replay_log (); + logprintf ("replay log end in %lf seconds\n", get_double_time () - t); + tgl_reopen_binlog_for_writing (); + #ifdef USE_LUA + lua_binlog_end (); + #endif update_prompt (); assert (DC_list[dc_working_num]); diff --git a/main.c b/main.c index 6c5a1ca..0f5195b 100644 --- a/main.c +++ b/main.c @@ -386,8 +386,8 @@ void usage (void) { exit (1); } -extern char *rsa_public_key_name; -extern int default_dc_num; +//extern char *rsa_public_key_name; +//extern int default_dc_num; char *log_net_file; FILE *log_net_f; @@ -406,7 +406,8 @@ void args_parse (int argc, char **argv) { set_default_username (optarg); break; case 'k': - rsa_public_key_name = tstrdup (optarg); + //rsa_public_key_name = tstrdup (optarg); + tgl_set_rsa_key (optarg); break; case 'v': tgl_incr_verbosity (); diff --git a/mtproto-client.c b/mtproto-client.c index 0f738ab..ce641f2 100644 --- a/mtproto-client.c +++ b/mtproto-client.c @@ -46,14 +46,18 @@ #include #include "telegram.h" -#include "net.h" #include "include.h" #include "queries.h" -#include "loop.h" +//#include "loop.h" #include "structures.h" #include "binlog.h" #include "auto.h" #include "tgl.h" +#include "mtproto-client.h" +#include "tools.h" +#include "tree.h" +#include "updates.h" +#include #if defined(__FreeBSD__) #define __builtin_bswap32(x) bswap32(x) @@ -68,35 +72,29 @@ #include "mtproto-common.h" #define MAX_NET_RES (1L << 16) -extern int log_level; +//extern int log_level; -int verbosity; -int auth_success; -enum dc_state c_state; -char nonce[256]; -char new_nonce[256]; -char server_nonce[256]; -extern int binlog_enabled; -extern int disable_auto_accept; -extern int allow_weak_random; +//int verbosity; +static int auth_success; +static enum dc_state c_state; +static char nonce[256]; +static char new_nonce[256]; +static char server_nonce[256]; +//extern int binlog_enabled; +//extern int disable_auto_accept; +//extern int allow_weak_random; -int total_packets_sent; -long long total_data_sent; +static int total_packets_sent; +static long long total_data_sent; -int rpc_execute (struct connection *c, int op, int len); -int rpc_becomes_ready (struct connection *c); -int rpc_close (struct connection *c); +static int rpc_execute (struct connection *c, int op, int len); +static int rpc_becomes_ready (struct connection *c); +static int rpc_close (struct connection *c); -struct connection_methods auth_methods = { - .execute = rpc_execute, - .ready = rpc_becomes_ready, - .close = rpc_close -}; +static long long precise_time; -long long precise_time; - -double get_utime (int clock_id) { +static double get_utime (int clock_id) { struct timespec T; my_clock_gettime (clock_id, &T); double res = T.tv_sec + (double) T.tv_nsec * 1e-9; @@ -106,25 +104,15 @@ double get_utime (int clock_id) { return res; } -void secure_random (void *s, int l) { - if (RAND_bytes (s, l) < 0) { - if (allow_weak_random) { - RAND_pseudo_bytes (s, l); - } else { - assert (0 && "End of random. If you want, you can start with -w"); - } - } -} - -#define STATS_BUFF_SIZE (64 << 10) -int stats_buff_len; -char stats_buff[STATS_BUFF_SIZE]; +//#define STATS_BUFF_SIZE (64 << 10) +//static int stats_buff_len; +//static char stats_buff[STATS_BUFF_SIZE]; #define MAX_RESPONSE_SIZE (1L << 24) -char Response[MAX_RESPONSE_SIZE]; -int Response_len; +static char Response[MAX_RESPONSE_SIZE]; +//static int Response_len; /* * @@ -133,9 +121,9 @@ int Response_len; */ #define TG_SERVER_PUBKEY_FILENAME "tg-server.pub" -char *rsa_public_key_name; // = TG_SERVER_PUBKEY_FILENAME; -RSA *pubKey; -long long pk_fingerprint; +static char *rsa_public_key_name; // = TG_SERVER_PUBKEY_FILENAME; +static RSA *pubKey; +static long long pk_fingerprint; static int rsa_load_public_key (const char *public_key_name) { pubKey = NULL; @@ -162,18 +150,16 @@ static int rsa_load_public_key (const char *public_key_name) { -int auth_work_start (struct connection *c); - /* * * UNAUTHORIZED (DH KEY EXCHANGE) PROTOCOL PART * */ -BIGNUM dh_prime, dh_g, g_a, dh_power, auth_key_num; -char s_power [256]; +static BIGNUM dh_prime, dh_g, g_a, auth_key_num; +static char s_power [256]; -struct { +static struct { long long auth_key_id; long long out_msg_id; int msg_len; @@ -181,24 +167,25 @@ struct { #define ENCRYPT_BUFFER_INTS 16384 -int encrypt_buffer[ENCRYPT_BUFFER_INTS]; +static int encrypt_buffer[ENCRYPT_BUFFER_INTS]; #define DECRYPT_BUFFER_INTS 16384 -int decrypt_buffer[ENCRYPT_BUFFER_INTS]; +static int decrypt_buffer[ENCRYPT_BUFFER_INTS]; -int encrypt_packet_buffer (void) { +static int encrypt_packet_buffer (void) { return pad_rsa_encrypt ((char *) packet_buffer, (packet_ptr - packet_buffer) * 4, (char *) encrypt_buffer, ENCRYPT_BUFFER_INTS * 4, pubKey->n, pubKey->e); } -int encrypt_packet_buffer_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32]) { +static int encrypt_packet_buffer_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32]) { init_aes_unauth (server_nonce, hidden_client_nonce, AES_ENCRYPT); return pad_aes_encrypt ((char *) packet_buffer, (packet_ptr - packet_buffer) * 4, (char *) encrypt_buffer, ENCRYPT_BUFFER_INTS * 4); } -int rpc_send_packet (struct connection *c) { +static int rpc_send_packet (struct connection *c) { int len = (packet_ptr - packet_buffer) * 4; - c->out_packet_num ++; + //c->out_packet_num ++; + tgl_state.net_methods->incr_out_packet_num (c); long long next_msg_id = (long long) ((1LL << 32) * get_utime (CLOCK_REALTIME)) & -4; if (next_msg_id <= unenc_msg_header.out_msg_id) { unenc_msg_header.out_msg_id += 4; @@ -211,60 +198,64 @@ int rpc_send_packet (struct connection *c) { assert (total_len > 0 && !(total_len & 0xfc000003)); total_len >>= 2; if (total_len < 0x7f) { - assert (write_out (c, &total_len, 1) == 1); + assert (tgl_state.net_methods->write_out (c, &total_len, 1) == 1); } else { total_len = (total_len << 8) | 0x7f; - assert (write_out (c, &total_len, 4) == 4); + assert (tgl_state.net_methods->write_out (c, &total_len, 4) == 4); } - write_out (c, &unenc_msg_header, 20); - write_out (c, packet_buffer, len); - flush_out (c); + tgl_state.net_methods->write_out (c, &unenc_msg_header, 20); + tgl_state.net_methods->write_out (c, packet_buffer, len); + tgl_state.net_methods->flush_out (c); total_packets_sent ++; total_data_sent += total_len; return 1; } -int rpc_send_message (struct connection *c, void *data, int len) { +static int rpc_send_message (struct connection *c, void *data, int len) { assert (len > 0 && !(len & 0xfc000003)); int total_len = len >> 2; if (total_len < 0x7f) { - assert (write_out (c, &total_len, 1) == 1); + assert (tgl_state.net_methods->write_out (c, &total_len, 1) == 1); } else { total_len = (total_len << 8) | 0x7f; - assert (write_out (c, &total_len, 4) == 4); + assert (tgl_state.net_methods->write_out (c, &total_len, 4) == 4); } - c->out_packet_num ++; - assert (write_out (c, data, len) == len); - flush_out (c); + + tgl_state.net_methods->incr_out_packet_num (c); + assert (tgl_state.net_methods->write_out (c, data, len) == len); + tgl_state.net_methods->flush_out (c); total_packets_sent ++; total_data_sent += total_len; return 1; } -int send_req_pq_packet (struct connection *c) { - assert (c_state == st_init); - secure_random (nonce, 16); +static int send_req_pq_packet (struct connection *c) { + struct dc *D = tgl_state.net_methods->get_dc (c); + assert (D->state == st_init); + + tglt_secure_random (nonce, 16); unenc_msg_header.out_msg_id = 0; clear_packet (); out_int (CODE_req_pq); out_ints ((int *)nonce, 4); rpc_send_packet (c); - c_state = st_reqpq_sent; + + D->state = st_reqpq_sent; return 1; } -unsigned long long gcd (unsigned long long a, unsigned long long b) { +static unsigned long long gcd (unsigned long long a, unsigned long long b) { return b ? gcd (b, a % b) : a; } //typedef unsigned int uint128_t __attribute__ ((mode(TI))); -unsigned long long what; -unsigned p1, p2; -int process_respq_answer (struct connection *c, char *packet, int len) { +static int process_respq_answer (struct connection *c, char *packet, int len) { + unsigned long long what; + unsigned p1, p2; int i; vlogprintf (E_DEBUG, "process_respq_answer(), len=%d\n", len); assert (len >= 76); @@ -383,7 +374,7 @@ int process_respq_answer (struct connection *c, char *packet, int len) { //out_int (0x0501); // q=5 out_ints ((int *) nonce, 4); out_ints ((int *) server_nonce, 4); - secure_random (new_nonce, 32); + tglt_secure_random (new_nonce, 32); out_ints ((int *) new_nonce, 8); sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer); @@ -428,13 +419,13 @@ int process_respq_answer (struct connection *c, char *packet, int len) { return rpc_send_packet (c); } -int check_prime (BIGNUM *p) { +static int check_prime (BIGNUM *p) { int r = BN_is_prime (p, BN_prime_checks, 0, BN_ctx, 0); ensure (r >= 0); return r; } -int check_DH_params (BIGNUM *p, int g) { +int tglmp_check_DH_params (BIGNUM *p, int g) { if (g < 2 || g > 7) { return -1; } BIGNUM t; BN_init (&t); @@ -480,7 +471,7 @@ int check_DH_params (BIGNUM *p, int g) { return 0; } -int check_g (unsigned char p[256], BIGNUM *g) { +int tglmp_check_g (unsigned char p[256], BIGNUM *g) { static unsigned char s[256]; memset (s, 0, 256); assert (BN_num_bytes (g) <= 256); @@ -516,19 +507,19 @@ int check_g (unsigned char p[256], BIGNUM *g) { return 0; } -int check_g_bn (BIGNUM *p, BIGNUM *g) { +int tglmp_check_g_bn (BIGNUM *p, BIGNUM *g) { static unsigned char s[256]; memset (s, 0, 256); assert (BN_num_bytes (p) <= 256); BN_bn2bin (p, s); - return check_g (s, g); + return tglmp_check_g (s, g); } -int process_dh_answer (struct connection *c, char *packet, int len) { +static int process_dh_answer (struct connection *c, char *packet, int len) { vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len); - if (len < 116) { - vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what); - } + //if (len < 116) { + // vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what); + //} assert (len >= 116); assert (!*(long long *) packet); assert (*(int *) (packet + 16) == len - 20); @@ -554,19 +545,20 @@ int process_dh_answer (struct connection *c, char *packet, int len) { BN_init (&g_a); assert (fetch_bignum (&dh_prime) > 0); assert (fetch_bignum (&g_a) > 0); - assert (check_g_bn (&dh_prime, &g_a) >= 0); + assert (tglmp_check_g_bn (&dh_prime, &g_a) >= 0); int server_time = *in_ptr++; assert (in_ptr <= in_end); - assert (check_DH_params (&dh_prime, g) >= 0); + assert (tglmp_check_DH_params (&dh_prime, g) >= 0); static char sha1_buffer[20]; sha1 ((unsigned char *) decrypt_buffer + 20, (in_ptr - decrypt_buffer - 5) * 4, (unsigned char *) sha1_buffer); assert (!memcmp (decrypt_buffer, sha1_buffer, 20)); assert ((char *) in_end - (char *) in_ptr < 16); - GET_DC(c)->server_time_delta = server_time - time (0); - GET_DC(c)->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC); + struct dc *D = tgl_state.net_methods->get_dc (c); + D->server_time_delta = server_time - time (0); + D->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC); //logprintf ( "server time is %d, delta = %d\n", server_time, server_time_delta); // Build set_client_DH_params answer @@ -580,7 +572,7 @@ int process_dh_answer (struct connection *c, char *packet, int len) { BN_init (&dh_g); ensure (BN_set_word (&dh_g, g)); - secure_random (s_power, 256); + tglt_secure_random (s_power, 256); BIGNUM *dh_power = BN_bin2bn ((unsigned char *)s_power, 256, 0); ensure_ptr (dh_power); @@ -594,8 +586,8 @@ int process_dh_answer (struct connection *c, char *packet, int len) { ensure (BN_mod_exp (&auth_key_num, &g_a, dh_power, &dh_prime, BN_ctx)); l = BN_num_bytes (&auth_key_num); assert (l >= 250 && l <= 256); - assert (BN_bn2bin (&auth_key_num, (unsigned char *)GET_DC(c)->auth_key)); - memset (GET_DC(c)->auth_key + l, 0, 256 - l); + assert (BN_bn2bin (&auth_key_num, (unsigned char *)D->auth_key)); + memset (D->auth_key + l, 0, 256 - l); BN_free (dh_power); BN_free (&auth_key_num); BN_free (&dh_g); @@ -622,7 +614,7 @@ int process_dh_answer (struct connection *c, char *packet, int len) { } -int process_auth_complete (struct connection *c UU, char *packet, int len) { +static int process_auth_complete (struct connection *c UU, char *packet, int len) { vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len); assert (len == 72); assert (!*(long long *) packet); @@ -636,13 +628,14 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) { tmp[32] = 1; //GET_DC(c)->auth_key_id = *(long long *)(sha1_buffer + 12); - bl_do_set_auth_key_id (GET_DC(c)->id, (unsigned char *)GET_DC(c)->auth_key); - sha1 ((unsigned char *)GET_DC(c)->auth_key, 256, sha1_buffer); + struct dc *D = tgl_state.net_methods->get_dc (c); + bl_do_set_auth_key_id (D->id, (unsigned char *)D->auth_key); + sha1 ((unsigned char *)D->auth_key, 256, sha1_buffer); memcpy (tmp + 33, sha1_buffer, 8); sha1 (tmp, 41, sha1_buffer); assert (!memcmp (packet + 56, sha1_buffer + 4, 16)); - GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce; + D->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce; //kprintf ("OK\n"); @@ -653,8 +646,8 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) { //return 1; vlogprintf (E_DEBUG, "Auth success\n"); auth_success ++; - GET_DC(c)->flags |= 1; - write_auth_file (); + D->flags |= 1; + //write_auth_file (); return 1; } @@ -665,18 +658,18 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) { * */ -struct encrypted_message enc_msg; +static struct encrypted_message enc_msg; -long long client_last_msg_id, server_last_msg_id; +static long long client_last_msg_id, server_last_msg_id; -double get_server_time (struct dc *DC) { +static double get_server_time (struct dc *DC) { if (!DC->server_time_udelta) { DC->server_time_udelta = get_utime (CLOCK_REALTIME) - get_utime (CLOCK_MONOTONIC); } return get_utime (CLOCK_MONOTONIC) + DC->server_time_udelta; } -long long generate_next_msg_id (struct dc *DC) { +static long long generate_next_msg_id (struct dc *DC) { long long next_id = (long long) (get_server_time (DC) * (1LL << 32)) & -4; if (next_id <= client_last_msg_id) { next_id = client_last_msg_id += 4; @@ -686,14 +679,14 @@ long long generate_next_msg_id (struct dc *DC) { return next_id; } -void init_enc_msg (struct session *S, int useful) { +static void init_enc_msg (struct session *S, int useful) { struct dc *DC = S->dc; assert (DC->auth_key_id); enc_msg.auth_key_id = DC->auth_key_id; // assert (DC->server_salt); enc_msg.server_salt = DC->server_salt; if (!S->session_id) { - secure_random (&S->session_id, 8); + tglt_secure_random (&S->session_id, 8); } enc_msg.session_id = S->session_id; //enc_msg.auth_key_id2 = auth_key_id; @@ -707,7 +700,7 @@ void init_enc_msg (struct session *S, int useful) { S->seq_no += 2; }; -int aes_encrypt_message (struct dc *DC, struct encrypted_message *enc) { +static int aes_encrypt_message (struct dc *DC, struct encrypted_message *enc) { unsigned char sha1_buffer[20]; const int MINSZ = offsetof (struct encrypted_message, message); const int UNENCSZ = offsetof (struct encrypted_message, server_salt); @@ -722,10 +715,11 @@ int aes_encrypt_message (struct dc *DC, struct encrypted_message *enc) { return pad_aes_encrypt ((char *) &enc->server_salt, enc_len, (char *) &enc->server_salt, MAX_MESSAGE_INTS * 4 + (MINSZ - UNENCSZ)); } -long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful) { - struct dc *DC = GET_DC(c); - struct session *S = c->session; +long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful) { + struct dc *DC = tgl_state.net_methods->get_dc (c); + struct session *S = tgl_state.net_methods->get_session (c); assert (S); + const int UNENCSZ = offsetof (struct encrypted_message, server_salt); if (msg_ints <= 0 || msg_ints > MAX_MESSAGE_INTS - 4) { return -1; @@ -749,723 +743,17 @@ long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, in return client_last_msg_id; } -int longpoll_count, good_messages; +static int good_messages; -int auth_work_start (struct connection *c UU) { - return 1; -} +static void rpc_execute_answer (struct connection *c, long long msg_id UU); -void rpc_execute_answer (struct connection *c, long long msg_id UU); +//int unread_messages; +//int pts; +//int qts; +//int last_date; +//int seq; -int unread_messages; -int pts; -int qts; -int last_date; -int seq; - -void fetch_pts (void) { - int p = fetch_int (); - if (p <= pts) { return; } - if (p != pts + 1) { - if (pts) { - //logprintf ("Hole in pts p = %d, pts = %d\n", p, pts); - - // get difference should be here - pts = p; - } else { - pts = p; - } - } else { - pts ++; - } - bl_do_set_pts (pts); -} - -void fetch_qts (void) { - int p = fetch_int (); - if (p <= qts) { return; } - if (p != qts + 1) { - if (qts) { - //logprintf ("Hole in qts\n"); - // get difference should be here - qts = p; - } else { - qts = p; - } - } else { - qts ++; - } - bl_do_set_qts (qts); -} - -void fetch_date (void) { - int p = fetch_int (); - if (p > last_date) { - last_date = p; - bl_do_set_date (last_date); - } -} - -void fetch_seq (void) { - int x = fetch_int (); - if (x > seq + 1) { - vlogprintf (E_NOTICE, "Hole in seq: seq = %d, x = %d\n", seq, x); - //tgl_do_get_difference (); - //seq = x; - } else if (x == seq + 1) { - seq = x; - bl_do_set_seq (seq); - } -} -/* -void work_update_binlog (void) { - unsigned op = fetch_int (); - switch (op) { - case CODE_update_user_name: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *UC = tgl_peer_get (user_id); - if (UC) { - struct tgl_user *U = &UC->user; - if (U->first_name) { tfree_str (U->first_name); } - if (U->last_name) { tfree_str (U->last_name); } - if (U->print_name) { - tglp_peer_delete_name (UC); - tfree_str (U->print_name); - } - U->first_name = fetch_str_dup (); - U->last_name = fetch_str_dup (); - U->print_name = create_print_name (U->id, U->first_name, U->last_name, 0, 0); - tglp_peer_insert_name ((void *)U); - } else { - fetch_skip_str (); - fetch_skip_str (); - } - } - break; - case CODE_update_user_photo: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *UC = tgl_peer_get (user_id); - fetch_date (); - if (UC) { - struct tgl_user *U = &UC->user; - - unsigned y = fetch_int (); - if (y == CODE_user_profile_photo_empty) { - U->photo_id = 0; - U->photo_big.dc = -2; - U->photo_small.dc = -2; - } else { - assert (y == CODE_user_profile_photo); - U->photo_id = fetch_long (); - tglf_fetch_file_location (&U->photo_small); - tglf_fetch_file_location (&U->photo_big); - } - } else { - struct tgl_file_location t; - unsigned y = fetch_int (); - if (y == CODE_user_profile_photo_empty) { - } else { - assert (y == CODE_user_profile_photo); - fetch_long (); // photo_id - tglf_fetch_file_location (&t); - tglf_fetch_file_location (&t); - } - } - fetch_bool (); - } - break; - default: - assert (0); - } -}*/ - -void work_update (struct connection *c UU, long long msg_id UU) { - unsigned op = fetch_int (); - switch (op) { - case CODE_update_new_message: - { - struct tgl_message *M = tglf_fetch_alloc_message (); - assert (M); - fetch_pts (); - - tgl_state.callback.new_msg (M); - //unread_messages ++; - //print_message (M); - //update_prompt (); - break; - }; - case CODE_update_message_i_d: - { - int id = fetch_int (); // id - int new = fetch_long (); // random_id - struct tgl_message *M = tgl_message_get (new); - if (M) { - bl_do_set_msg_id (M, id); - } - } - break; - case CODE_update_read_messages: - { - 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 (); - 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); - - tgl_state.callback.type_notification (id, (void *)U); - /*if (log_level >= 2) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" User "); - print_user_name (id, U); - printf (" is typing....\n"); - pop_color (); - print_end (); - }*/ - } - break; - case CODE_update_chat_user_typing: - { - tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); - 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); - - 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)); - printf (" User "); - print_user_name (id, U); - printf (" is typing in chat "); - print_chat_name (chat_id, C); - printf ("....\n"); - pop_color (); - print_end (); - }*/ - } - break; - case CODE_update_user_status: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *U = tgl_peer_get (user_id); - if (U) { - tglf_fetch_user_status (&U->user.status); - tgl_state.callback.status_notification ((void *)U); - /*if (log_level >= 3) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" User "); - print_user_name (user_id, U); - printf (" is now "); - 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); - } - } - break; - case CODE_update_user_name: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *UC = tgl_peer_get (user_id); - if (UC && (UC->flags & FLAG_CREATED)) { - int l1 = prefetch_strlen (); - char *f = fetch_str (l1); - int l2 = prefetch_strlen (); - char *l = fetch_str (l2); - struct tgl_user *U = &UC->user; - bl_do_user_set_real_name (U, f, l1, l, l2); - /*print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" User "); - print_user_name (user_id, UC); - printf (" changed name to "); - print_user_name (user_id, UC); - printf ("\n"); - pop_color (); - print_end ();*/ - } else { - fetch_skip_str (); - fetch_skip_str (); - } - } - break; - case CODE_update_user_photo: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *UC = tgl_peer_get (user_id); - fetch_date (); - if (UC && (UC->flags & FLAG_CREATED)) { - struct tgl_user *U = &UC->user; - unsigned y = fetch_int (); - long long photo_id; - struct tgl_file_location big; - struct tgl_file_location small; - memset (&big, 0, sizeof (big)); - memset (&small, 0, sizeof (small)); - if (y == CODE_user_profile_photo_empty) { - photo_id = 0; - big.dc = -2; - small.dc = -2; - } else { - assert (y == CODE_user_profile_photo); - photo_id = fetch_long (); - tglf_fetch_file_location (&small); - tglf_fetch_file_location (&big); - } - bl_do_set_user_profile_photo (U, photo_id, &big, &small); - - /*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 ();*/ - } else { - struct tgl_file_location t; - unsigned y = fetch_int (); - if (y == CODE_user_profile_photo_empty) { - } else { - assert (y == CODE_user_profile_photo); - fetch_long (); // photo_id - tglf_fetch_file_location (&t); - tglf_fetch_file_location (&t); - } - } - fetch_bool (); - } - break; - case CODE_update_restore_messages: - { - assert (fetch_int () == CODE_vector); - int n = fetch_int (); - /*print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" Restored %d messages\n", n); - pop_color (); - print_end ();*/ - fetch_skip (n); - fetch_pts (); - } - break; - case CODE_update_delete_messages: - { - assert (fetch_int () == CODE_vector); - int n = fetch_int (); - /*print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" Deleted %d messages\n", n); - pop_color (); - print_end ();*/ - fetch_skip (n); - fetch_pts (); - } - break; - case CODE_update_chat_participants: - { - unsigned x = fetch_int (); - assert (x == CODE_chat_participants || x == CODE_chat_participants_forbidden); - tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); - int n = 0; - tgl_peer_t *C = tgl_peer_get (chat_id); - if (C && (C->flags & FLAG_CREATED)) { - if (x == CODE_chat_participants) { - bl_do_chat_set_admin (&C->chat, fetch_int ()); - assert (fetch_int () == CODE_vector); - n = fetch_int (); - struct tgl_chat_user *users = talloc (12 * n); - int i; - for (i = 0; i < n; i++) { - assert (fetch_int () == (int)CODE_chat_participant); - users[i].user_id = fetch_int (); - users[i].inviter_id = fetch_int (); - users[i].date = fetch_int (); - } - int version = fetch_int (); - bl_do_chat_set_participants (&C->chat, version, n, users); - } - } else { - if (x == CODE_chat_participants) { - fetch_int (); // admin_id - assert (fetch_int () == CODE_vector); - n = fetch_int (); - fetch_skip (n * 4); - fetch_int (); // version - } - } - /*print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" Chat "); - print_chat_name (chat_id, C); - if (x == CODE_chat_participants) { - printf (" changed list: now %d members\n", n); - } else { - printf (" changed list, but we are forbidden to know about it (Why this update even was sent to us?\n"); - } - pop_color (); - print_end ();*/ - } - break; - case CODE_update_contact_registered: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *U = tgl_peer_get (user_id); - fetch_int (); // date - 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 ();*/ - } - 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 (); - 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 ();*/ - 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) { - fetch_bool (); // has_phone - } - t = fetch_int (); - assert (t == CODE_contacts_foreign_link_unknown || t == CODE_contacts_foreign_link_requested || t == CODE_contacts_foreign_link_mutual); - if (t == CODE_contacts_foreign_link_requested) { - fetch_bool (); // has_phone - } - } - break; - case CODE_update_activation: - { - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_t *U = tgl_peer_get (user_id); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" User "); - print_user_name (user_id, U); - printf (" activated\n"); - pop_color (); - print_end (); - } - break; - case CODE_update_new_authorization: - { - fetch_long (); // auth_key_id - fetch_int (); // date - char *s = fetch_str_dup (); - char *location = fetch_str_dup (); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" New autorization: device='%s' location='%s'\n", - s, location); - pop_color (); - print_end (); - tfree_str (s); - tfree_str (location); - } - break; - case CODE_update_new_geo_chat_message: - { - struct tgl_message *M = tglf_fetch_alloc_geo_message (); - unread_messages ++; - print_message (M); - update_prompt (); - } - break; - case CODE_update_new_encrypted_message: - { - struct tgl_message *M = tglf_fetch_alloc_encrypted_message (); - unread_messages ++; - print_message (M); - update_prompt (); - fetch_qts (); - } - break; - case CODE_update_encryption: - { - struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (); - vlogprintf (E_DEBUG, "Secret chat state = %d\n", E->state); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - switch (E->state) { - case sc_none: - break; - case sc_waiting: - printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); - printf (" is now in wait state\n"); - break; - case sc_request: - printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); - printf (" is now in request state. Sending request ok\n"); - break; - case sc_ok: - printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); - printf (" is now in ok state\n"); - break; - case sc_deleted: - printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); - printf (" is now in deleted state\n"); - break; - } - pop_color (); - print_end (); - if (E->state == sc_request && !disable_auto_accept) { - tgl_do_accept_encr_chat_request (E); - } - if (E->state == sc_ok) { - tgl_do_send_encr_chat_layer (E); - } - fetch_int (); // date - } - break; - case CODE_update_encrypted_chat_typing: - { - tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); - tgl_peer_t *P = tgl_peer_get (id); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - if (P) { - printf (" User "); - tgl_peer_id_t user_id = TGL_MK_USER (P->encr_chat.user_id); - print_user_name (user_id, tgl_peer_get (user_id)); - printf (" typing in secret chat "); - print_encr_chat_name (id, P); - printf ("\n"); - } else { - printf (" Some user is typing in unknown secret chat\n"); - } - pop_color (); - print_end (); - } - break; - case CODE_update_encrypted_messages_read: - { - tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); // chat_id - fetch_int (); // max_date - fetch_int (); // date - tgl_peer_t *P = tgl_peer_get (id); - int x = -1; - if (P && P->last) { - x = 0; - struct tgl_message *M = P->last; - while (M && (!M->out || M->unread)) { - if (M->out) { - M->unread = 0; - x ++; - } - M = M->next; - } - } - if (log_level >= 1) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" Encrypted chat "); - print_encr_chat_name_full (id, tgl_peer_get (id)); - printf (": %d messages marked read \n", x); - pop_color (); - print_end (); - } - } - break; - case CODE_update_chat_participant_add: - { - tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - tgl_peer_id_t inviter_id = TGL_MK_USER (fetch_int ()); - int version = fetch_int (); - - tgl_peer_t *C = tgl_peer_get (chat_id); - if (C && (C->flags & FLAG_CREATED)) { - bl_do_chat_add_user (&C->chat, version, tgl_get_peer_id (user_id), tgl_get_peer_id (inviter_id), time (0)); - } - - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" Chat "); - print_chat_name (chat_id, tgl_peer_get (chat_id)); - printf (": user "); - print_user_name (user_id, tgl_peer_get (user_id)); - printf (" added by user "); - print_user_name (inviter_id, tgl_peer_get (inviter_id)); - printf ("\n"); - pop_color (); - print_end (); - } - break; - case CODE_update_chat_participant_delete: - { - tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); - tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); - int version = fetch_int (); - - tgl_peer_t *C = tgl_peer_get (chat_id); - if (C && (C->flags & FLAG_CREATED)) { - bl_do_chat_del_user (&C->chat, version, tgl_get_peer_id (user_id)); - } - - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); - printf (" Chat "); - print_chat_name (chat_id, tgl_peer_get (chat_id)); - printf (": user "); - print_user_name (user_id, tgl_peer_get (user_id)); - printf (" deleted\n"); - pop_color (); - print_end (); - } - break; - case CODE_update_dc_options: - { - assert (fetch_int () == CODE_vector); - int n = fetch_int (); - assert (n >= 0); - int i; - for (i = 0; i < n; i++) { - fetch_dc_option (); - } - } - break; - case CODE_update_user_blocked: - { - int id = fetch_int (); - int blocked = fetch_bool (); - tgl_peer_t *P = tgl_peer_get (TGL_MK_USER (id)); - if (P && (P->flags & FLAG_CREATED)) { - bl_do_user_set_blocked (&P->user, blocked); - } - } - break; - case CODE_update_notify_settings: - { - assert (skip_type_any (TYPE_TO_PARAM (notify_peer)) >= 0); - assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0); - } - break; - default: - vlogprintf (E_ERROR, "Unknown update type %08x\n", op); - ; - } -} - -void work_update_short (struct connection *c, long long msg_id) { - assert (fetch_int () == CODE_update_short); - work_update (c, msg_id); - fetch_date (); -} - -void work_updates (struct connection *c, long long msg_id) { - int *save = in_ptr; - assert (!skip_type_any (TYPE_TO_PARAM (updates))); - int *save_end = in_ptr; - in_ptr = save; - assert (fetch_int () == CODE_updates); - assert (fetch_int () == CODE_vector); - int n = fetch_int (); - int i; - for (i = 0; i < n; i++) { - work_update (c, msg_id); - } - assert (fetch_int () == CODE_vector); - n = fetch_int (); - for (i = 0; i < n; i++) { - tglf_fetch_alloc_user (); - } - assert (fetch_int () == CODE_vector); - n = fetch_int (); - for (i = 0; i < n; i++) { - tglf_fetch_alloc_chat (); - } - bl_do_set_date (fetch_int ()); - bl_do_set_seq (fetch_int ()); - assert (save_end == in_ptr); -} - -void work_update_short_message (struct connection *c UU, long long msg_id UU) { - assert (fetch_int () == (int)CODE_update_short_message); - struct tgl_message *M = tglf_fetch_alloc_message_short (); - unread_messages ++; - print_message (M); - update_prompt (); - if (M->date > last_date) { - last_date = M->date; - } -} - -void work_update_short_chat_message (struct connection *c UU, long long msg_id UU) { - assert (fetch_int () == CODE_update_short_chat_message); - struct tgl_message *M = tglf_fetch_alloc_message_short_chat (); - unread_messages ++; - print_message (M); - update_prompt (); - if (M->date > last_date) { - last_date = M->date; - } -} - -void work_container (struct connection *c, long long msg_id UU) { +static void work_container (struct connection *c, long long msg_id UU) { vlogprintf (E_DEBUG, "work_container: msg_id = %lld\n", msg_id); assert (fetch_int () == CODE_msg_container); int n = fetch_int (); @@ -1475,7 +763,7 @@ void work_container (struct connection *c, long long msg_id UU) { //int seqno = fetch_int (); fetch_int (); // seq_no if (id & 1) { - insert_msg_id (c->session, id); + tgln_insert_msg_id (tgl_state.net_methods->get_session (c), id); } int bytes = fetch_int (); int *t = in_end; @@ -1486,17 +774,17 @@ void work_container (struct connection *c, long long msg_id UU) { } } -void work_new_session_created (struct connection *c, long long msg_id UU) { +static void work_new_session_created (struct connection *c, long long msg_id UU) { 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 (); fetch_long (); // unique_id - GET_DC(c)->server_salt = fetch_long (); + tgl_state.net_methods->get_dc (c)->server_salt = fetch_long (); } -void work_msgs_ack (struct connection *c UU, long long msg_id UU) { +static void work_msgs_ack (struct connection *c UU, long long msg_id UU) { vlogprintf (E_DEBUG, "work_msgs_ack: msg_id = %lld\n", msg_id); assert (fetch_int () == CODE_msgs_ack); assert (fetch_int () == CODE_vector); @@ -1505,24 +793,24 @@ void work_msgs_ack (struct connection *c UU, long long msg_id UU) { for (i = 0; i < n; i++) { long long id = fetch_long (); vlogprintf (E_DEBUG + 1, "ack for %lld\n", id); - query_ack (id); + tglq_query_ack (id); } } -void work_rpc_result (struct connection *c UU, long long msg_id UU) { +static void work_rpc_result (struct connection *c UU, long long msg_id UU) { 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 (); if (op == CODE_rpc_error) { - query_error (id); + tglq_query_error (id); } else { - query_result (id); + tglq_query_result (id); } } #define MAX_PACKED_SIZE (1 << 24) -void work_packed (struct connection *c, long long msg_id) { +static void work_packed (struct connection *c, long long msg_id) { assert (fetch_int () == CODE_gzip_packed); static int in_gzip; static int buf[MAX_PACKED_SIZE >> 2]; @@ -1544,23 +832,23 @@ void work_packed (struct connection *c, long long msg_id) { in_gzip = 0; } -void work_bad_server_salt (struct connection *c UU, long long msg_id UU) { +static void work_bad_server_salt (struct connection *c UU, long long msg_id UU) { assert (fetch_int () == (int)CODE_bad_server_salt); long long id = fetch_long (); - query_restart (id); + tglq_query_restart (id); fetch_int (); // seq_no fetch_int (); // error_code long long new_server_salt = fetch_long (); - GET_DC(c)->server_salt = new_server_salt; + tgl_state.net_methods->get_dc (c)->server_salt = new_server_salt; } -void work_pong (struct connection *c UU, long long msg_id UU) { +static void work_pong (struct connection *c UU, long long msg_id UU) { assert (fetch_int () == CODE_pong); fetch_long (); // msg_id fetch_long (); // ping_id } -void work_detailed_info (struct connection *c UU, long long msg_id UU) { +static void work_detailed_info (struct connection *c UU, long long msg_id UU) { assert (fetch_int () == CODE_msg_detailed_info); fetch_long (); // msg_id fetch_long (); // answer_msg_id @@ -1568,20 +856,14 @@ void work_detailed_info (struct connection *c UU, long long msg_id UU) { fetch_int (); // status } -void work_new_detailed_info (struct connection *c UU, long long msg_id UU) { +static void work_new_detailed_info (struct connection *c UU, long long msg_id UU) { assert (fetch_int () == (int)CODE_msg_new_detailed_info); fetch_long (); // answer_msg_id fetch_int (); // bytes fetch_int (); // status } -void work_updates_to_long (struct connection *c UU, long long msg_id UU) { - assert (fetch_int () == (int)CODE_updates_too_long); - vlogprintf (E_NOTICE, "updates to long... Getting difference\n"); - tgl_do_get_difference (); -} - -void work_bad_msg_notification (struct connection *c UU, long long msg_id UU) { +static void work_bad_msg_notification (struct connection *c UU, long long msg_id UU) { assert (fetch_int () == (int)CODE_bad_msg_notification); long long m1 = fetch_long (); int s = fetch_int (); @@ -1589,7 +871,7 @@ void work_bad_msg_notification (struct connection *c UU, long long msg_id UU) { 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) { +static void rpc_execute_answer (struct connection *c, long long msg_id UU) { int op = prefetch_int (); switch (op) { case CODE_msg_container: @@ -1605,16 +887,16 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { work_rpc_result (c, msg_id); return; case CODE_update_short: - work_update_short (c, msg_id); + tglu_work_update_short (c, msg_id); return; case CODE_updates: - work_updates (c, msg_id); + tglu_work_updates (c, msg_id); return; case CODE_update_short_message: - work_update_short_message (c, msg_id); + tglu_work_update_short_message (c, msg_id); return; case CODE_update_short_chat_message: - work_update_short_chat_message (c, msg_id); + tglu_work_update_short_chat_message (c, msg_id); return; case CODE_gzip_packed: work_packed (c, msg_id); @@ -1632,7 +914,7 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { work_new_detailed_info (c, msg_id); return; case CODE_updates_too_long: - work_updates_to_long (c, msg_id); + tglu_work_updates_to_long (c, msg_id); return; case CODE_bad_msg_notification: work_bad_msg_notification (c, msg_id); @@ -1642,12 +924,12 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { 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) { +static 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); vlogprintf (E_DEBUG, "process_rpc_message(), len=%d\n", len); assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15)); - struct dc *DC = GET_DC(c); + struct dc *DC = tgl_state.net_methods->get_dc (c); assert (enc->auth_key_id == DC->auth_key_id); assert (DC->auth_key_id); init_aes_auth (DC->auth_key + 8, enc->msg_key, AES_DECRYPT); @@ -1661,7 +943,7 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, //assert (enc->server_salt == server_salt); //in fact server salt can change if (DC->server_salt != enc->server_salt) { DC->server_salt = enc->server_salt; - write_auth_file (); + //write_auth_file (); } int this_server_time = enc->msg_id >> 32LL; @@ -1678,10 +960,7 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, assert (this_server_time >= st - 300 && this_server_time <= st + 30); //assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1); - if (verbosity >= 1) { - logprintf ( "received mesage id %016llx\n", enc->msg_id); - hexdump_in (); - } + vlogprintf (E_DEBUG, "received mesage id %016llx\n", enc->msg_id); server_last_msg_id = enc->msg_id; //*(long long *)(longpoll_query + 3) = *(long long *)((char *)(&enc->msg_id) + 0x3c); @@ -1694,77 +973,72 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, in_ptr = enc->message; in_end = in_ptr + (enc->msg_len / 4); + struct session *S = tgl_state.net_methods->get_session (c); if (enc->msg_id & 1) { - insert_msg_id (c->session, enc->msg_id); + tgln_insert_msg_id (S, enc->msg_id); } - assert (c->session->session_id == enc->session_id); + assert (S->session_id == enc->session_id); rpc_execute_answer (c, enc->msg_id); assert (in_ptr == in_end); return 0; } -int rpc_execute (struct connection *c, int op, int len) { - if (verbosity) { - logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len); - } +static int rpc_execute (struct connection *c, int op, int len) { + vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d : received rpc answer %d with %d content bytes\n", tgl_state.net_methods->get_dc(c)->id, op, len); /* if (op < 0) { - assert (read_in (c, Response, Response_len) == Response_len); + assert (tgl_state.net_methods->read_in (c, Response, Response_len) == Response_len); return 0; }*/ if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) { - logprintf ( "answer too long (%d bytes), skipping\n", len); + vlogprintf (E_WARNING, "answer too long (%d bytes), skipping\n", len); return 0; } int Response_len = len; - if (verbosity >= 2) { - logprintf ("Response_len = %d\n", Response_len); - } - assert (read_in (c, Response, Response_len) == Response_len); + vlogprintf (E_DEBUG, "Response_len = %d\n", Response_len); + assert (tgl_state.net_methods->read_in (c, Response, Response_len) == Response_len); Response[Response_len] = 0; - if (verbosity >= 2) { - logprintf ( "have %d Response bytes\n", Response_len); - } #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); +// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif - int o = c_state; - if (GET_DC(c)->flags & 1) { o = st_authorized;} + struct dc *D = tgl_state.net_methods->get_dc (c); + int o = D->state; + if (D->flags & 1) { o = st_authorized;} switch (o) { case st_reqpq_sent: process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/); #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); +// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif return 0; case st_reqdh_sent: process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/); #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); +// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif return 0; case st_client_dh_sent: process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/); #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); +// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif return 0; case st_authorized: if (op < 0 && op >= -999) { - logprintf ("Server error %d\n", op); + vlogprintf (E_WARNING, "Server error %d\n", op); } else { process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/); } #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); +// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif return 0; default: - logprintf ( "fatal: cannot receive answer in state %d\n", c_state); + vlogprintf (E_ERROR, "fatal: cannot receive answer in state %d\n", c_state); exit (2); } @@ -1772,60 +1046,50 @@ int rpc_execute (struct connection *c, int op, int len) { } -int tc_close (struct connection *c, int who) { - if (verbosity) { - logprintf ( "outbound http connection #%d : closing by %d\n", c->fd, who); - } +static int tc_close (struct connection *c, int who) { + vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d : closing by %d\n", tgl_state.net_methods->get_dc(c)->id, who); return 0; } -int tc_becomes_ready (struct connection *c) { - if (verbosity) { - logprintf ( "outbound connection #%d becomes ready\n", c->fd); - } +static int tc_becomes_ready (struct connection *c) { + vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d becomed ready\n", tgl_state.net_methods->get_dc(c)->id); char byte = 0xef; - assert (write_out (c, &byte, 1) == 1); - flush_out (c); + assert (tgl_state.net_methods->write_out (c, &byte, 1) == 1); + tgl_state.net_methods->flush_out (c); #if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); +// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); #endif - int o = c_state; - if (GET_DC(c)->flags & 1) { o = st_authorized; } + struct dc *D = tgl_state.net_methods->get_dc (c); + int o = D->state; + if (D->flags & 1) { o = st_authorized; } switch (o) { case st_init: send_req_pq_packet (c); break; - case st_authorized: - auth_work_start (c); - break; default: - logprintf ( "c_state = %d\n", c_state); + vlogprintf (E_DEBUG, "c_state = %d\n", c_state); assert (0); } return 0; } -int rpc_becomes_ready (struct connection *c) { +static int rpc_becomes_ready (struct connection *c) { return tc_becomes_ready (c); } -int rpc_close (struct connection *c) { +static int rpc_close (struct connection *c) { return tc_close (c, 0); } -int auth_is_success (void) { - return auth_success; -} - #define RANDSEED_PASSWORD_FILENAME NULL #define RANDSEED_PASSWORD_LENGTH 0 -void on_start (void) { +void tglmp_on_start (const char *key) { prng_seed (RANDSEED_PASSWORD_FILENAME, RANDSEED_PASSWORD_LENGTH); - if (rsa_public_key_name) { - if (rsa_load_public_key (rsa_public_key_name) < 0) { + if (key) { + if (rsa_load_public_key (key) < 0) { perror ("rsa_load_public_key"); exit (1); } @@ -1839,18 +1103,87 @@ void on_start (void) { pk_fingerprint = compute_rsa_key_fingerprint (pubKey); } -int auth_ok (void) { - return auth_success; +//int auth_ok (void) { +// return auth_success; +//} + +void tgl_dc_authorize (struct dc *DC) { + //c_state = 0; + //auth_success = 0; + if (!DC->sessions[0]) { + tglmp_dc_create_session (DC); + } + vlogprintf (E_DEBUG, "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port); + //net_loop (0, auth_ok); } -void dc_authorize (struct dc *DC) { - c_state = 0; - auth_success = 0; - if (!DC->sessions[0]) { - dc_create_session (DC); +#define long_cmp(a,b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1) +DEFINE_TREE(long,long long,long_cmp,0) + +static int send_all_acks (struct session *S) { + clear_packet (); + out_int (CODE_msgs_ack); + out_int (CODE_vector); + out_int (tree_count_long (S->ack_tree)); + while (S->ack_tree) { + long long x = tree_get_min_long (S->ack_tree); + out_long (x); + S->ack_tree = tree_delete_long (S->ack_tree, x); } - if (verbosity) { - logprintf ( "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port); - } - net_loop (0, auth_ok); + tglmp_encrypt_send_message (S->c, packet_buffer, packet_ptr - packet_buffer, 0); + return 0; +} + +static void send_all_acks_gateway (evutil_socket_t fd, short what, void *arg) { + send_all_acks (arg); +} + + +void tgln_insert_msg_id (struct session *S, long long id) { + if (!S->ack_tree) { + static struct timeval ptimeout = { ACK_TIMEOUT, 0}; + event_add (S->ev, &ptimeout); + } + if (!tree_lookup_long (S->ack_tree, id)) { + S->ack_tree = tree_insert_long (S->ack_tree, id, lrand48 ()); + } +} + +//extern struct dc *DC_list[]; + +struct dc *tglmp_alloc_dc (int id, char *ip, int port UU) { + assert (!tgl_state.DC_list[id]); + struct dc *DC = talloc0 (sizeof (*DC)); + DC->id = id; + DC->ip = ip; + DC->port = port; + tgl_state.DC_list[id] = DC; + return DC; +} + +static struct mtproto_methods mtproto_methods = { + .execute = rpc_execute, + .ready = rpc_becomes_ready, + .close = rpc_close +}; + +void tglmp_dc_create_session (struct dc *DC) { + struct session *S = talloc0 (sizeof (*S)); + assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0); + S->dc = DC; + S->c = tgl_state.net_methods->create_connection (DC->ip, DC->port, DC, S, &mtproto_methods); + if (!S->c) { + vlogprintf (E_DEBUG, "Can not create connection to DC. Is network down?\n"); + exit (1); + } + S->ev = evtimer_new (tgl_state.ev_base, send_all_acks_gateway, S); + assert (!DC->sessions[0]); + DC->sessions[0] = S; +} + +void tgl_do_send_ping (struct connection *c) { + int x[3]; + x[0] = CODE_ping; + *(long long *)(x + 1) = lrand48 () * (1ll << 32) + lrand48 (); + tglmp_encrypt_send_message (c, x, 3, 0); } diff --git a/mtproto-client.h b/mtproto-client.h index 0782b7b..b4bd80c 100644 --- a/mtproto-client.h +++ b/mtproto-client.h @@ -19,15 +19,76 @@ */ #ifndef __MTPROTO_CLIENT_H__ #define __MTPROTO_CLIENT_H__ -#include "net.h" +//#include "net.h" #include -void on_start (void); -long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful); -void dc_authorize (struct dc *DC); -void work_update (struct connection *c, long long msg_id); -void work_update_binlog (void); -int check_g (unsigned char p[256], BIGNUM *g); -int check_g_bn (BIGNUM *p, BIGNUM *g); -int check_DH_params (BIGNUM *p, int g); -void secure_random (void *s, int l); +//void on_start (void); +//..long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful); +//void dc_authorize (struct dc *DC); +//void work_update (struct connection *c, long long msg_id); +//void work_update_binlog (void); +//int check_g (unsigned char p[256], BIGNUM *g); +//int check_g_bn (BIGNUM *p, BIGNUM *g); +//int check_DH_params (BIGNUM *p, int g); +//void secure_random (void *s, int l); + +struct connection; +struct dc; +//#include "queries.h" +#define TG_SERVER "173.240.5.1" +#define TG_SERVER_TEST "173.240.5.253" +#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74" +#define TG_APP_ID 2899 + +#define ACK_TIMEOUT 1 +#define MAX_DC_ID 10 + +struct connection; + +enum dc_state { + st_init, + st_reqpq_sent, + st_reqdh_sent, + st_client_dh_sent, + st_authorized, + st_error +}; + +#define MAX_DC_SESSIONS 3 + +struct session { + struct dc *dc; + long long session_id; + int seq_no; + struct connection *c; + struct tree_long *ack_tree; + struct event *ev; + //struct event_timer ev; +}; + +struct dc { + int id; + int port; + int flags; + enum dc_state state; + char *ip; + char *user; + struct session *sessions[MAX_DC_SESSIONS]; + char auth_key[256]; + long long auth_key_id; + long long server_salt; + + int server_time_delta; + double server_time_udelta; + int has_auth; +}; + +long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful); +void tglmp_dc_create_session (struct dc *DC); +int tglmp_check_g (unsigned char p[256], BIGNUM *g); +int tglmp_check_DH_params (BIGNUM *p, int g); +struct dc *tglmp_alloc_dc (int id, char *ip, int port); + +void tgln_insert_msg_id (struct session *S, long long id); +void tglmp_on_start (const char *key); +void tgl_dc_authorize (struct dc *DC); #endif diff --git a/mtproto-common.c b/mtproto-common.c index 74650ae..fa0ab04 100644 --- a/mtproto-common.c +++ b/mtproto-common.c @@ -53,9 +53,9 @@ int *packet_buffer = __packet_buffer + 16; long long rsa_encrypted_chunks, rsa_decrypted_chunks; BN_CTX *BN_ctx; -int verbosity; +//int verbosity; -int get_random_bytes (unsigned char *buf, int n) { +static int get_random_bytes (unsigned char *buf, int n) { int r = 0, h = open ("/dev/random", O_RDONLY | O_NONBLOCK); if (h >= 0) { r = read (h, buf, n); @@ -87,20 +87,6 @@ int get_random_bytes (unsigned char *buf, int n) { return r; } -void my_clock_gettime (int clock_id UU, struct timespec *T) { -#ifdef __MACH__ - // We are ignoring MONOTONIC and hope time doesn't go back too often - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - T->tv_sec = mts.tv_sec; - T->tv_nsec = mts.tv_nsec; -#else - assert (clock_gettime(clock_id, T) >= 0); -#endif -} /* RDTSC */ #if defined(__i386__) diff --git a/mtproto-common.h b/mtproto-common.h index 439860a..a897cb0 100644 --- a/mtproto-common.h +++ b/mtproto-common.h @@ -25,12 +25,14 @@ #include #include #include +#include //#include "interface.h" #include "tools.h" #include "auto/constants.h" #include "tgl.h" +#include "tgl-inner.h" /* DH key exchange protocol data structures */ #define CODE_req_pq 0x60469778 #define CODE_resPQ 0x05162463 @@ -157,10 +159,10 @@ static inline void out_bignum (BIGNUM *n) { extern int *in_ptr, *in_end; -void fetch_pts (void); -void fetch_qts (void); -void fetch_date (void); -void fetch_seq (void); +//void fetch_pts (void); +//void fetch_qts (void); +//void fetch_date (void); +//void fetch_seq (void); static inline int prefetch_strlen (void) { if (in_ptr >= in_end) { return -1; @@ -331,7 +333,7 @@ static inline void fetch256 (void *buf) { } } -int get_random_bytes (unsigned char *buf, int n); +//int get_random_bytes (unsigned char *buf, int n); int pad_rsa_encrypt (char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E); int pad_rsa_decrypt (char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *D); diff --git a/net.c b/net.c index 881f670..16ff6c9 100644 --- a/net.c +++ b/net.c @@ -37,81 +37,73 @@ #include #include #include +#include +#include +#include #include "net.h" #include "include.h" -#include "mtproto-client.h" -#include "mtproto-common.h" +#include "tgl.h" +#include "tgl-inner.h" +//#include "mtproto-client.h" +//#include "mtproto-common.h" #include "tree.h" -#include "interface.h" #ifndef POLLRDHUP #define POLLRDHUP 0 #endif -#define long_cmp(a,b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1) -DEFINE_TREE(long,long long,long_cmp,0) -double get_utime (int clock_id); +//double get_utime (int clock_id); -int verbosity; -extern struct connection_methods auth_methods; -extern FILE *log_net_f; +//extern struct mtproto_methods auth_methods; -void fail_connection (struct connection *c); +static void fail_connection (struct connection *c); #define PING_TIMEOUT 10 -void start_ping_timer (struct connection *c); -int ping_alarm (struct connection *c) { - if (verbosity > 2) { - logprintf ("ping alarm\n"); - } +static void start_ping_timer (struct connection *c); +static void ping_alarm (evutil_socket_t fd, short what, void *arg) { + struct connection *c = arg; + vlogprintf (E_DEBUG + 2,"ping alarm\n"); assert (c->state == conn_ready || c->state == conn_connecting); if (get_double_time () - c->last_receive_time > 20 * PING_TIMEOUT) { - if (verbosity) { - logprintf ( "fail connection: reason: ping timeout\n"); - } + vlogprintf (E_WARNING, "fail connection: reason: ping timeout\n"); c->state = conn_failed; fail_connection (c); } else if (get_double_time () - c->last_receive_time > 5 * PING_TIMEOUT && c->state == conn_ready) { - int x[3]; - x[0] = CODE_ping; - *(long long *)(x + 1) = lrand48 () * (1ll << 32) + lrand48 (); - encrypt_send_message (c, x, 3, 0); + tgl_do_send_ping (c); start_ping_timer (c); } else { start_ping_timer (c); } - return 0; } -void stop_ping_timer (struct connection *c) { - remove_event_timer (&c->ev); +static void stop_ping_timer (struct connection *c) { + event_del (c->ping_ev); } -void start_ping_timer (struct connection *c) { - c->ev.timeout = get_double_time () + PING_TIMEOUT; - c->ev.alarm = (void *)ping_alarm; - c->ev.self = c; - insert_event_timer (&c->ev); +static void start_ping_timer (struct connection *c) { + static struct timeval ptimeout = { PING_TIMEOUT, 0}; + event_add (c->ping_ev, &ptimeout); } -void restart_connection (struct connection *c); -int fail_alarm (void *ev) { - ((struct connection *)ev)->in_fail_timer = 0; - restart_connection (ev); - return 0; +static void restart_connection (struct connection *c); + +static void fail_alarm (evutil_socket_t fd, short what, void *arg) { + struct connection *c = arg; + c->in_fail_timer = 0; + restart_connection (c); } -void start_fail_timer (struct connection *c) { + +static void start_fail_timer (struct connection *c) { if (c->in_fail_timer) { return; } c->in_fail_timer = 1; - c->ev.timeout = get_double_time () + 10; - c->ev.alarm = (void *)fail_alarm; - c->ev.self = c; - insert_event_timer (&c->ev); + + static struct timeval ptimeout = { 10, 0}; + event_add (c->fail_ev, &ptimeout); } -struct connection_buffer *new_connection_buffer (int size) { +static struct connection_buffer *new_connection_buffer (int size) { struct connection_buffer *b = talloc0 (sizeof (*b)); b->start = talloc (size); b->end = b->start + size; @@ -119,16 +111,19 @@ struct connection_buffer *new_connection_buffer (int size) { return b; } -void delete_connection_buffer (struct connection_buffer *b) { +static void delete_connection_buffer (struct connection_buffer *b) { tfree (b->start, b->end - b->start); tfree (b, sizeof (*b)); } -int write_out (struct connection *c, const void *_data, int len) { +int tgln_write_out (struct connection *c, const void *_data, int len) { const unsigned char *data = _data; if (!len) { return 0; } assert (len > 0); int x = 0; + if (!c->out_bytes) { + event_add (c->write_ev, 0); + } if (!c->out_head) { struct connection_buffer *b = new_connection_buffer (1 << 20); c->out_head = c->out_tail = b; @@ -156,7 +151,7 @@ int write_out (struct connection *c, const void *_data, int len) { return x; } -int read_in (struct connection *c, void *_data, int len) { +int tgln_read_in (struct connection *c, void *_data, int len) { unsigned char *data = _data; if (!len) { return 0; } assert (len > 0); @@ -188,7 +183,7 @@ int read_in (struct connection *c, void *_data, int len) { return x; } -int read_in_lookup (struct connection *c, void *_data, int len) { +int tgln_read_in_lookup (struct connection *c, void *_data, int len) { unsigned char *data = _data; if (!len || !c->in_bytes) { return 0; } assert (len > 0); @@ -213,14 +208,14 @@ int read_in_lookup (struct connection *c, void *_data, int len) { return x; } -void flush_out (struct connection *c UU) { +void tgln_flush_out (struct connection *c UU) { } #define MAX_CONNECTIONS 100 -struct connection *Connections[MAX_CONNECTIONS]; -int max_connection_fd; +static struct connection *Connections[MAX_CONNECTIONS]; +static int max_connection_fd; -void rotate_port (struct connection *c) { +static void rotate_port (struct connection *c) { switch (c->port) { case 443: c->port = 80; @@ -234,11 +229,26 @@ void rotate_port (struct connection *c) { } } -struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods) { +static void try_read (struct connection *c); +static void try_write (struct connection *c); + +static void conn_try_read (evutil_socket_t fd, short what, void *arg) { + struct connection *c = arg; + try_read (c); +} +static void conn_try_write (evutil_socket_t fd, short what, void *arg) { + struct connection *c = arg; + try_write (c); + if (c->out_bytes) { + event_add (c->write_ev, 0); + } +} + +struct connection *tgln_create_connection (const char *host, int port, struct session *session, struct mtproto_methods *methods) { struct connection *c = talloc0 (sizeof (*c)); int fd = socket (AF_INET, SOCK_STREAM, 0); if (fd == -1) { - logprintf ("Can not create socket: %m\n"); + vlogprintf (E_ERROR, "Can not create socket: %m\n"); exit (1); } assert (fd >= 0 && fd < MAX_CONNECTIONS); @@ -260,51 +270,38 @@ struct connection *create_connection (const char *host, int port, struct session if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) { if (errno != EINPROGRESS) { - logprintf ( "Can not connect to %s:%d %m\n", host, port); + vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port); close (fd); tfree (c, sizeof (*c)); return 0; } } - struct pollfd s; - s.fd = fd; - s.events = POLLOUT | POLLERR | POLLRDHUP | POLLHUP; - errno = 0; - - while (poll (&s, 1, 10000) <= 0 || !(s.revents & POLLOUT)) { - if (errno == EINTR) { continue; } - if (errno) { - logprintf ("Problems in poll: %m\n"); - exit (1); - } - logprintf ("Connect with %s:%d timeout\n", host, port); - close (fd); - tfree (c, sizeof (*c)); - return 0; - } - - c->session = session; - c->fd = fd; + c->fd = fd; + c->state = conn_connecting; + c->last_receive_time = get_double_time (); c->ip = tstrdup (host); c->flags = 0; - c->state = conn_ready; - c->methods = methods; c->port = port; assert (!Connections[fd]); Connections[fd] = c; - if (verbosity) { - logprintf ( "connect to %s:%d successful\n", host, port); - } - if (c->methods->ready) { - c->methods->ready (c); - } - c->last_receive_time = get_double_time (); + + c->ping_ev = evtimer_new (tgl_state.ev_base, ping_alarm, c); + c->fail_ev = evtimer_new (tgl_state.ev_base, fail_alarm, c); + c->read_ev = event_new (tgl_state.ev_base, c->fd, EV_READ | EV_PERSIST, conn_try_read, c); + c->write_ev = event_new (tgl_state.ev_base, c->fd, EV_WRITE, conn_try_write, c); + event_add (c->read_ev, 0); + start_ping_timer (c); + + char byte = 0xef; + assert (tgln_write_out (c, &byte, 1) == 1); + tgln_flush_out (c); + return c; } -void restart_connection (struct connection *c) { +static void restart_connection (struct connection *c) { if (c->last_connect_time == time (0)) { start_fail_timer (c); return; @@ -313,7 +310,7 @@ void restart_connection (struct connection *c) { c->last_connect_time = time (0); int fd = socket (AF_INET, SOCK_STREAM, 0); if (fd == -1) { - logprintf ("Can not create socket: %m\n"); + vlogprintf (E_ERROR, "Can not create socket: %m\n"); exit (1); } assert (fd >= 0 && fd < MAX_CONNECTIONS); @@ -335,7 +332,7 @@ void restart_connection (struct connection *c) { if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) { if (errno != EINPROGRESS) { - logprintf ( "Can not connect to %s:%d %m\n", c->ip, c->port); + vlogprintf (E_WARNING, "Can not connect to %s:%d %m\n", c->ip, c->port); start_fail_timer (c); close (fd); return; @@ -349,14 +346,15 @@ void restart_connection (struct connection *c) { Connections[fd] = c; char byte = 0xef; - assert (write_out (c, &byte, 1) == 1); - flush_out (c); + assert (tgln_write_out (c, &byte, 1) == 1); + tgln_flush_out (c); } -void fail_connection (struct connection *c) { +static void fail_connection (struct connection *c) { if (c->state == conn_ready || c->state == conn_connecting) { stop_ping_timer (c); } + event_del (c->write_ev); rotate_port (c); struct connection_buffer *b = c->out_head; while (b) { @@ -375,19 +373,17 @@ void fail_connection (struct connection *c) { c->out_bytes = c->in_bytes = 0; close (c->fd); Connections[c->fd] = 0; - logprintf ("Lost connection to server... %s:%d\n", c->ip, c->port); + vlogprintf (E_NOTICE, "Lost connection to server... %s:%d\n", c->ip, c->port); restart_connection (c); } -extern FILE *log_net_f; -void try_write (struct connection *c) { - if (verbosity) { - logprintf ( "try write: fd = %d\n", c->fd); - } +//extern FILE *log_net_f; +static void try_write (struct connection *c) { + vlogprintf (E_DEBUG, "try write: fd = %d\n", c->fd); int x = 0; while (c->out_head) { int r = write (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr); - if (r > 0 && log_net_f) { + /*if (r > 0 && log_net_f) { fprintf (log_net_f, "%.02lf %d OUT %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port); int i; for (i = 0; i < r; i++) { @@ -395,7 +391,7 @@ void try_write (struct connection *c) { } fprintf (log_net_f, "\n"); fflush (log_net_f); - } + }*/ if (r >= 0) { x += r; c->out_head->rptr += r; @@ -410,9 +406,7 @@ void try_write (struct connection *c) { delete_connection_buffer (b); } else { if (errno != EAGAIN && errno != EWOULDBLOCK) { - if (verbosity) { - logprintf ("fail_connection: write_error %m\n"); - } + vlogprintf (E_NOTICE, "fail_connection: write_error %m\n"); fail_connection (c); return; } else { @@ -420,13 +414,11 @@ void try_write (struct connection *c) { } } } - if (verbosity) { - logprintf ( "Sent %d bytes to %d\n", x, c->fd); - } + vlogprintf (E_DEBUG, "Sent %d bytes to %d\n", x, c->fd); c->out_bytes -= x; } -void hexdump_buf (struct connection_buffer *b) { +/*static void hexdump_buf (struct connection_buffer *b) { int pos = 0; int rem = 8; while (b) { @@ -448,57 +440,52 @@ void hexdump_buf (struct connection_buffer *b) { } printf ("\n"); -} +}*/ -void try_rpc_read (struct connection *c) { +static void try_rpc_read (struct connection *c) { assert (c->in_head); - if (verbosity >= 3) { - hexdump_buf (c->in_head); - } while (1) { if (c->in_bytes < 1) { return; } unsigned len = 0; unsigned t = 0; - assert (read_in_lookup (c, &len, 1) == 1); + assert (tgln_read_in_lookup (c, &len, 1) == 1); if (len >= 1 && len <= 0x7e) { if (c->in_bytes < (int)(1 + 4 * len)) { return; } } else { if (c->in_bytes < 4) { return; } - assert (read_in_lookup (c, &len, 4) == 4); + assert (tgln_read_in_lookup (c, &len, 4) == 4); len = (len >> 8); if (c->in_bytes < (int)(4 + 4 * len)) { return; } len = 0x7f; } if (len >= 1 && len <= 0x7e) { - assert (read_in (c, &t, 1) == 1); + assert (tgln_read_in (c, &t, 1) == 1); assert (t == len); assert (len >= 1); } else { assert (len == 0x7f); - assert (read_in (c, &len, 4) == 4); + assert (tgln_read_in (c, &len, 4) == 4); len = (len >> 8); assert (len >= 1); } len *= 4; int op; - assert (read_in_lookup (c, &op, 4) == 4); + assert (tgln_read_in_lookup (c, &op, 4) == 4); c->methods->execute (c, op, len); } } -void try_read (struct connection *c) { - if (verbosity) { - logprintf ( "try read: fd = %d\n", c->fd); - } +static void try_read (struct connection *c) { + vlogprintf (E_DEBUG, "try read: fd = %d\n", c->fd); if (!c->in_tail) { c->in_head = c->in_tail = new_connection_buffer (1 << 20); } int x = 0; while (1) { int r = read (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr); - if (r > 0 && log_net_f) { + /*if (r > 0 && log_net_f) { fprintf (log_net_f, "%.02lf %d IN %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port); int i; for (i = 0; i < r; i++) { @@ -506,7 +493,7 @@ void try_read (struct connection *c) { } fprintf (log_net_f, "\n"); fflush (log_net_f); - } + }*/ if (r > 0) { c->last_receive_time = get_double_time (); stop_ping_timer (c); @@ -523,9 +510,7 @@ void try_read (struct connection *c) { c->in_tail = b; } else { if (errno != EAGAIN && errno != EWOULDBLOCK) { - if (verbosity) { - logprintf ("fail_connection: read_error %m\n"); - } + vlogprintf (E_NOTICE, "fail_connection: read_error %m\n"); fail_connection (c); return; } else { @@ -533,16 +518,14 @@ void try_read (struct connection *c) { } } } - if (verbosity) { - logprintf ( "Received %d bytes from %d\n", x, c->fd); - } + vlogprintf (E_DEBUG, "Received %d bytes from %d\n", x, c->fd); c->in_bytes += x; if (x) { try_rpc_read (c); } } -int connections_make_poll_array (struct pollfd *fds, int max) { +int tgl_connections_make_poll_array (struct pollfd *fds, int max) { int _max = max; int i; for (i = 0; i <= max_connection_fd; i++) { @@ -561,16 +544,10 @@ int connections_make_poll_array (struct pollfd *fds, int max) { max --; } } - if (verbosity >= 10) { - logprintf ( "%d connections in poll\n", _max - max); - } return _max - max; } -void connections_poll_result (struct pollfd *fds, int max) { - if (verbosity >= 10) { - logprintf ( "connections_poll_result: max = %d\n", max); - } +void tgl_connections_poll_result (struct pollfd *fds, int max) { int i; for (i = 0; i < max; i++) { struct connection *c = Connections[fds[i].fd]; @@ -578,13 +555,11 @@ void connections_poll_result (struct pollfd *fds, int max) { try_read (c); } if (fds[i].revents & (POLLHUP | POLLERR | POLLRDHUP)) { - if (verbosity) { - logprintf ("fail_connection: events_mask=0x%08x\n", fds[i].revents); - } + vlogprintf (E_NOTICE, "fail_connection: events_mask=0x%08x\n", fds[i].revents); fail_connection (c); } else if (fds[i].revents & POLLOUT) { if (c->state == conn_connecting) { - logprintf ("connection ready\n"); + vlogprintf (E_DEBUG, "connection ready\n"); c->state = conn_ready; c->last_receive_time = get_double_time (); } @@ -594,54 +569,3 @@ void connections_poll_result (struct pollfd *fds, int max) { } } } - -int send_all_acks (struct session *S) { - clear_packet (); - out_int (CODE_msgs_ack); - out_int (CODE_vector); - out_int (tree_count_long (S->ack_tree)); - while (S->ack_tree) { - long long x = tree_get_min_long (S->ack_tree); - out_long (x); - S->ack_tree = tree_delete_long (S->ack_tree, x); - } - encrypt_send_message (S->c, packet_buffer, packet_ptr - packet_buffer, 0); - return 0; -} - -void insert_msg_id (struct session *S, long long id) { - if (!S->ack_tree) { - S->ev.alarm = (void *)send_all_acks; - S->ev.self = (void *)S; - S->ev.timeout = get_double_time () + ACK_TIMEOUT; - insert_event_timer (&S->ev); - } - if (!tree_lookup_long (S->ack_tree, id)) { - S->ack_tree = tree_insert_long (S->ack_tree, id, lrand48 ()); - } -} - -extern struct dc *DC_list[]; - -struct dc *alloc_dc (int id, char *ip, int port UU) { - assert (!DC_list[id]); - struct dc *DC = talloc0 (sizeof (*DC)); - DC->id = id; - DC->ip = ip; - DC->port = port; - DC_list[id] = DC; - return DC; -} - -void dc_create_session (struct dc *DC) { - struct session *S = talloc0 (sizeof (*S)); - assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0); - S->dc = DC; - S->c = create_connection (DC->ip, DC->port, S, &auth_methods); - if (!S->c) { - logprintf ("Can not create connection to DC. Is network down?\n"); - exit (1); - } - assert (!DC->sessions[0]); - DC->sessions[0] = S; -} diff --git a/net.h b/net.h index 1a47574..563bdb5 100644 --- a/net.h +++ b/net.h @@ -20,59 +20,6 @@ #define __NET_H__ #include -struct dc; -#include "queries.h" -#define TG_SERVER "173.240.5.1" -#define TG_SERVER_TEST "173.240.5.253" -#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74" -#define TG_APP_ID 2899 - -#define ACK_TIMEOUT 1 -#define MAX_DC_ID 10 - -enum dc_state { - st_init, - st_reqpq_sent, - st_reqdh_sent, - st_client_dh_sent, - st_authorized, - st_error -} ; - -struct connection; -struct connection_methods { - int (*ready) (struct connection *c); - int (*close) (struct connection *c); - int (*execute) (struct connection *c, int op, int len); -}; - - -#define MAX_DC_SESSIONS 3 - -struct session { - struct dc *dc; - long long session_id; - int seq_no; - struct connection *c; - struct tree_long *ack_tree; - struct event_timer ev; -}; - -struct dc { - int id; - int port; - int flags; - char *ip; - char *user; - struct session *sessions[MAX_DC_SESSIONS]; - char auth_key[256]; - long long auth_key_id; - long long server_salt; - - int server_time_delta; - double server_time_udelta; - int has_auth; -}; #define DC_SERIALIZED_MAGIC 0x64582faa #define DC_SERIALIZED_MAGIC_V2 0x94032abb @@ -122,27 +69,32 @@ struct connection { int out_packet_num; int last_connect_time; int in_fail_timer; - struct connection_methods *methods; + struct mtproto_methods *methods; struct session *session; void *extra; - struct event_timer ev; + struct event *ping_ev; + struct event *fail_ev; + struct event *read_ev; + struct event *write_ev; double last_receive_time; }; -extern struct connection *Connections[]; +//extern struct connection *Connections[]; -int write_out (struct connection *c, const void *data, int len); -void flush_out (struct connection *c); -int read_in (struct connection *c, void *data, int len); +int tgln_write_out (struct connection *c, const void *data, int len); +void tgln_flush_out (struct connection *c); +int tgln_read_in (struct connection *c, void *data, int len); +int tgln_read_in_lookup (struct connection *c, void *data, int len); -void create_all_outbound_connections (void); +void tgln_insert_msg_id (struct session *S, long long id); -struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods); -int connections_make_poll_array (struct pollfd *fds, int max); -void connections_poll_result (struct pollfd *fds, int max); -void dc_create_session (struct dc *DC); -void insert_msg_id (struct session *S, long long id); -struct dc *alloc_dc (int id, char *ip, int port); + +//void create_all_outbound_connections (void); + +//struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods); +struct dc *tgln_alloc_dc (int id, char *ip, int port); +void tgln_dc_create_session (struct dc *DC, struct mtproto_methods *methods); +struct connection *tgln_create_connection (const char *host, int port, struct session *session, struct mtproto_methods *methods); #define GET_DC(c) (c->session->dc) #endif diff --git a/queries.c b/queries.c index bcecd9b..0a30112 100644 --- a/queries.c +++ b/queries.c @@ -44,7 +44,7 @@ #include "loop.h" #include "structures.h" //#include "interface.h" -#include "net.h" +//#include "net.h" #include #include #include @@ -53,8 +53,10 @@ #include "no-preview.h" #include "binlog.h" +#include "updates.h" #include "auto.h" #include "tgl.h" +#include #define sha1 SHA1 @@ -85,25 +87,23 @@ static void out_peer_id (tgl_peer_id_t id); DEFINE_TREE (query, struct query *, memcmp8, 0) ; struct tree_query *queries_tree; -double get_double_time (void) { - struct timespec tv; - my_clock_gettime (CLOCK_REALTIME, &tv); - return tv.tv_sec + 1e-9 * tv.tv_nsec; -} - -struct query *query_get (long long id) { +struct query *tglq_query_get (long long id) { return tree_lookup_query (queries_tree, (void *)&id); } -int alarm_query (struct query *q) { +static int alarm_query (struct query *q) { assert (q); vlogprintf (E_DEBUG, "Alarm query %lld\n", q->msg_id); - q->ev.timeout = get_double_time () + QUERY_TIMEOUT; - insert_event_timer (&q->ev); + //q->ev.timeout = get_double_time () + QUERY_TIMEOUT; + //insert_event_timer (&q->ev); + + + static struct timeval ptimeout = { QUERY_TIMEOUT, 0}; + event_add (q->ev, &ptimeout); - if (q->session->c->out_bytes >= 100000) { + /*if (q->session->c->out_bytes >= 100000) { return 0; - } + }*/ clear_packet (); out_int (CODE_msg_container); @@ -113,30 +113,35 @@ int alarm_query (struct query *q) { out_int (4 * q->data_len); out_ints (q->data, q->data_len); - encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, 0); + tglmp_encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, 0); return 0; } -void query_restart (long long id) { - struct query *q = query_get (id); +void tglq_query_restart (long long id) { + struct query *q = tglq_query_get (id); if (q) { - remove_event_timer (&q->ev); + event_del (q->ev); alarm_query (q); } } -struct query *send_query (struct dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) { +static void alarm_query_gateway (evutil_socket_t fd, short what, void *arg) { + alarm_query (arg); +} + + +struct query *tglq_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); + tglmp_dc_create_session (DC); } 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); memcpy (q->data, data, 4 * ints); - q->msg_id = encrypt_send_message (DC->sessions[0]->c, data, ints, 1); + q->msg_id = tglmp_encrypt_send_message (DC->sessions[0]->c, data, ints, 1); q->session = DC->sessions[0]; q->seq_no = DC->sessions[0]->seq_no - 1; vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q); @@ -147,10 +152,14 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth } queries_tree = tree_insert_query (queries_tree, q, lrand48 ()); - q->ev.alarm = (void *)alarm_query; - q->ev.timeout = get_double_time () + QUERY_TIMEOUT; - q->ev.self = (void *)q; - insert_event_timer (&q->ev); + //q->ev.alarm = (void *)alarm_query; + //q->ev.timeout = get_double_time () + QUERY_TIMEOUT; + //q->ev.self = (void *)q; + //insert_event_timer (&q->ev); + + q->ev = evtimer_new (tgl_state.ev_base, alarm_query_gateway, q); + static struct timeval ptimeout = { QUERY_TIMEOUT, 0}; + event_add (q->ev, &ptimeout); q->extra = extra; q->callback = callback; @@ -165,27 +174,27 @@ static int fail_on_error (struct query *q UU, int error_code UU, int l UU, char return 0; } -void query_ack (long long id) { - struct query *q = query_get (id); +void tglq_query_ack (long long id) { + struct query *q = tglq_query_get (id); if (q && !(q->flags & QUERY_ACK_RECEIVED)) { assert (q->msg_id == id); q->flags |= QUERY_ACK_RECEIVED; - remove_event_timer (&q->ev); + event_del (q->ev); } } -void query_error (long long id) { +void tglq_query_error (long long id) { assert (fetch_int () == CODE_rpc_error); int error_code = fetch_int (); int error_len = prefetch_strlen (); char *error = fetch_str (error_len); vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); - struct query *q = query_get (id); + struct query *q = tglq_query_get (id); if (!q) { vlogprintf (E_WARNING, "No such query\n"); } else { if (!(q->flags & QUERY_ACK_RECEIVED)) { - remove_event_timer (&q->ev); + event_del (q->ev); } queries_tree = tree_delete_query (queries_tree, q); if (q->methods && q->methods->on_error) { @@ -194,6 +203,7 @@ void query_error (long long id) { vlogprintf ( E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error); } tfree (q->data, q->data_len * 4); + event_free (q->ev); tfree (q, sizeof (*q)); } queries_num --; @@ -202,7 +212,7 @@ void query_error (long long id) { #define MAX_PACKED_SIZE (1 << 24) static int packed_buffer[MAX_PACKED_SIZE / 4]; -void query_result (long long id UU) { +void tglq_query_result (long long id UU) { vlogprintf (E_DEBUG, "result for query #%lld\n", id); /*if (verbosity >= 4) { logprintf ( "result: "); @@ -226,7 +236,7 @@ void query_result (long long id UU) { hexdump_in (); }*/ } - struct query *q = query_get (id); + struct query *q = tglq_query_get (id); if (!q) { //if (verbosity) { // logprintf ( "No such query\n"); @@ -235,7 +245,7 @@ void query_result (long long id UU) { in_ptr = in_end; } else { if (!(q->flags & QUERY_ACK_RECEIVED)) { - remove_event_timer (&q->ev); + event_del (q->ev); } queries_tree = tree_delete_query (queries_tree, q); if (q->methods && q->methods->on_answer) { @@ -253,6 +263,7 @@ void query_result (long long id UU) { assert (in_ptr == in_end); } tfree (q->data, 4 * q->data_len); + event_free (q->ev); tfree (q, sizeof (*q)); } if (end) { @@ -262,37 +273,6 @@ void query_result (long long id UU) { queries_num --; } -#define event_timer_cmp(a,b) ((a)->timeout > (b)->timeout ? 1 : ((a)->timeout < (b)->timeout ? -1 : (memcmp (a, b, sizeof (struct event_timer))))) -DEFINE_TREE (timer, struct event_timer *, event_timer_cmp, 0) -struct tree_timer *timer_tree; - -void insert_event_timer (struct event_timer *ev) { - 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) { - vlogprintf (E_DEBUG + 2, "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); - timer_tree = tree_delete_timer (timer_tree, ev); -} - -double next_timer_in (void) { - if (!timer_tree) { return 1e100; } - return tree_get_min_timer (timer_tree)->timeout; -} - -void work_timers (void) { - double t = get_double_time (); - while (timer_tree) { - struct event_timer *ev = tree_get_min_timer (timer_tree); - assert (ev); - if (ev->timeout > t) { break; } - remove_event_timer (ev); - assert (ev->alarm); - vlogprintf (E_DEBUG, "Alarm\n"); - ev->alarm (ev->self); - } -} int max_chat_size; int max_bcast_size; @@ -304,7 +284,7 @@ extern struct dc *DC_working; static void out_random (int n) { assert (n <= 32); static char buf[32]; - secure_random (buf, n); + tglt_secure_random (buf, n); out_cstring (buf, n); } @@ -383,7 +363,7 @@ 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra); } /* }}} */ @@ -447,7 +427,7 @@ void tgl_do_send_code (const char *user, void (*callback)(void *callback_extra, out_string (TG_APP_HASH); out_string ("en"); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0, callback, callback_extra); } @@ -474,7 +454,7 @@ void tgl_do_phone_call (const char *user, void (*callback)(void *callback_extra, out_string (user); out_string (phone_code_hash); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0, callback, callback_extra); } /* }}} */ @@ -534,10 +514,10 @@ int tgl_do_auth_check_phone (const char *user) { out_int (CODE_auth_check_phone); out_string (user); check_phone_result = -1; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); net_loop (0, cr_f); check_phone_result = -1; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); net_loop (0, cr_f); return check_phone_result; }*/ @@ -571,7 +551,7 @@ int tgl_do_get_nearest_dc (void) { clear_packet (); out_int (CODE_help_get_nearest_dc); nearest_dc_num = -1; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &nearest_dc_methods, 0); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &nearest_dc_methods, 0); net_loop (0, nr_f); return nearest_dc_num; }*/ @@ -607,7 +587,7 @@ int tgl_do_send_code_result (const char *user, const char *code, void (*callback 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); return 0; } @@ -619,7 +599,7 @@ int tgl_do_send_code_result_auth (const char *user, const char *code, const char 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra); return 0; } /* }}} */ @@ -688,7 +668,7 @@ void tgl_do_update_contact_list (void (*callback) (void *callback_extra, int suc clear_packet (); out_int (CODE_contacts_get_contacts); out_string (""); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0, callback, callback_extra); } /* }}} */ @@ -745,7 +725,7 @@ static char *encrypt_decrypted_message (struct tgl_secret_chat *E) { return (void *)msg_key; } -void encr_start (void) { +static void encr_start (void) { encr_extra = packet_ptr; packet_ptr += 1; // str len packet_ptr += 2; // fingerprint @@ -754,11 +734,11 @@ void encr_start (void) { } -void encr_finish (struct tgl_secret_chat *E) { +static void encr_finish (struct tgl_secret_chat *E) { int l = packet_ptr - (encr_extra + 8); while (((packet_ptr - encr_extra) - 3) & 3) { int t; - secure_random (&t, 4); + tglt_secure_random (&t, 4); out_int (t); } @@ -775,7 +755,7 @@ void encr_finish (struct tgl_secret_chat *E) { void tgl_do_send_encr_chat_layer (struct tgl_secret_chat *E) { long long t; - secure_random (&t, 8); + tglt_secure_random (&t, 8); int action[2]; action[0] = CODE_decrypted_message_action_notify_layer; action[1] = 15; @@ -807,9 +787,9 @@ static int msg_send_on_answer (struct query *q UU) { int id = fetch_int (); // id struct tgl_message *M = q->extra; bl_do_set_msg_id (M, id); - fetch_date (); - fetch_pts (); - fetch_seq (); + tglu_fetch_date (); + tglu_fetch_pts (); + tglu_fetch_seq (); if (x == CODE_messages_sent_message_link) { assert (skip_type_any (TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (contacts_link))) >= 0); } @@ -902,7 +882,7 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void * out_int (CODE_decrypted_message_service); out_long (M->id); static int buf[4]; - secure_random (buf, 16); + tglt_secure_random (buf, 16); out_cstring ((void *)buf, 16); switch (M->action.type) { @@ -915,7 +895,7 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void * } encr_finish (&P->encr_chat); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { @@ -942,13 +922,13 @@ void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callbac out_int (CODE_decrypted_message); out_long (M->id); static int buf[4]; - secure_random (buf, 16); + tglt_secure_random (buf, 16); out_cstring ((void *)buf, 16); out_cstring ((void *)M->message, M->message_len); 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { @@ -961,7 +941,7 @@ void tgl_do_send_msg (struct tgl_message *M, void (*callback)(void *callback_ext 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { @@ -983,7 +963,7 @@ void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len, void (*cal } } long long t; - secure_random (&t, 8); + tglt_secure_random (&t, 8); 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); @@ -1024,8 +1004,8 @@ void tgl_do_send_text (tgl_peer_id_t id, char *file_name, void (*callback)(void /* {{{ Mark read */ static int mark_read_on_receive (struct query *q UU) { assert (fetch_int () == (int)CODE_messages_affected_history); - fetch_pts (); - fetch_seq (); + tglu_fetch_pts (); + tglu_fetch_seq (); fetch_int (); // offset if (q->callback) { ((void (*)(void *, int))q->callback)(q->callback_extra, 1); @@ -1057,7 +1037,7 @@ void tgl_do_messages_mark_read (tgl_peer_id_t id, int max_id, void (*callback)(v 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int), void *callback_extra) { @@ -1067,7 +1047,7 @@ void tgl_do_messages_mark_read_encr (tgl_peer_id_t id, long long access_hash, in 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success), void *callback_extra) { @@ -1177,7 +1157,7 @@ void tgl_do_get_history (tgl_peer_id_t id, int limit, int offline_mode, void (*c 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, (void *)*(long *)&id, callback, callback_extra); } /* }}} */ @@ -1264,7 +1244,7 @@ void tgl_do_get_dialog_list (void (*callback)(void *callback_extra, int success, out_int (0); out_int (0); out_int (1000); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0, callback, callback_extra); } /* }}} */ @@ -1332,8 +1312,8 @@ static int send_file_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { tglf_fetch_alloc_user (); } - fetch_pts (); - fetch_seq (); + tglu_fetch_pts (); + tglu_fetch_seq (); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback)(q->callback_extra, 1, M); @@ -1402,7 +1382,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra if (f->encr) { if (x & 15) { assert (f->offset == f->size); - secure_random (buf + x, (-x) & 15); + tglt_secure_random (buf + x, (-x) & 15); x = (x + 15) & ~15; } @@ -1420,7 +1400,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra assert (f->part_size == x); } //update_prompt (); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra); } else { tgl_state.cur_uploaded_bytes -= f->size; tgl_state.cur_uploading_bytes -= f->size; @@ -1467,7 +1447,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra } out_long (-lrand48 () * (1ll << 32) - lrand48 ()); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0, callback, callback_extra); + tglq_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)); @@ -1558,7 +1538,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra M->id = r; M->date = time (0); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra); + tglq_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)); @@ -1572,7 +1552,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { @@ -1617,11 +1597,11 @@ void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name, void (*c if (tgl_get_peer_type (f->to_id) == TGL_PEER_ENCR_CHAT) { f->encr = 1; f->iv = talloc (32); - secure_random (f->iv, 32); + tglt_secure_random (f->iv, 32); f->init_iv = talloc (32); memcpy (f->init_iv, f->iv, 32); f->key = talloc (32); - secure_random (f->key, 32); + tglt_secure_random (f->key, 32); } /*if (f->media_type == CODE_input_media_uploaded_video && !f->encr) { f->media_type = CODE_input_media_uploaded_thumb_video; @@ -1651,8 +1631,8 @@ static int fwd_msg_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { tglf_fetch_alloc_user (); } - fetch_pts (); - fetch_seq (); + tglu_fetch_pts (); + tglu_fetch_seq (); //print_message (M); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); @@ -1676,7 +1656,7 @@ void tgl_do_forward_message (tgl_peer_id_t id, int n, void (*callback)(void *cal 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra); } /* }}} */ @@ -1695,8 +1675,8 @@ static int rename_chat_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { tglf_fetch_alloc_user (); } - fetch_pts (); - fetch_seq (); + tglu_fetch_pts (); + tglu_fetch_seq (); //print_message (M); if (q->callback) { ((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M); @@ -1715,7 +1695,7 @@ void tgl_do_rename_chat (tgl_peer_id_t id, char *name UU, void (*callback)(void 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0, callback, callback_extra); } /* }}} */ @@ -1774,7 +1754,7 @@ void tgl_do_get_chat_info (tgl_peer_id_t id, int offline_mode, void (*callback)( 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0, callback, callback_extra); } /* }}} */ @@ -1836,7 +1816,7 @@ void tgl_do_get_user_info (tgl_peer_id_t id, int offline_mode, void (*callback)( 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, callback, callback_extra); } /* }}} */ @@ -1867,7 +1847,7 @@ void tgl_do_get_user_list_info_silent (int num, int *list) { out_int (list[i]); //out_long (0); } - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0); }*/ /* }}} */ @@ -2012,8 +1992,8 @@ static void load_next_part (struct download *D, void *callback, void *callback_e } out_int (D->offset); out_int (1 << 14); - 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); + tglq_send_query (DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D, callback, callback_extra); + //tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D); } void tgl_do_load_photo_size (struct tgl_photo_size *P, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) { @@ -2160,7 +2140,7 @@ static int export_auth_on_answer (struct query *q UU) { out_int (CODE_auth_import_authorization); out_int (tgl_state.our_id); out_cstring (s, l); - send_query (q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0, q->callback, q->callback_extra); + tglq_send_query (q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0, q->callback, q->callback_extra); tfree (s, l); return 0; } @@ -2175,7 +2155,7 @@ void tgl_do_export_auth (int num, void (*callback) (void *callback_extra, int su 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); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, DC_list[num], callback, callback_extra); } /* }}} */ @@ -2262,7 +2242,7 @@ 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0, callback, callback_extra); } /* }}} */ @@ -2298,7 +2278,7 @@ 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, 0, callback, callback_extra); } /* }}} */ @@ -2348,7 +2328,7 @@ void tgl_do_contacts_search (int limit, const char *s, void (*callback) (void *c 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &contacts_search_methods, 0, callback, callback_extra); } /* }}} */ @@ -2437,7 +2417,7 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran return; } // Already generated key for this chat unsigned char random_here[256]; - secure_random (random_here, 256); + tglt_secure_random (random_here, 256); for (i = 0; i < 256; i++) { random[i] ^= random_here[i]; } @@ -2445,7 +2425,7 @@ 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 (tgl_state.encr_prime, g_a) >= 0); + assert (tglmp_check_g (tgl_state.encr_prime, g_a) >= 0); if (!ctx) { ctx = BN_CTX_new (); ensure_ptr (ctx); @@ -2485,14 +2465,14 @@ 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, callback, callback_extra); + tglq_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 (tgl_state.encr_prime); BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0); ensure_ptr (g_b); - assert (check_g (tgl_state.encr_prime, g_b) >= 0); + assert (tglmp_check_g (tgl_state.encr_prime, g_b) >= 0); if (!ctx) { ctx = BN_CTX_new (); ensure_ptr (ctx); @@ -2535,7 +2515,7 @@ void tgl_do_send_create_encr_chat (void *x, unsigned char *random, void (*callba int user_id = (long)x; int i; unsigned char random_here[256]; - secure_random (random_here, 256); + tglt_secure_random (random_here, 256); for (i = 0; i < 256; i++) { random[i] ^= random_here[i]; } @@ -2595,7 +2575,7 @@ void tgl_do_send_create_encr_chat (void *x, unsigned char *random, void (*callba BN_clear_free (p); BN_clear_free (r); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra); } static int get_dh_config_on_answer (struct query *q UU) { @@ -2611,7 +2591,7 @@ static int get_dh_config_on_answer (struct query *q UU) { BIGNUM *p = BN_bin2bn ((void *)s, 256, 0); ensure_ptr (p); - assert (check_DH_params (p, a) >= 0); + assert (tglmp_check_DH_params (p, a) >= 0); BN_free (p); } int l = prefetch_strlen (); @@ -2644,7 +2624,7 @@ void tgl_do_accept_encr_chat_request (struct tgl_secret_chat *E, void (*callback 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) { @@ -2655,7 +2635,7 @@ void tgl_do_create_encr_chat_request (int user_id, void (*callback)(void *callba 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra); } /* }}} */ @@ -2711,7 +2691,7 @@ static int get_difference_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); n = fetch_int (); for (i = 0; i < n; i++) { - work_update (0, 0); + tglu_work_update (0, 0); } assert (fetch_int () == CODE_vector); n = fetch_int (); @@ -2780,10 +2760,10 @@ void tgl_do_get_difference (int sync_from_start, void (*callback)(void *callback 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); + tglq_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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0, callback, callback_extra); } } /* }}} */ @@ -2872,7 +2852,7 @@ void tgl_do_get_suggested (void) { clear_packet (); out_int (CODE_contacts_get_suggested); out_int (100); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_suggested_methods, 0); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_suggested_methods, 0); }*/ /* }}} */ @@ -2899,7 +2879,7 @@ 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, callback, callback_extra); + tglq_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 (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { @@ -2917,7 +2897,7 @@ void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, void (* 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra); } /* }}} */ @@ -2962,7 +2942,7 @@ void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic, void (*callba 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, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0, callback, callback_extra); } /* }}} */ @@ -2991,7 +2971,7 @@ void tgl_do_delete_msg (long long id, void (*callback)(void *callback_extra, int out_int (CODE_vector); out_int (1); out_int (id); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0, callback, callback_extra); + tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0, callback, callback_extra); } /* }}} */ @@ -3020,11 +3000,11 @@ void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, in out_int (CODE_vector); out_int (1); out_int (id); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &restore_msg_methods, 0, callback, callback_extra); + tglq_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) { +static int update_status_on_answer (struct query *q UU) { fetch_bool (); if (q->callback) { @@ -3042,5 +3022,5 @@ void tgl_do_update_status (int online UU, void (*callback)(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, callback, callback_extra); + tglq_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 257056b..b908a3b 100644 --- a/queries.h +++ b/queries.h @@ -16,13 +16,15 @@ Copyright Vitaly Valtman 2013 */ -#include "net.h" +//#include "net.h" #ifndef __QUERIES_H__ #define __QUERIES_H__ #include "structures.h" #include "auto.h" #include "tgl-layout.h" +struct event; + #define QUERY_ACK_RECEIVED 1 struct query; @@ -33,12 +35,6 @@ struct query_methods { struct paramed_type *type; }; -struct event_timer { - double timeout; - int (*alarm)(void *self); - void *self; -}; - struct query { long long msg_id; int data_len; @@ -46,7 +42,7 @@ struct query { int seq_no; void *data; struct query_methods *methods; - struct event_timer ev; + struct event *ev; struct dc *DC; struct session *session; void *extra; @@ -55,14 +51,12 @@ struct query { }; -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); -void query_restart (long long id); +struct query *tglq_send_query (struct dc *DC, int len, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra); +void tglq_query_ack (long long id); +void tglq_query_error (long long id); +void tglq_query_result (long long id); +void tglq_query_restart (long long id); -void insert_event_timer (struct event_timer *ev); -void remove_event_timer (struct event_timer *ev); double next_timer_in (void); void work_timers (void); diff --git a/structures.c b/structures.c index 2ee8dcf..a366cfc 100644 --- a/structures.c +++ b/structures.c @@ -32,6 +32,7 @@ #include #include "queries.h" #include "binlog.h" +#include "updates.h" #include "tgl.h" @@ -497,7 +498,7 @@ void tglf_fetch_photo_size (struct tgl_photo_size *S) { } } -void fetch_geo (struct tgl_geo *G) { +void tglf_fetch_geo (struct tgl_geo *G) { unsigned x = fetch_int (); if (x == CODE_geo_point) { G->longitude = fetch_double (); @@ -519,7 +520,7 @@ void tglf_fetch_photo (struct tgl_photo *P) { P->user_id = fetch_int (); P->date = fetch_int (); P->caption = fetch_str_dup (); - fetch_geo (&P->geo); + tglf_fetch_geo (&P->geo); assert (fetch_int () == CODE_vector); P->sizes_num = fetch_int (); P->sizes = talloc (sizeof (struct tgl_photo_size) * P->sizes_num); @@ -630,10 +631,10 @@ void tglf_fetch_message_short (struct tgl_message *M) { int l = prefetch_strlen (); char *s = fetch_str (l); - fetch_pts (); + tglu_fetch_pts (); int date = fetch_int (); - fetch_seq (); + tglu_fetch_seq (); bl_do_create_message_text (id, from_id, TGL_PEER_USER, to_id, date, l, s); } else { @@ -642,9 +643,9 @@ void tglf_fetch_message_short (struct tgl_message *M) { int l = prefetch_strlen (); fetch_str (l); // text - fetch_pts (); + tglu_fetch_pts (); fetch_int (); - fetch_seq (); + tglu_fetch_seq (); } } @@ -658,10 +659,10 @@ void tglf_fetch_message_short_chat (struct tgl_message *M) { int l = prefetch_strlen (); char *s = fetch_str (l); - fetch_pts (); + tglu_fetch_pts (); int date = fetch_int (); - fetch_seq (); + tglu_fetch_seq (); bl_do_create_message_text (id, from_id, TGL_PEER_CHAT, to_id, date, l, s); } else { @@ -671,9 +672,9 @@ void tglf_fetch_message_short_chat (struct tgl_message *M) { int l = prefetch_strlen (); fetch_str (l); // text - fetch_pts (); + tglu_fetch_pts (); fetch_int (); - fetch_seq (); + tglu_fetch_seq (); } } @@ -697,7 +698,7 @@ void tglf_fetch_message_media (struct tgl_message_media *M) { tglf_fetch_document (&M->document); break; case CODE_message_media_geo: - fetch_geo (&M->geo); + tglf_fetch_geo (&M->geo); break; case CODE_message_media_contact: M->phone = fetch_str_dup (); @@ -995,7 +996,7 @@ void tglf_fetch_message (struct tgl_message *M) { bl_do_set_unread (M, unread); } -void tglf_fetch_geo_message (struct tgl_message *M) { +void tglf_tglf_fetch_geo_message (struct tgl_message *M) { memset (M, 0, sizeof (*M)); unsigned x = fetch_int (); assert (x == CODE_geo_chat_message_empty || x == CODE_geo_chat_message || x == CODE_geo_chat_message_service); @@ -1254,7 +1255,7 @@ struct tgl_message *tglf_fetch_alloc_message (void) { struct tgl_message *tglf_fetch_alloc_geo_message (void) { struct tgl_message *M = talloc (sizeof (*M)); - tglf_fetch_geo_message (M); + tglf_tglf_fetch_geo_message (M); struct tgl_message *M1 = tree_lookup_message (message_tree, M); messages_allocated ++; if (M1) { diff --git a/tgl-inner.h b/tgl-inner.h new file mode 100644 index 0000000..75e829c --- /dev/null +++ b/tgl-inner.h @@ -0,0 +1,11 @@ +#ifndef __TGL_INNER_H__ +#define __TGL_INNER_H__ + +#define vlogprintf(verbosity_level,...) \ + do { \ + if (tgl_state.verbosity >= verbosity_level) { \ + tgl_state.callback.logprintf (__VA_ARGS__); \ + } \ + } while (0) + +#endif diff --git a/tgl.c b/tgl.c index 5fc5a76..d6c400d 100644 --- a/tgl.c +++ b/tgl.c @@ -3,6 +3,10 @@ #endif #include "tgl.h" +#include "tools.h" +#include "mtproto-client.h" + +#include struct tgl_state tgl_state; @@ -21,3 +25,16 @@ void tgl_set_auth_file_path (const char *path) { void tgl_set_download_directory (const char *path) { tgl_state.downloads_directory = tstrdup (path); } + +void tgl_set_callback (struct tgl_update_callback *cb) { + tgl_state.callback = *cb; +} + +void tgl_set_rsa_key (const char *key) { + tgl_state.rsa_key = tstrdup (key); +} + +void tgl_init (void) { + tgl_state.ev_base = event_base_new (); + tglmp_on_start (tgl_state.rsa_key); +} diff --git a/tgl.h b/tgl.h index a126675..5fcec37 100644 --- a/tgl.h +++ b/tgl.h @@ -10,22 +10,37 @@ #define TGL_VERSION "0.9-beta" // Do not modify this structure, unless you know what you do +struct connection; +struct mtproto_methods; +struct session; +struct dc; 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 (*type_notification)(struct tgl_user *U); + void (*type_in_chat_notification)(struct tgl_user *U, struct tgl_chat *C); + void (*type_in_secret_chat_notification)(struct tgl_secret_chat *E); void (*status_notification)(struct tgl_user *U); void (*user_registered)(struct tgl_user *U); + void (*user_activated)(struct tgl_user *U); + void (*new_authorization)(const char *device, const char *location); + void (*secret_chat_request)(struct tgl_secret_chat *E); + void (*secret_chat_established)(struct tgl_secret_chat *E); + void (*secret_chat_deleted)(struct tgl_secret_chat *E); }; -#define vlogprintf(verbosity_level,...) \ - do { \ - if (tgl_state.verbosity >= verbosity_level) { \ - tgl_state.callback.logprintf (__VA_ARGS__); \ - } \ - } while (0) +struct tgl_net_methods { + int (*write_out) (struct connection *c, void *data, int len); + int (*read_in) (struct connection *c, void *data, int len); + int (*read_in_lookup) (struct connection *c, void *data, int len); + int (*flush_out) (struct connection *c); + void (*incr_out_packet_num) (struct connection *c); + struct dc *(*get_dc) (struct connection *c); + struct session *(*get_session) (struct connection *c); + + struct connection *(*create_connection) (const char *host, int port, struct dc *dc, struct session *session, struct mtproto_methods *methods); +}; #define E_ERROR 0 @@ -61,6 +76,10 @@ struct tgl_state { char *downloads_directory; struct tgl_update_callback callback; + struct tgl_net_methods *net_methods; + struct event_base *ev_base; + + char *rsa_key; }; extern struct tgl_state tgl_state; @@ -94,6 +113,8 @@ 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); +void tgl_set_callback (struct tgl_update_callback *cb); +void tgl_set_rsa_key (const char *key); static inline int tgl_get_peer_type (tgl_peer_id_t id) { @@ -127,6 +148,10 @@ static inline void tgl_set_test_mode (void) { tgl_state.test_mode ++; } +struct pollfd; +int tgl_connections_make_poll_array (struct pollfd *fds, int max); +void tgl_connections_poll_result (struct pollfd *fds, int max); + 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); @@ -168,8 +193,19 @@ void tgl_do_update_status (int online, void (*callback)(void *callback_extra, in void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]); +void tgl_do_send_ping (struct connection *c); + //void tgl_do_get_suggested (void); void tgl_do_create_keys_end (struct tgl_secret_chat *U); void tgl_do_send_encr_chat_layer (struct tgl_secret_chat *E); + +struct mtproto_methods { + int (*ready) (struct connection *c); + int (*close) (struct connection *c); + int (*execute) (struct connection *c, int op, int len); +}; + +void tgl_init (void); +void tgl_dc_authorize (struct dc *DC); #endif diff --git a/tools.c b/tools.c index 7213d0e..fa2de15 100644 --- a/tools.c +++ b/tools.c @@ -28,9 +28,12 @@ #include #include #include +#include #include +#include +#include -#include "interface.h" +//#include "interface.h" #include "tools.h" #ifdef DEBUG @@ -43,6 +46,15 @@ int used_blocks; int free_blocks_cnt; #endif + +void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2), weak)); +void logprintf (const char *format, ...) { + va_list ap; + va_start (ap, format); + vfprintf (stdout, format, ap); + va_end (ap); +} + extern int verbosity; long long total_allocated_bytes; @@ -269,3 +281,35 @@ void texists (void *ptr, int size) { assert (block_num < used_blocks); } #endif + +void my_clock_gettime (int clock_id, struct timespec *T) { +#ifdef __MACH__ + // We are ignoring MONOTONIC and hope time doesn't go back too often + clock_serv_t cclock; + mach_timespec_t mts; + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + T->tv_sec = mts.tv_sec; + T->tv_nsec = mts.tv_nsec; +#else + assert (clock_gettime(clock_id, T) >= 0); +#endif +} + +double get_double_time (void) { + struct timespec tv; + my_clock_gettime (CLOCK_REALTIME, &tv); + return tv.tv_sec + 1e-9 * tv.tv_nsec; +} + +void tglt_secure_random (void *s, int l) { + if (RAND_bytes (s, l) < 0) { + /*if (allow_weak_random) { + RAND_pseudo_bytes (s, l); + } else {*/ + assert (0 && "End of random. If you want, you can start with -w"); + //} + } +} + diff --git a/tools.h b/tools.h index e63b133..f4097cc 100644 --- a/tools.h +++ b/tools.h @@ -20,6 +20,8 @@ #ifndef __TOOLS_H__ #define __TOOLS_H__ +double get_double_time (void); + void *talloc (size_t size); void *trealloc (void *ptr, size_t old_size, size_t size); void *talloc0 (size_t size); @@ -37,6 +39,8 @@ void tfree_secure (void *ptr, int size); int tsnprintf (char *buf, int len, const char *format, ...) __attribute__ ((format (printf, 3, 4))); int tasprintf (char **res, const char *format, ...) __attribute__ ((format (printf, 2, 3))); +void tglt_secure_random (void *s, int l); + #ifdef DEBUG void tcheck (void); void texists (void *ptr, int size); diff --git a/tree.h b/tree.h index d0bac44..2be4604 100644 --- a/tree.h +++ b/tree.h @@ -32,7 +32,7 @@ struct tree_ ## X_NAME { \ int y;\ };\ \ -struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\ +static inline struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\ struct tree_ ## X_NAME *T = talloc (sizeof (*T));\ T->x = x;\ T->y = y;\ @@ -40,11 +40,11 @@ struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\ return T;\ }\ \ -void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\ +static inline void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\ tfree (T, sizeof (*T));\ }\ \ -void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\ +static inline void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\ if (!T) {\ *L = *R = 0;\ } else {\ @@ -59,8 +59,8 @@ void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## }\ }\ \ -struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result));\ -struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\ +static inline struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result));\ +static inline struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\ if (!T) {\ return new_tree_node_ ## X_NAME (x, y);\ } else {\ @@ -81,7 +81,7 @@ struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYP }\ }\ \ -struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\ +static inline struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\ if (!L || !R) {\ return L ? L : R;\ } else {\ @@ -95,8 +95,8 @@ struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct }\ }\ \ -struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result));\ -struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ +static inline struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result));\ +static inline struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ assert (T);\ int c = X_CMP (x, T->x);\ if (!c) {\ @@ -113,13 +113,13 @@ struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYP }\ }\ \ -X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\ +static inline X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\ if (!T) { return X_UNSET; } \ while (T->left) { T = T->left; }\ return T->x; \ } \ \ -X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ +static inline X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ int c;\ while (T && (c = X_CMP (x, T->x))) {\ T = (c < 0 ? T->left : T->right);\ @@ -127,25 +127,25 @@ X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\ return T ? T->x : X_UNSET;\ }\ \ -void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) {\ +static inline void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) {\ if (!T) { return; } \ tree_act_ ## X_NAME (T->left, act); \ act (T->x); \ tree_act_ ## X_NAME (T->right, act); \ }\ \ -void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) {\ +static inline void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) {\ if (!T) { return; } \ tree_act_ex_ ## X_NAME (T->left, act, extra); \ act (T->x, extra); \ tree_act_ex_ ## X_NAME (T->right, act, extra); \ }\ \ -int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \ +static inline int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \ if (!T) { return 0; }\ return 1 + tree_count_ ## X_NAME (T->left) + tree_count_ ## X_NAME (T->right); \ }\ -void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \ +static inline void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \ if (!T) { return; }\ if (T->left) { \ assert (T->left->y <= T->y);\ @@ -158,7 +158,7 @@ void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \ tree_check_ ## X_NAME (T->left); \ tree_check_ ## X_NAME (T->right); \ }\ -struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \ +static inline struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \ if (!T) { return 0; }\ tree_clear_ ## X_NAME (T->left); \ tree_clear_ ## X_NAME (T->right); \ diff --git a/updates.c b/updates.c new file mode 100644 index 0000000..cb8f459 --- /dev/null +++ b/updates.c @@ -0,0 +1,728 @@ +#include "tgl.h" +#include "updates.h" +#include "mtproto-common.h" +#include "binlog.h" +#include "auto.h" + +#include + +void tglu_fetch_pts (void) { + int p = fetch_int (); + if (p <= tgl_state.pts) { return; } + if (p != tgl_state.pts + 1) { + if (tgl_state.pts) { + //vlogprintf (E_NOTICE, "Hole in pts p = %d, pts = %d\n", p, tgl_state.pts); + + // get difference should be here + tgl_state.pts = p; + } else { + tgl_state.pts = p; + } + } else { + tgl_state.pts ++; + } + bl_do_set_pts (tgl_state.pts); +} + +void tglu_fetch_qts (void) { + int p = fetch_int (); + if (p <= tgl_state.qts) { return; } + if (p != tgl_state.qts + 1) { + if (tgl_state.qts) { + //logprintf ("Hole in qts\n"); + // get difference should be here + tgl_state.qts = p; + } else { + tgl_state.qts = p; + } + } else { + tgl_state.qts ++; + } + bl_do_set_qts (tgl_state.qts); +} + +void tglu_fetch_date (void) { + int p = fetch_int (); + if (p > tgl_state.date) { + tgl_state.date = p; + bl_do_set_date (tgl_state.date); + } +} + +void tglu_fetch_seq (void) { + int x = fetch_int (); + if (x > tgl_state.seq + 1) { + vlogprintf (E_NOTICE, "Hole in seq: seq = %d, x = %d\n", tgl_state.seq, x); + //tgl_do_get_difference (); + //seq = x; + } else if (x == tgl_state.seq + 1) { + tgl_state.seq = x; + bl_do_set_seq (tgl_state.seq); + } +} + +static void fetch_dc_option (void) { + assert (fetch_int () == CODE_dc_option); + int id = fetch_int (); + int l1 = prefetch_strlen (); + char *name = fetch_str (l1); + int l2 = prefetch_strlen (); + char *ip = fetch_str (l2); + int port = fetch_int (); + 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); +} + +void tglu_work_update (struct connection *c, long long msg_id) { + unsigned op = fetch_int (); + switch (op) { + case CODE_update_new_message: + { + struct tgl_message *M = tglf_fetch_alloc_message (); + assert (M); + tglu_fetch_pts (); + + //if (tgl_state.callback.new_msg) { + // tgl_state.callback.new_msg (M); + //} + //unread_messages ++; + //print_message (M); + //update_prompt (); + break; + }; + case CODE_update_message_i_d: + { + int id = fetch_int (); // id + int new = fetch_long (); // random_id + struct tgl_message *M = tgl_message_get (new); + if (M) { + bl_do_set_msg_id (M, id); + } + } + break; + case CODE_update_read_messages: + { + assert (fetch_int () == (int)CODE_vector); + int n = fetch_int (); + + //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); + } + } + tglu_fetch_pts (); + /*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 (tgl_state.callback.type_notification && U) { + tgl_state.callback.type_notification ((void *)U); + } + /*if (log_level >= 2) { + print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" User "); + print_user_name (id, U); + printf (" is typing....\n"); + pop_color (); + print_end (); + }*/ + } + break; + case CODE_update_chat_user_typing: + { + tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); + 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 (U && C) { + if (tgl_state.callback.type_in_chat_notification) { + tgl_state.callback.type_in_chat_notification ((void *)U, (void *)C); + } + } + /*if (log_level >= 2) { + print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" User "); + print_user_name (id, U); + printf (" is typing in chat "); + print_chat_name (chat_id, C); + printf ("....\n"); + pop_color (); + print_end (); + }*/ + } + break; + case CODE_update_user_status: + { + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + tgl_peer_t *U = tgl_peer_get (user_id); + if (U) { + tglf_fetch_user_status (&U->user.status); + + if (tgl_state.callback.status_notification) { + tgl_state.callback.status_notification ((void *)U); + } + /*if (log_level >= 3) { + print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" User "); + print_user_name (user_id, U); + printf (" is now "); + 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); + } + } + break; + case CODE_update_user_name: + { + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + tgl_peer_t *UC = tgl_peer_get (user_id); + if (UC && (UC->flags & FLAG_CREATED)) { + int l1 = prefetch_strlen (); + char *f = fetch_str (l1); + int l2 = prefetch_strlen (); + char *l = fetch_str (l2); + struct tgl_user *U = &UC->user; + bl_do_user_set_real_name (U, f, l1, l, l2); + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" User "); + print_user_name (user_id, UC); + printf (" changed name to "); + print_user_name (user_id, UC); + printf ("\n"); + pop_color (); + print_end ();*/ + } else { + fetch_skip_str (); + fetch_skip_str (); + } + } + break; + case CODE_update_user_photo: + { + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + tgl_peer_t *UC = tgl_peer_get (user_id); + tglu_fetch_date (); + if (UC && (UC->flags & FLAG_CREATED)) { + struct tgl_user *U = &UC->user; + unsigned y = fetch_int (); + long long photo_id; + struct tgl_file_location big; + struct tgl_file_location small; + memset (&big, 0, sizeof (big)); + memset (&small, 0, sizeof (small)); + if (y == CODE_user_profile_photo_empty) { + photo_id = 0; + big.dc = -2; + small.dc = -2; + } else { + assert (y == CODE_user_profile_photo); + photo_id = fetch_long (); + tglf_fetch_file_location (&small); + tglf_fetch_file_location (&big); + } + bl_do_set_user_profile_photo (U, photo_id, &big, &small); + + /*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 ();*/ + } else { + struct tgl_file_location t; + unsigned y = fetch_int (); + if (y == CODE_user_profile_photo_empty) { + } else { + assert (y == CODE_user_profile_photo); + fetch_long (); // photo_id + tglf_fetch_file_location (&t); + tglf_fetch_file_location (&t); + } + } + fetch_bool (); + } + break; + case CODE_update_restore_messages: + { + assert (fetch_int () == CODE_vector); + int n = fetch_int (); + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" Restored %d messages\n", n); + pop_color (); + print_end ();*/ + fetch_skip (n); + tglu_fetch_pts (); + } + break; + case CODE_update_delete_messages: + { + assert (fetch_int () == CODE_vector); + int n = fetch_int (); + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" Deleted %d messages\n", n); + pop_color (); + print_end ();*/ + fetch_skip (n); + tglu_fetch_pts (); + } + break; + case CODE_update_chat_participants: + { + unsigned x = fetch_int (); + assert (x == CODE_chat_participants || x == CODE_chat_participants_forbidden); + tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); + int n = 0; + tgl_peer_t *C = tgl_peer_get (chat_id); + if (C && (C->flags & FLAG_CREATED)) { + if (x == CODE_chat_participants) { + bl_do_chat_set_admin (&C->chat, fetch_int ()); + assert (fetch_int () == CODE_vector); + n = fetch_int (); + struct tgl_chat_user *users = talloc (12 * n); + int i; + for (i = 0; i < n; i++) { + assert (fetch_int () == (int)CODE_chat_participant); + users[i].user_id = fetch_int (); + users[i].inviter_id = fetch_int (); + users[i].date = fetch_int (); + } + int version = fetch_int (); + bl_do_chat_set_participants (&C->chat, version, n, users); + } + } else { + if (x == CODE_chat_participants) { + fetch_int (); // admin_id + assert (fetch_int () == CODE_vector); + n = fetch_int (); + fetch_skip (n * 4); + fetch_int (); // version + } + } + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" Chat "); + print_chat_name (chat_id, C); + if (x == CODE_chat_participants) { + printf (" changed list: now %d members\n", n); + } else { + printf (" changed list, but we are forbidden to know about it (Why this update even was sent to us?\n"); + } + pop_color (); + print_end ();*/ + } + break; + case CODE_update_contact_registered: + { + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + tgl_peer_t *U = tgl_peer_get (user_id); + fetch_int (); // date + if (tgl_state.callback.user_registered && U) { + tgl_state.callback.user_registered ((void *)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 ();*/ + } + 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 (); + 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 ();*/ + 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) { + fetch_bool (); // has_phone + } + t = fetch_int (); + assert (t == CODE_contacts_foreign_link_unknown || t == CODE_contacts_foreign_link_requested || t == CODE_contacts_foreign_link_mutual); + if (t == CODE_contacts_foreign_link_requested) { + fetch_bool (); // has_phone + } + if (U) {} + } + break; + case CODE_update_activation: + { + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + tgl_peer_t *U = tgl_peer_get (user_id); + + if (tgl_state.callback.user_activated && U) { + tgl_state.callback.user_activated ((void *)U); + } + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" User "); + print_user_name (user_id, U); + printf (" activated\n"); + pop_color (); + print_end ();*/ + } + break; + case CODE_update_new_authorization: + { + fetch_long (); // auth_key_id + fetch_int (); // date + char *s = fetch_str_dup (); + char *location = fetch_str_dup (); + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" New autorization: device='%s' location='%s'\n", + s, location); + pop_color (); + print_end ();*/ + if (tgl_state.callback.new_authorization) { + tgl_state.callback.new_authorization (s, location); + } + tfree_str (s); + tfree_str (location); + } + break; + case CODE_update_new_geo_chat_message: + { + struct tgl_message *M = tglf_fetch_alloc_geo_message (); + assert (M); + //if (tgl_state.callback.new_msg) { + // tgl_state.callback.new_msg (M); + //} + //unread_messages ++; + //print_message (M); + //update_prompt (); + } + break; + case CODE_update_new_encrypted_message: + { + struct tgl_message *M = tglf_fetch_alloc_encrypted_message (); + assert (M); + //unread_messages ++; + //print_message (M); + //update_prompt (); + tglu_fetch_qts (); + //if (tgl_state.callback.new_msg) { + // tgl_state.callback.new_msg (M); + //} + } + break; + case CODE_update_encryption: + { + struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (); + vlogprintf (E_DEBUG, "Secret chat state = %d\n", E->state); + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + switch (E->state) { + case sc_none: + break; + case sc_waiting: + printf (" Encrypted chat "); + print_encr_chat_name (E->id, (void *)E); + printf (" is now in wait state\n"); + break; + case sc_request: + printf (" Encrypted chat "); + print_encr_chat_name (E->id, (void *)E); + printf (" is now in request state. Sending request ok\n"); + break; + case sc_ok: + printf (" Encrypted chat "); + print_encr_chat_name (E->id, (void *)E); + printf (" is now in ok state\n"); + break; + case sc_deleted: + printf (" Encrypted chat "); + print_encr_chat_name (E->id, (void *)E); + printf (" is now in deleted state\n"); + break; + } + pop_color (); + print_end ();*/ + + if (E->state == sc_request) { + if (tgl_state.callback.secret_chat_request) { + tgl_state.callback.secret_chat_request (E); + } + } else if (E->state == sc_ok) { + if (tgl_state.callback.secret_chat_established) { + tgl_state.callback.secret_chat_established (E); + } + } else if (E->state == sc_deleted) { + if (tgl_state.callback.secret_chat_deleted) { + tgl_state.callback.secret_chat_deleted (E); + } + } + if (E->state == sc_ok) { + tgl_do_send_encr_chat_layer (E); + } + fetch_int (); // date + } + break; + case CODE_update_encrypted_chat_typing: + { + tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); + tgl_peer_t *P = tgl_peer_get (id); + + if (P) { + if (tgl_state.callback.type_in_secret_chat_notification) { + tgl_state.callback.type_in_secret_chat_notification ((void *)P); + } + } + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + if (P) { + printf (" User "); + tgl_peer_id_t user_id = TGL_MK_USER (P->encr_chat.user_id); + print_user_name (user_id, tgl_peer_get (user_id)); + printf (" typing in secret chat "); + print_encr_chat_name (id, P); + printf ("\n"); + } else { + printf (" Some user is typing in unknown secret chat\n"); + } + pop_color (); + print_end ();*/ + } + break; + case CODE_update_encrypted_messages_read: + { + tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); // chat_id + fetch_int (); // max_date + fetch_int (); // date + tgl_peer_t *P = tgl_peer_get (id); + //int x = -1; + if (P && P->last) { + //x = 0; + struct tgl_message *M = P->last; + while (M && (!M->out || M->unread)) { + if (M->out) { + bl_do_set_unread (M, 0); + } + M = M->next; + } + } + /*if (log_level >= 1) { + print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" Encrypted chat "); + print_encr_chat_name_full (id, tgl_peer_get (id)); + printf (": %d messages marked read \n", x); + pop_color (); + print_end (); + }*/ + } + break; + case CODE_update_chat_participant_add: + { + tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + tgl_peer_id_t inviter_id = TGL_MK_USER (fetch_int ()); + int version = fetch_int (); + + tgl_peer_t *C = tgl_peer_get (chat_id); + if (C && (C->flags & FLAG_CREATED)) { + bl_do_chat_add_user (&C->chat, version, tgl_get_peer_id (user_id), tgl_get_peer_id (inviter_id), time (0)); + } + + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" Chat "); + print_chat_name (chat_id, tgl_peer_get (chat_id)); + printf (": user "); + print_user_name (user_id, tgl_peer_get (user_id)); + printf (" added by user "); + print_user_name (inviter_id, tgl_peer_get (inviter_id)); + printf ("\n"); + pop_color (); + print_end ();*/ + } + break; + case CODE_update_chat_participant_delete: + { + tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ()); + tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ()); + int version = fetch_int (); + + tgl_peer_t *C = tgl_peer_get (chat_id); + if (C && (C->flags & FLAG_CREATED)) { + bl_do_chat_del_user (&C->chat, version, tgl_get_peer_id (user_id)); + } + + /*print_start (); + push_color (COLOR_YELLOW); + print_date (time (0)); + printf (" Chat "); + print_chat_name (chat_id, tgl_peer_get (chat_id)); + printf (": user "); + print_user_name (user_id, tgl_peer_get (user_id)); + printf (" deleted\n"); + pop_color (); + print_end ();*/ + } + break; + case CODE_update_dc_options: + { + assert (fetch_int () == CODE_vector); + int n = fetch_int (); + assert (n >= 0); + int i; + for (i = 0; i < n; i++) { + fetch_dc_option (); + } + } + break; + case CODE_update_user_blocked: + { + int id = fetch_int (); + int blocked = fetch_bool (); + tgl_peer_t *P = tgl_peer_get (TGL_MK_USER (id)); + if (P && (P->flags & FLAG_CREATED)) { + bl_do_user_set_blocked (&P->user, blocked); + } + } + break; + case CODE_update_notify_settings: + { + assert (skip_type_any (TYPE_TO_PARAM (notify_peer)) >= 0); + assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0); + } + break; + default: + vlogprintf (E_ERROR, "Unknown update type %08x\n", op); + ; + } +} + +void tglu_work_update_short (struct connection *c, long long msg_id) { + int *save = in_ptr; + assert (!skip_type_any (TYPE_TO_PARAM (updates))); + int *save_end = in_ptr; + in_ptr = save; + + assert (fetch_int () == CODE_update_short); + tglu_work_update (c, msg_id); + tglu_fetch_date (); + + assert (save_end == in_ptr); +} + +void tglu_work_updates (struct connection *c, long long msg_id) { + int *save = in_ptr; + assert (!skip_type_any (TYPE_TO_PARAM (updates))); + int *save_end = in_ptr; + in_ptr = save; + assert (fetch_int () == CODE_updates); + assert (fetch_int () == CODE_vector); + int n = fetch_int (); + int i; + for (i = 0; i < n; i++) { + tglu_work_update (c, msg_id); + } + assert (fetch_int () == CODE_vector); + n = fetch_int (); + for (i = 0; i < n; i++) { + tglf_fetch_alloc_user (); + } + assert (fetch_int () == CODE_vector); + n = fetch_int (); + for (i = 0; i < n; i++) { + tglf_fetch_alloc_chat (); + } + bl_do_set_date (fetch_int ()); + bl_do_set_seq (fetch_int ()); + assert (save_end == in_ptr); +} + +void tglu_work_update_short_message (struct connection *c, long long msg_id) { + int *save = in_ptr; + assert (!skip_type_any (TYPE_TO_PARAM (updates))); + int *save_end = in_ptr; + in_ptr = save; + + assert (fetch_int () == (int)CODE_update_short_message); + struct tgl_message *M = tglf_fetch_alloc_message_short (); + assert (M); + /*unread_messages ++; + print_message (M); + update_prompt (); + if (M->date > last_date) { + last_date = M->date; + }*/ + + assert (save_end == in_ptr); +} + +void tglu_work_update_short_chat_message (struct connection *c, long long msg_id) { + int *save = in_ptr; + assert (!skip_type_any (TYPE_TO_PARAM (updates))); + int *save_end = in_ptr; + in_ptr = save; + + assert (fetch_int () == CODE_update_short_chat_message); + struct tgl_message *M = tglf_fetch_alloc_message_short_chat (); + assert (M); + /*unread_messages ++; + print_message (M); + update_prompt (); + if (M->date > last_date) { + last_date = M->date; + }*/ + assert (save_end == in_ptr); +} + +void tglu_work_updates_to_long (struct connection *c, long long msg_id) { + assert (fetch_int () == (int)CODE_updates_too_long); + vlogprintf (E_NOTICE, "updates to long... Getting difference\n"); + tgl_do_get_difference (0, 0, 0); +} diff --git a/updates.h b/updates.h new file mode 100644 index 0000000..3348716 --- /dev/null +++ b/updates.h @@ -0,0 +1,15 @@ +#ifndef __UPDATES_H__ +#define __UPDATES_H__ +struct connection; +void tglu_work_update (struct connection *c, long long msg_id); +void tglu_work_updates_to_long (struct connection *c, long long msg_id); +void tglu_work_update_short_chat_message (struct connection *c, long long msg_id); +void tglu_work_update_short_message (struct connection *c, long long msg_id); +void tglu_work_update_short (struct connection *c, long long msg_id); +void tglu_work_updates (struct connection *c, long long msg_id); + +void tglu_fetch_pts (void); +void tglu_fetch_qts (void); +void tglu_fetch_seq (void); +void tglu_fetch_date (void); +#endif