Commit bf291df3 authored by Vysheng's avatar Vysheng

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

parent 3243c29a
......@@ -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)
......
......@@ -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 = 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 saved_point = rl_point;
char *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);
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);
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);
}
}
#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
......@@ -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;
......
This diff is collapsed.
......@@ -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
......@@ -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) {
......
......@@ -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;
}
......
#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
#define MAX_DC_NUM 9
#define MAX_USER_NUM 1000
......@@ -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); \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment