many updates

This commit is contained in:
Vysheng 2014-08-14 22:03:33 +04:00
parent fe08f0c5e7
commit b12ca53816
21 changed files with 1497 additions and 1700 deletions

View File

@ -18,7 +18,7 @@ DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${DEP}/auto ${OBJ}/auto
EXE_LIST=${EXE}/generate ${EXE}/tlc ${EXE}/telegram-cli
TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/net.o ${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/lua-tg.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o
TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/net.o ${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/lua-tg.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o ${OBJ}/updates.o
TLC_OBJECTS=${OBJ}/tlc.o ${OBJ}/tl-parser.o ${OBJ}/crc32.o
GENERATE_OBJECTS=${OBJ}/generate.o
COMMON_OBJECTS=${OBJ}/tools.o
@ -60,6 +60,7 @@ ${EXE}/generate: ${GENERATE_OBJECTS} ${COMMON_OBJECTS}
${CC} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${LINK_FLAGS} -o $@
${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tlc
${EXE}/tlc -e $@ ${AUTO}/scheme.tl
${AUTO}/scheme.tl: ${srcdir}/scheme.tl ${srcdir}/binlog.tl ${srcdir}/append.tl

View File

@ -44,6 +44,7 @@
#include "loop.h"
#include "tgl.h"
#include "auto.h"
#include <openssl/sha.h>
@ -80,7 +81,7 @@ static int fetch_comb_binlog_dc_option (void *extra) {
vlogprintf (E_NOTICE, "DC%d '%.*s' update: %.*s:%d\n", id, l1, name, l2, ip, port);
alloc_dc (id, tstrndup (ip, l2), port);
tglmp_alloc_dc (id, tstrndup (ip, l2), port);
return 0;
}

318
loop.c
View File

@ -44,20 +44,11 @@
#include <fcntl.h>
#include "interface.h"
#include "net.h"
#include "mtproto-client.h"
#include "mtproto-common.h"
#include "queries.h"
#include "telegram.h"
#include "loop.h"
#include "binlog.h"
#include "lua-tg.h"
#include "structures.h"
#include "tgl.h"
#include "auto.h"
extern char *default_username;
extern char *auth_token;
void set_default_username (const char *s);
@ -80,7 +71,7 @@ void net_loop (int flags, int (*is_end)(void)) {
cc ++;
}
write_state_file ();
//write_state_file ();
int x = connections_make_poll_array (fds + cc, 101 - cc) + cc;
double timer = next_timer_in ();
if (timer > 1000) { timer = 1000; }
@ -155,289 +146,6 @@ char *get_state_filename (void);
char *get_secret_chat_filename (void);
int zero[512];
/*
void write_dc (int auth_file_fd, struct dc *DC) {
assert (write (auth_file_fd, &DC->port, 4) == 4);
int l = strlen (DC->ip);
assert (write (auth_file_fd, &l, 4) == 4);
assert (write (auth_file_fd, DC->ip, l) == l);
if (DC->flags & 1) {
assert (write (auth_file_fd, &DC->auth_key_id, 8) == 8);
assert (write (auth_file_fd, DC->auth_key, 256) == 256);
} else {
assert (write (auth_file_fd, zero, 256 + 8) == 256 + 8);
}
assert (write (auth_file_fd, &DC->server_salt, 8) == 8);
assert (write (auth_file_fd, &DC->has_auth, 4) == 4);
}
void write_auth_file (void) {
if (binlog_enabled) { return; }
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
assert (auth_file_fd >= 0);
int x = DC_SERIALIZED_MAGIC_V2;
assert (write (auth_file_fd, &x, 4) == 4);
x = MAX_DC_ID;
assert (write (auth_file_fd, &x, 4) == 4);
assert (write (auth_file_fd, &dc_working_num, 4) == 4);
assert (write (auth_file_fd, &auth_state, 4) == 4);
int i;
for (i = 0; i <= MAX_DC_ID; i++) {
if (DC_list[i]) {
x = 1;
assert (write (auth_file_fd, &x, 4) == 4);
write_dc (auth_file_fd, DC_list[i]);
} else {
x = 0;
assert (write (auth_file_fd, &x, 4) == 4);
}
}
assert (write (auth_file_fd, &tgl_state.our_id, 4) == 4);
close (auth_file_fd);
}
void read_dc (int auth_file_fd, int id, unsigned ver) {
int port = 0;
assert (read (auth_file_fd, &port, 4) == 4);
int l = 0;
assert (read (auth_file_fd, &l, 4) == 4);
assert (l >= 0);
char *ip = talloc (l + 1);
assert (read (auth_file_fd, ip, l) == l);
ip[l] = 0;
struct dc *DC = alloc_dc (id, ip, port);
assert (read (auth_file_fd, &DC->auth_key_id, 8) == 8);
assert (read (auth_file_fd, &DC->auth_key, 256) == 256);
assert (read (auth_file_fd, &DC->server_salt, 8) == 8);
if (DC->auth_key_id) {
DC->flags |= 1;
}
if (ver != DC_SERIALIZED_MAGIC) {
assert (read (auth_file_fd, &DC->has_auth, 4) == 4);
} else {
DC->has_auth = 0;
}
}
void empty_auth_file (void) {
alloc_dc (1, tstrdup (tgl_state.test_mode ? TG_SERVER_TEST : TG_SERVER), 443);
dc_working_num = 1;
auth_state = 0;
write_auth_file ();
}
int need_dc_list_update;
void read_auth_file (void) {
if (binlog_enabled) { return; }
int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600);
if (auth_file_fd < 0) {
empty_auth_file ();
}
assert (auth_file_fd >= 0);
unsigned x;
unsigned m;
if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC && m != DC_SERIALIZED_MAGIC_V2)) {
close (auth_file_fd);
empty_auth_file ();
return;
}
assert (read (auth_file_fd, &x, 4) == 4);
assert (x <= MAX_DC_ID);
assert (read (auth_file_fd, &dc_working_num, 4) == 4);
assert (read (auth_file_fd, &auth_state, 4) == 4);
if (m == DC_SERIALIZED_MAGIC) {
auth_state = 700;
}
int i;
for (i = 0; i <= (int)x; i++) {
int y;
assert (read (auth_file_fd, &y, 4) == 4);
if (y) {
read_dc (auth_file_fd, i, m);
}
}
int l = read (auth_file_fd, &tgl_state.our_id, 4);
if (l < 4) {
assert (!l);
}
close (auth_file_fd);
DC_working = DC_list[dc_working_num];
if (m == DC_SERIALIZED_MAGIC) {
DC_working->has_auth = 1;
}
}
int pts, qts, seq, last_date;
void read_state_file (void) {
if (binlog_enabled) { return; }
int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600);
if (state_file_fd < 0) {
return;
}
int version, magic;
if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return; }
if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return; }
if (read (state_file_fd, &version, 4) < 4) { close (state_file_fd); return; }
assert (version >= 0);
int x[4];
if (read (state_file_fd, x, 16) < 16) {
close (state_file_fd);
return;
}
pts = x[0];
qts = x[1];
seq = x[2];
last_date = x[3];
close (state_file_fd);
}
void write_state_file (void) {
if (binlog_enabled) { return; }
static int wseq;
static int wpts;
static int wqts;
static int wdate;
if (wseq >= seq && wpts >= pts && wqts >= qts && wdate >= last_date) { return; }
int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600);
if (state_file_fd < 0) {
return;
}
int x[6];
x[0] = STATE_FILE_MAGIC;
x[1] = 0;
x[2] = pts;
x[3] = qts;
x[4] = seq;
x[5] = last_date;
assert (write (state_file_fd, x, 24) == 24);
close (state_file_fd);
wseq = seq; wpts = pts; wqts = qts; wdate = last_date;
}
extern tgl_peer_t *Peers[];
extern int peer_num;
extern int encr_root;
extern unsigned char *encr_prime;
extern int encr_param_version;
extern int dialog_list_got;
void read_secret_chat_file (void) {
if (binlog_enabled) { return; }
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
if (fd < 0) {
return;
}
int x[2];
if (read (fd, x, 8) < 8) {
close (fd); return;
}
if (x[0] != (int)SECRET_CHAT_FILE_MAGIC) { close (fd); return; }
int version = x[1];
assert (version >= 0);
int cc;
assert (read (fd, &cc, 4) == 4);
int i;
for (i = 0; i < cc; i++) {
tgl_peer_t *P = talloc0 (sizeof (*P));
struct tgl_secret_chat *E = &P->encr_chat;
int t;
assert (read (fd, &t, 4) == 4);
P->id = TGL_MK_ENCR_CHAT (t);
assert (read (fd, &P->flags, 4) == 4);
assert (read (fd, &t, 4) == 4);
assert (t > 0);
P->print_name = talloc (t + 1);
assert (read (fd, P->print_name, t) == t);
P->print_name[t] = 0;
tglp_peer_insert_name (P);
assert (read (fd, &E->state, 4) == 4);
assert (read (fd, &E->user_id, 4) == 4);
assert (read (fd, &E->admin_id, 4) == 4);
assert (read (fd, &E->ttl, 4) == 4);
assert (read (fd, &E->access_hash, 8) == 8);
if (E->state != sc_waiting) {
E->g_key = talloc (256);
assert (read (fd, E->g_key, 256) == 256);
E->nonce = talloc (256);
assert (read (fd, E->nonce, 256) == 256);
}
assert (read (fd, E->key, 256) == 256);
assert (read (fd, &E->key_fingerprint, 8) == 8);
tglp_insert_encrypted_chat (P);
}
if (version >= 1) {
assert (read (fd, &encr_root, 4) == 4);
if (encr_root) {
assert (read (fd, &encr_param_version, 4) == 4);
encr_prime = talloc (256);
assert (read (fd, encr_prime, 256) == 256);
}
}
close (fd);
}
void count_encr_peer (tgl_peer_t *P, void *cc) {
if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && P->encr_chat.state != sc_none && P->encr_chat.state != sc_deleted) {
(*(int *)cc) ++;
}
}
void write_encr_peer (tgl_peer_t *P, void *pfd) {
int fd = *(int *)pfd;
if (tgl_get_peer_type (P->id) == TGL_PEER_ENCR_CHAT && P->encr_chat.state != sc_none && P->encr_chat.state != sc_deleted) {
int t = tgl_get_peer_id (P->id);
assert (write (fd, &t, 4) == 4);
t = P->flags;
assert (write (fd, &t, 4) == 4);
t = strlen (P->print_name);
assert (write (fd, &t, 4) == 4);
assert (write (fd, P->print_name, t) == t);
assert (write (fd, &P->encr_chat.state, 4) == 4);
assert (write (fd, &P->encr_chat.user_id, 4) == 4);
assert (write (fd, &P->encr_chat.admin_id, 4) == 4);
assert (write (fd, &P->encr_chat.ttl, 4) == 4);
assert (write (fd, &P->encr_chat.access_hash, 8) == 8);
if (P->encr_chat.state != sc_waiting) {
assert (write (fd, P->encr_chat.g_key, 256) == 256);
}
if (P->encr_chat.state != sc_waiting) {
assert (write (fd, P->encr_chat.nonce, 256) == 256);
}
assert (write (fd, P->encr_chat.key, 256) == 256);
assert (write (fd, &P->encr_chat.key_fingerprint, 8) == 8);
}
}
void write_secret_chat_file (void) {
if (binlog_enabled) { return; }
int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600);
if (fd < 0) {
return;
}
int x[2];
x[0] = SECRET_CHAT_FILE_MAGIC;
x[1] = 1;
assert (write (fd, x, 8) == 8);
int cc = 0;
tgl_peer_iterator_ex (count_encr_peer, &cc);
tgl_peer_iterator_ex (write_encr_peer, &fd);
assert (write (fd, &encr_root, 4) == 4);
if (encr_root) {
assert (write (fd, &encr_param_version, 4) == 4);
assert (write (fd, encr_prime, 256) == 256);
}
close (fd);
}*/
extern int max_chat_size;
int mcs (void) {
return max_chat_size;
@ -456,19 +164,17 @@ int new_dc_num;
int wait_dialog_list;
int loop (void) {
on_start ();
if (binlog_enabled) {
double t = get_double_time ();
logprintf ("replay log start\n");
tgl_replay_log ();
logprintf ("replay log end in %lf seconds\n", get_double_time () - t);
tgl_reopen_binlog_for_writing ();
#ifdef USE_LUA
lua_binlog_end ();
#endif
} else {
read_auth_file ();
}
//on_start ();
tgl_init ();
double t = get_double_time ();
logprintf ("replay log start\n");
tgl_replay_log ();
logprintf ("replay log end in %lf seconds\n", get_double_time () - t);
tgl_reopen_binlog_for_writing ();
#ifdef USE_LUA
lua_binlog_end ();
#endif
update_prompt ();
assert (DC_list[dc_working_num]);

7
main.c
View File

@ -386,8 +386,8 @@ void usage (void) {
exit (1);
}
extern char *rsa_public_key_name;
extern int default_dc_num;
//extern char *rsa_public_key_name;
//extern int default_dc_num;
char *log_net_file;
FILE *log_net_f;
@ -406,7 +406,8 @@ void args_parse (int argc, char **argv) {
set_default_username (optarg);
break;
case 'k':
rsa_public_key_name = tstrdup (optarg);
//rsa_public_key_name = tstrdup (optarg);
tgl_set_rsa_key (optarg);
break;
case 'v':
tgl_incr_verbosity ();

File diff suppressed because it is too large Load Diff

View File

@ -19,15 +19,76 @@
*/
#ifndef __MTPROTO_CLIENT_H__
#define __MTPROTO_CLIENT_H__
#include "net.h"
//#include "net.h"
#include <openssl/bn.h>
void on_start (void);
long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful);
void dc_authorize (struct dc *DC);
void work_update (struct connection *c, long long msg_id);
void work_update_binlog (void);
int check_g (unsigned char p[256], BIGNUM *g);
int check_g_bn (BIGNUM *p, BIGNUM *g);
int check_DH_params (BIGNUM *p, int g);
void secure_random (void *s, int l);
//void on_start (void);
//..long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful);
//void dc_authorize (struct dc *DC);
//void work_update (struct connection *c, long long msg_id);
//void work_update_binlog (void);
//int check_g (unsigned char p[256], BIGNUM *g);
//int check_g_bn (BIGNUM *p, BIGNUM *g);
//int check_DH_params (BIGNUM *p, int g);
//void secure_random (void *s, int l);
struct connection;
struct dc;
//#include "queries.h"
#define TG_SERVER "173.240.5.1"
#define TG_SERVER_TEST "173.240.5.253"
#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74"
#define TG_APP_ID 2899
#define ACK_TIMEOUT 1
#define MAX_DC_ID 10
struct connection;
enum dc_state {
st_init,
st_reqpq_sent,
st_reqdh_sent,
st_client_dh_sent,
st_authorized,
st_error
};
#define MAX_DC_SESSIONS 3
struct session {
struct dc *dc;
long long session_id;
int seq_no;
struct connection *c;
struct tree_long *ack_tree;
struct event *ev;
//struct event_timer ev;
};
struct dc {
int id;
int port;
int flags;
enum dc_state state;
char *ip;
char *user;
struct session *sessions[MAX_DC_SESSIONS];
char auth_key[256];
long long auth_key_id;
long long server_salt;
int server_time_delta;
double server_time_udelta;
int has_auth;
};
long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful);
void tglmp_dc_create_session (struct dc *DC);
int tglmp_check_g (unsigned char p[256], BIGNUM *g);
int tglmp_check_DH_params (BIGNUM *p, int g);
struct dc *tglmp_alloc_dc (int id, char *ip, int port);
void tgln_insert_msg_id (struct session *S, long long id);
void tglmp_on_start (const char *key);
void tgl_dc_authorize (struct dc *DC);
#endif

View File

@ -53,9 +53,9 @@ int *packet_buffer = __packet_buffer + 16;
long long rsa_encrypted_chunks, rsa_decrypted_chunks;
BN_CTX *BN_ctx;
int verbosity;
//int verbosity;
int get_random_bytes (unsigned char *buf, int n) {
static int get_random_bytes (unsigned char *buf, int n) {
int r = 0, h = open ("/dev/random", O_RDONLY | O_NONBLOCK);
if (h >= 0) {
r = read (h, buf, n);
@ -87,20 +87,6 @@ int get_random_bytes (unsigned char *buf, int n) {
return r;
}
void my_clock_gettime (int clock_id UU, struct timespec *T) {
#ifdef __MACH__
// We are ignoring MONOTONIC and hope time doesn't go back too often
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
T->tv_sec = mts.tv_sec;
T->tv_nsec = mts.tv_nsec;
#else
assert (clock_gettime(clock_id, T) >= 0);
#endif
}
/* RDTSC */
#if defined(__i386__)

View File

@ -25,12 +25,14 @@
#include <openssl/bn.h>
#include <openssl/aes.h>
#include <stdio.h>
#include <assert.h>
//#include "interface.h"
#include "tools.h"
#include "auto/constants.h"
#include "tgl.h"
#include "tgl-inner.h"
/* DH key exchange protocol data structures */
#define CODE_req_pq 0x60469778
#define CODE_resPQ 0x05162463
@ -157,10 +159,10 @@ static inline void out_bignum (BIGNUM *n) {
extern int *in_ptr, *in_end;
void fetch_pts (void);
void fetch_qts (void);
void fetch_date (void);
void fetch_seq (void);
//void fetch_pts (void);
//void fetch_qts (void);
//void fetch_date (void);
//void fetch_seq (void);
static inline int prefetch_strlen (void) {
if (in_ptr >= in_end) {
return -1;
@ -331,7 +333,7 @@ static inline void fetch256 (void *buf) {
}
}
int get_random_bytes (unsigned char *buf, int n);
//int get_random_bytes (unsigned char *buf, int n);
int pad_rsa_encrypt (char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E);
int pad_rsa_decrypt (char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *D);

294
net.c
View File

@ -37,81 +37,73 @@
#include <poll.h>
#include <openssl/rand.h>
#include <arpa/inet.h>
#include <event2/event.h>
#include <sys/time.h>
#include <time.h>
#include "net.h"
#include "include.h"
#include "mtproto-client.h"
#include "mtproto-common.h"
#include "tgl.h"
#include "tgl-inner.h"
//#include "mtproto-client.h"
//#include "mtproto-common.h"
#include "tree.h"
#include "interface.h"
#ifndef POLLRDHUP
#define POLLRDHUP 0
#endif
#define long_cmp(a,b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1)
DEFINE_TREE(long,long long,long_cmp,0)
double get_utime (int clock_id);
//double get_utime (int clock_id);
int verbosity;
extern struct connection_methods auth_methods;
extern FILE *log_net_f;
//extern struct mtproto_methods auth_methods;
void fail_connection (struct connection *c);
static void fail_connection (struct connection *c);
#define PING_TIMEOUT 10
void start_ping_timer (struct connection *c);
int ping_alarm (struct connection *c) {
if (verbosity > 2) {
logprintf ("ping alarm\n");
}
static void start_ping_timer (struct connection *c);
static void ping_alarm (evutil_socket_t fd, short what, void *arg) {
struct connection *c = arg;
vlogprintf (E_DEBUG + 2,"ping alarm\n");
assert (c->state == conn_ready || c->state == conn_connecting);
if (get_double_time () - c->last_receive_time > 20 * PING_TIMEOUT) {
if (verbosity) {
logprintf ( "fail connection: reason: ping timeout\n");
}
vlogprintf (E_WARNING, "fail connection: reason: ping timeout\n");
c->state = conn_failed;
fail_connection (c);
} else if (get_double_time () - c->last_receive_time > 5 * PING_TIMEOUT && c->state == conn_ready) {
int x[3];
x[0] = CODE_ping;
*(long long *)(x + 1) = lrand48 () * (1ll << 32) + lrand48 ();
encrypt_send_message (c, x, 3, 0);
tgl_do_send_ping (c);
start_ping_timer (c);
} else {
start_ping_timer (c);
}
return 0;
}
void stop_ping_timer (struct connection *c) {
remove_event_timer (&c->ev);
static void stop_ping_timer (struct connection *c) {
event_del (c->ping_ev);
}
void start_ping_timer (struct connection *c) {
c->ev.timeout = get_double_time () + PING_TIMEOUT;
c->ev.alarm = (void *)ping_alarm;
c->ev.self = c;
insert_event_timer (&c->ev);
static void start_ping_timer (struct connection *c) {
static struct timeval ptimeout = { PING_TIMEOUT, 0};
event_add (c->ping_ev, &ptimeout);
}
void restart_connection (struct connection *c);
int fail_alarm (void *ev) {
((struct connection *)ev)->in_fail_timer = 0;
restart_connection (ev);
return 0;
static void restart_connection (struct connection *c);
static void fail_alarm (evutil_socket_t fd, short what, void *arg) {
struct connection *c = arg;
c->in_fail_timer = 0;
restart_connection (c);
}
void start_fail_timer (struct connection *c) {
static void start_fail_timer (struct connection *c) {
if (c->in_fail_timer) { return; }
c->in_fail_timer = 1;
c->ev.timeout = get_double_time () + 10;
c->ev.alarm = (void *)fail_alarm;
c->ev.self = c;
insert_event_timer (&c->ev);
static struct timeval ptimeout = { 10, 0};
event_add (c->fail_ev, &ptimeout);
}
struct connection_buffer *new_connection_buffer (int size) {
static struct connection_buffer *new_connection_buffer (int size) {
struct connection_buffer *b = talloc0 (sizeof (*b));
b->start = talloc (size);
b->end = b->start + size;
@ -119,16 +111,19 @@ struct connection_buffer *new_connection_buffer (int size) {
return b;
}
void delete_connection_buffer (struct connection_buffer *b) {
static void delete_connection_buffer (struct connection_buffer *b) {
tfree (b->start, b->end - b->start);
tfree (b, sizeof (*b));
}
int write_out (struct connection *c, const void *_data, int len) {
int tgln_write_out (struct connection *c, const void *_data, int len) {
const unsigned char *data = _data;
if (!len) { return 0; }
assert (len > 0);
int x = 0;
if (!c->out_bytes) {
event_add (c->write_ev, 0);
}
if (!c->out_head) {
struct connection_buffer *b = new_connection_buffer (1 << 20);
c->out_head = c->out_tail = b;
@ -156,7 +151,7 @@ int write_out (struct connection *c, const void *_data, int len) {
return x;
}
int read_in (struct connection *c, void *_data, int len) {
int tgln_read_in (struct connection *c, void *_data, int len) {
unsigned char *data = _data;
if (!len) { return 0; }
assert (len > 0);
@ -188,7 +183,7 @@ int read_in (struct connection *c, void *_data, int len) {
return x;
}
int read_in_lookup (struct connection *c, void *_data, int len) {
int tgln_read_in_lookup (struct connection *c, void *_data, int len) {
unsigned char *data = _data;
if (!len || !c->in_bytes) { return 0; }
assert (len > 0);
@ -213,14 +208,14 @@ int read_in_lookup (struct connection *c, void *_data, int len) {
return x;
}
void flush_out (struct connection *c UU) {
void tgln_flush_out (struct connection *c UU) {
}
#define MAX_CONNECTIONS 100
struct connection *Connections[MAX_CONNECTIONS];
int max_connection_fd;
static struct connection *Connections[MAX_CONNECTIONS];
static int max_connection_fd;
void rotate_port (struct connection *c) {
static void rotate_port (struct connection *c) {
switch (c->port) {
case 443:
c->port = 80;
@ -234,11 +229,26 @@ void rotate_port (struct connection *c) {
}
}
struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods) {
static void try_read (struct connection *c);
static void try_write (struct connection *c);
static void conn_try_read (evutil_socket_t fd, short what, void *arg) {
struct connection *c = arg;
try_read (c);
}
static void conn_try_write (evutil_socket_t fd, short what, void *arg) {
struct connection *c = arg;
try_write (c);
if (c->out_bytes) {
event_add (c->write_ev, 0);
}
}
struct connection *tgln_create_connection (const char *host, int port, struct session *session, struct mtproto_methods *methods) {
struct connection *c = talloc0 (sizeof (*c));
int fd = socket (AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
logprintf ("Can not create socket: %m\n");
vlogprintf (E_ERROR, "Can not create socket: %m\n");
exit (1);
}
assert (fd >= 0 && fd < MAX_CONNECTIONS);
@ -260,51 +270,38 @@ struct connection *create_connection (const char *host, int port, struct session
if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
if (errno != EINPROGRESS) {
logprintf ( "Can not connect to %s:%d %m\n", host, port);
vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port);
close (fd);
tfree (c, sizeof (*c));
return 0;
}
}
struct pollfd s;
s.fd = fd;
s.events = POLLOUT | POLLERR | POLLRDHUP | POLLHUP;
errno = 0;
while (poll (&s, 1, 10000) <= 0 || !(s.revents & POLLOUT)) {
if (errno == EINTR) { continue; }
if (errno) {
logprintf ("Problems in poll: %m\n");
exit (1);
}
logprintf ("Connect with %s:%d timeout\n", host, port);
close (fd);
tfree (c, sizeof (*c));
return 0;
}
c->session = session;
c->fd = fd;
c->state = conn_connecting;
c->last_receive_time = get_double_time ();
c->ip = tstrdup (host);
c->flags = 0;
c->state = conn_ready;
c->methods = methods;
c->port = port;
assert (!Connections[fd]);
Connections[fd] = c;
if (verbosity) {
logprintf ( "connect to %s:%d successful\n", host, port);
}
if (c->methods->ready) {
c->methods->ready (c);
}
c->last_receive_time = get_double_time ();
c->ping_ev = evtimer_new (tgl_state.ev_base, ping_alarm, c);
c->fail_ev = evtimer_new (tgl_state.ev_base, fail_alarm, c);
c->read_ev = event_new (tgl_state.ev_base, c->fd, EV_READ | EV_PERSIST, conn_try_read, c);
c->write_ev = event_new (tgl_state.ev_base, c->fd, EV_WRITE, conn_try_write, c);
event_add (c->read_ev, 0);
start_ping_timer (c);
char byte = 0xef;
assert (tgln_write_out (c, &byte, 1) == 1);
tgln_flush_out (c);
return c;
}
void restart_connection (struct connection *c) {
static void restart_connection (struct connection *c) {
if (c->last_connect_time == time (0)) {
start_fail_timer (c);
return;
@ -313,7 +310,7 @@ void restart_connection (struct connection *c) {
c->last_connect_time = time (0);
int fd = socket (AF_INET, SOCK_STREAM, 0);
if (fd == -1) {
logprintf ("Can not create socket: %m\n");
vlogprintf (E_ERROR, "Can not create socket: %m\n");
exit (1);
}
assert (fd >= 0 && fd < MAX_CONNECTIONS);
@ -335,7 +332,7 @@ void restart_connection (struct connection *c) {
if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
if (errno != EINPROGRESS) {
logprintf ( "Can not connect to %s:%d %m\n", c->ip, c->port);
vlogprintf (E_WARNING, "Can not connect to %s:%d %m\n", c->ip, c->port);
start_fail_timer (c);
close (fd);
return;
@ -349,14 +346,15 @@ void restart_connection (struct connection *c) {
Connections[fd] = c;
char byte = 0xef;
assert (write_out (c, &byte, 1) == 1);
flush_out (c);
assert (tgln_write_out (c, &byte, 1) == 1);
tgln_flush_out (c);
}
void fail_connection (struct connection *c) {
static void fail_connection (struct connection *c) {
if (c->state == conn_ready || c->state == conn_connecting) {
stop_ping_timer (c);
}
event_del (c->write_ev);
rotate_port (c);
struct connection_buffer *b = c->out_head;
while (b) {
@ -375,19 +373,17 @@ void fail_connection (struct connection *c) {
c->out_bytes = c->in_bytes = 0;
close (c->fd);
Connections[c->fd] = 0;
logprintf ("Lost connection to server... %s:%d\n", c->ip, c->port);
vlogprintf (E_NOTICE, "Lost connection to server... %s:%d\n", c->ip, c->port);
restart_connection (c);
}
extern FILE *log_net_f;
void try_write (struct connection *c) {
if (verbosity) {
logprintf ( "try write: fd = %d\n", c->fd);
}
//extern FILE *log_net_f;
static void try_write (struct connection *c) {
vlogprintf (E_DEBUG, "try write: fd = %d\n", c->fd);
int x = 0;
while (c->out_head) {
int r = write (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
if (r > 0 && log_net_f) {
/*if (r > 0 && log_net_f) {
fprintf (log_net_f, "%.02lf %d OUT %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
int i;
for (i = 0; i < r; i++) {
@ -395,7 +391,7 @@ void try_write (struct connection *c) {
}
fprintf (log_net_f, "\n");
fflush (log_net_f);
}
}*/
if (r >= 0) {
x += r;
c->out_head->rptr += r;
@ -410,9 +406,7 @@ void try_write (struct connection *c) {
delete_connection_buffer (b);
} else {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
if (verbosity) {
logprintf ("fail_connection: write_error %m\n");
}
vlogprintf (E_NOTICE, "fail_connection: write_error %m\n");
fail_connection (c);
return;
} else {
@ -420,13 +414,11 @@ void try_write (struct connection *c) {
}
}
}
if (verbosity) {
logprintf ( "Sent %d bytes to %d\n", x, c->fd);
}
vlogprintf (E_DEBUG, "Sent %d bytes to %d\n", x, c->fd);
c->out_bytes -= x;
}
void hexdump_buf (struct connection_buffer *b) {
/*static void hexdump_buf (struct connection_buffer *b) {
int pos = 0;
int rem = 8;
while (b) {
@ -448,57 +440,52 @@ void hexdump_buf (struct connection_buffer *b) {
}
printf ("\n");
}
}*/
void try_rpc_read (struct connection *c) {
static void try_rpc_read (struct connection *c) {
assert (c->in_head);
if (verbosity >= 3) {
hexdump_buf (c->in_head);
}
while (1) {
if (c->in_bytes < 1) { return; }
unsigned len = 0;
unsigned t = 0;
assert (read_in_lookup (c, &len, 1) == 1);
assert (tgln_read_in_lookup (c, &len, 1) == 1);
if (len >= 1 && len <= 0x7e) {
if (c->in_bytes < (int)(1 + 4 * len)) { return; }
} else {
if (c->in_bytes < 4) { return; }
assert (read_in_lookup (c, &len, 4) == 4);
assert (tgln_read_in_lookup (c, &len, 4) == 4);
len = (len >> 8);
if (c->in_bytes < (int)(4 + 4 * len)) { return; }
len = 0x7f;
}
if (len >= 1 && len <= 0x7e) {
assert (read_in (c, &t, 1) == 1);
assert (tgln_read_in (c, &t, 1) == 1);
assert (t == len);
assert (len >= 1);
} else {
assert (len == 0x7f);
assert (read_in (c, &len, 4) == 4);
assert (tgln_read_in (c, &len, 4) == 4);
len = (len >> 8);
assert (len >= 1);
}
len *= 4;
int op;
assert (read_in_lookup (c, &op, 4) == 4);
assert (tgln_read_in_lookup (c, &op, 4) == 4);
c->methods->execute (c, op, len);
}
}
void try_read (struct connection *c) {
if (verbosity) {
logprintf ( "try read: fd = %d\n", c->fd);
}
static void try_read (struct connection *c) {
vlogprintf (E_DEBUG, "try read: fd = %d\n", c->fd);
if (!c->in_tail) {
c->in_head = c->in_tail = new_connection_buffer (1 << 20);
}
int x = 0;
while (1) {
int r = read (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr);
if (r > 0 && log_net_f) {
/*if (r > 0 && log_net_f) {
fprintf (log_net_f, "%.02lf %d IN %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
int i;
for (i = 0; i < r; i++) {
@ -506,7 +493,7 @@ void try_read (struct connection *c) {
}
fprintf (log_net_f, "\n");
fflush (log_net_f);
}
}*/
if (r > 0) {
c->last_receive_time = get_double_time ();
stop_ping_timer (c);
@ -523,9 +510,7 @@ void try_read (struct connection *c) {
c->in_tail = b;
} else {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
if (verbosity) {
logprintf ("fail_connection: read_error %m\n");
}
vlogprintf (E_NOTICE, "fail_connection: read_error %m\n");
fail_connection (c);
return;
} else {
@ -533,16 +518,14 @@ void try_read (struct connection *c) {
}
}
}
if (verbosity) {
logprintf ( "Received %d bytes from %d\n", x, c->fd);
}
vlogprintf (E_DEBUG, "Received %d bytes from %d\n", x, c->fd);
c->in_bytes += x;
if (x) {
try_rpc_read (c);
}
}
int connections_make_poll_array (struct pollfd *fds, int max) {
int tgl_connections_make_poll_array (struct pollfd *fds, int max) {
int _max = max;
int i;
for (i = 0; i <= max_connection_fd; i++) {
@ -561,16 +544,10 @@ int connections_make_poll_array (struct pollfd *fds, int 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 >= 10) {
logprintf ( "connections_poll_result: max = %d\n", max);
}
void tgl_connections_poll_result (struct pollfd *fds, int max) {
int i;
for (i = 0; i < max; i++) {
struct connection *c = Connections[fds[i].fd];
@ -578,13 +555,11 @@ void connections_poll_result (struct pollfd *fds, int max) {
try_read (c);
}
if (fds[i].revents & (POLLHUP | POLLERR | POLLRDHUP)) {
if (verbosity) {
logprintf ("fail_connection: events_mask=0x%08x\n", fds[i].revents);
}
vlogprintf (E_NOTICE, "fail_connection: events_mask=0x%08x\n", fds[i].revents);
fail_connection (c);
} else if (fds[i].revents & POLLOUT) {
if (c->state == conn_connecting) {
logprintf ("connection ready\n");
vlogprintf (E_DEBUG, "connection ready\n");
c->state = conn_ready;
c->last_receive_time = get_double_time ();
}
@ -594,54 +569,3 @@ void connections_poll_result (struct pollfd *fds, int max) {
}
}
}
int send_all_acks (struct session *S) {
clear_packet ();
out_int (CODE_msgs_ack);
out_int (CODE_vector);
out_int (tree_count_long (S->ack_tree));
while (S->ack_tree) {
long long x = tree_get_min_long (S->ack_tree);
out_long (x);
S->ack_tree = tree_delete_long (S->ack_tree, x);
}
encrypt_send_message (S->c, packet_buffer, packet_ptr - packet_buffer, 0);
return 0;
}
void insert_msg_id (struct session *S, long long id) {
if (!S->ack_tree) {
S->ev.alarm = (void *)send_all_acks;
S->ev.self = (void *)S;
S->ev.timeout = get_double_time () + ACK_TIMEOUT;
insert_event_timer (&S->ev);
}
if (!tree_lookup_long (S->ack_tree, id)) {
S->ack_tree = tree_insert_long (S->ack_tree, id, lrand48 ());
}
}
extern struct dc *DC_list[];
struct dc *alloc_dc (int id, char *ip, int port UU) {
assert (!DC_list[id]);
struct dc *DC = talloc0 (sizeof (*DC));
DC->id = id;
DC->ip = ip;
DC->port = port;
DC_list[id] = DC;
return DC;
}
void dc_create_session (struct dc *DC) {
struct session *S = talloc0 (sizeof (*S));
assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0);
S->dc = DC;
S->c = create_connection (DC->ip, DC->port, S, &auth_methods);
if (!S->c) {
logprintf ("Can not create connection to DC. Is network down?\n");
exit (1);
}
assert (!DC->sessions[0]);
DC->sessions[0] = S;
}

84
net.h
View File

@ -20,59 +20,6 @@
#define __NET_H__
#include <poll.h>
struct dc;
#include "queries.h"
#define TG_SERVER "173.240.5.1"
#define TG_SERVER_TEST "173.240.5.253"
#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74"
#define TG_APP_ID 2899
#define ACK_TIMEOUT 1
#define MAX_DC_ID 10
enum dc_state {
st_init,
st_reqpq_sent,
st_reqdh_sent,
st_client_dh_sent,
st_authorized,
st_error
} ;
struct connection;
struct connection_methods {
int (*ready) (struct connection *c);
int (*close) (struct connection *c);
int (*execute) (struct connection *c, int op, int len);
};
#define MAX_DC_SESSIONS 3
struct session {
struct dc *dc;
long long session_id;
int seq_no;
struct connection *c;
struct tree_long *ack_tree;
struct event_timer ev;
};
struct dc {
int id;
int port;
int flags;
char *ip;
char *user;
struct session *sessions[MAX_DC_SESSIONS];
char auth_key[256];
long long auth_key_id;
long long server_salt;
int server_time_delta;
double server_time_udelta;
int has_auth;
};
#define DC_SERIALIZED_MAGIC 0x64582faa
#define DC_SERIALIZED_MAGIC_V2 0x94032abb
@ -122,27 +69,32 @@ struct connection {
int out_packet_num;
int last_connect_time;
int in_fail_timer;
struct connection_methods *methods;
struct mtproto_methods *methods;
struct session *session;
void *extra;
struct event_timer ev;
struct event *ping_ev;
struct event *fail_ev;
struct event *read_ev;
struct event *write_ev;
double last_receive_time;
};
extern struct connection *Connections[];
//extern struct connection *Connections[];
int write_out (struct connection *c, const void *data, int len);
void flush_out (struct connection *c);
int read_in (struct connection *c, void *data, int len);
int tgln_write_out (struct connection *c, const void *data, int len);
void tgln_flush_out (struct connection *c);
int tgln_read_in (struct connection *c, void *data, int len);
int tgln_read_in_lookup (struct connection *c, void *data, int len);
void create_all_outbound_connections (void);
void tgln_insert_msg_id (struct session *S, long long id);
struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods);
int connections_make_poll_array (struct pollfd *fds, int max);
void connections_poll_result (struct pollfd *fds, int max);
void dc_create_session (struct dc *DC);
void insert_msg_id (struct session *S, long long id);
struct dc *alloc_dc (int id, char *ip, int port);
//void create_all_outbound_connections (void);
//struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods);
struct dc *tgln_alloc_dc (int id, char *ip, int port);
void tgln_dc_create_session (struct dc *DC, struct mtproto_methods *methods);
struct connection *tgln_create_connection (const char *host, int port, struct session *session, struct mtproto_methods *methods);
#define GET_DC(c) (c->session->dc)
#endif

256
queries.c
View File

@ -44,7 +44,7 @@
#include "loop.h"
#include "structures.h"
//#include "interface.h"
#include "net.h"
//#include "net.h"
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/aes.h>
@ -53,8 +53,10 @@
#include "no-preview.h"
#include "binlog.h"
#include "updates.h"
#include "auto.h"
#include "tgl.h"
#include <event2/event.h>
#define sha1 SHA1
@ -85,25 +87,23 @@ static void out_peer_id (tgl_peer_id_t id);
DEFINE_TREE (query, struct query *, memcmp8, 0) ;
struct tree_query *queries_tree;
double get_double_time (void) {
struct timespec tv;
my_clock_gettime (CLOCK_REALTIME, &tv);
return tv.tv_sec + 1e-9 * tv.tv_nsec;
}
struct query *query_get (long long id) {
struct query *tglq_query_get (long long id) {
return tree_lookup_query (queries_tree, (void *)&id);
}
int alarm_query (struct query *q) {
static int alarm_query (struct query *q) {
assert (q);
vlogprintf (E_DEBUG, "Alarm query %lld\n", q->msg_id);
q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
insert_event_timer (&q->ev);
//q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
//insert_event_timer (&q->ev);
if (q->session->c->out_bytes >= 100000) {
static struct timeval ptimeout = { QUERY_TIMEOUT, 0};
event_add (q->ev, &ptimeout);
/*if (q->session->c->out_bytes >= 100000) {
return 0;
}
}*/
clear_packet ();
out_int (CODE_msg_container);
@ -113,30 +113,35 @@ int alarm_query (struct query *q) {
out_int (4 * q->data_len);
out_ints (q->data, q->data_len);
encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, 0);
tglmp_encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, 0);
return 0;
}
void query_restart (long long id) {
struct query *q = query_get (id);
void tglq_query_restart (long long id) {
struct query *q = tglq_query_get (id);
if (q) {
remove_event_timer (&q->ev);
event_del (q->ev);
alarm_query (q);
}
}
struct query *send_query (struct dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) {
static void alarm_query_gateway (evutil_socket_t fd, short what, void *arg) {
alarm_query (arg);
}
struct query *tglq_send_query (struct dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) {
assert (DC);
assert (DC->auth_key_id);
if (!DC->sessions[0]) {
dc_create_session (DC);
tglmp_dc_create_session (DC);
}
vlogprintf (E_DEBUG, "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
struct query *q = talloc0 (sizeof (*q));
q->data_len = ints;
q->data = talloc (4 * ints);
memcpy (q->data, data, 4 * ints);
q->msg_id = encrypt_send_message (DC->sessions[0]->c, data, ints, 1);
q->msg_id = tglmp_encrypt_send_message (DC->sessions[0]->c, data, ints, 1);
q->session = DC->sessions[0];
q->seq_no = DC->sessions[0]->seq_no - 1;
vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q);
@ -147,10 +152,14 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
}
queries_tree = tree_insert_query (queries_tree, q, lrand48 ());
q->ev.alarm = (void *)alarm_query;
q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
q->ev.self = (void *)q;
insert_event_timer (&q->ev);
//q->ev.alarm = (void *)alarm_query;
//q->ev.timeout = get_double_time () + QUERY_TIMEOUT;
//q->ev.self = (void *)q;
//insert_event_timer (&q->ev);
q->ev = evtimer_new (tgl_state.ev_base, alarm_query_gateway, q);
static struct timeval ptimeout = { QUERY_TIMEOUT, 0};
event_add (q->ev, &ptimeout);
q->extra = extra;
q->callback = callback;
@ -165,27 +174,27 @@ static int fail_on_error (struct query *q UU, int error_code UU, int l UU, char
return 0;
}
void query_ack (long long id) {
struct query *q = query_get (id);
void tglq_query_ack (long long id) {
struct query *q = tglq_query_get (id);
if (q && !(q->flags & QUERY_ACK_RECEIVED)) {
assert (q->msg_id == id);
q->flags |= QUERY_ACK_RECEIVED;
remove_event_timer (&q->ev);
event_del (q->ev);
}
}
void query_error (long long id) {
void tglq_query_error (long long id) {
assert (fetch_int () == CODE_rpc_error);
int error_code = fetch_int ();
int error_len = prefetch_strlen ();
char *error = fetch_str (error_len);
vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
struct query *q = query_get (id);
struct query *q = tglq_query_get (id);
if (!q) {
vlogprintf (E_WARNING, "No such query\n");
} else {
if (!(q->flags & QUERY_ACK_RECEIVED)) {
remove_event_timer (&q->ev);
event_del (q->ev);
}
queries_tree = tree_delete_query (queries_tree, q);
if (q->methods && q->methods->on_error) {
@ -194,6 +203,7 @@ void query_error (long long id) {
vlogprintf ( E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
}
tfree (q->data, q->data_len * 4);
event_free (q->ev);
tfree (q, sizeof (*q));
}
queries_num --;
@ -202,7 +212,7 @@ void query_error (long long id) {
#define MAX_PACKED_SIZE (1 << 24)
static int packed_buffer[MAX_PACKED_SIZE / 4];
void query_result (long long id UU) {
void tglq_query_result (long long id UU) {
vlogprintf (E_DEBUG, "result for query #%lld\n", id);
/*if (verbosity >= 4) {
logprintf ( "result: ");
@ -226,7 +236,7 @@ void query_result (long long id UU) {
hexdump_in ();
}*/
}
struct query *q = query_get (id);
struct query *q = tglq_query_get (id);
if (!q) {
//if (verbosity) {
// logprintf ( "No such query\n");
@ -235,7 +245,7 @@ void query_result (long long id UU) {
in_ptr = in_end;
} else {
if (!(q->flags & QUERY_ACK_RECEIVED)) {
remove_event_timer (&q->ev);
event_del (q->ev);
}
queries_tree = tree_delete_query (queries_tree, q);
if (q->methods && q->methods->on_answer) {
@ -253,6 +263,7 @@ void query_result (long long id UU) {
assert (in_ptr == in_end);
}
tfree (q->data, 4 * q->data_len);
event_free (q->ev);
tfree (q, sizeof (*q));
}
if (end) {
@ -262,37 +273,6 @@ void query_result (long long id UU) {
queries_num --;
}
#define event_timer_cmp(a,b) ((a)->timeout > (b)->timeout ? 1 : ((a)->timeout < (b)->timeout ? -1 : (memcmp (a, b, sizeof (struct event_timer)))))
DEFINE_TREE (timer, struct event_timer *, event_timer_cmp, 0)
struct tree_timer *timer_tree;
void insert_event_timer (struct event_timer *ev) {
vlogprintf (E_DEBUG + 2, "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
timer_tree = tree_insert_timer (timer_tree, ev, lrand48 ());
}
void remove_event_timer (struct event_timer *ev) {
vlogprintf (E_DEBUG + 2, "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
timer_tree = tree_delete_timer (timer_tree, ev);
}
double next_timer_in (void) {
if (!timer_tree) { return 1e100; }
return tree_get_min_timer (timer_tree)->timeout;
}
void work_timers (void) {
double t = get_double_time ();
while (timer_tree) {
struct event_timer *ev = tree_get_min_timer (timer_tree);
assert (ev);
if (ev->timeout > t) { break; }
remove_event_timer (ev);
assert (ev->alarm);
vlogprintf (E_DEBUG, "Alarm\n");
ev->alarm (ev->self);
}
}
int max_chat_size;
int max_bcast_size;
@ -304,7 +284,7 @@ extern struct dc *DC_working;
static void out_random (int n) {
assert (n <= 32);
static char buf[32];
secure_random (buf, n);
tglt_secure_random (buf, n);
out_cstring (buf, n);
}
@ -383,7 +363,7 @@ void tgl_do_help_get_config (void (*callback)(void *, int), void *callback_extra
clear_packet ();
tgl_do_insert_header ();
out_int (CODE_help_get_config);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra);
}
/* }}} */
@ -447,7 +427,7 @@ void tgl_do_send_code (const char *user, void (*callback)(void *callback_extra,
out_string (TG_APP_HASH);
out_string ("en");
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0, callback, callback_extra);
}
@ -474,7 +454,7 @@ void tgl_do_phone_call (const char *user, void (*callback)(void *callback_extra,
out_string (user);
out_string (phone_code_hash);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0, callback, callback_extra);
}
/* }}} */
@ -534,10 +514,10 @@ int tgl_do_auth_check_phone (const char *user) {
out_int (CODE_auth_check_phone);
out_string (user);
check_phone_result = -1;
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0);
net_loop (0, cr_f);
check_phone_result = -1;
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0);
net_loop (0, cr_f);
return check_phone_result;
}*/
@ -571,7 +551,7 @@ int tgl_do_get_nearest_dc (void) {
clear_packet ();
out_int (CODE_help_get_nearest_dc);
nearest_dc_num = -1;
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &nearest_dc_methods, 0);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &nearest_dc_methods, 0);
net_loop (0, nr_f);
return nearest_dc_num;
}*/
@ -607,7 +587,7 @@ int tgl_do_send_code_result (const char *user, const char *code, void (*callback
out_string (user);
out_string (phone_code_hash);
out_string (code);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra);
return 0;
}
@ -619,7 +599,7 @@ int tgl_do_send_code_result_auth (const char *user, const char *code, const char
out_string (code);
out_string (first_name);
out_string (last_name);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra);
return 0;
}
/* }}} */
@ -688,7 +668,7 @@ void tgl_do_update_contact_list (void (*callback) (void *callback_extra, int suc
clear_packet ();
out_int (CODE_contacts_get_contacts);
out_string ("");
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0, callback, callback_extra);
}
/* }}} */
@ -745,7 +725,7 @@ static char *encrypt_decrypted_message (struct tgl_secret_chat *E) {
return (void *)msg_key;
}
void encr_start (void) {
static void encr_start (void) {
encr_extra = packet_ptr;
packet_ptr += 1; // str len
packet_ptr += 2; // fingerprint
@ -754,11 +734,11 @@ void encr_start (void) {
}
void encr_finish (struct tgl_secret_chat *E) {
static void encr_finish (struct tgl_secret_chat *E) {
int l = packet_ptr - (encr_extra + 8);
while (((packet_ptr - encr_extra) - 3) & 3) {
int t;
secure_random (&t, 4);
tglt_secure_random (&t, 4);
out_int (t);
}
@ -775,7 +755,7 @@ void encr_finish (struct tgl_secret_chat *E) {
void tgl_do_send_encr_chat_layer (struct tgl_secret_chat *E) {
long long t;
secure_random (&t, 8);
tglt_secure_random (&t, 8);
int action[2];
action[0] = CODE_decrypted_message_action_notify_layer;
action[1] = 15;
@ -807,9 +787,9 @@ static int msg_send_on_answer (struct query *q UU) {
int id = fetch_int (); // id
struct tgl_message *M = q->extra;
bl_do_set_msg_id (M, id);
fetch_date ();
fetch_pts ();
fetch_seq ();
tglu_fetch_date ();
tglu_fetch_pts ();
tglu_fetch_seq ();
if (x == CODE_messages_sent_message_link) {
assert (skip_type_any (TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (contacts_link))) >= 0);
}
@ -902,7 +882,7 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void *
out_int (CODE_decrypted_message_service);
out_long (M->id);
static int buf[4];
secure_random (buf, 16);
tglt_secure_random (buf, 16);
out_cstring ((void *)buf, 16);
switch (M->action.type) {
@ -915,7 +895,7 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void *
}
encr_finish (&P->encr_chat);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
}
void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
@ -942,13 +922,13 @@ void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callbac
out_int (CODE_decrypted_message);
out_long (M->id);
static int buf[4];
secure_random (buf, 16);
tglt_secure_random (buf, 16);
out_cstring ((void *)buf, 16);
out_cstring ((void *)M->message, M->message_len);
out_int (CODE_decrypted_message_media_empty);
encr_finish (&P->encr_chat);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
}
void tgl_do_send_msg (struct tgl_message *M, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
@ -961,7 +941,7 @@ void tgl_do_send_msg (struct tgl_message *M, void (*callback)(void *callback_ext
out_peer_id (M->to_id);
out_cstring (M->message, M->message_len);
out_long (M->id);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, M, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, M, callback, callback_extra);
}
void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
@ -983,7 +963,7 @@ void tgl_do_send_message (tgl_peer_id_t id, const char *msg, int len, void (*cal
}
}
long long t;
secure_random (&t, 8);
tglt_secure_random (&t, 8);
vlogprintf (E_DEBUG, "t = %lld, len = %d\n", t, len);
bl_do_send_message_text (t, tgl_state.our_id, tgl_get_peer_type (id), tgl_get_peer_id (id), time (0), len, msg);
struct tgl_message *M = tgl_message_get (t);
@ -1024,8 +1004,8 @@ void tgl_do_send_text (tgl_peer_id_t id, char *file_name, void (*callback)(void
/* {{{ Mark read */
static int mark_read_on_receive (struct query *q UU) {
assert (fetch_int () == (int)CODE_messages_affected_history);
fetch_pts ();
fetch_seq ();
tglu_fetch_pts ();
tglu_fetch_seq ();
fetch_int (); // offset
if (q->callback) {
((void (*)(void *, int))q->callback)(q->callback_extra, 1);
@ -1057,7 +1037,7 @@ void tgl_do_messages_mark_read (tgl_peer_id_t id, int max_id, void (*callback)(v
out_peer_id (id);
out_int (max_id);
out_int (0);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, 0, callback, callback_extra);
}
void tgl_do_messages_mark_read_encr (tgl_peer_id_t id, long long access_hash, int last_time, void (*callback)(void *callback_extra, int), void *callback_extra) {
@ -1067,7 +1047,7 @@ void tgl_do_messages_mark_read_encr (tgl_peer_id_t id, long long access_hash, in
out_int (tgl_get_peer_id (id));
out_long (access_hash);
out_int (last_time);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, 0, callback, callback_extra);
}
void tgl_do_mark_read (tgl_peer_id_t id, void (*callback)(void *callback_extra, int success), void *callback_extra) {
@ -1177,7 +1157,7 @@ void tgl_do_get_history (tgl_peer_id_t id, int limit, int offline_mode, void (*c
out_int (0);
out_int (0);
out_int (limit);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, (void *)*(long *)&id, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, (void *)*(long *)&id, callback, callback_extra);
}
/* }}} */
@ -1264,7 +1244,7 @@ void tgl_do_get_dialog_list (void (*callback)(void *callback_extra, int success,
out_int (0);
out_int (0);
out_int (1000);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0, callback, callback_extra);
}
/* }}} */
@ -1332,8 +1312,8 @@ static int send_file_on_answer (struct query *q UU) {
for (i = 0; i < n; i++) {
tglf_fetch_alloc_user ();
}
fetch_pts ();
fetch_seq ();
tglu_fetch_pts ();
tglu_fetch_seq ();
if (q->callback) {
((void (*)(void *, int, struct tgl_message *))q->callback)(q->callback_extra, 1, M);
@ -1402,7 +1382,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
if (f->encr) {
if (x & 15) {
assert (f->offset == f->size);
secure_random (buf + x, (-x) & 15);
tglt_secure_random (buf + x, (-x) & 15);
x = (x + 15) & ~15;
}
@ -1420,7 +1400,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
assert (f->part_size == x);
}
//update_prompt ();
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra);
} else {
tgl_state.cur_uploaded_bytes -= f->size;
tgl_state.cur_uploading_bytes -= f->size;
@ -1467,7 +1447,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
}
out_long (-lrand48 () * (1ll << 32) - lrand48 ());
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0, callback, callback_extra);
} else {
struct tgl_message *M = talloc0 (sizeof (*M));
@ -1558,7 +1538,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
M->id = r;
M->date = time (0);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra);
}
tfree_str (f->file_name);
tfree (f, sizeof (*f));
@ -1572,7 +1552,7 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra
out_long (f->thumb_id);
out_int (0);
out_cstring ((void *)thumb_file, thumb_file_size);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra);
}*/
void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
@ -1617,11 +1597,11 @@ void tgl_do_send_photo (int type, tgl_peer_id_t to_id, char *file_name, void (*c
if (tgl_get_peer_type (f->to_id) == TGL_PEER_ENCR_CHAT) {
f->encr = 1;
f->iv = talloc (32);
secure_random (f->iv, 32);
tglt_secure_random (f->iv, 32);
f->init_iv = talloc (32);
memcpy (f->init_iv, f->iv, 32);
f->key = talloc (32);
secure_random (f->key, 32);
tglt_secure_random (f->key, 32);
}
/*if (f->media_type == CODE_input_media_uploaded_video && !f->encr) {
f->media_type = CODE_input_media_uploaded_thumb_video;
@ -1651,8 +1631,8 @@ static int fwd_msg_on_answer (struct query *q UU) {
for (i = 0; i < n; i++) {
tglf_fetch_alloc_user ();
}
fetch_pts ();
fetch_seq ();
tglu_fetch_pts ();
tglu_fetch_seq ();
//print_message (M);
if (q->callback) {
((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M);
@ -1676,7 +1656,7 @@ void tgl_do_forward_message (tgl_peer_id_t id, int n, void (*callback)(void *cal
out_peer_id (id);
out_int (n);
out_long (lrand48 () * (1ll << 32) + lrand48 ());
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
}
/* }}} */
@ -1695,8 +1675,8 @@ static int rename_chat_on_answer (struct query *q UU) {
for (i = 0; i < n; i++) {
tglf_fetch_alloc_user ();
}
fetch_pts ();
fetch_seq ();
tglu_fetch_pts ();
tglu_fetch_seq ();
//print_message (M);
if (q->callback) {
((void (*)(void *, int, struct tgl_message *))q->callback) (q->callback_extra, 1, M);
@ -1715,7 +1695,7 @@ void tgl_do_rename_chat (tgl_peer_id_t id, char *name UU, void (*callback)(void
assert (tgl_get_peer_type (id) == TGL_PEER_CHAT);
out_int (tgl_get_peer_id (id));
out_string (name);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0, callback, callback_extra);
}
/* }}} */
@ -1774,7 +1754,7 @@ void tgl_do_get_chat_info (tgl_peer_id_t id, int offline_mode, void (*callback)(
out_int (CODE_messages_get_full_chat);
assert (tgl_get_peer_type (id) == TGL_PEER_CHAT);
out_int (tgl_get_peer_id (id));
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0, callback, callback_extra);
}
/* }}} */
@ -1836,7 +1816,7 @@ void tgl_do_get_user_info (tgl_peer_id_t id, int offline_mode, void (*callback)(
out_int (CODE_input_user_contact);
out_int (tgl_get_peer_id (id));
}
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, callback, callback_extra);
}
/* }}} */
@ -1867,7 +1847,7 @@ void tgl_do_get_user_list_info_silent (int num, int *list) {
out_int (list[i]);
//out_long (0);
}
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0);
}*/
/* }}} */
@ -2012,8 +1992,8 @@ static void load_next_part (struct download *D, void *callback, void *callback_e
}
out_int (D->offset);
out_int (1 << 14);
send_query (DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D, callback, callback_extra);
//send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D);
tglq_send_query (DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D, callback, callback_extra);
//tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D);
}
void tgl_do_load_photo_size (struct tgl_photo_size *P, void (*callback)(void *callback_extra, int success, char *filename), void *callback_extra) {
@ -2160,7 +2140,7 @@ static int export_auth_on_answer (struct query *q UU) {
out_int (CODE_auth_import_authorization);
out_int (tgl_state.our_id);
out_cstring (s, l);
send_query (q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0, q->callback, q->callback_extra);
tglq_send_query (q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0, q->callback, q->callback_extra);
tfree (s, l);
return 0;
}
@ -2175,7 +2155,7 @@ void tgl_do_export_auth (int num, void (*callback) (void *callback_extra, int su
clear_packet ();
out_int (CODE_auth_export_authorization);
out_int (num);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, DC_list[num], callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, DC_list[num], callback, callback_extra);
}
/* }}} */
@ -2262,7 +2242,7 @@ void tgl_do_add_contact (const char *phone, int phone_len, const char *first_nam
out_cstring (first_name, first_name_len);
out_cstring (last_name, last_name_len);
out_int (force ? CODE_bool_true : CODE_bool_false);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0, callback, callback_extra);
}
/* }}} */
@ -2298,7 +2278,7 @@ void tgl_do_msg_search (tgl_peer_id_t id, int from, int to, int limit, const cha
out_int (0); // offset
out_int (0); // max_id
out_int (limit);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, 0, callback, callback_extra);
}
/* }}} */
@ -2348,7 +2328,7 @@ void tgl_do_contacts_search (int limit, const char *s, void (*callback) (void *c
out_int (CODE_contacts_search);
out_string (s);
out_int (limit);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &contacts_search_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &contacts_search_methods, 0, callback, callback_extra);
}
/* }}} */
@ -2437,7 +2417,7 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran
return;
} // Already generated key for this chat
unsigned char random_here[256];
secure_random (random_here, 256);
tglt_secure_random (random_here, 256);
for (i = 0; i < 256; i++) {
random[i] ^= random_here[i];
}
@ -2445,7 +2425,7 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran
ensure_ptr (b);
BIGNUM *g_a = BN_bin2bn (E->g_key, 256, 0);
ensure_ptr (g_a);
assert (check_g (tgl_state.encr_prime, g_a) >= 0);
assert (tglmp_check_g (tgl_state.encr_prime, g_a) >= 0);
if (!ctx) {
ctx = BN_CTX_new ();
ensure_ptr (ctx);
@ -2485,14 +2465,14 @@ void tgl_do_send_accept_encr_chat (struct tgl_secret_chat *E, unsigned char *ran
BN_clear_free (p);
BN_clear_free (r);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E, callback, callback_extra);
}
void tgl_do_create_keys_end (struct tgl_secret_chat *U) {
assert (tgl_state.encr_prime);
BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0);
ensure_ptr (g_b);
assert (check_g (tgl_state.encr_prime, g_b) >= 0);
assert (tglmp_check_g (tgl_state.encr_prime, g_b) >= 0);
if (!ctx) {
ctx = BN_CTX_new ();
ensure_ptr (ctx);
@ -2535,7 +2515,7 @@ void tgl_do_send_create_encr_chat (void *x, unsigned char *random, void (*callba
int user_id = (long)x;
int i;
unsigned char random_here[256];
secure_random (random_here, 256);
tglt_secure_random (random_here, 256);
for (i = 0; i < 256; i++) {
random[i] ^= random_here[i];
}
@ -2595,7 +2575,7 @@ void tgl_do_send_create_encr_chat (void *x, unsigned char *random, void (*callba
BN_clear_free (p);
BN_clear_free (r);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra);
}
static int get_dh_config_on_answer (struct query *q UU) {
@ -2611,7 +2591,7 @@ static int get_dh_config_on_answer (struct query *q UU) {
BIGNUM *p = BN_bin2bn ((void *)s, 256, 0);
ensure_ptr (p);
assert (check_DH_params (p, a) >= 0);
assert (tglmp_check_DH_params (p, a) >= 0);
BN_free (p);
}
int l = prefetch_strlen ();
@ -2644,7 +2624,7 @@ void tgl_do_accept_encr_chat_request (struct tgl_secret_chat *E, void (*callback
void **x = talloc (2 * sizeof (void *));
x[0] = tgl_do_send_accept_encr_chat;
x[1] = E;
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra);
}
void tgl_do_create_encr_chat_request (int user_id, void (*callback)(void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) {
@ -2655,7 +2635,7 @@ void tgl_do_create_encr_chat_request (int user_id, void (*callback)(void *callba
void **x = talloc (2 * sizeof (void *));
x[0] = tgl_do_send_create_encr_chat;
x[1] = (void *)(long)(user_id);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra);
}
/* }}} */
@ -2711,7 +2691,7 @@ static int get_difference_on_answer (struct query *q UU) {
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
work_update (0, 0);
tglu_work_update (0, 0);
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
@ -2780,10 +2760,10 @@ void tgl_do_get_difference (int sync_from_start, void (*callback)(void *callback
out_int (tgl_state.pts);
out_int (tgl_state.date);
out_int (tgl_state.qts);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0, callback, callback_extra);
} else {
out_int (CODE_updates_get_state);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0, callback, callback_extra);
}
}
/* }}} */
@ -2872,7 +2852,7 @@ void tgl_do_get_suggested (void) {
clear_packet ();
out_int (CODE_contacts_get_suggested);
out_int (100);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_suggested_methods, 0);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_suggested_methods, 0);
}*/
/* }}} */
@ -2899,7 +2879,7 @@ void tgl_do_add_user_to_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit
out_int (tgl_get_peer_id (id));
}
out_int (limit);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra);
}
void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, void (*callback)(void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
@ -2917,7 +2897,7 @@ void tgl_do_del_user_from_chat (tgl_peer_id_t chat_id, tgl_peer_id_t id, void (*
out_int (CODE_input_user_contact);
out_int (tgl_get_peer_id (id));
}
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra);
}
/* }}} */
@ -2962,7 +2942,7 @@ void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic, void (*callba
out_int (tgl_get_peer_id (id));
}
out_string (chat_topic);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0, callback, callback_extra);
}
/* }}} */
@ -2991,7 +2971,7 @@ void tgl_do_delete_msg (long long id, void (*callback)(void *callback_extra, int
out_int (CODE_vector);
out_int (1);
out_int (id);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0, callback, callback_extra);
}
/* }}} */
@ -3020,11 +3000,11 @@ void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, in
out_int (CODE_vector);
out_int (1);
out_int (id);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &restore_msg_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &restore_msg_methods, 0, callback, callback_extra);
}
/* }}} */
int update_status_on_answer (struct query *q UU) {
static int update_status_on_answer (struct query *q UU) {
fetch_bool ();
if (q->callback) {
@ -3042,5 +3022,5 @@ void tgl_do_update_status (int online UU, void (*callback)(void *callback_extra,
clear_packet ();
out_int (CODE_account_update_status);
out_int (online ? CODE_bool_false : CODE_bool_true);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0, callback, callback_extra);
tglq_send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0, callback, callback_extra);
}

View File

@ -16,13 +16,15 @@
Copyright Vitaly Valtman 2013
*/
#include "net.h"
//#include "net.h"
#ifndef __QUERIES_H__
#define __QUERIES_H__
#include "structures.h"
#include "auto.h"
#include "tgl-layout.h"
struct event;
#define QUERY_ACK_RECEIVED 1
struct query;
@ -33,12 +35,6 @@ struct query_methods {
struct paramed_type *type;
};
struct event_timer {
double timeout;
int (*alarm)(void *self);
void *self;
};
struct query {
long long msg_id;
int data_len;
@ -46,7 +42,7 @@ struct query {
int seq_no;
void *data;
struct query_methods *methods;
struct event_timer ev;
struct event *ev;
struct dc *DC;
struct session *session;
void *extra;
@ -55,14 +51,12 @@ struct query {
};
struct query *send_query (struct dc *DC, int len, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra);
void query_ack (long long id);
void query_error (long long id);
void query_result (long long id);
void query_restart (long long id);
struct query *tglq_send_query (struct dc *DC, int len, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra);
void tglq_query_ack (long long id);
void tglq_query_error (long long id);
void tglq_query_result (long long id);
void tglq_query_restart (long long id);
void insert_event_timer (struct event_timer *ev);
void remove_event_timer (struct event_timer *ev);
double next_timer_in (void);
void work_timers (void);

View File

@ -32,6 +32,7 @@
#include <openssl/sha.h>
#include "queries.h"
#include "binlog.h"
#include "updates.h"
#include "tgl.h"
@ -497,7 +498,7 @@ void tglf_fetch_photo_size (struct tgl_photo_size *S) {
}
}
void fetch_geo (struct tgl_geo *G) {
void tglf_fetch_geo (struct tgl_geo *G) {
unsigned x = fetch_int ();
if (x == CODE_geo_point) {
G->longitude = fetch_double ();
@ -519,7 +520,7 @@ void tglf_fetch_photo (struct tgl_photo *P) {
P->user_id = fetch_int ();
P->date = fetch_int ();
P->caption = fetch_str_dup ();
fetch_geo (&P->geo);
tglf_fetch_geo (&P->geo);
assert (fetch_int () == CODE_vector);
P->sizes_num = fetch_int ();
P->sizes = talloc (sizeof (struct tgl_photo_size) * P->sizes_num);
@ -630,10 +631,10 @@ void tglf_fetch_message_short (struct tgl_message *M) {
int l = prefetch_strlen ();
char *s = fetch_str (l);
fetch_pts ();
tglu_fetch_pts ();
int date = fetch_int ();
fetch_seq ();
tglu_fetch_seq ();
bl_do_create_message_text (id, from_id, TGL_PEER_USER, to_id, date, l, s);
} else {
@ -642,9 +643,9 @@ void tglf_fetch_message_short (struct tgl_message *M) {
int l = prefetch_strlen ();
fetch_str (l); // text
fetch_pts ();
tglu_fetch_pts ();
fetch_int ();
fetch_seq ();
tglu_fetch_seq ();
}
}
@ -658,10 +659,10 @@ void tglf_fetch_message_short_chat (struct tgl_message *M) {
int l = prefetch_strlen ();
char *s = fetch_str (l);
fetch_pts ();
tglu_fetch_pts ();
int date = fetch_int ();
fetch_seq ();
tglu_fetch_seq ();
bl_do_create_message_text (id, from_id, TGL_PEER_CHAT, to_id, date, l, s);
} else {
@ -671,9 +672,9 @@ void tglf_fetch_message_short_chat (struct tgl_message *M) {
int l = prefetch_strlen ();
fetch_str (l); // text
fetch_pts ();
tglu_fetch_pts ();
fetch_int ();
fetch_seq ();
tglu_fetch_seq ();
}
}
@ -697,7 +698,7 @@ void tglf_fetch_message_media (struct tgl_message_media *M) {
tglf_fetch_document (&M->document);
break;
case CODE_message_media_geo:
fetch_geo (&M->geo);
tglf_fetch_geo (&M->geo);
break;
case CODE_message_media_contact:
M->phone = fetch_str_dup ();
@ -995,7 +996,7 @@ void tglf_fetch_message (struct tgl_message *M) {
bl_do_set_unread (M, unread);
}
void tglf_fetch_geo_message (struct tgl_message *M) {
void tglf_tglf_fetch_geo_message (struct tgl_message *M) {
memset (M, 0, sizeof (*M));
unsigned x = fetch_int ();
assert (x == CODE_geo_chat_message_empty || x == CODE_geo_chat_message || x == CODE_geo_chat_message_service);
@ -1254,7 +1255,7 @@ struct tgl_message *tglf_fetch_alloc_message (void) {
struct tgl_message *tglf_fetch_alloc_geo_message (void) {
struct tgl_message *M = talloc (sizeof (*M));
tglf_fetch_geo_message (M);
tglf_tglf_fetch_geo_message (M);
struct tgl_message *M1 = tree_lookup_message (message_tree, M);
messages_allocated ++;
if (M1) {

11
tgl-inner.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef __TGL_INNER_H__
#define __TGL_INNER_H__
#define vlogprintf(verbosity_level,...) \
do { \
if (tgl_state.verbosity >= verbosity_level) { \
tgl_state.callback.logprintf (__VA_ARGS__); \
} \
} while (0)
#endif

17
tgl.c
View File

@ -3,6 +3,10 @@
#endif
#include "tgl.h"
#include "tools.h"
#include "mtproto-client.h"
#include <event2/event.h>
struct tgl_state tgl_state;
@ -21,3 +25,16 @@ void tgl_set_auth_file_path (const char *path) {
void tgl_set_download_directory (const char *path) {
tgl_state.downloads_directory = tstrdup (path);
}
void tgl_set_callback (struct tgl_update_callback *cb) {
tgl_state.callback = *cb;
}
void tgl_set_rsa_key (const char *key) {
tgl_state.rsa_key = tstrdup (key);
}
void tgl_init (void) {
tgl_state.ev_base = event_base_new ();
tglmp_on_start (tgl_state.rsa_key);
}

52
tgl.h
View File

@ -10,22 +10,37 @@
#define TGL_VERSION "0.9-beta"
// Do not modify this structure, unless you know what you do
struct connection;
struct mtproto_methods;
struct session;
struct dc;
struct tgl_update_callback {
void (*new_msg)(struct tgl_message *M);
void (*marked_read)(int num, struct tgl_message *list[]);
void (*logprintf)(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
void (*type_notification)(tgl_peer_id_t id, struct tgl_user *U);
void (*type_in_chat_notification)(tgl_peer_id_t id, struct tgl_user *U, tgl_peer_id_t chat_id, struct tgl_chat *C);
void (*type_notification)(struct tgl_user *U);
void (*type_in_chat_notification)(struct tgl_user *U, struct tgl_chat *C);
void (*type_in_secret_chat_notification)(struct tgl_secret_chat *E);
void (*status_notification)(struct tgl_user *U);
void (*user_registered)(struct tgl_user *U);
void (*user_activated)(struct tgl_user *U);
void (*new_authorization)(const char *device, const char *location);
void (*secret_chat_request)(struct tgl_secret_chat *E);
void (*secret_chat_established)(struct tgl_secret_chat *E);
void (*secret_chat_deleted)(struct tgl_secret_chat *E);
};
#define vlogprintf(verbosity_level,...) \
do { \
if (tgl_state.verbosity >= verbosity_level) { \
tgl_state.callback.logprintf (__VA_ARGS__); \
} \
} while (0)
struct tgl_net_methods {
int (*write_out) (struct connection *c, void *data, int len);
int (*read_in) (struct connection *c, void *data, int len);
int (*read_in_lookup) (struct connection *c, void *data, int len);
int (*flush_out) (struct connection *c);
void (*incr_out_packet_num) (struct connection *c);
struct dc *(*get_dc) (struct connection *c);
struct session *(*get_session) (struct connection *c);
struct connection *(*create_connection) (const char *host, int port, struct dc *dc, struct session *session, struct mtproto_methods *methods);
};
#define E_ERROR 0
@ -61,6 +76,10 @@ struct tgl_state {
char *downloads_directory;
struct tgl_update_callback callback;
struct tgl_net_methods *net_methods;
struct event_base *ev_base;
char *rsa_key;
};
extern struct tgl_state tgl_state;
@ -94,6 +113,8 @@ void tgl_set_binlog_mode (int mode);
void tgl_set_binlog_path (const char *path);
void tgl_set_auth_file_path (const char *path);
void tgl_set_download_directory (const char *path);
void tgl_set_callback (struct tgl_update_callback *cb);
void tgl_set_rsa_key (const char *key);
static inline int tgl_get_peer_type (tgl_peer_id_t id) {
@ -127,6 +148,10 @@ static inline void tgl_set_test_mode (void) {
tgl_state.test_mode ++;
}
struct pollfd;
int tgl_connections_make_poll_array (struct pollfd *fds, int max);
void tgl_connections_poll_result (struct pollfd *fds, int max);
void tgl_do_help_get_config (void (*callback)(void *callback_extra, int success), void *callback_extra);
void tgl_do_send_code (const char *user, void (*callback)(void *callback_extra, int success, int registered, const char *hash), void *callback_extra);
void tgl_do_phone_call (const char *user, void (*callback)(void *callback_extra, int success), void *callback_extra);
@ -168,8 +193,19 @@ void tgl_do_update_status (int online, void (*callback)(void *callback_extra, in
void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]);
void tgl_do_send_ping (struct connection *c);
//void tgl_do_get_suggested (void);
void tgl_do_create_keys_end (struct tgl_secret_chat *U);
void tgl_do_send_encr_chat_layer (struct tgl_secret_chat *E);
struct mtproto_methods {
int (*ready) (struct connection *c);
int (*close) (struct connection *c);
int (*execute) (struct connection *c, int op, int len);
};
void tgl_init (void);
void tgl_dc_authorize (struct dc *DC);
#endif

46
tools.c
View File

@ -28,9 +28,12 @@
#include <stdlib.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <zlib.h>
#include <time.h>
#include <sys/time.h>
#include "interface.h"
//#include "interface.h"
#include "tools.h"
#ifdef DEBUG
@ -43,6 +46,15 @@ int used_blocks;
int free_blocks_cnt;
#endif
void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2), weak));
void logprintf (const char *format, ...) {
va_list ap;
va_start (ap, format);
vfprintf (stdout, format, ap);
va_end (ap);
}
extern int verbosity;
long long total_allocated_bytes;
@ -269,3 +281,35 @@ void texists (void *ptr, int size) {
assert (block_num < used_blocks);
}
#endif
void my_clock_gettime (int clock_id, struct timespec *T) {
#ifdef __MACH__
// We are ignoring MONOTONIC and hope time doesn't go back too often
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
T->tv_sec = mts.tv_sec;
T->tv_nsec = mts.tv_nsec;
#else
assert (clock_gettime(clock_id, T) >= 0);
#endif
}
double get_double_time (void) {
struct timespec tv;
my_clock_gettime (CLOCK_REALTIME, &tv);
return tv.tv_sec + 1e-9 * tv.tv_nsec;
}
void tglt_secure_random (void *s, int l) {
if (RAND_bytes (s, l) < 0) {
/*if (allow_weak_random) {
RAND_pseudo_bytes (s, l);
} else {*/
assert (0 && "End of random. If you want, you can start with -w");
//}
}
}

View File

@ -20,6 +20,8 @@
#ifndef __TOOLS_H__
#define __TOOLS_H__
double get_double_time (void);
void *talloc (size_t size);
void *trealloc (void *ptr, size_t old_size, size_t size);
void *talloc0 (size_t size);
@ -37,6 +39,8 @@ void tfree_secure (void *ptr, int size);
int tsnprintf (char *buf, int len, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
int tasprintf (char **res, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
void tglt_secure_random (void *s, int l);
#ifdef DEBUG
void tcheck (void);
void texists (void *ptr, int size);

30
tree.h
View File

@ -32,7 +32,7 @@ struct tree_ ## X_NAME { \
int y;\
};\
\
struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\
static inline struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\
struct tree_ ## X_NAME *T = talloc (sizeof (*T));\
T->x = x;\
T->y = y;\
@ -40,11 +40,11 @@ struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\
return T;\
}\
\
void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\
static inline void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\
tfree (T, sizeof (*T));\
}\
\
void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\
static inline void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\
if (!T) {\
*L = *R = 0;\
} else {\
@ -59,8 +59,8 @@ void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ##
}\
}\
\
struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result));\
struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\
static inline struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result));\
static inline struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\
if (!T) {\
return new_tree_node_ ## X_NAME (x, y);\
} else {\
@ -81,7 +81,7 @@ struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYP
}\
}\
\
struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\
static inline struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\
if (!L || !R) {\
return L ? L : R;\
} else {\
@ -95,8 +95,8 @@ struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct
}\
}\
\
struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result));\
struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
static inline struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result));\
static inline struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
assert (T);\
int c = X_CMP (x, T->x);\
if (!c) {\
@ -113,13 +113,13 @@ struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYP
}\
}\
\
X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\
static inline X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\
if (!T) { return X_UNSET; } \
while (T->left) { T = T->left; }\
return T->x; \
} \
\
X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
static inline X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
int c;\
while (T && (c = X_CMP (x, T->x))) {\
T = (c < 0 ? T->left : T->right);\
@ -127,25 +127,25 @@ 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)) {\
static inline 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); \
}\
\
void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) {\
static inline void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) {\
if (!T) { return; } \
tree_act_ex_ ## X_NAME (T->left, act, extra); \
act (T->x, extra); \
tree_act_ex_ ## X_NAME (T->right, act, extra); \
}\
\
int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \
static inline 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); \
}\
void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
static inline void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return; }\
if (T->left) { \
assert (T->left->y <= T->y);\
@ -158,7 +158,7 @@ void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
tree_check_ ## X_NAME (T->left); \
tree_check_ ## X_NAME (T->right); \
}\
struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \
static inline struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return 0; }\
tree_clear_ ## X_NAME (T->left); \
tree_clear_ ## X_NAME (T->right); \

728
updates.c Normal file
View File

@ -0,0 +1,728 @@
#include "tgl.h"
#include "updates.h"
#include "mtproto-common.h"
#include "binlog.h"
#include "auto.h"
#include <assert.h>
void tglu_fetch_pts (void) {
int p = fetch_int ();
if (p <= tgl_state.pts) { return; }
if (p != tgl_state.pts + 1) {
if (tgl_state.pts) {
//vlogprintf (E_NOTICE, "Hole in pts p = %d, pts = %d\n", p, tgl_state.pts);
// get difference should be here
tgl_state.pts = p;
} else {
tgl_state.pts = p;
}
} else {
tgl_state.pts ++;
}
bl_do_set_pts (tgl_state.pts);
}
void tglu_fetch_qts (void) {
int p = fetch_int ();
if (p <= tgl_state.qts) { return; }
if (p != tgl_state.qts + 1) {
if (tgl_state.qts) {
//logprintf ("Hole in qts\n");
// get difference should be here
tgl_state.qts = p;
} else {
tgl_state.qts = p;
}
} else {
tgl_state.qts ++;
}
bl_do_set_qts (tgl_state.qts);
}
void tglu_fetch_date (void) {
int p = fetch_int ();
if (p > tgl_state.date) {
tgl_state.date = p;
bl_do_set_date (tgl_state.date);
}
}
void tglu_fetch_seq (void) {
int x = fetch_int ();
if (x > tgl_state.seq + 1) {
vlogprintf (E_NOTICE, "Hole in seq: seq = %d, x = %d\n", tgl_state.seq, x);
//tgl_do_get_difference ();
//seq = x;
} else if (x == tgl_state.seq + 1) {
tgl_state.seq = x;
bl_do_set_seq (tgl_state.seq);
}
}
static void fetch_dc_option (void) {
assert (fetch_int () == CODE_dc_option);
int id = fetch_int ();
int l1 = prefetch_strlen ();
char *name = fetch_str (l1);
int l2 = prefetch_strlen ();
char *ip = fetch_str (l2);
int port = fetch_int ();
vlogprintf (E_DEBUG, "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
bl_do_dc_option (id, l1, name, l2, ip, port);
}
void tglu_work_update (struct connection *c, long long msg_id) {
unsigned op = fetch_int ();
switch (op) {
case CODE_update_new_message:
{
struct tgl_message *M = tglf_fetch_alloc_message ();
assert (M);
tglu_fetch_pts ();
//if (tgl_state.callback.new_msg) {
// tgl_state.callback.new_msg (M);
//}
//unread_messages ++;
//print_message (M);
//update_prompt ();
break;
};
case CODE_update_message_i_d:
{
int id = fetch_int (); // id
int new = fetch_long (); // random_id
struct tgl_message *M = tgl_message_get (new);
if (M) {
bl_do_set_msg_id (M, id);
}
}
break;
case CODE_update_read_messages:
{
assert (fetch_int () == (int)CODE_vector);
int n = fetch_int ();
//int p = 0;
int i;
for (i = 0; i < n; i++) {
int id = fetch_int ();
struct tgl_message *M = tgl_message_get (id);
if (M) {
bl_do_set_unread (M, 0);
}
}
tglu_fetch_pts ();
/*if (log_level >= 1) {
print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" %d messages marked as read\n", n);
pop_color ();
print_end ();
}*/
}
break;
case CODE_update_user_typing:
{
tgl_peer_id_t id = TGL_MK_USER (fetch_int ());
tgl_peer_t *U = tgl_peer_get (id);
if (tgl_state.callback.type_notification && U) {
tgl_state.callback.type_notification ((void *)U);
}
/*if (log_level >= 2) {
print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (id, U);
printf (" is typing....\n");
pop_color ();
print_end ();
}*/
}
break;
case CODE_update_chat_user_typing:
{
tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ());
tgl_peer_id_t id = TGL_MK_USER (fetch_int ());
tgl_peer_t *C = tgl_peer_get (chat_id);
tgl_peer_t *U = tgl_peer_get (id);
if (U && C) {
if (tgl_state.callback.type_in_chat_notification) {
tgl_state.callback.type_in_chat_notification ((void *)U, (void *)C);
}
}
/*if (log_level >= 2) {
print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (id, U);
printf (" is typing in chat ");
print_chat_name (chat_id, C);
printf ("....\n");
pop_color ();
print_end ();
}*/
}
break;
case CODE_update_user_status:
{
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_t *U = tgl_peer_get (user_id);
if (U) {
tglf_fetch_user_status (&U->user.status);
if (tgl_state.callback.status_notification) {
tgl_state.callback.status_notification ((void *)U);
}
/*if (log_level >= 3) {
print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (user_id, U);
printf (" is now ");
printf ("%s\n", (U->user.status.online > 0) ? "online" : "offline");
pop_color ();
print_end ();
}*/
} else {
struct tgl_user_status t;
tglf_fetch_user_status (&t);
}
}
break;
case CODE_update_user_name:
{
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_t *UC = tgl_peer_get (user_id);
if (UC && (UC->flags & FLAG_CREATED)) {
int l1 = prefetch_strlen ();
char *f = fetch_str (l1);
int l2 = prefetch_strlen ();
char *l = fetch_str (l2);
struct tgl_user *U = &UC->user;
bl_do_user_set_real_name (U, f, l1, l, l2);
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (user_id, UC);
printf (" changed name to ");
print_user_name (user_id, UC);
printf ("\n");
pop_color ();
print_end ();*/
} else {
fetch_skip_str ();
fetch_skip_str ();
}
}
break;
case CODE_update_user_photo:
{
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_t *UC = tgl_peer_get (user_id);
tglu_fetch_date ();
if (UC && (UC->flags & FLAG_CREATED)) {
struct tgl_user *U = &UC->user;
unsigned y = fetch_int ();
long long photo_id;
struct tgl_file_location big;
struct tgl_file_location small;
memset (&big, 0, sizeof (big));
memset (&small, 0, sizeof (small));
if (y == CODE_user_profile_photo_empty) {
photo_id = 0;
big.dc = -2;
small.dc = -2;
} else {
assert (y == CODE_user_profile_photo);
photo_id = fetch_long ();
tglf_fetch_file_location (&small);
tglf_fetch_file_location (&big);
}
bl_do_set_user_profile_photo (U, photo_id, &big, &small);
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (user_id, UC);
printf (" updated profile photo\n");
pop_color ();
print_end ();*/
} else {
struct tgl_file_location t;
unsigned y = fetch_int ();
if (y == CODE_user_profile_photo_empty) {
} else {
assert (y == CODE_user_profile_photo);
fetch_long (); // photo_id
tglf_fetch_file_location (&t);
tglf_fetch_file_location (&t);
}
}
fetch_bool ();
}
break;
case CODE_update_restore_messages:
{
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Restored %d messages\n", n);
pop_color ();
print_end ();*/
fetch_skip (n);
tglu_fetch_pts ();
}
break;
case CODE_update_delete_messages:
{
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Deleted %d messages\n", n);
pop_color ();
print_end ();*/
fetch_skip (n);
tglu_fetch_pts ();
}
break;
case CODE_update_chat_participants:
{
unsigned x = fetch_int ();
assert (x == CODE_chat_participants || x == CODE_chat_participants_forbidden);
tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ());
int n = 0;
tgl_peer_t *C = tgl_peer_get (chat_id);
if (C && (C->flags & FLAG_CREATED)) {
if (x == CODE_chat_participants) {
bl_do_chat_set_admin (&C->chat, fetch_int ());
assert (fetch_int () == CODE_vector);
n = fetch_int ();
struct tgl_chat_user *users = talloc (12 * n);
int i;
for (i = 0; i < n; i++) {
assert (fetch_int () == (int)CODE_chat_participant);
users[i].user_id = fetch_int ();
users[i].inviter_id = fetch_int ();
users[i].date = fetch_int ();
}
int version = fetch_int ();
bl_do_chat_set_participants (&C->chat, version, n, users);
}
} else {
if (x == CODE_chat_participants) {
fetch_int (); // admin_id
assert (fetch_int () == CODE_vector);
n = fetch_int ();
fetch_skip (n * 4);
fetch_int (); // version
}
}
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Chat ");
print_chat_name (chat_id, C);
if (x == CODE_chat_participants) {
printf (" changed list: now %d members\n", n);
} else {
printf (" changed list, but we are forbidden to know about it (Why this update even was sent to us?\n");
}
pop_color ();
print_end ();*/
}
break;
case CODE_update_contact_registered:
{
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_t *U = tgl_peer_get (user_id);
fetch_int (); // date
if (tgl_state.callback.user_registered && U) {
tgl_state.callback.user_registered ((void *)U);
}
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (user_id, U);
printf (" registered\n");
pop_color ();
print_end ();*/
}
break;
case CODE_update_contact_link:
{
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_t *U = tgl_peer_get (user_id);
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Updated link with user ");
print_user_name (user_id, U);
printf ("\n");
pop_color ();
print_end ();*/
unsigned t = fetch_int ();
assert (t == CODE_contacts_my_link_empty || t == CODE_contacts_my_link_requested || t == CODE_contacts_my_link_contact);
if (t == CODE_contacts_my_link_requested) {
fetch_bool (); // has_phone
}
t = fetch_int ();
assert (t == CODE_contacts_foreign_link_unknown || t == CODE_contacts_foreign_link_requested || t == CODE_contacts_foreign_link_mutual);
if (t == CODE_contacts_foreign_link_requested) {
fetch_bool (); // has_phone
}
if (U) {}
}
break;
case CODE_update_activation:
{
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_t *U = tgl_peer_get (user_id);
if (tgl_state.callback.user_activated && U) {
tgl_state.callback.user_activated ((void *)U);
}
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" User ");
print_user_name (user_id, U);
printf (" activated\n");
pop_color ();
print_end ();*/
}
break;
case CODE_update_new_authorization:
{
fetch_long (); // auth_key_id
fetch_int (); // date
char *s = fetch_str_dup ();
char *location = fetch_str_dup ();
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" New autorization: device='%s' location='%s'\n",
s, location);
pop_color ();
print_end ();*/
if (tgl_state.callback.new_authorization) {
tgl_state.callback.new_authorization (s, location);
}
tfree_str (s);
tfree_str (location);
}
break;
case CODE_update_new_geo_chat_message:
{
struct tgl_message *M = tglf_fetch_alloc_geo_message ();
assert (M);
//if (tgl_state.callback.new_msg) {
// tgl_state.callback.new_msg (M);
//}
//unread_messages ++;
//print_message (M);
//update_prompt ();
}
break;
case CODE_update_new_encrypted_message:
{
struct tgl_message *M = tglf_fetch_alloc_encrypted_message ();
assert (M);
//unread_messages ++;
//print_message (M);
//update_prompt ();
tglu_fetch_qts ();
//if (tgl_state.callback.new_msg) {
// tgl_state.callback.new_msg (M);
//}
}
break;
case CODE_update_encryption:
{
struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat ();
vlogprintf (E_DEBUG, "Secret chat state = %d\n", E->state);
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
switch (E->state) {
case sc_none:
break;
case sc_waiting:
printf (" Encrypted chat ");
print_encr_chat_name (E->id, (void *)E);
printf (" is now in wait state\n");
break;
case sc_request:
printf (" Encrypted chat ");
print_encr_chat_name (E->id, (void *)E);
printf (" is now in request state. Sending request ok\n");
break;
case sc_ok:
printf (" Encrypted chat ");
print_encr_chat_name (E->id, (void *)E);
printf (" is now in ok state\n");
break;
case sc_deleted:
printf (" Encrypted chat ");
print_encr_chat_name (E->id, (void *)E);
printf (" is now in deleted state\n");
break;
}
pop_color ();
print_end ();*/
if (E->state == sc_request) {
if (tgl_state.callback.secret_chat_request) {
tgl_state.callback.secret_chat_request (E);
}
} else if (E->state == sc_ok) {
if (tgl_state.callback.secret_chat_established) {
tgl_state.callback.secret_chat_established (E);
}
} else if (E->state == sc_deleted) {
if (tgl_state.callback.secret_chat_deleted) {
tgl_state.callback.secret_chat_deleted (E);
}
}
if (E->state == sc_ok) {
tgl_do_send_encr_chat_layer (E);
}
fetch_int (); // date
}
break;
case CODE_update_encrypted_chat_typing:
{
tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ());
tgl_peer_t *P = tgl_peer_get (id);
if (P) {
if (tgl_state.callback.type_in_secret_chat_notification) {
tgl_state.callback.type_in_secret_chat_notification ((void *)P);
}
}
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
if (P) {
printf (" User ");
tgl_peer_id_t user_id = TGL_MK_USER (P->encr_chat.user_id);
print_user_name (user_id, tgl_peer_get (user_id));
printf (" typing in secret chat ");
print_encr_chat_name (id, P);
printf ("\n");
} else {
printf (" Some user is typing in unknown secret chat\n");
}
pop_color ();
print_end ();*/
}
break;
case CODE_update_encrypted_messages_read:
{
tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); // chat_id
fetch_int (); // max_date
fetch_int (); // date
tgl_peer_t *P = tgl_peer_get (id);
//int x = -1;
if (P && P->last) {
//x = 0;
struct tgl_message *M = P->last;
while (M && (!M->out || M->unread)) {
if (M->out) {
bl_do_set_unread (M, 0);
}
M = M->next;
}
}
/*if (log_level >= 1) {
print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Encrypted chat ");
print_encr_chat_name_full (id, tgl_peer_get (id));
printf (": %d messages marked read \n", x);
pop_color ();
print_end ();
}*/
}
break;
case CODE_update_chat_participant_add:
{
tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ());
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
tgl_peer_id_t inviter_id = TGL_MK_USER (fetch_int ());
int version = fetch_int ();
tgl_peer_t *C = tgl_peer_get (chat_id);
if (C && (C->flags & FLAG_CREATED)) {
bl_do_chat_add_user (&C->chat, version, tgl_get_peer_id (user_id), tgl_get_peer_id (inviter_id), time (0));
}
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Chat ");
print_chat_name (chat_id, tgl_peer_get (chat_id));
printf (": user ");
print_user_name (user_id, tgl_peer_get (user_id));
printf (" added by user ");
print_user_name (inviter_id, tgl_peer_get (inviter_id));
printf ("\n");
pop_color ();
print_end ();*/
}
break;
case CODE_update_chat_participant_delete:
{
tgl_peer_id_t chat_id = TGL_MK_CHAT (fetch_int ());
tgl_peer_id_t user_id = TGL_MK_USER (fetch_int ());
int version = fetch_int ();
tgl_peer_t *C = tgl_peer_get (chat_id);
if (C && (C->flags & FLAG_CREATED)) {
bl_do_chat_del_user (&C->chat, version, tgl_get_peer_id (user_id));
}
/*print_start ();
push_color (COLOR_YELLOW);
print_date (time (0));
printf (" Chat ");
print_chat_name (chat_id, tgl_peer_get (chat_id));
printf (": user ");
print_user_name (user_id, tgl_peer_get (user_id));
printf (" deleted\n");
pop_color ();
print_end ();*/
}
break;
case CODE_update_dc_options:
{
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
assert (n >= 0);
int i;
for (i = 0; i < n; i++) {
fetch_dc_option ();
}
}
break;
case CODE_update_user_blocked:
{
int id = fetch_int ();
int blocked = fetch_bool ();
tgl_peer_t *P = tgl_peer_get (TGL_MK_USER (id));
if (P && (P->flags & FLAG_CREATED)) {
bl_do_user_set_blocked (&P->user, blocked);
}
}
break;
case CODE_update_notify_settings:
{
assert (skip_type_any (TYPE_TO_PARAM (notify_peer)) >= 0);
assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0);
}
break;
default:
vlogprintf (E_ERROR, "Unknown update type %08x\n", op);
;
}
}
void tglu_work_update_short (struct connection *c, long long msg_id) {
int *save = in_ptr;
assert (!skip_type_any (TYPE_TO_PARAM (updates)));
int *save_end = in_ptr;
in_ptr = save;
assert (fetch_int () == CODE_update_short);
tglu_work_update (c, msg_id);
tglu_fetch_date ();
assert (save_end == in_ptr);
}
void tglu_work_updates (struct connection *c, long long msg_id) {
int *save = in_ptr;
assert (!skip_type_any (TYPE_TO_PARAM (updates)));
int *save_end = in_ptr;
in_ptr = save;
assert (fetch_int () == CODE_updates);
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
int i;
for (i = 0; i < n; i++) {
tglu_work_update (c, msg_id);
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
tglf_fetch_alloc_user ();
}
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
tglf_fetch_alloc_chat ();
}
bl_do_set_date (fetch_int ());
bl_do_set_seq (fetch_int ());
assert (save_end == in_ptr);
}
void tglu_work_update_short_message (struct connection *c, long long msg_id) {
int *save = in_ptr;
assert (!skip_type_any (TYPE_TO_PARAM (updates)));
int *save_end = in_ptr;
in_ptr = save;
assert (fetch_int () == (int)CODE_update_short_message);
struct tgl_message *M = tglf_fetch_alloc_message_short ();
assert (M);
/*unread_messages ++;
print_message (M);
update_prompt ();
if (M->date > last_date) {
last_date = M->date;
}*/
assert (save_end == in_ptr);
}
void tglu_work_update_short_chat_message (struct connection *c, long long msg_id) {
int *save = in_ptr;
assert (!skip_type_any (TYPE_TO_PARAM (updates)));
int *save_end = in_ptr;
in_ptr = save;
assert (fetch_int () == CODE_update_short_chat_message);
struct tgl_message *M = tglf_fetch_alloc_message_short_chat ();
assert (M);
/*unread_messages ++;
print_message (M);
update_prompt ();
if (M->date > last_date) {
last_date = M->date;
}*/
assert (save_end == in_ptr);
}
void tglu_work_updates_to_long (struct connection *c, long long msg_id) {
assert (fetch_int () == (int)CODE_updates_too_long);
vlogprintf (E_NOTICE, "updates to long... Getting difference\n");
tgl_do_get_difference (0, 0, 0);
}

15
updates.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef __UPDATES_H__
#define __UPDATES_H__
struct connection;
void tglu_work_update (struct connection *c, long long msg_id);
void tglu_work_updates_to_long (struct connection *c, long long msg_id);
void tglu_work_update_short_chat_message (struct connection *c, long long msg_id);
void tglu_work_update_short_message (struct connection *c, long long msg_id);
void tglu_work_update_short (struct connection *c, long long msg_id);
void tglu_work_updates (struct connection *c, long long msg_id);
void tglu_fetch_pts (void);
void tglu_fetch_qts (void);
void tglu_fetch_seq (void);
void tglu_fetch_date (void);
#endif