Request proxy connections by callback

Require the user of telegram to provide a callback to create and cleanup proxy connections, to allow
the application to create new connections when needed.
This commit is contained in:
mjentsch 2014-08-22 18:28:58 +02:00
parent 1b1c5d132a
commit 1e6598c11c
3 changed files with 97 additions and 37 deletions

View file

@ -270,35 +270,34 @@ static void init_dc_settings(PurpleAccount *acc, struct dc *DC)
}
/**
* This must be implemented.
* Handle a proxy-request of telegram
*
* Request a new proxy connection from purple, and execute tgprpl_login_on_connected
* as callback once the connection is ready
*/
static void tgprpl_login(PurpleAccount * acct)
void telegram_on_proxy_request(struct telegram *instance, const char *ip, int port)
{
purple_debug_info(PLUGIN_ID, "tgprpl_login()\n");
PurpleConnection *gc = purple_account_get_connection(acct);
char const *username = purple_account_get_username(acct);
_gc = gc;
_pa = acct;
struct dc DC;
init_dc_settings(acct, &DC);
// TODO: fetch current home directory
// use this as root
struct telegram *tg = telegram_new(&DC, username, "/home/dev-jessie/.telegram");
telegram_add_state_change_listener(tg, tgprpl_on_state_change);
telegram_restore_session(tg);
telegram_conn *conn = g_new0(telegram_conn, 1);
conn->tg = tg;
conn->gc = gc;
conn->pa = acct;
purple_connection_set_protocol_data(gc, conn);
tg->extra = conn;
purple_connection_set_state(gc, PURPLE_CONNECTING);
purple_proxy_connect(gc, acct, DC.ip, DC.port, tgprpl_login_on_connected, tg);
telegram_conn *conn = instance->extra;
purple_proxy_connect (conn->gc, conn->pa, ip, port, tgprpl_login_on_connected, conn->tg);
}
/**
* Handle a proxy-close of telegram
*
* Remove all open inputs added to purple
*/
void telegram_on_proxy_close(struct telegram *instance, int fd UU)
{
telegram_conn *conn = instance->extra;
purple_input_remove (conn->rh);
purple_input_remove (conn->wh);
}
/**
* A proxy connection was created by purple
*
* Set the proxy to the current telegram-instance, and add callbacks to monitor
*/
void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_message)
{
purple_debug_info(PLUGIN_ID, "tgprpl_login_on_connected()\n");
@ -313,7 +312,8 @@ void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_messa
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);
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");
@ -364,6 +364,38 @@ void tgprpl_login_on_connected(gpointer *data, gint fd, const gchar *error_messa
*/
}
/**
* This must be implemented.
*/
static void tgprpl_login(PurpleAccount * acct)
{
purple_debug_info(PLUGIN_ID, "tgprpl_login()\n");
PurpleConnection *gc = purple_account_get_connection(acct);
char const *username = purple_account_get_username(acct);
_gc = gc;
_pa = acct;
struct dc DC;
init_dc_settings(acct, &DC);
// 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);
telegram_restore_session(tg);
telegram_conn *conn = g_new0(telegram_conn, 1);
conn->tg = tg;
conn->gc = gc;
conn->pa = acct;
purple_connection_set_protocol_data(gc, conn);
tg->extra = conn;
purple_connection_set_state (conn->gc, PURPLE_CONNECTING);
telegram_network_connect(tg);
}
void on_new_message(struct message *M)
{
purple_debug_info(PLUGIN_ID, "New Message: %s\n", M->message);

View file

@ -115,7 +115,9 @@ 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)
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 *this = malloc(sizeof(struct telegram));
this->protocol_data = NULL;
@ -123,6 +125,8 @@ struct telegram *telegram_new(struct dc *DC, const char* login, const char *conf
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->login = g_strdup(login);
this->config_path = g_strdup_printf("%s/%s", config_path, login);
@ -234,18 +238,16 @@ 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)
void telegram_network_connect(struct telegram *instance)
{
logprintf("telegram_network_connect()\n");
if (!instance->auth.DC_list) {
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_authorized;
instance->connection->on_ready_data = instance;
mtproto_connect(instance->connection);
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);
}
/**
@ -273,6 +275,13 @@ void on_authorized(struct mtproto_connection *c, void *data)
void telegram_read_input (struct telegram *instance)
{
return try_read(instance->connection->connection);
void telegram_set_proxy(struct telegram *instance, int fd)
{
struct dc *DC_working = telegram_get_working_dc (instance);
instance->connection = mtproto_new (DC_working, fd, instance);
instance->connection->on_ready = on_authorized;
instance->connection->on_ready_data = instance;
mtproto_connect (instance->connection);
}
int telegram_write_output (struct telegram *instance)

View file

@ -124,15 +124,27 @@ struct telegram {
* 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;
};
/**
* constructor
* 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
*/
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,
void (*proxy_request_cb)(struct telegram *instance, const char *ip, int port),
void (*proxy_close_cb)(struct telegram *instance, int fd));
/**
* Resume the session to
@ -194,7 +206,7 @@ void telegram_change_state(struct telegram *instance, int state, void *data);
/**
* Connect to the telegram network with the given configuration
*/
void telegram_network_connect (struct telegram *instance, int fd);
void telegram_network_connect(struct telegram *instance);
int telegram_login (struct telegram *instance);
@ -294,4 +306,11 @@ void set_net_read_cb(ssize_t (*cb)(int fd, void *buff, size_t size));
*/
void set_net_write_cb(ssize_t (*cb)(int fd, const void *buff, size_t size));
/**
* Set the proxy-connection to use
*
* NOTE: you may only call this function from the
*/
void telegram_set_proxy(struct telegram *instance, int fd);
#endif