Many fixes. Now (maybe) works authorization and get contact list query
This commit is contained in:
parent
3243c29a8c
commit
bf291df34a
1
Makefile
1
Makefile
@ -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)
|
||||
|
||||
|
114
interface.c
114
interface.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
10
interface.h
10
interface.h
@ -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
2
loop.c
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
27
net.c
@ -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) {
|
||||
|
53
queries.c
53
queries.c
@ -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;
|
||||
}
|
||||
|
64
structures.c
64
structures.c
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -1 +1,2 @@
|
||||
#define MAX_DC_NUM 9
|
||||
#define MAX_USER_NUM 1000
|
||||
|
14
tree.h
14
tree.h
@ -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); \
|
||||
|
Loading…
Reference in New Issue
Block a user