int secure_send_on_answer (void **IP, void **Data) { vkprintf (2, "fun %s\n", __func__); struct rpc_query *q = *Data; struct secure_send_extra *E = q->extra; if (E->state == 1) { //resend_answer_ack (q, &E->pid); q->ev.wakeup_time = precise_now + E->timeout; insert_event_timer (&q->ev); return 1; } secure_send_s0 --; secure_send_s1 ++; E->state ++; free (E->data); E->data_size = 0; E->data = 0; if (!tl_fetch_error ()) { tl_init_store (CQ->in_type, CQ->remote_pid, q->qid); //tl_store_init (CQ->in, q->qid); tl_store_end_ext (RPC_REQ_RESULT_ACK); sent_answer_ack ++; } if (E->binlog) { struct lev_answer_rx *L = alloc_log_event (LEV_ANSWER_RX, sizeof (*L), 0); L->qid = q->qid; if (binlog_mode_on & 2) { flush_cbinlog (0); } } int r = ((rpc_fun_t)(*IP))(IP + 1, Data); if (r < 0) { return r; } q->ev.wakeup_time = precise_now + E->timeout; insert_event_timer (&q->ev); return 1; }
static void try_change_zone (void) { if (cur_zone == NULL) { return; } vkprintf (3, "%s: %.*s\n", __func__, cur_zone->origin_len, cur_zone->origin); struct lev_dns_change_zone *E = alloc_log_event (LEV_DNS_CHANGE_ZONE + cur_zone->origin_len, sizeof (struct lev_dns_change_zone) + cur_zone->origin_len, 0); memcpy (E->origin, cur_zone->origin, cur_zone->origin_len); cur_zone = NULL; }
static void record_add (record_t *r) { try_change_zone (); assert (r->data_len >= 4); void *E = alloc_log_event (0, r->data_len, 0); memcpy (E, r->data, r->data_len); if (compute_uncommitted_log_bytes () > (1 << 23)) { flush_binlog_forced (0); } add_logevents++; }
int _secure_send_on_net_fail (void **IP, void **Data, int binlog) { long long new_qid = get_free_rpc_qid (0); //*(long long *)(Data[1]); struct rpc_query *q = default_create_rpc_query (new_qid); assert (q); struct secure_send_extra *E = zmalloc (sizeof (*E)); static int buf[10000]; struct tl_query_header *h = CQ->h; long long qid = h->qid; assert (h->actor_id == CC->id); h->qid = new_qid; h->actor_id = CC->new_id; int len = tl_write_header (CQ->h, buf, 10000); h->qid = qid; h->actor_id = CC->id; assert (len >= 0); E->state = 0; E->data_size = tl_fetch_unread () + len; E->data = malloc (E->data_size); memset (E->data, 0, E->data_size); struct rpc_cluster_bucket *B = *Data; assert (B); E->pid.ip = B->methods->get_host (B); E->pid.port = B->methods->get_port (B); E->timeout = CC->timeout; E->binlog = 0; memcpy (E->data, buf, len); tl_fetch_raw_data (E->data + len, E->data_size - len); secure_send_s0 ++; q->extra = E; if (binlog) { E->binlog_pos = log_last_pos (); insert_binlog_pos (E->binlog_pos, 0); struct lev_query_tx *L = alloc_log_event (LEV_QUERY_TX, sizeof (*L) + E->data_size, 0); L->qid = q->qid; L->old_qid = q->old_qid; L->cluster_id = CC->id; L->data_size = E->data_size; L->pid = E->pid; L->timeout = E->timeout; memcpy (L->data, E->data, E->data_size); E->binlog = 1; if (binlog_mode_on & 2) { flush_cbinlog (0); } } return 0; }
static void record_delete (record_t *r) { if (last_deleted_record && !cmp_str (last_deleted_record->name, last_deleted_record->name_len, r->name, r->name_len) && last_deleted_record->qtype == r->qtype) { return; } try_change_zone (); vkprintf (3, "Delete records for name '%.*s' of type %d.\n", r->name_len, r->name, r->qtype); struct lev_dns_delete_records *E = alloc_log_event (LEV_DNS_DELETE_RECORDS + r->name_len, sizeof (struct lev_dns_delete_records) + r->name_len, r->qtype); memcpy (E->name, r->name, r->name_len); last_deleted_record = r; if (compute_uncommitted_log_bytes () > (1 << 23)) { flush_binlog_forced (0); } delete_logevents++; }
int secure_receive_answer_ack (void **IP, void **Data) { int op = (long)*Data; if (op == RPC_REQ_RESULT_ACK) { vkprintf (2, "fun %s\n", __func__); tl_fetch_move (12); received_answer_ack ++; //struct connection *c = CQ->in; struct secure_receive_answer t; t.qid = tl_fetch_long (); // tl_fetch_raw_data (&t, 8); if (tl_fetch_error ()) { return -1; } t.pid = *CQ->remote_pid; //t.pid = RPCC_DATA(c)->remote_pid; struct tree_secure_receive_answer *T = tree_lookup_secure_receive_answer (secure_receive_answer_tree, &t); if (T) { secure_receive_answer_tree = tree_delete_secure_receive_answer (secure_receive_answer_tree, T->x); struct secure_receive_answer *A = T->x; secure_answer_allocated --; free (A->answer); if (A->h) { tl_query_header_delete (A->h); } if (A->binlog) { struct lev_answer_forget *L = alloc_log_event (LEV_ANSWER_FORGET, sizeof (*L), 0); L->qid = t.qid; L->pid = t.pid; delete_binlog_pos (A->binlog_pos, 0); if (binlog_mode_on & 2) { flush_cbinlog (0); } } zfree (A, sizeof (*A)); } //tl_store_init (c, t.qid); tl_init_store (CQ->in_type, CQ->remote_pid, t.qid); tl_store_end_ext (RPC_REQ_RESULT_ACK_ACK); sent_answer_ack_ack ++; return -1; } RPC_FUN_NEXT; }
int _secure_receive_on_alarm (void **IP, void **Data, int binlog) { struct rpc_query *q = *Data; struct secure_receive_answer *A = zmalloc (sizeof (*A)); A->h = 0; A->qid = q->old_qid; A->pid = q->pid; A->answer_op = RPC_REQ_ERROR_WRAPPED; static char buf [1000]; sprintf (buf + 1, "Query timeout: working_time = %lf", precise_now - q->start_time); tl_fetch_set_error (buf + 1, TL_ERROR_QUERY_TIMEOUT); int len = strlen (buf + 1) + 1; int pad = ((len + 3) & ~3) - len; memset (buf + len, 0, pad); buf[0] = len; len += pad; assert (len % 4 == 0); A->answer_len = 4 + len; A->answer = malloc (A->answer_len); A->binlog = 0; *(int *)A->answer = TL_ERROR_QUERY_TIMEOUT; memcpy (((char *)(A->answer)) + 4, buf, len); secure_receive_answer_tree = tree_insert_secure_receive_answer (secure_receive_answer_tree, A, lrand48 ()); secure_answer_allocated ++; if (binlog) { A->binlog_pos = log_last_pos (); insert_binlog_pos (A->binlog_pos, 0); struct lev_answer_tx *L = alloc_log_event (LEV_ANSWER_TX, sizeof (*L) + A->answer_len, 0); L->qid = A->qid; L->pid = A->pid; L->op = A->answer_op; L->answer_len = A->answer_len; memcpy (L->answer, A->answer, A->answer_len); A->binlog = 1; if (binlog_mode_on & 2) { flush_cbinlog (0); } } RPC_FUN_NEXT; }
struct rpc_query *_secure_send_create_rpc_query (long long new_qid, int binlog) { struct rpc_query *q = default_create_rpc_query (new_qid); if (!q) { return q; } struct secure_send_extra *E = zmalloc (sizeof (*E)); E->state = 0; E->data_size = tl.out_pos; E->data = malloc (E->data_size); memset (E->data, 0, E->data_size); assert (TL_OUT_TYPE == tl_type_conn); E->pid = RPCS_DATA(TL_OUT_CONN)->remote_pid; E->timeout = CC->timeout; E->binlog = 0; assert (tl_store_read_back_nondestruct (E->data, E->data_size) == E->data_size); secure_send_s0 ++; /* int i; for (i = 0; i < E->data_size / 4; i++) { fprintf (stderr, "%08x ", ((int *)E->data)[i]); } fprintf (stderr, "\n");*/ q->extra = E; if (binlog) { E->binlog_pos = log_last_pos (); insert_binlog_pos (E->binlog_pos, 0); struct lev_query_tx *L = alloc_log_event (LEV_QUERY_TX, sizeof (*L) + E->data_size, 0); L->qid = q->qid; L->old_qid = q->old_qid; L->cluster_id = CC->id; L->data_size = E->data_size; L->pid = E->pid; L->timeout = E->timeout; memcpy (L->data, E->data, E->data_size); E->binlog = 1; if (binlog_mode_on & 2) { flush_cbinlog (0); } } return q; }
int secure_send_answer_ack_ack (void **IP, void **Data) { vkprintf (2, "fun %s\n", __func__); int op = (long)*Data; if (op == RPC_REQ_RESULT_ACK_ACK) { received_answer_ack_ack ++; tl_fetch_move (12); long long qid = tl_fetch_long (); struct rpc_query *q = get_rpc_query (qid); if (!q) { return 0; } struct secure_send_extra *E = q->extra; if (E->binlog) { struct lev_query_forget *L = alloc_log_event (LEV_QUERY_FORGET, sizeof (*L), 0); L->qid = qid; delete_binlog_pos (E->binlog_pos, 0); if (binlog_mode_on & 2) { flush_cbinlog (0); } } query_on_free (q); return -1; } RPC_FUN_NEXT; }
int _secure_receive_on_answer (void **IP, void **Data, int binlog) { struct rpc_query *q = *Data; struct secure_receive_answer *A = zmalloc (sizeof (*A)); A->qid = q->old_qid; A->pid = q->pid; //A->h = tl_query_header_dup (CQ->h); A->h = 0; static char buf[(1 << 17)]; int r = tl_write_header (CQ->h, (int *)buf, (1 << 17)); assert (r >= 0); A->answer_op = CQ->h->real_op; A->answer_len = tl_fetch_unread () + r; A->answer = malloc (A->answer_len); A->binlog = 0; memcpy (A->answer, buf, r); //int t = tl_fetch_lookup_data (A->answer + r, A->answer_len - r); secure_receive_answer_tree = tree_insert_secure_receive_answer (secure_receive_answer_tree, A, lrand48 ()); secure_answer_allocated ++; if (binlog) { A->binlog_pos = log_last_pos (); insert_binlog_pos (A->binlog_pos, 0); struct lev_answer_tx *L = alloc_log_event (LEV_ANSWER_TX, sizeof (*L) + A->answer_len, 0); L->qid = A->qid; L->pid = A->pid; L->op = A->answer_op; L->answer_len = A->answer_len; memcpy (L->answer, A->answer, A->answer_len); A->binlog = 1; if (binlog_mode_on & 2) { flush_cbinlog (0); } } RPC_FUN_NEXT; }
int loop (void) { on_start (); if (binlog_enabled) { replay_log (); write_binlog (); } else { read_auth_file (); } update_prompt (); assert (DC_list[dc_working_num]); if (!DC_working || !DC_working->auth_key_id) { // if (auth_state == 0) { DC_working = DC_list[dc_working_num]; assert (!DC_working->auth_key_id); dc_authorize (DC_working); assert (DC_working->auth_key_id); auth_state = 100; write_auth_file (); } if (verbosity) { logprintf ("Requesting info about DC...\n"); } do_help_get_config (); net_loop (0, mcs); if (verbosity) { logprintf ("DC_info: %d new DC got\n", new_dc_num); } int i; for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->auth_key_id) { dc_authorize (DC_list[i]); assert (DC_list[i]->auth_key_id); write_auth_file (); } if (auth_state == 100 || !(DC_working->has_auth)) { if (!default_username) { size_t size = 0; char *user = 0; if (!user) { printf ("Telephone number (with '+' sign): "); if (net_getline (&user, &size) == -1) { perror ("getline()"); exit (EXIT_FAILURE); } set_default_username (user); } } int res = do_auth_check_phone (default_username); assert (res >= 0); logprintf ("%s\n", res > 0 ? "phone registered" : "phone not registered"); if (res > 0) { do_send_code (default_username); char *code = 0; size_t size = 0; printf ("Code from sms: "); while (1) { if (net_getline (&code, &size) == -1) { perror ("getline()"); exit (EXIT_FAILURE); } if (do_send_code_result (code) >= 0) { break; } printf ("Invalid code. Try again: "); free (code); } auth_state = 300; } else { printf ("User is not registered. Do you want to register? [Y/n] "); char *code; size_t size; if (net_getline (&code, &size) == -1) { perror ("getline()"); exit (EXIT_FAILURE); } if (!*code || *code == 'y' || *code == 'Y') { printf ("Ok, starting registartion.\n"); } else { printf ("Then try again\n"); exit (EXIT_SUCCESS); } char *first_name; printf ("Name: "); if (net_getline (&first_name, &size) == -1) { perror ("getline()"); exit (EXIT_FAILURE); } char *last_name; printf ("Name: "); if (net_getline (&last_name, &size) == -1) { perror ("getline()"); exit (EXIT_FAILURE); } int dc_num = do_get_nearest_dc (); assert (dc_num >= 0 && dc_num <= MAX_DC_NUM && DC_list[dc_num]); dc_working_num = dc_num; DC_working = DC_list[dc_working_num]; do_send_code (default_username); printf ("Code from sms: "); while (1) { if (net_getline (&code, &size) == -1) { perror ("getline()"); exit (EXIT_FAILURE); } if (do_send_code_result_auth (code, first_name, last_name) >= 0) { break; } printf ("Invalid code. Try again: "); free (code); } auth_state = 300; } } for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->has_auth) { do_export_auth (i); do_import_auth (i); DC_list[i]->has_auth = 1; if (binlog_enabled) { int *ev = alloc_log_event (8); ev[0] = LOG_DC_SIGNED; ev[1] = i; add_log_event (ev, 8); } write_auth_file (); } write_auth_file (); fflush (stdin); fflush (stdout); fflush (stderr); read_state_file (); read_secret_chat_file (); set_interface_callbacks (); do_get_difference (); net_loop (0, dgot); do_get_dialog_list (); return main_loop (); }