diff --git a/App configuration.html b/App configuration.html new file mode 100644 index 0000000..e416b66 --- /dev/null +++ b/App configuration.html @@ -0,0 +1,177 @@ + + + + + App configuration + + + + + + + + + + +
+
+ +
+
+
+
+

App configuration

+
+ +
+ 16154 +
+
+
+ +
+ +
+ 99428c722d0ed59b9cd844e4577cb4bb +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +

alphanumeric, 5-32 characters

+
+
+ +
+

PUSH-notifications settings

+ +
+ + +
+
+ +
+

+ APNS certificates + +  Update +  Delete + +

+ + + + +
+ +

Available MTProto servers

+ +
+ +
+ 173.240.5.253:443 +

First DC

+
+
+
+ +
+ 173.240.5.1:443 +

First DC

+
+
+ +
+ +
+
-----BEGIN RSA PUBLIC KEY-----
+MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
+lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
+an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
+Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
+8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
+Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
+-----END RSA PUBLIC KEY-----
+
+
+ + +
+ + Cancel +
+
+
+ +
+
+
+ + + + + + + \ No newline at end of file diff --git a/Makefile.in b/Makefile.in index 6e37204..865eb7f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8,16 +8,16 @@ CFLAGS=@CFLAGS@ LDFLAGS=@LDFLAGS@ CPPFLAGS=@CPPFLAGS@ DEFS=@DEFS@ -COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Werror -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb +COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ LOCAL_LDFLAGS=-rdynamic -ggdb ${EXTRA_LIBS} LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} -HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/interface.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h ${srcdir}/tools.h ${srcdir}/lua-tg.h ${srcdir}/msglog.h +HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/mtproto-common.h ${srcdir}/net.h ${srcdir}/no-preview.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/config.h ${srcdir}/binlog.h ${srcdir}/tools.h ${srcdir}/msglog.h INCLUDE=-I. -I${srcdir} CC=@CC@ -OBJECTS=main.o loop.o interface.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o lua-tg.o msglog.o telegram.o +OBJECTS=loop.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o msglog.o telegram.o .SUFFIXES: .SUFFIXES: .c .h .o diff --git a/README.es b/README.es deleted file mode 100644 index ede5809..0000000 --- a/README.es +++ /dev/null @@ -1,142 +0,0 @@ -## Telegram messenger CLI [![Build Status](https://travis-ci.org/vysheng/tg.png)](https://travis-ci.org/vysheng/tg) - -Interfaz de línea de comandos para: [Telegram](http://telegram.org). Usa interfaz readline. - -### Documentación del API y el protocolo - -La documentación del APi de Telegram está disponible aquí: http://core.telegram.org/api - -La documentación del protocolo MTproto está disponible aquí: http://core.telegram.org/mtproto - -### Instalación - -Clona el Repositorio GitHub - - $ git clone https://github.com/vysheng/tg.git && cd tg - -o descarga y descomprime el zip - - $ wget https://github.com/vysheng/tg/archive/master.zip -O tg-master.zip - $ unzip tg-master.zip && cd tg-master - -#### Linux - -Librerías requeridas: readline openssl y (si desea usar config) libconfig y liblua. -Si no deseas usarlo, pasa las siguientes opciones --disable-libconfig y --disable-liblua respectivamente. - -En Ubuntu usa: - - $ sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev - -En gentoo: - - $ sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua - -En Fedora: - - $ sudo yum install lua-devel openssl-devel libconfig-devel readline-devel - -Por defecto Makefile utiliza liblua5.2 de ubuntu. Si utilizas una versión diferente de liblua o linux, tienes que ejecutar el script ./configure o recibirás un error de compilación extraño. - -Entonces - - $ ./configure - $ make - - -#### Mac OS X - -El cliente depende de [librería readline](http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html) y [libconfig](http://www.hyperrealm.com/libconfig/), las cuales no están incluídas en OS X por defecto. Debes instalar estas librerías de forma manual, usando por ejemplo [Homebrew](http://brew.sh/). - - $ brew install libconfig - $ brew install readline - $ brew install lua - $ export CFLAGS="-I/usr/local/include -I/usr/local/Cellar/readline/6.2.4/include" - $ export LDFLAGS="-L/usr/local/lib -L/usr/local/Cellar/readline/6.2.4/lib" - $ ./configure && make - -Gracias a [@jfontan](https://github.com/vysheng/tg/issues/3#issuecomment-28293731) por esta solución. - -#### FreeBSD - -Instalar estos puertos: - -* devel/libconfig -* devel/libexecinfo - -Entonces construir: - - $ env CC=clang CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure - $ make - -#### Otros UNIX - -Si logras ejecutarlo en otros UNIX, por favor házmelo saber. - - -### Uso - - ./telegram -k - - -Por defecto la clave pública se almacena en la misma carpeta con el nombre tg-server.pub o en /etc/telegram/server.pub, si no lo es, indica dónde encontrarlo: - - ./telegram -k tg-server.pub - -El Cliente soporta completamiento con TAB e historial de comandos. - -Peer se refiere al nombre del contacto o de diálogo y se puede acceder por completamiento con Tab. -Para los contactos de usuario el peer es el Nombre Apellido con todos los espacios cambiados a guiones bajos. -Para los chats es su título con todos los espacios cambiados a guiones bajos. -Para los chats encriptados es Nombre Apellido con todos los espacios cambiados a guiones bajos. - -Si dos o más peers tienen el mismo nombre, una almohadilla y un número es añadido al nombre. (por ejemplo A_B,A_B#1,A_B#2 y así sucesivamente). - -### Comandos soportados - -#### Mensajería - - -* **msg** \ texto - envía el mensaje a este usuario. -* **fwd** \ \ - reenviar un mensaje al usuario. Puedes ver los número de mensajes iniciando el Cliente con -N. -* **chat_with_peer** \ - inicia un chat con este usuario. /exit o /quit para salir de este modo. -* **add_contact** \ \ \ - intenta añadir este contacto a la lista de contactos. -* **rename_contact** \ \ \ - intenta renombrar el contacto. Si tienes otro dispositivo será una pelea. -* **mark_read** \ - marca todos los mensajes como recibidos de ese usuario. - -#### Multimedia - -* **send_photo** \ \ - manda una foto al usuario. -* **send_video** \ \ - envia un video al usuario. -* **send_text** \ \ - envia un archivo de texto como un mensaje en plano. -* **load_photo**/load_video/load_video_thumb \ - carga foto/video indicado del directorio de descarga. -* **view_photo**/view_video/view_video_thumb \ - carga foto/video indicado del directorio de descarga y lo abre con el visor por defecto del sistema. - - -#### Opciones de chat de grupo - -* **chat_info** \ - imprime información del chat. -* **chat_add_user** \ \ - agrega un usuario al chat. -* **chat_del_user** \ \ - elimina un usuario del chat. -* **rename_chat** \ \ - cambia el nombre al chat. - -#### Search - -* **search** \ patrón - busca el patrón indicado en los mensajes con ese usuario. -* **global_search** patrón - busca el patrón indicado en todos los mensajes. - -#### Chat secreto - -* **create_secret_chat** \ - crea un chat secreto con el usuario indicado. -* **visualize_key** \ - Muestra la clave de cifrado. Debes compararla con la del otro usuario. - -#### Estadísticas e información varia. - -* **user_info** \ - muestra información sobre el usuario. -* **history** \ [limit] - muestra el historial (y la marca como leído). Limite por defecto = 40. -* **dialog_list** - muestra información acerca del dialogo -* **contact_list** - muestra información acerca de tu lista de contactos. -* **suggested_contacts** - muestra información sobre sus contactos, tiene un máximo de amigos comunes. -* **stats** - solo para depuración. -* **show_license** - muestra la licencia GPLv2. -* **help** - imprime esta ayuda. diff --git a/README.md b/README.md index 296ee48..3abf83a 100644 --- a/README.md +++ b/README.md @@ -1,111 +1,252 @@ -telegram-purple -=============== - - -# Installieren - -1. Sicherstellen dass Pidgin installiert ist. -2. Dieses Git-Repository klonen. - - - git clone https://bitbucket.org/telegrampurple/telegram-purple - - -3. Im Ordner von **telegram-purple** make ausführen: - - - cd telgram-purple - ./configure --disable-liblua --disable-libconfig - make install - - -Das Protokoll Telegram sollte dann beim nächsten Start in der Accountverwaltung von Pidgin automatisch auftauchen. - - -# Testen und Debuggen - -Um **telegram-purple** während der Entwicklung zu testen, ist es sinnvoll vorher die Berechtigungen des Plugin-Ordners zu ändern, damit beim Kopieren nicht jedes Mal Root-Rechte benötigt werden: - - - sudo chmod 777 -R `pkg-config --variable=plugindir purple` - sudo chmod 777 -R `pkg-config --variable=datarootdir purple`pixmaps/pidgin/protocol - - -## Testen - - -Zum Compilen, Testen und Ausgeben aller Debugnachrichten folgenden Befehl ausführen: - - - make run - - -Falls die Lognachrichten nach kurzer Zeit nicht mehr angezeigt werden, und die Meldung "Wird geschlossen, da bereits ein andere libpurple-Client läuft" erscheint, die laufende Instanz von Pidgin mit folgendem Befehl beenden: - - - sudo killall pidgin - - - -### Filtern der Lognachrichten - -Wenn Pidgin einfach mit **make run** ausgeführt wird, werden alle Debugnachrichten des gesamten Programms ausgegegeben. Libpurple verwendet interne Loggingfunktionen die den Lognachrichten automatisch einen Prefix hinzufügen, z.B. "plugins:" für Nachrichten des Pluginsloaders und "prpl-telegram:" für Nachrichten dieses Plugins. - -Wenn man nur Ausgaben des Plugin-Loaders und von telegram-purple haben möchte kann man unnötige Nachrichten mit **grep** herausfiltern. - - - make run | grep -i 'prpl-telegram:\|plugins:' - - -# Deinstallieren - -Mit folgendem Befehl werden alle installierten Dateien wieder aus den Plugin-Ordnern gelöscht: - - - sudo make uninstall - - - -# Coding-Guidelines - -## Coding Style - -Wir wollen wenn möglichen den typischen Linux-C-Coding-Style verwenden. Bei Funktionen werden die Klammern auf der nächsten Zeile geschrieben, bei allem anderen auf der gleichen Zeile. Bei Funktionsargumenten zwischen Komma und dem nächsten Argument und nach Bedingungen von if/else-Blöcken immer ein Leerzeichen lassen. - - unsigned int some_function(int a, int b) - { - if (true) { - // ... - } else { - // ... - } - } - - -## Logging - -Wenn irgendeine Ausgabe gemacht wird, sollte das ausschließlich über die Libpurple Debugging-Funktionen passieren (Siehe die Anleitung zum Debuggen im [Libpurple-Howto](https://developer.pidgin.im/wiki/CHowTo/DebugAPIHowTo "Libpurple-HowTo")). - - - #include "debug.h" - #define PLUGIN_ID "prpl-telegram" - - // ... - - purple_debug_info(PLUGIN_ID, "Debugnachricht"); - - -## GIT -git pull -> Stand aktualisieren -git add -A -> Files hinzufügen -git push -> Stand hochladen -git commit -> Commiten - - - -## Troubleshooting - -Zum löschen der angelegten Accounts -rm /home/USER/.purple/accounts.xml - -Die lib muss eventuell nach /usr/lib/purple-2/telegram-purple.so kopiert werden \ No newline at end of file +telegram-purple +=============== + + +# Installieren + +1. Sicherstellen dass Pidgin installiert ist. +2. Dieses Git-Repository klonen. + + + git clone https://bitbucket.org/telegrampurple/telegram-purple + + +3. Im Ordner von **telegram-purple** make ausführen: + + + cd telgram-purple + ./configure --disable-liblua --disable-libconfig + make install + + +Das Protokoll Telegram sollte dann beim nächsten Start in der Accountverwaltung von Pidgin automatisch auftauchen. + + +# Testen und Debuggen + +Um **telegram-purple** während der Entwicklung zu testen, ist es sinnvoll vorher die Berechtigungen des Plugin-Ordners zu ändern, damit beim Kopieren nicht jedes Mal Root-Rechte benötigt werden: + + + sudo chmod 777 -R `pkg-config --variable=plugindir purple` + sudo chmod 777 -R `pkg-config --variable=datarootdir purple`pixmaps/pidgin/protocol + + +## Testen + + +Zum Compilen, Testen und Ausgeben aller Debugnachrichten folgenden Befehl ausführen: + + + make run + + +Falls die Lognachrichten nach kurzer Zeit nicht mehr angezeigt werden, und die Meldung "Wird geschlossen, da bereits ein andere libpurple-Client läuft" erscheint, die laufende Instanz von Pidgin mit folgendem Befehl beenden: + + + sudo killall pidgin + + + +### Filtern der Lognachrichten + +Wenn Pidgin einfach mit **make run** ausgeführt wird, werden alle Debugnachrichten des gesamten Programms ausgegegeben. Libpurple verwendet interne Loggingfunktionen die den Lognachrichten automatisch einen Prefix hinzufügen, z.B. "plugins:" für Nachrichten des Pluginsloaders und "prpl-telegram:" für Nachrichten dieses Plugins. + +Wenn man nur Ausgaben des Plugin-Loaders und von telegram-purple haben möchte kann man unnötige Nachrichten mit **grep** herausfiltern. + + + make run | grep -i 'prpl-telegram:\|plugins:' + + +# Deinstallieren + +Mit folgendem Befehl werden alle installierten Dateien wieder aus den Plugin-Ordnern gelöscht: + + + sudo make uninstall + + + +# Coding-Guidelines + +## Coding Style + +Wir wollen wenn möglichen den typischen Linux-C-Coding-Style verwenden. Bei Funktionen werden die Klammern auf der nächsten Zeile geschrieben, bei allem anderen auf der gleichen Zeile. Bei Funktionsargumenten zwischen Komma und dem nächsten Argument und nach Bedingungen von if/else-Blöcken immer ein Leerzeichen lassen. + + unsigned int some_function(int a, int b) + { + if (true) { + // ... + } else { + // ... + } + } + + +## Logging + +Wenn irgendeine Ausgabe gemacht wird, sollte das ausschließlich über die Libpurple Debugging-Funktionen passieren (Siehe die Anleitung zum Debuggen im [Libpurple-Howto](https://developer.pidgin.im/wiki/CHowTo/DebugAPIHowTo "Libpurple-HowTo")). + + + #include "debug.h" + #define PLUGIN_ID "prpl-telegram" + + // ... + + purple_debug_info(PLUGIN_ID, "Debugnachricht"); + + +## GIT +git pull -> Stand aktualisieren +git add -A -> Files hinzufügen +git push -> Stand hochladen +git commit -> Commiten + + + +## Troubleshooting + +Zum löschen der angelegten Accounts +rm /home/USER/.purple/accounts.xml + +Die lib muss eventuell nach /usr/lib/purple-2/telegram-purple.so kopiert werden +======= +telegram-purple +=============== + + +# Installieren + +1. Sicherstellen dass Pidgin installiert ist. +2. Dieses Git-Repository klonen. + + + git clone https://bitbucket.org/telegrampurple/telegram-purple + + +3. Im Ordner von **telegram-purple** make ausführen: + + + cd telgram-purple + ./configure --disable-liblua --disable-libconfig + make install + + +Das Protokoll Telegram sollte dann beim nächsten Start in der Accountverwaltung von Pidgin automatisch auftauchen. + + +# Testen und Debuggen + +Um **telegram-purple** während der Entwicklung zu testen, ist es sinnvoll vorher die Berechtigungen des Plugin-Ordners zu ändern, damit beim Kopieren nicht jedes Mal Root-Rechte benötigt werden: + + + sudo chmod 777 -R `pkg-config --variable=plugindir purple` + sudo chmod 777 -R `pkg-config --variable=datarootdir purple`pixmaps/pidgin/protocol + + +## Testen + + +Zum Compilen, Testen und Ausgeben aller Debugnachrichten folgenden Befehl ausführen: + + + make run + + +Falls die Lognachrichten nach kurzer Zeit nicht mehr angezeigt werden, und die Meldung "Wird geschlossen, da bereits ein andere libpurple-Client läuft" erscheint, die laufende Instanz von Pidgin mit folgendem Befehl beenden: + + + sudo killall pidgin + + + +# Deinstallieren + +Mit folgendem Befehl werden alle installierten Dateien wieder aus den Plugin-Ordnern gelöscht: + + + sudo make uninstall + + + +# Coding-Guidelines + +## Speicherverwaltung + +Glib verwendet eigene Datentypen und eigene Funktionen zu Speicherverwaltung. Wenn diese mit den regulären Funktionen von c vermischt werden, z.B. malloc und g\_free auf dem selben Pointer, kann die Anwendung abstürzen. + + + char *str = malloc(10); + g_free(str); // APPLICATION ERROR + + +Beim Purple-Plugin müssen wir die Typen und Verwaltungsfunktionen von glib verwenden, deshalb werden im Unterordner ./purple-plugin ausschließlich g\_alloc g\_new und g\_free zum allozieren und löschen von Objekten verwendet. Siehe ([https://developer.gnome.org/glib/2.30/glib-Memory-Allocation.html]) + +In Telegram-Cli werden keine glib-Funktionen verwendet, deshalb müssen wie hier ausschließlich die regulären C-Funktionen malloc und free verwenden. + +### Aufrufe von Telegram-CLI + +Wir rufen Telegram-CLI vom Purple-Plugin aus auf. Um die verschiedenen Sorten der Speicherverwaltung nicht zu vermischen, muss Telegram-CLI seinen gesamten Speicher selbst verwalten. Wenn strings oder Structs vom Plugin aus an die Bibliothek übergeben werden müssen die Objekte deshalb kopiert werden. + + + void *telegram_do_something(Telegram tg, const char* string) + { + char *dup = malloc(strlen(login) * sizeof(char)); + dup = memcpy(dup, string); + global->login = dup; + } + + +Jede Komponente der Anwendung muss deshalb den Speicher den sie alloziert auch selbst verwalten, da andere Komponenten diese niemals löschen werden. Wenn der String im Plugin mit einer allozierenden Funktion wie g\_strdup erstellt wurde, muss diese deshalb auch wieder mit g\_free gelöscht werden, da sonst ein Memory Leak entsteht. + + + gchar *str = g_strdup(string); + // ... + telegram_do_something(telegram, str); + // ... + g\_gree(str); + + + +## Coding Style + +Wir wollen wenn möglichen den typischen Linux-C-Coding-Style verwenden. Bei Funktionen werden die Klammern auf der nächsten Zeile geschrieben, bei allem anderen auf der gleichen Zeile. Bei Funktionsargumenten zwischen Komma und dem nächsten Argument und nach Bedingungen von if/else-Blöcken immer ein Leerzeichen lassen. + + unsigned int some_function(int a, int b) + { + if (true) { + // ... + } else { + // ... + } + } + + +## Logging + +Wenn irgendeine Ausgabe gemacht wird, sollte das ausschließlich über die Libpurple Debugging-Funktionen passieren (Siehe die Anleitung zum Debuggen im [Libpurple-Howto](https://developer.pidgin.im/wiki/CHowTo/DebugAPIHowTo "Libpurple-HowTo")). + + + #include "debug.h" + #define PLUGIN_ID "prpl-telegram" + + // ... + + purple_debug_info(PLUGIN_ID, "Debugnachricht"); + + +## GIT +git pull -> Stand aktualisieren +git add -A -> Files hinzufügen +git push -> Stand hochladen +git commit -> Commiten + + + +## Troubleshooting + +Zum löschen der angelegten Accounts +rm /home/USER/.purple/accounts.xml + +Die lib muss eventuell nach /usr/lib/purple-2/telegram-purple.so kopiert werden + + diff --git a/binlog.c b/binlog.c index b544876..13dd663 100644 --- a/binlog.c +++ b/binlog.c @@ -21,9 +21,6 @@ #include "config.h" #endif -#ifdef USE_LUA -# include "lua-tg.h" -#endif #include #include #include @@ -41,6 +38,7 @@ #include "net.h" #include "include.h" #include "mtproto-client.h" +#include "telegram.h" #include @@ -48,6 +46,7 @@ int binlog_buffer[BINLOG_BUFFER_SIZE]; int *rptr; int *wptr; +int test_dc = 0; extern int test_dc; extern int pts; @@ -58,11 +57,11 @@ extern int seq; #define MAX_LOG_EVENT_SIZE (1 << 17) char *get_binlog_file_name (void); -extern struct dc *DC_list[]; -extern struct dc *DC_working; -extern int dc_working_num; +//extern struct dc *DC_list[]; +//extern int dc_working_num; extern int our_id; extern int binlog_enabled; +int binlog_enabled = 0; extern int encr_root; extern unsigned char *encr_prime; extern int encr_param_version; @@ -76,7 +75,8 @@ void *alloc_log_event (int l UU) { long long binlog_pos; -void replay_log_event (void) { +void replay_log_event (struct telegram *instance) { + int *start = rptr; in_replay_log = 1; assert (rptr < wptr); @@ -104,7 +104,7 @@ void replay_log_event (void) { if (verbosity) { logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port); } - alloc_dc (id, tstrndup (ip, l2), port); + alloc_dc (instance->auth.DC_list, id, tstrndup (ip, l2), port); } rptr = in_ptr; break; @@ -113,12 +113,12 @@ void replay_log_event (void) { { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); - assert (DC_list[num]); - DC_list[num]->auth_key_id = *(long long *)rptr; + assert (instance->auth.DC_list[num]); + instance->auth.DC_list[num]->auth_key_id = *(long long *)rptr; rptr += 2; - memcpy (DC_list[num]->auth_key, rptr, 256); + memcpy (instance->auth.DC_list[num]->auth_key, rptr, 256); rptr += 64; - DC_list[num]->flags |= 1; + instance->auth.DC_list[num]->flags |= 1; }; break; case LOG_DEFAULT_DC: @@ -126,17 +126,13 @@ void replay_log_event (void) { { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); - DC_working = DC_list[num]; - dc_working_num = num; + instance->auth.dc_working_num = num; } break; case LOG_OUR_ID: rptr ++; { our_id = *(rptr ++); - #ifdef USE_LUA - lua_our_id (our_id); - #endif } break; case LOG_DC_SIGNED: @@ -144,8 +140,8 @@ void replay_log_event (void) { { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); - assert (DC_list[num]); - DC_list[num]->has_auth = 1; + assert (instance->auth.DC_list[num]); + instance->auth.DC_list[num]->has_auth = 1; } break; case LOG_DC_SALT: @@ -153,20 +149,20 @@ void replay_log_event (void) { { int num = *(rptr ++); assert (num >= 0 && num <= MAX_DC_ID); - assert (DC_list[num]); - DC_list[num]->server_salt = *(long long *)rptr; + assert (instance->auth.DC_list[num]); + instance->auth.DC_list[num]->server_salt = *(long long *)rptr; rptr += 2; }; break; -/* case CODE_user_empty: - case CODE_user_self: - case CODE_user_contact: - case CODE_user_request: - case CODE_user_foreign: +// case CODE_user_empty: +// case CODE_user_self: +// case CODE_user_contact: +// case CODE_user_request: +// case CODE_user_foreign: case CODE_user_deleted: fetch_alloc_user (); rptr = in_ptr; - break;*/ + break; case LOG_DH_CONFIG: get_dh_config_on_answer (0); rptr = in_ptr; @@ -293,9 +289,6 @@ void replay_log_event (void) { struct secret_chat *U = (void *)user_chat_get (id); assert (U); U->state = sc_ok; - #ifdef USE_LUA - lua_secret_chat_created (U); - #endif } break; case CODE_binlog_new_user: @@ -325,10 +318,6 @@ void replay_log_event (void) { if (fetch_int ()) { U->flags |= FLAG_USER_CONTACT; } - - #ifdef USE_LUA - lua_user_update (U); - #endif } rptr = in_ptr; break; @@ -359,10 +348,6 @@ void replay_log_event (void) { assert (U); if (U->user.phone) { tfree_str (U->user.phone); } U->user.phone = fetch_str_dup (); - - #ifdef USE_LUA - lua_user_update (&U->user); - #endif } rptr = in_ptr; break; @@ -409,10 +394,6 @@ void replay_log_event (void) { if (U->user.real_last_name) { tfree_str (U->user.real_last_name); } U->user.real_first_name = fetch_str_dup (); U->user.real_last_name = fetch_str_dup (); - - #ifdef USE_LUA - lua_user_update (&U->user); - #endif } rptr = in_ptr; break; @@ -613,10 +594,6 @@ void replay_log_event (void) { C->version = fetch_int (); fetch_data (&C->photo_big, sizeof (struct file_location)); fetch_data (&C->photo_small, sizeof (struct file_location)); - - #ifdef USE_LUA - lua_chat_update (C); - #endif }; rptr = in_ptr; break; @@ -643,9 +620,6 @@ void replay_log_event (void) { } C->print_title = create_print_name (C->id, C->title, 0, 0, 0); peer_insert_name ((void *)C); - #ifdef USE_LUA - lua_chat_update (C); - #endif }; rptr = in_ptr; break; @@ -665,9 +639,6 @@ void replay_log_event (void) { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.date = *(rptr ++); - #ifdef USE_LUA - lua_chat_update (&C->chat); - #endif }; break; case CODE_binlog_set_chat_version: @@ -677,9 +648,6 @@ void replay_log_event (void) { assert (C && (C->flags & FLAG_CREATED)); C->chat.version = *(rptr ++); C->chat.users_num = *(rptr ++); - #ifdef USE_LUA - lua_chat_update (&C->chat); - #endif }; break; case CODE_binlog_set_chat_admin: @@ -688,9 +656,6 @@ void replay_log_event (void) { peer_t *C = user_chat_get (MK_CHAT (*(rptr ++))); assert (C && (C->flags & FLAG_CREATED)); C->chat.admin_id = *(rptr ++); - #ifdef USE_LUA - lua_chat_update (&C->chat); - #endif }; break; case CODE_binlog_set_chat_participants: @@ -704,9 +669,6 @@ void replay_log_event (void) { C->chat.user_list = talloc (12 * C->chat.user_list_size); memcpy (C->chat.user_list, rptr, 12 * C->chat.user_list_size); rptr += 3 * C->chat.user_list_size; - #ifdef USE_LUA - lua_chat_update (&C->chat); - #endif }; break; case CODE_binlog_chat_full_photo: @@ -746,9 +708,6 @@ void replay_log_event (void) { C->user_list[C->user_list_size - 1].inviter_id = inviter; C->user_list[C->user_list_size - 1].date = date; C->user_list_version = version; - #ifdef USE_LUA - lua_chat_update (C); - #endif } break; case CODE_binlog_del_chat_participant: @@ -776,9 +735,6 @@ void replay_log_event (void) { C->user_list_size --; C->user_list = trealloc (C->user_list, 12 * C->user_list_size + 12, 12 * C->user_list_size); C->user_list_version = version; - #ifdef USE_LUA - lua_chat_update (C); - #endif } break; case CODE_binlog_create_message_text: @@ -828,10 +784,6 @@ void replay_log_event (void) { message_insert_unsent (M); M->flags |= FLAG_PENDING; } - - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -867,9 +819,6 @@ void replay_log_event (void) { M->out = get_peer_id (M->from_id) == our_id; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -903,9 +852,6 @@ void replay_log_event (void) { M->out = get_peer_id (M->from_id) == our_id; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -941,9 +887,6 @@ void replay_log_event (void) { M->out = get_peer_id (M->from_id) == our_id; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -979,9 +922,6 @@ void replay_log_event (void) { M->out = get_peer_id (M->from_id) == our_id; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -1010,9 +950,6 @@ void replay_log_event (void) { M->service = 1; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -1042,9 +979,6 @@ void replay_log_event (void) { M->service = 1; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -1074,9 +1008,6 @@ void replay_log_event (void) { M->service = 1; message_insert (M); - #ifdef USE_LUA - lua_new_msg (M); - #endif } rptr = in_ptr; break; @@ -1176,7 +1107,7 @@ void create_new_binlog (void) { } -void replay_log (void) { +void replay_log (struct telegram *instance) { if (access (get_binlog_file_name (), F_OK) < 0) { printf ("No binlog found. Creating new one\n"); create_new_binlog (); @@ -1210,7 +1141,7 @@ void replay_log (void) { wptr += (k / 4); } if (wptr == rptr) { break; } - replay_log_event (); + replay_log_event (instance); } close (fd); } @@ -1240,7 +1171,8 @@ void add_log_event (const int *data, int len) { wptr = rptr + (len / 4); int *in = in_ptr; int *end = in_end; - replay_log_event (); + // TODO: + //replay_log_event (); if (rptr != wptr) { logprintf ("Unread %lld ints. Len = %d\n", (long long)(wptr - rptr), len); assert (rptr == wptr); @@ -1381,8 +1313,8 @@ void bl_do_set_user_friend (struct user *U, int friend) { add_log_event (ev, 12); } -void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port) { - struct dc *DC = DC_list[id]; +void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port, struct telegram *instance) { + struct dc *DC = instance->auth.DC_list[id]; if (DC) { return; } clear_packet (); diff --git a/binlog.h b/binlog.h index d0d2d9b..c72699a 100644 --- a/binlog.h +++ b/binlog.h @@ -20,6 +20,7 @@ #define __BINLOG_H__ #include "structures.h" +#include "telegram.h" #define LOG_START 0x8948329a #define LOG_AUTH_KEY 0x984932aa @@ -84,12 +85,12 @@ #define CODE_binlog_delete_msg 0xa1d6ab6d void *alloc_log_event (int l); -void replay_log (void); +void replay_log (struct telegram *instance); void add_log_event (const int *data, int l); void write_binlog (void); void bl_do_set_auth_key_id (int num, unsigned char *buf); -void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port); +void bl_do_dc_option (int id, int l1, const char *name, int l2, const char *ip, int port, struct telegram *instance); void bl_do_set_our_id (int id); void bl_do_new_user (int id, const char *f, int fl, const char *l, int ll, long long access_token, const char *p, int pl, int contact); diff --git a/interface.c b/interface.c index 6560f9c..1cf7d34 100644 --- a/interface.c +++ b/interface.c @@ -40,7 +40,6 @@ #include "include.h" #include "queries.h" -#include "interface.h" #include "telegram.h" #include "structures.h" @@ -63,7 +62,7 @@ int safe_quit; int in_readline; int readline_active; -int log_level; +int log_level = 1; long long cur_uploading_bytes; long long cur_uploaded_bytes; @@ -1183,13 +1182,6 @@ void print_end (void) { prompt_was = 0; } -void hexdump (int *in_ptr, int *in_end) { - print_start (); - int *ptr = in_ptr; - while (ptr < in_end) { printf (" %08x", *(ptr ++)); } - printf ("\n"); - print_end (); -} /* void logprintf (const char *format, ...) { diff --git a/loop.c b/loop.c index dae5586..fd29ca3 100644 --- a/loop.c +++ b/loop.c @@ -43,7 +43,6 @@ #include #include -#include "interface.h" #include "net.h" #include "mtproto-client.h" #include "mtproto-common.h" @@ -59,10 +58,9 @@ // -extern char *default_username; + extern char *auth_token; extern int test_dc; -void set_default_username (const char *s); int default_dc_num; extern int binlog_enabled; @@ -74,6 +72,7 @@ extern int queries_num; int unread_messages; void got_it (char *line, int len); +/* void net_loop (int flags, int (*is_end)(void)) { logprintf("starting net_loop()\n"); while (!is_end ()) { @@ -131,6 +130,7 @@ void net_loop (int flags, int (*is_end)(void)) { } } } +*/ char **_s; size_t *_l; @@ -167,13 +167,12 @@ int main_loop (void) { } -struct dc *DC_list[MAX_DC_ID + 1]; -struct dc *DC_working; -int dc_working_num; -int auth_state; +//struct dc *DC_list[MAX_DC_ID + 1]; +//struct dc *DC_working; +//int dc_working_num; +//int auth_state; char *get_auth_key_filename (void); char *get_state_filename (void); -char *get_secret_chat_filename (void); int zero[512]; @@ -195,36 +194,32 @@ void write_dc (int auth_file_fd, struct dc *DC) { int our_id; -void store_config () { - write_auth_file(); -} - -void write_auth_file (void) { +void write_auth_file (struct authorization_state state, const char *filename) { if (binlog_enabled) { return; } - int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); + int auth_file_fd = open (filename /*get_auth_key_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, &dc_working_num, 4) == 4); - assert (write (auth_file_fd, &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 (DC_list[i]) { + if (state.DC_list[i]) { x = 1; assert (write (auth_file_fd, &x, 4) == 4); - write_dc (auth_file_fd, 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, &our_id, 4) == 4); + assert (write (auth_file_fd, &state.our_id, 4) == 4); close (auth_file_fd); } -void read_dc (int auth_file_fd, int id, unsigned ver) { +void read_dc (int auth_file_fd, int id, unsigned ver, struct dc *DC_list[]) { int port = 0; assert (read (auth_file_fd, &port, 4) == 4); int l = 0; @@ -233,7 +228,7 @@ void read_dc (int auth_file_fd, int id, unsigned ver) { char *ip = talloc (l + 1); assert (read (auth_file_fd, ip, l) == l); ip[l] = 0; - struct dc *DC = alloc_dc (id, ip, port); + struct dc *DC = alloc_dc (DC_list, id, ip, port); 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); @@ -250,19 +245,24 @@ void read_dc (int auth_file_fd, int id, unsigned ver) { } } -void empty_auth_file (void) { - alloc_dc (1, tstrdup (test_dc ? TG_SERVER_TEST : TG_SERVER), 443); - dc_working_num = 1; - auth_state = 0; - write_auth_file (); + +void empty_auth_file (struct authorization_state *state, const char *filename) { + 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); } -int need_dc_list_update; -void read_auth_file (void) { - if (binlog_enabled) { return; } - int auth_file_fd = open (get_auth_key_filename (), O_CREAT | O_RDWR, 0600); +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; + + if (binlog_enabled) { return state; } + int auth_file_fd = open (filename /*get_auth_key_filename ()*/, O_CREAT | O_RDWR, 0600); if (auth_file_fd < 0) { - empty_auth_file (); + empty_auth_file (&state, filename); } assert (auth_file_fd >= 0); @@ -272,81 +272,91 @@ void read_auth_file (void) { unsigned m; if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC && m != DC_SERIALIZED_MAGIC_V2)) { close (auth_file_fd); - empty_auth_file (); - return; + empty_auth_file (&state, filename); + return state; } assert (read (auth_file_fd, &x, 4) == 4); assert (x <= MAX_DC_ID); - assert (read (auth_file_fd, &dc_working_num, 4) == 4); - assert (read (auth_file_fd, &auth_state, 4) == 4); + assert (read (auth_file_fd, &state.dc_working_num, 4) == 4); + assert (read (auth_file_fd, &state.auth_state, 4) == 4); if (m == DC_SERIALIZED_MAGIC) { - auth_state = 700; + state.auth_state = 700; } int i; for (i = 0; i <= (int)x; i++) { int y; assert (read (auth_file_fd, &y, 4) == 4); if (y) { - read_dc (auth_file_fd, i, m); + read_dc (auth_file_fd, i, m, state.DC_list); } } - int l = read (auth_file_fd, &our_id, 4); + int l = read (auth_file_fd, &state.our_id, 4); if (l < 4) { assert (!l); } close (auth_file_fd); - DC_working = DC_list[dc_working_num]; + struct dc *DC_working = state.DC_list[state.dc_working_num]; if (m == DC_SERIALIZED_MAGIC) { DC_working->has_auth = 1; } + return state; } int pts, qts, seq, last_date; -void read_state_file (void) { - if (binlog_enabled) { return; } - int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); +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; + + if (binlog_enabled) { return state; } + int state_file_fd = open (filename/*get_state_filename ()*/, O_CREAT | O_RDWR, 0600); if (state_file_fd < 0) { - return; + return state; } int version, magic; - if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return; } - if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return; } - if (read (state_file_fd, &version, 4) < 4) { close (state_file_fd); return; } + if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return state; } + if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return state; } + if (read (state_file_fd, &version, 4) < 4) { close (state_file_fd); return state; } assert (version >= 0); int x[4]; if (read (state_file_fd, x, 16) < 16) { close (state_file_fd); - return; + return state; } - pts = x[0]; - qts = x[1]; - seq = x[2]; - last_date = x[3]; + state.pts = x[0]; + state.qts = x[1]; + state.seq = x[2]; + state.last_date = x[3]; close (state_file_fd); + return state; } -void write_state_file (void) { +void write_state_file (struct protocol_state state, const char* filename) { if (binlog_enabled) { return; } + /* static int wseq; static int wpts; static int wqts; static int wdate; if (wseq >= seq && wpts >= pts && wqts >= qts && wdate >= last_date) { return; } - int state_file_fd = open (get_state_filename (), O_CREAT | O_RDWR, 0600); + */ + int state_file_fd = open (filename /*get_state_filename ()*/, O_CREAT | O_RDWR, 0600); if (state_file_fd < 0) { return; } int x[6]; x[0] = STATE_FILE_MAGIC; x[1] = 0; - x[2] = pts; - x[3] = qts; - x[4] = seq; - x[5] = 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; + //wseq = seq; wpts = pts; wqts = qts; wdate = last_date; } extern peer_t *Peers[]; @@ -357,9 +367,11 @@ extern unsigned char *encr_prime; extern int encr_param_version; extern int dialog_list_got; -void read_secret_chat_file (void) { +// TODO: Refactor +void read_secret_chat_file (const char *file) { + if (binlog_enabled) { return; } - int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); + int fd = open (file, O_CREAT | O_RDWR, 0600); if (fd < 0) { return; } @@ -414,9 +426,10 @@ void read_secret_chat_file (void) { close (fd); } -void write_secret_chat_file (void) { +// TODO: Refactor +void write_secret_chat_file (const char *filename) { if (binlog_enabled) { return; } - int fd = open (get_secret_chat_filename (), O_CREAT | O_RDWR, 0600); + int fd = open (filename, O_CREAT | O_RDWR, 0600); if (fd < 0) { return; } @@ -483,39 +496,31 @@ int readline_active; int new_dc_num; int wait_dialog_list; + /** * Discover the network and authorise with all data centers - */ -void network_connect (void) { +void network_connect (struct telegram *instance) { verbosity = 0; on_start (); - if (binlog_enabled) { - double t = get_double_time (); - logprintf ("replay log start\n"); - replay_log (); - logprintf ("replay log end in %lf seconds\n", get_double_time () - t); - write_binlog (); - #ifdef USE_LUA - lua_binlog_end (); - #endif - } else { - read_auth_file (); - } - logprintf("update prompt()\n"); - update_prompt (); - logprintf("update prompt() done... \n"); + // will return empty default values on empty files + instance->auth = read_auth_file ("/home/dev-jessie/.telegram/auth_file"); + instance->proto = read_state_file ("/home/dev-jessie/.telegram/auth_file"); + + struct dc *DC_list = (struct dc*)instance->auth.DC_list; + struct dc *DC_working = NULL; assert (DC_list[dc_working_num]); if (!DC_working || !DC_working->auth_key_id) { // if (auth_state == 0) { logprintf("No working DC or not start_loopd.\n"); - DC_working = DC_list[dc_working_num]; + DC_working = &DC_list[instance->auth.dc_working_num]; assert (!DC_working->auth_key_id); dc_authorize (DC_working); assert (DC_working->auth_key_id); auth_state = 100; - write_auth_file (); + write_auth_file (instance->auth); logprintf("Authorized DataCentre: auth_key_id: %lld \n", DC_working->auth_key_id); + } else { } if (verbosity) { @@ -528,62 +533,37 @@ void network_connect (void) { if (verbosity) { logprintf ("DC_info: %d new DC got\n", new_dc_num); } - int i; - for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->auth_key_id) { - logprintf("DataCentre %d not start_loopd, authorizing...\n", i); - dc_authorize (DC_list[i]); - assert (DC_list[i]->auth_key_id); - 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_state_file (); read_secret_chat_file (); } + */ /** * Return if the given phone is registered */ + /* int network_phone_is_registered() { int res = do_auth_check_phone (default_username); assert(res >= 0); return res; } - +*/ /** - * Return if the current client is registered. + * Return whether the current client is registered. */ -int network_client_is_registered() { - return !(auth_state == 100 || !(DC_working->has_auth)); +int network_client_is_registered(struct telegram *tg) { + return !(tg->auth.auth_state == 100 || !(telegram_get_working_dc(tg)->has_auth)); } -/** - * Request a verification for the given client, by sending - * a code to the current phone number - */ -char* network_request_registration () -{ - return do_send_code (default_username); -} - -/** - * Request a verification for the given client, by sending - * a code to the current phone number - */ -char* network_request_phone_registration () -{ - return do_send_code (default_username); -} - - /** * Verify the phone number by providing the sms_code and the real name * * NOTE: This should be called when the phone number was previously * unknown to the telegram network. */ + /* int network_verify_phone_registration(const char* code, const char *sms_hash, const char *first ,const char *last) { @@ -596,10 +576,12 @@ int network_verify_phone_registration(const char* code, const char *sms_hash, } 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); @@ -611,145 +593,148 @@ int network_verify_registration(const char *code, const char *sms_hash) } return 0; } +*/ /** * Export current authentication state to all known data centers. */ -void network_export_registration() -{ - int i; - for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->has_auth) { - do_export_auth (i); - do_import_auth (i); - bl_do_dc_signed (i); - write_auth_file (); - } - write_auth_file (); - fflush (stdout); - fflush (stderr); -} +//void network_export_registration() +//{ +// int i; +// for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->has_auth) { +// do_export_auth (i); +// do_import_auth (i); +// bl_do_dc_signed (i); +// write_auth_file (); +// } +// write_auth_file (); +// fflush (stdout); +// fflush (stderr); +//} -int start_loop (char* code, char* auth_mode) { - logprintf("Calling start_loop()\n"); - logprintf("auth_state %i\n", auth_state); - if (auth_state == 100 || !(DC_working->has_auth)) { - logprintf("auth_state == 100 || !(DC_working->has_auth)"); - int res = do_auth_check_phone (default_username); - assert (res >= 0); - logprintf ("%s\n", res > 0 ? "phone registered" : "phone not registered"); - if (res > 0 && !register_mode) { - // Register Mode 1 - logprintf ("Register Mode 1\n"); - if (code) { - /* - if (do_send_code_result (code) >= 0) { - logprintf ("Authentication successfull, state = 300\n"); - auth_state = 300; - } - */ - } else { - logprintf("No code given, attempting to register\n"); - // Send Code - logprintf ("auth mode %s\n", auth_mode); - /* - if (strcmp(TELEGRAM_AUTH_MODE_SMS"sms", auth_mode)) { - */ - do_send_code (default_username); - logprintf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); - logprintf("storing current state in auth file...\n"); - write_auth_file (); - logprintf("exitting...\n"); - return 0; - /* - } else { - logprintf ("You typed \"call\", switching to phone system.\n"); - do_phone_call (default_username); - logprintf ("Calling you!"); - } - */ - } - } else { - logprintf ("User is not registered. Do you want to register? [Y/n] "); - logprintf ("ERROR THIS IS NOT POSSIBLE!\n"); - return 1; - // Register Mode 2 - // TODO: Requires first and last name, decide how to handle this. - // - We need some sort of switch between registration modes - // - When this mode is selected First and Last name should be added to the form - // Currently Requires Manuel Entry in Terminal. - size_t size; - char *first_name; - logprintf ("First name: "); - if (net_getline (&first_name, &size) == -1) { - perror ("getline()"); - exit (EXIT_FAILURE); - } - char *last_name; - logprintf ("Last name: "); - if (net_getline (&last_name, &size) == -1) { - perror ("getline()"); - exit (EXIT_FAILURE); - } - - int dc_num = do_get_nearest_dc (); - assert (dc_num >= 0 && dc_num <= MAX_DC_NUM && DC_list[dc_num]); - dc_working_num = dc_num; - DC_working = DC_list[dc_working_num]; - - if (*code) { - if (do_send_code_result_auth (code, "-", first_name, last_name) >= 0) { - auth_state = 300; - } - } else { - if (strcmp(TELEGRAM_AUTH_MODE_SMS, auth_mode)) { - do_send_code (default_username); - logprintf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); - } else { - logprintf ("You typed \"call\", switching to phone system.\n"); - do_phone_call (default_username); - logprintf ("Calling you! Code: "); - } - } - } - } - logprintf("Authentication done\n"); - - int i; - for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->has_auth) { - do_export_auth (i); - do_import_auth (i); - bl_do_dc_signed (i); - write_auth_file (); - } - write_auth_file (); - - 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 (); - net_loop (0, dgot); - #ifdef USE_LUA - lua_diff_end (); - #endif - send_all_unsent (); - - do_get_dialog_list (); - if (wait_dialog_list) { - dialog_list_got = 0; - net_loop (0, dlgot); - } - - return 0; //main_loop (); -} +//int start_loop (char* code, char* auth_mode) { +// logprintf("Calling start_loop()\n"); +// logprintf("auth_state %i\n", auth_state); +// if (auth_state == 100 || !(DC_working->has_auth)) { +// logprintf("auth_state == 100 || !(DC_working->has_auth)"); +// int res = do_auth_check_phone (default_username); +// assert (res >= 0); +// logprintf ("%s\n", res > 0 ? "phone registered" : "phone not registered"); +// if (res > 0 && !register_mode) { +// // Register Mode 1 +// logprintf ("Register Mode 1\n"); +// if (code) { +// /* +// if (do_send_code_result (code) >= 0) { +// logprintf ("Authentication successfull, state = 300\n"); +// auth_state = 300; +// } +// */ +// } else { +// logprintf("No code given, attempting to register\n"); +// // Send Code +// logprintf ("auth mode %s\n", auth_mode); +// /* +// if (strcmp(TELEGRAM_AUTH_MODE_SMS"sms", auth_mode)) { +// */ +// do_send_code (default_username); +// logprintf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); +// logprintf("storing current state in auth file...\n"); +// write_auth_file (); +// logprintf("exitting...\n"); +// return 0; +// /* +// } else { +// logprintf ("You typed \"call\", switching to phone system.\n"); +// do_phone_call (default_username); +// logprintf ("Calling you!"); +// } +// */ +// } +// } else { +// logprintf ("User is not registered. Do you want to register? [Y/n] "); +// logprintf ("ERROR THIS IS NOT POSSIBLE!\n"); +// return 1; +// // Register Mode 2 +// // TODO: Requires first and last name, decide how to handle this. +// // - We need some sort of switch between registration modes +// // - When this mode is selected First and Last name should be added to the form +// // Currently Requires Manuel Entry in Terminal. +// size_t size; +// char *first_name; +// logprintf ("First name: "); +// if (net_getline (&first_name, &size) == -1) { +// perror ("getline()"); +// exit (EXIT_FAILURE); +// } +// char *last_name; +// logprintf ("Last name: "); +// if (net_getline (&last_name, &size) == -1) { +// perror ("getline()"); +// exit (EXIT_FAILURE); +// } +// +// int dc_num = do_get_nearest_dc (); +// assert (dc_num >= 0 && dc_num <= MAX_DC_NUM && DC_list[dc_num]); +// dc_working_num = dc_num; +// DC_working = DC_list[dc_working_num]; +// +// if (*code) { +// if (do_send_code_result_auth (code, "-", first_name, last_name) >= 0) { +// auth_state = 300; +// } +// } else { +// if (strcmp(TELEGRAM_AUTH_MODE_SMS, auth_mode)) { +// do_send_code (default_username); +// logprintf ("Code from sms (if you did not receive an SMS and want to be called, type \"call\"): "); +// } else { +// logprintf ("You typed \"call\", switching to phone system.\n"); +// do_phone_call (default_username); +// logprintf ("Calling you! Code: "); +// } +// } +// } +// } +// logprintf("Authentication done\n"); +// +// int i; +// for (i = 0; i <= MAX_DC_NUM; i++) if (DC_list[i] && !DC_list[i]->has_auth) { +// do_export_auth (i); +// do_import_auth (i); +// bl_do_dc_signed (i); +// write_auth_file (); +// } +// write_auth_file (); +// +// 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 (); +// net_loop (0, dgot); +// #ifdef USE_LUA +// lua_diff_end (); +// #endif +// send_all_unsent (); +// +// do_get_dialog_list (); +// if (wait_dialog_list) { +// dialog_list_got = 0; +// net_loop (0, dlgot); +// } +// +// return 0; //main_loop (); +//} +/* int loop (void) { network_connect(); return start_loop(NULL, NULL); } +*/ diff --git a/loop.h b/loop.h index d09ef02..467b454 100644 --- a/loop.h +++ b/loop.h @@ -16,11 +16,36 @@ Copyright Vitaly Valtman 2013 */ + +#pragma once + +#include "net.h" + #ifndef __LOOP_H__ #define __LOOP_H__ int loop(); void net_loop (int flags, int (*end)(void)); -void write_auth_file (void); -void write_state_file (void); -void write_secret_chat_file (void); +void write_secret_chat_file (const char *filename); #endif + +struct protocol_state { + int pts; + int qts; + int seq; + int last_date; +}; + +struct authorization_state { + int dc_working_num; + int auth_state; + struct dc *DC_list[11]; + int our_id; +}; + +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); +struct protocol_state read_state_file (const char *filename); + +void on_start(); diff --git a/lua-tg.c b/lua-tg.c index 1d7b6e9..6ff996b 100644 --- a/lua-tg.c +++ b/lua-tg.c @@ -3,6 +3,7 @@ #endif #ifdef USE_LUA +/* #include "lua-tg.h" #include "include.h" @@ -16,7 +17,6 @@ lua_State *luaState; #include "structures.h" -#include "interface.h" #include "constants.h" #include "tools.h" #include "queries.h" @@ -545,5 +545,6 @@ void lua_init (const char *file) { exit (1); } } +*/ #endif diff --git a/lua-tg.h b/lua-tg.h index 35f3b09..6ea8faa 100644 --- a/lua-tg.h +++ b/lua-tg.h @@ -4,6 +4,7 @@ #include #include "structures.h" +/* void lua_init (const char *file); void lua_new_msg (struct message *M); void lua_our_id (int id); @@ -13,4 +14,5 @@ void lua_chat_update (struct chat *C); void lua_binlog_end (void); void lua_diff_end (void); void lua_do_all (void); +*/ #endif diff --git a/main.c b/main.c index 10b0018..ff68e14 100644 --- a/main.c +++ b/main.c @@ -50,7 +50,6 @@ #include "telegram.h" #include "loop.h" #include "mtproto-client.h" -#include "interface.h" #include "tools.h" #ifdef USE_LUA @@ -92,6 +91,7 @@ char *config_directory; char *binlog_file_name; int binlog_enabled; extern int log_level; +int log_level = 1; int sync_from_start; int allow_weak_random; diff --git a/msglog.c b/msglog.c index 0799b79..cbbbcc2 100644 --- a/msglog.c +++ b/msglog.c @@ -50,6 +50,12 @@ void logprintf(const char *format, ...) va_end (ap); } +void hexdump (int *in_ptr, int *in_end) { + int *ptr = in_ptr; + while (ptr < in_end) { printf (" %08x", *(ptr ++)); } + printf ("\n"); +} + /* TODO: implement different log levels diff --git a/msglog.h b/msglog.h index e574ba2..9d52637 100644 --- a/msglog.h +++ b/msglog.h @@ -11,6 +11,8 @@ void set_log_cb(void (*cb)(const char*, va_list ap)); */ void logprintf(const char *format, ...); +void hexdump (int *in_ptr, int *in_end); + /* void log_debug(const char* format, ...); void log_warning(const char* format, ...); diff --git a/mtproto-client.c b/mtproto-client.c index 827a50c..bda8bf7 100644 --- a/mtproto-client.c +++ b/mtproto-client.c @@ -50,7 +50,6 @@ #include "include.h" #include "queries.h" #include "loop.h" -#include "interface.h" #include "structures.h" #include "binlog.h" @@ -69,6 +68,7 @@ #define MAX_NET_RES (1L << 16) extern int log_level; +int log_level = 1; int verbosity; int auth_success; @@ -78,12 +78,14 @@ char new_nonce[256]; char server_nonce[256]; extern int binlog_enabled; extern int disable_auto_accept; +int disable_auto_accept = 0; extern int allow_weak_random; +int allow_weak_random = 0; int total_packets_sent; long long total_data_sent; - +/* int rpc_execute (struct connection *c, int op, int len); int rpc_becomes_ready (struct connection *c); int rpc_close (struct connection *c); @@ -93,6 +95,7 @@ struct connection_methods auth_methods = { .ready = rpc_becomes_ready, .close = rpc_close }; +*/ long long precise_time; @@ -218,7 +221,7 @@ int rpc_send_packet (struct connection *c) { } write_out (c, &unenc_msg_header, 20); write_out (c, packet_buffer, len); - flush_out (c); + //flush_out (c); total_packets_sent ++; total_data_sent += total_len; @@ -674,7 +677,6 @@ int process_auth_complete (struct connection *c UU, char *packet, int len) { } auth_success ++; GET_DC(c)->flags |= 1; - write_auth_file (); return 1; } @@ -778,7 +780,7 @@ int auth_work_start (struct connection *c UU) { return 1; } -void rpc_execute_answer (struct connection *c, long long msg_id UU); +void rpc_execute_answer (struct telegram *instance, long long msg_id UU); int unread_messages; int our_id; @@ -905,19 +907,19 @@ void work_update_binlog (void) { } } -void work_update (struct connection *c UU, long long msg_id UU) { +void work_update (struct connection *c UU, long long msg_id UU, struct telegram *instance) { unsigned op = fetch_int (); logprintf("work_update(): OP:%d\n", op); switch (op) { case CODE_update_new_message: { - struct message *M = fetch_alloc_message (); + struct message *M = fetch_alloc_message (instance); assert (M); fetch_pts (); unread_messages ++; event_update_new_message(M); - //print_message (M); - update_prompt (); + ////print_message (M); + //update_prompt (); break; }; case CODE_update_message_i_d: @@ -944,12 +946,12 @@ void work_update (struct connection *c UU, long long msg_id UU) { } fetch_pts (); if (log_level >= 1) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" %d messages marked as read\n", n); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } } break; @@ -958,14 +960,14 @@ void work_update (struct connection *c UU, long long msg_id UU) { peer_id_t id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (id); if (log_level >= 2) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (id, U); + //print_user_name (id, U); printf (" is typing....\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } } break; @@ -976,16 +978,16 @@ void work_update (struct connection *c UU, long long msg_id UU) { peer_t *C = user_chat_get (chat_id); peer_t *U = user_chat_get (id); if (log_level >= 2) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (id, U); + //print_user_name (id, U); printf (" is typing in chat "); - print_chat_name (chat_id, C); + //print_chat_name (chat_id, C); printf ("....\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } } break; @@ -996,15 +998,15 @@ void work_update (struct connection *c UU, long long msg_id UU) { if (U) { fetch_user_status (&U->user.status); if (log_level >= 3) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (user_id, U); + //print_user_name (user_id, U); printf (" is now "); printf ("%s\n", (U->user.status.online > 0) ? "online" : "offline"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } } else { struct user_status t; @@ -1023,16 +1025,16 @@ void work_update (struct connection *c UU, long long msg_id UU) { char *l = fetch_str (l2); struct user *U = &UC->user; bl_do_set_user_real_name (U, f, l1, l, l2); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (user_id, UC); + //print_user_name (user_id, UC); printf (" changed name to "); - print_user_name (user_id, UC); + //print_user_name (user_id, UC); printf ("\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } else { fetch_skip_str (); fetch_skip_str (); @@ -1064,14 +1066,14 @@ void work_update (struct connection *c UU, long long msg_id UU) { } bl_do_set_user_profile_photo (U, photo_id, &big, &small); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (user_id, UC); + //print_user_name (user_id, UC); printf (" updated profile photo\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } else { struct file_location t; unsigned y = fetch_int (); @@ -1090,12 +1092,12 @@ void work_update (struct connection *c UU, long long msg_id UU) { { assert (fetch_int () == CODE_vector); int n = fetch_int (); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Restored %d messages\n", n); - pop_color (); - print_end (); + //pop_color (); + //print_end (); fetch_skip (n); fetch_pts (); } @@ -1104,12 +1106,12 @@ void work_update (struct connection *c UU, long long msg_id UU) { { assert (fetch_int () == CODE_vector); int n = fetch_int (); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Deleted %d messages\n", n); - pop_color (); - print_end (); + //pop_color (); + //print_end (); fetch_skip (n); fetch_pts (); } @@ -1146,18 +1148,18 @@ void work_update (struct connection *c UU, long long msg_id UU) { fetch_int (); // version } } - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Chat "); - print_chat_name (chat_id, C); + //print_chat_name (chat_id, C); if (x == CODE_chat_participants) { printf (" changed list: now %d members\n", n); } else { printf (" changed list, but we are forbidden to know about it (Why this update even was sent to us?\n"); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); } break; case CODE_update_contact_registered: @@ -1165,28 +1167,28 @@ void work_update (struct connection *c UU, long long msg_id UU) { peer_id_t user_id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (user_id); fetch_int (); // date - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (user_id, U); + //print_user_name (user_id, U); printf (" registered\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } break; case CODE_update_contact_link: { peer_id_t user_id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (user_id); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Updated link with user "); - print_user_name (user_id, U); + //print_user_name (user_id, U); printf ("\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); unsigned t = fetch_int (); assert (t == CODE_contacts_my_link_empty || t == CODE_contacts_my_link_requested || t == CODE_contacts_my_link_contact); if (t == CODE_contacts_my_link_requested) { @@ -1203,14 +1205,14 @@ void work_update (struct connection *c UU, long long msg_id UU) { { peer_id_t user_id = MK_USER (fetch_int ()); peer_t *U = user_chat_get (user_id); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" User "); - print_user_name (user_id, U); + //print_user_name (user_id, U); printf (" activated\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } break; case CODE_update_new_authorization: @@ -1219,31 +1221,31 @@ void work_update (struct connection *c UU, long long msg_id UU) { fetch_int (); // date char *s = fetch_str_dup (); char *location = fetch_str_dup (); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" New autorization: device='%s' location='%s'\n", s, location); - pop_color (); - print_end (); + //pop_color (); + //print_end (); tfree_str (s); tfree_str (location); } break; case CODE_update_new_geo_chat_message: { - struct message *M = fetch_alloc_geo_message (); + struct message *M = fetch_alloc_geo_message (instance); unread_messages ++; - print_message (M); - update_prompt (); + //print_message (M); + //update_prompt (); } break; case CODE_update_new_encrypted_message: { - struct message *M = fetch_alloc_encrypted_message (); + struct message *M = fetch_alloc_encrypted_message (instance); unread_messages ++; - print_message (M); - update_prompt (); + //print_message (M); + //update_prompt (); fetch_qts (); } break; @@ -1253,37 +1255,37 @@ void work_update (struct connection *c UU, long long msg_id UU) { if (verbosity >= 2) { logprintf ("Secret chat state = %d\n", E->state); } - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); switch (E->state) { case sc_none: break; case sc_waiting: printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); + //print_encr_chat_name (E->id, (void *)E); printf (" is now in wait state\n"); break; case sc_request: printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); + //print_encr_chat_name (E->id, (void *)E); printf (" is now in request state. Sending request ok\n"); break; case sc_ok: printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); + //print_encr_chat_name (E->id, (void *)E); printf (" is now in ok state\n"); break; case sc_deleted: printf (" Encrypted chat "); - print_encr_chat_name (E->id, (void *)E); + //print_encr_chat_name (E->id, (void *)E); printf (" is now in deleted state\n"); break; } - pop_color (); - print_end (); + //pop_color (); + //print_end (); if (E->state == sc_request && !disable_auto_accept) { - do_accept_encr_chat_request (E); + do_accept_encr_chat_request (instance, E); } fetch_int (); // date } @@ -1292,21 +1294,21 @@ void work_update (struct connection *c UU, long long msg_id UU) { { peer_id_t id = MK_ENCR_CHAT (fetch_int ()); peer_t *P = user_chat_get (id); - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); if (P) { printf (" User "); peer_id_t user_id = MK_USER (P->encr_chat.user_id); - print_user_name (user_id, user_chat_get (user_id)); + //print_user_name (user_id, user_chat_get (user_id)); printf (" typing in secret chat "); - print_encr_chat_name (id, P); + //print_encr_chat_name (id, P); printf ("\n"); } else { printf (" Some user is typing in unknown secret chat\n"); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); } break; case CODE_update_encrypted_messages_read: @@ -1328,14 +1330,14 @@ void work_update (struct connection *c UU, long long msg_id UU) { } } if (log_level >= 1) { - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Encrypted chat "); - print_encr_chat_name_full (id, user_chat_get (id)); + //print_encr_chat_name_full (id, user_chat_get (id)); printf (": %d messages marked read \n", x); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } } break; @@ -1351,18 +1353,18 @@ void work_update (struct connection *c UU, long long msg_id UU) { bl_do_chat_add_user (&C->chat, version, get_peer_id (user_id), get_peer_id (inviter_id), time (0)); } - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Chat "); - print_chat_name (chat_id, user_chat_get (chat_id)); + //print_chat_name (chat_id, user_chat_get (chat_id)); printf (": user "); - print_user_name (user_id, user_chat_get (user_id)); + //print_user_name (user_id, user_chat_get (user_id)); printf (" added by user "); - print_user_name (inviter_id, user_chat_get (inviter_id)); + //print_user_name (inviter_id, user_chat_get (inviter_id)); printf ("\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } break; case CODE_update_chat_participant_delete: @@ -1376,16 +1378,16 @@ void work_update (struct connection *c UU, long long msg_id UU) { bl_do_chat_del_user (&C->chat, version, get_peer_id (user_id)); } - print_start (); - push_color (COLOR_YELLOW); - print_date (time (0)); + //print_start (); + //push_color (COLOR_YELLOW); + //print_date (time (0)); printf (" Chat "); - print_chat_name (chat_id, user_chat_get (chat_id)); + //print_chat_name (chat_id, user_chat_get (chat_id)); printf (": user "); - print_user_name (user_id, user_chat_get (user_id)); + //print_user_name (user_id, user_chat_get (user_id)); printf (" deleted\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } break; case CODE_update_dc_options: @@ -1395,7 +1397,7 @@ void work_update (struct connection *c UU, long long msg_id UU) { assert (n >= 0); int i; for (i = 0; i < n; i++) { - fetch_dc_option (); + fetch_dc_option (instance); } } break; @@ -1405,19 +1407,21 @@ void work_update (struct connection *c UU, long long msg_id UU) { } } -void work_update_short (struct connection *c, long long msg_id) { +void work_update_short (struct telegram *instance, long long msg_id) { + struct connection *c = telegram_get_connection(instance); assert (fetch_int () == CODE_update_short); - work_update (c, msg_id); + work_update (c, msg_id, instance); fetch_date (); } -void work_updates (struct connection *c, long long msg_id) { +void work_updates (struct telegram *instance, long long msg_id) { + struct connection *c = telegram_get_connection(instance); assert (fetch_int () == CODE_updates); assert (fetch_int () == CODE_vector); int n = fetch_int (); int i; for (i = 0; i < n; i++) { - work_update (c, msg_id); + work_update (c, msg_id, instance); } assert (fetch_int () == CODE_vector); n = fetch_int (); @@ -1433,29 +1437,30 @@ void work_updates (struct connection *c, long long msg_id) { bl_do_set_seq (fetch_int ()); } -void work_update_short_message (struct connection *c UU, long long msg_id UU) { +void work_update_short_message (struct connection *c UU, long long msg_id UU, struct telegram *instance) { assert (fetch_int () == (int)CODE_update_short_message); - struct message *M = fetch_alloc_message_short (); + struct message *M = fetch_alloc_message_short (instance); unread_messages ++; - print_message (M); - update_prompt (); + //print_message (M); + //update_prompt (); if (M->date > last_date) { last_date = M->date; } } -void work_update_short_chat_message (struct connection *c UU, long long msg_id UU) { +void work_update_short_chat_message (struct connection *c UU, long long msg_id UU, struct telegram *instance) { assert (fetch_int () == CODE_update_short_chat_message); - struct message *M = fetch_alloc_message_short_chat (); + struct message *M = fetch_alloc_message_short_chat (instance); unread_messages ++; - print_message (M); - update_prompt (); + //print_message (M); + //update_prompt (); if (M->date > last_date) { last_date = M->date; } } -void work_container (struct connection *c, long long msg_id UU) { +void work_container (struct telegram *instance, long long msg_id UU) { + struct connection *c = telegram_get_connection(instance); if (verbosity) { logprintf ( "work_container: msg_id = %lld\n", msg_id); } @@ -1472,7 +1477,7 @@ void work_container (struct connection *c, long long msg_id UU) { int bytes = fetch_int (); int *t = in_end; in_end = in_ptr + (bytes / 4); - rpc_execute_answer (c, id); + rpc_execute_answer (instance, id); assert (in_ptr == in_end); in_end = t; } @@ -1487,7 +1492,6 @@ void work_new_session_created (struct connection *c, long long msg_id UU) { //DC->session_id = fetch_long (); fetch_long (); // unique_id GET_DC(c)->server_salt = fetch_long (); - } void work_msgs_ack (struct connection *c UU, long long msg_id UU) { @@ -1522,7 +1526,7 @@ void work_rpc_result (struct connection *c UU, long long msg_id UU) { } #define MAX_PACKED_SIZE (1 << 24) -void work_packed (struct connection *c, long long msg_id) { +void work_packed (struct telegram *instance, long long msg_id) { assert (fetch_int () == CODE_gzip_packed); static int in_gzip; static int buf[MAX_PACKED_SIZE >> 2]; @@ -1542,7 +1546,7 @@ void work_packed (struct connection *c, long long msg_id) { logprintf ( "Unzipped data: "); hexdump_in (); } - rpc_execute_answer (c, msg_id); + rpc_execute_answer (instance, msg_id); in_ptr = end; in_end = eend; in_gzip = 0; @@ -1579,10 +1583,10 @@ void work_new_detailed_info (struct connection *c UU, long long msg_id UU) { fetch_int (); // status } -void work_updates_to_long (struct connection *c UU, long long msg_id UU) { +void work_updates_to_long (struct telegram *instance, struct connection *c UU, long long msg_id UU) { assert (fetch_int () == (int)CODE_updates_too_long); logprintf ("updates to long... Getting difference\n"); - do_get_difference (); + do_get_difference (instance); } void work_bad_msg_notification (struct connection *c UU, long long msg_id UU) { @@ -1593,7 +1597,8 @@ void work_bad_msg_notification (struct connection *c UU, long long msg_id UU) { logprintf ("bad_msg_notification: msg_id = %lld, seq = %d, error = %d\n", m1, s, e); } -void rpc_execute_answer (struct connection *c, long long msg_id UU) { +void rpc_execute_answer (struct telegram *instance, long long msg_id UU) { + struct connection *c = telegram_get_connection(instance); if (verbosity >= 5) { logprintf ("rpc_execute_answer: fd=%d\n", c->fd); hexdump_in (); @@ -1601,7 +1606,7 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { int op = prefetch_int (); switch (op) { case CODE_msg_container: - work_container (c, msg_id); + work_container (instance, msg_id); return; case CODE_new_session_created: work_new_session_created (c, msg_id); @@ -1613,19 +1618,19 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { work_rpc_result (c, msg_id); return; case CODE_update_short: - work_update_short (c, msg_id); + work_update_short (instance, msg_id); return; case CODE_updates: - work_updates (c, msg_id); + work_updates (instance, msg_id); return; case CODE_update_short_message: - work_update_short_message (c, msg_id); + work_update_short_message (c, msg_id, instance); return; case CODE_update_short_chat_message: - work_update_short_chat_message (c, msg_id); + work_update_short_chat_message (c, msg_id, instance); return; case CODE_gzip_packed: - work_packed (c, msg_id); + work_packed (instance, msg_id); return; case CODE_bad_server_salt: work_bad_server_salt (c, msg_id); @@ -1640,7 +1645,7 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { work_new_detailed_info (c, msg_id); return; case CODE_updates_too_long: - work_updates_to_long (c, msg_id); + work_updates_to_long (instance, c, msg_id); return; case CODE_bad_msg_notification: work_bad_msg_notification (c, msg_id); @@ -1651,7 +1656,9 @@ void rpc_execute_answer (struct connection *c, long long msg_id UU) { in_ptr = in_end; // Will not fail due to assertion in_ptr == in_end } -int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, int len) { +int process_rpc_message (struct telegram *instance, struct encrypted_message *enc, int len) { + struct connection *c UU = telegram_get_connection(instance); + const int MINSZ = offsetof (struct encrypted_message, message); const int UNENCSZ = offsetof (struct encrypted_message, server_salt); if (verbosity) { @@ -1672,7 +1679,7 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, //assert (enc->server_salt == server_salt); //in fact server salt can change if (DC->server_salt != enc->server_salt) { DC->server_salt = enc->server_salt; - write_auth_file (); + //write_auth_file (); } int this_server_time = enc->msg_id >> 32LL; @@ -1710,81 +1717,121 @@ int process_rpc_message (struct connection *c UU, struct encrypted_message *enc, insert_msg_id (c->session, enc->msg_id); } assert (c->session->session_id == enc->session_id); - rpc_execute_answer (c, enc->msg_id); + rpc_execute_answer (instance, enc->msg_id); assert (in_ptr == in_end); return 0; } -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) { - assert (read_in (c, Response, Response_len) == Response_len); - return 0; - } - */ +//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) { +// 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); +// return 0; +// } +// +// int Response_len = len; +// +// if (verbosity >= 2) { +// logprintf ("Response_len = %d\n", Response_len); +// } +// assert (read_in (c, Response, Response_len) == Response_len); +// Response[Response_len] = 0; +// if (verbosity >= 2) { +// logprintf ( "have %d Response bytes\n", Response_len); +// } +// +// int o = c_state; +// if (GET_DC(c)->flags & 1) { o = st_authorized;} +// switch (o) { +// case st_reqpq_sent: +// process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/); +// return 0; +// case st_reqdh_sent: +// process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/); +// return 0; +// case st_client_dh_sent: +// process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/); +// return 0; +// case st_authorized: +// if (op < 0 && op >= -999) { +// logprintf ("Server error %d\n", op); +// } else { +// process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/); +// } +// return 0; +// default: +// logprintf ( "fatal: cannot receive answer in state %d\n", c_state); +// exit (2); +// } +// +// return 0; +//} +int rpc_execute_req_pq (struct telegram *instance, int len) { + 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); return 0; } - int Response_len = len; - - if (verbosity >= 2) { - logprintf ("Response_len = %d\n", Response_len); - } assert (read_in (c, Response, Response_len) == Response_len); Response[Response_len] = 0; - if (verbosity >= 2) { - logprintf ( "have %d Response bytes\n", Response_len); - } - -#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); -#endif - int o = c_state; - if (GET_DC(c)->flags & 1) { o = st_authorized;} - switch (o) { - case st_reqpq_sent: - process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/); -#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); -#endif - return 0; - case st_reqdh_sent: - process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/); -#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); -#endif - return 0; - case st_client_dh_sent: - process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/); -#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); -#endif - return 0; - case st_authorized: - if (op < 0 && op >= -999) { - logprintf ("Server error %d\n", op); - } else { - process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/); - } -#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); -#endif - return 0; - default: - logprintf ( "fatal: cannot receive answer in state %d\n", c_state); - exit (2); - } - + process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/); return 0; } +int rpc_execute_rq_dh (struct telegram *instance, int len) { + 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); + 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*/); + return 0; +} + +int rpc_execute_cdh_sent (struct telegram *instance, int len) { + 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); + 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*/); + return 0; +} + +int rpc_execute_authorized (struct telegram *instance, int op, int len) { + 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); + return 0; + } + int Response_len = len; + assert (read_in (c, Response, Response_len) == Response_len); + Response[Response_len] = 0; + if (op < 0 && op >= -999) { + logprintf ("Server error %d\n", op); + } else { + process_rpc_message (instance, (void *)(Response/* + 8*/), Response_len/* - 12*/); + } + return 0; +} + + int tc_close (struct connection *c, int who) { if (verbosity) { @@ -1799,11 +1846,7 @@ int tc_becomes_ready (struct connection *c) { } char byte = 0xef; assert (write_out (c, &byte, 1) == 1); - flush_out (c); -#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__) - setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4); -#endif int o = c_state; if (GET_DC(c)->flags & 1) { o = st_authorized; } switch (o) { @@ -1860,9 +1903,6 @@ int auth_ok (void) { void dc_authorize (struct dc *DC) { c_state = 0; auth_success = 0; - if (!DC->sessions[0]) { - dc_create_session (DC); - } if (verbosity) { logprintf ( "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port); } diff --git a/mtproto-client.h b/mtproto-client.h index 0782b7b..49f8891 100644 --- a/mtproto-client.h +++ b/mtproto-client.h @@ -30,4 +30,13 @@ int check_g (unsigned char p[256], BIGNUM *g); int check_g_bn (BIGNUM *p, BIGNUM *g); int check_DH_params (BIGNUM *p, int g); void secure_random (void *s, int l); + + +int send_req_pq_packet (struct telegram *instance); + +int rpc_execute_req_pq (struct telegram *instance, int len); +int rpc_execute_rq_dh (struct telegram *instance, int len); +int rpc_execute_cdh_sent (struct telegram *instance, int len); +int rpc_execute_authorized (struct telegram *instance, int op, int len); + #endif diff --git a/mtproto-common.c b/mtproto-common.c index 65c95eb..28027c4 100644 --- a/mtproto-common.c +++ b/mtproto-common.c @@ -39,7 +39,6 @@ #include #include "mtproto-common.h" -#include "interface.h" #include "include.h" #ifdef __MACH__ diff --git a/mtproto-common.h b/mtproto-common.h index 619be74..0dbf71d 100644 --- a/mtproto-common.h +++ b/mtproto-common.h @@ -26,9 +26,10 @@ #include #include -#include "interface.h" #include "tools.h" #include "constants.h" +#include "msglog.h" + /* DH key exchange protocol data structures */ #define CODE_req_pq 0x60469778 #define CODE_resPQ 0x05162463 diff --git a/net.c b/net.c index fe88e11..0570d65 100644 --- a/net.c +++ b/net.c @@ -1,12 +1,12 @@ /* This file is part of telegram-client. - Telegram-client is free software: you can redistribute it and/or modify + struct telegram-client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - Telegram-client is distributed in the hope that it will be useful, + struct telegram-client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -43,7 +43,7 @@ #include "mtproto-client.h" #include "mtproto-common.h" #include "tree.h" -#include "interface.h" +#include "telegram.h" #ifndef POLLRDHUP #define POLLRDHUP 0 @@ -55,7 +55,8 @@ double get_utime (int clock_id); int verbosity; extern struct connection_methods auth_methods; -extern FILE *log_net_f; +extern FILE *log_net_f ; +FILE *log_net_f = NULL; void fail_connection (struct connection *c); @@ -75,27 +76,6 @@ 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); @@ -254,8 +234,8 @@ void flush_out (struct connection *c UU) { } #define MAX_CONNECTIONS 100 -struct connection *Connections[MAX_CONNECTIONS]; -int max_connection_fd; +//struct connection *Connections[MAX_CONNECTIONS]; +//int max_connection_fd; void rotate_port (struct connection *c) { switch (c->port) { @@ -271,76 +251,23 @@ void rotate_port (struct connection *c) { } } -struct connection *create_connection (const char *host, int port, struct session *session, struct connection_methods *methods) { +struct connection *create_connection (const char *host, int port, int fd) { struct connection *c = talloc0 (sizeof (*c)); - int fd = socket (AF_INET, SOCK_STREAM, 0); - if (fd == -1) { - logprintf ("Can not create socket: %m\n"); - exit (1); - } - assert (fd >= 0 && fd < MAX_CONNECTIONS); - if (fd > max_connection_fd) { - max_connection_fd = fd; - } - int flags = -1; - setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags)); - setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof (flags)); - setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof (flags)); - - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons (port); - addr.sin_addr.s_addr = inet_addr (host); - - - fcntl (fd, F_SETFL, O_NONBLOCK); - - if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) { - if (errno != EINPROGRESS) { - logprintf ( "Can not connect to %s:%d %m\n", host, port); - close (fd); - tfree (c, sizeof (*c)); - return 0; - } - } - - struct pollfd s; - s.fd = fd; - s.events = POLLOUT | POLLERR | POLLRDHUP | POLLHUP; - errno = 0; - - while (poll (&s, 1, 10000) <= 0 || !(s.revents & POLLOUT)) { - if (errno == EINTR) { continue; } - if (errno) { - logprintf ("Problems in poll: %m\n"); - exit (1); - } - logprintf ("Connect with %s:%d timeout\n", host, port); - close (fd); - tfree (c, sizeof (*c)); - return 0; - } - - c->session = session; c->fd = fd; c->ip = tstrdup (host); c->flags = 0; c->state = conn_ready; - c->methods = methods; c->port = port; - assert (!Connections[fd]); - Connections[fd] = c; if (verbosity) { logprintf ( "connect to %s:%d successful\n", host, port); } - if (c->methods->ready) { - c->methods->ready (c); - } c->last_receive_time = get_double_time (); - start_ping_timer (c); + // Don't ping TODO: Really? Timeout callback functions of libpurple + //start_ping_timer (c); return c; } +/* void restart_connection (struct connection *c) { if (c->last_connect_time == time (0)) { start_fail_timer (c); @@ -415,9 +342,11 @@ void fail_connection (struct connection *c) { logprintf ("Lost connection to server... %s:%d\n", c->ip, c->port); restart_connection (c); } +*/ extern FILE *log_net_f; -void try_write (struct connection *c) { +void try_write (struct telegram *instance) { + struct connection *c = telegram_get_connection(instance); if (verbosity) { logprintf ( "try write: fd = %d\n", c->fd); } @@ -494,7 +423,9 @@ void hexdump_buf (struct connection_buffer *b) { } -void try_rpc_read (struct connection *c) { +void try_rpc_read (struct telegram *instance) { + struct connection *c = instance->auth.DC_list[instance->auth.dc_working_num]->sessions[0]->c; + assert (c->in_head); if (verbosity >= 3) { hexdump_buf (c->in_head); @@ -528,11 +459,15 @@ void try_rpc_read (struct connection *c) { len *= 4; int op; assert (read_in_lookup (c, &op, 4) == 4); - c->methods->execute (c, op, len); + // read + //c->methods->execute (c, op, len); + try_rpc_interpret(instance, op, len); } } -void try_read (struct connection *c) { +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); } @@ -587,10 +522,11 @@ void try_read (struct connection *c) { } c->in_bytes += x; if (x) { - try_rpc_read (c); + try_rpc_read (instance); } } +/* int connections_make_poll_array (struct pollfd *fds, int max) { int _max = max; int i; @@ -615,7 +551,9 @@ int connections_make_poll_array (struct pollfd *fds, int max) { } return _max - max; } +*/ +/* void connections_poll_result (struct pollfd *fds, int max) { if (verbosity >= 10) { logprintf ( "connections_poll_result: max = %d\n", max); @@ -643,6 +581,7 @@ void connections_poll_result (struct pollfd *fds, int max) { } } } +*/ int send_all_acks (struct session *S) { clear_packet (); @@ -672,7 +611,7 @@ void insert_msg_id (struct session *S, long long id) { extern struct dc *DC_list[]; -struct dc *alloc_dc (int id, char *ip, int port UU) { +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; @@ -682,16 +621,12 @@ struct dc *alloc_dc (int id, char *ip, int port UU) { return DC; } -void dc_create_session (struct dc *DC) { +void dc_create_session (struct dc *DC, struct connection *c) { logprintf("dc_create_session(...)\n"); struct session *S = talloc0 (sizeof (*S)); assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0); S->dc = DC; - S->c = create_connection (DC->ip, DC->port, S, &auth_methods); - if (!S->c) { - logprintf ("Can not create connection to DC. Is network down?\n"); - exit (1); - } + S->c = c; assert (!DC->sessions[0]); DC->sessions[0] = S; } diff --git a/net.h b/net.h index d89029f..10ec628 100644 --- a/net.h +++ b/net.h @@ -1,12 +1,12 @@ /* This file is part of telegram-client. - Telegram-client is free software: you can redistribute it and/or modify + struct telegram-client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - Telegram-client is distributed in the hope that it will be useful, + struct telegram-client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -19,9 +19,11 @@ #ifndef __NET_H__ #define __NET_H__ +#define MAX_DC_ID 10 #include struct dc; #include "queries.h" +#include "telegram.h" #define TG_SERVER "173.240.5.1" #define TG_SERVER_TEST "173.240.5.253" #define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74" @@ -31,7 +33,6 @@ struct dc; #define TG_VERSION "0.01-beta" #define ACK_TIMEOUT 1 -#define MAX_DC_ID 10 enum dc_state { st_init, @@ -40,7 +41,7 @@ enum dc_state { st_client_dh_sent, st_authorized, st_error -} ; +}; struct connection; struct connection_methods { @@ -125,7 +126,6 @@ struct connection { int out_packet_num; int last_connect_time; int in_fail_timer; - struct connection_methods *methods; struct session *session; void *extra; struct event_timer ev; @@ -140,12 +140,19 @@ 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, struct session *session, struct connection_methods *methods); +struct connection *create_connection (const char *host, int port, int fd); int connections_make_poll_array (struct pollfd *fds, int max); void connections_poll_result (struct pollfd *fds, int max); -void dc_create_session (struct dc *DC); void insert_msg_id (struct session *S, long long id); -struct dc *alloc_dc (int id, char *ip, int port); +struct dc *alloc_dc (struct dc* DC_list[], int id, char *ip, int port); + +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); #define GET_DC(c) (c->session->dc) #endif + diff --git a/purple-plugin/telegram-purple.c b/purple-plugin/telegram-purple.c index ea99879..4cf58c9 100644 --- a/purple-plugin/telegram-purple.c +++ b/purple-plugin/telegram-purple.c @@ -43,7 +43,7 @@ #include "prefs.h" #include "util.h" -// Telegram Includes +// struct telegram Includes #include "telegram.h" #include "msglog.h" #include "mtproto-client.h" @@ -60,15 +60,15 @@ static PurplePlugin *_telegram_protocol = NULL; -// TODO: Use PurpleConnection from PurpleAccount callback PurpleConnection *_gc; -// TODO: Use PurpleAccount from PurpleAccount callback PurpleAccount *_pa; PurpleGroup *tggroup; +void tgprpl_login_on_connected(); + /** - * Redirect the msglog of the telegram-cli application to the libpurple - * logger + * Formats the given format string with the given arguments and writes + * it to the libpurple log */ void tg_cli_log_cb(const char* format, va_list ap) { @@ -116,7 +116,7 @@ static void login_request_verification(PurpleAccount *acct) 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 Telegram has sent to you by SMS.", + "You need to verify this device, please enter the code struct telegram has sent to you by SMS.", NULL, NULL, NULL); } @@ -130,7 +130,116 @@ static void login_verification_fail(PurpleAccount *acct) purple_account_set_string(acct, "verification_key", ""); purple_notify_message(_telegram_protocol, PURPLE_NOTIFY_MSG_INFO, "Verification Failed", "Please make sure you entered the correct verification code.", NULL, NULL, NULL); - +} + +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); +} + +static void tgprpl_input_cb(gpointer data, gint source, PurpleInputCondition cond) +{ + logprintf("tgprpl_input_cb()\n"); + PurpleConnection *c = data; + telegram_conn *conn = purple_connection_get_protocol_data(c); + telegram_read_input(conn->tg); +} + +/* +static void tgprpl_on_input(struct telegram *tg) +{ + PurpleConnection *c = data; +} +*/ + +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; + } + network_verify_phone_registration(code, hash, first_name, last_name); + break; + + case STATE_PHONE_CODE_NOT_ENTERED: + purple_connection_set_state(_gc, PURPLE_CONNECTED); + // TODO: Request SMS code + break; + + case STATE_CLIENT_NOT_REGISTERED: + // ask for registration type + break; + + 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); + // 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); + 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); + DC->ip = g_strdup(purple_account_get_string(acc, "server", TELEGRAM_TEST_SERVER)); + DC->id = 0; } /** @@ -140,46 +249,58 @@ 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; - const char *username = purple_account_get_username(acct); - const char *code = purple_account_get_string(acct, "verification_key", NULL); - const char *hash = purple_account_get_string(acct, "verification_hash", NULL); - const char *hostname = purple_account_get_string(acct, "server", TELEGRAM_TEST_SERVER); - // const char *verificationType = purple_account_get_string(acct, "verification_type", TELEGRAM_AUTH_MODE_SMS); - // int port = purple_account_get_int(acct, "port", TELEGRAM_DEFAULT_PORT); + 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); purple_debug_info(PLUGIN_ID, "username: %s\n", username); - purple_debug_info(PLUGIN_ID, "code: %s\n", code); - purple_debug_info(PLUGIN_ID, "verification_hash: %s\n", hash); - purple_debug_info(PLUGIN_ID, "hostname: %s\n", hostname); + purple_debug_info(PLUGIN_ID, "hostname: %s\n", DC.ip); +} - // ensure config-file exists an - purple_debug_info(PLUGIN_ID, "running_for_first_time()\n"); - running_for_first_time(); +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; + //running_for_first_time(); - // 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); + if (fd == -1) { + logprintf("purple_proxy_connect failed: %s\n", error_message); + telegram_free(tg); + 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)); + telegram_network_connect(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 - purple_debug_info(PLUGIN_ID, "Connecting to the Telegram network...\n"); - network_connect(); - // Assure phone number registration + /* if (!network_phone_is_registered()) { - purple_debug_info(PLUGIN_ID, "Phone is not registered, registering...\n"); - const char *first_name = purple_account_get_string(acct, "first_name", NULL); - const char *last_name = purple_account_get_string(acct, "last_name", 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; - } if (code && strlen(code) > 0 && hash && strlen(hash) > 0) { int registered = network_verify_phone_registration(code, hash, first_name, last_name); if (registered) { @@ -193,8 +314,10 @@ static void tgprpl_login(PurpleAccount * acct) return; } } + */ // Assure client registration + /* if (!network_client_is_registered()) { purple_debug_info(PLUGIN_ID, "Client is not registered\n"); @@ -203,7 +326,6 @@ static void tgprpl_login(PurpleAccount * acct) purple_debug_info(PLUGIN_ID, "strlen - code: %lu hash: %lu\n", strlen(code), strlen(hash)); purple_debug_info(PLUGIN_ID, "pointer - code: %p hash: %p\n", code, hash); purple_debug_info(PLUGIN_ID, "string - code: %s hash: %s\n", code, hash); - int verified = network_verify_registration(code, hash); if (verified) { store_config(); } else { @@ -215,41 +337,7 @@ static void tgprpl_login(PurpleAccount * acct) return; } } - purple_debug_info(PLUGIN_ID, "Logged in...\n"); - purple_connection_set_display_name(gc, username); - purple_connection_set_state(gc, PURPLE_CONNECTED); - purple_blist_add_account(acct); - - tggroup = purple_find_group("Telegram"); - if (tggroup == NULL) { - purple_debug_info(PLUGIN_ID, "PurpleGroup = NULL, creating"); - tggroup = purple_group_new("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(); - - purple_debug_info(PLUGIN_ID, "Fetching all current chats...\n"); - do_get_dialog_list(); - - // get new messages - purple_debug_info(PLUGIN_ID, "Fetching new messages...\n"); - do_get_difference(); - flush_queries(); - - // Our protocol data, that will be delivered to us - // through purple connection - telegram_conn *conn = g_new0(telegram_conn, 1); - conn->gc = gc; - conn->account = acct; - - purple_connection_set_protocol_data(gc, conn); - gc->proto_data = conn; + */ } void on_new_message(struct message *M) @@ -389,11 +477,11 @@ static void tgprpl_close(PurpleConnection * gc) */ static int tgprpl_send_im(PurpleConnection * gc, const char *who, const char *message, PurpleMessageFlags flags) { + telegram_conn *conn = purple_connection_get_protocol_data(gc); purple_debug_info(PLUGIN_ID, "tgprpl_send_im()\n"); PurpleBuddy *b = purple_find_buddy(_pa, who); peer_id_t *peer = purple_buddy_get_protocol_data(b); - do_send_message(*peer, message, strlen(message)); - flush_queries(); + do_send_message(conn->tg, *peer, message, strlen(message)); return 1; } @@ -751,14 +839,9 @@ static void tgprpl_init(PurplePlugin *plugin) PurpleAccountUserSplit *split; GList *verification_values = NULL; - // intialise logging + // Redirect the msglog of the telegram-cli application to the libpurple logger set_log_cb(&tg_cli_log_cb); - // Required Verification-Key -// split = purple_account_user_split_new("Verification key", NULL, '@'); -// purple_account_user_split_set_reverse(split, FALSE); -// prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); - // Extra Options #define ADD_VALUE(list, desc, v) { \ PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \ @@ -768,12 +851,10 @@ static void tgprpl_init(PurplePlugin *plugin) } ADD_VALUE(verification_values, "Phone", TELEGRAM_AUTH_MODE_PHONE); ADD_VALUE(verification_values, "SMS", TELEGRAM_AUTH_MODE_SMS); + option = purple_account_option_list_new("Verification type", "verification_type", verification_values); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - // option = purple_account_option_string_new("Server", "server", TELEGRAM_TEST_SERVER); - // prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_string_new("Verification key", "verification_key", NULL); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); @@ -786,9 +867,13 @@ static void tgprpl_init(PurplePlugin *plugin) option = purple_account_option_string_new("Last Name", "last_name", NULL); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + // TODO: Path to public key (When you can change the server hostname, // you should also be able to change the public key) + option = purple_account_option_string_new("Server", "server", TELEGRAM_TEST_SERVER); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); + option = purple_account_option_int_new("Port", "port", TELEGRAM_DEFAULT_PORT); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); @@ -811,10 +896,10 @@ static PurplePluginInfo info = { NULL, PURPLE_PRIORITY_DEFAULT, PLUGIN_ID, - "Telegram", + "struct telegram", "0.1", - "Telegram integration.", - "Includes support for the Telegram protocol into libpurple.", + "struct telegram integration.", + "Adds support for the struct telegram protocol to libpurple.", "Christopher Althaus , Markus Endres , Matthias Jentsch ", "https://bitbucket.org/telegrampurple/telegram-purple", NULL, // on load @@ -832,3 +917,4 @@ static PurplePluginInfo info = { PURPLE_INIT_PLUGIN(telegram, tgprpl_init, info) + diff --git a/purple-plugin/telegram-purple.h b/purple-plugin/telegram-purple.h index 3c0d48a..433e7f3 100644 --- a/purple-plugin/telegram-purple.h +++ b/purple-plugin/telegram-purple.h @@ -21,6 +21,7 @@ #include "version.h" #include "account.h" #include "connection.h" +#include "telegram.h" #define PLUGIN_ID "prpl-telegram" @@ -35,7 +36,7 @@ #define TELEGRAM_AUTH_MODE_SMS "sms" typedef struct { - PurpleAccount *account; + struct telegram *tg; + PurpleAccount *pa; PurpleConnection *gc; - PurpleSslConnection *gsc; } telegram_conn; diff --git a/queries.c b/queries.c index 0197f8d..3f07807 100644 --- a/queries.c +++ b/queries.c @@ -1,12 +1,12 @@ /* This file is part of telegram-client. - Telegram-client is free software: you can redistribute it and/or modify + struct telegram-client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - Telegram-client is distributed in the hope that it will be useful, + struct telegram-client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -40,10 +40,8 @@ #include "queries.h" #include "tree.h" #include "mtproto-common.h" -#include "telegram.h" #include "loop.h" #include "structures.h" -#include "interface.h" #include "net.h" #include #include @@ -53,6 +51,8 @@ #include "no-preview.h" #include "binlog.h" +#include "telegram.h" +#include "msglog.h" #define sha1 SHA1 @@ -65,6 +65,7 @@ char *get_downloads_directory (void); int verbosity; extern int offline_mode; +int offline_mode = 0; long long cur_uploading_bytes; long long cur_uploaded_bytes; @@ -73,6 +74,7 @@ long long cur_downloaded_bytes; extern int binlog_enabled; extern int sync_from_start; +int sync_from_start = 0; int queries_num = 0; @@ -87,8 +89,8 @@ int all_queries_done() } } -void flush_queries () { - net_loop(0, all_queries_done); +void telegram_flush_queries (struct telegram *instance) { + instance->on_output(instance); } void out_peer_id (peer_id_t id); @@ -142,11 +144,11 @@ 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"); - assert (DC); - assert (DC->auth_key_id); + /* 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); } @@ -316,8 +318,8 @@ int max_chat_size; int max_bcast_size; int want_dc_num; int new_dc_num; -extern struct dc *DC_list[]; -extern struct dc *DC_working; +//extern struct dc *DC_list[]; +//extern struct dc *DC_working; void out_random (int n) { assert (n <= 32); @@ -350,7 +352,7 @@ void do_insert_header (void) { /* {{{ Get config */ -void fetch_dc_option (void) { +void fetch_dc_option (struct telegram *instance) { assert (fetch_int () == CODE_dc_option); int id = fetch_int (); int l1 = prefetch_strlen (); @@ -362,10 +364,12 @@ void fetch_dc_option (void) { logprintf ( "id = %d, name = %.*s ip = %.*s port = %d\n", id, l1, name, l2, ip, port); } - bl_do_dc_option (id, l1, name, l2, ip, port); + bl_do_dc_option (id, l1, name, l2, ip, port, instance); } int help_get_config_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; + unsigned op = fetch_int (); assert (op == CODE_config || op == CODE_config_old); fetch_int (); @@ -382,7 +386,7 @@ int help_get_config_on_answer (struct query *q UU) { assert (n <= 10); int i; for (i = 0; i < n; i++) { - fetch_dc_option (); + fetch_dc_option (instance); } max_chat_size = fetch_int (); if (op == CODE_config) { @@ -391,6 +395,7 @@ int help_get_config_on_answer (struct query *q UU) { if (verbosity >= 2) { logprintf ( "chat_size = %d\n", max_chat_size); } + telegram_change_state(instance, STATE_CONNECTED, 0); return 0; } @@ -398,16 +403,19 @@ struct query_methods help_get_config_methods = { .on_answer = help_get_config_on_answer }; -void do_help_get_config (void) { +void do_help_get_config (struct telegram *instance) { clear_packet (); out_int (CODE_help_get_config); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0); + struct dc *DC_working = telegram_get_working_dc(instance); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, instance); } /* }}} */ /* {{{ Send code */ char *phone_code_hash; int send_code_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; + assert (fetch_int () == (int)CODE_auth_sent_code); fetch_bool (); int l = prefetch_strlen (); @@ -420,18 +428,30 @@ int send_code_on_answer (struct query *q UU) { fetch_int (); fetch_bool (); want_dc_num = -1; + if (instance->session_state == STATE_PHONE_CODE_REQUESTED) { + telegram_change_state(instance, STATE_PHONE_CODE_NOT_ENTERED, phone_code_hash); + } else if (instance->session_state == STATE_CLIENT_CODE_REQUESTED) { + telegram_change_state(instance, STATE_CLIENT_CODE_NOT_ENTERED, phone_code_hash); + } else { + logprintf("send_code_on_answer(): Invalid State %d ", instance->session_state); + telegram_change_state(instance, STATE_ERROR, NULL); + } return 0; } int send_code_on_error (struct query *q UU, int error_code, int l, char *error) { + struct telegram *tg = q->extra; + int s = strlen ("PHONE_MIGRATE_"); int s2 = strlen ("NETWORK_MIGRATE_"); if (l >= s && !memcmp (error, "PHONE_MIGRATE_", s)) { - int i = error[s] - '0'; - want_dc_num = i; + int want_dc_num = error[s] - '0'; + tg->auth.dc_working_num = want_dc_num; + telegram_change_state(tg, STATE_ERROR, error); } else if (l >= s2 && !memcmp (error, "NETWORK_MIGRATE_", s2)) { - int i = error[s2] - '0'; - want_dc_num = i; + int want_dc_num = error[s2] - '0'; + tg->auth.dc_working_num = want_dc_num; + telegram_change_state(tg, STATE_ERROR, error); } else { logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error); assert (0); @@ -448,13 +468,8 @@ int code_is_sent (void) { return want_dc_num; } -int config_got (void) { - return DC_list[want_dc_num] != 0; -} - char *suser; -extern int dc_working_num; -char* do_send_code (const char *user) { +void do_send_code (struct telegram *instance, const char *user) { logprintf ("sending code\n"); suser = tstrdup (user); want_dc_num = 0; @@ -467,17 +482,21 @@ char* do_send_code (const char *user) { out_string (TG_APP_HASH); out_string ("en"); - logprintf ("send_code: dc_num = %d\n", dc_working_num); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0); - net_loop (0, code_is_sent); - if (want_dc_num == -1) { return phone_code_hash; } - - DC_working = DC_list[want_dc_num]; - if (!DC_working->sessions[0]) { - dc_create_session (DC_working); + logprintf ("send_code: dc_num = %d\n", instance->auth.dc_working_num); + send_query (telegram_get_working_dc(instance), packet_ptr - packet_buffer, packet_buffer, &send_code_methods, instance); + if (instance->session_state == STATE_PHONE_NOT_REGISTERED) { + telegram_change_state(instance, STATE_PHONE_CODE_REQUESTED, NULL); + } else if (instance->session_state == STATE_CLIENT_NOT_REGISTERED) { + telegram_change_state(instance, STATE_CLIENT_CODE_REQUESTED, NULL); + } else { + logprintf("do_send_code() Invalid State %d, erroring\n", instance->session_state); + telegram_change_state(instance, STATE_ERROR, NULL); } - dc_working_num = want_dc_num; + // TODO: Phone Code Hash + /* + net_loop (0, code_is_sent); + if (want_dc_num == -1) { return phone_code_hash; } bl_do_set_working_dc (dc_working_num); logprintf ("send_code: dc_num = %d\n", dc_working_num); @@ -491,11 +510,12 @@ char* do_send_code (const char *user) { out_string (TG_APP_HASH); out_string ("en"); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0); + send_query (telegram_get_working_dc(instance), packet_ptr - packet_buffer, packet_buffer, &send_code_methods, 0); net_loop (0, code_is_sent); assert (want_dc_num == -1); return phone_code_hash; + */ } @@ -515,7 +535,7 @@ struct query_methods phone_call_methods = { .on_error = phone_call_on_error }; -void do_phone_call (const char *user) { +void do_phone_call (struct telegram *instance, const char *user) { logprintf ("calling user\n"); suser = tstrdup (user); want_dc_num = 0; @@ -525,8 +545,8 @@ void do_phone_call (const char *user) { out_string (user); out_string (phone_code_hash); - logprintf ("do_phone_call: dc_num = %d\n", dc_working_num); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0); + logprintf ("do_phone_call: dc_num = %d\n", instance->auth.dc_working_num); + send_query (telegram_get_working_dc(instance), packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0); } /* }}} */ @@ -546,31 +566,26 @@ int check_phone_on_answer (struct query *q UU) { int check_phone_on_error (struct query *q UU, int error_code, int l, char *error) { int s = strlen ("PHONE_MIGRATE_"); int s2 = strlen ("NETWORK_MIGRATE_"); + struct telegram* instance = q->extra; + if (l >= s && !memcmp (error, "PHONE_MIGRATE_", s)) { + // update used data centre int i = error[s] - '0'; - assert (DC_list[i]); + instance->auth.dc_working_num = i; - dc_working_num = i; - DC_working = DC_list[i]; - write_auth_file (); - - bl_do_set_working_dc (i); - - check_phone_result = 1; + //bl_do_set_working_dc (i); + //check_phone_result = 1; } else if (l >= s2 && !memcmp (error, "NETWORK_MIGRATE_", s2)) { + // update used data centre int i = error[s2] - '0'; - assert (DC_list[i]); - dc_working_num = i; + instance->auth.dc_working_num = i; + //bl_do_set_working_dc (i); - bl_do_set_working_dc (i); - - DC_working = DC_list[i]; - write_auth_file (); - check_phone_result = 1; + //check_phone_result = 1; } else { logprintf ( "error_code = %d, error = %.*s\n", error_code, l, error); - assert (0); } + telegram_change_state(instance, STATE_ERROR, error); return 0; } @@ -579,17 +594,20 @@ struct query_methods check_phone_methods = { .on_error = check_phone_on_error }; -int do_auth_check_phone (const char *user) { +int do_auth_check_phone (struct telegram *instance, const char *user) { suser = tstrdup (user); clear_packet (); out_int (CODE_auth_check_phone); out_string (user); check_phone_result = -1; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); + struct dc *DC_working = telegram_get_working_dc(instance); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, instance); + /* net_loop (0, cr_f); check_phone_result = -1; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &check_phone_methods, instance); net_loop (0, cr_f); + */ return check_phone_result; } /* }}} */ @@ -623,7 +641,8 @@ struct query_methods nearest_dc_methods = { .on_error = fail_on_error }; -int do_get_nearest_dc (void) { +int 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; @@ -643,6 +662,7 @@ int sign_in_is_ok (void) { struct user User; int sign_in_on_answer (struct query *q UU) { + struct dc *DC_working = telegram_get_working_dc(q->extra); assert (fetch_int () == (int)CODE_auth_authorization); int expires = fetch_int (); fetch_user (&User); @@ -682,19 +702,21 @@ struct query_methods sign_in_methods = { .on_error = sign_in_on_error }; -int do_send_code_result (const char *code, const char *sms_hash) { +int 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); out_string (suser); out_string(sms_hash); out_string (code); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0); + 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; } -int do_send_code_result_auth (const char *code, const char *sms_hash, const char *first_name, const char *last_name) { +int 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); out_string (suser); @@ -702,7 +724,7 @@ int do_send_code_result_auth (const char *code, const char *sms_hash, const char out_string (code); out_string (first_name); out_string (last_name); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0); + 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; @@ -728,11 +750,11 @@ int get_contacts_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { fetch_alloc_user (); /* - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("User #%d: ", get_peer_id (U->id)); - print_user_name (U->id, (peer_t *)U); - push_color (COLOR_GREEN); + //print_user_name (U->id, (peer_t *)U); + //push_color (COLOR_GREEN); logprintf (" ("); logprintf ("%s", U->print_name); if (U->phone) { @@ -740,20 +762,20 @@ int get_contacts_on_answer (struct query *q UU) { logprintf ("%s", U->phone); } logprintf (") "); - pop_color (); + //pop_color (); if (U->status.online > 0) { logprintf ("online\n"); } else { if (U->status.online < 0) { logprintf ("offline. Was online "); - print_date_full (U->status.when); + //print_date_full (U->status.when); } else { logprintf ("offline permanent"); } logprintf ("\n"); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); */ } contacts_got = 1; @@ -765,7 +787,8 @@ struct query_methods get_contacts_methods = { }; -void do_update_contact_list (void) { +void do_update_contact_list (struct telegram *instance) { + struct dc *DC_working = telegram_get_working_dc(instance); contacts_got = 0; clear_packet (); out_int (CODE_contacts_get_contacts); @@ -860,7 +883,7 @@ void encr_finish (struct secret_chat *E) { /* {{{ Seng msg (plain text) */ int msg_send_encr_on_answer (struct query *q UU) { assert (fetch_int () == CODE_messages_sent_encrypted_message); - rprintf ("Sent\n"); + logprintf ("Sent\n"); struct message *M = q->extra; //M->date = fetch_int (); fetch_int (); @@ -907,16 +930,16 @@ int msg_send_on_answer (struct query *q UU) { if (b == CODE_contacts_foreign_link_requested) { U->flags |= FLAG_USER_OUT_CONTACT; } - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("Link with user "); - print_user_name (U->id, (void *)U); + //print_user_name (U->id, (void *)U); logprintf (" changed\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } } - rprintf ("Sent: id = %d\n", id); + logprintf ("Sent: id = %d\n", id); bl_do_set_message_sent (M); return 0; } @@ -940,7 +963,8 @@ struct query_methods msg_send_encr_methods = { int out_message_num; int our_id; -void do_send_encr_msg (struct message *M) { +void do_send_encr_msg (struct telegram *instance, struct message *M) { + struct dc *DC_working = telegram_get_working_dc(instance); peer_t *P = user_chat_get (M->to_id); if (!P || P->encr_chat.state != sc_ok) { return; } @@ -963,9 +987,10 @@ void do_send_encr_msg (struct message *M) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M); } -void do_send_msg (struct message *M) { +void do_send_msg (struct telegram *instance, struct message *M) { + struct dc *DC_working = telegram_get_working_dc(instance); if (get_peer_type (M->to_id) == PEER_ENCR_CHAT) { - do_send_encr_msg (M); + do_send_encr_msg (instance ,M); return; } clear_packet (); @@ -976,7 +1001,7 @@ void do_send_msg (struct message *M) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, M); } -void do_send_message (peer_id_t id, const char *msg, int len) { +void do_send_message (struct telegram *instance, peer_id_t id, const char *msg, int len) { if (get_peer_type (id) == PEER_ENCR_CHAT) { peer_t *P = user_chat_get (id); if (!P) { @@ -994,16 +1019,16 @@ void do_send_message (peer_id_t id, const char *msg, int len) { bl_do_send_message_text (t, our_id, get_peer_type (id), get_peer_id (id), time (0), len, msg); struct message *M = message_get (t); assert (M); - do_send_msg (M); - print_message (M); + do_send_msg (instance, M); + //print_message (M); } /* }}} */ /* {{{ Send text file */ -void do_send_text (peer_id_t id, char *file_name) { +void do_send_text (struct telegram *instance, peer_id_t id, char *file_name) { int fd = open (file_name, O_RDONLY); if (fd < 0) { - rprintf ("No such file '%s'\n", file_name); + logprintf ("No such file '%s'\n", file_name); tfree_str (file_name); return; } @@ -1011,12 +1036,12 @@ void do_send_text (peer_id_t id, char *file_name) { int x = read (fd, buf, (1 << 20) + 1); assert (x >= 0); if (x == (1 << 20) + 1) { - rprintf ("Too big file '%s'\n", file_name); + logprintf ("Too big file '%s'\n", file_name); tfree_str (file_name); close (fd); } else { buf[x] = 0; - do_send_message (id, buf, x); + do_send_message (instance, id, buf, x); tfree_str (file_name); close (fd); } @@ -1045,7 +1070,8 @@ struct query_methods mark_read_encr_methods = { .on_answer = mark_read_encr_on_receive }; -void do_messages_mark_read (peer_id_t id, int max_id) { +void do_messages_mark_read (struct telegram *instance, peer_id_t id, int max_id) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_read_history); out_peer_id (id); @@ -1054,7 +1080,8 @@ void do_messages_mark_read (peer_id_t id, int max_id) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, 0); } -void do_messages_mark_read_encr (peer_id_t id, long long access_hash, int last_time) { +void do_messages_mark_read_encr (struct telegram *instance, peer_id_t id, long long access_hash, int last_time) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_read_encrypted_history); out_int (CODE_input_encrypted_chat); @@ -1064,45 +1091,54 @@ void do_messages_mark_read_encr (peer_id_t id, long long access_hash, int last_t send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, 0); } -void do_mark_read (peer_id_t id) { +void do_mark_read (struct telegram *instance, peer_id_t id) { peer_t *P = user_chat_get (id); if (!P) { - rprintf ("Unknown peer\n"); + logprintf ("Unknown peer\n"); return; } if (get_peer_type (id) == PEER_USER || get_peer_type (id) == PEER_CHAT) { if (!P->last) { - rprintf ("Unknown last peer message\n"); + logprintf ("Unknown last peer message\n"); return; } - do_messages_mark_read (id, P->last->id); + do_messages_mark_read (instance, id, P->last->id); return; } assert (get_peer_type (id) == PEER_ENCR_CHAT); if (P->last) { - do_messages_mark_read_encr (id, P->encr_chat.access_hash, P->last->date); + do_messages_mark_read_encr (instance, id, P->encr_chat.access_hash, P->last->date); } else { - do_messages_mark_read_encr (id, P->encr_chat.access_hash, time (0) - 10); + do_messages_mark_read_encr (instance, id, P->encr_chat.access_hash, time (0) - 10); } } /* }}} */ +struct get_hist_extra { + struct telegram *instance; + peer_id_t peer_id; +}; + /* {{{ Get history */ int get_history_on_answer (struct query *q UU) { + struct get_hist_extra *extra = q->extra; + struct telegram *instance = extra->instance; + peer_id_t peer_id = extra->peer_id; + static struct message *ML[10000]; int i; int x = fetch_int (); if (x == (int)CODE_messages_messages_slice) { fetch_int (); - rprintf ("...\n"); + logprintf ("...\n"); } else { assert (x == (int)CODE_messages_messages); } assert (fetch_int () == CODE_vector); int n = fetch_int (); for (i = 0; i < n; i++) { - struct message *M = fetch_alloc_message (); + struct message *M = fetch_alloc_message (instance); if (i <= 9999) { ML[i] = M; } @@ -1110,7 +1146,7 @@ int get_history_on_answer (struct query *q UU) { if (n > 10000) { n = 10000; } int sn = n; for (i = n - 1; i >= 0; i--) { - print_message (ML[i]); + //print_message (ML[i]); } assert (fetch_int () == CODE_vector); n = fetch_int (); @@ -1122,9 +1158,11 @@ int get_history_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { fetch_alloc_user (); } + if (sn > 0 && q->extra) { - do_messages_mark_read (*(peer_id_t *)&(q->extra), ML[0]->id); + do_messages_mark_read (instance, peer_id, ML[0]->id); } + free(extra); return 0; } @@ -1143,15 +1181,16 @@ void do_get_local_history (peer_id_t id, int limit) { count ++; } while (M) { - print_message (M); + //print_message (M); M = M->prev; } } -void do_get_history (peer_id_t id, int limit) { +void do_get_history (struct telegram *instance, peer_id_t id, int limit) { + struct dc *DC_working = telegram_get_working_dc(instance); if (get_peer_type (id) == PEER_ENCR_CHAT || offline_mode) { do_get_local_history (id, limit); - do_mark_read (id); + do_mark_read (instance, id); return; } clear_packet (); @@ -1160,13 +1199,19 @@ void do_get_history (peer_id_t id, int limit) { out_int (0); out_int (0); out_int (limit); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, (void *)*(long *)&id); + + struct get_hist_extra *extra = malloc(sizeof(struct get_hist_extra)); + extra->instance = instance; + extra->peer_id = id; + + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, extra); } /* }}} */ /* {{{ Get dialogs */ int dialog_list_got; int get_dialogs_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; unsigned x = fetch_int (); assert (x == CODE_messages_dialogs || x == CODE_messages_dialogs_slice); if (x == CODE_messages_dialogs_slice) { @@ -1193,7 +1238,7 @@ int get_dialogs_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); n = fetch_int (); for (i = 0; i < n; i++) { - fetch_alloc_message (); + fetch_alloc_message (instance); } assert (fetch_int () == CODE_vector); n = fetch_int (); @@ -1205,27 +1250,27 @@ int get_dialogs_on_answer (struct query *q UU) { for (i = 0; i < n; i++) { fetch_alloc_user (); } - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); for (i = dl_size - 1; i >= 0; i--) { peer_t *UC; switch (get_peer_type (plist[i])) { case PEER_USER: UC = user_chat_get (plist[i]); logprintf ("User "); - print_user_name (plist[i], UC); + //print_user_name (plist[i], UC); logprintf (": %d unread\n", dlist[2 * i + 1]); break; case PEER_CHAT: UC = user_chat_get (plist[i]); logprintf ("Chat "); - print_chat_name (plist[i], UC); + //print_chat_name (plist[i], UC); logprintf (": %d unread\n", dlist[2 * i + 1]); break; } } - pop_color (); - print_end (); + //pop_color (); + //print_end (); dialog_list_got = 1; return 0; @@ -1236,13 +1281,14 @@ struct query_methods get_dialogs_methods = { }; -void do_get_dialog_list (void) { +void do_get_dialog_list (struct telegram *instance) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_get_dialogs); out_int (0); out_int (0); out_int (1000); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, instance); } /* }}} */ @@ -1289,16 +1335,23 @@ void out_peer_id (peer_id_t id) { } } -void send_part (struct send_file *f); +struct send_file_extra { + struct telegram *instance; + struct send_file *file; +}; + +void send_part (struct telegram *instance, struct send_file *f); int send_file_part_on_answer (struct query *q) { + struct send_file_extra *extra = q->extra; assert (fetch_int () == (int)CODE_bool_true); - send_part (q->extra); + send_part (extra->instance, extra->file); return 0; } int send_file_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; assert (fetch_int () == (int)CODE_messages_stated_message); - struct message *M = fetch_alloc_message (); + struct message *M = fetch_alloc_message (instance); assert (fetch_int () == CODE_vector); int n, i; n = fetch_int (); @@ -1312,7 +1365,7 @@ int send_file_on_answer (struct query *q UU) { } fetch_pts (); fetch_seq (); - print_message (M); + //print_message (M); return 0; } @@ -1330,7 +1383,7 @@ int send_encr_file_on_answer (struct query *q UU) { fetch_int (); M->media.encr_photo.dc_id = fetch_int (); assert (fetch_int () == M->media.encr_photo.key_fingerprint); - print_message (M); + //print_message (M); message_insert (M); return 0; } @@ -1347,7 +1400,9 @@ struct query_methods send_encr_file_methods = { .on_answer = send_encr_file_on_answer }; -void send_part (struct send_file *f) { +void send_part (struct telegram *instance, struct send_file *f) { + + struct dc *DC_working = telegram_get_working_dc(instance); if (f->fd >= 0) { if (!f->part_num) { cur_uploading_bytes += f->size; @@ -1391,12 +1446,16 @@ void send_part (struct send_file *f) { } else { assert (f->part_size == x); } - update_prompt (); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f); + //update_prompt (); + + struct send_file_extra *extra = malloc(sizeof(struct send_file_extra)); + extra->instance = instance; + extra->file = f; + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, extra); } else { cur_uploaded_bytes -= f->size; cur_uploading_bytes -= f->size; - update_prompt (); + //update_prompt (); clear_packet (); assert (f->media_type == CODE_input_media_uploaded_photo || f->media_type == CODE_input_media_uploaded_video || f->media_type == CODE_input_media_uploaded_thumb_video || f->media_type == CODE_input_media_uploaded_audio || f->media_type == CODE_input_media_uploaded_document || f->media_type == CODE_input_media_uploaded_thumb_document); if (!f->encr) { @@ -1437,7 +1496,7 @@ void send_part (struct send_file *f) { } out_long (-lrand48 () * (1ll << 32) - lrand48 ()); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, instance); } else { struct message *M = talloc0 (sizeof (*M)); @@ -1527,14 +1586,14 @@ void send_part (struct send_file *f) { M->date = time (0); send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M); - } tfree_str (f->file_name); tfree (f, sizeof (*f)); } } -void send_file_thumb (struct send_file *f) { +void send_file_thumb (struct telegram *instance, struct send_file *f) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); f->thumb_id = lrand48 () * (1ll << 32) + lrand48 (); out_int (CODE_upload_save_file_part); @@ -1544,10 +1603,10 @@ void send_file_thumb (struct send_file *f) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f); } -void do_send_photo (int type, peer_id_t to_id, char *file_name) { +void do_send_photo (struct telegram *instance, int type, peer_id_t to_id, char *file_name) { int fd = open (file_name, O_RDONLY); if (fd < 0) { - rprintf ("No such file '%s'\n", file_name); + logprintf ("No such file '%s'\n", file_name); tfree_str (file_name); return; } @@ -1555,7 +1614,7 @@ void do_send_photo (int type, peer_id_t to_id, char *file_name) { fstat (fd, &buf); long long size = buf.st_size; if (size <= 0) { - rprintf ("File has zero length\n"); + logprintf ("File has zero length\n"); tfree_str (file_name); close (fd); return; @@ -1573,7 +1632,7 @@ void do_send_photo (int type, peer_id_t to_id, char *file_name) { if (f->part_size > (512 << 10)) { close (fd); - rprintf ("Too big file. Maximal supported size is %d.\n", (512 << 10) * 1000); + logprintf ("Too big file. Maximal supported size is %d.\n", (512 << 10) * 1000); tfree (f, sizeof (*f)); tfree_str (file_name); return; @@ -1594,20 +1653,21 @@ void do_send_photo (int type, peer_id_t to_id, char *file_name) { } if (f->media_type == CODE_input_media_uploaded_video && !f->encr) { f->media_type = CODE_input_media_uploaded_thumb_video; - send_file_thumb (f); + send_file_thumb (instance, f); } else if (f->media_type == CODE_input_media_uploaded_document && !f->encr) { f->media_type = CODE_input_media_uploaded_thumb_document; - send_file_thumb (f); + send_file_thumb (instance, f); } else { - send_part (f); + send_part (instance, f); } } /* }}} */ /* {{{ Forward */ int fwd_msg_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; assert (fetch_int () == (int)CODE_messages_stated_message); - struct message *M = fetch_alloc_message (); + struct message *M = fetch_alloc_message (instance); assert (fetch_int () == CODE_vector); int n, i; n = fetch_int (); @@ -1621,7 +1681,7 @@ int fwd_msg_on_answer (struct query *q UU) { } fetch_pts (); fetch_seq (); - print_message (M); + //print_message (M); return 0; } @@ -1629,9 +1689,10 @@ struct query_methods fwd_msg_methods = { .on_answer = fwd_msg_on_answer }; -void do_forward_message (peer_id_t id, int n) { +void do_forward_message (struct telegram *instance, peer_id_t id, int n) { + struct dc *DC_working = telegram_get_working_dc(instance); if (get_peer_type (id) == PEER_ENCR_CHAT) { - rprintf ("Can not forward messages from secret chat\n"); + logprintf ("Can not forward messages from secret chat\n"); return; } clear_packet (); @@ -1639,14 +1700,16 @@ void do_forward_message (peer_id_t id, int n) { out_peer_id (id); out_int (n); out_long (lrand48 () * (1ll << 32) + lrand48 ()); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, instance); } /* }}} */ /* {{{ Rename chat */ int rename_chat_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; + assert (fetch_int () == (int)CODE_messages_stated_message); - struct message *M = fetch_alloc_message (); + struct message *M = fetch_alloc_message (instance); assert (fetch_int () == CODE_vector); int n, i; n = fetch_int (); @@ -1660,7 +1723,7 @@ int rename_chat_on_answer (struct query *q UU) { } fetch_pts (); fetch_seq (); - print_message (M); + //print_message (M); return 0; } @@ -1668,44 +1731,45 @@ struct query_methods rename_chat_methods = { .on_answer = rename_chat_on_answer }; -void do_rename_chat (peer_id_t id, char *name UU) { +void do_rename_chat (struct telegram *instance, peer_id_t id, char *name UU) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_edit_chat_title); assert (get_peer_type (id) == PEER_CHAT); out_int (get_peer_id (id)); out_string (name); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, instance); } /* }}} */ /* {{{ Chat info */ void print_chat_info (struct chat *C) { peer_t *U = (void *)C; - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("Chat "); - print_chat_name (U->id, U); + //print_chat_name (U->id, U); logprintf (" members:\n"); int i; for (i = 0; i < C->user_list_size; i++) { logprintf ("\t\t"); - print_user_name (MK_USER (C->user_list[i].user_id), user_chat_get (MK_USER (C->user_list[i].user_id))); + //print_user_name (MK_USER (C->user_list[i].user_id), user_chat_get (MK_USER (C->user_list[i].user_id))); logprintf (" invited by "); - print_user_name (MK_USER (C->user_list[i].inviter_id), user_chat_get (MK_USER (C->user_list[i].inviter_id))); + //print_user_name (MK_USER (C->user_list[i].inviter_id), user_chat_get (MK_USER (C->user_list[i].inviter_id))); logprintf (" at "); - print_date_full (C->user_list[i].date); + //print_date_full (C->user_list[i].date); if (C->user_list[i].user_id == C->admin_id) { logprintf (" admin"); } logprintf ("\n"); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); } int chat_info_on_answer (struct query *q UU) { struct chat *C = fetch_alloc_chat_full (); - print_chat_info (C); + //print_chat_info (C); return 0; } @@ -1713,13 +1777,14 @@ struct query_methods chat_info_methods = { .on_answer = chat_info_on_answer }; -void do_get_chat_info (peer_id_t id) { +void do_get_chat_info (struct telegram *instance, peer_id_t id) { + struct dc *DC_working = telegram_get_working_dc(instance); if (offline_mode) { peer_t *C = user_chat_get (id); if (!C) { - rprintf ("No such chat\n"); + logprintf ("No such chat\n"); } else { - print_chat_info (&C->chat); + //print_chat_info (&C->chat); } return; } @@ -1735,10 +1800,10 @@ void do_get_chat_info (peer_id_t id) { void print_user_info (struct user *U) { peer_t *C = (void *)U; - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("User "); - print_user_name (U->id, C); + //print_user_name (U->id, C); logprintf (":\n"); logprintf ("\treal name: %s %s\n", U->real_first_name, U->real_last_name); logprintf ("\tphone: %s\n", U->phone); @@ -1746,16 +1811,16 @@ void print_user_info (struct user *U) { logprintf ("\tonline\n"); } else { logprintf ("\toffline (was online "); - print_date_full (U->status.when); + //print_date_full (U->status.when); logprintf (")\n"); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); } int user_info_on_answer (struct query *q UU) { struct user *U = fetch_alloc_user_full (); - print_user_info (U); + //print_user_info (U); return 0; } @@ -1763,13 +1828,14 @@ struct query_methods user_info_methods = { .on_answer = user_info_on_answer }; -void do_get_user_info (peer_id_t id) { +void do_get_user_info (struct telegram *instance, peer_id_t id) { + struct dc *DC_working = telegram_get_working_dc(instance); if (offline_mode) { peer_t *C = user_chat_get (id); if (!C) { - rprintf ("No such user\n"); + logprintf ("No such user\n"); } else { - print_user_info (&C->user); + //print_user_info (&C->user); } return; } @@ -1804,7 +1870,8 @@ struct query_methods user_list_info_silent_methods = { .on_answer = user_list_info_silent_on_answer }; -void do_get_user_list_info_silent (int num, int *list) { +void do_get_user_list_info_silent (struct telegram *instance, int num, int *list) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_users_get_users); out_int (CODE_vector); @@ -1841,7 +1908,7 @@ struct download { void end_load (struct download *D) { cur_downloading_bytes -= D->size; cur_downloaded_bytes -= D->size; - update_prompt (); + //update_prompt (); close (D->fd); if (D->next == 1) { logprintf ("Done: %s\n", D->name); @@ -1864,12 +1931,21 @@ void end_load (struct download *D) { tfree (D, sizeof (*D)); } -void load_next_part (struct download *D); +struct download_extra { + struct telegram *instance; + struct download *dl; +}; + +void load_next_part (struct telegram *instance, struct download *D); int download_on_answer (struct query *q) { + struct download_extra *extra = q->extra; + struct telegram *instance = extra->instance; + struct download *D = extra->dl; + free(extra); + assert (fetch_int () == (int)CODE_upload_file); unsigned x = fetch_int (); assert (x); - struct download *D = q->extra; if (D->fd == -1) { D->fd = open (D->name, O_CREAT | O_WRONLY, 0640); } @@ -1877,7 +1953,7 @@ int download_on_answer (struct query *q) { int len = prefetch_strlen (); assert (len >= 0); cur_downloaded_bytes += len; - update_prompt (); + //update_prompt (); if (D->iv) { unsigned char *ptr = (void *)fetch_str (len); assert (!(len & 15)); @@ -1894,7 +1970,7 @@ int download_on_answer (struct query *q) { } D->offset += len; if (D->offset < D->size) { - load_next_part (D); + load_next_part (instance, D); return 0; } else { end_load (D); @@ -1906,7 +1982,7 @@ struct query_methods download_methods = { .on_answer = download_on_answer }; -void load_next_part (struct download *D) { +void load_next_part (struct telegram *instance, struct download *D) { if (!D->offset) { static char buf[PATH_MAX]; int l; @@ -1926,7 +2002,7 @@ void load_next_part (struct download *D) { if (D->offset >= D->size) { cur_downloading_bytes += D->size; cur_downloaded_bytes += D->offset; - rprintf ("Already downloaded\n"); + logprintf ("Already downloaded\n"); end_load (D); return; } @@ -1934,7 +2010,7 @@ void load_next_part (struct download *D) { cur_downloading_bytes += D->size; cur_downloaded_bytes += D->offset; - update_prompt (); + //update_prompt (); } clear_packet (); out_int (CODE_upload_get_file); @@ -1954,13 +2030,18 @@ void load_next_part (struct download *D) { } out_int (D->offset); out_int (1 << 14); - send_query (DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D); + + struct download_extra *extra = malloc(sizeof(struct download_extra)); + extra->instance = instance; + extra->dl = D; + + send_query (instance->auth.DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, extra); //send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D); } -void do_load_photo_size (struct photo_size *P, int next) { +void do_load_photo_size (struct telegram *instance, struct photo_size *P, int next) { if (!P->loc.dc) { - rprintf ("Bad video thumb\n"); + logprintf ("Bad video thumb\n"); return; } @@ -1977,10 +2058,10 @@ void do_load_photo_size (struct photo_size *P, int next) { D->next = next; D->name = 0; D->fd = -1; - load_next_part (D); + load_next_part (instance, D); } -void do_load_photo (struct photo *photo, int next) { +void do_load_photo (struct telegram *instance, struct photo *photo, int next) { if (!photo->sizes_num) { return; } int max = -1; int maxi = 0; @@ -1991,18 +2072,18 @@ void do_load_photo (struct photo *photo, int next) { maxi = i; } } - do_load_photo_size (&photo->sizes[maxi], next); + do_load_photo_size (instance, &photo->sizes[maxi], next); } -void do_load_video_thumb (struct video *video, int next) { - do_load_photo_size (&video->thumb, next); +void do_load_video_thumb (struct telegram *instance, struct video *video, int next) { + do_load_photo_size (instance, &video->thumb, next); } -void do_load_document_thumb (struct document *video, int next) { - do_load_photo_size (&video->thumb, next); +void do_load_document_thumb (struct telegram *instance, struct document *video, int next) { + do_load_photo_size (instance, &video->thumb, next); } -void do_load_video (struct video *V, int next) { +void do_load_video (struct telegram *instance, struct video *V, int next) { assert (V); assert (next); struct download *D = talloc0 (sizeof (*D)); @@ -2015,10 +2096,10 @@ void do_load_video (struct video *V, int next) { D->name = 0; D->fd = -1; D->type = CODE_input_video_file_location; - load_next_part (D); + load_next_part (instance, D); } -void do_load_audio (struct video *V, int next) { +void do_load_audio (struct telegram *instance, struct video *V, int next) { assert (V); assert (next); struct download *D = talloc0 (sizeof (*D)); @@ -2031,10 +2112,10 @@ void do_load_audio (struct video *V, int next) { D->name = 0; D->fd = -1; D->type = CODE_input_audio_file_location; - load_next_part (D); + load_next_part (instance, D); } -void do_load_document (struct document *V, int next) { +void do_load_document (struct telegram *instance, struct document *V, int next) { assert (V); assert (next); struct download *D = talloc0 (sizeof (*D)); @@ -2047,10 +2128,10 @@ void do_load_document (struct document *V, int next) { D->name = 0; D->fd = -1; D->type = CODE_input_document_file_location; - load_next_part (D); + load_next_part (instance, D); } -void do_load_encr_video (struct encr_video *V, int next) { +void do_load_encr_video (struct telegram *instance, struct encr_video *V, int next) { assert (V); assert (next); struct download *D = talloc0 (sizeof (*D)); @@ -2065,7 +2146,7 @@ void do_load_encr_video (struct encr_video *V, int next) { D->key = V->key; D->iv = talloc (32); memcpy (D->iv, V->iv, 32); - load_next_part (D); + load_next_part (instance, D); unsigned char md5[16]; unsigned char str[64]; @@ -2107,7 +2188,8 @@ struct query_methods export_auth_methods = { .on_error = fail_on_error }; -void do_export_auth (int num) { +void do_export_auth (struct telegram *instance, int num) { + struct dc *DC_working = telegram_get_working_dc(instance); export_auth_str = 0; clear_packet (); out_int (CODE_auth_export_authorization); @@ -2132,12 +2214,12 @@ struct query_methods import_auth_methods = { .on_error = fail_on_error }; -void do_import_auth (int num) { +void do_import_auth (struct telegram *instance, int num) { clear_packet (); out_int (CODE_auth_import_authorization); out_int (our_id); out_cstring (export_auth_str, export_auth_str_len); - send_query (DC_list[num], packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0); + send_query (instance->auth.DC_list[num], packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0); net_loop (0, isn_export_auth_str); } /* }}} */ @@ -2162,11 +2244,11 @@ int add_contact_on_answer (struct query *q UU) { n = fetch_int (); for (i = 0; i < n ; i++) { struct user *U = fetch_alloc_user (); - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("User #%d: ", get_peer_id (U->id)); - print_user_name (U->id, (peer_t *)U); - push_color (COLOR_GREEN); + //print_user_name (U->id, (peer_t *)U); + //push_color (COLOR_GREEN); logprintf (" ("); logprintf ("%s", U->print_name); if (U->phone) { @@ -2174,20 +2256,20 @@ int add_contact_on_answer (struct query *q UU) { logprintf ("%s", U->phone); } logprintf (") "); - pop_color (); + //pop_color (); if (U->status.online > 0) { logprintf ("online\n"); } else { if (U->status.online < 0) { logprintf ("offline. Was online "); - print_date_full (U->status.when); + //print_date_full (U->status.when); } else { logprintf ("offline permanent"); } logprintf ("\n"); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); } return 0; @@ -2197,7 +2279,8 @@ struct query_methods add_contact_methods = { .on_answer = add_contact_on_answer, }; -void do_add_contact (const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force) { +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) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_contacts_import_contacts); out_int (CODE_vector); @@ -2221,9 +2304,10 @@ struct query_methods msg_search_methods = { .on_answer = msg_search_on_answer }; -void do_msg_search (peer_id_t id, int from, int to, int limit, const char *s) { +void do_msg_search (struct telegram *instance, peer_id_t id, int from, int to, int limit, const char *s) { + struct dc *DC_working = telegram_get_working_dc(instance); if (get_peer_type (id) == PEER_ENCR_CHAT) { - rprintf ("Can not search in secure chat\n"); + logprintf ("Can not search in secure chat\n"); return; } clear_packet (); @@ -2256,18 +2340,18 @@ int contacts_search_on_answer (struct query *q UU) { } assert (fetch_int () == CODE_vector); n = fetch_int (); - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); for (i = 0; i < n; i++) { struct user *U = fetch_alloc_user (); logprintf ("User "); - push_color (COLOR_RED); + //push_color (COLOR_RED); logprintf ("%s %s", U->first_name, U->last_name); - pop_color (); + //pop_color (); logprintf (". Phone %s\n", U->phone); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); return 0; } @@ -2275,7 +2359,8 @@ struct query_methods contacts_search_methods = { .on_answer = contacts_search_on_answer }; -void do_contacts_search (int limit, const char *s) { +void do_contacts_search (struct telegram *instance, int limit, const char *s) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_contacts_search); out_string (s); @@ -2289,21 +2374,21 @@ int send_encr_accept_on_answer (struct query *q UU) { struct secret_chat *E = fetch_alloc_encrypted_chat (); if (E->state == sc_ok) { - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("Encrypted connection with "); - print_encr_chat_name (E->id, (void *)E); + ////print_encr_chat_name (E->id, (void *)E); logprintf (" established\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } else { - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("Encrypted connection with "); - print_encr_chat_name (E->id, (void *)E); + ////print_encr_chat_name (E->id, (void *)E); logprintf (" failed\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } return 0; } @@ -2311,21 +2396,21 @@ int send_encr_accept_on_answer (struct query *q UU) { int send_encr_request_on_answer (struct query *q UU) { struct secret_chat *E = fetch_alloc_encrypted_chat (); if (E->state == sc_deleted) { - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("Encrypted connection with "); - print_encr_chat_name (E->id, (void *)E); + //print_encr_chat_name (E->id, (void *)E); logprintf (" can not be established\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); } else { - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); logprintf ("Establishing connection with "); - print_encr_chat_name (E->id, (void *)E); + //print_encr_chat_name (E->id, (void *)E); logprintf ("\n"); - pop_color (); - print_end (); + //pop_color (); + //print_end (); assert (E->state == sc_waiting); } @@ -2345,7 +2430,8 @@ unsigned char *encr_prime; int encr_param_version; BN_CTX *ctx; -void do_send_accept_encr_chat (struct secret_chat *E, unsigned char *random) { +void do_send_accept_encr_chat (struct telegram *instance, struct secret_chat *E, unsigned char *random) { + struct dc *DC_working = telegram_get_working_dc(instance); int i; int ok = 0; for (i = 0; i < 64; i++) { @@ -2456,7 +2542,8 @@ void do_create_keys_end (struct secret_chat *U) { BN_clear_free (a); } -void do_send_create_encr_chat (void *x, unsigned char *random) { +void do_send_create_encr_chat (struct telegram *instance, void *x, unsigned char *random) { + struct dc *DC_working = telegram_get_working_dc(instance); int user_id = (long)x; int i; unsigned char random_here[256]; @@ -2514,7 +2601,8 @@ void do_send_create_encr_chat (void *x, unsigned char *random) { } out_int (get_peer_id (E->id)); out_cstring (g_a, 256); - write_secret_chat_file (); + // TODO: properly... + write_secret_chat_file ("/home/dev-jessie/.telegram/+4915736384600/secret"); BN_clear_free (g); BN_clear_free (p); @@ -2523,6 +2611,12 @@ void do_send_create_encr_chat (void *x, unsigned char *random) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E); } +struct create_encr_chat_extra { + void (*callback) (struct telegram *instance, struct secret_chat *E, unsigned char *random); + void *data; + struct telegram *instance; +}; + int get_dh_config_on_answer (struct query *q UU) { unsigned x = fetch_int (); assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified || LOG_DH_CONFIG); @@ -2545,9 +2639,13 @@ int get_dh_config_on_answer (struct query *q UU) { unsigned char *random = talloc (256); memcpy (random, fetch_str (256), 256); if (q->extra) { - void **x = q->extra; - ((void (*)(void *, void *))(*x))(x[1], random); - tfree (x, 2 * sizeof (void *)); + //((void (*)(void *, void *))(*x))(x[1], random); + + struct create_encr_chat_extra *extra = q->extra; + extra->callback(extra->instance, extra->data, random); + free(extra); + //tfree (x, 2 * sizeof (void *)); + tfree_secure (random, 256); } else { tfree_secure (random, 256); @@ -2559,28 +2657,34 @@ struct query_methods get_dh_config_methods = { .on_answer = get_dh_config_on_answer }; -void do_accept_encr_chat_request (struct secret_chat *E) { +void do_accept_encr_chat_request (struct telegram *instance, struct secret_chat *E) { + struct dc *DC_working = telegram_get_working_dc(instance); assert (E->state == sc_request); clear_packet (); out_int (CODE_messages_get_dh_config); out_int (encr_param_version); out_int (256); - void **x = talloc (2 * sizeof (void *)); - x[0] = do_send_accept_encr_chat; - x[1] = E; - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x); + + struct create_encr_chat_extra *extra = malloc(sizeof(struct create_encr_chat_extra)); + extra->callback = do_send_accept_encr_chat; + extra->instance = instance; + extra->data = (void*)E; + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, extra); } -void do_create_encr_chat_request (int user_id) { +void do_create_encr_chat_request (struct telegram *instance, int user_id) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_get_dh_config); out_int (encr_param_version); out_int (256); - void **x = talloc (2 * sizeof (void *)); - x[0] = do_send_create_encr_chat; - x[1] = (void *)(long)(user_id); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x); + + struct create_encr_chat_extra *extra = malloc(sizeof(struct create_encr_chat_extra)); + extra->callback = do_send_accept_encr_chat; + extra->instance = instance; + extra->data = (void *)(long)user_id; + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, extra); } /* }}} */ @@ -2596,13 +2700,15 @@ int get_state_on_answer (struct query *q UU) { bl_do_set_date (fetch_int ()); bl_do_set_seq (fetch_int ()); unread_messages = fetch_int (); - write_state_file (); + //write_state_file (); difference_got = 1; return 0; } int get_difference_active; int get_difference_on_answer (struct query *q UU) { + struct telegram *instance = q->extra; + logprintf("get_difference_on_answer()\n"); get_difference_active = 0; unsigned x = fetch_int (); @@ -2618,18 +2724,18 @@ int get_difference_on_answer (struct query *q UU) { int ml_pos = 0; for (i = 0; i < n; i++) { if (ml_pos < 10000) { - ML[ml_pos ++] = fetch_alloc_message (); + ML[ml_pos ++] = fetch_alloc_message (instance); } else { - fetch_alloc_message (); + fetch_alloc_message (instance); } } assert (fetch_int () == CODE_vector); n = fetch_int (); for (i = 0; i < n; i++) { if (ml_pos < 10000) { - ML[ml_pos ++] = fetch_alloc_encrypted_message (); + ML[ml_pos ++] = fetch_alloc_encrypted_message (instance); } else { - fetch_alloc_encrypted_message (); + fetch_alloc_encrypted_message (instance); } } assert (fetch_int () == CODE_vector); @@ -2655,13 +2761,13 @@ int get_difference_on_answer (struct query *q UU) { bl_do_set_date (fetch_int ()); bl_do_set_seq (fetch_int ()); unread_messages = fetch_int (); - write_state_file (); + //write_state_file (); for (i = 0; i < ml_pos; i++) { event_update_new_message(ML[i]); - //print_message (ML[i]); + ////print_message (ML[i]); } if (x == CODE_updates_difference_slice) { - do_get_difference (); + do_get_difference (instance); } else { difference_got = 1; } @@ -2679,7 +2785,8 @@ struct query_methods get_difference_methods = { .on_answer = get_difference_on_answer }; -void do_get_difference (void) { +void do_get_difference (struct telegram *instance) { + struct dc *DC_working = telegram_get_working_dc(instance); logprintf("do_get_difference()\n"); get_difference_active = 1; difference_got = 0; @@ -2693,7 +2800,7 @@ void do_get_difference (void) { out_int (pts); out_int (last_date); out_int (qts); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0); + send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, instance); } else { out_int (CODE_updates_get_state); send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0); @@ -2702,34 +2809,34 @@ void do_get_difference (void) { /* }}} */ /* {{{ Visualize key */ -char *colors[4] = {COLOR_GREY, COLOR_CYAN, COLOR_BLUE, COLOR_GREEN}; +//char *colors[4] = {COLOR_GREY, COLOR_CYAN, COLOR_BLUE, COLOR_GREEN}; void do_visualize_key (peer_id_t id) { assert (get_peer_type (id) == PEER_ENCR_CHAT); peer_t *P = user_chat_get (id); assert (P); if (P->encr_chat.state != sc_ok) { - rprintf ("Chat is not initialized yet\n"); + logprintf ("Chat is not initialized yet\n"); return; } unsigned char buf[20]; SHA1 ((void *)P->encr_chat.key, 256, buf); - print_start (); + //print_start (); int i; for (i = 0; i < 16; i++) { int x = buf[i]; int j; for (j = 0; j < 4; j ++) { - push_color (colors[x & 3]); - push_color (COLOR_INVERSE); - logprintf (" "); - pop_color (); - pop_color (); + ////push_color (colors[x & 3]); + ////push_color (COLOR_INVERSE); + //logprintf (" "); + ////pop_color (); + ////pop_color (); x = x >> 2; } if (i & 1) { logprintf ("\n"); } } - print_end (); + //print_end (); } /* }}} */ @@ -2750,16 +2857,16 @@ int get_suggested_on_answer (struct query *q UU) { assert (fetch_int () == CODE_vector); int m = fetch_int (); assert (n == m); - print_start (); - push_color (COLOR_YELLOW); + //print_start (); + //push_color (COLOR_YELLOW); for (i = 0; i < m; i++) { peer_t *U = (void *)fetch_alloc_user (); assert (get_peer_id (U->id) == l[2 * i]); - print_user_name (U->id, U); + //print_user_name (U->id, U); logprintf (" phone %s: %d mutual friends\n", U->user.phone, l[2 * i + 1]); } - pop_color (); - print_end (); + //pop_color (); + //print_end (); return 0; } @@ -2767,7 +2874,8 @@ struct query_methods get_suggested_methods = { .on_answer = get_suggested_on_answer }; -void do_get_suggested (void) { +void do_get_suggested (struct telegram *instance) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_contacts_get_suggested); out_int (100); @@ -2781,7 +2889,8 @@ struct query_methods add_user_to_chat_methods = { .on_answer = fwd_msg_on_answer }; -void do_add_user_to_chat (peer_id_t chat_id, peer_id_t id, int limit) { +void do_add_user_to_chat (struct telegram *instance, peer_id_t chat_id, peer_id_t id, int limit) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_add_chat_user); out_int (get_peer_id (chat_id)); @@ -2800,7 +2909,8 @@ void do_add_user_to_chat (peer_id_t chat_id, peer_id_t id, int limit) { send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0); } -void do_del_user_from_chat (peer_id_t chat_id, peer_id_t id) { +void do_del_user_from_chat (struct telegram *instance, peer_id_t chat_id, peer_id_t id) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_delete_chat_user); out_int (get_peer_id (chat_id)); @@ -2822,15 +2932,15 @@ void do_del_user_from_chat (peer_id_t chat_id, peer_id_t id) { /* {{{ Create secret chat */ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4); -void do_create_secret_chat (peer_id_t id) { +void do_create_secret_chat (struct telegram *instance, peer_id_t id) { assert (get_peer_type (id) == PEER_USER); peer_t *U = user_chat_get (id); if (!U) { - rprintf ("Can not create chat with unknown user\n"); + logprintf ("Can not create chat with unknown user\n"); return; } - do_create_encr_chat_request (get_peer_id (id)); + do_create_encr_chat_request (instance, get_peer_id (id)); } /* }}} */ @@ -2839,11 +2949,11 @@ struct query_methods create_group_chat_methods = { .on_answer = fwd_msg_on_answer }; -void do_create_group_chat (peer_id_t id, char *chat_topic) { +void do_create_group_chat (struct telegram *instance, peer_id_t id, char *chat_topic) { assert (get_peer_type (id) == PEER_USER); peer_t *U = user_chat_get (id); if (!U) { - rprintf ("Can not create chat with unknown user\n"); + logprintf ("Can not create chat with unknown user\n"); return; } clear_packet (); @@ -2859,7 +2969,7 @@ void do_create_group_chat (peer_id_t id, char *chat_topic) { out_int (get_peer_id (id)); } out_string (chat_topic); - send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0); + send_query (telegram_get_working_dc(instance), packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0); } /* }}} */ @@ -2878,7 +2988,8 @@ struct query_methods delete_msg_methods = { .on_answer = delete_msg_on_answer }; -void do_delete_msg (long long id) { +void do_delete_msg (struct telegram *instance, long long id) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_delete_messages); out_int (CODE_vector); @@ -2902,7 +3013,8 @@ struct query_methods restore_msg_methods = { .on_answer = restore_msg_on_answer }; -void do_restore_msg (long long id) { +void do_restore_msg (struct telegram *instance, long long id) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_messages_restore_messages); out_int (CODE_vector); @@ -2920,7 +3032,8 @@ struct query_methods update_status_methods = { .on_answer = update_status_on_answer }; -void do_update_status (int online UU) { +void do_update_status (struct telegram *instance, int online UU) { + struct dc *DC_working = telegram_get_working_dc(instance); clear_packet (); out_int (CODE_account_update_status); out_int (online ? CODE_bool_false : CODE_bool_true); diff --git a/queries.h b/queries.h index 8456600..dd6588e 100644 --- a/queries.h +++ b/queries.h @@ -1,12 +1,12 @@ /* This file is part of telegram-client. - Telegram-client is free software: you can redistribute it and/or modify + struct telegram-client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - Telegram-client is distributed in the hope that it will be useful, + struct telegram-client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -17,10 +17,14 @@ Copyright Vitaly Valtman 2013 */ #include "net.h" +#include "telegram.h" #ifndef __QUERIES_H__ #define __QUERIES_H__ #include "structures.h" +// forward declare telegram +struct telegram; + #define QUERY_ACK_RECEIVED 1 struct query; @@ -63,63 +67,63 @@ void work_timers (void); extern struct query_methods help_get_config_methods; -char* do_send_code (const char *user); -void do_phone_call (const char *user); -int do_send_code_result (const char *code, const char *sms_hash); +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); double get_double_time (void); -void do_update_contact_list (void); +void do_update_contact_list (struct telegram *instance); union user_chat; -void do_send_message (peer_id_t id, const char *msg, int len); -void do_send_text (peer_id_t id, char *file); -void do_get_history (peer_id_t id, int limit); -void do_get_dialog_list (void); -void do_get_dialog_list_ex (void); -void do_send_photo (int type, peer_id_t to_id, char *file_name); -void do_get_chat_info (peer_id_t id); -void do_get_user_list_info_silent (int num, int *list); -void do_get_user_info (peer_id_t id); -void do_forward_message (peer_id_t id, int n); -void do_rename_chat (peer_id_t id, char *name); -void do_load_encr_video (struct encr_video *V, int next); -void do_create_encr_chat_request (int user_id); -void do_create_secret_chat (peer_id_t id); -void do_create_group_chat (peer_id_t id, char *chat_topic); -void do_get_suggested (void); +void do_send_message (struct telegram *instance, peer_id_t id, const char *msg, int len); +void do_send_text (struct telegram *instance, peer_id_t id, char *file); +void do_get_history (struct telegram *instance, peer_id_t id, int limit); +void do_get_dialog_list (struct telegram*); +void do_get_dialog_list_ex (struct telegram*); +void do_send_photo (struct telegram *instance, int type, peer_id_t to_id, char *file_name); +void do_get_chat_info (struct telegram *instance, peer_id_t id); +void do_get_user_list_info_silent (struct telegram *instance, int num, int *list); +void do_get_user_info (struct telegram *instance, peer_id_t id); +void do_forward_message (struct telegram *instance, peer_id_t id, int n); +void do_rename_chat (struct telegram *instance, peer_id_t id, char *name); +void do_load_encr_video (struct telegram *instance, struct encr_video *V, int next); +void do_create_encr_chat_request (struct telegram *instance, int user_id); +void do_create_secret_chat (struct telegram *instance, peer_id_t id); +void do_create_group_chat (struct telegram *instance, peer_id_t id, char *chat_topic); +void do_get_suggested (struct telegram*); struct photo; struct video; -void do_load_photo (struct photo *photo, int next); -void do_load_video_thumb (struct video *video, int next); -void do_load_audio (struct video *V, int next); -void do_load_video (struct video *V, int next); -void do_load_document (struct document *V, int next); -void do_load_document_thumb (struct document *video, int next); -void do_help_get_config (void); -int do_auth_check_phone (const char *user); -int do_get_nearest_dc (void); -int do_send_code_result_auth (const char *code, const char *sms_hash, const char *first_name, const char *last_name); -void do_import_auth (int num); -void do_export_auth (int num); -void do_add_contact (const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force); -void do_msg_search (peer_id_t id, int from, int to, int limit, const char *s); -void do_accept_encr_chat_request (struct secret_chat *E); -void do_get_difference (void); -void do_mark_read (peer_id_t id); +void do_load_photo (struct telegram *instance, struct photo *photo, int next); +void do_load_video_thumb (struct telegram *instance, struct video *video, int next); +void do_load_audio (struct telegram *instance, struct video *V, int next); +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); +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_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); +void do_msg_search (struct telegram *instance, peer_id_t id, int from, int to, int limit, const char *s); +void do_accept_encr_chat_request (struct telegram *instance, struct secret_chat *E); +void do_get_difference (struct telegram*); +void do_mark_read (struct telegram *instance, peer_id_t id); void do_visualize_key (peer_id_t id); void do_create_keys_end (struct secret_chat *U); -void do_add_user_to_chat (peer_id_t chat_id, peer_id_t id, int limit); -void do_del_user_from_chat (peer_id_t chat_id, peer_id_t id); -void do_update_status (int online); -void do_contacts_search (int limit, const char *s); -void do_send_msg (struct message *M); -void do_delete_msg (long long id); -void do_restore_msg (long long id); +void do_add_user_to_chat (struct telegram *instance, peer_id_t chat_id, peer_id_t id, int limit); +void do_del_user_from_chat (struct telegram *instance, peer_id_t chat_id, peer_id_t id); +void do_update_status (struct telegram *instance, int online); +void do_contacts_search (struct telegram *instance, int limit, const char *s); +void do_send_msg (struct telegram *instance, struct message *M); +void do_delete_msg (struct telegram *instance, long long id); +void do_restore_msg (struct telegram *instance, long long id); // For binlog int get_dh_config_on_answer (struct query *q); -void fetch_dc_option (void); +void fetch_dc_option (struct telegram *instance); #endif const char *get_last_err(); diff --git a/structures.c b/structures.c index a06290b..3d68143 100644 --- a/structures.c +++ b/structures.c @@ -231,7 +231,8 @@ int fetch_user (struct user *U) { assert (!our_id || (our_id == get_peer_id (U->id))); if (!our_id) { bl_do_set_our_id (get_peer_id (U->id)); - write_auth_file (); + // TODO: What to do here? + //write_auth_file (); } } @@ -323,7 +324,9 @@ void fetch_encrypted_chat (struct secret_chat *U) { return; } bl_do_encr_chat_delete (U); - write_secret_chat_file (); + + // TODO: properly + write_secret_chat_file ("/home/dev-jessie/.telegram/+4915736384600/secret"); return; } @@ -372,7 +375,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { } bl_do_encr_chat_requested (U, access_hash, date, admin_id, user_id, (void *)g_key, (void *)nonce); - write_secret_chat_file (); + write_secret_chat_file ("/home/dev-jessie/.telegram/+4915736384600/secret"); } else { bl_do_set_encr_chat_access_hash (U, fetch_long ()); bl_do_set_encr_chat_date (U, fetch_int ()); @@ -386,7 +389,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { } if (x == CODE_encrypted_chat_waiting) { bl_do_set_encr_chat_state (U, sc_waiting); - write_secret_chat_file (); + write_secret_chat_file ("/home/dev-jessie/.telegram/+4915736384600/secret"); return; // We needed only access hash from here } @@ -418,7 +421,7 @@ void fetch_encrypted_chat (struct secret_chat *U) { } bl_do_encr_chat_accepted (U, (void *)g_key, (void *)nonce, fetch_long ()); } - write_secret_chat_file (); + write_secret_chat_file ("/home/dev-jessie/.telegram/+4915736384600/secret"); } void fetch_notify_settings (void); @@ -1808,11 +1811,12 @@ void message_del_peer (struct message *M) { } } -struct message *fetch_alloc_message (void) { +struct message *fetch_alloc_message (struct telegram *instance) { logprintf("fetch_alloc_message()\n"); int data[2]; prefetch_data (data, 8); struct message *M = message_get (data[1]); + M->instance = instance; if (!M) { M = talloc0 (sizeof (*M)); @@ -1824,9 +1828,10 @@ struct message *fetch_alloc_message (void) { return M; } -struct message *fetch_alloc_geo_message (void) { +struct message *fetch_alloc_geo_message (struct telegram *instance) { logprintf("fetch_alloc_geo_message()\n"); struct message *M = talloc (sizeof (*M)); + M->instance = instance; fetch_geo_message (M); struct message *M1 = tree_lookup_message (message_tree, M); messages_allocated ++; @@ -1848,11 +1853,12 @@ struct message *fetch_alloc_geo_message (void) { } } -struct message *fetch_alloc_encrypted_message (void) { +struct message *fetch_alloc_encrypted_message (struct telegram *instance) { logprintf("fetch_alloc_encrypted_message()\n"); int data[3]; prefetch_data (data, 12); struct message *M = message_get (*(long long *)(data + 1)); + M->instance = instance; if (!M) { M = talloc0 (sizeof (*M)); @@ -1866,10 +1872,11 @@ struct message *fetch_alloc_encrypted_message (void) { return M; } -struct message *fetch_alloc_message_short (void) { +struct message *fetch_alloc_message_short (struct telegram *instance) { int data[1]; prefetch_data (data, 4); struct message *M = message_get (data[0]); + M->instance = instance; if (!M) { M = talloc0 (sizeof (*M)); @@ -1881,10 +1888,11 @@ struct message *fetch_alloc_message_short (void) { return M; } -struct message *fetch_alloc_message_short_chat (void) { +struct message *fetch_alloc_message_short_chat (struct telegram *instance) { int data[1]; prefetch_data (data, 4); struct message *M = message_get (data[0]); + M->instance = instance; if (!M) { M = talloc0 (sizeof (*M)); @@ -1998,9 +2006,10 @@ void message_remove_unsent (struct message *M) { void __send_msg (struct message *M) { logprintf ("Resending message...\n"); - print_message (M); - - do_send_msg (M); + //print_message (M); + + assert(M->instance); + do_send_msg (M->instance, M); } void send_all_unsent (void ) { diff --git a/structures.h b/structures.h index 63610b4..e9b9c59 100644 --- a/structures.h +++ b/structures.h @@ -318,6 +318,7 @@ struct message { int unread; int date; int service; + struct telegram *instance; union { struct message_action action; struct { @@ -336,11 +337,11 @@ struct user *fetch_alloc_user_full (void); struct chat *fetch_alloc_chat (void); struct chat *fetch_alloc_chat_full (void); struct secret_chat *fetch_alloc_encrypted_chat (void); -struct message *fetch_alloc_message (void); -struct message *fetch_alloc_geo_message (void); -struct message *fetch_alloc_message_short (void); -struct message *fetch_alloc_message_short_chat (void); -struct message *fetch_alloc_encrypted_message (void); +struct message *fetch_alloc_message (struct telegram *instance); +struct message *fetch_alloc_geo_message (struct telegram *instance); +struct message *fetch_alloc_message_short (struct telegram *instance); +struct message *fetch_alloc_message_short_chat (struct telegram *instance); +struct message *fetch_alloc_encrypted_message (struct telegram *instance); void fetch_encrypted_message_file (struct message_media *M); void fetch_skip_encrypted_message_file (void); void fetch_encrypted_message_file (struct message_media *M); diff --git a/telegram.c b/telegram.c index 071dc63..f712483 100755 --- a/telegram.c +++ b/telegram.c @@ -1,7 +1,15 @@ #include +#include +#include +#include +#include +#include + #include "mtproto-common.h" #include "telegram.h" #include "msglog.h" +#include "glib.h" +#include "mtproto-client.h" /* * Events @@ -11,50 +19,203 @@ * New message received */ void (*on_msg_handler)(struct message *M); -void on_update_new_message(void (*on_msg)(struct message *M)) { - on_msg_handler = on_msg; +void on_update_new_message(void (*on_msg)(struct message *M)) +{ + on_msg_handler = on_msg; } -void event_update_new_message(struct message *M) { - if (on_msg_handler) { - on_msg_handler(M); - } +void event_update_new_message(struct message *M) +{ + if (on_msg_handler) { + on_msg_handler(M); + } } /* * Peer allocated */ void (*on_peer_allocated_handler)(peer_t *peer); -void on_peer_allocated(void (*handler)(peer_t *peer)) { - on_peer_allocated_handler = handler; +void on_peer_allocated(void (*handler)(peer_t *peer)) +{ + on_peer_allocated_handler = handler; } -void event_peer_allocated(peer_t *peer) { - if (on_peer_allocated_handler) { - on_peer_allocated_handler(peer); - } +void event_peer_allocated(peer_t *peer) +{ + if (on_peer_allocated_handler) { + on_peer_allocated_handler(peer); + } } /* - * Callback to create proxy connections + * State changed */ -void (*proxy_connection_source)(const char *host, int port, void (*on_connection_created)(int fd)) = NULL; -void *proxy_connection_data = NULL; -void set_proxy_connection_source (void (*connection_source)(const char *host, int port, - void (*on_connection_created)(int fd)), void* data) +GList *change_listeners = NULL; +void telegram_add_state_change_listener(struct telegram *instance, state_listener_t listener) { - proxy_connection_source = connection_source; - proxy_connection_data = data; + instance->change_state_listeners = g_list_append(instance->change_state_listeners, listener); +} +void telegram_change_state(struct telegram *instance, int state, void *data) +{ + logprintf("Changing struct telegram state %d\n", state); + instance->session_state = state; + GList *curr = instance->change_state_listeners; + while ((curr = g_list_next(change_listeners)) != NULL) { + ((state_listener_t)curr->data)(instance, state, data); + } +} + +struct telegram *telegram_new(struct dc *DC, const char* login, const char *config_path) +{ + 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)); + telegram_change_state(this, STATE_INITIALISED, NULL); + return this; +} + +void telegram_free(struct telegram *instance) +{ + g_list_free(instance->change_state_listeners); + free(instance->login); + free(instance); +} + +void assert_file_usable(const char *file) +{ + assert(access(file, W_OK | R_OK | F_OK) != -1); +} + +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); + close(open(f, O_RDWR | O_CREAT, S_IRUSR, S_IWUSR)); + assert_file_usable(f); +} + +struct connection *telegram_get_connection(struct telegram *instance) +{ + struct dc *DC = instance->auth.DC_list[instance->auth.dc_working_num]; + return DC->sessions[0]->c; +} + +struct dc *telegram_get_working_dc(struct telegram *instance) +{ + struct dc *DC = instance->auth.DC_list[instance->auth.dc_working_num]; + return DC; +} + +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); +} + +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); +} + +void telegram_get_downloads_dir(struct telegram *instance) +{ + +} + +void telegram_network_connect(struct telegram *instance, int fd) +{ + on_start (); + struct dc *DC_working = telegram_get_working_dc(instance); + + // check whether authentication is needed + if (!DC_working->auth_key_id) { + logprintf("No working DC, authenticating.\n"); + + // init a new connection + struct connection *c = create_connection (DC_working->ip, DC_working->port, fd); + // 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); + telegram_change_state(instance, STATE_PQ_REQUESTED, NULL); + } else { + logprintf("Already working session, setting state to connected.\n"); + telegram_change_state(instance, STATE_CONNECTED, NULL); + } +} + +void on_connected(struct telegram *instance) +{ + assert (telegram_get_working_dc(instance)->auth_key_id); + logprintf("Done...\n"); + telegram_store_session(instance); +} + +void on_state_change(struct telegram *instance, int state, void *data) +{ + switch (state) { + case STATE_CONNECTED: + on_connected(instance); + break; + case STATE_ERROR: { + const char* err = data; + logprintf("Telegram errored: %s \n", err); + break; + } + } +} + + +/** + * Read newest rpc response and update state + */ +void try_rpc_interpret(struct telegram *instance, int op, int len) +{ + switch (instance->session_state) { + case STATE_PQ_REQUESTED: + rpc_execute_req_pq(instance, len); + telegram_change_state(instance, STATE_DH_REQUESTED, NULL); + break; + case STATE_DH_REQUESTED: + rpc_execute_rq_dh(instance, len); + telegram_change_state(instance, STATE_CDH_REQUESTED, NULL); + break; + case STATE_CDH_REQUESTED: + rpc_execute_cdh_sent(instance, len); + telegram_change_state(instance, STATE_AUTH_DONE, NULL); + break; + case STATE_AUTH_DONE: + 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); } -// template -//void (*on_blarg_handler)(type); -//void on_blarg(void (*handler)(type)) -//{ -// on_blarg_handler = handler; -//} -//void event_blarg(type) -//{ -// if (on_blarg_handler) -// { -// on_blarg_handler(type); -// } -//} diff --git a/telegram.h b/telegram.h index 597014d..77ac0c5 100644 --- a/telegram.h +++ b/telegram.h @@ -2,9 +2,10 @@ * libtelegram * =========== * - * Telegram library based on the telegram cli application, that was originally made by vysheng (see https://github.com/vysheng/tg) + * struct telegram library based on the telegram cli application, that was originally made by vysheng (see https://github.com/vysheng/tg) */ +#pragma once #define MAX_DC_NUM 9 #define MAX_PEER_NUM 100000 @@ -16,72 +17,175 @@ #include "net.h" #include "mtproto-common.h" #include "structures.h" +#include "glib.h" +#include "loop.h" +/* + * Libtelegram states + */ + +#define STATE_INITIALISED 0 +#define STATE_DISCONNECTED 1 + +// 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 +#define STATE_CONFIG_REQUESTED 7 +#define STATE_EXPORTING_CONFIG 8 +#define STATE_DISCONNECTED_SWITCH_DC 9 + +// Login +#define STATE_CONNECTED 10 + +// - 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 + +// Ready for sending and receiving messages +#define STATE_READY 21 + /** * A telegram session * - * Contains all globals from the telegram-cli application and should - * be passed to + * Contains all globals from the telegram-cli application is passed to every + * query call */ struct telegram { - - /* - * Read and save the configuration files into this directory - * - * Every distinct account needs its own configuration directory, that - * will be used to store encryption data and the protocol state for this - * specific user - */ - char *config_dir; - - /* - * Reserved for custom protocol data - */ void *protocol_data; - + int curr_dc; + char *login; + const char *config_path; + int session_state; + /* - * Events and Callbacks + * MtProto state */ - // TODO: Insert definitions for all function pointers for event and logging + struct protocol_state proto; + struct authorization_state auth; - /* - * Internal protocol state - */ - // TODO: Insert *all* global variables from the telegram-implementation + GList *change_state_listeners; + void (*on_output)(struct telegram *instance); + void *extra; }; -/* +/** * Constructor */ -void telegram_create( /* struct telegram, struct configuration config */ ); - // TODO: Initiate a new telegram instance +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); + +/** + * Store + */ +void telegram_store_session(struct telegram *instance); + +/** * Destructor */ -void telegram_destroy(struct telegram instance); - // TODO: Write clean-up functions to free all allocated resources of this session - -// Export functions for plugins - -int tg_login (); - -void running_for_first_time (); -void parse_config (); -void store_config (); -void read_auth_file (); +void telegram_free(struct telegram *instance); /** - * Read and write until all queries received a response or errored + * Get the currently active connection */ -void flush_queries (); +struct connection *telegram_get_connection(struct telegram *instance); + +/** + * Return the current working dc + */ +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 + * + * @param instance The telegram instance that changed its state + * @param state The changed state + * @param data Extra data that depends on switched state + */ +void telegram_change_state(struct telegram *instance, int state, void *data); /** * Connect to the telegram network with the given configuration */ -void network_connect(); +void telegram_network_connect (struct telegram *instance, int fd); + +/** + * Read the authorization_state stored in the given file + */ + +// Export functions for plugins +void running_for_first_time (); + +/* TODO: Remove? +void parse_config (); +void store_config (); +*/ + +/** + * Read and write until all queries received a response or errored + */ +void telegram_flush_queries (struct telegram *instance); + +/** + * Read and process all available input from the network + */ +void telegram_read_input (struct telegram *instance); + +/** + * Write all available output to the network + */ +void telegram_write_output (struct telegram *instance); + +/** + * Try to interpret RPC calls and apply the changes to the current telegram state + */ +void try_rpc_interpret(struct telegram *instance, int op, int len); + +/* + * TODO: Refactor all old calls to take a telegrma instance + */ /** * Request a registration code @@ -130,17 +234,9 @@ void session_update_contact_list(); 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_peer_allocated(void (*handler)(peer_t *peer)); void event_peer_allocated(peer_t *peer); @@ -152,37 +248,16 @@ void event_peer_allocated(peer_t *peer); * 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)); +void set_net_read_cb(ssize_t (*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)); - -/** - * The current proxy connection source. - */ -extern void (*proxy_connection_source)(const char *host, int port, void (*on_connection_created)(int fd)); - -/** - * The connection data passed to the connection source. - */ -extern void *proxy_connection_data; - -/** - * Set an alternative connection_source which is used to create open connections instead of the - * regular function. - * - * @param connection_source Called when a new connection is needed. A connection source must accept - * host and port and pass a valid file descriptor to an open TCP-Socket to the - * callback function on_connection_created - * @param data Additional connection data, that will be passed to the callback and may be - * needed for establishing the connection. - */ -void set_proxy_connection_source (void (*connection_source)(const char *host, int port, void (*on_connection_created)(int fd)), void* data); +void set_net_write_cb(ssize_t (*cb)(int fd, const void *buff, size_t size)); /** * */ void set_default_username (); +