Refactor - Intermediate Commit 2

This commit is contained in:
mjentsch 2014-07-29 15:28:04 +02:00
parent ed7aa7de5b
commit 8a2c043db4
18 changed files with 388 additions and 222 deletions

View file

@ -53,6 +53,7 @@ PRPL_CFLAGS = \
-fPIC \
-DPURPLE_PLUGINS \
-DPIC \
-DDEBUG \
-g \
$(CFLAGS_PURPLE)
@ -84,10 +85,6 @@ plugin: $(PRPL_LIBNAME)
strip: $(PRPL_LIBNAME)
$(STRIP) --strip-unneeded $(PRPL_LIBNAME)
debug: PRPL_CFLAGS += -g -DDEBUG
debug: $(PRPL_LIBNAME)
gdb -tui -ex 'break telegram-purple.c:tgprpl_login' pidgin
# TODO: Find a better place for server.pub
install: $(PRPL_LIBNAME)
install -D $(PRPL_LIBNAME) $(DESTDIR)$(PLUGIN_DIR_PURPLE)/$(PRPL_LIBNAME)
@ -108,6 +105,10 @@ uninstall: $(PRPL_LIBNAME)
run: install
pidgin -d | grep 'telegram\|plugin\|proxy'
.PHONY: debug
debug: install
gdb -tui -ex "$(shell echo $$GDB_BPOINTS )" pidgin
clean:
rm -rf *.so *.a *.o telegram config.log config.status $(PRPL_C_OBJS) $(PRPL_LIBNAME) > /dev/null || echo "all clean"

View file

@ -56,7 +56,13 @@ extern int seq;
#define MAX_LOG_EVENT_SIZE (1 << 17)
// TODO: remove this completely
char *get_binlog_file_name (void);
char *get_binlog_file_name()
{
return "/home/dev-jessie/.telegram/binlog";
}
//extern struct dc *DC_list[];
//extern int dc_working_num;
extern int our_id;
@ -1162,9 +1168,9 @@ void write_binlog (void) {
}
void add_log_event (const int *data, int len) {
if (verbosity) {
logprintf ("Add log event: magic = 0x%08x, len = %d\n", data[0], len);
}
logprintf ("Add log event: magic = 0x%08x, len = %d\n", data[0], len);
assert(0);
// TODO: Mit add_log_event_i austauschen
assert (!(len & 3));
if (in_replay_log) { return; }
rptr = (void *)data;
@ -1185,7 +1191,29 @@ void add_log_event (const int *data, int len) {
in_end = end;
}
void bl_do_set_auth_key_id (int num, unsigned char *buf) {
void add_log_event_i (struct telegram *instance, const int *data, int len) {
logprintf ("Add log event: magic = 0x%08x, len = %d\n", data[0], len);
assert (!(len & 3));
if (in_replay_log) { return; }
rptr = (void *)data;
wptr = rptr + (len / 4);
int *in = in_ptr;
int *end = in_end;
// TODO:
replay_log_event (instance);
if (rptr != wptr) {
logprintf ("Unread %lld ints. Len = %d\n", (long long)(wptr - rptr), len);
assert (rptr == wptr);
}
if (binlog_enabled) {
assert (binlog_fd > 0);
assert (write (binlog_fd, data, len) == len);
}
in_ptr = in;
in_end = end;
}
void bl_do_set_auth_key_id (struct telegram *instance, int num, unsigned char *buf) {
static unsigned char sha1_buffer[20];
SHA1 (buf, 256, sha1_buffer);
long long fingerprint = *(long long *)(sha1_buffer + 12);
@ -1194,7 +1222,7 @@ void bl_do_set_auth_key_id (int num, unsigned char *buf) {
ev[1] = num;
*(long long *)(ev + 2) = fingerprint;
memcpy (ev + 4, buf, 256);
add_log_event (ev, 8 + 8 + 256);
add_log_event_i (instance, ev, 8 + 8 + 256);
}
void bl_do_set_our_id (int id) {

View file

@ -87,8 +87,9 @@
void *alloc_log_event (int l);
void replay_log (struct telegram *instance);
void add_log_event (const int *data, int l);
void add_log_event_i (struct telegram *instance, const int *data, int l);
void write_binlog (void);
void bl_do_set_auth_key_id (int num, unsigned char *buf);
void bl_do_set_auth_key_id (struct telegram *instance, int num, unsigned char *buf);
void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port, struct telegram *instance);

101
loop.c
View file

@ -148,6 +148,7 @@ int is_got_it (void) {
return got_it_ok;
}
/*
int net_getline (char **s, size_t *l) {
fflush (stdout);
// rl_already_prompted = 1;
@ -155,16 +156,19 @@ int net_getline (char **s, size_t *l) {
_s = s;
_l = l;
// rl_callback_handler_install (0, got_it);
net_loop (2, is_got_it);
//net_loop (2, is_got_it);
return 0;
}
*/
int ret1 (void) { return 0; }
/*
int main_loop (void) {
net_loop (1, ret1);
return 0;
}
*/
//struct dc *DC_list[MAX_DC_ID + 1];
@ -177,6 +181,7 @@ int zero[512];
void write_dc (int auth_file_fd, struct dc *DC) {
logprintf("writing to auth_file: auth_file_fd: %d, port: %d, ip: %s\n", auth_file_fd, DC->port, DC->ip);
assert (write (auth_file_fd, &DC->port, 4) == 4);
int l = strlen (DC->ip);
assert (write (auth_file_fd, &l, 4) == 4);
@ -194,28 +199,28 @@ void write_dc (int auth_file_fd, struct dc *DC) {
int our_id;
void write_auth_file (struct authorization_state state, const char *filename) {
if (binlog_enabled) { return; }
int auth_file_fd = open (filename /*get_auth_key_filename ()*/, O_CREAT | O_RDWR, 0600);
void write_auth_file (struct authorization_state *state, const char *filename) {
logprintf("Writing to auth_file: %s\n", filename);
int auth_file_fd = open (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, &state.dc_working_num, 4) == 4);
assert (write (auth_file_fd, &state.auth_state, 4) == 4);
assert (write (auth_file_fd, &state->dc_working_num, 4) == 4);
assert (write (auth_file_fd, &state->auth_state, 4) == 4);
int i;
for (i = 0; i <= MAX_DC_ID; i++) {
if (state.DC_list[i]) {
if (state->DC_list[i]) {
x = 1;
assert (write (auth_file_fd, &x, 4) == 4);
write_dc (auth_file_fd, state.DC_list[i]);
write_dc (auth_file_fd, state->DC_list[i]);
} else {
x = 0;
assert (write (auth_file_fd, &x, 4) == 4);
}
}
assert (write (auth_file_fd, &state.our_id, 4) == 4);
assert (write (auth_file_fd, &state->our_id, 4) == 4);
close (auth_file_fd);
}
@ -232,9 +237,6 @@ void read_dc (int auth_file_fd, int id, unsigned ver, struct dc *DC_list[]) {
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);
logprintf("auth_key_id: %lli \n", DC->auth_key_id);
logprintf("auth_key_id: ?");
logprintf("server_salt: %lli \n", DC->server_salt);
if (DC->auth_key_id) {
DC->flags |= 1;
}
@ -247,23 +249,33 @@ void read_dc (int auth_file_fd, int id, unsigned ver, struct dc *DC_list[]) {
void empty_auth_file (struct authorization_state *state, const char *filename) {
logprintf("empty_auth_file()\n");
alloc_dc (state->DC_list, 1, tstrdup (test_dc ? TG_SERVER_TEST : TG_SERVER), 443);
state->dc_working_num = 1;
state->auth_state = 0;
write_auth_file (*state, filename);
write_auth_file (state, filename);
}
/**
* Read the auth-file and return the read authorization state
*
* When the given file doesn't exist, create a new empty
* file containing the default authorization state at this
* path
*/
struct authorization_state read_auth_file (const char *filename) {
struct authorization_state state;
state.dc_working_num = 0;
state.auth_state = 0;
state.our_id = 0;
logprintf("read_auth_file()\n");
if (binlog_enabled) { return state; }
int auth_file_fd = open (filename /*get_auth_key_filename ()*/, O_CREAT | O_RDWR, 0600);
struct authorization_state state;
memset(state.DC_list, 0, 11 * sizeof(void *));
int auth_file_fd = open (filename, O_RDWR, 0600);
logprintf("fd: %d\n", auth_file_fd);
if (auth_file_fd < 0) {
logprintf("auth_file does not exist, creating empty...\n");
empty_auth_file (&state, filename);
}
auth_file_fd = open (filename, O_RDWR, 0600);
assert (auth_file_fd >= 0);
// amount of data centers
@ -271,6 +283,7 @@ struct authorization_state read_auth_file (const char *filename) {
// magic number of file
unsigned m;
if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC && m != DC_SERIALIZED_MAGIC_V2)) {
logprintf("Invalid File content, wrong Magic numebr\n");
close (auth_file_fd);
empty_auth_file (&state, filename);
return state;
@ -288,6 +301,10 @@ struct authorization_state read_auth_file (const char *filename) {
assert (read (auth_file_fd, &y, 4) == 4);
if (y) {
read_dc (auth_file_fd, i, m, state.DC_list);
logprintf("loaded dc[%d] - port: %d, ip: %s, auth_key_id: %lli, server_salt: %lli, has_auth: %d\n",
i, state.DC_list[i]->port, state.DC_list[i]->ip, state.DC_list[i]->auth_key_id, state.DC_list[i]->server_salt, state.DC_list[i]->has_auth);
} else {
logprintf("loaded dc[%d] - NULL\n", i);
}
}
int l = read (auth_file_fd, &state.our_id, 4);
@ -299,20 +316,17 @@ struct authorization_state read_auth_file (const char *filename) {
if (m == DC_SERIALIZED_MAGIC) {
DC_working->has_auth = 1;
}
logprintf("loaded authorization state - our_id: %d, auth_state: %d, dc_working_num: %d \n", state.our_id, state.auth_state, state.dc_working_num);
return state;
}
int pts, qts, seq, last_date;
struct protocol_state read_state_file (const char *filename) {
struct protocol_state state;
state.last_date = 0;
state.qts = 0;
state.pts = 0;
state.seq = 0;
logprintf("read_state_file()\n");
struct protocol_state state = {0, 0, 0, 0};
if (binlog_enabled) { return state; }
int state_file_fd = open (filename/*get_state_filename ()*/, O_CREAT | O_RDWR, 0600);
int state_file_fd = open (filename, O_CREAT | O_RDWR, 0600);
if (state_file_fd < 0) {
return state;
}
@ -331,11 +345,12 @@ struct protocol_state read_state_file (const char *filename) {
state.seq = x[2];
state.last_date = x[3];
close (state_file_fd);
logprintf("loaded session state - pts: %d, qts: %d, seq: %d, last_date: %d.\n", state.pts,
state.qts, state.seq, state.last_date);
return state;
}
void write_state_file (struct protocol_state state, const char* filename) {
if (binlog_enabled) { return; }
void write_state_file (struct protocol_state *state, const char* filename) {
/*
static int wseq;
static int wpts;
@ -350,10 +365,10 @@ void write_state_file (struct protocol_state state, const char* filename) {
int x[6];
x[0] = STATE_FILE_MAGIC;
x[1] = 0;
x[2] = state.pts;
x[3] = state.qts;
x[4] = state.seq;
x[5] = state.last_date;
x[2] = state->pts;
x[3] = state->qts;
x[4] = state->seq;
x[5] = state->last_date;
assert (write (state_file_fd, x, 24) == 24);
close (state_file_fd);
//wseq = seq; wpts = pts; wqts = qts; wdate = last_date;
@ -569,32 +584,10 @@ int network_verify_phone_registration(const char* code, const char *sms_hash,
{
logprintf("Registering with code:%s, hash:%s, first:%s, last:%s\n", code, sms_hash,
first, last);
if (do_send_code_result_auth (code, sms_hash, first, last) >= 0) {
logprintf ("Authentication successfull, state = 300\n");
auth_state = 300;
return 1;
}
return 0;
}
*/
/**
* Verify the current client by providing the given code
*/
/*
int network_verify_registration(const char *code, const char *sms_hash)
{
logprintf("Verifying with hash:%s, code:%s\n", code, sms_hash);
int state;
if ((state = do_send_code_result (code, sms_hash)) >= 0) {
logprintf ("Authentication successfull, state = 300\n");
auth_state = 300;
return 1;
}
return 0;
}
*/
/**
* Export current authentication state to all known data centers.
*/

7
loop.h
View file

@ -24,7 +24,6 @@
#ifndef __LOOP_H__
#define __LOOP_H__
int loop();
void net_loop (int flags, int (*end)(void));
void write_secret_chat_file (const char *filename);
#endif
@ -38,14 +37,14 @@ struct protocol_state {
struct authorization_state {
int dc_working_num;
int auth_state;
struct dc *DC_list[11];
struct dc* DC_list[11];
int our_id;
};
void write_auth_file (struct authorization_state state, const char *filename);
void write_auth_file (struct authorization_state *state, const char *filename);
struct authorization_state read_auth_file (const char *filename);
void write_state_file (struct protocol_state state, const char *filename);
void write_state_file (struct protocol_state *state, const char *filename);
struct protocol_state read_state_file (const char *filename);
void on_start();

View file

@ -85,6 +85,8 @@ int allow_weak_random = 0;
int total_packets_sent;
long long total_data_sent;
extern int queries_num;
/*
int rpc_execute (struct connection *c, int op, int len);
int rpc_becomes_ready (struct connection *c);
@ -224,6 +226,8 @@ int rpc_send_packet (struct connection *c) {
//flush_out (c);
total_packets_sent ++;
queries_num++;
logprintf("pending queries: %d\n", queries_num);
total_data_sent += total_len;
return 1;
}
@ -248,6 +252,9 @@ int rpc_send_message (struct connection *c, void *data, int len) {
}
int send_req_pq_packet (struct connection *c) {
char byte = 0xef;
assert (write_out (c, &byte, 1) == 1);
assert (c_state == st_init);
secure_random (nonce, 16);
unenc_msg_header.out_msg_id = 0;
@ -255,6 +262,7 @@ int send_req_pq_packet (struct connection *c) {
out_int (CODE_req_pq);
out_ints ((int *)nonce, 4);
rpc_send_packet (c);
c_state = st_reqpq_sent;
return 1;
}
@ -539,9 +547,7 @@ int check_g_bn (BIGNUM *p, BIGNUM *g) {
}
int process_dh_answer (struct connection *c, char *packet, int len) {
if (verbosity) {
logprintf ( "process_dh_answer(), len=%d\n", len);
}
logprintf ( "process_dh_answer(), len=%d\n", len);
if (len < 116) {
logprintf ( "%u * %u = %llu", p1, p2, what);
}
@ -633,15 +639,13 @@ int process_dh_answer (struct connection *c, char *packet, int len) {
out_cstring ((char *) encrypt_buffer, l);
c_state = st_client_dh_sent;
return rpc_send_packet (c);
}
int process_auth_complete (struct connection *c UU, char *packet, int len) {
if (verbosity) {
logprintf ( "process_dh_answer(), len=%d\n", len);
}
logprintf ( "process_dh_answer(), len=%d\n", len);
assert (len == 72);
assert (!*(long long *) packet);
assert (*(int *) (packet + 16) == len - 20);
@ -654,7 +658,8 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
tmp[32] = 1;
//GET_DC(c)->auth_key_id = *(long long *)(sha1_buffer + 12);
bl_do_set_auth_key_id (GET_DC(c)->id, (unsigned char *)GET_DC(c)->auth_key);
bl_do_set_auth_key_id (c->instance, GET_DC(c)->id, (unsigned char *)GET_DC(c)->auth_key);
sha1 ((unsigned char *)GET_DC(c)->auth_key, 256, sha1_buffer);
memcpy (tmp + 33, sha1_buffer, 8);
@ -662,9 +667,8 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
GET_DC(c)->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce;
if (verbosity >= 3) {
logprintf ( "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id);
}
logprintf ( "auth_key_id=%016llx\n", GET_DC(c)->auth_key_id);
//logprintf ( "auth_key=%s\n", GET_DC(c)->auth_key);
//kprintf ("OK\n");
//c->status = conn_error;
@ -672,9 +676,7 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) {
c_state = st_authorized;
//return 1;
if (verbosity) {
logprintf ( "Auth success\n");
}
logprintf ( "Auth success\n");
auth_success ++;
GET_DC(c)->flags |= 1;
@ -804,7 +806,7 @@ void fetch_pts (void) {
} else {
pts ++;
}
bl_do_set_pts (pts);
//bl_do_set_pts (pts);
}
void fetch_qts (void) {
@ -821,14 +823,14 @@ void fetch_qts (void) {
} else {
qts ++;
}
bl_do_set_qts (qts);
//bl_do_set_qts (qts);
}
void fetch_date (void) {
int p = fetch_int ();
if (p > last_date) {
last_date = p;
bl_do_set_date (last_date);
//bl_do_set_date (last_date);
}
}
@ -1252,9 +1254,7 @@ void work_update (struct connection *c UU, long long msg_id UU, struct telegram
case CODE_update_encryption:
{
struct secret_chat *E = fetch_alloc_encrypted_chat ();
if (verbosity >= 2) {
logprintf ("Secret chat state = %d\n", E->state);
}
logprintf ("Secret chat state = %d\n", E->state);
//print_start ();
//push_color (COLOR_YELLOW);
//print_date (time (0));
@ -1776,48 +1776,59 @@ int process_rpc_message (struct telegram *instance, struct encrypted_message *en
//}
int rpc_execute_req_pq (struct telegram *instance, int len) {
logprintf("rpc_execute_rq_dh()\n");
struct connection *c = telegram_get_connection(instance);
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
logprintf ( "answer too long (%d bytes), skipping\n", len);
queries_num--;
return 0;
}
int Response_len = len;
assert (read_in (c, Response, Response_len) == Response_len);
Response[Response_len] = 0;
process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/);
queries_num--;
return 0;
}
int rpc_execute_rq_dh (struct telegram *instance, int len) {
logprintf("rpc_execute_rq_dh()\n");
struct connection *c = telegram_get_connection(instance);
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
logprintf ( "answer too long (%d bytes), skipping\n", len);
queries_num--;
return 0;
}
int Response_len = len;
assert (read_in (c, Response, Response_len) == Response_len);
Response[Response_len] = 0;
process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/);
queries_num--;
return 0;
}
int rpc_execute_cdh_sent (struct telegram *instance, int len) {
logprintf("rpc_execute_cdh()\n");
struct connection *c = telegram_get_connection(instance);
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
logprintf ( "answer too long (%d bytes), skipping\n", len);
queries_num--;
return 0;
}
int Response_len = len;
assert (read_in (c, Response, Response_len) == Response_len);
Response[Response_len] = 0;
process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/);
queries_num--;
return 0;
}
int rpc_execute_authorized (struct telegram *instance, int op, int len) {
logprintf("rpc_execute_authorized()\n");
struct connection *c = telegram_get_connection(instance);
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
logprintf ( "answer too long (%d bytes), skipping\n", len);
queries_num--;
return 0;
}
int Response_len = len;
@ -1828,11 +1839,10 @@ int rpc_execute_authorized (struct telegram *instance, int op, int len) {
} else {
process_rpc_message (instance, (void *)(Response/* + 8*/), Response_len/* - 12*/);
}
queries_num--;
return 0;
}
int tc_close (struct connection *c, int who) {
if (verbosity) {
logprintf ( "outbound http connection #%d : closing by %d\n", c->fd, who);
@ -1900,11 +1910,13 @@ int auth_ok (void) {
return auth_success;
}
/*
void dc_authorize (struct dc *DC) {
c_state = 0;
auth_success = 0;
if (verbosity) {
logprintf ( "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port);
}
net_loop (0, auth_ok);
//net_loop (0, auth_ok);
}
*/

View file

@ -23,7 +23,7 @@
#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 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);
@ -32,7 +32,7 @@ int check_DH_params (BIGNUM *p, int g);
void secure_random (void *s, int l);
int send_req_pq_packet (struct telegram *instance);
int send_req_pq_packet (struct connection *c);
int rpc_execute_req_pq (struct telegram *instance, int len);
int rpc_execute_rq_dh (struct telegram *instance, int len);

View file

@ -20,6 +20,7 @@
#ifndef __MTPROTO_COMMON_H__
#define __MTPROTO_COMMON_H__
#include <assert.h>
#include <string.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>

57
net.c
View file

@ -113,10 +113,11 @@ void start_ping_timer (struct connection *c) {
insert_event_timer (&c->ev);
}
void restart_connection (struct connection *c);
int fail_alarm (void *ev) {
((struct connection *)ev)->in_fail_timer = 0;
restart_connection (ev);
struct connection *c = ev;
c->in_fail_timer = 0;
logprintf("Connection %d FAILED.", c->fd);
telegram_change_state(c->instance, STATE_ERROR, NULL);
return 0;
}
void start_fail_timer (struct connection *c) {
@ -251,13 +252,14 @@ void rotate_port (struct connection *c) {
}
}
struct connection *create_connection (const char *host, int port, int fd) {
struct connection *create_connection (const char *host, int port, int fd, struct telegram *instance) {
struct connection *c = talloc0 (sizeof (*c));
c->fd = fd;
c->ip = tstrdup (host);
c->flags = 0;
c->state = conn_ready;
c->port = port;
c->instance = instance;
if (verbosity) {
logprintf ( "connect to %s:%d successful\n", host, port);
}
@ -316,12 +318,11 @@ void restart_connection (struct connection *c) {
assert (write_out (c, &byte, 1) == 1);
flush_out (c);
}
*/
void fail_connection (struct connection *c) {
if (c->state == conn_ready || c->state == conn_connecting) {
stop_ping_timer (c);
}
rotate_port (c);
struct connection_buffer *b = c->out_head;
while (b) {
struct connection_buffer *d = b;
@ -338,18 +339,15 @@ void fail_connection (struct connection *c) {
c->state = conn_failed;
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);
restart_connection (c);
telegram_change_state(c->instance, STATE_ERROR, NULL);
}
*/
extern FILE *log_net_f;
void try_write (struct telegram *instance) {
int try_write (struct telegram *instance) {
struct connection *c = telegram_get_connection(instance);
if (verbosity) {
logprintf ( "try write: fd = %d\n", c->fd);
}
logprintf ("try write: fd = %d\n", c->fd);
int x = 0;
while (c->out_head) {
int r = netwrite (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
@ -359,7 +357,6 @@ void try_write (struct telegram *instance) {
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++) {
fprintf (log_net_f, " %02x", *(unsigned char *)(c->out_head->rptr + i));
}
fprintf (log_net_f, "\n");
@ -387,16 +384,15 @@ void try_write (struct telegram *instance) {
logprintf ("fail_connection: write_error %m\n");
}
fail_connection (c);
return;
return 0;
} else {
break;
}
}
}
if (verbosity) {
logprintf ( "Sent %d bytes to %d\n", x, c->fd);
}
logprintf ( "Sent %d bytes to %d\n", x, c->fd);
c->out_bytes -= x;
return x;
}
void hexdump_buf (struct connection_buffer *b) {
@ -423,6 +419,9 @@ void hexdump_buf (struct connection_buffer *b) {
}
/**
* Read all rpc responses from the current connection
*/
void try_rpc_read (struct telegram *instance) {
struct connection *c = instance->auth.DC_list[instance->auth.dc_working_num]->sessions[0]->c;
@ -467,10 +466,7 @@ void try_rpc_read (struct telegram *instance) {
void try_read (struct telegram *instance) {
struct connection *c = instance->auth.DC_list[instance->auth.dc_working_num]->sessions[0]->c;
if (verbosity) {
logprintf ( "try read: fd = %d\n", c->fd);
}
logprintf ( "try read: fd = %d\n", c->fd);
if (!c->in_tail) {
c->in_head = c->in_tail = new_connection_buffer (1 << 20);
}
@ -489,9 +485,11 @@ void try_read (struct telegram *instance) {
}
if (r > 0) {
c->last_receive_time = get_double_time ();
// TODO: Implement the Ping-Timer
// reset ping timer
stop_ping_timer (c);
start_ping_timer (c);
//stop_ping_timer (c);
//start_ping_timer (c);
}
if (r >= 0) {
// write pointer nach vorne setzen
@ -507,9 +505,7 @@ void try_read (struct telegram *instance) {
c->in_tail = b;
} else {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
if (verbosity) {
logprintf ("fail_connection: read_error %m\n");
}
logprintf ("fail_connection: read_error %m\n");
fail_connection (c);
return;
} else {
@ -517,9 +513,7 @@ void try_read (struct telegram *instance) {
}
}
}
if (verbosity) {
logprintf ( "Received %d bytes from %d\n", x, c->fd);
}
logprintf ( "Received %d bytes from %d\n", x, c->fd);
c->in_bytes += x;
if (x) {
try_rpc_read (instance);
@ -609,10 +603,7 @@ void insert_msg_id (struct session *S, long long id) {
}
}
extern struct dc *DC_list[];
struct dc *alloc_dc (struct dc* DC_list[], int id, char *ip, int port UU) {
assert (!DC_list[id]);
struct dc *DC = talloc0 (sizeof (*DC));
DC->id = id;
DC->ip = ip;

7
net.h
View file

@ -130,6 +130,7 @@ struct connection {
void *extra;
struct event_timer ev;
double last_receive_time;
struct telegram *instance;
};
extern struct connection *Connections[];
@ -140,7 +141,7 @@ int read_in (struct connection *c, void *data, int len);
void create_all_outbound_connections (void);
struct connection *create_connection (const char *host, int port, int fd);
struct connection *create_connection (const char *host, int port, int fd, struct telegram *instance);
int connections_make_poll_array (struct pollfd *fds, int max);
void connections_poll_result (struct pollfd *fds, int max);
void insert_msg_id (struct session *S, long long id);
@ -151,8 +152,8 @@ void dc_create_session (struct dc *DC, struct connection *c);
void try_read (struct telegram *instance);
void try_rpc_read (struct telegram *instance);
void try_write (struct telegram *instance);
int try_write (struct telegram *instance);
#define GET_DC(c) (c->session->dc)
#define GET_DC(c) (telegram_get_working_dc(c->instance))
#endif

View file

@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
// test
@ -42,6 +43,7 @@
#include "prpl.h"
#include "prefs.h"
#include "util.h"
#include "eventloop.h"
// struct telegram Includes
#include "telegram.h"
@ -105,7 +107,6 @@ static void tgprpl_tooltip_text(PurpleBuddy * buddy, PurpleNotifyUserInfo * info
/**
* Request a verification key, save the returned verification_hash in the account settings
* for later usage and inform the user.
*/
static void login_request_verification(PurpleAccount *acct)
{
// TODO: we should find a way to request the key
@ -119,6 +120,7 @@ static void login_request_verification(PurpleAccount *acct)
"You need to verify this device, please enter the code struct telegram has sent to you by SMS.",
NULL, NULL, NULL);
}
*/
/**
* Handle a failed verification, by removing the invalid sms code and
@ -135,25 +137,52 @@ static void login_verification_fail(PurpleAccount *acct)
static void tgprpl_output_cb(gpointer data, gint source, PurpleInputCondition cond)
{
logprintf("tgprpl_output_cb()\n");
PurpleConnection *c = data;
telegram_conn *conn = purple_connection_get_protocol_data(c);
telegram_write_output(conn->tg);
struct telegram *tg = data;
telegram_conn *conn = tg->extra;
int written = telegram_write_output(tg);
logprintf("written(%d): %d.\n", telegram_get_connection(tg)->fd, written);
if (written == 0) {
logprintf("no output, removing output...\n");
purple_input_remove(conn->wh);
conn->wh = 0;
}
}
static void tgprpl_has_output(struct telegram *tg)
{
logprintf("tgprpl_has_output()\n");
telegram_conn *conn = tg->extra;
if (! conn->wh) {
conn->wh = purple_input_add(telegram_get_connection(tg)->fd, PURPLE_INPUT_WRITE,
tgprpl_output_cb, tg);
logprintf("Attached write handle: %u ", conn->wh);
}
}
static void tgprpl_input_cb(gpointer data, gint source, PurpleInputCondition cond)
{
struct telegram *tg = data;
//telegram_conn *conn = tg->extra;
logprintf("tgprpl_input_cb()\n");
PurpleConnection *c = data;
telegram_conn *conn = purple_connection_get_protocol_data(c);
telegram_read_input(conn->tg);
// TODO: remove input handler when no more input
telegram_read_input(tg);
if (telegram_has_output(tg)) {
tgprpl_has_output(tg);
}
}
/*
static void tgprpl_on_input(struct telegram *tg)
static void tgprpl_has_input(struct telegram *tg)
{
PurpleConnection *c = data;
logprintf("tgprpl_has_input()\n");
telegram_conn *conn = tg->extra;
if (! conn->rh) {
conn->rh = purple_input_add(telegram_get_connection(tg)->fd, PURPLE_INPUT_READ,
tgprpl_input_cb, tg);
logprintf("Attached read handle: %u ", conn->rh);
}
}
*/
static void tgprpl_on_state_change(struct telegram *instance, int state, void *data)
{
@ -175,7 +204,8 @@ static void tgprpl_on_state_change(struct telegram *instance, int state, void *d
NULL, NULL, NULL);
return;
}
network_verify_phone_registration(code, hash, first_name, last_name);
do_send_code_result_auth (instance, code, hash, first_name, last_name);
break;
case STATE_PHONE_CODE_NOT_ENTERED:
@ -190,7 +220,7 @@ static void tgprpl_on_state_change(struct telegram *instance, int state, void *d
case STATE_CLIENT_CODE_NOT_ENTERED: {
const char *code = purple_account_get_string(conn->pa, "verification_key", NULL);
const char *hash = purple_account_get_string(conn->pa, "verification_hash", NULL);
network_verify_registration(code, hash);
do_send_code_result(instance, code, hash);
// enter SMS code
}
break;
@ -270,14 +300,13 @@ static void tgprpl_login(PurpleAccount * acct)
purple_connection_set_state(gc, PURPLE_CONNECTING);
purple_proxy_connect(gc, acct, DC.ip, DC.port, tgprpl_login_on_connected, tg);
purple_debug_info(PLUGIN_ID, "username: %s\n", username);
purple_debug_info(PLUGIN_ID, "hostname: %s\n", DC.ip);
}
void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_message)
{
purple_debug_info(PLUGIN_ID, "tgprpl_login_on_connected()\n");
struct telegram *tg = (struct telegram*) data;
telegram_conn *conn = tg->extra;
//running_for_first_time();
if (fd == -1) {
@ -286,9 +315,10 @@ void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_messa
return;
}
purple_debug_info(PLUGIN_ID, "Connecting to the struct telegram network...\n");
purple_input_add(fd, PURPLE_INPUT_WRITE, tgprpl_output_cb, telegram_get_connection(tg));
purple_input_add(fd, PURPLE_INPUT_READ, tgprpl_input_cb, telegram_get_connection(tg));
purple_debug_info(PLUGIN_ID, "Connecting to the telegram network...\n");
conn->wh = purple_input_add(fd, PURPLE_INPUT_WRITE, tgprpl_output_cb, tg);
conn->rh = purple_input_add(fd, PURPLE_INPUT_READ, tgprpl_input_cb, tg);
telegram_network_connect(tg, fd);
// // load all settings: the known network topology, secret keys, logs and configuration file paths
@ -896,10 +926,10 @@ static PurplePluginInfo info = {
NULL,
PURPLE_PRIORITY_DEFAULT,
PLUGIN_ID,
"struct telegram",
"Telegram",
"0.1",
"struct telegram integration.",
"Adds support for the struct telegram protocol to libpurple.",
"Telegram protocol",
"Adds support for the telegram protocol to libpurple.",
"Christopher Althaus <althaus.christopher@gmail.com>, Markus Endres <endresma45241@th-nuernberg.de>, Matthias Jentsch <mtthsjntsch@gmail.com>",
"https://bitbucket.org/telegrampurple/telegram-purple",
NULL, // on load

View file

@ -39,4 +39,14 @@ typedef struct {
struct telegram *tg;
PurpleAccount *pa;
PurpleConnection *gc;
/**
* Write handler returned by purple_input_add
*/
guint wh;
/**
* Read handler returned by purple_input_add
*/
guint rh;
} telegram_conn;

View file

@ -196,14 +196,10 @@ void query_error (long long id) {
int error_code = fetch_int ();
int error_len = prefetch_strlen ();
char *error = fetch_str (error_len);
if (verbosity) {
logprintf ( "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
}
logprintf ( "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
struct query *q = query_get (id);
if (!q) {
if (verbosity) {
logprintf ( "No such query\n");
}
logprintf ( "No such query\n");
} else {
if (!(q->flags & QUERY_ACK_RECEIVED)) {
remove_event_timer (&q->ev);
@ -281,16 +277,12 @@ DEFINE_TREE (timer, struct event_timer *, event_timer_cmp, 0)
struct tree_timer *timer_tree;
void insert_event_timer (struct event_timer *ev) {
if (verbosity > 2) {
logprintf ( "INSERT: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
}
logprintf ( "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) {
if (verbosity > 2) {
logprintf ( "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
}
logprintf ( "REMOVE: %lf %p %p\n", ev->timeout, ev->self, ev->alarm);
timer_tree = tree_delete_timer (timer_tree, ev);
}
@ -641,14 +633,14 @@ struct query_methods nearest_dc_methods = {
.on_error = fail_on_error
};
int do_get_nearest_dc (struct telegram *instance) {
void do_get_nearest_dc (struct telegram *instance) {
struct dc *DC_working = telegram_get_working_dc(instance);
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);
net_loop (0, nr_f);
return nearest_dc_num;
//net_loop (0, nr_f);
//return nearest_dc_num;
}
/* }}} */
@ -702,7 +694,7 @@ struct query_methods sign_in_methods = {
.on_error = sign_in_on_error
};
int do_send_code_result (struct telegram *instance, const char *code, const char *sms_hash) {
void do_send_code_result (struct telegram *instance, const char *code, const char *sms_hash) {
struct dc *DC_working = telegram_get_working_dc(instance);
clear_packet ();
out_int (CODE_auth_sign_in);
@ -710,12 +702,14 @@ int do_send_code_result (struct telegram *instance, const char *code, const char
out_string(sms_hash);
out_string (code);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, instance);
/*
sign_in_ok = 0;
net_loop (0, sign_in_is_ok);
//net_loop (0, sign_in_is_ok);
return sign_in_ok;
*/
}
int do_send_code_result_auth (struct telegram *instance, const char *code, const char *sms_hash, const char *first_name, const char *last_name) {
void do_send_code_result_auth (struct telegram *instance, const char *code, const char *sms_hash, const char *first_name, const char *last_name) {
struct dc *DC_working = telegram_get_working_dc(instance);
clear_packet ();
out_int (CODE_auth_sign_up);
@ -725,9 +719,11 @@ int do_send_code_result_auth (struct telegram *instance, const char *code, const
out_string (first_name);
out_string (last_name);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, instance);
/*
sign_in_ok = 0;
net_loop (0, sign_in_is_ok);
return sign_in_ok;
*/
}
/* }}} */
@ -1987,9 +1983,9 @@ void load_next_part (struct telegram *instance, struct download *D) {
static char buf[PATH_MAX];
int l;
if (!D->id) {
l = tsnprintf (buf, sizeof (buf), "%s/download_%lld_%d", get_downloads_directory (), D->volume, D->local_id);
l = tsnprintf (buf, sizeof (buf), "%s/download_%lld_%d", instance->download_path, D->volume, D->local_id);
} else {
l = tsnprintf (buf, sizeof (buf), "%s/download_%lld", get_downloads_directory (), D->id);
l = tsnprintf (buf, sizeof (buf), "%s/download_%lld", instance->download_path, D->id);
}
if (l >= (int) sizeof (buf)) {
logprintf ("Download filename is too long");
@ -2195,7 +2191,6 @@ void do_export_auth (struct telegram *instance, int num) {
out_int (CODE_auth_export_authorization);
out_int (num);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, 0);
net_loop (0, is_export_auth_str);
}
/* }}} */
@ -2220,7 +2215,6 @@ void do_import_auth (struct telegram *instance, int num) {
out_int (our_id);
out_cstring (export_auth_str, export_auth_str_len);
send_query (instance->auth.DC_list[num], packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0);
net_loop (0, isn_export_auth_str);
}
/* }}} */

View file

@ -69,7 +69,7 @@ extern struct query_methods help_get_config_methods;
void do_send_code (struct telegram *instance, const char *user);
void do_phone_call (struct telegram *instance, const char *user);
int do_send_code_result (struct telegram *instance, const char *code, const char *sms_hash);
void do_send_code_result (struct telegram *instance, const char *code, const char *sms_hash);
double get_double_time (void);
void do_update_contact_list (struct telegram *instance);
@ -101,8 +101,8 @@ void do_load_document (struct telegram *instance, struct document *V, int next);
void do_load_document_thumb (struct telegram *instance, struct document *video, int next);
void do_help_get_config (struct telegram *instance);
int do_auth_check_phone (struct telegram *instance, const char *user);
int do_get_nearest_dc (struct telegram*);
int do_send_code_result_auth (struct telegram *instance, const char *code, const char *sms_hash, const char *first_name, const char *last_name);
void do_get_nearest_dc (struct telegram*);
void do_send_code_result_auth (struct telegram *instance, const char *code, const char *sms_hash, const char *first_name, const char *last_name);
void do_import_auth (struct telegram *instance, int num);
void do_export_auth (struct telegram *instance, int num);
void do_add_contact (struct telegram *instance, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force);
@ -127,3 +127,5 @@ void fetch_dc_option (struct telegram *instance);
#endif
const char *get_last_err();
int all_queries_done();

View file

@ -4,17 +4,15 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <assert.h>
#include "mtproto-common.h"
#include "telegram.h"
#include "msglog.h"
#include "glib.h"
#include "tools.h"
#include "mtproto-client.h"
/*
* Events
*/
/*
* New message received
*/
@ -55,7 +53,7 @@ void telegram_add_state_change_listener(struct telegram *instance, state_listene
}
void telegram_change_state(struct telegram *instance, int state, void *data)
{
logprintf("Changing struct telegram state %d\n", state);
logprintf("telegram connection state changed to: %d\n", state);
instance->session_state = state;
GList *curr = instance->change_state_listeners;
while ((curr = g_list_next(change_listeners)) != NULL) {
@ -65,22 +63,40 @@ void telegram_change_state(struct telegram *instance, int state, void *data)
struct telegram *telegram_new(struct dc *DC, const char* login, const char *config_path)
{
on_start ();
struct telegram *this = malloc(sizeof(struct telegram));
this->protocol_data = NULL;
this->curr_dc = 0;
this->auth.DC_list[0] = DC;
this->change_state_listeners = NULL;
this->config_path = config_path;
strcpy(this->login, malloc(strlen(login) + 1));
this->login = g_strdup(login);
this->config_path = g_strdup_printf("%s/%s", config_path, login);
this->download_path = telegram_get_config(this, "downloads");
this->auth_path = telegram_get_config(this, "auth");
this->state_path = telegram_get_config(this, "state");
this->secret_path = telegram_get_config(this, "secret");
logprintf("%s\n", this->login);
logprintf("%s\n", this->config_path);
logprintf("%s\n", this->download_path);
logprintf("%s\n", this->auth_path);
logprintf("%s\n", this->state_path);
telegram_change_state(this, STATE_INITIALISED, NULL);
return this;
}
void telegram_free(struct telegram *instance)
void telegram_free(struct telegram *this)
{
g_list_free(instance->change_state_listeners);
free(instance->login);
free(instance);
g_list_free(this->change_state_listeners);
g_free(this->login);
g_free(this->config_path);
g_free(this->download_path);
g_free(this->auth_path);
g_free(this->state_path);
g_free(this->secret_path);
free(this);
}
void assert_file_usable(const char *file)
@ -90,56 +106,80 @@ void assert_file_usable(const char *file)
void assure_file_exists(const char *dir, const char *file)
{
char f[256];
g_mkdir_with_parents(dir, 0700);
sprintf(f, "%s/%s", dir, file);
char *f = g_strdup_printf("%s/%s", dir, file);
close(open(f, O_RDWR | O_CREAT, S_IRUSR, S_IWUSR));
assert_file_usable(f);
g_free(f);
}
/**
* Get the currently used connection
*
* Will only work after telegram_connect has been called and the connection has
* not errored.
*/
struct connection *telegram_get_connection(struct telegram *instance)
{
struct dc *DC = instance->auth.DC_list[instance->auth.dc_working_num];
assert(instance->session_state != STATE_ERROR);
struct dc *DC = telegram_get_working_dc(instance);
assert(DC);
assert(DC->sessions[0]);
assert(DC->sessions[0]->c);
//logprintf("get_connection() -> fd: %d\n", DC->sessions[0]->c->fd);
return DC->sessions[0]->c;
}
/**
* Get the currently used DC
*
* Will only work after restore_session has been called and the data center configuration
* was properly loaded
*/
struct dc *telegram_get_working_dc(struct telegram *instance)
{
assert(instance->session_state != STATE_ERROR);
assert(instance->auth.DC_list);
assert(instance->auth.dc_working_num > 0);
struct dc *DC = instance->auth.DC_list[instance->auth.dc_working_num];
return DC;
}
/**
* Store the current session state to a file
*/
void telegram_restore_session(struct telegram *instance)
{
char file[256];
sprintf(file, "%s/%s/%s", instance->config_path, instance->login, "auth");
instance->auth = read_auth_file(file);
sprintf(file, "%s/%s/%s", instance->config_path, instance->login, "state");
instance->proto = read_state_file(file);
g_mkdir_with_parents(instance->config_path, 0700);
instance->auth = read_auth_file(instance->auth_path);
instance->proto = read_state_file(instance->state_path);
}
/**
* Load the current session state from a file
*/
void telegram_store_session(struct telegram *instance)
{
char file[256];
sprintf(file, "%s/%s", instance->config_path, instance->login);
assure_file_exists(file, "auth");
assure_file_exists(file, "state");
sprintf(file, "%s/%s/%s", instance->config_path, instance->login, "auth");
write_auth_file(instance->auth, file);
sprintf(file, "%s/%s/%s", instance->config_path, instance->login, "state");
write_state_file(instance->proto, file);
assure_file_exists(instance->config_path, "auth");
assure_file_exists(instance->config_path, "state");
write_auth_file(&instance->auth, instance->auth_path);
write_state_file(&instance->proto, instance->state_path);
}
void telegram_get_downloads_dir(struct telegram *instance)
char *telegram_get_config(struct telegram *instance, char *config)
{
return g_strdup_printf("%s/%s", instance->config_path, config);
}
void telegram_network_connect(struct telegram *instance, int fd)
{
on_start ();
logprintf("telegram_network_connect()\n");
if (!instance->auth.DC_list) {
logprintf("telegram_network_connect(): cannot connect, restore / initialise a session first.\n");
assert(0);
}
struct dc *DC_working = telegram_get_working_dc(instance);
// check whether authentication is needed
@ -147,14 +187,12 @@ void telegram_network_connect(struct telegram *instance, int fd)
logprintf("No working DC, authenticating.\n");
// init a new connection
struct connection *c = create_connection (DC_working->ip, DC_working->port, fd);
struct connection *c = create_connection (DC_working->ip, DC_working->port, fd, instance);
// init a new session with random session id
dc_create_session(DC_working, c);
// Request PQ
char byte = 0xef;
assert (write_out (c, &byte, 1) == 1);
send_req_pq_packet (instance);
send_req_pq_packet (c);
telegram_change_state(instance, STATE_PQ_REQUESTED, NULL);
} else {
logprintf("Already working session, setting state to connected.\n");
@ -175,11 +213,23 @@ void on_state_change(struct telegram *instance, int state, void *data)
case STATE_CONNECTED:
on_connected(instance);
break;
case STATE_ERROR: {
const char* err = data;
logprintf("Telegram errored: %s \n", err);
break;
}
break;
case STATE_AUTH_DONE:
logprintf("requesting configuration");
telegram_change_state(instance, STATE_CONFIG_REQUESTED, NULL);
do_help_get_config (instance);
break;
case STATE_CONFIG_REQUESTED:
logprintf("switch: config_requested\n");
telegram_store_session(instance);
break;
}
}
@ -191,31 +241,39 @@ void try_rpc_interpret(struct telegram *instance, int op, int len)
{
switch (instance->session_state) {
case STATE_PQ_REQUESTED:
logprintf("switch: pq_requested\n");
rpc_execute_req_pq(instance, len);
telegram_change_state(instance, STATE_DH_REQUESTED, NULL);
break;
case STATE_DH_REQUESTED:
logprintf("switch: dh_requested\n");
rpc_execute_rq_dh(instance, len);
telegram_change_state(instance, STATE_CDH_REQUESTED, NULL);
break;
case STATE_CDH_REQUESTED:
logprintf("switch: cdh_requested\n");
rpc_execute_cdh_sent(instance, len);
telegram_change_state(instance, STATE_AUTH_DONE, NULL);
break;
case STATE_AUTH_DONE:
logprintf("switch: auth_done\n");
rpc_execute_authorized(instance, op, len);
telegram_change_state(instance, STATE_CONFIG_REQUESTED, NULL);
do_help_get_config (instance);
break;
case STATE_CONFIG_REQUESTED:
// ?
telegram_store_session(instance);
break;
}
}
void telegram_read_input (struct telegram *instance)
{
try_read(instance);
return try_read(instance);
}
int telegram_write_output (struct telegram *instance)
{
return try_write(instance);
}
int telegram_has_output (struct telegram *instance)
{
return !all_queries_done();
}

View file

@ -70,8 +70,14 @@
struct telegram {
void *protocol_data;
int curr_dc;
char *login;
const char *config_path;
char *config_path;
char *download_path;
char *auth_path;
char *state_path;
char *secret_path;
int session_state;
/*
@ -81,6 +87,10 @@ struct telegram {
struct authorization_state auth;
GList *change_state_listeners;
/*
* Callbacks
*/
void (*on_output)(struct telegram *instance);
void *extra;
@ -89,13 +99,16 @@ struct telegram {
/**
* Constructor
*/
struct telegram *telegram_new(struct dc *DC, const char* login, const char* config_path);
struct telegram *telegram_new(struct dc *DC, const char* login,
const char* config_path);
/**
* Resume the session to
*/
void telegram_restore_session(struct telegram *instance);
char *telegram_get_config(struct telegram *instance, char *config);
/**
* Store
*/
@ -176,7 +189,12 @@ void telegram_read_input (struct telegram *instance);
/**
* Write all available output to the network
*/
void telegram_write_output (struct telegram *instance);
int telegram_write_output (struct telegram *instance);
/**
* Return whether there is pending output.
*/
int telegram_has_output (struct telegram *instance);
/**
* Try to interpret RPC calls and apply the changes to the current telegram state

26
tools.c
View file

@ -105,6 +105,32 @@ void tfree (void *ptr, int size __attribute__ ((unused))) {
#endif
}
/**
* Add a variable amount of strings together
*/
//char *stradd(const char *strs, ...)
//{
// va_list args;
// size_t size = 0;
// char *result;
//
// // count strlen
// va_start(args, strs);
// for (int i = 0; strs[i] != '\0'; i++) {
// size += strlen(va_arg(args, char*));
// }
// va_end(args);
//
// // create the new string
// result = talloc0(size + 1);
// va_start(args, strs);
// for (int i = 0; strs[i] != '\0'; i++) {
// strcat(result, va_arg(args, char*));
// }
// va_end(args);
// return result;
//}
void tfree_str (void *ptr) {
if (!ptr) { return; }
tfree (ptr, strlen (ptr) + 1);

View file

@ -25,6 +25,7 @@ void *trealloc (void *ptr, size_t old_size, size_t size);
void *talloc0 (size_t size);
char *tstrdup (const char *s);
char *tstrndup (const char *s, size_t n);
//char *stradd(const char *, ...);
int tinflate (void *input, int ilen, void *output, int olen);
void ensure (int r);
void ensure_ptr (void *p);