Refactor Intermediate State 1
This commit is contained in:
parent
67c5a5e712
commit
ed7aa7de5b
28 changed files with 2050 additions and 1487 deletions
177
App configuration.html
Normal file
177
App configuration.html
Normal file
|
@ -0,0 +1,177 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>App configuration</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="apple-itunes-app" content="app-id=686449807">
|
||||
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
|
||||
|
||||
<link rel="shortcut icon" href="/favicon.ico?3" type="image/x-icon" />
|
||||
|
||||
<link href="/css/telegram.css?22" rel="stylesheet" media="screen">
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="fb-root"></div>
|
||||
<div class="tl_page_wrap">
|
||||
<div class="tl_page_head navbar navbar-static-top navbar-inverse">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<ul class="nav pull-right"><li class="hidden-phone"><a href="/dl/android" target="_blank" data-track="AppDownload/Android">Android</a></li><li class="hidden-phone"><a href="/dl/ios" target="_blank" data-track="AppDownload/iOS">iPhone</a></li><li><a href="https://twitter.com/telegram" target="_blank" data-track="Follow/Twitter"><i class="icon icon-twitter"></i> Twitter</a></li></ul>
|
||||
<ul class="nav">
|
||||
<li><a href="//telegram.org/">Home</a></li>
|
||||
<li><a href="//telegram.org/faq">FAQ</a></li>
|
||||
<li><a href="//telegram.org/apps">Apps</a></li>
|
||||
<li class="hidden-phone"><a href="//core.telegram.org/api">API</a></li>
|
||||
<li class="hidden-phone"><a href="//core.telegram.org/mtproto">Protocol</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container tl_page_container">
|
||||
<div class="tl_page">
|
||||
<div class="app_edit_page">
|
||||
<form class="form-horizontal" id="app_edit_form">
|
||||
<h2>App configuration</h2>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="app_id">App api_id:</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input" onclick="this.select();"><strong>16154</strong></span>
|
||||
<div class="app_lock_tt"><i class="icon icon-lock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="app_hash">App api_hash:</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input" onclick="this.select();">99428c722d0ed59b9cd844e4577cb4bb</span>
|
||||
<div class="app_lock_tt"><i class="icon icon-lock"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="app_title">App title:</label>
|
||||
<div class="controls">
|
||||
<input id="app_title" name="app_title" type="text" class="input-xlarge" value="Telegram Libpurple" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="app_shortname">Short name:</label>
|
||||
<div class="controls">
|
||||
<input id="app_shortname" name="app_shortname" type="text" class="input-xlarge" value="telerampurple" />
|
||||
<p class="help-block"><span class="muted">alphanumeric, 5-32 characters</span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: none;">
|
||||
<h3>PUSH-notifications settings</h3>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="app_gcm_api_key">GCM API key:</label>
|
||||
<div class="controls">
|
||||
<input id="app_gcm_api_key" name="app_gcm_api_key" type="text" class="input-xlarge" value="" />
|
||||
<p class="help-block"><a href="http://developer.android.com/google/gcm/gs.html#access-key" target="_blank">How do I get this?</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: none;">
|
||||
<h3>
|
||||
APNS certificates
|
||||
<small>
|
||||
<a href="/apps/apns_cert">Update</a>
|
||||
<a href="/apps/apns_cert_delete" onclick="return confirm('Are you sure to delete certificates?');" style="display: none;">Delete</a>
|
||||
</small>
|
||||
</h3>
|
||||
|
||||
<div class="control-group" style="display: none;">
|
||||
<label class="control-label" for="app_apns_production_pem">APNS production certificate:</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group" style="display: none;">
|
||||
<label class="control-label" for="app_apns_dev_pem">APNS development certificate:</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Available MTProto servers</h3>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Test configuration:</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input"><strong>173.240.5.253:443</strong></span>
|
||||
<p class="help-block">First DC</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">Production configuration</label>
|
||||
<div class="controls">
|
||||
<span class="input-xlarge uneditable-input"><strong>173.240.5.1:443</strong></span>
|
||||
<p class="help-block">First DC</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">Public keys:</label>
|
||||
<div class="controls">
|
||||
<pre><code>-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
||||
lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
||||
an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
|
||||
Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
||||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="button" class="btn btn-primary" data-loading-text="Saving..." id="app_save_btn" onclick="saveApp(); return false;">Save changes</button>
|
||||
<a href="/" class="btn">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/jquery.min.js"></script>
|
||||
<script src="/js/bootstrap.min.js"></script>
|
||||
<script src="/js/main.js?4"></script>
|
||||
|
||||
<script>$('#app_save_btn').button();
|
||||
$('.app_lock_tt').tooltip({html: true, title: '<div class="app_lock_text">It is forbidden to pass this value to third parties.</div>'});
|
||||
|
||||
function saveApp() {
|
||||
$('#app_save_btn').button('loading');
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/apps/save',
|
||||
data: $('#app_edit_form').serialize(),
|
||||
success: function (error) {
|
||||
$('#app_save_btn').button('reset');
|
||||
if (error) {
|
||||
alert(error);
|
||||
}
|
||||
},
|
||||
error: function (error) {
|
||||
$('#app_save_btn').button('reset');
|
||||
if (error) {
|
||||
alert(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -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
|
||||
|
|
142
README.es
142
README.es
|
@ -1,142 +0,0 @@
|
|||
## Telegram messenger CLI [](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 <clave-servidor-público>
|
||||
|
||||
|
||||
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 <guión bajo> 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 <marca de exclamación> <guión bajo> Nombre <guión bajo> 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** \<peer\> texto - envía el mensaje a este usuario.
|
||||
* **fwd** \<usuario\> \<numero-mensaje\> - reenviar un mensaje al usuario. Puedes ver los número de mensajes iniciando el Cliente con -N.
|
||||
* **chat_with_peer** \<peer\> - inicia un chat con este usuario. /exit o /quit para salir de este modo.
|
||||
* **add_contact** \<numero-teléfono\> \<nombre\> \<apellido\> - intenta añadir este contacto a la lista de contactos.
|
||||
* **rename_contact** \<usuario\> \<nombre\> \<apellido\> - intenta renombrar el contacto. Si tienes otro dispositivo será una pelea.
|
||||
* **mark_read** \<peer\> - marca todos los mensajes como recibidos de ese usuario.
|
||||
|
||||
#### Multimedia
|
||||
|
||||
* **send_photo** \<peer\> \<nombre-archivo-foto\> - manda una foto al usuario.
|
||||
* **send_video** \<peer\> \<nombre-archivo-video\> - envia un video al usuario.
|
||||
* **send_text** \<peer\> \<nombre-archivo-texto> - envia un archivo de texto como un mensaje en plano.
|
||||
* **load_photo**/load_video/load_video_thumb \<numero-mensaje\> - carga foto/video indicado del directorio de descarga.
|
||||
* **view_photo**/view_video/view_video_thumb \<numero-mensaje\> - 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** \<chat\> - imprime información del chat.
|
||||
* **chat_add_user** \<chat\> \<usuario\> - agrega un usuario al chat.
|
||||
* **chat_del_user** \<chat\> \<usuario\> - elimina un usuario del chat.
|
||||
* **rename_chat** \<chat\> \<nuevo-nombre\> - cambia el nombre al chat.
|
||||
|
||||
#### Search
|
||||
|
||||
* **search** \<peer\> 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** \<user\> - crea un chat secreto con el usuario indicado.
|
||||
* **visualize_key** \<secret_chat\> - Muestra la clave de cifrado. Debes compararla con la del otro usuario.
|
||||
|
||||
#### Estadísticas e información varia.
|
||||
|
||||
* **user_info** \<user\> - muestra información sobre el usuario.
|
||||
* **history** \<peer\> [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.
|
363
README.md
363
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
|
||||
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
|
||||
|
||||
|
||||
|
|
126
binlog.c
126
binlog.c
|
@ -21,9 +21,6 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_LUA
|
||||
# include "lua-tg.h"
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
@ -41,6 +38,7 @@
|
|||
#include "net.h"
|
||||
#include "include.h"
|
||||
#include "mtproto-client.h"
|
||||
#include "telegram.h"
|
||||
|
||||
#include <openssl/sha.h>
|
||||
|
||||
|
@ -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 ();
|
||||
|
|
5
binlog.h
5
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);
|
||||
|
|
10
interface.c
10
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, ...) {
|
||||
|
|
477
loop.c
477
loop.c
|
@ -43,7 +43,6 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
*/
|
||||
|
|
31
loop.h
31
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();
|
||||
|
|
3
lua-tg.c
3
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
|
||||
|
|
2
lua-tg.h
2
lua-tg.h
|
@ -4,6 +4,7 @@
|
|||
#include <string.h>
|
||||
#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
|
||||
|
|
2
main.c
2
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;
|
||||
|
||||
|
|
6
msglog.c
6
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
|
||||
|
||||
|
|
2
msglog.h
2
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, ...);
|
||||
|
|
490
mtproto-client.c
490
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
#include <openssl/sha.h>
|
||||
|
||||
#include "mtproto-common.h"
|
||||
#include "interface.h"
|
||||
#include "include.h"
|
||||
|
||||
#ifdef __MACH__
|
||||
|
|
|
@ -26,9 +26,10 @@
|
|||
#include <openssl/aes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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
|
||||
|
|
127
net.c
127
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;
|
||||
}
|
||||
|
|
23
net.h
23
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 <poll.h>
|
||||
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
|
||||
|
||||
|
|
|
@ -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 <althaus.christopher@gmail.com>, Markus Endres <endresma45241@th-nuernberg.de>, Matthias Jentsch <mtthsjntsch@gmail.com>",
|
||||
"https://bitbucket.org/telegrampurple/telegram-purple",
|
||||
NULL, // on load
|
||||
|
@ -832,3 +917,4 @@ static PurplePluginInfo info = {
|
|||
|
||||
|
||||
PURPLE_INIT_PLUGIN(telegram, tgprpl_init, info)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
98
queries.h
98
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();
|
||||
|
|
35
structures.c
35
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 ) {
|
||||
|
|
11
structures.h
11
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);
|
||||
|
|
225
telegram.c
225
telegram.c
|
@ -1,7 +1,15 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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);
|
||||
// }
|
||||
//}
|
||||
|
|
221
telegram.h
221
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 ();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue