Add possibillity to listen to created users, chats and groups with event handlers and add some ability to exchange output functions with own callbacks

This commit is contained in:
mjentsch 2014-06-22 23:36:52 +02:00
parent dbf509d59e
commit d712b7e17f
7 changed files with 202 additions and 11 deletions

27
loop.c
View file

@ -536,6 +536,10 @@ void network_connect (void) {
write_auth_file ();
logprintf("DataCentre start_loopd, key id: %lld\n", DC_list[i]->auth_key_id);
}
// read saved connection state
read_state_file ();
read_secret_chat_file ();
}
/**
@ -625,6 +629,25 @@ void network_export_registration()
fflush (stderr);
}
/**
* Fetch all unknown messages of the current session
*/
void session_get_difference()
{
do_get_difference();
net_loop (0, dgot);
}
extern int contacts_got;
int cupdate_got() {
return contacts_got;
}
void session_update_contact_list()
{
do_update_contact_list();
net_loop(0, cupdate_got);
}
int start_loop (char* code, char* auth_mode) {
logprintf("Calling start_loop()\n");
logprintf("auth_state %i\n", auth_state);
@ -722,9 +745,11 @@ int start_loop (char* code, char* auth_mode) {
fflush (stdout);
fflush (stderr);
// read saved connection state
read_state_file ();
read_secret_chat_file ();
// callbacks for interface functions
set_interface_callbacks ();
do_get_difference ();

View file

@ -66,6 +66,8 @@
#include "mtproto-common.h"
#include "tg-cli.h"
#define MAX_NET_RES (1L << 16)
extern int log_level;
@ -906,6 +908,7 @@ void work_update_binlog (void) {
void work_update (struct connection *c UU, long long msg_id UU) {
unsigned op = fetch_int ();
logprintf("work_update(): OP:%d\n", op);
switch (op) {
case CODE_update_new_message:
{
@ -913,7 +916,8 @@ void work_update (struct connection *c UU, long long msg_id UU) {
assert (M);
fetch_pts ();
unread_messages ++;
print_message (M);
event_update_new_message(M);
//print_message (M);
update_prompt ();
break;
};
@ -1717,10 +1721,12 @@ int rpc_execute (struct connection *c, int op, int len) {
if (verbosity) {
logprintf ( "outbound rpc connection #%d : received rpc answer %d with %d content bytes\n", c->fd, op, len);
}
/* if (op < 0) {
/*
if (op < 0) {
assert (read_in (c, Response, Response_len) == Response_len);
return 0;
}*/
}
*/
if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
logprintf ( "answer too long (%d bytes), skipping\n", len);

54
net.c
View file

@ -59,6 +59,43 @@ extern FILE *log_net_f;
void fail_connection (struct connection *c);
/*
* Delegate the read-oprations to external function
*/
ssize_t (*netread)(int fd, void *buff, size_t size) = read;
void set_net_read_cb(ssize_t (*cb)(int fd, void *buff, size_t size)) {
netread = cb;
}
/*
* Delegate the write operations to external function
*/
ssize_t (*netwrite)(int fd, const void *buff, size_t size) = write;
void set_net_write_cb(ssize_t (*cb)(int fd, const void *buff, size_t size)) {
netwrite = cb;
}
/*
* Delegate the session creation to an external callback
*
* TODO: use dc_ensure_session instead of dc_create_session to create sessions,
* to make this actually work
*/
void dc_create_session (struct dc *DC);
void dc_ensure_session_local (struct dc *DC, void (*on_session_ready)(void)) {
dc_create_session(DC);
on_session_ready();
}
void (*dc_ensure_session)(struct dc *DC, void (*on_session_ready)(void));
void set_dc_ensure_session_cb (void (*dc_ens_sess)(struct dc *DC, void (*on_session_ready)(void)))
{
dc_ensure_session = dc_ens_sess;
}
/*
*
*/
#define PING_TIMEOUT 10
void start_ping_timer (struct connection *c);
@ -386,22 +423,29 @@ void try_write (struct connection *c) {
}
int x = 0;
while (c->out_head) {
int r = write (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
int r = netwrite (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
// Log all written packages
if (r > 0 && log_net_f) {
fprintf (log_net_f, "%.02lf %d OUT %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
int i;
for (i = 0; i < r; i++) {
fprintf (log_net_f, " %02x", *(unsigned char *)(c->out_head->rptr + i));
}
fprintf (log_net_f, "\n");
fflush (log_net_f);
}
if (r >= 0) {
x += r;
c->out_head->rptr += r;
if (c->out_head->rptr != c->out_head->wptr) {
// Inhalt des Buffers nicht komplett abgeschickt,
// es geht nichts mehr in den Socket
break;
}
// buffer ausgelesen, alten buffer löschen
struct connection_buffer *b = c->out_head;
c->out_head = b->next;
if (!c->out_head) {
@ -497,11 +541,12 @@ void try_read (struct connection *c) {
}
int x = 0;
while (1) {
int r = read (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr);
int r = netread (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr);
if (r > 0 && log_net_f) {
fprintf (log_net_f, "%.02lf %d IN %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
int i;
for (i = 0; i < r; i++) {
// print all writte bits
fprintf (log_net_f, " %02x", *(unsigned char *)(c->in_tail->wptr + i));
}
fprintf (log_net_f, "\n");
@ -509,13 +554,17 @@ void try_read (struct connection *c) {
}
if (r > 0) {
c->last_receive_time = get_double_time ();
// reset ping timer
stop_ping_timer (c);
start_ping_timer (c);
}
if (r >= 0) {
// write pointer nach vorne setzen
c->in_tail->wptr += r;
x += r;
if (c->in_tail->wptr != c->in_tail->end) {
// Paket nicht komplett beschrieben, keine neuen Daten liegen an.
break;
}
struct connection_buffer *b = new_connection_buffer (1 << 20);
@ -646,3 +695,4 @@ void dc_create_session (struct dc *DC) {
assert (!DC->sessions[0]);
DC->sessions[0] = S;
}

View file

@ -53,6 +53,7 @@
#include "no-preview.h"
#include "binlog.h"
#include "tg-cli.h"
#define sha1 SHA1
@ -132,7 +133,6 @@ struct query *send_query (struct dc *DC, int ints, void *data, struct query_meth
if (!DC->sessions[0]) {
dc_create_session (DC);
}
logprintf("telegram: verbosity: %d\n", verbosity);
if (verbosity) {
logprintf ( "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
}
@ -695,6 +695,7 @@ int do_send_code_result_auth (const char *code, const char *sms_hash, const char
/* {{{ Get contacts */
extern char *user_list[];
int contacts_got = 0;
int get_contacts_on_answer (struct query *q UU) {
int i;
assert (fetch_int () == (int)CODE_contacts_contacts);
@ -708,7 +709,8 @@ int get_contacts_on_answer (struct query *q UU) {
assert (fetch_int () == CODE_vector);
n = fetch_int ();
for (i = 0; i < n; i++) {
struct user *U = fetch_alloc_user ();
fetch_alloc_user ();
/*
print_start ();
push_color (COLOR_YELLOW);
logprintf ("User #%d: ", get_peer_id (U->id));
@ -735,7 +737,9 @@ int get_contacts_on_answer (struct query *q UU) {
}
pop_color ();
print_end ();
*/
}
contacts_got = 1;
return 0;
}
@ -745,11 +749,14 @@ struct query_methods get_contacts_methods = {
void do_update_contact_list (void) {
contacts_got = 0;
clear_packet ();
out_int (CODE_contacts_get_contacts);
out_string ("");
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0);
}
/* }}} */
/* {{{ Encrypt decrypted */
@ -2565,6 +2572,7 @@ int unread_messages;
int difference_got;
int seq, pts, qts, last_date;
int get_state_on_answer (struct query *q UU) {
logprintf("get_state_on_answer()\n");
assert (fetch_int () == (int)CODE_updates_state);
bl_do_set_pts (fetch_int ());
bl_do_set_qts (fetch_int ());
@ -2578,6 +2586,7 @@ int get_state_on_answer (struct query *q UU) {
int get_difference_active;
int get_difference_on_answer (struct query *q UU) {
logprintf("get_difference_on_answer()\n");
get_difference_active = 0;
unsigned x = fetch_int ();
if (x == CODE_updates_difference_empty) {
@ -2629,7 +2638,8 @@ int get_difference_on_answer (struct query *q UU) {
unread_messages = fetch_int ();
write_state_file ();
for (i = 0; i < ml_pos; i++) {
print_message (ML[i]);
event_update_new_message(ML[i]);
//print_message (ML[i]);
}
if (x == CODE_updates_difference_slice) {
do_get_difference ();
@ -2651,6 +2661,7 @@ struct query_methods get_difference_methods = {
};
void do_get_difference (void) {
logprintf("do_get_difference()\n");
get_difference_active = 1;
difference_got = 0;
clear_packet ();

View file

@ -33,6 +33,8 @@
#include "queries.h"
#include "binlog.h"
#include "tg-cli.h"
#define sha1 SHA1
static int id_cmp (struct message *M1, struct message *M2);
@ -204,6 +206,21 @@ long long fetch_user_photo (struct user *U) {
return 0;
}
int user_get_printname(peer_t *user, char *buffer, int maxlen)
{
char* last_name = (user->user.last_name && strlen(user->user.last_name)) ? user->user.last_name : "";
char* first_name = (user->user.first_name && strlen(user->user.first_name)) ? user->user.first_name : "";
if (strlen(first_name) && strlen(last_name)) {
return snprintf(buffer, maxlen, "%s %s", first_name, last_name);
} else if (strlen(first_name)) {
return snprintf(buffer, maxlen, "%s", first_name);
} else if (strlen(last_name)) {
return snprintf(buffer, maxlen, "%s", last_name);
} else {
return snprintf(buffer, maxlen, "%d", get_peer_id(user->id));
}
}
int fetch_user (struct user *U) {
unsigned x = fetch_int ();
code_assert (x == CODE_user_empty || x == CODE_user_self || x == CODE_user_contact || x == CODE_user_request || x == CODE_user_foreign || x == CODE_user_deleted);
@ -1512,10 +1529,12 @@ static int id_cmp (struct message *M1, struct message *M2) {
}
struct user *fetch_alloc_user (void) {
int send_event = 0;
int data[2];
prefetch_data (data, 8);
peer_t *U = user_chat_get (MK_USER (data[1]));
if (!U) {
send_event = 1;
users_allocated ++;
U = talloc0 (sizeof (*U));
U->id = MK_USER (data[1]);
@ -1524,6 +1543,9 @@ struct user *fetch_alloc_user (void) {
Peers[peer_num ++] = U;
}
fetch_user (&U->user);
if (send_event) {
event_user_allocated(U);
}
return &U->user;
}
@ -1871,10 +1893,12 @@ struct message *fetch_alloc_message_short_chat (void) {
}
struct chat *fetch_alloc_chat (void) {
int send_event = 0;
int data[2];
prefetch_data (data, 8);
peer_t *U = user_chat_get (MK_CHAT (data[1]));
if (!U) {
send_event = 1;
chats_allocated ++;
U = talloc0 (sizeof (*U));
U->id = MK_CHAT (data[1]);
@ -1883,6 +1907,9 @@ struct chat *fetch_alloc_chat (void) {
Peers[peer_num ++] = U;
}
fetch_chat (&U->chat);
if (send_event) {
event_chat_allocated(U);
}
return &U->chat;
}

View file

@ -156,6 +156,7 @@ struct user {
char *real_last_name;
};
struct chat_user {
int user_id;
int inviter_id;
@ -380,6 +381,8 @@ void peer_insert_name (peer_t *P);
void peer_delete_name (peer_t *P);
peer_t *peer_lookup_name (const char *s);
int user_get_printname(peer_t *user, char *buffer, int maxlen);
#define PEER_USER 1
#define PEER_CHAT 2
#define PEER_GEO_CHAT 3

View file

@ -1,12 +1,15 @@
#include <sys/types.h>
#include "net.h"
#include "mtproto-common.h"
#include "structures.h"
// Export functions for plugins
int tg_login ();
void running_for_first_time ();
void parse_config ();
void store_config ();
void read_auth_file ();
/**
@ -40,6 +43,72 @@ int network_phone_is_registered();
*/
int network_client_is_registered();
/**
* Export the current registration to all available data centers
*/
void network_export_registration();
/**
* Fetch all unknown messages of the current session
*/
void session_get_difference();
/**
* Fetch all known contacts
*/
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 on_update_user_typing();
void on_update_chat_user_typing();
void on_update_user_status();
void on_update_user_name();
void on_update_user_photo();
void on_update_chat_participants();
/*
* Load known users and chats on connect
*/
void on_user_allocated();
void on_user_allocated(void (*handler)(peer_t *user));
void event_user_allocated(peer_t *user);
void on_chat_allocated(void (*handler)(peer_t *chat));
void event_chat_allocated(peer_t *chat);
// template
//void on_blarg(void (*on_msg)(struct message *M));
//void event_blarg(struct message *M);
void on_chat_allocated();
/**
* Set a function to use as a handle to read from a network resource
* instead of the regular socket read function
*/
void set_net_read_cb(int (*cb)(int fd, void *buff, size_t size));
/**
* Set a function to use as handle to write to a newtork resource
* instead of the regular socket write function
*/
void set_net_write_cb(int (*cb)(int fd, const void *buff, size_t size));
/**
* Set a function to use as handle to create new connections instead of the regular
* socket write function
*/
void set_dc_ensure_session_cb (void (*dc_ens_sess)(struct dc *DC, void (*on_session_ready)(void)));
/**
* ?
*/
void set_default_username ();
// Settings
#define AUTH_MODE_SMS "sms"