Move telegram callbacks and settings into configuration struct

This commit is contained in:
mjentsch 2014-08-23 02:40:10 +02:00
parent f09b4c1c87
commit a4e5449d5a
5 changed files with 213 additions and 229 deletions

View file

@ -890,7 +890,7 @@ void work_update (struct mtproto_connection *self, long long msg_id UU) {
assert (M);
fetch_pts (self);
self->unread_messages ++;
event_update_new_message(M);
event_update_new_message (tg, M);
//print_message (M);
//update_prompt ();
break;

View file

@ -73,8 +73,10 @@ void tg_cli_log_cb(const char* format, va_list ap)
purple_debug_info(PLUGIN_ID, "%s", buffer);
}
void on_new_message(struct message *M);
void peer_allocated_handler(void *user);
void on_new_message (struct telegram *instance, struct message *M);
void peer_allocated_handler (struct telegram *instance, void *user);
void telegram_on_phone_registration (struct telegram *instance);
void elegram_on_client_registration (struct telegram *instance);
/**
* Returns the base icon name for the given buddy and account.
@ -99,26 +101,7 @@ 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
// only once.
purple_debug_info(PLUGIN_ID, "No code provided, requesting new authentication code.\n");
char *new_hash = network_request_registration();
purple_debug_info(PLUGIN_ID, "Saving verification_hash: '%s'", new_hash);
purple_account_set_string(acct, "verification_hash", new_hash);
purple_notify_message(_telegram_protocol, PURPLE_NOTIFY_MSG_INFO, "Please Verify",
"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
* notifying the user
* Handle a failed verification by removing the invalid sms code and notifying the user
*/
static void login_verification_fail(PurpleAccount *acct)
{
@ -179,89 +162,6 @@ static void tgprpl_has_input(struct telegram *tg)
}
}
static void tgprpl_on_state_change(struct telegram *instance, int state, void *data)
{
telegram_conn *conn = instance->extra;
switch (state) {
case STATE_PHONE_NOT_REGISTERED:
// TODO: Request first and last name
// TODO: Fetch PurpleAccount and don't use global
purple_debug_info(PLUGIN_ID, "Phone is not registered, registering...\n");
const char *first_name = purple_account_get_string(conn->pa, "first_name", NULL);
const char *last_name = purple_account_get_string(conn->pa, "last_name", NULL);
const char *code = purple_account_get_string(conn->pa, "verification_key", NULL);
const char *hash = purple_account_get_string(conn->pa, "verification_hash", NULL);
purple_debug_info(PLUGIN_ID, "code: %s\n", code);
purple_debug_info(PLUGIN_ID, "verification_hash: %s\n", hash);
if (!first_name || !last_name || !strlen(first_name) > 0 || !strlen(last_name) > 0) {
purple_notify_message(_telegram_protocol, PURPLE_NOTIFY_MSG_INFO, "Registration Needed",
"Enter your first and last name to register this phone number with the telegram network.",
NULL, NULL, NULL);
return;
}
do_send_code_result_auth (instance, code, hash, first_name, last_name);
break;
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_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);
do_send_code_result(instance, code, hash);
// enter SMS code
}
break;
case STATE_READY:
// ready
purple_debug_info(PLUGIN_ID, "Logged in...\n");
purple_connection_set_state(conn->gc, PURPLE_CONNECTED);
char const *username = purple_account_get_username(conn->pa);
purple_connection_set_display_name(conn->gc, username);
purple_blist_add_account(conn->pa);
tggroup = purple_find_group("struct telegram");
if (tggroup == NULL) {
purple_debug_info(PLUGIN_ID, "PurpleGroup = NULL, creating");
tggroup = purple_group_new("struct telegram");
purple_blist_add_group(tggroup, NULL);
}
on_update_new_message(on_new_message);
on_peer_allocated(peer_allocated_handler);
// get all current contacts
purple_debug_info(PLUGIN_ID, "Fetching all current contacts...\n");
do_update_contact_list(instance);
purple_debug_info(PLUGIN_ID, "Fetching all current chats...\n");
do_get_dialog_list(instance);
// get new messages
purple_debug_info(PLUGIN_ID, "Fetching new messages...\n");
do_get_difference(instance);
tgprpl_has_output(instance);
//telegram_flush_queries(instance);
break;
case STATE_ERROR: {
const char* err = data;
logprintf("Connection errored: %s\n", err);
}
break;
}
}
static void init_dc_settings(PurpleAccount *acc, struct dc *DC)
{
DC->port = purple_account_get_int(acc, "port", TELEGRAM_DEFAULT_PORT);
@ -293,6 +193,101 @@ void telegram_on_proxy_close(struct telegram *instance, int fd UU)
purple_input_remove (conn->wh);
}
void telegram_on_phone_registration (struct telegram *instance)
{
telegram_conn *conn = instance->extra;
// TODO: Request first and last name
// TODO: Fetch PurpleAccount and don't use global
purple_debug_info(PLUGIN_ID, "Phone is not registered, registering...\n");
const char *first_name = purple_account_get_string(conn->pa, "first_name", NULL);
const char *last_name = purple_account_get_string(conn->pa, "last_name", NULL);
const char *code = purple_account_get_string(conn->pa, "verification_key", NULL);
if (!first_name || !last_name || !strlen(first_name) > 0 || !strlen(last_name) > 0) {
purple_notify_message(_telegram_protocol, PURPLE_NOTIFY_MSG_INFO, "Registration Needed",
"Enter your first and last name to register this phone number with the telegram network.",
NULL, NULL, NULL);
return;
}
do_send_code_result_auth (instance, code, first_name, last_name);
}
void client_registration_entered (gpointer data, const gchar *code)
{
struct telegram *tg = data;
do_send_code_result (tg, code);
tgprpl_has_output (tg);
}
void client_registration_canceled (gpointer data)
{
struct telegram *tg = data;
// TODO: disconnect and exit
}
void telegram_on_client_registration (struct telegram *instance)
{
purple_debug_info(PLUGIN_ID, "Client is not registered, registering...\n");
telegram_conn *conn = instance->extra;
purple_request_input(
conn->gc, // handle (the PurpleAccount)
"Telegram Code", // title
"Enter Telegram Code", // primary
"Telegram wants to verify your identity, please enter the code, that you have received via SMS.", // secondary
NULL, // default_value
FALSE, // multiline
FALSE, // masked
"code", // hint
"OK", // ok_text
G_CALLBACK(client_registration_entered), // ok_cb
"Cancel", // cancel_text
G_CALLBACK(client_registration_canceled), // cancel_cb
conn->pa, // account
NULL, // who
NULL, // conv
conn->tg // user_data
);
}
void telegram_on_ready (struct telegram *instance)
{
purple_debug_info(PLUGIN_ID, "telegram_on_ready().\n");
telegram_conn *conn = instance->extra;
purple_connection_set_state(conn->gc, PURPLE_CONNECTED);
purple_connection_set_display_name(conn->gc, purple_account_get_username(conn->pa));
purple_blist_add_account(conn->pa);
tggroup = purple_find_group("Telegram");
if (tggroup == NULL) {
purple_debug_info (PLUGIN_ID, "PurpleGroup = NULL, creating");
tggroup = purple_group_new ("struct telegram");
purple_blist_add_group (tggroup, NULL);
}
// get all current contacts
purple_debug_info(PLUGIN_ID, "Fetching all current contacts...\n");
do_update_contact_list(instance);
purple_debug_info(PLUGIN_ID, "Fetching all current chats...\n");
do_get_dialog_list(instance);
// get new messages
purple_debug_info(PLUGIN_ID, "Fetching new messages...\n");
do_get_difference(instance);
tgprpl_has_output(instance);
}
void telegram_on_disconnected (struct telegram *tg)
{
logprintf ("telegram_on_disconnected()\n");
assert (0);
}
/**
* A proxy connection was created by purple
*
@ -314,31 +309,17 @@ void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_messa
conn->rh = purple_input_add(fd, PURPLE_INPUT_READ, tgprpl_input_cb, tg);
telegram_set_proxy(tg, fd);
}
// // load all settings: the known network topology, secret keys, logs and configuration file paths
// purple_debug_info(PLUGIN_ID, "parse_config()\n");
// parse_config ();
// purple_debug_info(PLUGIN_ID, "set_default_username()\n");
//set_default_username (username);
// Connect to the network
// Assure phone number registration
/*
if (!network_phone_is_registered()) {
if (code && strlen(code) > 0 && hash && strlen(hash) > 0) {
int registered = network_verify_phone_registration(code, hash, first_name, last_name);
if (registered) {
store_config();
} else {
login_verification_fail(acct);
return;
}
} else {
login_request_verification(acct);
return;
}
}
*/
struct telegram_config tgconf = {
"/home/dev-jessie/.telegram",
NULL, // on output
telegram_on_proxy_request,
telegram_on_proxy_close,
telegram_on_phone_registration,
telegram_on_client_registration,
telegram_on_ready,
telegram_on_disconnected,
// Assure client registration
/*
@ -362,7 +343,9 @@ void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_messa
}
}
*/
}
on_new_message,
peer_allocated_handler
};
/**
* This must be implemented.
@ -380,9 +363,7 @@ static void tgprpl_login(PurpleAccount * acct)
// TODO: fetch current home directory
// use this as root
struct telegram *tg = telegram_new(&DC, username, "/home/dev-jessie/.telegram",
telegram_on_proxy_request, telegram_on_proxy_close);
telegram_add_state_change_listener(tg, tgprpl_on_state_change);
struct telegram *tg = telegram_new (&DC, username, &tgconf);
telegram_restore_session(tg);
telegram_conn *conn = g_new0(telegram_conn, 1);
@ -396,7 +377,7 @@ static void tgprpl_login(PurpleAccount * acct)
telegram_network_connect(tg);
}
void on_new_message(struct message *M)
void on_new_message(struct telegram *tg, struct message *M)
{
purple_debug_info(PLUGIN_ID, "New Message: %s\n", M->message);
// TODO: this should probably be freed again somwhere
@ -439,7 +420,7 @@ static PurpleChat *blist_find_chat_by_id(PurpleConnection *gc, const char *id)
}
void peer_allocated_handler(void *usr)
void peer_allocated_handler(struct telegram *tg, void *usr)
{
peer_t *user = usr;
gchar *name = g_strdup_printf("%d", get_peer_id(user->id));

View file

@ -75,7 +75,7 @@ extern int sync_from_start;
int sync_from_start = 0;
void telegram_flush_queries (struct telegram *instance) {
instance->on_output(instance);
instance->config->on_output(instance);
}
void out_peer_id (struct mtproto_connection *self, peer_id_t id);
@ -153,8 +153,10 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
logprintf ( "%lld %lld\n", q->msg_id, queries_tree->x->msg_id);
}
}
queries_tree = tree_insert_query (queries_tree, q, lrand48 ());
logprintf("queries_num: %d\n", ++ mtc->queries_num);
struct mtproto_connection *mtp = query_get_mtproto(q);
logprintf("queries_num: %d\n", ++ mtp->queries_num);
q->ev.alarm = (void *)alarm_query;
q->ev.timeout = get_double_time () + QUERY_TIMEOUT;

View file

@ -18,51 +18,23 @@
/*
* New message received
*/
void (*on_msg_handler)(struct message *M);
void on_update_new_message(void (*on_msg)(struct message *M))
void event_update_new_message(struct telegram *instance, struct message *M)
{
on_msg_handler = on_msg;
}
void event_update_new_message(struct message *M)
{
if (on_msg_handler) {
on_msg_handler(M);
if (instance->config->on_msg_handler) {
instance->config->on_msg_handler(instance, M);
}
}
/*
* Peer allocated
*/
void (*on_peer_allocated_handler)(void *peer);
void on_peer_allocated(void (*handler)(void *peer))
void event_peer_allocated(struct telegram *instance, void *peer)
{
on_peer_allocated_handler = handler;
}
void event_peer_allocated(void *peer)
{
if (on_peer_allocated_handler) {
on_peer_allocated_handler(peer);
if (instance->config->on_peer_allocated_handler) {
instance->config->on_peer_allocated_handler(instance, peer);
}
}
/*
* State changed
*/
GList *change_listeners = NULL;
void telegram_add_state_change_listener(struct telegram *instance, state_listener_t listener)
{
instance->change_state_listeners = g_list_append(instance->change_state_listeners, listener);
}
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;
do {
((state_listener_t)curr->data)(instance, state, data);
} while ((curr = g_list_next(change_listeners)) != NULL);
}
/**
* Calculate the configuration path for the given config file and the given instance
*
@ -82,8 +54,9 @@ char *telegram_get_config(struct telegram *instance, char *config)
* the authorization and registration steps needed to connect the client to the telegram network,
* and will either trigger RPC queries or callbacks to the GUI to request input from the user.
*/
void on_state_change(struct telegram *instance, int state, void *data)
void telegram_change_state (struct telegram *instance, int state, void *data)
{
instance->session_state = state;
logprintf("on_state_change: %d\n", state);
switch (state) {
case STATE_ERROR: {
@ -139,11 +112,9 @@ void on_state_change(struct telegram *instance, int state, void *data)
// close old connection and mark it for destruction
mtproto_close (instance->connection);
if (instance->proxy_request_cb) {
// tell the proxy to close all connections
instance->proxy_close_cb (instance,
instance->connection->connection->fd);
}
assert (instance->config->proxy_request_cb);
// tell the proxy to close all connections
instance->config->proxy_close_cb (instance, instance->connection->connection->fd);
// start a new connection to the demanded data center. The pointer to the
// currently working dc should have already been updated by the
@ -154,20 +125,16 @@ void on_state_change(struct telegram *instance, int state, void *data)
}
}
struct telegram *telegram_new(struct dc *DC, const char* login, const char *config_path,
void (*proxy_request_cb)(struct telegram *instance, const char *ip, int port),
void (*proxy_close_cb)(struct telegram *instance, int fd))
struct telegram *telegram_new(struct dc *DC, const char* login, struct telegram_config *config)
{
struct telegram *this = talloc0(sizeof(struct telegram));
this->protocol_data = NULL;
this->auth.DC_list[0] = DC;
this->change_state_listeners = NULL;
this->bl = talloc0 (sizeof(struct binlog));
this->proxy_request_cb = proxy_request_cb;
this->proxy_close_cb = proxy_close_cb;
this->config = config;
this->login = g_strdup(login);
this->config_path = g_strdup_printf("%s/%s", config_path, login);
this->config_path = g_strdup_printf("%s/%s", config->base_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");
@ -180,14 +147,12 @@ struct telegram *telegram_new(struct dc *DC, const char* login, const char *conf
logprintf("%s\n", this->state_path);
logprintf("%s\n", this->secret_path);
telegram_add_state_change_listener(this, on_state_change);
telegram_change_state(this, STATE_INITIALISED, NULL);
return this;
}
void telegram_free(struct telegram *this)
{
g_list_free(this->change_state_listeners);
g_free(this->login);
g_free(this->config_path);
g_free(this->download_path);
@ -279,8 +244,8 @@ void telegram_network_connect(struct telegram *instance)
assert(0);
}
struct dc *DC_working = telegram_get_working_dc (instance);
assert (instance->proxy_request_cb);
instance->proxy_request_cb (instance, DC_working->ip, DC_working->port);
assert (instance->config->proxy_request_cb);
instance->config->proxy_request_cb (instance, DC_working->ip, DC_working->port);
}
/**

View file

@ -83,6 +83,75 @@ struct binlog {
int s[1000];
};
struct telegram;
/**
* Contains all options and pointer to callback functions required by telegram
*/
struct telegram_config {
/**
* The base path containing the telegram configuration
*/
const char* base_config_path;
/**
* Called when there is pending network output
*/
void (*on_output)(struct telegram *instance);
/**
* A callback function that delivers a connections to the given hostname
* and port by calling telegram_set_proxy. This is useful for tunelling
* the connection through a proxy server.
*/
void (*proxy_request_cb)(struct telegram *instance, const char *ip, int port);
/**
* A callback function that is called once the proxy connection is no longer
* needed. This is useful for freeing all used resources.
*/
void (*proxy_close_cb)(struct telegram *instance, int fd);
/**
* A callback function that is called when a phone registration is required.
*
* This callback must query first name, last name and the
* authentication code from the user and call do_send_code_result_auth once done
*/
void (*on_phone_registration_required) (struct telegram *instance);
/**
* A callback function that is called when a client registration is required.
*
* This callback must query the authentication code from the user and
* call do_send_code_result once done
*/
void (*on_client_registration_required) (struct telegram *instance);
/**
* A callback function that is called when telegram is ready
*/
void (*on_ready) (struct telegram *instance);
/**
* A callback function that is called when telegram is disconnected
*/
void (*on_disconnected) (struct telegram *instance);
/**
* A callback function that is called when a new message was allocated. This is useful
* for adding new messages to the GUI.
*/
void (*on_msg_handler)(struct telegram *instance, struct message *M);
/**
* A callback function that is called when a new peer was allocated. This is useful
* for populating the GUI with new peers.
*/
void (*on_peer_allocated_handler)(struct telegram *instance, void *peer);
};
/**
* A telegram session
*
@ -101,6 +170,7 @@ struct telegram {
char *secret_path;
int session_state;
struct telegram_config *config;
/*
* protocol state
@ -108,8 +178,6 @@ struct telegram {
struct protocol_state proto;
struct authorization_state auth;
GList *change_state_listeners;
/*
* connection
*/
@ -120,12 +188,6 @@ struct telegram {
*/
struct binlog *bl;
/*
* callbacks
*/
void (*on_output)(struct telegram *instance);
void (*proxy_request_cb)(struct telegram *instance, const char *ip, int port);
void (*proxy_close_cb)(struct telegram *instance, int fd);
void *extra;
};
@ -133,18 +195,11 @@ struct telegram {
/**
* Create a new telegram application
*
* @param DC The initial data center to use
* @param login The phone number to use as login name
* @param config_path The configuration path used to store the content
* @param proxy_request_cb A callback function that delivers a connections to the given hostname
* and port by calling telegram_set_proxy. This is useful for tunelling
* the connection through a proxy server
* @param proxy_close_cb A callback function that is called once the proxy connection is no longer
* needed. This is useful for freeing all used resources
* @param DC The initial data center to use
* @param login The phone number to use as login name
* @param config Contains all callbacks used for the telegram instance
*/
struct telegram *telegram_new(struct dc *DC, const char* login, const char* config_path,
void (*proxy_request_cb)(struct telegram *instance, const char *ip, int port),
void (*proxy_close_cb)(struct telegram *instance, int fd));
struct telegram *telegram_new(struct dc *DC, const char* login, struct telegram_config *config);
/**
* Resume the session to
@ -175,23 +230,6 @@ struct dc *telegram_get_working_dc(struct telegram *instance);
* Events
*/
/**
* Handler to process a state change
*
* @param instance The telegram instance that changed its state
* @param state The changed state
* @param data Extra data that depends on switched state
*/
typedef void (*state_listener_t)(struct telegram *instance, int state, void *data);
/**
* Execute this listener when the state has changed
*
* @param instance The telegram instance
* @param listener The listener to execute
*/
void telegram_add_state_change_listener(struct telegram *instance, state_listener_t listener);
/**
* Change the state of the given telegram instance and execute all event handlers
*
@ -283,14 +321,12 @@ void session_update_contact_list();
/*
* Events
*/
void on_update_new_message(void (*on_msg)(struct message *M));
void event_update_new_message(struct message *M);
void event_update_new_message(struct telegram *instance, struct message *M);
/*
* Load known users and chats on connect
*/
void on_peer_allocated(void (*handler)(void *peer));
void event_peer_allocated(void *peer);
void event_peer_allocated(struct telegram *instance, void *peer);
/**
* Set a function to use as a handle to read from a network resource