Implement state machine for dc discovery and login.
This commit is contained in:
parent
f1a2738783
commit
1170ae5710
8 changed files with 139 additions and 84 deletions
|
@ -238,6 +238,9 @@ int rpc_send_message (struct connection *c, void *data, int len) {
|
|||
|
||||
self->total_packets_sent ++;
|
||||
self->total_data_sent += total_len;
|
||||
|
||||
self->queries_num ++;
|
||||
logprintf("queries_num=%d\n", self->queries_num);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1787,6 +1790,7 @@ int tc_becomes_ready (struct connection *c) {
|
|||
break;
|
||||
case st_authorized:
|
||||
auth_work_start (c);
|
||||
telegram_change_state(c->instance, STATE_AUTHORIZED, NULL);
|
||||
break;
|
||||
default:
|
||||
logprintf ( "c_state = %d\n", c->mtconnection->c_state);
|
||||
|
@ -1890,3 +1894,4 @@ void mtproto_close(struct mtproto_connection *c)
|
|||
// stop_ping_timer (c->connection);
|
||||
fd_close_connection(c->connection);
|
||||
}
|
||||
|
||||
|
|
3
net.c
3
net.c
|
@ -722,10 +722,11 @@ struct connection *fd_create_connection (struct dc *DC, int fd,
|
|||
S->c = c;
|
||||
DC->sessions[0] = S;
|
||||
}
|
||||
// add backreference to session
|
||||
c->session = DC->sessions[0];
|
||||
|
||||
// add backreference to used mtproto-connection
|
||||
c->mtconnection = mtp;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,18 +203,18 @@ static void tgprpl_on_state_change(struct telegram *instance, int state, void *d
|
|||
do_send_code_result_auth (instance, code, hash, first_name, last_name);
|
||||
break;
|
||||
|
||||
case STATE_PHONE_CODE_NOT_ENTERED:
|
||||
purple_connection_set_state(_gc, PURPLE_CONNECTED);
|
||||
case STATE_PHONE_CODE_NOT_ENTERED: {
|
||||
char *hash = data;
|
||||
const char *code = purple_account_get_string(conn->pa, "verification_key", NULL);
|
||||
do_send_code_result(instance, code, hash);
|
||||
// TODO: Request SMS code
|
||||
break;
|
||||
|
||||
case STATE_CLIENT_NOT_REGISTERED:
|
||||
// ask for registration type
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_CLIENT_CODE_NOT_ENTERED: {
|
||||
char *hash = data;
|
||||
const char *code = purple_account_get_string(conn->pa, "verification_key", NULL);
|
||||
const char *hash = purple_account_get_string(conn->pa, "verification_hash", NULL);
|
||||
//const char *hash = purple_account_get_string(conn->pa, "verification_hash", NULL);
|
||||
do_send_code_result(instance, code, hash);
|
||||
// enter SMS code
|
||||
}
|
||||
|
@ -248,7 +248,9 @@ static void tgprpl_on_state_change(struct telegram *instance, int state, void *d
|
|||
// get new messages
|
||||
purple_debug_info(PLUGIN_ID, "Fetching new messages...\n");
|
||||
do_get_difference(instance);
|
||||
telegram_flush_queries(instance);
|
||||
|
||||
tgprpl_has_output(instance);
|
||||
//telegram_flush_queries(instance);
|
||||
break;
|
||||
|
||||
case STATE_ERROR: {
|
||||
|
@ -302,15 +304,12 @@ void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_messa
|
|||
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) {
|
||||
logprintf("purple_proxy_connect failed: %s\n", error_message);
|
||||
telegram_free(tg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
|
51
queries.c
51
queries.c
|
@ -140,11 +140,6 @@ void query_restart (long long id) {
|
|||
|
||||
struct query *send_query (struct dc *DC, int ints, void *data, struct query_methods *methods, void *extra) {
|
||||
logprintf("send_query(...)\n");
|
||||
/*
|
||||
if (!DC->sessions[0]) {
|
||||
dc_create_session (DC);
|
||||
}
|
||||
*/
|
||||
if (verbosity) {
|
||||
logprintf ( "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
|
||||
}
|
||||
|
@ -173,8 +168,10 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
|
|||
insert_event_timer (&q->ev);
|
||||
|
||||
q->extra = extra;
|
||||
//queries_num ++;
|
||||
//logprintf("queries_num: %d\n", queries_num);
|
||||
|
||||
struct mtproto_connection *mtp = DC->sessions[0]->c->mtconnection;
|
||||
mtp->queries_num ++;
|
||||
logprintf("queries_num: %d\n", mtp->queries_num);
|
||||
return q;
|
||||
}
|
||||
|
||||
|
@ -211,8 +208,9 @@ void query_error (long long id) {
|
|||
tfree (q->data, q->data_len * 4);
|
||||
tfree (q, sizeof (*q));
|
||||
}
|
||||
//queries_num --;
|
||||
//logprintf("queries_num: %d\n", queries_num);
|
||||
|
||||
mtp->queries_num --;
|
||||
logprintf("queries_num: %d\n", mtp->queries_num);
|
||||
}
|
||||
|
||||
#define MAX_PACKED_SIZE (1 << 24)
|
||||
|
@ -355,9 +353,7 @@ void fetch_dc_option (struct telegram *instance) {
|
|||
int l2 = prefetch_strlen (mtp);
|
||||
char *ip = fetch_str (mtp, l2);
|
||||
int port = fetch_int (mtp);
|
||||
if (verbosity) {
|
||||
logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
|
||||
}
|
||||
logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port);
|
||||
|
||||
bl_do_dc_option (mtp, id, l1, name, l2, ip, port, instance);
|
||||
}
|
||||
|
@ -374,9 +370,7 @@ int help_get_config_on_answer (struct query *q UU) {
|
|||
assert (test_mode == CODE_bool_true || test_mode == CODE_bool_false);
|
||||
assert (test_mode == CODE_bool_false || test_mode == CODE_bool_true);
|
||||
int this_dc = fetch_int (mtp);
|
||||
if (verbosity) {
|
||||
logprintf ( "this_dc = %d\n", this_dc);
|
||||
}
|
||||
logprintf ( "this_dc = %d\n", this_dc);
|
||||
assert (fetch_int (mtp) == CODE_vector);
|
||||
int n = fetch_int (mtp);
|
||||
assert (n <= 10);
|
||||
|
@ -388,10 +382,9 @@ int help_get_config_on_answer (struct query *q UU) {
|
|||
if (op == CODE_config) {
|
||||
max_bcast_size = fetch_int (mtp);
|
||||
}
|
||||
if (verbosity >= 2) {
|
||||
logprintf ( "chat_size = %d\n", max_chat_size);
|
||||
}
|
||||
telegram_change_state(instance, STATE_CONNECTED, 0);
|
||||
logprintf ( "max_chat_size = %d\n", max_chat_size);
|
||||
|
||||
telegram_change_state(instance, STATE_CONFIG_RECEIVED, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -405,7 +398,8 @@ void do_help_get_config (struct telegram *instance) {
|
|||
clear_packet (mtp);
|
||||
out_int (mtp, CODE_help_get_config);
|
||||
struct dc *DC_working = telegram_get_working_dc(instance);
|
||||
send_query (DC_working, mtp->packet_ptr - mtp->packet_buffer, mtp->packet_buffer, &help_get_config_methods, instance);
|
||||
send_query (DC_working, mtp->packet_ptr - mtp->packet_buffer,
|
||||
mtp->packet_buffer, &help_get_config_methods, instance);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -567,6 +561,18 @@ int check_phone_on_answer (struct query *q UU) {
|
|||
assert (fetch_int (mtp) == (int)CODE_auth_checked_phone);
|
||||
check_phone_result = fetch_bool (mtp);
|
||||
fetch_bool (mtp);
|
||||
|
||||
if (mtp->connection->instance->session_state != STATE_CONFIG_RECEIVED) {
|
||||
logprintf("check_phone_on_answer(): invalid state: %d\n", mtp->connection->instance->session_state);
|
||||
telegram_change_state(mtp->connection->instance, STATE_ERROR, NULL);
|
||||
return -1;
|
||||
}
|
||||
logprintf("check_phone_result=%d\n", check_phone_result);
|
||||
if (check_phone_result) {
|
||||
telegram_change_state(mtp->connection->instance, STATE_CLIENT_NOT_REGISTERED, NULL);
|
||||
} else {
|
||||
telegram_change_state(mtp->connection->instance, STATE_PHONE_NOT_REGISTERED, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -592,7 +598,7 @@ int check_phone_on_error (struct query *q UU, int error_code, int l, char *error
|
|||
} else {
|
||||
logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error);
|
||||
}
|
||||
telegram_change_state(instance, STATE_ERROR, error);
|
||||
telegram_change_state(instance, STATE_DISCONNECTED_SWITCH_DC, error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -601,7 +607,7 @@ struct query_methods check_phone_methods = {
|
|||
.on_error = check_phone_on_error
|
||||
};
|
||||
|
||||
int do_auth_check_phone (struct telegram *instance, const char *user) {
|
||||
void do_auth_check_phone (struct telegram *instance, const char *user) {
|
||||
struct mtproto_connection *mtp = instance->connection;
|
||||
|
||||
suser = tstrdup (user);
|
||||
|
@ -617,7 +623,6 @@ int do_auth_check_phone (struct telegram *instance, const char *user) {
|
|||
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, instance);
|
||||
net_loop (0, cr_f);
|
||||
*/
|
||||
return check_phone_result;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ void do_load_video (struct telegram *instance, struct video *V, int next);
|
|||
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);
|
||||
void do_auth_check_phone (struct telegram *instance, const char *user);
|
||||
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);
|
||||
|
|
|
@ -1535,7 +1535,7 @@ static int id_cmp (struct message *M1, struct message *M2) {
|
|||
}
|
||||
|
||||
struct user *fetch_alloc_user (struct mtproto_connection *mtp) {
|
||||
logprintf("fetch_alloc_user()\n");
|
||||
logprintf("fetch_alloc_user()\n");
|
||||
int send_event = 0;
|
||||
int data[2];
|
||||
prefetch_data (mtp, data, 8);
|
||||
|
|
105
telegram.c
105
telegram.c
|
@ -55,8 +55,57 @@ void telegram_change_state(struct telegram *instance, int state, void *data)
|
|||
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) {
|
||||
do {
|
||||
((state_listener_t)curr->data)(instance, state, data);
|
||||
} while ((curr = g_list_next(change_listeners)) != NULL);
|
||||
}
|
||||
|
||||
void on_state_change(struct telegram *instance, int state, void *data)
|
||||
{
|
||||
logprintf("on_state_change: %d\n", state);
|
||||
switch (state) {
|
||||
case STATE_ERROR: {
|
||||
const char* err = data;
|
||||
logprintf("Telegram errored: %s \n", err);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_AUTHORIZED:
|
||||
logprintf("requesting configuration");
|
||||
telegram_change_state(instance, STATE_CONFIG_REQUESTED, NULL);
|
||||
do_help_get_config (instance);
|
||||
break;
|
||||
|
||||
case STATE_CONFIG_RECEIVED:
|
||||
logprintf("received network configuration, checking whether phone is registered.");
|
||||
telegram_store_session(instance);
|
||||
do_auth_check_phone(instance, instance->login);
|
||||
break;
|
||||
|
||||
case STATE_PHONE_NOT_REGISTERED:
|
||||
logprintf("phone is not registered, need to register phone number.\n");
|
||||
do_send_code(instance, instance->login);
|
||||
break;
|
||||
|
||||
case STATE_PHONE_CODE_REQUESTED:
|
||||
logprintf("phone authenticion, user needs to enter code, first and last name.\n");
|
||||
// wait for user input ...
|
||||
break;
|
||||
|
||||
case STATE_CLIENT_NOT_REGISTERED:
|
||||
logprintf("phone is already registered, need to register client.\n");
|
||||
do_send_code(instance, instance->login);
|
||||
break;
|
||||
|
||||
case STATE_CLIENT_CODE_NOT_ENTERED:
|
||||
logprintf("client authentication, user needs to enter code");
|
||||
// wait for user input ...
|
||||
break;
|
||||
|
||||
case STATE_DISCONNECTED_SWITCH_DC:
|
||||
logprintf("Have to migrate to other DC");
|
||||
instance->connection
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +130,7 @@ struct telegram *telegram_new(struct dc *DC, const char* login, const char *conf
|
|||
logprintf("%s\n", this->auth_path);
|
||||
logprintf("%s\n", this->state_path);
|
||||
|
||||
telegram_add_state_change_listener(this, on_state_change);
|
||||
telegram_change_state(this, STATE_INITIALISED, NULL);
|
||||
return this;
|
||||
}
|
||||
|
@ -125,7 +175,6 @@ struct connection *telegram_get_connection(struct telegram *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;
|
||||
}
|
||||
|
||||
|
@ -171,51 +220,45 @@ char *telegram_get_config(struct telegram *instance, char *config)
|
|||
return g_strdup_printf("%s/%s", instance->config_path, config);
|
||||
}
|
||||
|
||||
void on_connected(struct mtproto_connection *c, void* data);
|
||||
void on_authorized(struct mtproto_connection *c, void* data);
|
||||
|
||||
/**
|
||||
* Connect to the currently active data center
|
||||
*/
|
||||
void telegram_network_connect(struct telegram *instance, int fd)
|
||||
{
|
||||
logprintf("telegram_network_connect()\n");
|
||||
if (!instance->auth.DC_list) {
|
||||
logprintf("telegram_network_connect(): cannot connect, restore / initialise a session first.\n");
|
||||
logprintf("telegram_network_connect(): cannot connect, restore / init a session first.\n");
|
||||
assert(0);
|
||||
}
|
||||
struct dc *DC_working = telegram_get_working_dc(instance);
|
||||
instance->connection = mtproto_new(DC_working, fd, instance);
|
||||
instance->connection->on_ready = on_connected;
|
||||
instance->connection->on_ready = on_authorized;
|
||||
instance->connection->on_ready_data = instance;
|
||||
mtproto_connect(instance->connection);
|
||||
}
|
||||
|
||||
void on_connected(struct mtproto_connection *c, void *data)
|
||||
/**
|
||||
* Login, and perform a registration when needed
|
||||
*/
|
||||
int telegram_login(struct telegram *instance)
|
||||
{
|
||||
struct telegram *instance = data;
|
||||
logprintf("Authorized... storing current session.\n");
|
||||
telegram_store_session(instance);
|
||||
if (instance->session_state != STATE_AUTHORIZED) {
|
||||
logprintf("Cannot log in, invalid state: %d \n", instance->session_state);
|
||||
return -1;
|
||||
}
|
||||
do_help_get_config(instance);
|
||||
telegram_change_state(instance, STATE_CONFIG_REQUESTED, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void on_state_change(struct telegram *instance, int state, void *data)
|
||||
void on_authorized(struct mtproto_connection *c, void *data)
|
||||
{
|
||||
switch (state) {
|
||||
case STATE_CONNECTED:
|
||||
break;
|
||||
|
||||
case STATE_ERROR: {
|
||||
const char* err = data;
|
||||
logprintf("Telegram errored: %s \n", err);
|
||||
}
|
||||
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;
|
||||
}
|
||||
struct telegram *instance = data;
|
||||
logprintf("Authorized... storing current session %d.\n", c->connection->session[0]);
|
||||
telegram_store_session(instance);
|
||||
telegram_change_state(instance, STATE_AUTHORIZED, NULL);
|
||||
}
|
||||
|
||||
void telegram_read_input (struct telegram *instance)
|
||||
|
|
34
telegram.h
34
telegram.h
|
@ -26,7 +26,7 @@ struct protocol_state;
|
|||
struct authorization_state;
|
||||
|
||||
/*
|
||||
* Libtelegram states
|
||||
* telegram states
|
||||
*/
|
||||
|
||||
#define STATE_INITIALISED 0
|
||||
|
@ -35,35 +35,35 @@ struct authorization_state;
|
|||
// Error
|
||||
#define STATE_ERROR 2
|
||||
|
||||
// Authentication
|
||||
#define STATE_PQ_REQUESTED 3
|
||||
#define STATE_DH_REQUESTED 4
|
||||
#define STATE_CDH_REQUESTED 5
|
||||
#define STATE_AUTH_DONE 6
|
||||
// intermediate authorization states already present and handled in mtproto-client.c
|
||||
//#define STATE_PQ_REQUESTED 3
|
||||
//#define STATE_DH_REQUESTED 4
|
||||
//#define STATE_CDH_REQUESTED 5
|
||||
#define STATE_AUTHORIZED 6
|
||||
|
||||
// dc discovery
|
||||
#define STATE_CONFIG_REQUESTED 7
|
||||
#define STATE_EXPORTING_CONFIG 8
|
||||
#define STATE_DISCONNECTED_SWITCH_DC 9
|
||||
#define STATE_CONFIG_RECEIVED 11
|
||||
|
||||
// Login
|
||||
#define STATE_CONNECTED 10
|
||||
// login
|
||||
|
||||
// - Phone Registration
|
||||
#define STATE_PHONE_IS_REGISTERED_SENT 11
|
||||
#define STATE_PHONE_IS_REGISTERED_SENT_2 12
|
||||
#define STATE_PHONE_NOT_REGISTERED 13
|
||||
#define STATE_PHONE_CODE_REQUESTED 14
|
||||
#define STATE_PHONE_CODE_NOT_ENTERED 15
|
||||
#define STATE_PHONE_CODE_ENTERED 16
|
||||
|
||||
// - Client Registration
|
||||
#define STATE_CLIENT_IS_REGISTERED_SENT 16
|
||||
#define STATE_CLIENT_NOT_REGISTERED 17
|
||||
#define STATE_CLIENT_CODE_REQUESTED 18
|
||||
#define STATE_CLIENT_CODE_NOT_ENTERED 19
|
||||
#define STATE_CLIENT_CODE_ENTERED 20
|
||||
#define STATE_CLIENT_IS_REGISTERED_SENT 17
|
||||
#define STATE_CLIENT_NOT_REGISTERED 18
|
||||
#define STATE_CLIENT_CODE_REQUESTED 19
|
||||
#define STATE_CLIENT_CODE_NOT_ENTERED 20
|
||||
#define STATE_CLIENT_CODE_ENTERED 21
|
||||
|
||||
// Ready for sending and receiving messages
|
||||
#define STATE_READY 21
|
||||
#define STATE_READY 22
|
||||
|
||||
/**
|
||||
* A telegram session
|
||||
|
@ -173,6 +173,8 @@ void telegram_change_state(struct telegram *instance, int state, void *data);
|
|||
*/
|
||||
void telegram_network_connect (struct telegram *instance, int fd);
|
||||
|
||||
int telegram_login (struct telegram *instance);
|
||||
|
||||
/**
|
||||
* Read the authorization_state stored in the given file
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue