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 SRC=main.c loop.c interface.c net.c mtproto-common.c mtproto-client.c queries.c structures.c
OBJ=$(SRC:.c=.o) OBJ=$(SRC:.c=.o)
EXE=telegram 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) all: $(SRC) $(EXE)

View File

@ -9,6 +9,10 @@
#include <string.h> #include <string.h>
#include "include.h" #include "include.h"
#include "queries.h" #include "queries.h"
#include "interface.h"
#include "telegram.h"
#include "structures.h"
char *default_prompt = ">"; char *default_prompt = ">";
char *get_default_prompt (void) { char *get_default_prompt (void) {
@ -23,16 +27,18 @@ char *commands[] = {
"help", "help",
"msg", "msg",
"contact_list", "contact_list",
"stats",
0 }; 0 };
int commands_flags[] = { int commands_flags[] = {
070, 070,
072, 072,
00, 07,
07,
}; };
char *a = 0; char *a = 0;
char **user_list = &a; char *user_list[MAX_USER_NUM + 1];
char **chat_list = &a; char **chat_list = &a;
int init_token (char **q) { int init_token (char **q) {
@ -91,12 +97,27 @@ int get_complete_mode (void) {
int s = 0; int s = 0;
while (1) { while (1) {
get_token (&q, &l); get_token (&q, &l);
if (!*q) { return flags & 7; } if (!*q) { return flags ? flags & 7 : 7; }
s ++; s ++;
if (s <= 4) { flags >>= 3; } 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) { int complete_string_list (char **list, int index, const char *text, int len, char **R) {
index ++; index ++;
while (list[index] && strncmp (list[index], text, len)) { 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); index = complete_string_list (commands, index, text, len, &R);
return R; return R;
case 1: case 1:
index = complete_string_list (user_list, index, text, len, &R); index = complete_user_list (index, text, len, &R);
return R; return R;
case 2: case 2:
index = complete_string_list (chat_list, index, text, len, &R); 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) { void interpreter (char *line UU) {
if (line && *line) {
add_history (line);
}
if (!memcmp (line, "contact_list", 12)) { if (!memcmp (line, "contact_list", 12)) {
do_update_contact_list (); 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, ...) { void rprintf (const char *format, ...) {
int saved_point = 0;
int saved_point = rl_point; char *saved_line = 0;
char *saved_line = rl_copy_text(0, rl_end); if (readline_active) {
rl_save_prompt(); saved_point = rl_point;
rl_replace_line("", 0); saved_line = rl_copy_text(0, rl_end);
rl_redisplay(); rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
}
va_list ap; va_list ap;
va_start (ap, format); va_start (ap, format);
vfprintf (stdout, format, ap); vfprintf (stdout, format, ap);
va_end (ap); va_end (ap);
rl_restore_prompt(); if (readline_active) {
rl_replace_line(saved_line, 0); rl_restore_prompt();
rl_point = saved_point; rl_replace_line(saved_line, 0);
rl_redisplay(); rl_point = saved_point;
free(saved_line); 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__ #ifndef __INTERFACE_H__
#define __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 *get_default_prompt (void);
char *complete_none (const char *text, int state); char *complete_none (const char *text, int state);
char **complete_text (char *text, int start, int end); char **complete_text (char *text, int start, int end);
void interpreter (char *line); void interpreter (char *line);
void rprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); 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 #endif

2
loop.c
View File

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

View File

@ -22,6 +22,7 @@
#include "include.h" #include "include.h"
#include "queries.h" #include "queries.h"
#include "loop.h" #include "loop.h"
#include "interface.h"
#define sha1 SHA1 #define sha1 SHA1
@ -89,13 +90,13 @@ static int rsa_load_public_key (const char *public_key_name) {
pubKey = NULL; pubKey = NULL;
FILE *f = fopen (public_key_name, "r"); FILE *f = fopen (public_key_name, "r");
if (f == NULL) { 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; return -1;
} }
pubKey = PEM_read_RSAPublicKey (f, NULL, NULL, NULL); pubKey = PEM_read_RSAPublicKey (f, NULL, NULL, NULL);
fclose (f); fclose (f);
if (pubKey == NULL) { if (pubKey == NULL) {
fprintf (stderr, "PEM_read_RSAPublicKey returns NULL.\n"); logprintf ( "PEM_read_RSAPublicKey returns NULL.\n");
return -1; return -1;
} }
@ -205,7 +206,7 @@ unsigned p1, p2;
int process_respq_answer (struct connection *c, char *packet, int len) { int process_respq_answer (struct connection *c, char *packet, int len) {
int i; int i;
if (verbosity) { if (verbosity) {
fprintf (stderr, "process_respq_answer(), len=%d\n", len); logprintf ( "process_respq_answer(), len=%d\n", len);
} }
assert (len >= 76); assert (len >= 76);
assert (!*(long long *) packet); assert (!*(long long *) packet);
@ -227,7 +228,7 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
p1 = 0, p2 = 0; p1 = 0, p2 = 0;
if (verbosity >= 2) { if (verbosity >= 2) {
fprintf (stderr, "%lld received\n", what); logprintf ( "%lld received\n", what);
} }
int it = 0; int it = 0;
@ -275,7 +276,7 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
if (verbosity) { 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; /// /// ++p1; ///
@ -286,12 +287,12 @@ int process_respq_answer (struct connection *c, char *packet, int len) {
long long *fingerprints = (long long *) (from + 8); long long *fingerprints = (long long *) (from + 8);
for (i = 0; i < fingerprints_num; i++) { for (i = 0; i < fingerprints_num; i++) {
if (fingerprints[i] == pk_fingerprint) { 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; break;
} }
} }
if (i == fingerprints_num) { 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); exit (2);
} }
// create inner part (P_Q_inner_data) // 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) { int process_dh_answer (struct connection *c, char *packet, int len) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "process_dh_answer(), len=%d\n", len); logprintf ( "process_dh_answer(), len=%d\n", len);
} }
if (len < 116) { if (len < 116) {
fprintf (stderr, "%u * %u = %llu", p1, p2, what); logprintf ( "%u * %u = %llu", p1, p2, what);
} }
assert (len >= 116); assert (len >= 116);
assert (!*(long long *) packet); 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_delta = server_time - time (0);
GET_DC(c)->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC); 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 // Build set_client_DH_params answer
clear_packet (); 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) { int process_auth_complete (struct connection *c UU, char *packet, int len) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "process_dh_answer(), len=%d\n", len); logprintf ( "process_dh_answer(), len=%d\n", len);
} }
assert (len == 72); assert (len == 72);
assert (!*(long long *) packet); 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)); assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce; GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce;
if (verbosity >= 3) { 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"); //kprintf ("OK\n");
@ -503,7 +504,7 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
c_state = st_authorized; c_state = st_authorized;
//return 1; //return 1;
if (verbosity) { if (verbosity) {
fprintf (stderr, "Auth success\n"); logprintf ( "Auth success\n");
} }
auth_success ++; auth_success ++;
GET_DC(c)->flags |= 1; 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); sha1 ((unsigned char *) &enc->server_salt, enc_len, sha1_buffer);
//printf ("enc_len is %d\n", enc_len); //printf ("enc_len is %d\n", enc_len);
if (verbosity >= 2) { 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); memcpy (enc->msg_key, sha1_buffer + 4, 16);
init_aes_auth (DC->auth_key, enc->msg_key, AES_ENCRYPT); 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 rpc_execute_answer (struct connection *c, long long msg_id UU);
void work_container (struct connection *c, long long msg_id UU) { void work_container (struct connection *c, long long msg_id UU) {
if (verbosity) { 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); assert (fetch_int () == CODE_msg_container);
int n = fetch_int (); 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) { void work_new_session_created (struct connection *c, long long msg_id UU) {
if (verbosity) { 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); assert (fetch_int () == (int)CODE_new_session_created);
fetch_long (); // first message id 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) { void work_msgs_ack (struct connection *c UU, long long msg_id UU) {
if (verbosity) { 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_msgs_ack);
assert (fetch_int () == CODE_vector); 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) { void work_rpc_result (struct connection *c UU, long long msg_id UU) {
if (verbosity) { 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); assert (fetch_int () == (int)CODE_rpc_result);
long long id = fetch_long (); 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); work_rpc_result (c, msg_id);
return; return;
} }
fprintf (stderr, "Unknown message: \n"); logprintf ( "Unknown message: \n");
hexdump_in (); 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 MINSZ = offsetof (struct encrypted_message, message);
const int UNENCSZ = offsetof (struct encrypted_message, server_salt); const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
if (verbosity) { 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)); assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
struct dc *DC = GET_DC(c); 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 (this_server_time >= st - 300 && this_server_time <= st + 30);
//assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1); //assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1);
if (verbosity >= 2) { 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; 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 (l >= (MINSZ - UNENCSZ) + 8);
//assert (enc->message[0] == CODE_rpc_result && *(long long *)(enc->message + 1) == client_last_msg_id); //assert (enc->message[0] == CODE_rpc_result && *(long long *)(enc->message + 1) == client_last_msg_id);
if (verbosity >= 2) { if (verbosity >= 2) {
fprintf (stderr, "OK, message is good!\n"); logprintf ( "OK, message is good!\n");
} }
++good_messages; ++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) { int rpc_execute (struct connection *c, int op, int len) {
if (verbosity) { 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*/) { 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; 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); assert (read_in (c, Response, Response_len) == Response_len);
Response[Response_len] = 0; Response[Response_len] = 0;
if (verbosity >= 2) { 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); 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); setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
return 0; return 0;
default: 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); exit (2);
} }
@ -792,14 +793,14 @@ int rpc_execute (struct connection *c, int op, int len) {
int tc_close (struct connection *c, int who) { int tc_close (struct connection *c, int who) {
if (verbosity) { 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; return 0;
} }
int tc_becomes_ready (struct connection *c) { int tc_becomes_ready (struct connection *c) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "outbound connection #%d becomes ready\n", c->fd); logprintf ( "outbound connection #%d becomes ready\n", c->fd);
} }
char byte = 0xef; char byte = 0xef;
assert (write_out (c, &byte, 1) == 1); assert (write_out (c, &byte, 1) == 1);
@ -816,7 +817,7 @@ int tc_becomes_ready (struct connection *c) {
auth_work_start (c); auth_work_start (c);
break; break;
default: default:
fprintf (stderr, "c_state = %d\n", c_state); logprintf ( "c_state = %d\n", c_state);
assert (0); assert (0);
} }
return 0; return 0;
@ -842,7 +843,7 @@ void on_start (void) {
exit (1); exit (1);
} }
if (verbosity) { 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); pk_fingerprint = compute_rsa_key_fingerprint (pubKey);
} }
@ -858,7 +859,7 @@ void dc_authorize (struct dc *DC) {
dc_create_session (DC); dc_create_session (DC);
} }
if (verbosity) { 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); net_loop (0, auth_ok);
} }

View File

@ -16,6 +16,7 @@
#include <openssl/sha.h> #include <openssl/sha.h>
#include "mtproto-common.h" #include "mtproto-common.h"
#include "interface.h"
long long rsa_encrypted_chunks, rsa_decrypted_chunks; 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); r = read (h, buf, n);
if (r > 0) { if (r > 0) {
if (verbosity >= 3) { 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); close (h);
@ -71,14 +72,14 @@ void prng_seed (const char *password_filename, int password_length) {
if (password_filename) { if (password_filename) {
int fd = open (password_filename, O_RDONLY); int fd = open (password_filename, O_RDONLY);
if (fd < 0) { 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 { } else {
int l = read (fd, a + s, password_length); int l = read (fd, a + s, password_length);
if (l < 0) { 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 { } else {
if (verbosity > 0) { if (verbosity > 0) {
fprintf (stderr, "read %d bytes from password file.\n", l); logprintf ( "read %d bytes from password file.\n", l);
} }
s += l; s += l;
} }

View File

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

27
net.c
View File

@ -17,6 +17,7 @@
#include "mtproto-client.h" #include "mtproto-client.h"
#include "mtproto-common.h" #include "mtproto-common.h"
#include "tree.h" #include "tree.h"
#include "interface.h"
DEFINE_TREE(int,int,int_cmp,0) 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 (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
if (errno != EINPROGRESS) { 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); close (fd);
free (c); free (c);
return 0; return 0;
@ -183,7 +184,7 @@ struct connection *create_connection (const char *host, int port, struct session
assert (!Connections[fd]); assert (!Connections[fd]);
Connections[fd] = c; Connections[fd] = c;
if (verbosity) { 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) { if (c->methods->ready) {
c->methods->ready (c); c->methods->ready (c);
@ -211,7 +212,7 @@ void fail_connection (struct connection *c) {
void try_write (struct connection *c) { void try_write (struct connection *c) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "try write: fd = %d\n", c->fd); logprintf ( "try write: fd = %d\n", c->fd);
} }
int x = 0; int x = 0;
while (c->out_head) { while (c->out_head) {
@ -238,12 +239,12 @@ void try_write (struct connection *c) {
} }
} }
if (verbosity) { 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; c->out_bytes -= x;
} }
void hexdump (struct connection_buffer *b) { void hexdump_buf (struct connection_buffer *b) {
int pos = 0; int pos = 0;
int rem = 8; int rem = 8;
while (b) { while (b) {
@ -270,7 +271,7 @@ void hexdump (struct connection_buffer *b) {
void try_rpc_read (struct connection *c) { void try_rpc_read (struct connection *c) {
assert (c->in_head); assert (c->in_head);
if (verbosity >= 4) { if (verbosity >= 4) {
hexdump (c->in_head); hexdump_buf (c->in_head);
} }
while (1) { while (1) {
@ -307,7 +308,7 @@ void try_rpc_read (struct connection *c) {
void try_read (struct connection *c) { void try_read (struct connection *c) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "try read: fd = %d\n", c->fd); logprintf ( "try read: fd = %d\n", c->fd);
} }
if (!c->in_tail) { if (!c->in_tail) {
c->in_head = c->in_tail = new_connection_buffer (1 << 20); c->in_head = c->in_tail = new_connection_buffer (1 << 20);
@ -334,7 +335,7 @@ void try_read (struct connection *c) {
} }
} }
if (verbosity) { 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; c->in_bytes += x;
if (x) { if (x) {
@ -356,15 +357,15 @@ int connections_make_poll_array (struct pollfd *fds, int max) {
fds ++; fds ++;
max --; max --;
} }
if (verbosity >= 3) { if (verbosity >= 10) {
fprintf (stderr, "%d connections in poll\n", _max - max); logprintf ( "%d connections in poll\n", _max - max);
} }
return _max - max; return _max - max;
} }
void connections_poll_result (struct pollfd *fds, int max) { void connections_poll_result (struct pollfd *fds, int max) {
if (verbosity >= 2) { if (verbosity >= 10) {
fprintf (stderr, "connections_poll_result: max = %d\n", max); logprintf ( "connections_poll_result: max = %d\n", max);
} }
int i; int i;
for (i = 0; i < max; 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 (fds[i].revents & (POLLHUP | POLLERR | POLLRDHUP)) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "fail connection\n"); logprintf ( "fail connection\n");
} }
fail_connection (c); fail_connection (c);
} else if (fds[i].revents & POLLOUT) { } 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); dc_create_session (DC);
} }
if (verbosity) { 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)); struct query *q = malloc (sizeof (*q));
q->data_len = ints; 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); memcpy (q->data, data, 4 * ints);
q->msg_id = encrypt_send_message (DC->sessions[0]->c, data, ints, 1); q->msg_id = encrypt_send_message (DC->sessions[0]->c, data, ints, 1);
if (verbosity) { if (verbosity) {
fprintf (stderr, "Msg_id is %lld\n", q->msg_id); logprintf ( "Msg_id is %lld\n", q->msg_id);
} }
q->methods = methods; q->methods = methods;
if (queries_tree) { 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 ()); queries_tree = tree_insert_query (queries_tree, q, lrand48 ());
@ -77,12 +77,12 @@ void query_error (long long id) {
int error_len = prefetch_strlen (); int error_len = prefetch_strlen ();
char *error = fetch_str (error_len); char *error = fetch_str (error_len);
if (verbosity) { 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); struct query *q = query_get (id);
if (!q) { if (!q) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "No such query\n"); logprintf ( "No such query\n");
} }
} else { } else {
remove_event_timer (&q->ev); remove_event_timer (&q->ev);
@ -100,10 +100,10 @@ static int packed_buffer[MAX_PACKED_SIZE / 4];
void query_result (long long id UU) { void query_result (long long id UU) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "result for query #%lld\n", id); logprintf ( "result for query #%lld\n", id);
} }
if (verbosity >= 4) { if (verbosity >= 4) {
fprintf (stderr, "result: "); logprintf ( "result: ");
hexdump_in (); hexdump_in ();
} }
int op = prefetch_int (); int op = prefetch_int ();
@ -124,8 +124,8 @@ void query_result (long long id UU) {
int err = inflate (&strm, Z_FINISH); int err = inflate (&strm, Z_FINISH);
if (verbosity) { if (verbosity) {
fprintf (stderr, "inflate error = %d\n", err); logprintf ( "inflate error = %d\n", err);
fprintf (stderr, "inflated %d bytes\n", (int)strm.total_out); logprintf ( "inflated %d bytes\n", (int)strm.total_out);
} }
end = in_ptr; end = in_ptr;
eend = in_end; eend = in_end;
@ -133,14 +133,14 @@ void query_result (long long id UU) {
in_ptr = packed_buffer; in_ptr = packed_buffer;
in_end = in_ptr + strm.total_out / 4; in_end = in_ptr + strm.total_out / 4;
if (verbosity >= 4) { if (verbosity >= 4) {
fprintf (stderr, "Unzipped data: "); logprintf ( "Unzipped data: ");
hexdump_in (); hexdump_in ();
} }
} }
struct query *q = query_get (id); struct query *q = query_get (id);
if (!q) { if (!q) {
if (verbosity) { if (verbosity) {
fprintf (stderr, "No such query\n"); logprintf ( "No such query\n");
} }
} else { } else {
remove_event_timer (&q->ev); remove_event_timer (&q->ev);
@ -162,16 +162,18 @@ DEFINE_TREE (timer, struct event_timer *, event_timer_cmp, 0)
struct tree_timer *timer_tree; struct tree_timer *timer_tree;
void insert_event_timer (struct event_timer *ev) { void insert_event_timer (struct event_timer *ev) {
return; if (verbosity > 2) {
fprintf (stderr, "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); logprintf ( "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
}
tree_check_timer (timer_tree); tree_check_timer (timer_tree);
timer_tree = tree_insert_timer (timer_tree, ev, lrand48 ()); timer_tree = tree_insert_timer (timer_tree, ev, lrand48 ());
tree_check_timer (timer_tree); tree_check_timer (timer_tree);
} }
void remove_event_timer (struct event_timer *ev) { void remove_event_timer (struct event_timer *ev) {
return; if (verbosity > 2) {
fprintf (stderr, "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm); logprintf ( "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
}
tree_check_timer (timer_tree); tree_check_timer (timer_tree);
timer_tree = tree_delete_timer (timer_tree, ev); timer_tree = tree_delete_timer (timer_tree, ev);
tree_check_timer (timer_tree); 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); assert (test_mode == CODE_bool_false);
int this_dc = fetch_int (); int this_dc = fetch_int ();
if (verbosity) { if (verbosity) {
fprintf (stderr, "this_dc = %d\n", this_dc); logprintf ( "this_dc = %d\n", this_dc);
} }
assert (fetch_int () == CODE_vector); assert (fetch_int () == CODE_vector);
int n = fetch_int (); int n = fetch_int ();
@ -222,7 +224,7 @@ int help_get_config_on_answer (struct query *q UU) {
char *ip = fetch_str (l2); char *ip = fetch_str (l2);
int port = fetch_int (); int port = fetch_int ();
if (verbosity) { 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]) { if (!DC_list[id]) {
alloc_dc (id, strndup (ip, l2), port); 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 (); max_chat_size = fetch_int ();
if (verbosity >= 2) { if (verbosity >= 2) {
fprintf (stderr, "chat_size = %d\n", max_chat_size); logprintf ( "chat_size = %d\n", max_chat_size);
} }
return 0; 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'; int i = error[s] - '0';
want_dc_num = i; want_dc_num = i;
} else { } 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); assert (0);
} }
return 0; return 0;
@ -343,13 +345,13 @@ int sign_in_on_answer (struct query *q UU) {
fetch_user (&User); fetch_user (&User);
sign_in_ok = 1; sign_in_ok = 1;
if (verbosity) { 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; return 0;
} }
int sign_in_on_error (struct query *q UU, int error_code, int l, char *error) { 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; sign_in_ok = -1;
return 0; return 0;
} }
@ -371,11 +373,13 @@ int do_send_code_result (const char *code) {
return sign_in_ok; return sign_in_ok;
} }
extern char *user_list[];
int get_contacts_on_answer (struct query *q UU) { int get_contacts_on_answer (struct query *q UU) {
int i;
assert (fetch_int () == (int)CODE_contacts_contacts); assert (fetch_int () == (int)CODE_contacts_contacts);
assert (fetch_int () == CODE_vector); assert (fetch_int () == CODE_vector);
int n = fetch_int (); int n = fetch_int ();
int i;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
assert (fetch_int () == (int)CODE_contact); assert (fetch_int () == (int)CODE_contact);
fetch_int (); // id fetch_int (); // id
@ -384,9 +388,8 @@ int get_contacts_on_answer (struct query *q UU) {
assert (fetch_int () == CODE_vector); assert (fetch_int () == CODE_vector);
n = fetch_int (); n = fetch_int ();
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
struct user User; struct user *U = fetch_alloc_user ();
fetch_user (&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);
rprintf ("User: id = %d, first_name = %s, last_name = %s\n", User.id, User.first_name, User.last_name);
} }
return 0; return 0;
} }

View File

@ -1,6 +1,8 @@
#include <assert.h> #include <assert.h>
#include "structures.h" #include "structures.h"
#include "mtproto-common.h" #include "mtproto-common.h"
#include "telegram.h"
#include "tree.h"
void fetch_file_location (struct file_location *loc) { void fetch_file_location (struct file_location *loc) {
int x = fetch_int (); int x = fetch_int ();
@ -48,6 +50,25 @@ void fetch_user (struct user *U) {
} }
U->first_name = fetch_str_dup (); U->first_name = fetch_str_dup ();
U->last_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) { if (x == CODE_user_deleted) {
U->flags = 2; U->flags = 2;
return; return;
@ -79,3 +100,46 @@ void fetch_user (struct user *U) {
U->flags |= 16; 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 *first_name;
char *last_name; char *last_name;
char *phone; char *phone;
char *print_name;
long long access_hash; long long access_hash;
struct file_location photo_big; struct file_location photo_big;
struct file_location photo_small; struct file_location photo_small;
@ -28,4 +29,9 @@ struct user {
void fetch_file_location (struct file_location *loc); void fetch_file_location (struct file_location *loc);
void fetch_user (struct user *U); 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 #endif

View File

@ -1 +1,2 @@
#define MAX_DC_NUM 9 #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 {\ } else {\
int c = X_CMP (x, T->x);\ int c = X_CMP (x, T->x);\
assert (c);\ 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;\ 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) { \ int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return 0; }\ if (!T) { return 0; }\
return 1 + tree_count_ ## X_NAME (T->left) + tree_count_ ## X_NAME (T->right); \ return 1 + tree_count_ ## X_NAME (T->left) + tree_count_ ## X_NAME (T->right); \