Many fixes. Now (maybe) works authorization and get contact list query

This commit is contained in:
Vysheng 2013-10-13 14:18:08 +04:00
parent 3243c29a8c
commit bf291df34a
13 changed files with 277 additions and 92 deletions

View File

@ -6,6 +6,7 @@ LD=cc
SRC=main.c loop.c interface.c net.c mtproto-common.c mtproto-client.c queries.c structures.c
OBJ=$(SRC:.c=.o)
EXE=telegram
HDRS=include.h interface.h loop.h mtproto-client.h mtproto-common.h net.h queries.h structures.h telegram.h tree.h
all: $(SRC) $(EXE)

View File

@ -9,6 +9,10 @@
#include <string.h>
#include "include.h"
#include "queries.h"
#include "interface.h"
#include "telegram.h"
#include "structures.h"
char *default_prompt = ">";
char *get_default_prompt (void) {
@ -23,16 +27,18 @@ char *commands[] = {
"help",
"msg",
"contact_list",
"stats",
0 };
int commands_flags[] = {
070,
072,
00,
07,
07,
};
char *a = 0;
char **user_list = &a;
char *user_list[MAX_USER_NUM + 1];
char **chat_list = &a;
int init_token (char **q) {
@ -91,12 +97,27 @@ int get_complete_mode (void) {
int s = 0;
while (1) {
get_token (&q, &l);
if (!*q) { return flags & 7; }
if (!*q) { return flags ? flags & 7 : 7; }
s ++;
if (s <= 4) { flags >>= 3; }
}
}
extern int user_num;
extern struct user *Users[];
int complete_user_list (int index, const char *text, int len, char **R) {
index ++;
while (index < user_num && (!Users[index]->print_name || strncmp (Users[index]->print_name, text, len))) {
index ++;
}
if (index < user_num) {
*R = strdup (Users[index]->print_name);
return index;
} else {
return -1;
}
}
int complete_string_list (char **list, int index, const char *text, int len, char **R) {
index ++;
while (list[index] && strncmp (list[index], text, len)) {
@ -137,7 +158,7 @@ char *command_generator (const char *text, int state) {
index = complete_string_list (commands, index, text, len, &R);
return R;
case 1:
index = complete_string_list (user_list, index, text, len, &R);
index = complete_user_list (index, text, len, &R);
return R;
case 2:
index = complete_string_list (chat_list, index, text, len, &R);
@ -154,27 +175,90 @@ char **complete_text (char *text, int start UU, int end UU) {
}
void interpreter (char *line UU) {
if (line && *line) {
add_history (line);
}
if (!memcmp (line, "contact_list", 12)) {
do_update_contact_list ();
} else if (!memcmp (line, "stats", 5)) {
static char stat_buf[1 << 15];
print_stat (stat_buf, (1 << 15) - 1);
printf ("%s\n", stat_buf);
}
}
int readline_active;
void rprintf (const char *format, ...) {
int saved_point = rl_point;
char *saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
int saved_point = 0;
char *saved_line = 0;
if (readline_active) {
saved_point = rl_point;
saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
}
va_list ap;
va_start (ap, format);
vfprintf (stdout, format, ap);
va_end (ap);
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);
if (readline_active) {
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);
}
}
void hexdump (int *in_ptr, int *in_end) {
int saved_point = 0;
char *saved_line = 0;
if (readline_active) {
saved_point = rl_point;
saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
}
int *ptr = in_ptr;
while (ptr < in_end) { fprintf (stdout, " %08x", *(ptr ++)); }
fprintf (stdout, "\n");
if (readline_active) {
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);
}
}
void logprintf (const char *format, ...) {
int saved_point = 0;
char *saved_line = 0;
if (readline_active) {
saved_point = rl_point;
saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
}
printf (COLOR_GREY " *** ");
va_list ap;
va_start (ap, format);
vfprintf (stdout, format, ap);
va_end (ap);
printf (COLOR_NORMAL);
if (readline_active) {
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);
}
}

View File

@ -1,9 +1,19 @@
#ifndef __INTERFACE_H__
#define __INTERFACE_H__
#define COLOR_RED "\033[31;1m"
#define COLOR_NORMAL "\033[0m"
#define COLOR_GREEN "\033[32;1m"
#define COLOR_GREY "\033[37;1m"
char *get_default_prompt (void);
char *complete_none (const char *text, int state);
char **complete_text (char *text, int start, int end);
void interpreter (char *line);
void rprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void iprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void hexdump (int *in_ptr, int *in_end);
#endif

2
loop.c
View File

@ -167,6 +167,7 @@ void read_auth_file (void) {
close (auth_file_fd);
}
int readline_active;
int loop (void) {
on_start ();
read_auth_file ();
@ -216,6 +217,7 @@ int loop (void) {
fflush (stdout);
fflush (stderr);
readline_active = 1;
rl_callback_handler_install (get_default_prompt (), interpreter);
rl_attempted_completion_function = (CPPFunction *) complete_text;
rl_completion_entry_function = complete_none;

View File

@ -22,6 +22,7 @@
#include "include.h"
#include "queries.h"
#include "loop.h"
#include "interface.h"
#define sha1 SHA1
@ -89,13 +90,13 @@ static int rsa_load_public_key (const char *public_key_name) {
pubKey = NULL;
FILE *f = fopen (public_key_name, "r");
if (f == NULL) {
fprintf (stderr, "Couldn't open public key file: %s\n", public_key_name);
logprintf ( "Couldn't open public key file: %s\n", public_key_name);
return -1;
}
pubKey = PEM_read_RSAPublicKey (f, NULL, NULL, NULL);
fclose (f);
if (pubKey == NULL) {
fprintf (stderr, "PEM_read_RSAPublicKey returns NULL.\n");
logprintf ( "PEM_read_RSAPublicKey returns NULL.\n");
return -1;
}
@ -205,7 +206,7 @@ unsigned p1, p2;
int process_respq_answer (struct connection *c, char *packet, int len) {
int i;
if (verbosity) {
fprintf (stderr, "process_respq_answer(), len=%d\n", len);
logprintf ( "process_respq_answer(), len=%d\n", len);
}
assert (len >= 76);
assert (!*(long long *) packet);
@ -227,7 +228,7 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
p1 = 0, p2 = 0;
if (verbosity >= 2) {
fprintf (stderr, "%lld received\n", what);
logprintf ( "%lld received\n", what);
}
int it = 0;
@ -275,7 +276,7 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
if (verbosity) {
fprintf (stderr, "p1 = %d, p2 = %d, %d iterations\n", p1, p2, it);
logprintf ( "p1 = %d, p2 = %d, %d iterations\n", p1, p2, it);
}
/// ++p1; ///
@ -286,12 +287,12 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
long long *fingerprints = (long long *) (from + 8);
for (i = 0; i < fingerprints_num; i++) {
if (fingerprints[i] == pk_fingerprint) {
//fprintf (stderr, "found our public key at position %d\n", i);
//logprintf ( "found our public key at position %d\n", i);
break;
}
}
if (i == fingerprints_num) {
fprintf (stderr, "fatal: don't have any matching keys (%016llx expected)\n", pk_fingerprint);
logprintf ( "fatal: don't have any matching keys (%016llx expected)\n", pk_fingerprint);
exit (2);
}
// create inner part (P_Q_inner_data)
@ -378,10 +379,10 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
int process_dh_answer (struct connection *c, char *packet, int len) {
if (verbosity) {
fprintf (stderr, "process_dh_answer(), len=%d\n", len);
logprintf ( "process_dh_answer(), len=%d\n", len);
}
if (len < 116) {
fprintf (stderr, "%u * %u = %llu", p1, p2, what);
logprintf ( "%u * %u = %llu", p1, p2, what);
}
assert (len >= 116);
assert (!*(long long *) packet);
@ -418,7 +419,7 @@ int process_dh_answer (struct connection *c, char *packet, int len) {
GET_DC(c)->server_time_delta = server_time - time (0);
GET_DC(c)->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC);
//fprintf (stderr, "server time is %d, delta = %d\n", server_time, server_time_delta);
//logprintf ( "server time is %d, delta = %d\n", server_time, server_time_delta);
// Build set_client_DH_params answer
clear_packet ();
@ -474,7 +475,7 @@ int process_dh_answer (struct connection *c, char *packet, int len) {
int process_auth_complete (struct connection *c UU, char *packet, int len) {
if (verbosity) {
fprintf (stderr, "process_dh_answer(), len=%d\n", len);
logprintf ( "process_dh_answer(), len=%d\n", len);
}
assert (len == 72);
assert (!*(long long *) packet);
@ -493,7 +494,7 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce;
if (verbosity >= 3) {
fprintf (stderr, "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id);
logprintf ( "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id);
}
//kprintf ("OK\n");
@ -503,7 +504,7 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
c_state = st_authorized;
//return 1;
if (verbosity) {
fprintf (stderr, "Auth success\n");
logprintf ( "Auth success\n");
}
auth_success ++;
GET_DC(c)->flags |= 1;
@ -568,7 +569,7 @@ int aes_encrypt_message (struct dc *DC, struct encrypted_message *enc) {
sha1 ((unsigned char *) &enc->server_salt, enc_len, sha1_buffer);
//printf ("enc_len is %d\n", enc_len);
if (verbosity >= 2) {
fprintf (stderr, "sending message with sha1 %08x\n", *(int *)sha1_buffer);
logprintf ( "sending message with sha1 %08x\n", *(int *)sha1_buffer);
}
memcpy (enc->msg_key, sha1_buffer + 4, 16);
init_aes_auth (DC->auth_key, enc->msg_key, AES_ENCRYPT);
@ -612,7 +613,7 @@ int auth_work_start (struct connection *c UU) {
void rpc_execute_answer (struct connection *c, long long msg_id UU);
void work_container (struct connection *c, long long msg_id UU) {
if (verbosity) {
fprintf (stderr, "work_container: msg_id = %lld\n", msg_id);
logprintf ( "work_container: msg_id = %lld\n", msg_id);
}
assert (fetch_int () == CODE_msg_container);
int n = fetch_int ();
@ -632,7 +633,7 @@ void work_container (struct connection *c, long long msg_id UU) {
void work_new_session_created (struct connection *c, long long msg_id UU) {
if (verbosity) {
fprintf (stderr, "work_new_session_created: msg_id = %lld\n", msg_id);
logprintf ( "work_new_session_created: msg_id = %lld\n", msg_id);
}
assert (fetch_int () == (int)CODE_new_session_created);
fetch_long (); // first message id
@ -643,7 +644,7 @@ void work_new_session_created (struct connection *c, long long msg_id UU) {
void work_msgs_ack (struct connection *c UU, long long msg_id UU) {
if (verbosity) {
fprintf (stderr, "work_msgs_ack: msg_id = %lld\n", msg_id);
logprintf ( "work_msgs_ack: msg_id = %lld\n", msg_id);
}
assert (fetch_int () == CODE_msgs_ack);
assert (fetch_int () == CODE_vector);
@ -657,7 +658,7 @@ void work_msgs_ack (struct connection *c UU, long long msg_id UU) {
void work_rpc_result (struct connection *c UU, long long msg_id UU) {
if (verbosity) {
fprintf (stderr, "work_rpc_result: msg_id = %lld\n", msg_id);
logprintf ( "work_rpc_result: msg_id = %lld\n", msg_id);
}
assert (fetch_int () == (int)CODE_rpc_result);
long long id = fetch_long ();
@ -685,7 +686,7 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) {
work_rpc_result (c, msg_id);
return;
}
fprintf (stderr, "Unknown message: \n");
logprintf ( "Unknown message: \n");
hexdump_in ();
}
@ -693,7 +694,7 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
const int MINSZ = offsetof (struct encrypted_message, message);
const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
if (verbosity) {
fprintf (stderr, "process_rpc_message(), len=%d\n", len);
logprintf ( "process_rpc_message(), len=%d\n", len);
}
assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
struct dc *DC = GET_DC(c);
@ -717,7 +718,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 >= 2) {
fprintf (stderr, "received mesage id %016llx\n", enc->msg_id);
logprintf ( "received mesage id %016llx\n", enc->msg_id);
}
server_last_msg_id = enc->msg_id;
@ -727,7 +728,7 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
assert (l >= (MINSZ - UNENCSZ) + 8);
//assert (enc->message[0] == CODE_rpc_result && *(long long *)(enc->message + 1) == client_last_msg_id);
if (verbosity >= 2) {
fprintf (stderr, "OK, message is good!\n");
logprintf ( "OK, message is good!\n");
}
++good_messages;
@ -745,11 +746,11 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc,
int rpc_execute (struct connection *c, int op, int len) {
if (verbosity) {
fprintf (stderr, "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
}
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
fprintf (stderr, "answer too long (%d bytes), skipping\n", len);
logprintf ( "answer too long (%d bytes), skipping\n", len);
return 0;
}
@ -758,7 +759,7 @@ int rpc_execute (struct connection *c, int op, int len) {
assert (read_in (c, Response, Response_len) == Response_len);
Response[Response_len] = 0;
if (verbosity >= 2) {
fprintf (stderr, "have %d Response bytes\n", Response_len);
logprintf ( "have %d Response bytes\n", Response_len);
}
setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
@ -782,7 +783,7 @@ int rpc_execute (struct connection *c, int op, int len) {
setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
return 0;
default:
fprintf (stderr, "fatal: cannot receive answer in state %d\n", c_state);
logprintf ( "fatal: cannot receive answer in state %d\n", c_state);
exit (2);
}
@ -792,14 +793,14 @@ int rpc_execute (struct connection *c, int op, int len) {
int tc_close (struct connection *c, int who) {
if (verbosity) {
fprintf (stderr, "outbound http connection #%d : closing by %d\n", c->fd, who);
logprintf ( "outbound http connection #%d : closing by %d\n", c->fd, who);
}
return 0;
}
int tc_becomes_ready (struct connection *c) {
if (verbosity) {
fprintf (stderr, "outbound connection #%d becomes ready\n", c->fd);
logprintf ( "outbound connection #%d becomes ready\n", c->fd);
}
char byte = 0xef;
assert (write_out (c, &byte, 1) == 1);
@ -816,7 +817,7 @@ int tc_becomes_ready (struct connection *c) {
auth_work_start (c);
break;
default:
fprintf (stderr, "c_state = %d\n", c_state);
logprintf ( "c_state = %d\n", c_state);
assert (0);
}
return 0;
@ -842,7 +843,7 @@ void on_start (void) {
exit (1);
}
if (verbosity) {
fprintf (stderr, "public key '%s' loaded successfully\n", rsa_public_key_name);
logprintf ( "public key '%s' loaded successfully\n", rsa_public_key_name);
}
pk_fingerprint = compute_rsa_key_fingerprint (pubKey);
}
@ -858,7 +859,7 @@ void dc_authorize (struct dc *DC) {
dc_create_session (DC);
}
if (verbosity) {
fprintf (stderr, "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port);
logprintf ( "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port);
}
net_loop (0, auth_ok);
}

View File

@ -16,6 +16,7 @@
#include <openssl/sha.h>
#include "mtproto-common.h"
#include "interface.h"
long long rsa_encrypted_chunks, rsa_decrypted_chunks;
@ -28,7 +29,7 @@ int get_random_bytes (void *buf, int n) {
r = read (h, buf, n);
if (r > 0) {
if (verbosity >= 3) {
fprintf (stderr, "added %d bytes of real entropy to secure random numbers seed\n", r);
logprintf ( "added %d bytes of real entropy to secure random numbers seed\n", r);
}
}
close (h);
@ -71,14 +72,14 @@ void prng_seed (const char *password_filename, int password_length) {
if (password_filename) {
int fd = open (password_filename, O_RDONLY);
if (fd < 0) {
fprintf (stderr, "Warning: fail to open password file - \"%s\", %m.\n", password_filename);
logprintf ( "Warning: fail to open password file - \"%s\", %m.\n", password_filename);
} else {
int l = read (fd, a + s, password_length);
if (l < 0) {
fprintf (stderr, "Warning: fail to read password file - \"%s\", %m.\n", password_filename);
logprintf ( "Warning: fail to read password file - \"%s\", %m.\n", password_filename);
} else {
if (verbosity > 0) {
fprintf (stderr, "read %d bytes from password file.\n", l);
logprintf ( "read %d bytes from password file.\n", l);
}
s += l;
}

View File

@ -7,6 +7,7 @@
#include <openssl/aes.h>
#include <stdio.h>
#include "interface.h"
/* DH key exchange protocol data structures */
#define CODE_req_pq 0x60469778
#define CODE_resPQ 0x05162463
@ -409,8 +410,6 @@ int pad_aes_encrypt (char *from, int from_len, char *to, int size);
int pad_aes_decrypt (char *from, int from_len, char *to, int size);
static inline void hexdump_in (void) {
int *ptr = in_ptr;
while (ptr < in_end) { fprintf (stderr, " %08x", *(ptr ++)); }
fprintf (stderr, "\n");
hexdump (in_ptr, in_end);
}
#endif

27
net.c
View File

@ -17,6 +17,7 @@
#include "mtproto-client.h"
#include "mtproto-common.h"
#include "tree.h"
#include "interface.h"
DEFINE_TREE(int,int,int_cmp,0)
@ -156,7 +157,7 @@ struct connection *create_connection (const char *host, int port, struct session
if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
if (errno != EINPROGRESS) {
fprintf (stderr, "Can not connect to %s:%d %m\n", host, port);
logprintf ( "Can not connect to %s:%d %m\n", host, port);
close (fd);
free (c);
return 0;
@ -183,7 +184,7 @@ struct connection *create_connection (const char *host, int port, struct session
assert (!Connections[fd]);
Connections[fd] = c;
if (verbosity) {
fprintf (stderr, "connect to %s:%d successful\n", host, port);
logprintf ( "connect to %s:%d successful\n", host, port);
}
if (c->methods->ready) {
c->methods->ready (c);
@ -211,7 +212,7 @@ void fail_connection (struct connection *c) {
void try_write (struct connection *c) {
if (verbosity) {
fprintf (stderr, "try write: fd = %d\n", c->fd);
logprintf ( "try write: fd = %d\n", c->fd);
}
int x = 0;
while (c->out_head) {
@ -238,12 +239,12 @@ void try_write (struct connection *c) {
}
}
if (verbosity) {
fprintf (stderr, "Sent %d bytes to %d\n", x, c->fd);
logprintf ( "Sent %d bytes to %d\n", x, c->fd);
}
c->out_bytes -= x;
}
void hexdump (struct connection_buffer *b) {
void hexdump_buf (struct connection_buffer *b) {
int pos = 0;
int rem = 8;
while (b) {
@ -270,7 +271,7 @@ void hexdump (struct connection_buffer *b) {
void try_rpc_read (struct connection *c) {
assert (c->in_head);
if (verbosity >= 4) {
hexdump (c->in_head);
hexdump_buf (c->in_head);
}
while (1) {
@ -307,7 +308,7 @@ void try_rpc_read (struct connection *c) {
void try_read (struct connection *c) {
if (verbosity) {
fprintf (stderr, "try read: fd = %d\n", c->fd);
logprintf ( "try read: fd = %d\n", c->fd);
}
if (!c->in_tail) {
c->in_head = c->in_tail = new_connection_buffer (1 << 20);
@ -334,7 +335,7 @@ void try_read (struct connection *c) {
}
}
if (verbosity) {
fprintf (stderr, "Received %d bytes from %d\n", x, c->fd);
logprintf ( "Received %d bytes from %d\n", x, c->fd);
}
c->in_bytes += x;
if (x) {
@ -356,15 +357,15 @@ int connections_make_poll_array (struct pollfd *fds, int max) {
fds ++;
max --;
}
if (verbosity >= 3) {
fprintf (stderr, "%d connections in poll\n", _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 >= 2) {
fprintf (stderr, "connections_poll_result: max = %d\n", max);
if (verbosity >= 10) {
logprintf ( "connections_poll_result: max = %d\n", max);
}
int i;
for (i = 0; i < max; i++) {
@ -374,7 +375,7 @@ void connections_poll_result (struct pollfd *fds, int max) {
}
if (fds[i].revents & (POLLHUP | POLLERR | POLLRDHUP)) {
if (verbosity) {
fprintf (stderr, "fail connection\n");
logprintf ( "fail connection\n");
}
fail_connection (c);
} else if (fds[i].revents & POLLOUT) {

View File

@ -43,7 +43,7 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
dc_create_session (DC);
}
if (verbosity) {
fprintf (stderr, "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
logprintf ( "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
}
struct query *q = malloc (sizeof (*q));
q->data_len = ints;
@ -51,11 +51,11 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
memcpy (q->data, data, 4 * ints);
q->msg_id = encrypt_send_message (DC->sessions[0]->c, data, ints, 1);
if (verbosity) {
fprintf (stderr, "Msg_id is %lld\n", q->msg_id);
logprintf ( "Msg_id is %lld\n", q->msg_id);
}
q->methods = methods;
if (queries_tree) {
fprintf (stderr, "%lld %lld\n", q->msg_id, queries_tree->x->msg_id);
logprintf ( "%lld %lld\n", q->msg_id, queries_tree->x->msg_id);
}
queries_tree = tree_insert_query (queries_tree, q, lrand48 ());
@ -77,12 +77,12 @@ void query_error (long long id) {
int error_len = prefetch_strlen ();
char *error = fetch_str (error_len);
if (verbosity) {
fprintf (stderr, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
logprintf ( "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
}
struct query *q = query_get (id);
if (!q) {
if (verbosity) {
fprintf (stderr, "No such query\n");
logprintf ( "No such query\n");
}
} else {
remove_event_timer (&q->ev);
@ -100,10 +100,10 @@ static int packed_buffer[MAX_PACKED_SIZE / 4];
void query_result (long long id UU) {
if (verbosity) {
fprintf (stderr, "result for query #%lld\n", id);
logprintf ( "result for query #%lld\n", id);
}
if (verbosity >= 4) {
fprintf (stderr, "result: ");
logprintf ( "result: ");
hexdump_in ();
}
int op = prefetch_int ();
@ -124,8 +124,8 @@ void query_result (long long id UU) {
int err = inflate (&strm, Z_FINISH);
if (verbosity) {
fprintf (stderr, "inflate error = %d\n", err);
fprintf (stderr, "inflated %d bytes\n", (int)strm.total_out);
logprintf ( "inflate error = %d\n", err);
logprintf ( "inflated %d bytes\n", (int)strm.total_out);
}
end = in_ptr;
eend = in_end;
@ -133,14 +133,14 @@ void query_result (long long id UU) {
in_ptr = packed_buffer;
in_end = in_ptr + strm.total_out / 4;
if (verbosity >= 4) {
fprintf (stderr, "Unzipped data: ");
logprintf ( "Unzipped data: ");
hexdump_in ();
}
}
struct query *q = query_get (id);
if (!q) {
if (verbosity) {
fprintf (stderr, "No such query\n");
logprintf ( "No such query\n");
}
} else {
remove_event_timer (&q->ev);
@ -162,16 +162,18 @@ DEFINE_TREE (timer, struct event_timer *, event_timer_cmp, 0)
struct tree_timer *timer_tree;
void insert_event_timer (struct event_timer *ev) {
return;
fprintf (stderr, "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
if (verbosity > 2) {
logprintf ( "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
}
tree_check_timer (timer_tree);
timer_tree = tree_insert_timer (timer_tree, ev, lrand48 ());
tree_check_timer (timer_tree);
}
void remove_event_timer (struct event_timer *ev) {
return;
fprintf (stderr, "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
if (verbosity > 2) {
logprintf ( "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
}
tree_check_timer (timer_tree);
timer_tree = tree_delete_timer (timer_tree, ev);
tree_check_timer (timer_tree);
@ -207,7 +209,7 @@ int help_get_config_on_answer (struct query *q UU) {
assert (test_mode == CODE_bool_false);
int this_dc = fetch_int ();
if (verbosity) {
fprintf (stderr, "this_dc = %d\n", this_dc);
logprintf ( "this_dc = %d\n", this_dc);
}
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
@ -222,7 +224,7 @@ int help_get_config_on_answer (struct query *q UU) {
char *ip = fetch_str (l2);
int port = fetch_int ();
if (verbosity) {
fprintf (stderr, "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
}
if (!DC_list[id]) {
alloc_dc (id, strndup (ip, l2), port);
@ -230,7 +232,7 @@ int help_get_config_on_answer (struct query *q UU) {
}
max_chat_size = fetch_int ();
if (verbosity >= 2) {
fprintf (stderr, "chat_size = %d\n", max_chat_size);
logprintf ( "chat_size = %d\n", max_chat_size);
}
return 0;
}
@ -259,7 +261,7 @@ int send_code_on_error (struct query *q UU, int error_code, int l, char *error)
int i = error[s] - '0';
want_dc_num = i;
} else {
fprintf (stderr, "error_code = %d, error = %.*s\n", error_code, l, error);
logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error);
assert (0);
}
return 0;
@ -343,13 +345,13 @@ int sign_in_on_answer (struct query *q UU) {
fetch_user (&User);
sign_in_ok = 1;
if (verbosity) {
fprintf (stderr, "authorized successfully: name = '%s %s', phone = '%s', expires = %d\n", User.first_name, User.last_name, User.phone, (int)(expires - get_double_time ()));
logprintf ( "authorized successfully: name = '%s %s', phone = '%s', expires = %d\n", User.first_name, User.last_name, User.phone, (int)(expires - get_double_time ()));
}
return 0;
}
int sign_in_on_error (struct query *q UU, int error_code, int l, char *error) {
fprintf (stderr, "error_code = %d, error = %.*s\n", error_code, l, error);
logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error);
sign_in_ok = -1;
return 0;
}
@ -371,11 +373,13 @@ int do_send_code_result (const char *code) {
return sign_in_ok;
}
extern char *user_list[];
int get_contacts_on_answer (struct query *q UU) {
int i;
assert (fetch_int () == (int)CODE_contacts_contacts);
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
int i;
for (i = 0; i < n; i++) {
assert (fetch_int () == (int)CODE_contact);
fetch_int (); // id
@ -384,9 +388,8 @@ int get_contacts_on_answer (struct query *q UU) {
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
struct user User;
fetch_user (&User);
rprintf ("User: id = %d, first_name = %s, last_name = %s\n", User.id, User.first_name, User.last_name);
struct user *U = fetch_alloc_user ();
rprintf ("User #%d: " COLOR_RED "%s %s" COLOR_NORMAL " (" COLOR_GREEN "%s" COLOR_NORMAL ")\n", U->id, U->first_name, U->last_name, U->print_name);
}
return 0;
}

View File

@ -1,6 +1,8 @@
#include <assert.h>
#include "structures.h"
#include "mtproto-common.h"
#include "telegram.h"
#include "tree.h"
void fetch_file_location (struct file_location *loc) {
int x = fetch_int ();
@ -48,6 +50,25 @@ void fetch_user (struct user *U) {
}
U->first_name = fetch_str_dup ();
U->last_name = fetch_str_dup ();
if (!strlen (U->first_name)) {
if (!strlen (U->last_name)) {
U->print_name = strdup ("none");
} else {
U->print_name = strdup (U->last_name);
}
} else {
if (!strlen (U->last_name)) {
U->print_name = strdup (U->first_name);
} else {
U->print_name = malloc (strlen (U->first_name) + strlen (U->last_name) + 2);
sprintf (U->print_name, "%s_%s", U->first_name, U->last_name);
}
}
char *s = U->print_name;
while (*s) {
if (*s == ' ') { *s = '_'; }
s++;
}
if (x == CODE_user_deleted) {
U->flags = 2;
return;
@ -79,3 +100,46 @@ void fetch_user (struct user *U) {
U->flags |= 16;
}
}
#define user_cmp(a,b) ((a)->id - (b)->id)
DEFINE_TREE(user,struct user *,user_cmp,0)
struct tree_user *user_tree;
int user_num;
struct user *Users[MAX_USER_NUM];
int users_allocated;
struct user *fetch_alloc_user (void) {
struct user *U = malloc (sizeof (*U));
fetch_user (U);
users_allocated ++;
struct user *U1 = tree_lookup_user (user_tree, U);
if (U1) {
free_user (U1);
memcpy (U1, U, sizeof (*U));
free (U);
users_allocated --;
return U1;
} else {
user_tree = tree_insert_user (user_tree, U, lrand48 ());
Users[user_num ++] = U;
return U;
}
}
void free_user (struct user *U) {
if (U->first_name) { free (U->first_name); }
if (U->last_name) { free (U->last_name); }
if (U->print_name) { free (U->print_name); }
if (U->phone) { free (U->phone); }
}
int print_stat (char *s, int len) {
return snprintf (s, len,
"user_num\t%d\n"
"users_allocated\t%d\n",
user_num,
users_allocated);
}

View File

@ -20,6 +20,7 @@ struct user {
char *first_name;
char *last_name;
char *phone;
char *print_name;
long long access_hash;
struct file_location photo_big;
struct file_location photo_small;
@ -28,4 +29,9 @@ struct user {
void fetch_file_location (struct file_location *loc);
void fetch_user (struct user *U);
struct user *fetch_alloc_user (void);
void free_user (struct user *U);
int print_stat (char *s, int len);
#endif

View File

@ -1 +1,2 @@
#define MAX_DC_NUM 9
#define MAX_USER_NUM 1000

14
tree.h
View File

@ -51,7 +51,12 @@ struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYP
} else {\
int c = X_CMP (x, T->x);\
assert (c);\
return tree_insert_ ## X_NAME (c < 0 ? T->left : T->right, x, y);\
if (c < 0) { \
T->left = tree_insert_ ## X_NAME (T->left, x, y);\
} else { \
T->right = tree_insert_ ## X_NAME (T->right, x, y);\
} \
return T; \
}\
}\
}\
@ -96,6 +101,13 @@ 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)) {\
if (!T) { return; } \
tree_act_ ## X_NAME (T->left, act); \
act (T->x); \
tree_act_ ## X_NAME (T->right, act); \
}\
\
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); \